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