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