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