Support for changes to OS X Mavericks VNOP_SYMLINK() function.
[openafs.git] / src / afs / AIX / osi_vnodeops.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 #include <afsconfig.h>
11 #include "afs/param.h"
12
13
14 #include "h/systm.h"
15 #include "h/types.h"
16 #include "h/errno.h"
17 #include "h/stat.h"
18 #include "h/user.h"
19 #include "h/uio.h"
20 #include "h/vattr.h"
21 #include "h/file.h"
22 #include "h/vfs.h"
23 #include "h/chownx.h"
24 #include "h/systm.h"
25 #include "h/access.h"
26 #ifdef AFS_AIX51_ENV
27 #include "h/acl.h"
28 #endif
29 #include "rpc/types.h"
30 #include "osi_vfs.h"
31 #include "netinet/in.h"
32 #include "h/mbuf.h"
33 #include "h/vmuser.h"
34 #include "h/shm.h"
35 #include "rpc/types.h"
36 #include "rpc/xdr.h"
37
38 #include "afs/stds.h"
39 #include "afs/afs_osi.h"
40 #define RFTP_INTERNALS 1
41 #include "afs/volerrors.h"
42 #include "afsint.h"
43 #include "vldbint.h"
44 #include "afs/lock.h"
45 #include "afs/exporter.h"
46 #include "afs/afs.h"
47 #include "afs/afs_chunkops.h"
48 #include "afs/afs_stats.h"
49 #include "afs/nfsclient.h"
50 #include "afs/icl.h"
51 #include "afs/prs_fs.h"
52 #include "h/flock.h"
53 #include "afsincludes.h"
54
55
56 int
57 afs_gn_link(struct vnode *vp, 
58             struct vnode *dp, 
59             char *name, 
60             struct ucred *cred)
61 {
62     int error;
63
64     AFS_STATCNT(afs_gn_link);
65     error = afs_link(vp, dp, name, cred);
66     afs_Trace3(afs_iclSetp, CM_TRACE_GNLINK, ICL_TYPE_POINTER, vp,
67                ICL_TYPE_STRING, name, ICL_TYPE_LONG, error);
68     return (error);
69 }
70
71
72 int
73 afs_gn_mkdir(struct vnode *dp, 
74              char *name, 
75              int32long64_t Mode, 
76              struct ucred *cred)
77 {
78     struct vattr va;
79     struct vnode *vp;
80     int error;
81     int mode = Mode;
82
83     AFS_STATCNT(afs_gn_mkdir);
84     VATTR_NULL(&va);
85     va.va_type = VDIR;
86     va.va_mode = (mode & 07777) & ~get_umask();
87     error = afs_mkdir(dp, name, &va, &vp, cred);
88     if (!error) {
89         AFS_RELE(vp);
90     }
91     afs_Trace4(afs_iclSetp, CM_TRACE_GMKDIR, ICL_TYPE_POINTER, vp,
92                ICL_TYPE_STRING, name, ICL_TYPE_LONG, mode, ICL_TYPE_LONG,
93                error);
94     return (error);
95 }
96
97
98 int
99 afs_gn_mknod(struct vnode *dp, 
100              char *name, 
101              int32long64_t Mode, 
102              dev_t dev, 
103              struct ucred *cred)
104 {
105     struct vattr va;
106     struct vnode *vp;
107     int error;
108     int mode = Mode;
109
110     AFS_STATCNT(afs_gn_mknod);
111     VATTR_NULL(&va);
112     va.va_type = IFTOVT(mode);
113     va.va_mode = (mode & 07777) & ~get_umask();
114
115 /**** I'm not sure if suser() should stay here since it makes no sense in AFS; however the documentation says that one "should be super-user unless making a FIFO file. Others systems such as SUN do this checking in the early stages of mknod (before the abstraction), so it's equivalently the same! *****/
116     if (va.va_type != VFIFO && !suser((char *)&error))
117         return (EPERM);
118     switch (va.va_type) {
119     case VDIR:
120         error = afs_mkdir(dp, name, &va, &vp, cred);
121         break;
122     case VNON:
123         error = EINVAL;
124         break;
125     case VBAD:
126     case VCHR:
127     case VBLK:
128         va.va_rdev = dev;
129     default:
130         error = afs_create(VTOAFS(dp), name, &va, NONEXCL, mode, (struct vcache **)&vp, cred);
131     }
132     if (!error) {
133         AFS_RELE(vp);
134     }
135     afs_Trace4(afs_iclSetp, CM_TRACE_GMKNOD, ICL_TYPE_POINTER, (afs_int32) vp,
136                ICL_TYPE_STRING, name, ICL_TYPE_LONG, mode, ICL_TYPE_LONG,
137                error);
138     return (error);
139 }
140
141
142 int
143 afs_gn_remove(struct vnode *vp,         /* Ignored in AFS */
144               struct vnode * dp, 
145               char *name, 
146               struct ucred *cred)
147 {
148     int error;
149
150     AFS_STATCNT(afs_gn_remove);
151     error = afs_remove(dp, name, cred);
152     afs_Trace3(afs_iclSetp, CM_TRACE_GREMOVE, ICL_TYPE_POINTER, dp,
153                ICL_TYPE_STRING, name, ICL_TYPE_LONG, error);
154     return (error);
155 }
156
157
158 int
159 afs_gn_rename(struct vnode *vp,                 /* Ignored in AFS */
160               struct vnode *dp, 
161               char *name, 
162               struct vnode *tp,                 /* Ignored in AFS */
163               struct vnode *tdp, 
164               char *tname, 
165               struct ucred *cred)
166 {
167     int error;
168
169     AFS_STATCNT(afs_gn_rename);
170     error = afs_rename(dp, name, tdp, tname, cred);
171     afs_Trace4(afs_iclSetp, CM_TRACE_GRENAME, ICL_TYPE_POINTER, dp,
172                ICL_TYPE_STRING, name, ICL_TYPE_STRING, tname, ICL_TYPE_LONG,
173                error);
174     return (error);
175 }
176
177
178 int
179 afs_gn_rmdir(struct vnode *vp,          /* Ignored in AFS */
180              struct vnode *dp, 
181              char *name, 
182              struct ucred *cred)
183 {
184     int error;
185
186     AFS_STATCNT(afs_gn_rmdir);
187     error = afs_rmdir(dp, name, cred);
188     if (error) {
189         if (error == 66 /* 4.3's ENOTEMPTY */ )
190             error = EEXIST;     /* AIX returns EEXIST where 4.3 used ENOTEMPTY */
191     }
192     afs_Trace3(afs_iclSetp, CM_TRACE_GRMDIR, ICL_TYPE_POINTER, dp,
193                ICL_TYPE_STRING, name, ICL_TYPE_LONG, error);
194     return (error);
195 }
196
197
198 int
199 afs_gn_lookup(struct vnode *dp, 
200               struct vnode **vpp, 
201               char *name, 
202               int32long64_t Flags,      /* includes FOLLOW... */
203               struct vattr *vattrp, 
204               struct ucred *cred)
205 {
206     int error;
207     int flags = Flags;
208
209     AFS_STATCNT(afs_gn_lookup);
210     error = afs_lookup(dp, name, vpp, cred);
211     afs_Trace3(afs_iclSetp, CM_TRACE_GLOOKUP, ICL_TYPE_POINTER, dp,
212                ICL_TYPE_STRING, name, ICL_TYPE_LONG, error);
213     if (vattrp != NULL && error == 0)
214         afs_gn_getattr(*vpp, vattrp, cred);
215     return (error);
216 }
217
218
219 int
220 afs_gn_fid(struct vnode *vp, 
221         struct fid *fidp, 
222         struct ucred *cred)
223 {
224     int error;
225
226     AFS_STATCNT(afs_gn_fid);
227     error = afs_fid(vp, fidp);
228     afs_Trace3(afs_iclSetp, CM_TRACE_GFID, ICL_TYPE_POINTER, vp,
229                ICL_TYPE_LONG, (afs_int32) fidp, ICL_TYPE_LONG, error);
230     return (error);
231 }
232
233
234 int
235 afs_gn_open(struct vnode *vp, 
236             int32long64_t Flags, 
237             ext_t ext, 
238             struct ucred **vinfop, 
239             struct ucred *cred)
240 {
241     int error;
242     struct vattr va;
243     struct vcache *tvp = VTOAFS(vp);
244     afs_int32 modes;
245     int flags = Flags;
246
247     AFS_STATCNT(afs_gn_open);
248     modes = 0;
249     if ((flags & FREAD))
250         modes |= R_ACC;
251     if ((flags & FEXEC))
252         modes |= X_ACC;
253     if ((flags & FWRITE) || (flags & FTRUNC))
254         modes |= W_ACC;
255
256     while ((flags & FNSHARE) && tvp->opens) {
257         if (!(flags & FDELAY)) {
258             error = ETXTBSY;
259             goto abort;
260         }
261         afs_osi_Sleep(&tvp->opens);
262     }
263
264     error = afs_access(VTOAFS(vp), modes, cred);
265     if (error) {
266         goto abort;
267     }
268
269     error = afs_open((struct vcache **) &vp, flags, cred);
270     if (!error) {
271         if (flags & FTRUNC) {
272             VATTR_NULL(&va);
273             va.va_size = 0;
274             error = afs_setattr(VTOAFS(vp), &va, cred);
275         }
276
277         if (flags & FNSHARE)
278             tvp->f.states |= CNSHARE;
279
280         if (!error) {
281             *vinfop = cred;     /* fp->f_vinfo is like fp->f_cred in suns */
282         } else {
283             /* an error occurred; we've told CM that the file
284              * is open, so close it now so that open and
285              * writer counts are correct.  Ignore error code,
286              * as it is likely to fail (the setattr just did).
287              */
288             afs_close(vp, flags, cred);
289         }
290     }
291
292   abort:
293     afs_Trace3(afs_iclSetp, CM_TRACE_GOPEN, ICL_TYPE_POINTER, vp,
294                ICL_TYPE_LONG, flags, ICL_TYPE_LONG, error);
295     return (error);
296 }
297
298
299 int
300 afs_gn_create(struct vnode *dp, 
301               struct vnode **vpp, 
302               int32long64_t Flags, 
303               char *name, 
304               int32long64_t Mode, 
305               struct ucred **vinfop, /* return ptr for fp->f_vinfo, used as fp->f_cred */
306               struct ucred *cred)
307
308 {
309     struct vattr va;
310     enum vcexcl exclusive;
311     int error, modes = 0;
312     int flags = Flags;
313     int mode = Mode;
314
315     AFS_STATCNT(afs_gn_create);
316     if ((flags & (O_EXCL | O_CREAT)) == (O_EXCL | O_CREAT))
317         exclusive = EXCL;
318     else
319         exclusive = NONEXCL;
320     VATTR_NULL(&va);
321     va.va_type = VREG;
322     va.va_mode = (mode & 07777) & ~get_umask();
323     if ((flags & FREAD))
324         modes |= R_ACC;
325     if ((flags & FEXEC))
326         modes |= X_ACC;
327     if ((flags & FWRITE) || (flags & FTRUNC))
328         modes |= W_ACC;
329     error = afs_create(VTOAFS(dp), name, &va, exclusive, modes, (struct vcache **)vpp, cred);
330     if (error) {
331         return error;
332     }
333     /* 'cr_luid' is a flag (when it comes thru the NFS server it's set to
334      * RMTUSER_REQ) that determines if we should call afs_open(). We shouldn't
335      * call it when this NFS traffic since the close will never happen thus
336      * we'd never flush the files out to the server! Gross but the simplest
337      * solution we came out with */
338     if (cred->cr_luid != RMTUSER_REQ) {
339         while ((flags & FNSHARE) && VTOAFS(*vpp)->opens) {
340             if (!(flags & FDELAY))
341                 return ETXTBSY;
342             afs_osi_Sleep(&VTOAFS(*vpp)->opens);
343         }
344         /* Since in the standard copen() for bsd vnode kernels they do an
345          * vop_open after the vop_create, we must do the open here since there
346          * are stuff in afs_open that we need. For example advance the
347          * execsOrWriters flag (else we'll be treated as the sun's "core"
348          * case). */
349         *vinfop = cred;         /* save user creds in fp->f_vinfo */
350         error = afs_open((struct vcache **)vpp, flags, cred);
351     }
352     afs_Trace4(afs_iclSetp, CM_TRACE_GCREATE, ICL_TYPE_POINTER, dp,
353                ICL_TYPE_STRING, name, ICL_TYPE_LONG, mode, ICL_TYPE_LONG,
354                error);
355     return error;
356 }
357
358
359 int
360 afs_gn_hold(struct vnode *vp)
361 {
362     AFS_STATCNT(afs_gn_hold);
363     ++(vp->v_count);
364     return (0);
365 }
366
367 int vmPageHog = 0;
368
369 int
370 afs_gn_rele(struct vnode *vp)
371 {
372     struct vcache *vcp = VTOAFS(vp);
373     int error = 0;
374
375     AFS_STATCNT(afs_gn_rele);
376     if (vp->v_count == 0)
377         osi_Panic("afs_rele: zero v_count");
378     if (--(vp->v_count) == 0) {
379         if (vcp->f.states & CPageHog) {
380             vmPageHog--;
381             vcp->f.states &= ~CPageHog;
382         }
383         error = afs_inactive(vp, 0);
384     }
385     return (error);
386 }
387
388
389 int
390 afs_gn_close(struct vnode *vp, 
391              int32long64_t Flags, 
392              caddr_t vinfo,             /* Ignored in AFS */
393              struct ucred *cred)
394 {
395     int error;
396     struct vcache *tvp = VTOAFS(vp);
397     int flags = Flags;
398
399     AFS_STATCNT(afs_gn_close);
400
401     if (flags & FNSHARE) {
402         tvp->f.states &= ~CNSHARE;
403         afs_osi_Wakeup(&tvp->opens);
404     }
405
406     error = afs_close(vp, flags, cred);
407     afs_Trace3(afs_iclSetp, CM_TRACE_GCLOSE, ICL_TYPE_POINTER, (afs_int32) vp,
408                ICL_TYPE_LONG, flags, ICL_TYPE_LONG, error);
409     return (error);
410 }
411
412
413 int
414 afs_gn_map(struct vnode *vp, 
415            caddr_t addr, 
416            uint32long64_t Len, 
417            uint32long64_t Off, 
418            uint32long64_t Flag, 
419            struct ucred *cred)
420 {
421     struct vcache *vcp = VTOAFS(vp);
422     struct vrequest treq;
423     afs_int32 error;
424     afs_int32 len = Len;
425     afs_int32 off = Off;
426     afs_int32 flag = Flag;
427
428     AFS_STATCNT(afs_gn_map);
429 #ifdef  notdef
430     if (error = afs_InitReq(&treq, cred))
431         return error;
432     error = afs_VerifyVCache(vcp, &treq);
433     if (error)
434         return afs_CheckCode(error, &treq, 49);
435 #endif
436     osi_FlushPages(vcp, cred);  /* XXX ensure old pages are gone XXX */
437     ObtainWriteLock(&vcp->lock, 401);
438     vcp->f.states |= CMAPPED;   /* flag cleared at afs_inactive */
439     /*
440      * We map the segment into our address space using the handle returned by vm_create.
441      */
442     if (!vcp->segid) {
443         afs_uint32 tlen = vcp->f.m.Length;
444 #ifdef AFS_64BIT_CLIENT
445         if (vcp->f.m.Length > afs_vmMappingEnd)
446             tlen = afs_vmMappingEnd;
447 #endif
448         /* Consider  V_INTRSEG too for interrupts */
449         if (error =
450             vms_create(&vcp->segid, V_CLIENT, (dev_t) vcp->v.v_gnode, tlen, 0, 0)) {
451             ReleaseWriteLock(&vcp->lock);
452             return (EOPNOTSUPP);
453         }
454 #ifdef AFS_64BIT_KERNEL
455         vcp->vmh = vm_handle(vcp->segid, (int32long64_t) 0);
456 #else
457         vcp->vmh = SRVAL(vcp->segid, 0, 0);
458 #endif
459     }
460     vcp->v.v_gnode->gn_seg = vcp->segid;        /* XXX Important XXX */
461     if (flag & SHM_RDONLY) {
462         vp->v_gnode->gn_mrdcnt++;
463     } else {
464         vp->v_gnode->gn_mwrcnt++;
465     }
466     /*
467      * We keep the caller's credentials since an async daemon will handle the 
468      * request at some point. We assume that the same credentials will be used.
469      */
470     if (!vcp->credp || (vcp->credp != cred)) {
471         crhold(cred);
472         if (vcp->credp) {
473             struct ucred *crp = vcp->credp;
474             vcp->credp = NULL;
475             crfree(crp);
476         }
477         vcp->credp = cred;
478     }
479     ReleaseWriteLock(&vcp->lock);
480     VN_HOLD(vp);
481     afs_Trace4(afs_iclSetp, CM_TRACE_GMAP, ICL_TYPE_POINTER, vp,
482                ICL_TYPE_LONG, addr, ICL_TYPE_LONG, len, ICL_TYPE_LONG, off);
483     return (0);
484 }
485
486
487 int
488 afs_gn_unmap(struct vnode *vp, 
489              int32long64_t flag, 
490              struct ucred *cred)
491 {
492     struct vcache *vcp = VTOAFS(vp);
493     AFS_STATCNT(afs_gn_unmap);
494     ObtainWriteLock(&vcp->lock, 402);
495     if (flag & SHM_RDONLY) {
496         vp->v_gnode->gn_mrdcnt--;
497         if (vp->v_gnode->gn_mrdcnt <= 0)
498             vp->v_gnode->gn_mrdcnt = 0;
499     } else {
500         vp->v_gnode->gn_mwrcnt--;
501         if (vp->v_gnode->gn_mwrcnt <= 0)
502             vp->v_gnode->gn_mwrcnt = 0;
503     }
504     ReleaseWriteLock(&vcp->lock);
505
506     AFS_RELE(vp);
507     return 0;
508 }
509
510
511 int
512 afs_gn_access(struct vnode *vp, 
513               int32long64_t Mode, 
514               int32long64_t Who, 
515               struct ucred *cred)
516 {
517     int error;
518     struct vattr vattr;
519     int mode = Mode;
520     int who = Who;
521
522     AFS_STATCNT(afs_gn_access);
523     if (mode & ~0x7) {
524         error = EINVAL;
525         goto out;
526     }
527
528     error = afs_access(VTOAFS(vp), mode, cred);
529     if (!error) {
530         /* Additional testing */
531         if (who == ACC_OTHERS || who == ACC_ANY) {
532             error = afs_getattr(VTOAFS(vp), &vattr, cred);
533             if (!error) {
534                 if (who == ACC_ANY) {
535                     if (((vattr.va_mode >> 6) & mode) == mode) {
536                         error = 0;
537                         goto out;
538                     }
539                 }
540                 if (((vattr.va_mode >> 3) & mode) == mode)
541                     error = 0;
542                 else
543                     error = EACCES;
544             }
545         } else if (who == ACC_ALL) {
546             error = afs_getattr(VTOAFS(vp), &vattr, cred);
547             if (!error) {
548                 if ((!((vattr.va_mode >> 6) & mode))
549                     || (!((vattr.va_mode >> 3) & mode))
550                     || (!(vattr.va_mode & mode)))
551                     error = EACCES;
552                 else
553                     error = 0;
554             }
555         }
556
557     }
558   out:
559     afs_Trace3(afs_iclSetp, CM_TRACE_GACCESS, ICL_TYPE_POINTER, vp,
560                ICL_TYPE_LONG, mode, ICL_TYPE_LONG, error);
561     return (error);
562 }
563
564
565 int
566 afs_gn_getattr(struct vnode *vp, 
567                struct vattr *vattrp, 
568                struct ucred *cred)
569 {
570     int error;
571
572     AFS_STATCNT(afs_gn_getattr);
573     error = afs_getattr(VTOAFS(vp), vattrp, cred);
574     afs_Trace2(afs_iclSetp, CM_TRACE_GGETATTR, ICL_TYPE_POINTER, vp,
575                ICL_TYPE_LONG, error);
576     return (error);
577 }
578
579
580 int
581 afs_gn_setattr(struct vnode *vp, 
582                int32long64_t op, 
583                int32long64_t arg1, 
584                int32long64_t arg2, 
585                int32long64_t arg3, 
586                struct ucred *cred)
587 {
588     struct vattr va;
589     int error = 0;
590
591     AFS_STATCNT(afs_gn_setattr);
592     VATTR_NULL(&va);
593     switch (op) {
594         /* change mode */
595     case V_MODE:
596         va.va_mode = arg1;
597         break;
598     case V_OWN:
599         if ((arg1 & T_OWNER_AS_IS) == 0)
600             va.va_uid = arg2;
601         if ((arg1 & T_GROUP_AS_IS) == 0)
602             va.va_gid = arg3;
603         break;
604     case V_UTIME:
605 #ifdef  notdef
606         error = afs_access(vp, VWRITE, cred);
607         if (error)
608             goto out;
609 #endif
610         if (arg1 & T_SETTIME) {
611             va.va_atime.tv_sec = time;
612             va.va_mtime.tv_sec = time;
613         } else {
614             va.va_atime = *(struct timestruc_t *)arg2;
615             va.va_mtime = *(struct timestruc_t *)arg3;
616         }
617         break;
618     default:
619         error = EINVAL;
620         goto out;
621     }
622
623     error = afs_setattr(VTOAFS(vp), &va, cred);
624   out:
625     afs_Trace2(afs_iclSetp, CM_TRACE_GSETATTR, ICL_TYPE_POINTER, vp,
626                ICL_TYPE_LONG, error);
627     return (error);
628 }
629
630
631 char zero_buffer[PAGESIZE];
632 int
633 afs_gn_fclear(struct vnode *vp, 
634               int32long64_t flags, 
635               offset_t offset, 
636               offset_t length, 
637               caddr_t vinfo, 
638               struct ucred *cred)
639 {
640     int i, len, error = 0;
641     struct iovec iov;
642     struct uio uio;
643     static int fclear_init = 0;
644     struct vcache *avc = VTOAFS(vp);
645
646     AFS_STATCNT(afs_gn_fclear);
647     if (!fclear_init) {
648         memset(zero_buffer, 0, PAGESIZE);
649         fclear_init = 1;
650     }
651     /*
652      * Don't clear past ulimit
653      */
654     if (offset + length > get_ulimit())
655         return (EFBIG);
656
657     /* Flush all pages first */
658     if (avc->segid) {
659         AFS_GUNLOCK();
660         vm_flushp(avc->segid, 0, MAXFSIZE / PAGESIZE - 1);
661         vms_iowait(avc->segid);
662         AFS_GLOCK();
663     }
664     uio.afsio_offset = offset;
665     for (i = offset; i < offset + length; i = uio.afsio_offset) {
666         len = offset + length - i;
667         iov.iov_len = (len > PAGESIZE) ? PAGESIZE : len;
668         iov.iov_base = zero_buffer;
669         uio.afsio_iov = &iov;
670         uio.afsio_iovcnt = 1;
671         uio.afsio_seg = AFS_UIOSYS;
672         uio.afsio_resid = iov.iov_len;
673         if (error = afs_rdwr(VTOAFS(vp), &uio, UIO_WRITE, 0, cred))
674             break;
675     }
676     afs_Trace4(afs_iclSetp, CM_TRACE_GFCLEAR, ICL_TYPE_POINTER, vp,
677                ICL_TYPE_LONG, offset, ICL_TYPE_LONG, length, ICL_TYPE_LONG,
678                error);
679     return (error);
680 }
681
682
683 int
684 afs_gn_fsync(struct vnode *vp, 
685              int32long64_t flags,       /* Not used by AFS */
686              int32long64_t vinfo,       /* Not used by AFS */
687              struct ucred *cred)
688 {
689     int error;
690
691     AFS_STATCNT(afs_gn_fsync);
692     error = afs_fsync(vp, cred);
693     afs_Trace3(afs_iclSetp, CM_TRACE_GFSYNC, ICL_TYPE_POINTER, vp,
694                ICL_TYPE_LONG, flags, ICL_TYPE_LONG, error);
695     return (error);
696 }
697
698
699 int
700 afs_gn_ftrunc(struct vnode *vp, 
701               int32long64_t flags, 
702               offset_t length, 
703               caddr_t vinfo, 
704               struct ucred *cred)
705 {
706     struct vattr va;
707     int error;
708
709     AFS_STATCNT(afs_gn_ftrunc);
710     VATTR_NULL(&va);
711     va.va_size = length;
712     error = afs_setattr(VTOAFS(vp), &va, cred);
713     afs_Trace4(afs_iclSetp, CM_TRACE_GFTRUNC, ICL_TYPE_POINTER, vp,
714                ICL_TYPE_LONG, flags, ICL_TYPE_OFFSET,
715                ICL_HANDLE_OFFSET(length), ICL_TYPE_LONG, error);
716     return (error);
717 }
718
719 /* Min size of a file which is dumping core before we declare it a page hog. */
720 #define MIN_PAGE_HOG_SIZE 8388608
721
722 int
723 afs_gn_rdwr(struct vnode *vp, 
724             enum uio_rw op, 
725             int32long64_t Flags, 
726             struct uio *ubuf, 
727             ext_t ext,                  /* Ignored in AFS */
728             caddr_t vinfo,              /* Ignored in AFS */
729             struct vattr *vattrp, 
730             struct ucred *cred)
731 {
732     struct vcache *vcp = VTOAFS(vp);
733     struct vrequest treq;
734     int error = 0;
735     int free_cred = 0;
736     int flags = Flags;
737
738     AFS_STATCNT(afs_gn_rdwr);
739
740     if (vcp->vc_error) {
741         if (op == UIO_WRITE) {
742             afs_Trace2(afs_iclSetp, CM_TRACE_GRDWR1, ICL_TYPE_POINTER, vp,
743                        ICL_TYPE_LONG, vcp->vc_error);
744             return vcp->vc_error;
745         } else
746             return EIO;
747     }
748
749     ObtainSharedLock(&vcp->lock, 507);
750     /*
751      * We keep the caller's credentials since an async daemon will handle the 
752      * request at some point. We assume that the same credentials will be used.
753      * If this is being called from an NFS server thread, then dupe the
754      * cred and only use that copy in calls and for the stach. 
755      */
756     if (!vcp->credp || (vcp->credp != cred)) {
757 #ifdef AFS_AIX_IAUTH_ENV
758         if (AFS_NFSXLATORREQ(cred)) {
759             /* Must be able to use cred later, so dupe it so that nfs server
760              * doesn't overwrite it's contents.
761              */
762             cred = crdup(cred);
763             free_cred = 1;
764         }
765 #endif
766         crhold(cred);           /* Bump refcount for reference in vcache */
767
768         if (vcp->credp) {
769             struct ucred *crp;
770             UpgradeSToWLock(&vcp->lock, 508);
771             crp = vcp->credp;
772             vcp->credp = NULL;
773             ConvertWToSLock(&vcp->lock);
774             crfree(crp);
775         }
776         vcp->credp = cred;
777     }
778     ReleaseSharedLock(&vcp->lock);
779
780     /*
781      * XXX Is the following really required?? XXX
782      */
783     if (error = afs_InitReq(&treq, cred))
784         return error;
785     if (error = afs_VerifyVCache(vcp, &treq))
786         return afs_CheckCode(error, &treq, 50);
787     osi_FlushPages(vcp, cred);  /* Flush old pages */
788
789     if (AFS_NFSXLATORREQ(cred)) {
790         if (flags & FSYNC)
791             flags &= ~FSYNC;
792         if (op == UIO_READ) {
793             if (!afs_AccessOK
794                 (vcp, PRSFS_READ, &treq,
795                  CHECK_MODE_BITS | CMB_ALLOW_EXEC_AS_READ)) {
796                 if (free_cred)
797                     crfree(cred);
798                 return EACCES;
799             }
800         }
801     }
802
803     /*
804      * We have to bump the open/exwriters field here courtesy of the nfs xlator
805      * because there're no open/close nfs rpcs to call our afs_open/close.
806      * We do a similar thing on the afs_read/write interface.
807      */
808     if (op == UIO_WRITE) {
809 #ifdef AFS_64BIT_CLIENT
810         if (ubuf->afsio_offset < afs_vmMappingEnd) {
811 #endif /* AFS_64BIT_CLIENT */
812             ObtainWriteLock(&vcp->lock, 240);
813             vcp->f.states |= CDirty;    /* Set the dirty bit */
814             afs_FakeOpen(vcp);
815             ReleaseWriteLock(&vcp->lock);
816 #ifdef AFS_64BIT_CLIENT
817         }
818 #endif /* AFS_64BIT_CLIENT */
819     }
820
821     error = afs_vm_rdwr(vp, ubuf, op, flags, cred);
822
823     if (op == UIO_WRITE) {
824 #ifdef AFS_64BIT_CLIENT
825         if (ubuf->afsio_offset < afs_vmMappingEnd) {
826 #endif /* AFS_64BIT_CLIENT */
827             ObtainWriteLock(&vcp->lock, 241);
828             afs_FakeClose(vcp, cred);   /* XXXX For nfs trans and cores XXXX */
829             ReleaseWriteLock(&vcp->lock);
830 #ifdef AFS_64BIT_CLIENT
831         }
832 #endif /* AFS_64BIT_CLIENT */
833     }
834     if (vattrp != NULL && error == 0)
835         afs_gn_getattr(vp, vattrp, cred);
836
837     afs_Trace4(afs_iclSetp, CM_TRACE_GRDWR, ICL_TYPE_POINTER, vp,
838                ICL_TYPE_LONG, flags, ICL_TYPE_LONG, op, ICL_TYPE_LONG, error);
839
840     if (free_cred)
841         crfree(cred);
842     return (error);
843 }
844
845 #define AFS_MAX_VM_CHUNKS 10
846 static int
847 afs_vm_rdwr(struct vnode *vp, 
848             struct uio *uiop, 
849             enum uio_rw rw, 
850             int ioflag, 
851             struct ucred *credp)
852 {
853     afs_int32 code = 0;
854     int i;
855     afs_int32 blockSize;
856     afs_size_t fileSize, xfrOffset, offset, old_offset, xfrSize;
857     vmsize_t txfrSize;
858 #ifdef AFS_64BIT_CLIENT
859     afs_size_t finalOffset;
860     off_t toffset;
861     int mixed = 0;
862     afs_size_t add2resid = 0;
863 #endif /* AFS_64BIT_CLIENT */
864     struct vcache *vcp = VTOAFS(vp);
865     struct dcache *tdc;
866     afs_size_t start_offset;
867     afs_int32 save_resid = uiop->afsio_resid;
868     int first_page, last_page, pages;
869     int count, len;
870     int counter = 0;
871     struct vrequest treq;
872
873     if (code = afs_InitReq(&treq, credp))
874         return code;
875
876     /* special case easy transfer; apparently a lot are done */
877     if ((xfrSize = uiop->afsio_resid) == 0)
878         return 0;
879
880     ObtainReadLock(&vcp->lock);
881     fileSize = vcp->f.m.Length;
882     if (rw == UIO_WRITE && (ioflag & IO_APPEND)) {      /* handle IO_APPEND mode */
883         uiop->afsio_offset = fileSize;
884     }
885     /* compute xfrOffset now, and do some checks */
886     xfrOffset = uiop->afsio_offset;
887     if (xfrOffset < 0 || xfrOffset + xfrSize < 0) {
888         code = EINVAL;
889         ReleaseReadLock(&vcp->lock);
890         goto fail;
891     }
892 #ifndef AFS_64BIT_CLIENT
893     /* check for "file too big" error, which should really be done above us */
894     if (rw == UIO_WRITE && xfrSize + fileSize > get_ulimit()) {
895         code = EFBIG;
896         ReleaseReadLock(&vcp->lock);
897         goto fail;
898     }
899 #endif /* AFS_64BIT_CLIENT */
900
901 #ifdef AFS_64BIT_CLIENT
902     if (xfrOffset + xfrSize > afs_vmMappingEnd) {
903         if (rw == UIO_READ) {
904             /* don't read past EOF */
905             if (xfrSize+xfrOffset > fileSize) {
906                 add2resid = xfrSize + xfrOffset - fileSize;
907                 xfrSize = fileSize - xfrOffset;
908                 if (xfrSize <= 0) {
909                     ReleaseReadLock(&vcp->lock);
910                     goto fail;
911                 }
912                 txfrSize = xfrSize;
913                 afsio_trim(uiop, txfrSize);
914             }
915         }
916         if (xfrOffset < afs_vmMappingEnd) {
917             /* special case of a buffer crossing the VM mapping line */
918             struct uio tuio;
919             struct iovec tvec[16];      /* Should have access to #define */
920             afs_int32 tsize;
921
922             mixed = 1;
923             finalOffset = xfrOffset + xfrSize;
924             tsize = (afs_size_t) (xfrOffset + xfrSize - afs_vmMappingEnd);
925             txfrSize = xfrSize;
926             afsio_copy(uiop, &tuio, tvec);
927             afsio_skip(&tuio, txfrSize - tsize);
928             afsio_trim(&tuio, tsize);
929             tuio.afsio_offset = afs_vmMappingEnd;
930             ReleaseReadLock(&vcp->lock);
931             ObtainWriteLock(&vcp->lock, 243);
932             afs_FakeClose(vcp, credp);  /* XXXX For nfs trans and cores XXXX */
933             ReleaseWriteLock(&vcp->lock);
934             code = afs_direct_rdwr(vp, &tuio, rw, ioflag, credp);
935             ObtainWriteLock(&vcp->lock, 244);
936             afs_FakeOpen(vcp);  /* XXXX For nfs trans and cores XXXX */
937             ReleaseWriteLock(&vcp->lock);
938             if (code)
939                 goto fail;
940             ObtainReadLock(&vcp->lock);
941             xfrSize = afs_vmMappingEnd - xfrOffset;
942             txfrSize = xfrSize;
943             afsio_trim(uiop, txfrSize);
944         } else {
945             ReleaseReadLock(&vcp->lock);
946             code = afs_direct_rdwr(vp, uiop, rw, ioflag, credp);
947             uiop->uio_resid += add2resid;
948             return code;
949         }
950     }
951 #endif /* AFS_64BIT_CLIENT */
952
953     if (!vcp->segid) {
954         afs_uint32 tlen = vcp->f.m.Length;
955 #ifdef AFS_64BIT_CLIENT
956         if (vcp->f.m.Length > afs_vmMappingEnd)
957             tlen = afs_vmMappingEnd;
958 #endif
959         /* Consider  V_INTRSEG too for interrupts */
960         if (code =
961             vms_create(&vcp->segid, V_CLIENT, (dev_t) vcp->v.v_gnode, tlen, 0, 0)) {
962             ReleaseReadLock(&vcp->lock);
963             goto fail;
964         }
965 #ifdef AFS_64BIT_KERNEL
966         vcp->vmh = vm_handle(vcp->segid, (int32long64_t) 0);
967 #else
968         vcp->vmh = SRVAL(vcp->segid, 0, 0);
969 #endif
970     }
971     vcp->v.v_gnode->gn_seg = vcp->segid;
972     if (rw == UIO_READ) {
973         ReleaseReadLock(&vcp->lock);
974         /* don't read past EOF */
975         if (xfrSize + xfrOffset > fileSize)
976             xfrSize = fileSize - xfrOffset;
977         if (xfrSize <= 0)
978             goto fail;
979 #ifdef AFS_64BIT_CLIENT
980         toffset = xfrOffset;
981         uiop->afsio_offset = xfrOffset;
982         afs_Trace3(afs_iclSetp, CM_TRACE_VMWRITE, ICL_TYPE_POINTER, vcp,
983                    ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(xfrOffset),
984                    ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(xfrSize));
985         AFS_GUNLOCK();
986         txfrSize = xfrSize;
987         code = vm_move(vcp->segid, toffset, txfrSize, rw, uiop);
988 #else /* AFS_64BIT_CLIENT */
989         AFS_GUNLOCK();
990         code = vm_move(vcp->segid, xfrOffset, xfrSize, rw, uiop);
991 #endif /* AFS_64BIT_CLIENT */
992         AFS_GLOCK();
993         /*
994          * If at a chunk boundary and staying within chunk,
995          * start prefetch of next chunk.
996          */
997         if (counter == 0 || AFS_CHUNKOFFSET(xfrOffset) == 0
998             && xfrSize <= AFS_CHUNKSIZE(xfrOffset)) {
999             ObtainWriteLock(&vcp->lock, 407);
1000             tdc = afs_FindDCache(vcp, xfrOffset);
1001             if (tdc) {
1002                 if (!(tdc->mflags & DFNextStarted))
1003                     afs_PrefetchChunk(vcp, tdc, credp, &treq);
1004                 afs_PutDCache(tdc);
1005             }
1006             ReleaseWriteLock(&vcp->lock);
1007         }
1008 #ifdef AFS_64BIT_CLIENT
1009         if (mixed) {
1010             uiop->afsio_offset = finalOffset;
1011         }
1012         uiop->uio_resid += add2resid;
1013 #endif /* AFS_64BIT_CLIENT */
1014         return code;
1015     }
1016
1017     /* UIO_WRITE */
1018     start_offset = uiop->afsio_offset;
1019     afs_Trace3(afs_iclSetp, CM_TRACE_VMWRITE, ICL_TYPE_POINTER, vcp,
1020                ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(start_offset),
1021                ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(xfrSize));
1022     ReleaseReadLock(&vcp->lock);
1023     ObtainWriteLock(&vcp->lock, 400);
1024     vcp->f.m.Date = osi_Time(); /* Set file date (for ranlib) */
1025     /* extend file */
1026     /* un-protect last page. */
1027     last_page = vcp->f.m.Length / PAGESIZE;
1028 #ifdef AFS_64BIT_CLIENT
1029     if (vcp->f.m.Length > afs_vmMappingEnd)
1030         last_page = afs_vmMappingEnd / PAGESIZE;
1031 #endif
1032     vm_protectp(vcp->segid, last_page, 1, FILEKEY);
1033     if (xfrSize + xfrOffset > fileSize) {
1034         vcp->f.m.Length = xfrSize + xfrOffset;
1035     }
1036     if ((!(vcp->f.states & CPageHog)) && (xfrSize >= MIN_PAGE_HOG_SIZE)) {
1037         vmPageHog++;
1038         vcp->f.states |= CPageHog;
1039     }
1040     ReleaseWriteLock(&vcp->lock);
1041
1042     /* If the write will fit into a single chunk we'll write all of it
1043      * at once. Otherwise, we'll write one chunk at a time, flushing
1044      * some of it to disk.
1045      */
1046     count = 0;
1047
1048     /* Only create a page to avoid excess VM access if we're writing a
1049      * small file which is either new or completely overwrites the 
1050      * existing file.
1051      */
1052     if ((xfrOffset == 0) && (xfrSize < PAGESIZE) && (xfrSize >= fileSize)
1053         && (vcp->v.v_gnode->gn_mwrcnt == 0)
1054         && (vcp->v.v_gnode->gn_mrdcnt == 0)) {
1055         (void)vm_makep(vcp->segid, 0);
1056     }
1057
1058     while (xfrSize > 0) {
1059         offset = AFS_CHUNKBASE(xfrOffset);
1060         len = xfrSize;
1061
1062         if (AFS_CHUNKSIZE(xfrOffset) <= len)
1063             len =
1064                 (afs_size_t) AFS_CHUNKSIZE(xfrOffset) - (xfrOffset - offset);
1065
1066         if (len == xfrSize) {
1067             /* All data goes to this one chunk. */
1068             AFS_GUNLOCK();
1069             old_offset = uiop->afsio_offset;
1070 #ifdef AFS_64BIT_CLIENT
1071             uiop->afsio_offset = xfrOffset;
1072             toffset = xfrOffset;
1073             txfrSize = xfrSize;
1074             code = vm_move(vcp->segid, toffset, txfrSize, rw, uiop);
1075 #else /* AFS_64BIT_CLIENT */
1076             code = vm_move(vcp->segid, xfrOffset, xfrSize, rw, uiop);
1077 #endif /* AFS_64BIT_CLIENT */
1078             AFS_GLOCK();
1079             if (code) {
1080                 goto fail;
1081             }
1082             xfrOffset += len;
1083             xfrSize = 0;
1084         } else {
1085             /* Write just one chunk's worth of data. */
1086             struct uio tuio;
1087             struct iovec tvec[16];      /* Should have access to #define */
1088
1089             /* Purge dirty chunks of file if there are too many dirty chunks.
1090              * Inside the write loop, we only do this at a chunk boundary.
1091              * Clean up partial chunk if necessary at end of loop.
1092              */
1093             if (counter > 0 && code == 0 && xfrOffset == offset) {
1094                 ObtainWriteLock(&vcp->lock, 403);
1095                 if (xfrOffset > vcp->f.m.Length)
1096                     vcp->f.m.Length = xfrOffset;
1097                 code = afs_DoPartialWrite(vcp, &treq);
1098                 vcp->f.states |= CDirty;
1099                 ReleaseWriteLock(&vcp->lock);
1100                 if (code) {
1101                     goto fail;
1102                 }
1103             }
1104             counter++;
1105
1106             afsio_copy(uiop, &tuio, tvec);
1107             afsio_trim(&tuio, len);
1108             tuio.afsio_offset = xfrOffset;
1109
1110             AFS_GUNLOCK();
1111             old_offset = uiop->afsio_offset;
1112 #ifdef AFS_64BIT_CLIENT
1113             toffset = xfrOffset;
1114             code = vm_move(vcp->segid, toffset, len, rw, &tuio);
1115 #else /* AFS_64BIT_CLIENT */
1116             code = vm_move(vcp->segid, xfrOffset, len, rw, &tuio);
1117 #endif /* AFS_64BIT_CLIENT */
1118             AFS_GLOCK();
1119             len -= tuio.afsio_resid;
1120             if (code || (len <= 0)) {
1121                 code = code ? code : EINVAL;
1122                 goto fail;
1123             }
1124             afsio_skip(uiop, len);
1125             xfrSize -= len;
1126             xfrOffset += len;
1127         }
1128
1129         first_page = (afs_size_t) old_offset >> PGSHIFT;
1130         pages =
1131             1 + (((afs_size_t) old_offset + (len - 1)) >> PGSHIFT) -
1132             first_page;
1133         afs_Trace3(afs_iclSetp, CM_TRACE_VMWRITE2, ICL_TYPE_POINTER, vcp,
1134                    ICL_TYPE_INT32, first_page, ICL_TYPE_INT32, pages);
1135         AFS_GUNLOCK();
1136         code = vm_writep(vcp->segid, first_page, pages);
1137         if (code) {
1138             AFS_GLOCK();
1139             goto fail;
1140         }
1141         if (++count > AFS_MAX_VM_CHUNKS) {
1142             count = 0;
1143             code = vms_iowait(vcp->segid);
1144             if (code) {
1145                 /* cache device failure? */
1146                 AFS_GLOCK();
1147                 goto fail;
1148             }
1149         }
1150         AFS_GLOCK();
1151
1152     }
1153
1154     if (count) {
1155         AFS_GUNLOCK();
1156         code = vms_iowait(vcp->segid);
1157         AFS_GLOCK();
1158         if (code) {
1159             /* cache device failure? */
1160             goto fail;
1161         }
1162     }
1163
1164     ObtainWriteLock(&vcp->lock, 242);
1165     if (code == 0 && (vcp->f.states & CDirty)) {
1166         code = afs_DoPartialWrite(vcp, &treq);
1167     }
1168     vm_protectp(vcp->segid, last_page, 1, RDONLY);
1169     ReleaseWriteLock(&vcp->lock);
1170
1171     /* If requested, fsync the file after every write */
1172     if (ioflag & FSYNC)
1173         afs_fsync(vp, credp);
1174
1175     ObtainReadLock(&vcp->lock);
1176     if (vcp->vc_error) {
1177         /* Pretend we didn't write anything. We need to get the error back to
1178          * the user. If we don't it's possible for a quota error for this
1179          * write to succeed and the file to be closed without the user ever
1180          * having seen the store error. And AIX syscall clears the error if
1181          * anything was written.
1182          */
1183         code = vcp->vc_error;
1184         if (code == EDQUOT || code == ENOSPC)
1185             uiop->afsio_resid = save_resid;
1186     }
1187 #ifdef AFS_64BIT_CLIENT
1188     if (mixed) {
1189         uiop->afsio_offset = finalOffset;
1190     }
1191 #endif /* AFS_64BIT_CLIENT */
1192     ReleaseReadLock(&vcp->lock);
1193
1194   fail:
1195     afs_Trace2(afs_iclSetp, CM_TRACE_VMWRITE3, ICL_TYPE_POINTER, vcp,
1196                ICL_TYPE_INT32, code);
1197     return code;
1198 }
1199
1200
1201 static int
1202 afs_direct_rdwr(struct vnode *vp, 
1203                 struct uio *uiop, 
1204                 enum uio_rw rw, 
1205                 int ioflag, 
1206                 struct ucred *credp)
1207 {
1208     afs_int32 code = 0;
1209     afs_size_t fileSize, xfrOffset, offset, old_offset, xfrSize;
1210     struct vcache *vcp = VTOAFS(vp);
1211     afs_int32 save_resid = uiop->afsio_resid;
1212     struct vrequest treq;
1213
1214     if (code = afs_InitReq(&treq, credp))
1215         return code;
1216
1217     /* special case easy transfer; apparently a lot are done */
1218     if ((xfrSize = uiop->afsio_resid) == 0)
1219         return 0;
1220
1221     ObtainReadLock(&vcp->lock);
1222     fileSize = vcp->f.m.Length;
1223     if (rw == UIO_WRITE && (ioflag & IO_APPEND)) {      /* handle IO_APPEND mode */
1224         uiop->afsio_offset = fileSize;
1225     }
1226     /* compute xfrOffset now, and do some checks */
1227     xfrOffset = uiop->afsio_offset;
1228     if (xfrOffset < 0 || xfrOffset + xfrSize < 0) {
1229         code = EINVAL;
1230         ReleaseReadLock(&vcp->lock);
1231         goto fail;
1232     }
1233
1234     /* check for "file too big" error, which should really be done above us */
1235 #ifdef notdef
1236     if (rw == UIO_WRITE && xfrSize + fileSize > get_ulimit()) {
1237         code = EFBIG;
1238         ReleaseReadLock(&vcp->lock);
1239         goto fail;
1240     }
1241 #endif
1242     ReleaseReadLock(&vcp->lock);
1243     if (rw == UIO_WRITE) {
1244         ObtainWriteLock(&vcp->lock, 400);
1245         vcp->f.m.Date = osi_Time();     /* Set file date (for ranlib) */
1246         /* extend file */
1247         if (xfrSize + xfrOffset > fileSize)
1248             vcp->f.m.Length = xfrSize + xfrOffset;
1249         ReleaseWriteLock(&vcp->lock);
1250     }
1251     afs_Trace3(afs_iclSetp, CM_TRACE_DIRECTRDWR, ICL_TYPE_POINTER, vp,
1252                ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(uiop->afsio_offset),
1253                ICL_TYPE_LONG, uiop->afsio_resid);
1254     code = afs_rdwr(VTOAFS(vp), uiop, rw, ioflag, credp);
1255     if (code != 0) {
1256         uiop->afsio_resid = save_resid;
1257     } else {
1258         uiop->afsio_offset = xfrOffset + xfrSize;
1259         if (uiop->afsio_resid > 0) {
1260             /* should zero here the remaining buffer */
1261             uiop->afsio_resid = 0;
1262         }
1263         /* Purge dirty chunks of file if there are too many dirty chunks.
1264          * Inside the write loop, we only do this at a chunk boundary.
1265          * Clean up partial chunk if necessary at end of loop.
1266          */
1267         if (AFS_CHUNKBASE(uiop->afsio_offset) != AFS_CHUNKBASE(xfrOffset)) {
1268             ObtainWriteLock(&vcp->lock, 402);
1269             code = afs_DoPartialWrite(vcp, &treq);
1270             vcp->f.states |= CDirty;
1271             ReleaseWriteLock(&vcp->lock);
1272         }
1273     }
1274
1275   fail:
1276     return code;
1277 }
1278
1279
1280 static int
1281 lock_normalize(struct vnode *vp, 
1282                struct flock *lckdat, 
1283                offset_t offset, 
1284                struct ucred *cred)
1285 {
1286     struct vattr vattr;
1287     int code;
1288
1289     switch (lckdat->l_whence) {
1290     case 0:
1291         return 0;
1292     case 1:
1293         lckdat->l_start += (off_t) offset;
1294         break;
1295     case 2:
1296         code = afs_getattr(VTOAFS(vp), &vattr, cred);
1297         if (code != 0)
1298             return code;
1299         lckdat->l_start += (off_t) vattr.va_size;
1300         break;
1301     default:
1302         return EINVAL;
1303     }
1304     lckdat->l_whence = 0;
1305     return 0;
1306 }
1307
1308
1309
1310 int
1311 afs_gn_lockctl(struct vnode *vp, 
1312                offset_t offset, 
1313                struct eflock *lckdat, 
1314                int32long64_t cmd, 
1315                int (*ignored_fcn) (),
1316 #ifdef AFS_AIX52_ENV /* Changed in AIX 5.2 and up */
1317                ulong * ignored_id, 
1318 #else /* AFS_AIX52_ENV */
1319                ulong32int64_t * ignored_id,
1320 #endif /* AFS_AIX52_ENV */
1321                struct ucred *cred)
1322 {
1323     int error, ncmd = 0;
1324     struct flock flkd;
1325     struct vattr *attrs;
1326
1327     AFS_STATCNT(afs_gn_lockctl);
1328     /* Convert from AIX's cmd to standard lockctl lock types... */
1329     if (cmd == 0)
1330         ncmd = F_GETLK;
1331     else if (cmd & SETFLCK) {
1332         ncmd = F_SETLK;
1333         if (cmd & SLPFLCK)
1334             ncmd = F_SETLKW;
1335     }
1336     flkd.l_type = lckdat->l_type;
1337     flkd.l_whence = lckdat->l_whence;
1338     flkd.l_start = lckdat->l_start;
1339     flkd.l_len = lckdat->l_len;
1340     flkd.l_pid = lckdat->l_pid;
1341     flkd.l_sysid = lckdat->l_sysid;
1342
1343     if (flkd.l_start != lckdat->l_start || flkd.l_len != lckdat->l_len)
1344         return EINVAL;
1345     if (error = lock_normalize(vp, &flkd, offset, cred))
1346         return (error);
1347     error = afs_lockctl(vp, &flkd, ncmd, cred);
1348     lckdat->l_type = flkd.l_type;
1349     lckdat->l_whence = flkd.l_whence;
1350     lckdat->l_start = flkd.l_start;
1351     lckdat->l_len = flkd.l_len;
1352     lckdat->l_pid = flkd.l_pid;
1353     lckdat->l_sysid = flkd.l_sysid;
1354     afs_Trace3(afs_iclSetp, CM_TRACE_GLOCKCTL, ICL_TYPE_POINTER, vp,
1355                ICL_TYPE_LONG, ncmd, ICL_TYPE_LONG, error);
1356     return (error);
1357 }
1358
1359
1360 /* NOTE: In the nfs glue routine (nfs_gn2sun.c) the order was wrong (vp, flags, cmd, arg, ext); was that another typo? */
1361 int
1362 afs_gn_ioctl(struct vnode *vp, 
1363              int32long64_t Cmd, 
1364              caddr_t arg, 
1365              size_t flags,              /* Ignored in AFS */
1366              ext_t ext,                 /* Ignored in AFS */
1367              struct ucred *crp)         /* Ignored in AFS */
1368 {
1369     int error;
1370     int cmd = Cmd;
1371
1372     AFS_STATCNT(afs_gn_ioctl);
1373     /* This seems to be a perfect fit for our ioctl redirection (afs_xioctl hack); thus the ioctl(2) entry in sysent.c is unaffected in the aix/afs port. */
1374     error = afs_ioctl(vp, cmd, arg);
1375     afs_Trace3(afs_iclSetp, CM_TRACE_GIOCTL, ICL_TYPE_POINTER, vp,
1376                ICL_TYPE_LONG, cmd, ICL_TYPE_LONG, error);
1377     return (error);
1378 }
1379
1380
1381 int
1382 afs_gn_readlink(struct vnode *vp, 
1383                 struct uio *uiop, 
1384                 struct ucred *cred)
1385 {
1386     int error;
1387
1388     AFS_STATCNT(afs_gn_readlink);
1389     error = afs_readlink(vp, uiop, cred);
1390     afs_Trace2(afs_iclSetp, CM_TRACE_GREADLINK, ICL_TYPE_POINTER, vp,
1391                ICL_TYPE_LONG, error);
1392     return (error);
1393 }
1394
1395
1396 int
1397 afs_gn_select(struct vnode *vp, 
1398               int32long64_t correl,
1399               ushort e,
1400               ushort *re,
1401               void (* notify)(),
1402               caddr_t vinfo,
1403               struct ucred *crp)
1404 {
1405     AFS_STATCNT(afs_gn_select);
1406     /* NO SUPPORT for this in afs YET! */
1407     return (EOPNOTSUPP);
1408 }
1409
1410
1411 int
1412 afs_gn_symlink(struct vnode *vp, 
1413                char *link, 
1414                char *target, 
1415                struct ucred *cred)
1416 {
1417     struct vattr va;
1418     int error;
1419
1420     AFS_STATCNT(afs_gn_symlink);
1421     VATTR_NULL(&va);
1422     va.va_mode = 0777;
1423     error = afs_symlink(vp, link, &va, target, NULL, cred);
1424     afs_Trace4(afs_iclSetp, CM_TRACE_GSYMLINK, ICL_TYPE_POINTER, vp,
1425                ICL_TYPE_STRING, link, ICL_TYPE_STRING, target, ICL_TYPE_LONG,
1426                error);
1427     return (error);
1428 }
1429
1430
1431 int
1432 afs_gn_readdir(struct vnode *vp, 
1433                struct uio *uiop, 
1434                struct ucred *cred)
1435 {
1436     int error;
1437
1438     AFS_STATCNT(afs_gn_readdir);
1439     error = afs_readdir(vp, uiop, cred);
1440     afs_Trace2(afs_iclSetp, CM_TRACE_GREADDIR, ICL_TYPE_POINTER, vp,
1441                ICL_TYPE_LONG, error);
1442     return (error);
1443 }
1444
1445
1446 extern Simple_lock afs_asyncbuf_lock;
1447 extern struct buf *afs_asyncbuf;
1448 extern int afs_asyncbuf_cv;
1449
1450 /*
1451  * Buffers are ranked by age.  A buffer's age is the value of afs_biotime
1452  * when the buffer is processed by afs_gn_strategy.  afs_biotime is
1453  * incremented for each buffer.  A buffer's age is kept in its av_back field.
1454  * The age ranking is used by the daemons, which favor older buffers.
1455  */
1456 afs_int32 afs_biotime = 0;
1457
1458 /* This function is called with a list of buffers, threaded through
1459  * the av_forw field.  Our goal is to copy the list of buffers into the
1460  * afs_asyncbuf list, sorting buffers into sublists linked by the b_work field.
1461  * Within buffers within the same work group, the guy with the lowest address
1462  * has to be located at the head of the queue; his b_bcount field will also
1463  * be increased to cover all of the buffers in the b_work queue.
1464  */
1465 #define AIX_VM_BLKSIZE  8192
1466 /* Note: This function seems to be called as ddstrategy entry point, ie
1467  * has one argument. However, it also needs to be present as
1468  * vn_strategy entry point which has three arguments, but it seems to never
1469  * be called in that capacity (it would fail horribly due to the argument
1470  * mismatch). I'm confused, but it obviously has to be this way, maybe
1471  * some IBM people can shed som light on this 
1472  */
1473 int
1474 afs_gn_strategy(struct buf *abp)
1475 {
1476     struct buf **lbp, *tbp;
1477     struct buf **lwbp;
1478     struct buf *nbp, *qbp, *qnbp, *firstComparable;
1479     int doMerge;
1480     int oldPriority;
1481
1482 #define EFS_COMPARABLE(x,y)     ((x)->b_vp == (y)->b_vp \
1483                                  && (x)->b_xmemd.subspace_id == (y)->b_xmemd.subspace_id \
1484                                  && (x)->b_flags == (y)->b_flags \
1485                                  && !((x)->b_flags & B_PFPROT) \
1486                                  && !((y)->b_flags & B_PFPROT))
1487
1488     oldPriority = disable_lock(INTMAX, &afs_asyncbuf_lock);
1489     for (tbp = abp; tbp; tbp = nbp) {
1490         nbp = tbp->av_forw;     /* remember for later */
1491         tbp->b_work = 0;
1492         tbp->av_back = (struct buf *)afs_biotime++;
1493
1494         /* first insert the buffer into the afs_async queue.  Insert buffer
1495          * sorted within its disk position within a set of comparable buffers.
1496          * Ensure that all comparable buffers are grouped contiguously.
1497          * Later on, we'll merge adjacent buffers into a single request.
1498          */
1499         firstComparable = NULL;
1500         lbp = &afs_asyncbuf;
1501         for (qbp = *lbp; qbp; lbp = &qbp->av_forw, qbp = *lbp) {
1502             if (EFS_COMPARABLE(tbp, qbp)) {
1503                 if (!firstComparable)
1504                     firstComparable = qbp;
1505                 /* this buffer is comparable, so see if the next buffer
1506                  * is farther in the file; if it is insert before next buffer.
1507                  */
1508                 if (tbp->b_blkno < qbp->b_blkno) {
1509                     break;
1510                 }
1511             } else {
1512                 /* If we're at the end of a block of comparable buffers, we
1513                  * insert the buffer here to keep all comparable buffers
1514                  * contiguous.
1515                  */
1516                 if (firstComparable)
1517                     break;
1518             }
1519         }
1520         /* do the insert before qbp now */
1521         tbp->av_forw = *lbp;
1522         *lbp = tbp;
1523         if (firstComparable == NULL) {
1524             /* next we're going to do all sorts of buffer merging tricks, but
1525              * here we know we're the only COMPARABLE block in the
1526              * afs_asyncbuf list, so we just skip that and continue with
1527              * the next input buffer.
1528              */
1529             continue;
1530         }
1531
1532         /* we may have actually added the "new" firstComparable */
1533         if (tbp->av_forw == firstComparable)
1534             firstComparable = tbp;
1535         /*
1536          * when we get here, firstComparable points to the first dude in the
1537          * same vnode and subspace that we (tbp) are in.  We go through the
1538          * area of this list with COMPARABLE buffers (a contiguous region) and
1539          * repeated merge buffers that are contiguous and in the same block or
1540          * buffers that are contiguous and are both integral numbers of blocks.
1541          * Note that our end goal is to have as big blocks as we can, but we
1542          * must minimize the transfers that are not integral #s of blocks on
1543          * block boundaries, since Episode will do those smaller and/or
1544          * unaligned I/Os synchronously.
1545          *
1546          * A useful example to consider has the async queue with this in it:
1547          * [8K block, 2 pages] [4K block, 1 page] [4K hole] [8K block, 2 pages]
1548          * If we get a request that fills the 4K hole, we want to merge this
1549          * whole mess into a 24K, 6 page transfer.  If we don't, however, we
1550          * don't want to do any merging since adding the 4K transfer to the 8K
1551          * transfer makes the 8K transfer synchronous.
1552          *
1553          * Note that if there are any blocks whose size is a multiple of
1554          * the file system block size, then we know that such blocks are also
1555          * on block boundaries.
1556          */
1557
1558         doMerge = 1;            /* start the loop */
1559         while (doMerge) {       /* loop until an iteration doesn't
1560                                  * make any more changes */
1561             doMerge = 0;
1562             for (qbp = firstComparable;; qbp = qnbp) {
1563                 qnbp = qbp->av_forw;
1564                 if (!qnbp)
1565                     break;      /* we're done */
1566                 if (!EFS_COMPARABLE(qbp, qnbp))
1567                     break;
1568
1569                 /* try to merge qbp and qnbp */
1570
1571                 /* first check if both not adjacent go on to next region */
1572                 if ((dbtob(qbp->b_blkno) + qbp->b_bcount) !=
1573                     dbtob(qnbp->b_blkno))
1574                     continue;
1575
1576                 /* note if both in the same block, the first byte of leftmost guy
1577                  * and last byte of rightmost guy are in the same block.
1578                  */
1579                 if ((dbtob(qbp->b_blkno) & ~(AIX_VM_BLKSIZE - 1)) ==
1580                     ((dbtob(qnbp->b_blkno) + qnbp->b_bcount -
1581                       1) & ~(AIX_VM_BLKSIZE - 1))) {
1582                     doMerge = 1;        /* both in same block */
1583                 } else if ((qbp->b_bcount & (AIX_VM_BLKSIZE - 1)) == 0
1584                            && (qnbp->b_bcount & (AIX_VM_BLKSIZE - 1)) == 0) {
1585                     doMerge = 1;        /* both integral #s of blocks */
1586                 }
1587                 if (doMerge) {
1588                     struct buf *xbp;
1589
1590                     /* merge both of these blocks together */
1591                     /* first set age to the older of the two */
1592                     if ((int32long64_t) qnbp->av_back - 
1593                             (int32long64_t) qbp->av_back < 0) {
1594                         qbp->av_back = qnbp->av_back;
1595                     }
1596                     lwbp = (struct buf **) &qbp->b_work;
1597                     /* find end of qbp's work queue */
1598                     for (xbp = *lwbp; xbp;
1599                          lwbp = (struct buf **) &xbp->b_work, xbp = *lwbp);
1600                     /*
1601                      * now setting *lwbp will change the last ptr in the qbp's
1602                      * work chain
1603                      */
1604                     qbp->av_forw = qnbp->av_forw;       /* splice out qnbp */
1605                     qbp->b_bcount += qnbp->b_bcount;    /* fix count */
1606                     *lwbp = qnbp;       /* append qnbp to end */
1607                     /*
1608                      * note that qnbp is bogus, but it doesn't matter because
1609                      * we're going to restart the for loop now.
1610                      */
1611                     break;      /* out of the for loop */
1612                 }
1613             }
1614         }
1615     }                           /* for loop for all interrupt data */
1616     /* at this point, all I/O has been queued.  Wakeup the daemon */
1617     e_wakeup_one((int *)&afs_asyncbuf_cv);
1618     unlock_enable(oldPriority, &afs_asyncbuf_lock);
1619     return 0;
1620 }
1621
1622
1623 int
1624 afs_inactive(struct vcache *avc, 
1625              afs_ucred_t *acred)
1626 {
1627     afs_InactiveVCache(avc, acred);
1628 }
1629
1630 int
1631 afs_gn_revoke(struct vnode *vp,
1632               int32long64_t cmd,
1633               int32long64_t flag,
1634               struct vattr *vinfop,
1635               struct ucred *crp)
1636 {
1637     AFS_STATCNT(afs_gn_revoke);
1638     /* NO SUPPORT for this in afs YET! */
1639     return (EOPNOTSUPP);
1640 }
1641
1642 int
1643 afs_gn_getacl(struct vnode *vp, 
1644               struct uio *uiop, 
1645               struct ucred *cred)
1646 {
1647     return ENOSYS;
1648 };
1649
1650
1651 int
1652 afs_gn_setacl(struct vnode *vp, 
1653               struct uio *uiop, 
1654               struct ucred *cred)
1655 {
1656     return ENOSYS;
1657 };
1658
1659
1660 int
1661 afs_gn_getpcl(struct vnode *vp, 
1662               struct uio *uiop, 
1663               struct ucred *cred)
1664 {
1665     return ENOSYS;
1666 };
1667
1668
1669 int
1670 afs_gn_setpcl(struct vnode *vp, 
1671               struct uio *uiop, 
1672               struct ucred *cred)
1673 {
1674     return ENOSYS;
1675 };
1676
1677
1678 int
1679 afs_gn_seek(struct vnode* vp, offset_t * offp, struct ucred * crp)
1680 {
1681 /*
1682  * File systems which do not wish to do offset validation can simply
1683  * return 0.  File systems which do not provide the vn_seek entry point
1684  * will have a maximum offset of OFF_MAX (2 gigabytes minus 1) enforced
1685  * by the logical file system.
1686  */
1687     return 0;
1688 }
1689
1690
1691 int
1692 afs_gn_enosys()
1693 {
1694     return ENOSYS;
1695 }
1696
1697 /*
1698  * declare a struct vnodeops and initialize it with ptrs to all functions
1699  */
1700 struct vnodeops afs_gn_vnodeops = {
1701     /* creation/naming/deletion */
1702     afs_gn_link,
1703     afs_gn_mkdir,
1704     afs_gn_mknod,
1705     afs_gn_remove,
1706     afs_gn_rename,
1707     afs_gn_rmdir,
1708     /* lookup, file handle stuff */
1709     afs_gn_lookup,
1710     (int(*)(struct vnode*,struct fileid*,struct ucred*))
1711         afs_gn_fid,
1712     /* access to files */
1713     (int(*)(struct vnode *, int32long64_t, ext_t, caddr_t *,struct ucred *))
1714         afs_gn_open,
1715     (int(*)(struct vnode *, struct vnode **, int32long64_t,caddr_t, int32long64_t, caddr_t *, struct ucred *))
1716         afs_gn_create,
1717     afs_gn_hold,
1718     afs_gn_rele,
1719     afs_gn_close,
1720     afs_gn_map,
1721     afs_gn_unmap,
1722     /* manipulate attributes of files */
1723     afs_gn_access,
1724     afs_gn_getattr,
1725     afs_gn_setattr,
1726     /* data update operations */
1727     afs_gn_fclear,
1728     afs_gn_fsync,
1729     afs_gn_ftrunc,
1730     afs_gn_rdwr,
1731     afs_gn_lockctl,
1732     /* extensions */
1733     afs_gn_ioctl,
1734     afs_gn_readlink,
1735     afs_gn_select,
1736     afs_gn_symlink,
1737     afs_gn_readdir,
1738     /* buffer ops */
1739     (int(*)(struct vnode*,struct buf*,struct ucred*))
1740         afs_gn_strategy,
1741     /* security things */
1742     afs_gn_revoke,
1743     afs_gn_getacl,
1744     afs_gn_setacl,
1745     afs_gn_getpcl,
1746     afs_gn_setpcl,
1747     afs_gn_seek,
1748     (int(*)(struct vnode *, int32long64_t, int32long64_t, offset_t, offset_t, struct ucred *))
1749         afs_gn_enosys,          /* vn_fsync_range */
1750     (int(*)(struct vnode *, struct vnode **, int32long64_t, char *, struct vattr *, int32long64_t, caddr_t *, struct ucred *))
1751         afs_gn_enosys,          /* vn_create_attr */
1752     (int(*)(struct vnode *, int32long64_t, void *, size_t, struct ucred *))
1753         afs_gn_enosys,          /* vn_finfo */
1754     (int(*)(struct vnode *, caddr_t, offset_t, offset_t, uint32long64_t, uint32long64_t, struct ucred *))
1755         afs_gn_enosys,          /* vn_map_lloff */
1756     (int(*)(struct vnode*,struct uio*,int*,struct ucred*))
1757         afs_gn_enosys,          /* vn_readdir_eofp */
1758     (int(*)(struct vnode *, enum uio_rw, int32long64_t, struct uio *, ext_t , caddr_t, struct vattr *, struct vattr *, struct ucred *))
1759         afs_gn_enosys,          /* vn_rdwr_attr */
1760     (int(*)(struct vnode*,int,void*,struct ucred*))
1761         afs_gn_enosys,          /* vn_memcntl */
1762 #ifdef AFS_AIX53_ENV /* Present in AIX 5.3 and up */
1763     (int(*)(struct vnode*,const char*,struct uio*,struct ucred*))
1764         afs_gn_enosys,          /* vn_getea */
1765     (int(*)(struct vnode*,const char*,struct uio*,int,struct ucred*))
1766         afs_gn_enosys,          /* vn_setea */
1767     (int(*)(struct vnode *, struct uio *, struct ucred *))
1768         afs_gn_enosys,          /* vn_listea */
1769     (int(*)(struct vnode *, const char *, struct ucred *))
1770         afs_gn_enosys,          /* vn_removeea */
1771     (int(*)(struct vnode *, const char *, struct vattr *, struct ucred *))
1772         afs_gn_enosys,          /* vn_statea */
1773     (int(*)(struct vnode *, uint64_t, acl_type_t *, struct uio *, size_t *, mode_t *, struct ucred *))
1774         afs_gn_enosys,          /* vn_getxacl */
1775     (int(*)(struct vnode *, uint64_t, acl_type_t, struct uio *, mode_t,  struct ucred *))
1776         afs_gn_enosys,          /* vn_setxacl */
1777 #else /* AFS_AIX53_ENV */
1778     afs_gn_enosys,              /* vn_spare7 */
1779     afs_gn_enosys,              /* vn_spare8 */
1780     afs_gn_enosys,              /* vn_spare9 */
1781     afs_gn_enosys,              /* vn_spareA */
1782     afs_gn_enosys,              /* vn_spareB */
1783     afs_gn_enosys,              /* vn_spareC */
1784     afs_gn_enosys,              /* vn_spareD */
1785 #endif /* AFS_AIX53_ENV */
1786     afs_gn_enosys,              /* vn_spareE */
1787     afs_gn_enosys               /* vn_spareF */
1788 #ifdef AFS_AIX51_ENV
1789     ,(int(*)(struct gnode*,long long,char*,unsigned long*, unsigned long*,unsigned int*))
1790         afs_gn_enosys,          /* pagerBackRange */
1791     (int64_t(*)(struct gnode*))
1792         afs_gn_enosys,          /* pagerGetFileSize */
1793     (void(*)(struct gnode *, vpn_t, vpn_t *, vpn_t *, vpn_t *, boolean_t))
1794         afs_gn_enosys,          /* pagerReadAhead */
1795     (void(*)(struct gnode *, int64_t, int64_t, uint))
1796         afs_gn_enosys,          /* pagerReadWriteBehind */
1797     (void(*)(struct gnode*,long long,unsigned long,unsigned long,unsigned int))
1798         afs_gn_enosys           /* pagerEndCopy */
1799 #endif
1800 };
1801 struct vnodeops *afs_ops = &afs_gn_vnodeops;
1802
1803
1804
1805 extern struct vfsops Afs_vfsops;
1806 extern int Afs_init();
1807
1808 #define AFS_CALLOUT_TBL_SIZE    256
1809
1810 /*
1811  * the following additional layer of gorp is due to the fact that the
1812  * filesystem layer no longer obtains the kernel lock for me.  I was relying
1813  * on this behavior to avoid having to think about locking.
1814  */
1815
1816 static
1817 vfs_mount(struct vfs *a, struct ucred *b)
1818 {
1819     int glockOwner, ret;
1820
1821     glockOwner = ISAFS_GLOCK();
1822     if (!glockOwner)
1823         AFS_GLOCK();
1824     ret = (*Afs_vfsops.vfs_mount) (a, b);
1825     if (!glockOwner)
1826         AFS_GUNLOCK();
1827
1828     return ret;
1829 }
1830
1831 static
1832 vfs_unmount(struct vfs *a, int b, struct ucred *c)
1833 {
1834     int glockOwner, ret;
1835
1836     glockOwner = ISAFS_GLOCK();
1837     if (!glockOwner)
1838         AFS_GLOCK();
1839     ret = (*Afs_vfsops.vfs_unmount) (a, b, c);
1840     if (!glockOwner)
1841         AFS_GUNLOCK();
1842
1843     return ret;
1844 }
1845
1846 static
1847 vfs_root(struct vfs *a, struct vnode **b, struct ucred *c)
1848 {
1849     int glockOwner, ret;
1850
1851     glockOwner = ISAFS_GLOCK();
1852     if (!glockOwner)
1853         AFS_GLOCK();
1854     ret = (*Afs_vfsops.vfs_root) (a, b, c);
1855     if (!glockOwner)
1856         AFS_GUNLOCK();
1857
1858     return ret;
1859 }
1860
1861 static
1862 vfs_statfs(struct vfs *a, struct statfs *b, struct ucred *c)
1863 {
1864     int glockOwner, ret;
1865
1866     glockOwner = ISAFS_GLOCK();
1867     if (!glockOwner)
1868         AFS_GLOCK();
1869     ret = (*Afs_vfsops.vfs_statfs) (a, b, c);
1870     if (!glockOwner)
1871         AFS_GUNLOCK();
1872
1873     return ret;
1874 }
1875
1876 static
1877 vfs_sync(struct gfs *a)
1878 {
1879     int glockOwner, ret;
1880
1881     glockOwner = ISAFS_GLOCK();
1882     if (!glockOwner)
1883         AFS_GLOCK();
1884     ret = (*Afs_vfsops.vfs_sync) (a);
1885     if (!glockOwner)
1886         AFS_GUNLOCK();
1887     return ret;
1888 }
1889
1890 static
1891 vfs_vget(struct vfs *a, struct vnode **b, struct fileid *c, struct ucred *d)
1892 {
1893     int glockOwner, ret;
1894
1895     glockOwner = ISAFS_GLOCK();
1896     if (!glockOwner)
1897         AFS_GLOCK();
1898     ret = (*Afs_vfsops.vfs_vget) (a, b, c, d);
1899     if (!glockOwner)
1900         AFS_GUNLOCK();
1901
1902     return ret;
1903 }
1904
1905 static
1906 vfs_cntl(struct vfs *a, int b, caddr_t c, size_t d, struct ucred *e)
1907 {
1908     int glockOwner, ret;
1909
1910     glockOwner = ISAFS_GLOCK();
1911     if (!glockOwner)
1912         AFS_GLOCK();
1913     ret = (*Afs_vfsops.vfs_cntl) (a, b, c, d, e);
1914     if (!glockOwner)
1915         AFS_GUNLOCK();
1916
1917     return ret;
1918 }
1919
1920 static
1921 vfs_quotactl(struct vfs *a, int b, uid_t c, caddr_t d, struct ucred *e)
1922 {
1923     int glockOwner, ret;
1924
1925     glockOwner = ISAFS_GLOCK();
1926     if (!glockOwner)
1927         AFS_GLOCK();
1928     ret = (*Afs_vfsops.vfs_quotactl) (a, b, c, d, e);
1929     if (!glockOwner)
1930         AFS_GUNLOCK();
1931
1932     return ret;
1933 }
1934
1935 #ifdef AFS_AIX51_ENV
1936 static
1937 vfs_syncvfs(struct gfs *a, struct vfs *b, int c, struct ucred *d)
1938 {
1939     int glockOwner, ret;
1940
1941     glockOwner = ISAFS_GLOCK();
1942     if (!glockOwner)
1943         AFS_GLOCK();
1944     ret = (*Afs_vfsops.vfs_syncvfs) (a, b, c, d);
1945     if (!glockOwner)
1946         AFS_GUNLOCK();
1947
1948     return ret;
1949 }
1950 #endif
1951
1952
1953 struct vfsops locked_Afs_vfsops = {
1954     vfs_mount,
1955     vfs_unmount,
1956     vfs_root,
1957     vfs_statfs,
1958     vfs_sync,
1959     vfs_vget,
1960     vfs_cntl,
1961     vfs_quotactl,
1962 #ifdef AFS_AIX51_ENV
1963     vfs_syncvfs
1964 #endif
1965 };
1966
1967 static
1968 vn_link(struct vnode *a, struct vnode *b, char *c, struct ucred *d)
1969 {
1970     int glockOwner, ret;
1971
1972     glockOwner = ISAFS_GLOCK();
1973     if (!glockOwner)
1974         AFS_GLOCK();
1975     ret = (*afs_gn_vnodeops.vn_link) (a, b, c, d);
1976     if (!glockOwner)
1977         AFS_GUNLOCK();
1978
1979     return ret;
1980 }
1981
1982 static
1983 vn_mkdir(struct vnode *a, char *b, int32long64_t c, struct ucred *d)
1984 {
1985     int glockOwner, ret;
1986
1987     glockOwner = ISAFS_GLOCK();
1988     if (!glockOwner)
1989         AFS_GLOCK();
1990     ret = (*afs_gn_vnodeops.vn_mkdir) (a, b, c, d);
1991     if (!glockOwner)
1992         AFS_GUNLOCK();
1993
1994     return ret;
1995 }
1996
1997 static
1998 vn_mknod(struct vnode *a, caddr_t b, int32long64_t c, dev_t d,
1999          struct ucred *e)
2000 {
2001     int glockOwner, ret;
2002
2003     glockOwner = ISAFS_GLOCK();
2004     if (!glockOwner)
2005         AFS_GLOCK();
2006     ret = (*afs_gn_vnodeops.vn_mknod) (a, b, c, d, e);
2007     if (!glockOwner)
2008         AFS_GUNLOCK();
2009
2010     return ret;
2011 }
2012
2013 static
2014 vn_remove(struct vnode *a, struct vnode *b, char *c, struct ucred *d)
2015 {
2016     int glockOwner, ret;
2017
2018     glockOwner = ISAFS_GLOCK();
2019     if (!glockOwner)
2020         AFS_GLOCK();
2021     ret = (*afs_gn_vnodeops.vn_remove) (a, b, c, d);
2022     if (!glockOwner)
2023         AFS_GUNLOCK();
2024
2025     return ret;
2026 }
2027
2028 static
2029 vn_rename(struct vnode *a, struct vnode *b, caddr_t c, struct vnode *d,
2030           struct vnode *e, caddr_t f, struct ucred *g)
2031 {
2032     int glockOwner, ret;
2033
2034     glockOwner = ISAFS_GLOCK();
2035     if (!glockOwner)
2036         AFS_GLOCK();
2037     ret = (*afs_gn_vnodeops.vn_rename) (a, b, c, d, e, f, g);
2038     if (!glockOwner)
2039         AFS_GUNLOCK();
2040
2041     return ret;
2042 }
2043
2044 static
2045 vn_rmdir(struct vnode *a, struct vnode *b, char *c, struct ucred *d)
2046 {
2047     int glockOwner, ret;
2048
2049     glockOwner = ISAFS_GLOCK();
2050     if (!glockOwner)
2051         AFS_GLOCK();
2052     ret = (*afs_gn_vnodeops.vn_rmdir) (a, b, c, d);
2053     if (!glockOwner)
2054         AFS_GUNLOCK();
2055
2056     return ret;
2057 }
2058
2059 static
2060 vn_lookup(struct vnode *a, struct vnode **b, char *c, int32long64_t d,
2061           struct vattr *v, struct ucred *e)
2062 {
2063     int glockOwner, ret;
2064
2065     glockOwner = ISAFS_GLOCK();
2066     if (!glockOwner)
2067         AFS_GLOCK();
2068     ret = (*afs_gn_vnodeops.vn_lookup) (a, b, c, d, v, e);
2069     if (!glockOwner)
2070         AFS_GUNLOCK();
2071
2072     return ret;
2073 }
2074
2075 static
2076 vn_fid(struct vnode *a, struct fileid *b, struct ucred *c)
2077 {
2078     int glockOwner, ret;
2079
2080     glockOwner = ISAFS_GLOCK();
2081     if (!glockOwner)
2082         AFS_GLOCK();
2083     ret = (*afs_gn_vnodeops.vn_fid) (a, b, c);
2084     if (!glockOwner)
2085         AFS_GUNLOCK();
2086
2087     return ret;
2088 }
2089
2090 static
2091 vn_open(struct vnode *a, 
2092         int32long64_t b, 
2093         ext_t c, 
2094         caddr_t * d, 
2095         struct ucred *e)
2096 {
2097     int glockOwner, ret;
2098
2099     glockOwner = ISAFS_GLOCK();
2100     if (!glockOwner)
2101         AFS_GLOCK();
2102     ret = (*afs_gn_vnodeops.vn_open) (a, b, c, d, e);
2103     if (!glockOwner)
2104         AFS_GUNLOCK();
2105
2106     return ret;
2107 }
2108
2109 static
2110 vn_create(struct vnode *a, struct vnode **b, int32long64_t c, caddr_t d,
2111           int32long64_t e, caddr_t * f, struct ucred *g)
2112 {
2113     int glockOwner, ret;
2114
2115     glockOwner = ISAFS_GLOCK();
2116     if (!glockOwner)
2117         AFS_GLOCK();
2118     ret = (*afs_gn_vnodeops.vn_create) (a, b, c, d, e, f, g);
2119     if (!glockOwner)
2120         AFS_GUNLOCK();
2121
2122     return ret;
2123 }
2124
2125 static
2126 vn_hold(struct vnode *a)
2127 {
2128     int glockOwner, ret;
2129
2130     glockOwner = ISAFS_GLOCK();
2131     if (!glockOwner)
2132         AFS_GLOCK();
2133     ret = (*afs_gn_vnodeops.vn_hold) (a);
2134     if (!glockOwner)
2135         AFS_GUNLOCK();
2136
2137     return ret;
2138 }
2139
2140 static
2141 vn_rele(struct vnode *a)
2142 {
2143     int glockOwner, ret;
2144
2145     glockOwner = ISAFS_GLOCK();
2146     if (!glockOwner)
2147         AFS_GLOCK();
2148     ret = (*afs_gn_vnodeops.vn_rele) (a);
2149     if (!glockOwner)
2150         AFS_GUNLOCK();
2151
2152     return ret;
2153 }
2154
2155 static
2156 vn_close(struct vnode *a, int32long64_t b, caddr_t c, struct ucred *d)
2157 {
2158     int glockOwner, ret;
2159
2160     glockOwner = ISAFS_GLOCK();
2161     if (!glockOwner)
2162         AFS_GLOCK();
2163     ret = (*afs_gn_vnodeops.vn_close) (a, b, c, d);
2164     if (!glockOwner)
2165         AFS_GUNLOCK();
2166
2167     return ret;
2168 }
2169
2170 static
2171 vn_map(struct vnode *a, caddr_t b, uint32long64_t c, uint32long64_t d,
2172        uint32long64_t e, struct ucred *f)
2173 {
2174     int glockOwner, ret;
2175
2176     glockOwner = ISAFS_GLOCK();
2177     if (!glockOwner)
2178         AFS_GLOCK();
2179     ret = (*afs_gn_vnodeops.vn_map) (a, b, c, d, e, f);
2180     if (!glockOwner)
2181         AFS_GUNLOCK();
2182
2183     return ret;
2184 }
2185
2186 static
2187 vn_unmap(struct vnode *a, int32long64_t b, struct ucred *c)
2188 {
2189     int glockOwner, ret;
2190
2191     glockOwner = ISAFS_GLOCK();
2192     if (!glockOwner)
2193         AFS_GLOCK();
2194     ret = (*afs_gn_vnodeops.vn_unmap) (a, b, c);
2195     if (!glockOwner)
2196         AFS_GUNLOCK();
2197
2198     return ret;
2199 }
2200
2201 static
2202 vn_access(struct vnode *a, int32long64_t b, int32long64_t c, struct ucred *d)
2203 {
2204     int glockOwner, ret;
2205
2206     glockOwner = ISAFS_GLOCK();
2207     if (!glockOwner)
2208         AFS_GLOCK();
2209     ret = (*afs_gn_vnodeops.vn_access) (a, b, c, d);
2210     if (!glockOwner)
2211         AFS_GUNLOCK();
2212
2213     return ret;
2214 }
2215
2216 static
2217 vn_getattr(struct vnode *a, struct vattr *b, struct ucred *c)
2218 {
2219     int glockOwner, ret;
2220
2221     glockOwner = ISAFS_GLOCK();
2222     if (!glockOwner)
2223         AFS_GLOCK();
2224     ret = (*afs_gn_vnodeops.vn_getattr) (a, b, c);
2225     if (!glockOwner)
2226         AFS_GUNLOCK();
2227
2228     return ret;
2229 }
2230
2231 static
2232 vn_setattr(struct vnode *a, int32long64_t b, int32long64_t c, int32long64_t d,
2233            int32long64_t e, struct ucred *f)
2234 {
2235     int glockOwner, ret;
2236
2237     glockOwner = ISAFS_GLOCK();
2238     if (!glockOwner)
2239         AFS_GLOCK();
2240     ret = (*afs_gn_vnodeops.vn_setattr) (a, b, c, d, e, f);
2241     if (!glockOwner)
2242         AFS_GUNLOCK();
2243
2244     return ret;
2245 }
2246
2247 static
2248 vn_fclear(struct vnode *a, int32long64_t b, offset_t c, offset_t d
2249           , caddr_t e, struct ucred *f)
2250 {
2251     int glockOwner, ret;
2252
2253     glockOwner = ISAFS_GLOCK();
2254     if (!glockOwner)
2255         AFS_GLOCK();
2256     ret = (*afs_gn_vnodeops.vn_fclear) (a, b, c, d, e, f);
2257     if (!glockOwner)
2258         AFS_GUNLOCK();
2259
2260     return ret;
2261 }
2262
2263 static
2264 vn_fsync(struct vnode *a, int32long64_t b, int32long64_t c, struct ucred *d)
2265 {
2266     int glockOwner, ret;
2267
2268     glockOwner = ISAFS_GLOCK();
2269     if (!glockOwner)
2270         AFS_GLOCK();
2271     ret = (*afs_gn_vnodeops.vn_fsync) (a, b, c, d);
2272     if (!glockOwner)
2273         AFS_GUNLOCK();
2274
2275     return ret;
2276 }
2277
2278 static
2279 vn_ftrunc(struct vnode *a, int32long64_t b, offset_t c, caddr_t d,
2280           struct ucred *e)
2281 {
2282     int glockOwner, ret;
2283
2284     glockOwner = ISAFS_GLOCK();
2285     if (!glockOwner)
2286         AFS_GLOCK();
2287     ret = (*afs_gn_vnodeops.vn_ftrunc) (a, b, c, d, e);
2288     if (!glockOwner)
2289         AFS_GUNLOCK();
2290
2291     return ret;
2292 }
2293
2294 static
2295 vn_rdwr(struct vnode *a, enum uio_rw b, int32long64_t c, struct uio *d,
2296         ext_t e, caddr_t f, struct vattr *v, struct ucred *g)
2297 {
2298     int glockOwner, ret;
2299
2300     glockOwner = ISAFS_GLOCK();
2301     if (!glockOwner)
2302         AFS_GLOCK();
2303     ret = (*afs_gn_vnodeops.vn_rdwr) (a, b, c, d, e, f, v, g);
2304     if (!glockOwner)
2305         AFS_GUNLOCK();
2306
2307     return ret;
2308 }
2309
2310 static
2311 vn_lockctl(struct vnode *a,
2312            offset_t b,
2313            struct eflock *c,
2314            int32long64_t d,
2315            int (*e) (),
2316 #ifdef AFS_AIX52_ENV /* Changed in AIX 5.2 and up */
2317                ulong * f, 
2318 #else /* AFS_AIX52_ENV */
2319                ulong32int64_t * f,
2320 #endif /* AFS_AIX52_ENV */
2321            struct ucred *g)
2322 {
2323     int glockOwner, ret;
2324
2325     glockOwner = ISAFS_GLOCK();
2326     if (!glockOwner)
2327         AFS_GLOCK();
2328     ret = (*afs_gn_vnodeops.vn_lockctl) (a, b, c, d, e, f, g);
2329     if (!glockOwner)
2330         AFS_GUNLOCK();
2331
2332     return ret;
2333 }
2334
2335 static
2336 vn_ioctl(struct vnode *a, int32long64_t b, caddr_t c, size_t d, ext_t e,
2337          struct ucred *f)
2338 {
2339     int glockOwner, ret;
2340
2341     glockOwner = ISAFS_GLOCK();
2342     if (!glockOwner)
2343         AFS_GLOCK();
2344     ret = (*afs_gn_vnodeops.vn_ioctl) (a, b, c, d, e, f);
2345     if (!glockOwner)
2346         AFS_GUNLOCK();
2347
2348     return ret;
2349 }
2350
2351 static
2352 vn_readlink(struct vnode *a, struct uio *b, struct ucred *c)
2353 {
2354     int glockOwner, ret;
2355
2356     glockOwner = ISAFS_GLOCK();
2357     if (!glockOwner)
2358         AFS_GLOCK();
2359     ret = (*afs_gn_vnodeops.vn_readlink) (a, b, c);
2360     if (!glockOwner)
2361         AFS_GUNLOCK();
2362
2363     return ret;
2364 }
2365
2366 static
2367 vn_select(struct vnode *a, int32long64_t b, ushort c, ushort * d,
2368           void (*e) (), caddr_t f, struct ucred *g)
2369 {
2370     int glockOwner, ret;
2371
2372     glockOwner = ISAFS_GLOCK();
2373     if (!glockOwner)
2374         AFS_GLOCK();
2375     ret = (*afs_gn_vnodeops.vn_select) (a, b, c, d, e, f, g);
2376     if (!glockOwner)
2377         AFS_GUNLOCK();
2378
2379     return ret;
2380 }
2381
2382 static
2383 vn_symlink(struct vnode *a, char *b, char *c, struct ucred *d)
2384 {
2385     int glockOwner, ret;
2386
2387     glockOwner = ISAFS_GLOCK();
2388     if (!glockOwner)
2389         AFS_GLOCK();
2390     ret = (*afs_gn_vnodeops.vn_symlink) (a, b, c, d);
2391     if (!glockOwner)
2392         AFS_GUNLOCK();
2393
2394     return ret;
2395 }
2396
2397 static
2398 vn_readdir(struct vnode *a, struct uio *b, struct ucred *c)
2399 {
2400     int glockOwner, ret;
2401
2402     glockOwner = ISAFS_GLOCK();
2403     if (!glockOwner)
2404         AFS_GLOCK();
2405     ret = (*afs_gn_vnodeops.vn_readdir) (a, b, c);
2406     if (!glockOwner)
2407         AFS_GUNLOCK();
2408
2409     return ret;
2410 }
2411
2412 static
2413 vn_revoke(struct vnode *a, int32long64_t b, int32long64_t c, struct vattr *d,
2414           struct ucred *e)
2415 {
2416     int glockOwner, ret;
2417
2418     glockOwner = ISAFS_GLOCK();
2419     if (!glockOwner)
2420         AFS_GLOCK();
2421     ret = (*afs_gn_vnodeops.vn_revoke) (a, b, c, d, e);
2422     if (!glockOwner)
2423         AFS_GUNLOCK();
2424
2425     return ret;
2426 }
2427
2428 static
2429 vn_getacl(struct vnode *a, struct uio *b, struct ucred *c)
2430 {
2431     int glockOwner, ret;
2432
2433     glockOwner = ISAFS_GLOCK();
2434     if (!glockOwner)
2435         AFS_GLOCK();
2436     ret = (*afs_gn_vnodeops.vn_getacl) (a, b, c);
2437     if (!glockOwner)
2438         AFS_GUNLOCK();
2439
2440     return ret;
2441 }
2442
2443 static
2444 vn_setacl(struct vnode *a, struct uio *b, struct ucred *c)
2445 {
2446     int glockOwner, ret;
2447
2448     glockOwner = ISAFS_GLOCK();
2449     if (!glockOwner)
2450         AFS_GLOCK();
2451     ret = (*afs_gn_vnodeops.vn_setacl) (a, b, c);
2452     if (!glockOwner)
2453         AFS_GUNLOCK();
2454
2455     return ret;
2456 }
2457
2458 static
2459 vn_getpcl(struct vnode *a, struct uio *b, struct ucred *c)
2460 {
2461     int glockOwner, ret;
2462
2463     glockOwner = ISAFS_GLOCK();
2464     if (!glockOwner)
2465         AFS_GLOCK();
2466     ret = (*afs_gn_vnodeops.vn_getpcl) (a, b, c);
2467     if (!glockOwner)
2468         AFS_GUNLOCK();
2469
2470     return ret;
2471 }
2472
2473 static
2474 vn_setpcl(struct vnode *a, struct uio *b, struct ucred *c)
2475 {
2476     int glockOwner, ret;
2477
2478     glockOwner = ISAFS_GLOCK();
2479     if (!glockOwner)
2480         AFS_GLOCK();
2481     ret = (*afs_gn_vnodeops.vn_setpcl) (a, b, c);
2482     if (!glockOwner)
2483         AFS_GUNLOCK();
2484
2485     return ret;
2486 }
2487
2488
2489 struct vnodeops locked_afs_gn_vnodeops = {
2490     vn_link,
2491     vn_mkdir,
2492     vn_mknod,
2493     vn_remove,
2494     vn_rename,
2495     vn_rmdir,
2496     vn_lookup,
2497     vn_fid,
2498     vn_open,
2499     vn_create,
2500     vn_hold,
2501     vn_rele,
2502     vn_close,
2503     vn_map,
2504     vn_unmap,
2505     vn_access,
2506     vn_getattr,
2507     vn_setattr,
2508     vn_fclear,
2509     vn_fsync,
2510     vn_ftrunc,
2511     vn_rdwr,
2512     vn_lockctl,
2513     vn_ioctl,
2514     vn_readlink,
2515     vn_select,
2516     vn_symlink,
2517     vn_readdir,
2518     (int(*)(struct vnode*,struct buf*,struct ucred*))
2519         afs_gn_strategy,        /* no locking!!! (discovered the hard way) */
2520     vn_revoke,
2521     vn_getacl,
2522     vn_setacl,
2523     vn_getpcl,
2524     vn_setpcl,
2525     afs_gn_seek,
2526     (int(*)(struct vnode *, int32long64_t, int32long64_t, offset_t, offset_t, struct ucred *))
2527         afs_gn_enosys,          /* vn_fsync_range */
2528     (int(*)(struct vnode *, struct vnode **, int32long64_t, char *, struct vattr *, int32long64_t, caddr_t *, struct ucred *))
2529         afs_gn_enosys,          /* vn_create_attr */
2530     (int(*)(struct vnode *, int32long64_t, void *, size_t, struct ucred *))
2531         afs_gn_enosys,          /* vn_finfo */
2532     (int(*)(struct vnode *, caddr_t, offset_t, offset_t, uint32long64_t, uint32long64_t, struct ucred *))
2533         afs_gn_enosys,          /* vn_map_lloff */
2534     (int(*)(struct vnode*,struct uio*,int*,struct ucred*))
2535         afs_gn_enosys,          /* vn_readdir_eofp */
2536     (int(*)(struct vnode *, enum uio_rw, int32long64_t, struct uio *, ext_t , caddr_t, struct vattr *, struct vattr *, struct ucred *))
2537         afs_gn_enosys,          /* vn_rdwr_attr */
2538     (int(*)(struct vnode*,int,void*,struct ucred*))
2539         afs_gn_enosys,          /* vn_memcntl */
2540 #ifdef AFS_AIX53_ENV /* Present in AIX 5.3 and up */
2541     (int(*)(struct vnode*,const char*,struct uio*,struct ucred*))
2542         afs_gn_enosys,          /* vn_getea */
2543     (int(*)(struct vnode*,const char*,struct uio*,int,struct ucred*))
2544         afs_gn_enosys,          /* vn_setea */
2545     (int(*)(struct vnode *, struct uio *, struct ucred *))
2546         afs_gn_enosys,          /* vn_listea */
2547     (int(*)(struct vnode *, const char *, struct ucred *))
2548         afs_gn_enosys,          /* vn_removeea */
2549     (int(*)(struct vnode *, const char *, struct vattr *, struct ucred *))
2550         afs_gn_enosys,          /* vn_statea */
2551     (int(*)(struct vnode *, uint64_t, acl_type_t *, struct uio *, size_t *, mode_t *, struct ucred *))
2552         afs_gn_enosys,          /* vn_getxacl */
2553     (int(*)(struct vnode *, uint64_t, acl_type_t, struct uio *, mode_t,  struct ucred *))
2554         afs_gn_enosys,          /* vn_setxacl */
2555 #else /* AFS_AIX53_ENV */
2556     afs_gn_enosys,              /* vn_spare7 */
2557     afs_gn_enosys,              /* vn_spare8 */
2558     afs_gn_enosys,              /* vn_spare9 */
2559     afs_gn_enosys,              /* vn_spareA */
2560     afs_gn_enosys,              /* vn_spareB */
2561     afs_gn_enosys,              /* vn_spareC */
2562     afs_gn_enosys,              /* vn_spareD */
2563 #endif /* AFS_AIX53_ENV */
2564     afs_gn_enosys,              /* vn_spareE */
2565     afs_gn_enosys               /* vn_spareF */
2566 #ifdef AFS_AIX51_ENV
2567     ,(int(*)(struct gnode*,long long,char*,unsigned long*, unsigned long*,unsigned int*))
2568         afs_gn_enosys,          /* pagerBackRange */
2569     (int64_t(*)(struct gnode*))
2570         afs_gn_enosys,          /* pagerGetFileSize */
2571     (void(*)(struct gnode *, vpn_t, vpn_t *, vpn_t *, vpn_t *, boolean_t))
2572         afs_gn_enosys,          /* pagerReadAhead */
2573     (void(*)(struct gnode *, int64_t, int64_t, uint))
2574         afs_gn_enosys,          /* pagerReadWriteBehind */
2575     (void(*)(struct gnode*,long long,unsigned long,unsigned long,unsigned int))
2576         afs_gn_enosys           /* pagerEndCopy */
2577 #endif
2578 };
2579
2580 struct gfs afs_gfs = {
2581     &locked_Afs_vfsops,
2582     &locked_afs_gn_vnodeops,
2583     AFS_MOUNT_AFS,
2584     "afs",
2585     Afs_init,
2586     GFS_VERSION4 | GFS_VERSION42 | GFS_REMOTE,
2587     NULL
2588 };