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