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