discon-allow-saving-vcaches-on-shutdown-20090126
[openafs.git] / src / afs / IRIX / 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 /*
11  * SGI specific vnodeops + other misc interface glue
12  */
13 #include <afsconfig.h>
14 #include "afs/param.h"
15
16 RCSID
17     ("$Header$");
18
19 #ifdef  AFS_SGI62_ENV
20 #include "afs/sysincludes.h"    /* Standard vendor system headers */
21 #include "afsincludes.h"        /* Afs-based standard headers */
22 #include "afs/afs_stats.h"      /* statistics */
23 #include "sys/flock.h"
24 #include "afs/nfsclient.h"
25
26 /* AFSBSIZE must be at least the size of a page, else the client will hang.
27  * For 64 bit platforms, the page size is more than 8K.
28  */
29 #define AFSBSIZE        _PAGESZ
30 extern struct afs_exporter *root_exported;
31 extern void afs_chkpgoob(vnode_t *, pgno_t);
32
33 static void afs_strategy();
34 static int afs_xread(), afs_xwrite();
35 static int afs_xbmap(), afs_map(), afs_reclaim();
36 #ifndef AFS_SGI65_ENV
37 static int afs_addmap(), afs_delmap();
38 #endif
39 extern int afs_open(), afs_close(), afs_ioctl(), afs_getattr(), afs_setattr();
40 extern int afs_access(), afs_lookup();
41 extern int afs_create(), afs_remove(), afs_link(), afs_rename();
42 extern int afs_mkdir(), afs_rmdir(), afs_readdir();
43 extern int afs_symlink(), afs_readlink(), afs_fsync(), afs_fid(),
44 afs_frlock();
45 static int afs_seek(OSI_VC_DECL(a), off_t b, off_t * c);
46 #ifdef AFS_SGI64_ENV
47 extern int afs_xinactive();
48 #else
49 extern void afs_xinactive();
50 #endif
51
52 extern void afs_rwlock(OSI_VN_DECL(vp), AFS_RWLOCK_T b);
53 extern void afs_rwunlock(OSI_VN_DECL(vp), AFS_RWLOCK_T b);
54
55 extern int afs_fid2();
56
57 static int afsrwvp(register struct vcache *avc, register struct uio *uio,
58                    enum uio_rw rw, int ioflag,
59 #ifdef AFS_SGI64_ENV
60                    struct cred *cr, struct flid *flp);
61 #else
62                    struct cred *cr);
63 #endif
64 #ifdef MP
65 static void mp_afs_rwlock(OSI_VN_DECL(a), AFS_RWLOCK_T b);
66 static void mp_afs_rwunlock(OSI_VN_DECL(a), AFS_RWLOCK_T b);
67 struct vnodeops afs_lockedvnodeops =
68 #else
69 struct vnodeops Afs_vnodeops =
70 #endif
71 {
72 #ifdef AFS_SGI64_ENV
73 #ifdef AFS_SGI65_ENV
74     BHV_IDENTITY_INIT_POSITION(VNODE_POSITION_BASE),
75 #else
76     VNODE_POSITION_BASE,
77 #endif
78 #endif
79     afs_open,
80     afs_close,
81     afs_xread,
82     afs_xwrite,
83     afs_ioctl,
84     fs_setfl,
85     afs_getattr,
86     afs_setattr,
87     afs_access,
88     afs_lookup,
89     afs_create,
90     afs_remove,
91     afs_link,
92     afs_rename,
93     afs_mkdir,
94     afs_rmdir,
95     afs_readdir,
96     afs_symlink,
97     afs_readlink,
98     afs_fsync,
99     afs_xinactive,
100     afs_fid,
101     afs_fid2,
102     afs_rwlock,
103     afs_rwunlock,
104     afs_seek,
105     fs_cmp,
106     afs_frlock,
107     fs_nosys,                   /* realvp */
108     afs_xbmap,
109     afs_strategy,
110     afs_map,
111 #ifdef AFS_SGI65_ENV
112     fs_noerr,                   /* addmap - devices only */
113     fs_noerr,                   /* delmap - devices only */
114 #else
115     afs_addmap,
116     afs_delmap,
117 #endif
118     fs_poll,                    /* poll */
119     fs_nosys,                   /* dump */
120     fs_pathconf,
121     fs_nosys,                   /* allocstore */
122     fs_nosys,                   /* fcntl */
123     afs_reclaim,                /* reclaim */
124     fs_nosys,                   /* attr_get */
125     fs_nosys,                   /* attr_set */
126     fs_nosys,                   /* attr_remove */
127     fs_nosys,                   /* attr_list */
128 #ifdef AFS_SGI64_ENV
129 #ifdef AFS_SGI65_ENV
130     fs_cover,
131     (vop_link_removed_t) fs_noval,
132     fs_vnode_change,
133     fs_tosspages,
134     fs_flushinval_pages,
135     fs_flush_pages,
136     fs_invalfree_pages,
137     fs_pages_sethole,
138     (vop_commit_t) fs_nosys,
139     (vop_readbuf_t) fs_nosys,
140     fs_strgetmsg,
141     fs_strputmsg,
142 #else
143     fs_mount,
144 #endif
145 #endif
146 };
147
148 #ifndef MP
149 struct vnodeops *afs_ops = &Afs_vnodeops;
150 #endif
151
152 int
153 afs_frlock(OSI_VN_DECL(vp), int cmd, struct flock *lfp, int flag,
154            off_t offset,
155 #ifdef AFS_SGI65_ENV
156            vrwlock_t vrwlock,
157 #endif
158            cred_t * cr)
159 {
160     int error;
161     OSI_VN_CONVERT(vp);
162 #ifdef AFS_SGI65_ENV
163     struct flid flid;
164     int pid;
165     get_current_flid(&flid);
166     pid = flid.fl_pid;
167 #endif
168
169     /*
170      * Since AFS doesn't support byte-wise locks (and simply
171      * says yes! we handle byte locking locally only.
172      * This makes lots of things work much better
173      * XXX This doesn't properly handle moving from a
174      * byte-wise lock up to a full file lock (we should
175      * remove the byte locks ..) Of course neither did the
176      * regular AFS way ...
177      *
178      * For GETLK we do a bit more - we first check any byte-wise
179      * locks - if none then check for full AFS file locks
180      */
181     if (cmd == F_GETLK || lfp->l_whence != 0 || lfp->l_start != 0
182         || (lfp->l_len != MAXEND && lfp->l_len != 0)) {
183         AFS_RWLOCK(vp, VRWLOCK_WRITE);
184         AFS_GUNLOCK();
185 #ifdef AFS_SGI65_ENV
186         error =
187             fs_frlock(OSI_VN_ARG(vp), cmd, lfp, flag, offset, vrwlock, cr);
188 #else
189         error = fs_frlock(vp, cmd, lfp, flag, offset, cr);
190 #endif
191         AFS_GLOCK();
192         AFS_RWUNLOCK(vp, VRWLOCK_WRITE);
193         if (error || cmd != F_GETLK)
194             return error;
195         if (lfp->l_type != F_UNLCK)
196             /* found some blocking lock */
197             return 0;
198         /* fall through to check for full AFS file locks */
199     }
200
201     /* map BSD style to plain - we don't call reclock() 
202      * and its only there that the difference is important
203      */
204     switch (cmd) {
205     case F_GETLK:
206     case F_RGETLK:
207         break;
208     case F_SETLK:
209     case F_RSETLK:
210         break;
211     case F_SETBSDLK:
212         cmd = F_SETLK;
213         break;
214     case F_SETLKW:
215     case F_RSETLKW:
216         break;
217     case F_SETBSDLKW:
218         cmd = F_SETLKW;
219         break;
220     default:
221         return EINVAL;
222     }
223
224     AFS_GUNLOCK();
225
226     error = convoff(vp, lfp, 0, offset, SEEKLIMIT
227 #ifdef AFS_SGI64_ENV
228                     , OSI_GET_CURRENT_CRED()
229 #endif /* AFS_SGI64_ENV */
230         );
231
232     AFS_GLOCK();
233     if (!error) {
234 #ifdef AFS_SGI65_ENV
235         error = afs_lockctl(vp, lfp, cmd, cr, pid);
236 #else
237         error = afs_lockctl(vp, lfp, cmd, cr, OSI_GET_CURRENT_PID());
238 #endif
239     }
240     return error;
241 }
242
243
244 /*
245  * We need to get the cache hierarchy right.
246  * First comes the page cache - pages are hashed based on afs
247  * vnode and offset. It is important to have things hashed here
248  * for the VM/paging system to work.
249  * Note that the paging system calls VOP_READ with the UIO_NOSPACE -
250  * it simply requires that somehow the page is hashed
251  * upon successful return.
252  * This means in afs_read we
253  * must call the 'chunk' code that handles page insertion. In order
254  * to actually get the data, 'chunk' calls the VOP_STRATEGY routine.
255  * This is basically the std afs_read routine - validating and
256  * getting the info into the Dcache, then calling VOP_READ.
257  * The only bad thing here is that by calling VOP_READ (and VOP_WRITE
258  * to fill the cache) we will get 2 copies of these pages into the
259  * page cache - one hashed on afs vnode and one on efs vnode. THis
260  * is wasteful but does no harm. A potential solution involves
261  * causing an ASYNC flush of the newly fetched cache data and
262  * doing direct I/O on the read side....
263  */
264 /* ARGSUSED */
265 #ifdef AFS_SGI64_ENV
266 static int
267 afs_xread(OSI_VC_ARG(avc), uiop, ioflag, cr, flp)
268      struct flid *flp;
269 #else
270 static int
271 afs_xread(OSI_VC_ARG(avc), uiop, ioflag, cr)
272 #endif
273 OSI_VC_DECL(avc);
274      struct uio *uiop;
275      int ioflag;
276      struct cred *cr;
277 {
278     int code;
279     OSI_VC_CONVERT(avc);
280
281     osi_Assert(avc->v.v_count > 0);
282     if (avc->v.v_type != VREG)
283         return EISDIR;
284
285 #ifdef AFS_SGI64_ENV
286 #ifdef AFS_SGI65_ENV
287     if (!(ioflag & IO_ISLOCKED))
288         AFS_RWLOCK((vnode_t *) avc, VRWLOCK_READ);
289 #endif
290     code = afsrwvp(avc, uiop, UIO_READ, ioflag, cr, flp);
291 #ifdef AFS_SGI65_ENV
292     if (!(ioflag & IO_ISLOCKED))
293         AFS_RWUNLOCK((vnode_t *) avc, VRWLOCK_READ);
294 #endif
295 #else
296     code = afsrwvp(avc, uiop, UIO_READ, ioflag, cr);
297 #endif
298     return code;
299 }
300
301 /* ARGSUSED */
302 #ifdef AFS_SGI64_ENV
303 static int
304 afs_xwrite(OSI_VC_ARG(avc), uiop, ioflag, cr, flp)
305      struct flid *flp;
306 #else
307 static int
308 afs_xwrite(OSI_VC_ARG(avc), uiop, ioflag, cr)
309 #endif
310 OSI_VC_DECL(avc);
311      struct uio *uiop;
312      int ioflag;
313      struct cred *cr;
314 {
315     int code;
316     OSI_VC_CONVERT(avc);
317
318     osi_Assert(avc->v.v_count > 0);
319     if (avc->v.v_type != VREG)
320         return EISDIR;
321
322     if (ioflag & IO_APPEND)
323         uiop->uio_offset = avc->f.m.Length;
324 #ifdef AFS_SGI64_ENV
325 #ifdef AFS_SGI65_ENV
326     if (!(ioflag & IO_ISLOCKED))
327         AFS_RWLOCK(((vnode_t *) avc), VRWLOCK_WRITE);
328 #endif
329     code = afsrwvp(avc, uiop, UIO_WRITE, ioflag, cr, flp);
330 #ifdef AFS_SGI65_ENV
331     if (!(ioflag & IO_ISLOCKED))
332         AFS_RWUNLOCK((vnode_t *) avc, VRWLOCK_WRITE);
333 #endif
334 #else
335     code = afsrwvp(avc, uiop, UIO_WRITE, ioflag, cr);
336 #endif
337     return code;
338 }
339
340 static int prra = 0;
341 static int prnra = 0;
342 static int acchk = 0;
343 static int acdrop = 0;
344
345 static int
346 afsrwvp(register struct vcache *avc, register struct uio *uio, enum uio_rw rw,
347         int ioflag,
348 #ifdef AFS_SGI64_ENV
349         struct cred *cr, struct flid *flp)
350 #else
351         struct cred *cr)
352 #endif
353 {
354     register struct vnode *vp = AFSTOV(avc);
355     struct buf *bp;
356     daddr_t bn;
357     off_t acnt, cnt;
358     off_t off, newoff;
359     off_t bsize, rem, len;
360     int error;
361     struct bmapval bmv[2];
362     int nmaps, didFakeOpen = 0;
363     struct vrequest treq;
364     struct dcache *tdc;
365     int counter = 0;
366
367     osi_Assert((valusema(&avc->vc_rwlock) <= 0)
368                && (OSI_GET_LOCKID() == avc->vc_rwlockid));
369
370
371     newoff = uio->uio_resid + uio->uio_offset;
372     if (uio->uio_resid <= 0) {
373         return (0);
374     }
375     if (uio->uio_offset < 0 || newoff < 0)  {
376         return (EINVAL);
377     }
378     if (ioflag & IO_DIRECT)
379         return EINVAL;
380
381     if (rw == UIO_WRITE && vp->v_type == VREG && newoff > uio->uio_limit) {
382         return (EFBIG);
383     }
384
385     afs_Trace4(afs_iclSetp, CM_TRACE_GRDWR, ICL_TYPE_POINTER, avc,
386                ICL_TYPE_INT32, ioflag, ICL_TYPE_INT32, rw, ICL_TYPE_INT32, 0);
387
388     /* get a validated vcache entry */
389     afs_InitReq(&treq, cr);
390     error = afs_VerifyVCache(avc, &treq);
391     if (error)
392         return afs_CheckCode(error, &treq, 51);
393
394     /*
395      * flush any stale pages - this will unmap
396      * and invalidate all pages for vp (NOT writing them back!)
397      */
398     osi_FlushPages(avc, cr);
399
400     if (cr && AFS_NFSXLATORREQ(cr) && rw == UIO_READ) {
401         if (!afs_AccessOK
402             (avc, PRSFS_READ, &treq,
403              CHECK_MODE_BITS | CMB_ALLOW_EXEC_AS_READ))
404             return EACCES;
405     }
406     /*
407      * To handle anonymous calls to VOP_STRATEGY from afs_sync/sync/bdflush
408      * we need better than the callers credentials. So we squirrel away
409      * the last writers credentials
410      */
411     if (rw == UIO_WRITE || (rw == UIO_READ && avc->cred == NULL)) {
412         ObtainWriteLock(&avc->lock, 92);
413         if (avc->cred)
414             crfree(avc->cred);
415         crhold(cr);
416         avc->cred = cr;
417         ReleaseWriteLock(&avc->lock);
418     }
419
420     /*
421      * We have to bump the open/exwriters field here
422      * courtesy of the nfs xlator
423      * because there're no open/close nfs rpc's to call our afs_open/close.
424      */
425     if (root_exported && rw == UIO_WRITE) {
426         ObtainWriteLock(&avc->lock, 234);
427         if (root_exported) {
428             didFakeOpen = 1;
429             afs_FakeOpen(avc);
430         }
431         ReleaseWriteLock(&avc->lock);
432     }
433     error = 0;
434
435     if (rw == UIO_WRITE) {
436         ObtainWriteLock(&avc->lock, 330);
437         avc->f.states |= CDirty;
438         ReleaseWriteLock(&avc->lock);
439     }
440
441     AFS_GUNLOCK();
442
443     do {
444         /* If v_dpages is set SGI 5.3 will convert those pages to
445          * B_DELWRI in chunkread and getchunk. Write the pages out
446          * before we trigger that behavior. For 6.1, dirty pages stay
447          * around too long and we should get rid of them as quickly
448          * as possible.
449          */
450         while (VN_GET_DPAGES(vp))
451             pdflush(vp, 0);
452
453         if (avc->vc_error) {
454             error = avc->vc_error;
455             break;
456         }
457         bsize = AFSBSIZE;       /* why not?? */
458         off = uio->uio_offset % bsize;
459         bn = BTOBBT(uio->uio_offset - off);
460         /*
461          * decrease bsize - otherwise we will
462          * get 'extra' pages in the cache for this
463          * vnode that we would need to flush when
464          * calling e.g. ptossvp.
465          * So we can use Length in ptossvp,
466          * we make sure we never go more than to the file size
467          * rounded up to a page boundary.
468          * That doesn't quite work, since we may get a page hashed to
469          * the vnode w/o updating the length. Thus we always use
470          * MAXLONG in ptossvp to be safe.
471          */
472         if (rw == UIO_READ) {
473             /*
474              * read/paging in a normal file
475              */
476             rem = avc->f.m.Length - uio->uio_offset;
477             if (rem <= 0)
478                 /* EOF */
479                 break;
480             /*
481              * compute minimum of rest of block and rest of file
482              */
483             cnt = MIN(bsize - off, rem);
484             osi_Assert((off + cnt) <= bsize);
485             bsize = ctob(btoc(off + cnt));
486             len = BTOBBT(bsize);
487             nmaps = 1;
488             bmv[0].bn = bmv[0].offset = bn;
489             bmv[0].length = len;
490             bmv[0].bsize = bsize;
491             bmv[0].pboff = off;
492             bmv[0].pbsize = MIN(cnt, uio->uio_resid);
493             bmv[0].eof = 0;
494 #ifdef AFS_SGI64_ENV
495             bmv[0].pbdev = vp->v_rdev;
496             bmv[0].pmp = uio->uio_pmp;
497 #endif
498             osi_Assert(cnt > 0);
499             /*
500              * initiate read-ahead if it looks like
501              * we are reading sequentially OR they want
502              * more than one 'bsize' (==AFSBSIZE) worth
503              * XXXHack - to avoid DELWRI buffers we can't
504              * do read-ahead on any file that has potentially
505              * dirty mmap pages.
506              */
507             if ((avc->lastr + BTOBB(AFSBSIZE) == bn
508                  || uio->uio_resid > AFSBSIZE)
509 #ifdef AFS_SGI61_ENV
510                 && (!AFS_VN_MAPPED(vp))
511 #else /* AFS_SGI61_ENV */
512                 && ((vp->v_flag & VWASMAP) == 0)
513 #endif /* AFS_SGI61_ENV */
514                 ) {
515                 rem -= cnt;
516                 if (rem > 0) {
517                     bsize = AFSBSIZE;
518                     bmv[1].bn = bmv[1].offset = bn + len;
519                     osi_Assert((BBTOB(bn + len) % bsize) == 0);
520                     acnt = MIN(bsize, rem);
521                     bsize = ctob(btoc(acnt));
522                     len = BTOBBT(bsize);
523                     nmaps = 2;
524                     bmv[1].length = len;
525                     bmv[1].eof = 0;
526                     bmv[1].bsize = bsize;
527                     bmv[1].pboff = 0;
528                     bmv[1].pbsize = acnt;
529 #ifdef AFS_SGI64_ENV
530                     bmv[1].pmp = uio->uio_pmp;
531                     bmv[1].pbdev = vp->v_rdev;
532 #endif
533                 }
534             }
535 #ifdef DEBUG
536             else if (prnra)
537                 printf
538                     ("NRA:vp 0x%x lastr %d bn %d len %d cnt %d bsize %d rem %d resid %d\n",
539                      vp, avc->lastr, bn, len, cnt, bsize, rem,
540                      uio->uio_resid);
541 #endif
542
543             avc->lastr = bn;
544             bp = chunkread(vp, bmv, nmaps, cr);
545             /*
546              * If at a chunk boundary, start prefetch of next chunk.
547              */
548             if (counter == 0 || AFS_CHUNKOFFSET(off) == 0) {
549                 AFS_GLOCK();
550                 ObtainWriteLock(&avc->lock, 562);
551                 tdc = afs_FindDCache(avc, off);
552                 if (tdc) {
553                     if (!(tdc->mflags & DFNextStarted))
554                         afs_PrefetchChunk(avc, tdc, cr, &treq);
555                     afs_PutDCache(tdc);
556                 }
557                 ReleaseWriteLock(&avc->lock);
558                 AFS_GUNLOCK();
559             }
560             counter++;
561         } else {
562             /*
563              * writing a normal file
564              */
565             /*
566              * Purge dirty chunks of file if there are too many dirty chunks.
567              * Inside the write loop, we only do this at a chunk boundary.
568              * Clean up partial chunk if necessary at end of loop.
569              */
570             if (counter > 0 && AFS_CHUNKOFFSET(uio->uio_offset) == 0) {
571                 AFS_GLOCK();
572                 ObtainWriteLock(&avc->lock, 90);
573                 error = afs_DoPartialWrite(avc, &treq);
574                 if (error == 0)
575                     avc->f.states |= CDirty;
576                 ReleaseWriteLock(&avc->lock);
577                 AFS_GUNLOCK();
578                 if (error)
579                     break;
580             }
581             counter++;
582
583             cnt = MIN(bsize - off, uio->uio_resid);
584             bsize = ctob(btoc(off + cnt));
585             len = BTOBBT(bsize);
586             bmv[0].bn = bn;
587             bmv[0].offset = bn;
588             bmv[0].length = len;
589             bmv[0].eof = 0;
590             bmv[0].bsize = bsize;
591             bmv[0].pboff = off;
592             bmv[0].pbsize = cnt;
593 #ifdef AFS_SGI64_ENV
594             bmv[0].pmp = uio->uio_pmp;
595 #endif
596
597             if (cnt == bsize)
598                 bp = getchunk(vp, bmv, cr);
599             else
600                 bp = chunkread(vp, bmv, 1, cr);
601
602             avc->f.m.Date = osi_Time(); /* Set file date (for ranlib) */
603         }
604         if (bp->b_flags & B_ERROR) {
605             /*
606              * Since we compile -signed, b_error is a signed
607              * char when it should be an unsigned char.
608              * This can cause some errors codes to be interpreted
609              * as negative #s
610              */
611             error = (unsigned char)(bp->b_error);
612             if (!error)
613                 error = EIO;
614 #ifdef DEBUG
615             if (acchk && error) {
616                 cmn_err(CE_WARN, "bp 0x%x has error %d\n", bp, error);
617                 if (acdrop)
618                     debug("AFS");
619             }
620 #endif
621             brelse(bp);
622             break;
623         }
624
625         osi_Assert(bp->b_error == 0);
626
627         if (uio->uio_segflg != UIO_NOSPACE)
628             (void)bp_mapin(bp);
629         AFS_UIOMOVE(bp->b_un.b_addr + bmv[0].pboff, cnt, rw, uio, error);
630         if (rw == UIO_READ || error) {
631             if (bp->b_flags & B_DELWRI) {
632                 bawrite(bp);
633             } else
634                 brelse(bp);
635         } else {
636             /*
637              * m.Length is the maximum number of bytes known to be in the file.
638              * Make sure it is at least as high as the last byte we just wrote
639              * into the buffer.
640              */
641             if (avc->f.m.Length < uio->uio_offset)  {
642                 AFS_GLOCK();
643                 ObtainWriteLock(&avc->lock, 235);
644                 avc->f.m.Length = uio->uio_offset;
645                 ReleaseWriteLock(&avc->lock);
646                 AFS_GUNLOCK();
647             }
648             if (uio->uio_fmode & FSYNC) {
649                 error = bwrite(bp);
650             } else if (off + cnt < bsize) {
651                 bawrite(bp);    /* was bdwrite */
652             } else {
653                 bp->b_flags |= B_AGE;
654                 bawrite(bp);
655             }
656             /*
657              * Since EIO on an unlinked file is non-intuitive - give some
658              * explanation
659              */
660             if (error) {
661                 if (avc->f.m.LinkCount == 0)
662                     cmn_err(CE_WARN,
663                             "AFS: Process pid %d write error %d writing to unlinked file.",
664                             OSI_GET_CURRENT_PID(), error);
665             }
666         }
667     } while (!error && uio->uio_resid > 0);
668     afs_chkpgoob(&avc->v, btoc(avc->f.m.Length));
669
670     AFS_GLOCK();
671
672     if (rw == UIO_WRITE && error == 0 && (avc->f.states & CDirty)) {
673         ObtainWriteLock(&avc->lock, 405);
674         error = afs_DoPartialWrite(avc, &treq);
675         ReleaseWriteLock(&avc->lock);
676     }
677
678     if (!error) {
679 #ifdef AFS_SGI61_ENV
680         if (((ioflag & IO_SYNC) || (ioflag & IO_DSYNC)) && (rw == UIO_WRITE)
681             && !AFS_NFSXLATORREQ(cr)) {
682             error = afs_fsync(avc, 0, cr
683 #ifdef AFS_SGI65_ENV
684                               , 0, 0
685 #endif
686                               );
687         }
688 #else /* AFS_SGI61_ENV */
689         if ((ioflag & IO_SYNC) && (rw == UIO_WRITE) && !AFS_NFSXLATORREQ(cr)) {
690             error = afs_fsync(avc, 0, cr);
691         }
692 #endif /* AFS_SGI61_ENV */
693     }
694     if (didFakeOpen) {
695         ObtainWriteLock(&avc->lock, 236);
696         afs_FakeClose(avc, cr); /* XXXX For nfs trans XXXX */
697         ReleaseWriteLock(&avc->lock);
698     }
699     afs_Trace4(afs_iclSetp, CM_TRACE_GRDWR, ICL_TYPE_POINTER, avc,
700                ICL_TYPE_INT32, ioflag, ICL_TYPE_INT32, rw, ICL_TYPE_INT32,
701                error);
702
703     return (error);
704 }
705
706 int
707 afs_xbmap(OSI_VC_ARG(avc), offset, count, flag, cr, bmv, nbmv)
708 OSI_VC_DECL(avc);
709      off_t offset;
710      ssize_t count;
711      int flag;
712      struct cred *cr;
713      struct bmapval *bmv;
714      int *nbmv;
715 {
716     int bsize;                  /* server's block size in bytes */
717     off_t off;
718     size_t rem, cnt;
719     OSI_VC_CONVERT(avc);
720
721     bsize = AFSBSIZE;
722     off = offset % bsize;       /* offset into block */
723     bmv->bn = BTOBBT(offset - off);
724     bmv->offset = bmv->bn;
725     bmv->pboff = off;
726     rem = avc->f.m.Length - offset;
727     if (rem <= 0)
728         cnt = 0;                /* EOF */
729     else
730         cnt = MIN(bsize - off, rem);
731
732     /*
733      * It is benign to ignore *nbmv > 1, since it is only for requesting
734      * readahead.
735      */
736
737     /*
738      * Don't map more than up to next page if at end of file
739      * See comment in afsrwvp
740      */
741     osi_Assert((off + cnt) <= bsize);
742     bsize = ctob(btoc(off + cnt));
743     bmv->pbsize = MIN(cnt, count);
744     bmv->eof = 0;
745 #ifdef AFS_SGI64_ENV
746     bmv->pmp = NULL;
747     bmv->pbdev = avc->v.v_rdev;
748 #endif
749     bmv->bsize = bsize;
750     bmv->length = BTOBBT(bsize);
751     *nbmv = 1;
752     return (0);
753 }
754
755 /*
756  * called out of chunkread from afs_xread & clusterwrite to push dirty
757  * pages back - this routine
758  * actually does the reading/writing by calling afs_read/afs_write
759  * bp points to a set of pages that have been inserted into
760  * the page cache hashed on afs vp.
761  */
762 static void
763 afs_strategy(OSI_VC_ARG(avc), bp)
764 OSI_VC_DECL(avc);
765      struct buf *bp;
766 {
767     uio_t auio;
768     uio_t *uio = &auio;
769     iovec_t aiovec;
770     int error;
771     struct cred *cr;
772     OSI_VC_CONVERT(avc);
773     vnode_t *vp = (vnode_t *) avc;
774
775     /*
776      * We can't afford DELWRI buffers for 2 reasons:
777      * 1) Since we can call underlying EFS, we can require a
778      *  buffer to flush a buffer. This leads to 2 potential
779      *  recursions/deadlocks
780      *          a) if all buffers are DELWRI afs buffers, then
781      *             ngeteblk -> bwrite -> afs_strategy -> afs_write ->
782      *             UFS_Write -> efs_write -> ngeteblk .... could
783      *             recurse a long ways!
784      *          b) brelse -> chunkhold which can call dchunkpush
785      *             will look for any DELWRI buffers and call strategy
786      *             on them. This can then end up via UFS_Write
787      *             recursing
788      * Current hack:
789      *  a) We never do bdwrite(s) on AFS buffers.
790      *  b) We call pdflush with B_ASYNC
791      *  c) in chunkhold where it can set a buffer DELWRI
792      *     we immediatly do a clusterwrite for AFS vp's
793      * XXX Alas, 'c' got dropped in 5.1 so its possible to get DELWRI
794      *  buffers if someone has mmaped the file and dirtied it then
795      *  reads/faults it again.
796      *  Instead - wherever we call chunkread/getchunk we check for a
797      *  returned bp with DELWRI set, and write it out immediately
798      */
799     if (CheckLock(&avc->lock) && VN_GET_DBUF(vp)) {
800         printf("WARN: afs_strategy vp=%x, v_dbuf=%x bp=%x\n", vp,
801                VN_GET_DBUF(vp), bp);
802         bp->b_error = EIO;
803         bp->b_flags |= B_ERROR;
804         iodone(bp);
805         return;
806     }
807     if (bp->b_error != 0)
808         printf("WARNING: afs_strategy3 vp=%x, bp=%x, err=%x\n", vp, bp,
809                bp->b_error);
810
811     /*
812      * To get credentials somewhat correct (we may be called from bdflush/
813      * sync) we use saved credentials in Vcache.
814      * We must hold them since someone else could change them
815      */
816     ObtainReadLock(&avc->lock);
817     if (bp->b_flags & B_READ) {
818         if (BBTOB(bp->b_blkno) >= avc->f.m.Length) {
819             /* we are responsible for zero'ing the page */
820             caddr_t c;
821             c = bp_mapin(bp);
822             memset(c, 0, bp->b_bcount);
823             iodone(bp);
824             ReleaseReadLock(&avc->lock);
825             return;
826         }
827     } else if ((avc->f.states & CWritingUFS) && (bp->b_flags & B_DELWRI)) {
828         bp->b_ref = 3;
829         ReleaseReadLock(&avc->lock);
830         iodone(bp);
831         return;
832     }
833     cr = avc->cred;
834     osi_Assert(cr);
835     crhold(cr);
836     ReleaseReadLock(&avc->lock);
837
838     aiovec.iov_base = bp_mapin(bp);
839     uio->uio_iov = &aiovec;
840     uio->uio_iovcnt = 1;
841     uio->uio_resid = aiovec.iov_len = bp->b_bcount;
842     uio->uio_offset = BBTOB(bp->b_blkno);
843     uio->uio_segflg = UIO_SYSSPACE;
844     uio->uio_limit = RLIM_INFINITY;     /* we checked the limit earlier */
845 #ifdef AFS_SGI64_ENV
846     uio->uio_pmp = NULL;
847 #endif
848
849     if (bp->b_flags & B_READ) {
850         uio->uio_fmode = FREAD;
851         error = afs_read(vp, uio, cr, 0, 0, 0);
852     } else {
853         uio->uio_fmode = FWRITE;
854         error = afs_write(vp, uio, 0, cr, 0);
855     }
856     crfree(cr);
857
858 #ifdef DEBUG
859     if (acchk && error) {
860         cmn_err(CE_WARN, "vp 0x%x has error %d\n", vp, error);
861         if (acdrop)
862             debug("AFS");
863     }
864 #endif
865     if (error) {
866         bp->b_error = error;
867         bp->b_flags |= B_ERROR;
868         if ((uio->uio_fmode == FWRITE) && !avc->vc_error)
869             avc->vc_error = error;
870     }
871     iodone(bp);
872     return;
873 }
874
875 /* ARGSUSED */
876 static int
877 afs_seek(OSI_VC_ARG(avc), ooff, noffp)
878 OSI_VC_DECL(avc);
879      off_t ooff;
880      off_t *noffp;
881 {
882     return *noffp < 0 ? EINVAL : 0;
883 }
884
885 #if !defined(AFS_SGI65_ENV)
886 /* Irix 6.5 uses addmap/delmap only for devices. */
887 /* ARGSUSED */
888 static int
889 afs_addmap(OSI_VC_ARG(avc), off, prp, addr, len, prot, maxprot, flags, cr)
890      off_t off;
891 OSI_VC_DECL(avc);
892      struct pregion *prp;
893      addr_t addr;
894      size_t len;
895      u_int prot, maxprot;
896      u_int flags;
897      struct cred *cr;
898 {
899     OSI_VC_CONVERT(avc);
900     struct vnode *vp = AFSTOV(avc);
901
902     if (vp->v_flag & VNOMAP)
903         return ENOSYS;
904     if (len == 0)
905         return 0;
906     AFS_RWLOCK(vp, VRWLOCK_WRITE);
907     if (avc->mapcnt == 0) {
908         /* on first mapping add a open reference */
909         ObtainWriteLock(&avc->lock, 237);
910         avc->execsOrWriters++;
911         avc->opens++;
912         ReleaseWriteLock(&avc->lock);
913     }
914     avc->mapcnt += btoc(len);
915     AFS_RWUNLOCK(vp, VRWLOCK_WRITE);
916     return 0;
917 }
918
919  /*ARGSUSED*/ static int
920 afs_delmap(OSI_VC_ARG(avc), off, prp, addr, len, prot, maxprot, flags, acred)
921      off_t off;
922 OSI_VC_DECL(avc);
923      struct pregion *prp;
924      addr_t addr;
925      size_t len;
926      u_int prot, maxprot;
927      u_int flags;
928      struct cred *acred;
929 {
930     OSI_VC_CONVERT(avc);
931     struct vnode *vp = AFSTOV(avc);
932     register struct brequest *tb;
933     struct vrequest treq;
934     afs_int32 code;
935
936     if (vp->v_flag & VNOMAP)
937         return ENOSYS;
938     if (len == 0)
939         return 0;
940     AFS_RWLOCK(vp, VRWLOCK_WRITE);
941     osi_Assert(avc->mapcnt > 0);
942     avc->mapcnt -= btoc(len);
943     osi_Assert(avc->mapcnt >= 0);
944     if (avc->mapcnt == 0) {
945         /* on last mapping push back and remove our reference */
946         osi_Assert(avc->execsOrWriters > 0);
947         osi_Assert(avc->opens > 0);
948         if (avc->f.m.LinkCount == 0) {
949             ObtainWriteLock(&avc->lock, 238);
950             AFS_GUNLOCK();
951             PTOSSVP(vp, (off_t) 0, (off_t) MAXLONG);
952             AFS_GLOCK();
953             ReleaseWriteLock(&avc->lock);
954         }
955         /*
956          * mimic afs_close
957          */
958         afs_InitReq(&treq, acred);
959         if (afs_BBusy()) {
960             /* do it yourself if daemons are all busy */
961             ObtainWriteLock(&avc->lock, 239);
962             code = afs_StoreOnLastReference(avc, &treq);
963             ReleaseWriteLock(&avc->lock);
964             /* BStore does CheckCode so we should also */
965             /* VNOVNODE is "acceptable" error code from close, since
966              * may happen when deleting a file on another machine while
967              * it is open here. */
968             if (code == VNOVNODE)
969                 code = 0;
970             if (code) {
971                 afs_StoreWarn(code, avc->f.fid.Fid.Volume,      /* /dev/console */
972                               1);
973             }
974             code = afs_CheckCode(code, &treq, 52);
975             AFS_RWUNLOCK(vp, VRWLOCK_WRITE);
976         } else {
977             AFS_RWUNLOCK(vp, VRWLOCK_WRITE);
978             /* at least one daemon is idle, so ask it to do the store.
979              * Also, note that  we don't lock it any more... */
980             tb = afs_BQueue(BOP_STORE, avc, 0, 1, acred,
981                             (afs_size_t) acred->cr_uid, 0L, (void *)0);
982             /* sleep waiting for the store to start, then retrieve error code */
983             while ((tb->flags & BUVALID) == 0) {
984                 tb->flags |= BUWAIT;
985                 afs_osi_Sleep(tb);
986             }
987             code = tb->code;
988             afs_BRelease(tb);
989         }
990     } else {
991         AFS_RWUNLOCK(vp, VRWLOCK_WRITE);
992     }
993     return 0;
994 }
995 #endif /* ! AFS_SGI65_ENV */
996
997
998 /* ARGSUSED */
999 /*
1000  * Note - if mapping in an ELF interpreter, one can get called without vp
1001  * ever having been 'opened'
1002  */
1003 #ifdef AFS_SGI65_ENV
1004 static int
1005 afs_map(OSI_VC_ARG(avc), off, len, prot, flags, cr, vpp)
1006      off_t off;
1007 OSI_VC_DECL(avc);
1008      size_t len;
1009      mprot_t prot;
1010      u_int flags;
1011      struct cred *cr;
1012      vnode_t **vpp;
1013 #else
1014 static int
1015 afs_map(OSI_VC_ARG(avc), off, prp, addrp, len, prot, maxprot, flags, cr)
1016      off_t off;
1017 OSI_VC_DECL(avc);
1018      struct pregion *prp;
1019      addr_t *addrp;
1020      size_t len;
1021      u_int prot, maxprot;
1022      u_int flags;
1023      struct cred *cr;
1024 #endif
1025 {
1026     OSI_VC_CONVERT(avc);
1027     struct vnode *vp = AFSTOV(avc);
1028     struct vrequest treq;
1029     int error;
1030
1031     /* get a validated vcache entry */
1032     afs_InitReq(&treq, cr);
1033     error = afs_VerifyVCache(avc, &treq);
1034     if (error)
1035         return afs_CheckCode(error, &treq, 53);
1036
1037     osi_FlushPages(avc, cr);    /* ensure old pages are gone */
1038 #ifdef AFS_SGI65_ENV
1039     /* If the vnode is currently opened for write, there's the potential
1040      * that this mapping might (now or in the future) have PROT_WRITE.
1041      * So assume it does and we'll have to call afs_StoreOnLastReference.
1042      */
1043     AFS_RWLOCK(vp, VRWLOCK_WRITE);
1044     ObtainWriteLock(&avc->lock, 501);
1045     if (avc->execsOrWriters > 0) {
1046         avc->execsOrWriters++;
1047         avc->opens++;
1048         avc->mapcnt++;          /* count eow's due to mappings. */
1049     }
1050     ReleaseWriteLock(&avc->lock);
1051     AFS_RWUNLOCK(vp, VRWLOCK_WRITE);
1052 #else
1053     AFS_RWLOCK(vp, VRWLOCK_WRITE);
1054     AFS_GUNLOCK();
1055     error =
1056         fs_map_subr(vp, (off_t) avc->f.m.Length, (u_int) avc->f.m.Mode, off, prp,
1057                     *addrp, len, prot, maxprot, flags, cr);
1058     AFS_GLOCK();
1059     AFS_RWUNLOCK(vp, VRWLOCK_WRITE);
1060 #endif /* AFS_SGI65_ENV */
1061     afs_Trace4(afs_iclSetp, CM_TRACE_GMAP, ICL_TYPE_POINTER, vp,
1062 #ifdef AFS_SGI65_ENV
1063                ICL_TYPE_POINTER, NULL,
1064 #else
1065                ICL_TYPE_POINTER, *addrp,
1066 #endif
1067                ICL_TYPE_INT32, len, ICL_TYPE_INT32, off);
1068     return error;
1069 }
1070
1071
1072 extern afs_rwlock_t afs_xvcache;
1073 extern afs_lock_t afs_xdcache;
1074 #ifdef AFS_SGI64_ENV
1075 int
1076 #else
1077 void
1078 #endif
1079 afs_xinactive(OSI_VC_ARG(avc), acred)
1080 OSI_VC_DECL(avc);
1081      struct ucred *acred;
1082 {
1083     int s;
1084     OSI_VC_CONVERT(avc);
1085     vnode_t *vp = (vnode_t *) avc;
1086     int mapcnt = avc->mapcnt;   /* We just clear off this many. */
1087
1088     AFS_STATCNT(afs_inactive);
1089
1090     s = VN_LOCK(vp);
1091     if (!(vp->v_flag & VINACT) || (vp->v_count > 0)) {
1092         /* inactive was already done, or someone did a VN_HOLD; just return */
1093         vp->v_flag &= ~VINACT;
1094         VN_UNLOCK(vp, s);
1095 #ifdef AFS_SGI64_ENV
1096         return VN_INACTIVE_CACHE;
1097 #else
1098         return;
1099 #endif
1100     }
1101     osi_Assert((vp->v_flag & VSHARE) == 0);
1102     vp->v_flag &= ~VINACT;
1103     /* Removed broadcast to waiters, since no one ever will. Only for vnodes
1104      * in common pool.
1105      */
1106     VN_UNLOCK(vp, s);
1107
1108 #ifdef AFS_SGI65_ENV
1109     /* In Irix 6.5, the last unmap of a dirty mmap'd file does not
1110      * get an explicit vnode op. Instead we only find out at VOP_INACTIVE.
1111      */
1112     if (!afs_rwlock_nowait((vnode_t *) avc, VRWLOCK_WRITE)) {
1113         return VN_INACTIVE_CACHE;
1114     }
1115     if (NBObtainWriteLock(&avc->lock, 502)) {
1116         AFS_RWUNLOCK(vp, VRWLOCK_WRITE);
1117         return VN_INACTIVE_CACHE;
1118     }
1119     if (avc->f.states & CUnlinked) {
1120         if (CheckLock(&afs_xvcache) || CheckLock(&afs_xdcache)) {
1121             avc->f.states |= CUnlinkedDel;
1122             ReleaseWriteLock(&avc->lock);
1123             AFS_RWUNLOCK(vp, VRWLOCK_WRITE);
1124         } else {
1125             ReleaseWriteLock(&avc->lock);
1126             AFS_RWUNLOCK(vp, VRWLOCK_WRITE);
1127             afs_remunlink(avc, 1);      /* ignore any return code */
1128         }
1129         return VN_INACTIVE_CACHE;
1130     }
1131     if ((avc->f.states & CDirty) || (avc->execsOrWriters > 0)) {
1132         /* File either already has dirty chunks (CDirty) or was mapped at 
1133          * time in its life with the potential for being written into. 
1134          * Note that afs_close defers storebacks if the vnode's ref count
1135          * if more than 1.
1136          */
1137         int code;
1138         struct vrequest treq;
1139         if (!afs_InitReq(&treq, acred)) {
1140             int s;
1141
1142             VN_HOLD(vp);
1143             avc->execsOrWriters -= mapcnt - 1;
1144             avc->opens -= mapcnt - 1;
1145             avc->mapcnt -= mapcnt;
1146             code = afs_StoreOnLastReference(avc, &treq);
1147             /* The following behavior mimics the behavior in afs_close. */
1148             if (code == VNOVNODE || code == ENOENT)
1149                 code = 0;
1150             if (code) {
1151                 if (mapcnt) {
1152                     cmn_err(CE_WARN,
1153                             "AFS: Failed to store FID (%x:%lu.%lu.%lu) in VOP_INACTIVE, error = %d\n",
1154                             (int)(avc->f.fid.Cell) & 0xffffffff,
1155                             avc->f.fid.Fid.Volume, avc->f.fid.Fid.Vnode,
1156                             avc->f.fid.Fid.Unique, code);
1157                 }
1158                 afs_InvalidateAllSegments(avc);
1159             }
1160             s = VN_LOCK(vp);
1161             vp->v_count--;
1162             code = (vp->v_count == 0);
1163             VN_UNLOCK(vp, s);
1164             /* If the vnode is now in use by someone else, return early. */
1165             if (!code) {
1166                 ReleaseWriteLock(&avc->lock);
1167                 AFS_RWUNLOCK(vp, VRWLOCK_WRITE);
1168                 return VN_INACTIVE_CACHE;
1169             }
1170         }
1171     }
1172 #endif
1173
1174     osi_Assert((avc->f.states & (CCore | CMAPPED)) == 0);
1175
1176     if (avc->cred) {
1177         crfree(avc->cred);
1178         avc->cred = NULL;
1179     }
1180     ReleaseWriteLock(&avc->lock);
1181     AFS_RWUNLOCK(vp, VRWLOCK_WRITE);
1182
1183     /*
1184      * If someone unlinked a file and this is the last hurrah -
1185      * nuke all the pages.
1186      */
1187     if (avc->f.m.LinkCount == 0) {
1188         AFS_GUNLOCK();
1189         PTOSSVP(vp, (off_t) 0, (off_t) MAXLONG);
1190         AFS_GLOCK();
1191     }
1192 #ifndef AFS_SGI65_ENV
1193     osi_Assert(avc->mapcnt == 0);
1194     afs_chkpgoob(&avc->v, btoc(avc->f.m.Length));
1195
1196     avc->f.states &= ~CDirty;   /* Give up on store-backs */
1197     if (avc->f.states & CUnlinked) {
1198         if (CheckLock(&afs_xvcache) || CheckLock(&afs_xdcache)) {
1199             avc->f.states |= CUnlinkedDel;
1200         } else {
1201             afs_remunlink(avc, 1);      /* ignore any return code */
1202         }
1203     }
1204 #endif
1205 #ifdef AFS_SGI64_ENV
1206     return VN_INACTIVE_CACHE;
1207 #endif
1208 }
1209
1210 static int
1211 afs_reclaim(OSI_VC_DECL(avc), int flag)
1212 {
1213 #ifdef AFS_SGI64_ENV
1214     /* Get's called via VOP_RELCAIM in afs_FlushVCache to clear repl_vnodeops */
1215     return 0;
1216 #else
1217     panic("afs_reclaim");
1218 #endif
1219 }
1220
1221 void
1222 afs_rwlock(OSI_VN_DECL(vp), AFS_RWLOCK_T flag)
1223 {
1224     OSI_VN_CONVERT(vp);
1225     struct vcache *avc = VTOAFS(vp);
1226
1227     if (OSI_GET_LOCKID() == avc->vc_rwlockid) {
1228         avc->vc_locktrips++;
1229         return;
1230     }
1231     AFS_GUNLOCK();
1232     psema(&avc->vc_rwlock, PINOD);
1233     AFS_GLOCK();
1234     avc->vc_rwlockid = OSI_GET_LOCKID();
1235 }
1236
1237 void
1238 afs_rwunlock(OSI_VN_DECL(vp), AFS_RWLOCK_T flag)
1239 {
1240     OSI_VN_CONVERT(vp);
1241     struct vcache *avc = VTOAFS(vp);
1242
1243     AFS_ASSERT_GLOCK();
1244     osi_Assert(OSI_GET_LOCKID() == avc->vc_rwlockid);
1245     if (avc->vc_locktrips > 0) {
1246         --avc->vc_locktrips;
1247         return;
1248     }
1249     avc->vc_rwlockid = OSI_NO_LOCKID;
1250     vsema(&avc->vc_rwlock);
1251 }
1252
1253
1254 /* The flag argument is for symmetry with the afs_rwlock and afs_rwunlock
1255  * calls. SGI currently only uses the flag to assert if the unlock flag
1256  * does not match the corresponding lock flag. But they may start using this
1257  * flag for a real rw lock at some time.
1258  */
1259 int
1260 afs_rwlock_nowait(vnode_t * vp, AFS_RWLOCK_T flag)
1261 {
1262     struct vcache *avc = VTOAFS(vp);
1263
1264     AFS_ASSERT_GLOCK();
1265     if (OSI_GET_LOCKID() == avc->vc_rwlockid) {
1266         avc->vc_locktrips++;
1267         return 1;
1268     }
1269     if (cpsema(&avc->vc_rwlock)) {
1270         avc->vc_rwlockid = OSI_GET_LOCKID();
1271         return 1;
1272     }
1273     return 0;
1274 }
1275
1276 #if defined(AFS_SGI64_ENV) && defined(CKPT) && !defined(_R5000_CVT_WAR)
1277 int
1278 afs_fid2(OSI_VC_DECL(avc), struct fid *fidp)
1279 {
1280     struct cell *tcell;
1281     afs_fid2_t *afid = (afs_fid2_t *) fidp;
1282     OSI_VC_CONVERT(avc);
1283
1284     osi_Assert(sizeof(fid_t) >= sizeof(afs_fid2_t));
1285     afid->af_len = sizeof(afs_fid2_t) - sizeof(afid->af_len);
1286
1287     tcell = afs_GetCell(avc->f.fid.Cell, READ_LOCK);
1288     afid->af_cell = tcell->cellIndex & 0xffff;
1289     afs_PutCell(tcell, READ_LOCK);
1290
1291     afid->af_volid = avc->f.fid.Fid.Volume;
1292     afid->af_vno = avc->f.fid.Fid.Vnode;
1293     afid->af_uniq = avc->f.fid.Fid.Unique;
1294
1295     return 0;
1296 }
1297 #else
1298 /* Only use so far is in checkpoint/restart for IRIX 6.4. In ckpt_fid, a
1299  * return of ENOSYS would make the code fail over to VOP_FID. We can't let
1300  * that happen, since we do a VN_HOLD there in the expectation that 
1301  * posthandle will be called to release the vnode.
1302  *
1303  * afs_fid2 is used to support the R5000 workarounds (_R5000_CVT_WAR)
1304  */
1305 int
1306 afs_fid2(OSI_VC_DECL(avc), struct fid *fidp)
1307 {
1308 #if defined(_R5000_CVT_WAR)
1309     extern int R5000_cvt_war;
1310
1311     if (R5000_cvt_war)
1312         return ENOSYS;
1313     else
1314         return EINVAL;
1315 #else
1316     return EINVAL;
1317 #endif
1318 }
1319 #endif /* AFS_SGI64_ENV && CKPT */
1320
1321
1322 /*
1323  * check for any pages hashed that shouldn't be!
1324  * Only valid if PGCACHEDEBUG is set in os/page.c
1325  * Drop the global lock here, since we may not actually do the call.
1326  */
1327 void
1328 afs_chkpgoob(vnode_t * vp, pgno_t pgno)
1329 {
1330 #undef PGDEBUG
1331 #ifdef PGDEBUG
1332     AFS_GUNLOCK();
1333     pfindanyoob(vp, pgno);
1334     AFS_GLOCK();
1335 #endif
1336 }
1337
1338
1339 #ifdef MP
1340
1341 #ifdef AFS_SGI64_ENV
1342 #define AFS_MP_VC_ARG(A) bhv_desc_t A
1343 #else
1344 #define AFS_MP_VC_ARG(A) vnode_t A
1345 #endif
1346
1347 #ifdef AFS_SGI64_ENV
1348 int
1349 mp_afs_open(bhv_desc_t * bhp, vnode_t ** a, mode_t b, struct cred *c)
1350 #else
1351 int
1352 mp_afs_open(vnode_t ** a, mode_t b, struct cred *c)
1353 #endif
1354 {
1355     int rv;
1356     AFS_GLOCK();
1357 #ifdef AFS_SGI64_ENV
1358     rv = afs_lockedvnodeops.vop_open(bhp, a, b, c);
1359 #else
1360     rv = afs_lockedvnodeops.vop_open(a, b, c);
1361 #endif
1362     AFS_GUNLOCK();
1363     return rv;
1364 }
1365
1366 #if defined(AFS_SGI64_ENV)
1367 #if defined(AFS_SGI65_ENV)
1368 int
1369 mp_afs_close(AFS_MP_VC_ARG(*a), int b, lastclose_t c, struct cred *d)
1370 #else
1371 int
1372 mp_afs_close(AFS_MP_VC_ARG(*a), int b, lastclose_t c, off_t d, struct cred *e,
1373              struct flid *f)
1374 #endif
1375 #else
1376 int
1377 mp_afs_close(AFS_MP_VC_ARG(*a), int b, lastclose_t c, off_t d, struct cred *e)
1378 #endif
1379 {
1380     int rv;
1381     AFS_GLOCK();
1382     rv = afs_lockedvnodeops.vop_close(a, b, c, d
1383 #if !defined(AFS_SGI65_ENV)
1384                                       , e
1385 #if defined(AFS_SGI64_ENV)
1386                                       , f
1387 #endif
1388 #endif
1389         );
1390
1391     AFS_GUNLOCK();
1392     return rv;
1393 }
1394
1395 #ifdef AFS_SGI64_ENV
1396 int
1397 mp_afs_read(AFS_MP_VC_ARG(*a), struct uio *b, int c, struct cred *d,
1398             struct flid *f)
1399 #else
1400 int
1401 mp_afs_read(AFS_MP_VC_ARG(*a), struct uio *b, int c, struct cred *d)
1402 #endif
1403 {
1404     int rv;
1405     AFS_GLOCK();
1406 #ifdef AFS_SGI64_ENV
1407     rv = afs_lockedvnodeops.vop_read(a, b, c, d, f);
1408 #else
1409     rv = afs_lockedvnodeops.vop_read(a, b, c, d);
1410 #endif
1411     AFS_GUNLOCK();
1412     return rv;
1413 }
1414
1415
1416 #ifdef AFS_SGI64_ENV
1417 int
1418 mp_afs_write(AFS_MP_VC_ARG(*a), struct uio *b, int c, struct cred *d,
1419              struct flid *f)
1420 #else
1421 int
1422 mp_afs_write(AFS_MP_VC_ARG(*a), struct uio *b, int c, struct cred *d)
1423 #endif
1424 {
1425     int rv;
1426     AFS_GLOCK();
1427 #ifdef AFS_SGI64_ENV
1428     rv = afs_lockedvnodeops.vop_write(a, b, c, d, f);
1429 #else
1430     rv = afs_lockedvnodeops.vop_write(a, b, c, d);
1431 #endif
1432     AFS_GUNLOCK();
1433     return rv;
1434 }
1435
1436 int
1437 mp_afs_ioctl(AFS_MP_VC_ARG(*a), int b, void *c, int d, struct cred *e, int *f
1438 #ifdef AFS_SGI65_ENV
1439              , struct vopbd *vbds
1440 #endif
1441     )
1442 {
1443     int rv;
1444     AFS_GLOCK();
1445     rv = afs_lockedvnodeops.vop_ioctl(a, b, c, d, e, f
1446 #ifdef AFS_SGI65_ENV
1447                                       , vbds
1448 #endif
1449         );
1450     AFS_GUNLOCK();
1451     return rv;
1452 }
1453
1454 int
1455 mp_fs_setfl(AFS_MP_VC_ARG(*a), int b, int c, struct cred *d)
1456 {
1457     int rv;
1458     AFS_GLOCK();
1459     rv = afs_lockedvnodeops.vop_setfl(a, b, c, d);
1460     AFS_GUNLOCK();
1461     return rv;
1462 }
1463
1464 int
1465 mp_afs_getattr(AFS_MP_VC_ARG(*a), struct vattr *b, int c, struct cred *d)
1466 {
1467     int rv;
1468     AFS_GLOCK();
1469     rv = afs_lockedvnodeops.vop_getattr(a, b, c, d);
1470     AFS_GUNLOCK();
1471     return rv;
1472 }
1473
1474 int
1475 mp_afs_setattr(AFS_MP_VC_ARG(*a), struct vattr *b, int c, struct cred *d)
1476 {
1477     int rv;
1478     AFS_GLOCK();
1479     rv = afs_lockedvnodeops.vop_setattr(a, b, c, d);
1480     AFS_GUNLOCK();
1481     return rv;
1482 }
1483
1484 int
1485 mp_afs_access(AFS_MP_VC_ARG(*a), int b,
1486 #ifndef AFS_SGI65_ENV
1487               int c,
1488 #endif
1489               struct cred *d)
1490 {
1491     int rv;
1492     AFS_GLOCK();
1493     rv = afs_lockedvnodeops.vop_access(a, b,
1494 #ifndef AFS_SGI65_ENV
1495                                        c,
1496 #endif
1497                                        d);
1498     AFS_GUNLOCK();
1499     return rv;
1500 }
1501
1502 int
1503 mp_afs_lookup(AFS_MP_VC_ARG(*a), char *b, vnode_t ** c, struct pathname *d,
1504               int e, vnode_t * f, struct cred *g)
1505 {
1506     int rv;
1507     AFS_GLOCK();
1508     rv = afs_lockedvnodeops.vop_lookup(a, b, c, d, e, f, g);
1509     AFS_GUNLOCK();
1510     return rv;
1511 }
1512
1513 #ifdef AFS_SGI64_ENV
1514 int
1515 mp_afs_create(AFS_MP_VC_ARG(*a), char *b, struct vattr *c, int d, int e,
1516               vnode_t ** f, struct cred *g)
1517 #else
1518 int
1519 mp_afs_create(AFS_MP_VC_ARG(*a), char *b, struct vattr *c, enum vcexcl d,
1520               int e, vnode_t ** f, struct cred *g)
1521 #endif
1522 {
1523     int rv;
1524     AFS_GLOCK();
1525     rv = afs_lockedvnodeops.vop_create(a, b, c, d, e, f, g);
1526     AFS_GUNLOCK();
1527     return rv;
1528 }
1529
1530 int
1531 mp_afs_remove(AFS_MP_VC_ARG(*a), char *b, struct cred *c)
1532 {
1533     int rv;
1534     AFS_GLOCK();
1535     rv = afs_lockedvnodeops.vop_remove(a, b, c);
1536     AFS_GUNLOCK();
1537     return rv;
1538 }
1539
1540 int
1541 mp_afs_link(AFS_MP_VC_ARG(*a), vnode_t * b, char *c, struct cred *d)
1542 {
1543     int rv;
1544     AFS_GLOCK();
1545     rv = afs_lockedvnodeops.vop_link(a, b, c, d);
1546     AFS_GUNLOCK();
1547     return rv;
1548 }
1549
1550 int
1551 mp_afs_rename(AFS_MP_VC_ARG(*a), char *b, vnode_t * c, char *d,
1552               struct pathname *e, struct cred *f)
1553 {
1554     int rv;
1555     AFS_GLOCK();
1556     rv = afs_lockedvnodeops.vop_rename(a, b, c, d, e, f);
1557     AFS_GUNLOCK();
1558     return rv;
1559 }
1560
1561 int
1562 mp_afs_mkdir(AFS_MP_VC_ARG(*a), char *b, struct vattr *c, vnode_t ** d,
1563              struct cred *e)
1564 {
1565     int rv;
1566     AFS_GLOCK();
1567     rv = afs_lockedvnodeops.vop_mkdir(a, b, c, d, e);
1568     AFS_GUNLOCK();
1569     return rv;
1570 }
1571
1572 int
1573 mp_afs_rmdir(AFS_MP_VC_ARG(*a), char *b, vnode_t * c, struct cred *d)
1574 {
1575     int rv;
1576     AFS_GLOCK();
1577     rv = afs_lockedvnodeops.vop_rmdir(a, b, c, d);
1578     AFS_GUNLOCK();
1579     return rv;
1580 }
1581
1582 int
1583 mp_afs_readdir(AFS_MP_VC_ARG(*a), struct uio *b, struct cred *c, int *d)
1584 {
1585     int rv;
1586     AFS_GLOCK();
1587     rv = afs_lockedvnodeops.vop_readdir(a, b, c, d);
1588     AFS_GUNLOCK();
1589     return rv;
1590 }
1591
1592 int
1593 mp_afs_symlink(AFS_MP_VC_ARG(*a), char *b, struct vattr *c, char *d,
1594                struct cred *e)
1595 {
1596     int rv;
1597     AFS_GLOCK();
1598     rv = afs_lockedvnodeops.vop_symlink(a, b, c, d, e);
1599     AFS_GUNLOCK();
1600     return rv;
1601 }
1602
1603 int
1604 mp_afs_readlink(AFS_MP_VC_ARG(*a), struct uio *b, struct cred *c)
1605 {
1606     int rv;
1607     AFS_GLOCK();
1608     rv = afs_lockedvnodeops.vop_readlink(a, b, c);
1609     AFS_GUNLOCK();
1610     return rv;
1611 }
1612
1613 int
1614 mp_afs_fsync(AFS_MP_VC_ARG(*a), int b, struct cred *c
1615 #ifdef AFS_SGI65_ENV
1616              , off_t start, off_t stop
1617 #endif
1618     )
1619 {
1620     int rv;
1621     AFS_GLOCK();
1622     rv = afs_lockedvnodeops.vop_fsync(a, b, c
1623 #ifdef AFS_SGI65_ENV
1624                                       , start, stop
1625 #endif
1626         );
1627     AFS_GUNLOCK();
1628     return rv;
1629 }
1630
1631 void
1632 mp_afs_inactive(AFS_MP_VC_ARG(*a), struct cred *b)
1633 {
1634     AFS_GLOCK();
1635     afs_lockedvnodeops.vop_inactive(a, b);
1636     AFS_GUNLOCK();
1637     return;
1638 }
1639
1640 int
1641 mp_afs_fid(AFS_MP_VC_ARG(*a), struct fid **b)
1642 {
1643     int rv;
1644     AFS_GLOCK();
1645     rv = afs_lockedvnodeops.vop_fid(a, b);
1646     AFS_GUNLOCK();
1647     return rv;
1648 }
1649
1650 int
1651 mp_afs_fid2(AFS_MP_VC_ARG(*a), struct fid *b)
1652 {
1653     int rv;
1654     AFS_GLOCK();
1655     rv = afs_lockedvnodeops.vop_fid2(a, b);
1656     AFS_GUNLOCK();
1657     return rv;
1658 }
1659
1660 void
1661 mp_afs_rwlock(AFS_MP_VC_ARG(*a), AFS_RWLOCK_T b)
1662 {
1663     AFS_GLOCK();
1664     afs_rwlock(a, VRWLOCK_WRITE);
1665     AFS_GUNLOCK();
1666 }
1667
1668 void
1669 mp_afs_rwunlock(AFS_MP_VC_ARG(*a), AFS_RWLOCK_T b)
1670 {
1671     AFS_GLOCK();
1672     afs_rwunlock(a, VRWLOCK_WRITE);
1673     AFS_GUNLOCK();
1674 }
1675
1676 int
1677 mp_afs_seek(AFS_MP_VC_ARG(*a), off_t b, off_t * c)
1678 {
1679     int rv;
1680     AFS_GLOCK();
1681     rv = afs_lockedvnodeops.vop_seek(a, b, c);
1682     AFS_GUNLOCK();
1683     return rv;
1684 }
1685
1686 int
1687 mp_fs_cmp(AFS_MP_VC_ARG(*a), vnode_t * b)
1688 {
1689     int rv;
1690     AFS_GLOCK();
1691     rv = afs_lockedvnodeops.vop_cmp(a, b);
1692     AFS_GUNLOCK();
1693     return rv;
1694 }
1695
1696 int
1697 mp_afs_frlock(AFS_MP_VC_ARG(*a), int b, struct flock *c, int d, off_t e,
1698 #ifdef AFS_SGI65_ENV
1699               vrwlock_t vrwlock,
1700 #endif
1701               struct cred *f)
1702 {
1703     int rv;
1704     AFS_GLOCK();
1705     rv = afs_lockedvnodeops.vop_frlock(a, b, c, d, e,
1706 #ifdef AFS_SGI65_ENV
1707                                        vrwlock,
1708 #endif
1709                                        f);
1710     AFS_GUNLOCK();
1711     return rv;
1712 }
1713
1714 int
1715 mp_afs_realvp(AFS_MP_VC_ARG(*a), vnode_t ** b)
1716 {
1717     int rv;
1718     AFS_GLOCK();
1719     rv = afs_lockedvnodeops.vop_realvp(a, b);
1720     AFS_GUNLOCK();
1721     return rv;
1722 }
1723
1724 int
1725 mp_afs_bmap(AFS_MP_VC_ARG(*a), off_t b, ssize_t c, int d, struct cred *e,
1726             struct bmapval *f, int *g)
1727 {
1728     int rv;
1729     AFS_GLOCK();
1730     rv = afs_lockedvnodeops.vop_bmap(a, b, c, d, e, f, g);
1731     AFS_GUNLOCK();
1732     return rv;
1733 }
1734
1735 void
1736 mp_afs_strategy(AFS_MP_VC_ARG(*a), struct buf *b)
1737 {
1738     int rv;
1739     AFS_GLOCK();
1740     afs_lockedvnodeops.vop_strategy(a, b);
1741     AFS_GUNLOCK();
1742     return;
1743 }
1744
1745 #ifdef AFS_SGI65_ENV
1746 int
1747 mp_afs_map(AFS_MP_VC_ARG(*a), off_t b, size_t c, mprot_t d, u_int e,
1748            struct cred *f, vnode_t ** g)
1749 #else
1750 int
1751 mp_afs_map(AFS_MP_VC_ARG(*a), off_t b, struct pregion *c, char **d, size_t e,
1752            u_int f, u_int g, u_int h, struct cred *i)
1753 #endif
1754 {
1755     int rv;
1756     AFS_GLOCK();
1757     rv = afs_lockedvnodeops.vop_map(a, b, c, d, e, f, g
1758 #ifndef AFS_SGI65_ENV
1759                                     , h, i
1760 #endif
1761         );
1762     AFS_GUNLOCK();
1763     return rv;
1764 }
1765
1766
1767 #ifndef AFS_SGI65_ENV
1768 /* As of Irix 6.5, addmap and delmap are only for devices */
1769 int
1770 mp_afs_addmap(AFS_MP_VC_ARG(*a), off_t b, struct pregion *c, addr_t d,
1771               size_t e, u_int f, u_int g, u_int h, struct cred *i)
1772 {
1773     int rv;
1774     AFS_GLOCK();
1775     rv = afs_lockedvnodeops.vop_addmap(a, b, c, d, e, f, g, h, i);
1776     AFS_GUNLOCK();
1777     return rv;
1778 }
1779
1780 int
1781 mp_afs_delmap(AFS_MP_VC_ARG(*a), off_t b, struct pregion *c, addr_t d,
1782               size_t e, u_int f, u_int g, u_int h, struct cred *i)
1783 {
1784     int rv;
1785     AFS_GLOCK();
1786     rv = afs_lockedvnodeops.vop_delmap(a, b, c, d, e, f, g, h, i);
1787     AFS_GUNLOCK();
1788     return rv;
1789 }
1790 #endif /* ! AFS_SGI65_ENV */
1791
1792 int
1793 mp_fs_poll(AFS_MP_VC_ARG(*a), short b, int c, short *d, struct pollhead **e
1794 #ifdef AFS_SGI65_ENV
1795            , unsigned int *f
1796 #endif
1797     )
1798 {
1799     int rv;
1800     AFS_GLOCK();
1801     rv = afs_lockedvnodeops.vop_poll(a, b, c, d, e
1802 #ifdef AFS_SGI65_ENV
1803                                      , f
1804 #endif
1805         );
1806     AFS_GUNLOCK();
1807     return rv;
1808 }
1809
1810
1811 struct vnodeops Afs_vnodeops = {
1812 #ifdef AFS_SGI64_ENV
1813 #ifdef AFS_SGI65_ENV
1814     BHV_IDENTITY_INIT_POSITION(VNODE_POSITION_BASE),
1815 #else
1816     VNODE_POSITION_BASE,
1817 #endif
1818 #endif
1819     mp_afs_open,
1820     mp_afs_close,
1821     mp_afs_read,
1822     mp_afs_write,
1823     mp_afs_ioctl,
1824     mp_fs_setfl,
1825     mp_afs_getattr,
1826     mp_afs_setattr,
1827     mp_afs_access,
1828     mp_afs_lookup,
1829     mp_afs_create,
1830     mp_afs_remove,
1831     mp_afs_link,
1832     mp_afs_rename,
1833     mp_afs_mkdir,
1834     mp_afs_rmdir,
1835     mp_afs_readdir,
1836     mp_afs_symlink,
1837     mp_afs_readlink,
1838     mp_afs_fsync,
1839     mp_afs_inactive,
1840     mp_afs_fid,
1841     mp_afs_fid2,
1842     mp_afs_rwlock,
1843     mp_afs_rwunlock,
1844     mp_afs_seek,
1845     mp_fs_cmp,
1846     mp_afs_frlock,
1847     fs_nosys,                   /* realvp */
1848     mp_afs_bmap,
1849     mp_afs_strategy,
1850     mp_afs_map,
1851 #ifdef AFS_SGI65_ENV
1852     fs_noerr,                   /* addmap - devices only */
1853     fs_noerr,                   /* delmap - devices only */
1854 #else
1855     mp_afs_addmap,
1856     mp_afs_delmap,
1857 #endif
1858     mp_fs_poll,                 /* poll */
1859     fs_nosys,                   /* dump */
1860     fs_pathconf,
1861     fs_nosys,                   /* allocstore */
1862     fs_nosys,                   /* fcntl */
1863     afs_reclaim,                /* reclaim */
1864     fs_nosys,                   /* attr_get */
1865     fs_nosys,                   /* attr_set */
1866     fs_nosys,                   /* attr_remove */
1867     fs_nosys,                   /* attr_list */
1868 #ifdef AFS_SGI64_ENV
1869 #ifdef AFS_SGI65_ENV
1870     fs_cover,
1871     (vop_link_removed_t) fs_noval,
1872     fs_vnode_change,
1873     fs_tosspages,
1874     fs_flushinval_pages,
1875     fs_flush_pages,
1876     fs_invalfree_pages,
1877     fs_pages_sethole,
1878     (vop_commit_t) fs_nosys,
1879     (vop_readbuf_t) fs_nosys,
1880     fs_strgetmsg,
1881     fs_strputmsg,
1882 #else
1883     fs_mount,
1884 #endif
1885 #endif
1886 };
1887 struct vnodeops *afs_ops = &Afs_vnodeops;
1888 #endif /* MP */
1889
1890
1891 #if defined(AFS_SGI62_ENV) && defined(AFS_SGI_DUAL_FS_CACHE)
1892 /* Support for EFS and XFS caches. The assumption here is that the size of
1893  * a cache file also does not exceed 32 bits. 
1894  */
1895
1896 /* Initialized in osi_InitCacheFSType(). Used to determine inode type. */
1897 int afs_CacheFSType = -1;
1898 vnodeops_t *afs_efs_vnodeopsp;
1899 vnodeops_t *afs_xfs_vnodeopsp;
1900 vnode_t *(*afs_IGetVnode) (ino_t);
1901
1902 extern vnode_t *afs_EFSIGetVnode(ino_t);        /* defined in osi_file.c */
1903 extern vnode_t *afs_XFSIGetVnode(ino_t);        /* defined in osi_file.c */
1904
1905 extern afs_lock_t afs_xosi;     /* lock is for tvattr */
1906
1907 /* Initialize the cache operations. Called while initializing cache files. */
1908 void
1909 afs_InitDualFSCacheOps(struct vnode *vp)
1910 {
1911     static int inited = 0;
1912     struct vfssw *swp;
1913     int found = 0;
1914
1915     if (inited)
1916         return;
1917     inited = 1;
1918
1919     swp = vfs_getvfssw("xfs");
1920     if (swp) {
1921         afs_xfs_vnodeopsp = swp->vsw_vnodeops;
1922         if (!found) {
1923             if (vp && vp->v_op == afs_xfs_vnodeopsp) {
1924                 afs_CacheFSType = AFS_SGI_XFS_CACHE;
1925                 afs_IGetVnode = afs_XFSIGetVnode;
1926                 found = 1;
1927             }
1928         }
1929     }
1930
1931     if (vp && !found)
1932         osi_Panic("osi_InitCacheFSType: Can't find fstype for vnode 0x%llx\n",
1933                   vp);
1934 }
1935
1936 ino_t
1937 VnodeToIno(vnode_t * vp)
1938 {
1939     int code;
1940     struct vattr vattr;
1941
1942     MObtainWriteLock(&afs_xosi, 579);
1943     vattr.va_mask = AT_FSID | AT_NODEID;        /* quick return using this mask. */
1944     AFS_GUNLOCK();
1945     AFS_VOP_GETATTR(vp, &vattr, 0, OSI_GET_CURRENT_CRED(), code);
1946     AFS_GLOCK();
1947     if (code) {
1948         osi_Panic("VnodeToIno");
1949     }
1950     MReleaseWriteLock(&afs_xosi);
1951     return vattr.va_nodeid;
1952 }
1953
1954 dev_t
1955 VnodeToDev(vnode_t * vp)
1956 {
1957     int code;
1958     struct vattr vattr;
1959
1960     MObtainWriteLock(&afs_xosi, 580);
1961     vattr.va_mask = AT_FSID | AT_NODEID;        /* quick return using this mask. */
1962     AFS_GUNLOCK();
1963     AFS_VOP_GETATTR(vp, &vattr, 0, OSI_GET_CURRENT_CRED(), code);
1964     AFS_GLOCK();
1965     if (code) {
1966         osi_Panic("VnodeToDev");
1967     }
1968     MReleaseWriteLock(&afs_xosi);
1969     return (dev_t) vattr.va_fsid;
1970 }
1971
1972 off_t
1973 VnodeToSize(vnode_t * vp)
1974 {
1975     int code;
1976     struct vattr vattr;
1977
1978     MObtainWriteLock(&afs_xosi, 581);
1979     vattr.va_mask = AT_SIZE;
1980     AFS_GUNLOCK();
1981     AFS_VOP_GETATTR(vp, &vattr, 0, OSI_GET_CURRENT_CRED(), code);
1982     AFS_GLOCK();
1983     if (code) {
1984         osi_Panic("VnodeToSize");
1985     }
1986     MReleaseWriteLock(&afs_xosi);
1987     return vattr.va_size;
1988 }
1989 #endif /* 6.2 and dual fs cache */
1990 #endif /* AFS_SGI62_ENV */