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