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