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