afs: Return raw code from background daemons
[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);
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             afs_BRelease(tb);
987         }
988     } else {
989         AFS_RWUNLOCK(vp, VRWLOCK_WRITE);
990     }
991     return 0;
992 }
993 #endif /* ! AFS_SGI65_ENV */
994
995
996 /* ARGSUSED */
997 /*
998  * Note - if mapping in an ELF interpreter, one can get called without vp
999  * ever having been 'opened'
1000  */
1001 #ifdef AFS_SGI65_ENV
1002 static int
1003 afs_map(OSI_VC_ARG(avc), off, len, prot, flags, cr, vpp)
1004      off_t off;
1005 OSI_VC_DECL(avc);
1006      size_t len;
1007      mprot_t prot;
1008      u_int flags;
1009      struct cred *cr;
1010      vnode_t **vpp;
1011 #else
1012 static int
1013 afs_map(OSI_VC_ARG(avc), off, prp, addrp, len, prot, maxprot, flags, cr)
1014      off_t off;
1015 OSI_VC_DECL(avc);
1016      struct pregion *prp;
1017      addr_t *addrp;
1018      size_t len;
1019      u_int prot, maxprot;
1020      u_int flags;
1021      struct cred *cr;
1022 #endif
1023 {
1024     OSI_VC_CONVERT(avc);
1025     struct vnode *vp = AFSTOV(avc);
1026     struct vrequest treq;
1027     int error;
1028
1029     /* get a validated vcache entry */
1030     afs_InitReq(&treq, cr);
1031     error = afs_VerifyVCache(avc, &treq);
1032     if (error)
1033         return afs_CheckCode(error, &treq, 53);
1034
1035     osi_FlushPages(avc, cr);    /* ensure old pages are gone */
1036 #ifdef AFS_SGI65_ENV
1037     /* If the vnode is currently opened for write, there's the potential
1038      * that this mapping might (now or in the future) have PROT_WRITE.
1039      * So assume it does and we'll have to call afs_StoreOnLastReference.
1040      */
1041     AFS_RWLOCK(vp, VRWLOCK_WRITE);
1042     ObtainWriteLock(&avc->lock, 501);
1043     if (avc->execsOrWriters > 0) {
1044         avc->execsOrWriters++;
1045         avc->opens++;
1046         avc->mapcnt++;          /* count eow's due to mappings. */
1047     }
1048     ReleaseWriteLock(&avc->lock);
1049     AFS_RWUNLOCK(vp, VRWLOCK_WRITE);
1050 #else
1051     AFS_RWLOCK(vp, VRWLOCK_WRITE);
1052     AFS_GUNLOCK();
1053     error =
1054         fs_map_subr(vp, (off_t) avc->f.m.Length, (u_int) avc->f.m.Mode, off, prp,
1055                     *addrp, len, prot, maxprot, flags, cr);
1056     AFS_GLOCK();
1057     AFS_RWUNLOCK(vp, VRWLOCK_WRITE);
1058 #endif /* AFS_SGI65_ENV */
1059     afs_Trace4(afs_iclSetp, CM_TRACE_GMAP, ICL_TYPE_POINTER, vp,
1060 #ifdef AFS_SGI65_ENV
1061                ICL_TYPE_POINTER, NULL,
1062 #else
1063                ICL_TYPE_POINTER, *addrp,
1064 #endif
1065                ICL_TYPE_INT32, len, ICL_TYPE_INT32, off);
1066     return error;
1067 }
1068
1069
1070 extern afs_rwlock_t afs_xvcache;
1071 extern afs_lock_t afs_xdcache;
1072 #ifdef AFS_SGI64_ENV
1073 int
1074 #else
1075 void
1076 #endif
1077 afs_xinactive(OSI_VC_ARG(avc), acred)
1078 OSI_VC_DECL(avc);
1079      struct ucred *acred;
1080 {
1081     int s;
1082     OSI_VC_CONVERT(avc);
1083     vnode_t *vp = (vnode_t *) avc;
1084     int mapcnt = avc->mapcnt;   /* We just clear off this many. */
1085
1086     AFS_STATCNT(afs_inactive);
1087
1088     s = VN_LOCK(vp);
1089     if (!(vp->v_flag & VINACT) || (vp->v_count > 0)) {
1090         /* inactive was already done, or someone did a VN_HOLD; just return */
1091         vp->v_flag &= ~VINACT;
1092         VN_UNLOCK(vp, s);
1093 #ifdef AFS_SGI64_ENV
1094         return VN_INACTIVE_CACHE;
1095 #else
1096         return;
1097 #endif
1098     }
1099     osi_Assert((vp->v_flag & VSHARE) == 0);
1100     vp->v_flag &= ~VINACT;
1101     /* Removed broadcast to waiters, since no one ever will. Only for vnodes
1102      * in common pool.
1103      */
1104     VN_UNLOCK(vp, s);
1105
1106 #ifdef AFS_SGI65_ENV
1107     /* In Irix 6.5, the last unmap of a dirty mmap'd file does not
1108      * get an explicit vnode op. Instead we only find out at VOP_INACTIVE.
1109      */
1110     if (!afs_rwlock_nowait((vnode_t *) avc, VRWLOCK_WRITE)) {
1111         return VN_INACTIVE_CACHE;
1112     }
1113     if (NBObtainWriteLock(&avc->lock, 502)) {
1114         AFS_RWUNLOCK(vp, VRWLOCK_WRITE);
1115         return VN_INACTIVE_CACHE;
1116     }
1117     if (avc->f.states & CUnlinked) {
1118         if (CheckLock(&afs_xvcache) || CheckLock(&afs_xdcache)) {
1119             avc->f.states |= CUnlinkedDel;
1120             ReleaseWriteLock(&avc->lock);
1121             AFS_RWUNLOCK(vp, VRWLOCK_WRITE);
1122         } else {
1123             ReleaseWriteLock(&avc->lock);
1124             AFS_RWUNLOCK(vp, VRWLOCK_WRITE);
1125             afs_remunlink(avc, 1);      /* ignore any return code */
1126         }
1127         return VN_INACTIVE_CACHE;
1128     }
1129     if ((avc->f.states & CDirty) || (avc->execsOrWriters > 0)) {
1130         /* File either already has dirty chunks (CDirty) or was mapped at 
1131          * time in its life with the potential for being written into. 
1132          * Note that afs_close defers storebacks if the vnode's ref count
1133          * if more than 1.
1134          */
1135         int code;
1136         struct vrequest treq;
1137         if (!afs_InitReq(&treq, acred)) {
1138             int s;
1139
1140             VN_HOLD(vp);
1141             avc->execsOrWriters -= mapcnt - 1;
1142             avc->opens -= mapcnt - 1;
1143             avc->mapcnt -= mapcnt;
1144             code = afs_StoreOnLastReference(avc, &treq);
1145             /* The following behavior mimics the behavior in afs_close. */
1146             if (code == VNOVNODE || code == ENOENT)
1147                 code = 0;
1148             if (code) {
1149                 if (mapcnt) {
1150                     cmn_err(CE_WARN,
1151                             "AFS: Failed to store FID (%x:%lu.%lu.%lu) in VOP_INACTIVE, error = %d\n",
1152                             (int)(avc->f.fid.Cell) & 0xffffffff,
1153                             avc->f.fid.Fid.Volume, avc->f.fid.Fid.Vnode,
1154                             avc->f.fid.Fid.Unique, code);
1155                 }
1156                 afs_InvalidateAllSegments(avc);
1157             }
1158             s = VN_LOCK(vp);
1159             vp->v_count--;
1160             code = (vp->v_count == 0);
1161             VN_UNLOCK(vp, s);
1162             /* If the vnode is now in use by someone else, return early. */
1163             if (!code) {
1164                 ReleaseWriteLock(&avc->lock);
1165                 AFS_RWUNLOCK(vp, VRWLOCK_WRITE);
1166                 return VN_INACTIVE_CACHE;
1167             }
1168         }
1169     }
1170 #endif
1171
1172     osi_Assert((avc->f.states & (CCore | CMAPPED)) == 0);
1173
1174     if (avc->cred) {
1175         crfree(avc->cred);
1176         avc->cred = NULL;
1177     }
1178     ReleaseWriteLock(&avc->lock);
1179     AFS_RWUNLOCK(vp, VRWLOCK_WRITE);
1180
1181     /*
1182      * If someone unlinked a file and this is the last hurrah -
1183      * nuke all the pages.
1184      */
1185     if (avc->f.m.LinkCount == 0) {
1186         AFS_GUNLOCK();
1187         PTOSSVP(vp, (off_t) 0, (off_t) MAXLONG);
1188         AFS_GLOCK();
1189     }
1190 #ifndef AFS_SGI65_ENV
1191     osi_Assert(avc->mapcnt == 0);
1192     afs_chkpgoob(&avc->v, btoc(avc->f.m.Length));
1193
1194     avc->f.states &= ~CDirty;   /* Give up on store-backs */
1195     if (avc->f.states & CUnlinked) {
1196         if (CheckLock(&afs_xvcache) || CheckLock(&afs_xdcache)) {
1197             avc->f.states |= CUnlinkedDel;
1198         } else {
1199             afs_remunlink(avc, 1);      /* ignore any return code */
1200         }
1201     }
1202 #endif
1203 #ifdef AFS_SGI64_ENV
1204     return VN_INACTIVE_CACHE;
1205 #endif
1206 }
1207
1208 static int
1209 afs_reclaim(OSI_VC_DECL(avc), int flag)
1210 {
1211 #ifdef AFS_SGI64_ENV
1212     /* Get's called via VOP_RELCAIM in afs_FlushVCache to clear repl_vnodeops */
1213     return 0;
1214 #else
1215     panic("afs_reclaim");
1216 #endif
1217 }
1218
1219 void
1220 afs_rwlock(OSI_VN_DECL(vp), AFS_RWLOCK_T flag)
1221 {
1222     OSI_VN_CONVERT(vp);
1223     struct vcache *avc = VTOAFS(vp);
1224
1225     if (OSI_GET_LOCKID() == avc->vc_rwlockid) {
1226         avc->vc_locktrips++;
1227         return;
1228     }
1229     AFS_GUNLOCK();
1230     psema(&avc->vc_rwlock, PINOD);
1231     AFS_GLOCK();
1232     avc->vc_rwlockid = OSI_GET_LOCKID();
1233 }
1234
1235 void
1236 afs_rwunlock(OSI_VN_DECL(vp), AFS_RWLOCK_T flag)
1237 {
1238     OSI_VN_CONVERT(vp);
1239     struct vcache *avc = VTOAFS(vp);
1240
1241     AFS_ASSERT_GLOCK();
1242     osi_Assert(OSI_GET_LOCKID() == avc->vc_rwlockid);
1243     if (avc->vc_locktrips > 0) {
1244         --avc->vc_locktrips;
1245         return;
1246     }
1247     avc->vc_rwlockid = OSI_NO_LOCKID;
1248     vsema(&avc->vc_rwlock);
1249 }
1250
1251
1252 /* The flag argument is for symmetry with the afs_rwlock and afs_rwunlock
1253  * calls. SGI currently only uses the flag to assert if the unlock flag
1254  * does not match the corresponding lock flag. But they may start using this
1255  * flag for a real rw lock at some time.
1256  */
1257 int
1258 afs_rwlock_nowait(vnode_t * vp, AFS_RWLOCK_T flag)
1259 {
1260     struct vcache *avc = VTOAFS(vp);
1261
1262     AFS_ASSERT_GLOCK();
1263     if (OSI_GET_LOCKID() == avc->vc_rwlockid) {
1264         avc->vc_locktrips++;
1265         return 1;
1266     }
1267     if (cpsema(&avc->vc_rwlock)) {
1268         avc->vc_rwlockid = OSI_GET_LOCKID();
1269         return 1;
1270     }
1271     return 0;
1272 }
1273
1274 #if defined(AFS_SGI64_ENV) && defined(CKPT) && !defined(_R5000_CVT_WAR)
1275 int
1276 afs_fid2(OSI_VC_DECL(avc), struct fid *fidp)
1277 {
1278     struct cell *tcell;
1279     afs_fid2_t *afid = (afs_fid2_t *) fidp;
1280     OSI_VC_CONVERT(avc);
1281
1282     osi_Assert(sizeof(fid_t) >= sizeof(afs_fid2_t));
1283     afid->af_len = sizeof(afs_fid2_t) - sizeof(afid->af_len);
1284
1285     tcell = afs_GetCell(avc->f.fid.Cell, READ_LOCK);
1286     afid->af_cell = tcell->cellIndex & 0xffff;
1287     afs_PutCell(tcell, READ_LOCK);
1288
1289     afid->af_volid = avc->f.fid.Fid.Volume;
1290     afid->af_vno = avc->f.fid.Fid.Vnode;
1291     afid->af_uniq = avc->f.fid.Fid.Unique;
1292
1293     return 0;
1294 }
1295 #else
1296 /* Only use so far is in checkpoint/restart for IRIX 6.4. In ckpt_fid, a
1297  * return of ENOSYS would make the code fail over to VOP_FID. We can't let
1298  * that happen, since we do a VN_HOLD there in the expectation that 
1299  * posthandle will be called to release the vnode.
1300  *
1301  * afs_fid2 is used to support the R5000 workarounds (_R5000_CVT_WAR)
1302  */
1303 int
1304 afs_fid2(OSI_VC_DECL(avc), struct fid *fidp)
1305 {
1306 #if defined(_R5000_CVT_WAR)
1307     extern int R5000_cvt_war;
1308
1309     if (R5000_cvt_war)
1310         return ENOSYS;
1311     else
1312         return EINVAL;
1313 #else
1314     return EINVAL;
1315 #endif
1316 }
1317 #endif /* AFS_SGI64_ENV && CKPT */
1318
1319
1320 /*
1321  * check for any pages hashed that shouldn't be!
1322  * Only valid if PGCACHEDEBUG is set in os/page.c
1323  * Drop the global lock here, since we may not actually do the call.
1324  */
1325 void
1326 afs_chkpgoob(vnode_t * vp, pgno_t pgno)
1327 {
1328 #undef PGDEBUG
1329 #ifdef PGDEBUG
1330     AFS_GUNLOCK();
1331     pfindanyoob(vp, pgno);
1332     AFS_GLOCK();
1333 #endif
1334 }
1335
1336
1337 #ifdef MP
1338
1339 #ifdef AFS_SGI64_ENV
1340 #define AFS_MP_VC_ARG(A) bhv_desc_t A
1341 #else
1342 #define AFS_MP_VC_ARG(A) vnode_t A
1343 #endif
1344
1345 #ifdef AFS_SGI64_ENV
1346 int
1347 mp_afs_open(bhv_desc_t * bhp, vnode_t ** a, mode_t b, struct cred *c)
1348 #else
1349 int
1350 mp_afs_open(vnode_t ** a, mode_t b, struct cred *c)
1351 #endif
1352 {
1353     int rv;
1354     AFS_GLOCK();
1355 #ifdef AFS_SGI64_ENV
1356     rv = afs_lockedvnodeops.vop_open(bhp, a, b, c);
1357 #else
1358     rv = afs_lockedvnodeops.vop_open(a, b, c);
1359 #endif
1360     AFS_GUNLOCK();
1361     return rv;
1362 }
1363
1364 #if defined(AFS_SGI64_ENV)
1365 #if defined(AFS_SGI65_ENV)
1366 int
1367 mp_afs_close(AFS_MP_VC_ARG(*a), int b, lastclose_t c, struct cred *d)
1368 #else
1369 int
1370 mp_afs_close(AFS_MP_VC_ARG(*a), int b, lastclose_t c, off_t d, struct cred *e,
1371              struct flid *f)
1372 #endif
1373 #else
1374 int
1375 mp_afs_close(AFS_MP_VC_ARG(*a), int b, lastclose_t c, off_t d, struct cred *e)
1376 #endif
1377 {
1378     int rv;
1379     AFS_GLOCK();
1380     rv = afs_lockedvnodeops.vop_close(a, b, c, d
1381 #if !defined(AFS_SGI65_ENV)
1382                                       , e
1383 #if defined(AFS_SGI64_ENV)
1384                                       , f
1385 #endif
1386 #endif
1387         );
1388
1389     AFS_GUNLOCK();
1390     return rv;
1391 }
1392
1393 #ifdef AFS_SGI64_ENV
1394 int
1395 mp_afs_read(AFS_MP_VC_ARG(*a), struct uio *b, int c, struct cred *d,
1396             struct flid *f)
1397 #else
1398 int
1399 mp_afs_read(AFS_MP_VC_ARG(*a), struct uio *b, int c, struct cred *d)
1400 #endif
1401 {
1402     int rv;
1403     AFS_GLOCK();
1404 #ifdef AFS_SGI64_ENV
1405     rv = afs_lockedvnodeops.vop_read(a, b, c, d, f);
1406 #else
1407     rv = afs_lockedvnodeops.vop_read(a, b, c, d);
1408 #endif
1409     AFS_GUNLOCK();
1410     return rv;
1411 }
1412
1413
1414 #ifdef AFS_SGI64_ENV
1415 int
1416 mp_afs_write(AFS_MP_VC_ARG(*a), struct uio *b, int c, struct cred *d,
1417              struct flid *f)
1418 #else
1419 int
1420 mp_afs_write(AFS_MP_VC_ARG(*a), struct uio *b, int c, struct cred *d)
1421 #endif
1422 {
1423     int rv;
1424     AFS_GLOCK();
1425 #ifdef AFS_SGI64_ENV
1426     rv = afs_lockedvnodeops.vop_write(a, b, c, d, f);
1427 #else
1428     rv = afs_lockedvnodeops.vop_write(a, b, c, d);
1429 #endif
1430     AFS_GUNLOCK();
1431     return rv;
1432 }
1433
1434 int
1435 mp_afs_ioctl(AFS_MP_VC_ARG(*a), int b, void *c, int d, struct cred *e, int *f
1436 #ifdef AFS_SGI65_ENV
1437              , struct vopbd *vbds
1438 #endif
1439     )
1440 {
1441     int rv;
1442     AFS_GLOCK();
1443     rv = afs_lockedvnodeops.vop_ioctl(a, b, c, d, e, f
1444 #ifdef AFS_SGI65_ENV
1445                                       , vbds
1446 #endif
1447         );
1448     AFS_GUNLOCK();
1449     return rv;
1450 }
1451
1452 int
1453 mp_fs_setfl(AFS_MP_VC_ARG(*a), int b, int c, struct cred *d)
1454 {
1455     int rv;
1456     AFS_GLOCK();
1457     rv = afs_lockedvnodeops.vop_setfl(a, b, c, d);
1458     AFS_GUNLOCK();
1459     return rv;
1460 }
1461
1462 int
1463 mp_afs_getattr(AFS_MP_VC_ARG(*a), struct vattr *b, int c, struct cred *d)
1464 {
1465     int rv;
1466     AFS_GLOCK();
1467     rv = afs_lockedvnodeops.vop_getattr(a, b, c, d);
1468     AFS_GUNLOCK();
1469     return rv;
1470 }
1471
1472 int
1473 mp_afs_setattr(AFS_MP_VC_ARG(*a), struct vattr *b, int c, struct cred *d)
1474 {
1475     int rv;
1476     AFS_GLOCK();
1477     rv = afs_lockedvnodeops.vop_setattr(a, b, c, d);
1478     AFS_GUNLOCK();
1479     return rv;
1480 }
1481
1482 int
1483 mp_afs_access(AFS_MP_VC_ARG(*a), int b,
1484 #ifndef AFS_SGI65_ENV
1485               int c,
1486 #endif
1487               struct cred *d)
1488 {
1489     int rv;
1490     AFS_GLOCK();
1491     rv = afs_lockedvnodeops.vop_access(a, b,
1492 #ifndef AFS_SGI65_ENV
1493                                        c,
1494 #endif
1495                                        d);
1496     AFS_GUNLOCK();
1497     return rv;
1498 }
1499
1500 int
1501 mp_afs_lookup(AFS_MP_VC_ARG(*a), char *b, vnode_t ** c, struct pathname *d,
1502               int e, vnode_t * f, struct cred *g)
1503 {
1504     int rv;
1505     AFS_GLOCK();
1506     rv = afs_lockedvnodeops.vop_lookup(a, b, c, d, e, f, g);
1507     AFS_GUNLOCK();
1508     return rv;
1509 }
1510
1511 #ifdef AFS_SGI64_ENV
1512 int
1513 mp_afs_create(AFS_MP_VC_ARG(*a), char *b, struct vattr *c, int d, int e,
1514               vnode_t ** f, struct cred *g)
1515 #else
1516 int
1517 mp_afs_create(AFS_MP_VC_ARG(*a), char *b, struct vattr *c, enum vcexcl d,
1518               int e, vnode_t ** f, struct cred *g)
1519 #endif
1520 {
1521     int rv;
1522     AFS_GLOCK();
1523     rv = afs_lockedvnodeops.vop_create(a, b, c, d, e, f, g);
1524     AFS_GUNLOCK();
1525     return rv;
1526 }
1527
1528 int
1529 mp_afs_remove(AFS_MP_VC_ARG(*a), char *b, struct cred *c)
1530 {
1531     int rv;
1532     AFS_GLOCK();
1533     rv = afs_lockedvnodeops.vop_remove(a, b, c);
1534     AFS_GUNLOCK();
1535     return rv;
1536 }
1537
1538 int
1539 mp_afs_link(AFS_MP_VC_ARG(*a), vnode_t * b, char *c, struct cred *d)
1540 {
1541     int rv;
1542     AFS_GLOCK();
1543     rv = afs_lockedvnodeops.vop_link(a, b, c, d);
1544     AFS_GUNLOCK();
1545     return rv;
1546 }
1547
1548 int
1549 mp_afs_rename(AFS_MP_VC_ARG(*a), char *b, vnode_t * c, char *d,
1550               struct pathname *e, struct cred *f)
1551 {
1552     int rv;
1553     AFS_GLOCK();
1554     rv = afs_lockedvnodeops.vop_rename(a, b, c, d, e, f);
1555     AFS_GUNLOCK();
1556     return rv;
1557 }
1558
1559 int
1560 mp_afs_mkdir(AFS_MP_VC_ARG(*a), char *b, struct vattr *c, vnode_t ** d,
1561              struct cred *e)
1562 {
1563     int rv;
1564     AFS_GLOCK();
1565     rv = afs_lockedvnodeops.vop_mkdir(a, b, c, d, e);
1566     AFS_GUNLOCK();
1567     return rv;
1568 }
1569
1570 int
1571 mp_afs_rmdir(AFS_MP_VC_ARG(*a), char *b, vnode_t * c, struct cred *d)
1572 {
1573     int rv;
1574     AFS_GLOCK();
1575     rv = afs_lockedvnodeops.vop_rmdir(a, b, c, d);
1576     AFS_GUNLOCK();
1577     return rv;
1578 }
1579
1580 int
1581 mp_afs_readdir(AFS_MP_VC_ARG(*a), struct uio *b, struct cred *c, int *d)
1582 {
1583     int rv;
1584     AFS_GLOCK();
1585     rv = afs_lockedvnodeops.vop_readdir(a, b, c, d);
1586     AFS_GUNLOCK();
1587     return rv;
1588 }
1589
1590 int
1591 mp_afs_symlink(AFS_MP_VC_ARG(*a), char *b, struct vattr *c, char *d,
1592                struct cred *e)
1593 {
1594     int rv;
1595     AFS_GLOCK();
1596     rv = afs_lockedvnodeops.vop_symlink(a, b, c, d, e);
1597     AFS_GUNLOCK();
1598     return rv;
1599 }
1600
1601 int
1602 mp_afs_readlink(AFS_MP_VC_ARG(*a), struct uio *b, struct cred *c)
1603 {
1604     int rv;
1605     AFS_GLOCK();
1606     rv = afs_lockedvnodeops.vop_readlink(a, b, c);
1607     AFS_GUNLOCK();
1608     return rv;
1609 }
1610
1611 int
1612 mp_afs_fsync(AFS_MP_VC_ARG(*a), int b, struct cred *c
1613 #ifdef AFS_SGI65_ENV
1614              , off_t start, off_t stop
1615 #endif
1616     )
1617 {
1618     int rv;
1619     AFS_GLOCK();
1620     rv = afs_lockedvnodeops.vop_fsync(a, b, c
1621 #ifdef AFS_SGI65_ENV
1622                                       , start, stop
1623 #endif
1624         );
1625     AFS_GUNLOCK();
1626     return rv;
1627 }
1628
1629 void
1630 mp_afs_inactive(AFS_MP_VC_ARG(*a), struct cred *b)
1631 {
1632     AFS_GLOCK();
1633     afs_lockedvnodeops.vop_inactive(a, b);
1634     AFS_GUNLOCK();
1635     return;
1636 }
1637
1638 int
1639 mp_afs_fid(AFS_MP_VC_ARG(*a), struct fid **b)
1640 {
1641     int rv;
1642     AFS_GLOCK();
1643     rv = afs_lockedvnodeops.vop_fid(a, b);
1644     AFS_GUNLOCK();
1645     return rv;
1646 }
1647
1648 int
1649 mp_afs_fid2(AFS_MP_VC_ARG(*a), struct fid *b)
1650 {
1651     int rv;
1652     AFS_GLOCK();
1653     rv = afs_lockedvnodeops.vop_fid2(a, b);
1654     AFS_GUNLOCK();
1655     return rv;
1656 }
1657
1658 void
1659 mp_afs_rwlock(AFS_MP_VC_ARG(*a), AFS_RWLOCK_T b)
1660 {
1661     AFS_GLOCK();
1662     afs_rwlock(a, VRWLOCK_WRITE);
1663     AFS_GUNLOCK();
1664 }
1665
1666 void
1667 mp_afs_rwunlock(AFS_MP_VC_ARG(*a), AFS_RWLOCK_T b)
1668 {
1669     AFS_GLOCK();
1670     afs_rwunlock(a, VRWLOCK_WRITE);
1671     AFS_GUNLOCK();
1672 }
1673
1674 int
1675 mp_afs_seek(AFS_MP_VC_ARG(*a), off_t b, off_t * c)
1676 {
1677     int rv;
1678     AFS_GLOCK();
1679     rv = afs_lockedvnodeops.vop_seek(a, b, c);
1680     AFS_GUNLOCK();
1681     return rv;
1682 }
1683
1684 int
1685 mp_fs_cmp(AFS_MP_VC_ARG(*a), vnode_t * b)
1686 {
1687     int rv;
1688     AFS_GLOCK();
1689     rv = afs_lockedvnodeops.vop_cmp(a, b);
1690     AFS_GUNLOCK();
1691     return rv;
1692 }
1693
1694 int
1695 mp_afs_frlock(AFS_MP_VC_ARG(*a), int b, struct flock *c, int d, off_t e,
1696 #ifdef AFS_SGI65_ENV
1697               vrwlock_t vrwlock,
1698 #endif
1699               struct cred *f)
1700 {
1701     int rv;
1702     AFS_GLOCK();
1703     rv = afs_lockedvnodeops.vop_frlock(a, b, c, d, e,
1704 #ifdef AFS_SGI65_ENV
1705                                        vrwlock,
1706 #endif
1707                                        f);
1708     AFS_GUNLOCK();
1709     return rv;
1710 }
1711
1712 int
1713 mp_afs_realvp(AFS_MP_VC_ARG(*a), vnode_t ** b)
1714 {
1715     int rv;
1716     AFS_GLOCK();
1717     rv = afs_lockedvnodeops.vop_realvp(a, b);
1718     AFS_GUNLOCK();
1719     return rv;
1720 }
1721
1722 int
1723 mp_afs_bmap(AFS_MP_VC_ARG(*a), off_t b, ssize_t c, int d, struct cred *e,
1724             struct bmapval *f, int *g)
1725 {
1726     int rv;
1727     AFS_GLOCK();
1728     rv = afs_lockedvnodeops.vop_bmap(a, b, c, d, e, f, g);
1729     AFS_GUNLOCK();
1730     return rv;
1731 }
1732
1733 void
1734 mp_afs_strategy(AFS_MP_VC_ARG(*a), struct buf *b)
1735 {
1736     int rv;
1737     AFS_GLOCK();
1738     afs_lockedvnodeops.vop_strategy(a, b);
1739     AFS_GUNLOCK();
1740     return;
1741 }
1742
1743 #ifdef AFS_SGI65_ENV
1744 int
1745 mp_afs_map(AFS_MP_VC_ARG(*a), off_t b, size_t c, mprot_t d, u_int e,
1746            struct cred *f, vnode_t ** g)
1747 #else
1748 int
1749 mp_afs_map(AFS_MP_VC_ARG(*a), off_t b, struct pregion *c, char **d, size_t e,
1750            u_int f, u_int g, u_int h, struct cred *i)
1751 #endif
1752 {
1753     int rv;
1754     AFS_GLOCK();
1755     rv = afs_lockedvnodeops.vop_map(a, b, c, d, e, f, g
1756 #ifndef AFS_SGI65_ENV
1757                                     , h, i
1758 #endif
1759         );
1760     AFS_GUNLOCK();
1761     return rv;
1762 }
1763
1764
1765 #ifndef AFS_SGI65_ENV
1766 /* As of Irix 6.5, addmap and delmap are only for devices */
1767 int
1768 mp_afs_addmap(AFS_MP_VC_ARG(*a), off_t b, struct pregion *c, addr_t d,
1769               size_t e, u_int f, u_int g, u_int h, struct cred *i)
1770 {
1771     int rv;
1772     AFS_GLOCK();
1773     rv = afs_lockedvnodeops.vop_addmap(a, b, c, d, e, f, g, h, i);
1774     AFS_GUNLOCK();
1775     return rv;
1776 }
1777
1778 int
1779 mp_afs_delmap(AFS_MP_VC_ARG(*a), off_t b, struct pregion *c, addr_t d,
1780               size_t e, u_int f, u_int g, u_int h, struct cred *i)
1781 {
1782     int rv;
1783     AFS_GLOCK();
1784     rv = afs_lockedvnodeops.vop_delmap(a, b, c, d, e, f, g, h, i);
1785     AFS_GUNLOCK();
1786     return rv;
1787 }
1788 #endif /* ! AFS_SGI65_ENV */
1789
1790 int
1791 mp_fs_poll(AFS_MP_VC_ARG(*a), short b, int c, short *d, struct pollhead **e
1792 #ifdef AFS_SGI65_ENV
1793            , unsigned int *f
1794 #endif
1795     )
1796 {
1797     int rv;
1798     AFS_GLOCK();
1799     rv = afs_lockedvnodeops.vop_poll(a, b, c, d, e
1800 #ifdef AFS_SGI65_ENV
1801                                      , f
1802 #endif
1803         );
1804     AFS_GUNLOCK();
1805     return rv;
1806 }
1807
1808
1809 struct vnodeops Afs_vnodeops = {
1810 #ifdef AFS_SGI64_ENV
1811 #ifdef AFS_SGI65_ENV
1812     BHV_IDENTITY_INIT_POSITION(VNODE_POSITION_BASE),
1813 #else
1814     VNODE_POSITION_BASE,
1815 #endif
1816 #endif
1817     mp_afs_open,
1818     mp_afs_close,
1819     mp_afs_read,
1820     mp_afs_write,
1821     mp_afs_ioctl,
1822     mp_fs_setfl,
1823     mp_afs_getattr,
1824     mp_afs_setattr,
1825     mp_afs_access,
1826     mp_afs_lookup,
1827     mp_afs_create,
1828     mp_afs_remove,
1829     mp_afs_link,
1830     mp_afs_rename,
1831     mp_afs_mkdir,
1832     mp_afs_rmdir,
1833     mp_afs_readdir,
1834     mp_afs_symlink,
1835     mp_afs_readlink,
1836     mp_afs_fsync,
1837     mp_afs_inactive,
1838     mp_afs_fid,
1839     mp_afs_fid2,
1840     mp_afs_rwlock,
1841     mp_afs_rwunlock,
1842     mp_afs_seek,
1843     mp_fs_cmp,
1844     mp_afs_frlock,
1845     fs_nosys,                   /* realvp */
1846     mp_afs_bmap,
1847     mp_afs_strategy,
1848     mp_afs_map,
1849 #ifdef AFS_SGI65_ENV
1850     fs_noerr,                   /* addmap - devices only */
1851     fs_noerr,                   /* delmap - devices only */
1852 #else
1853     mp_afs_addmap,
1854     mp_afs_delmap,
1855 #endif
1856     mp_fs_poll,                 /* poll */
1857     fs_nosys,                   /* dump */
1858     fs_pathconf,
1859     fs_nosys,                   /* allocstore */
1860     fs_nosys,                   /* fcntl */
1861     afs_reclaim,                /* reclaim */
1862     fs_nosys,                   /* attr_get */
1863     fs_nosys,                   /* attr_set */
1864     fs_nosys,                   /* attr_remove */
1865     fs_nosys,                   /* attr_list */
1866 #ifdef AFS_SGI64_ENV
1867 #ifdef AFS_SGI65_ENV
1868     fs_cover,
1869     (vop_link_removed_t) fs_noval,
1870     fs_vnode_change,
1871     fs_tosspages,
1872     fs_flushinval_pages,
1873     fs_flush_pages,
1874     fs_invalfree_pages,
1875     fs_pages_sethole,
1876     (vop_commit_t) fs_nosys,
1877     (vop_readbuf_t) fs_nosys,
1878     fs_strgetmsg,
1879     fs_strputmsg,
1880 #else
1881     fs_mount,
1882 #endif
1883 #endif
1884 };
1885 struct vnodeops *afs_ops = &Afs_vnodeops;
1886 #endif /* MP */
1887
1888
1889 /* Support for XFS caches. The assumption here is that the size of
1890  * a cache file also does not exceed 32 bits. 
1891  */
1892
1893 /* Initialized in osi_InitCacheFSType(). Used to determine inode type. */
1894 vnodeops_t *afs_xfs_vnodeopsp;
1895
1896 extern afs_lock_t afs_xosi;     /* lock is for tvattr */
1897
1898 ino_t
1899 VnodeToIno(vnode_t * vp)
1900 {
1901     int code;
1902     struct vattr vattr;
1903
1904     ObtainWriteLock(&afs_xosi, 579);
1905     vattr.va_mask = AT_FSID | AT_NODEID;        /* quick return using this mask. */
1906     AFS_GUNLOCK();
1907     AFS_VOP_GETATTR(vp, &vattr, 0, OSI_GET_CURRENT_CRED(), code);
1908     AFS_GLOCK();
1909     if (code) {
1910         osi_Panic("VnodeToIno");
1911     }
1912     ReleaseWriteLock(&afs_xosi);
1913     return vattr.va_nodeid;
1914 }
1915
1916 dev_t
1917 VnodeToDev(vnode_t * vp)
1918 {
1919     int code;
1920     struct vattr vattr;
1921
1922     ObtainWriteLock(&afs_xosi, 580);
1923     vattr.va_mask = AT_FSID | AT_NODEID;        /* quick return using this mask. */
1924     AFS_GUNLOCK();
1925     AFS_VOP_GETATTR(vp, &vattr, 0, OSI_GET_CURRENT_CRED(), code);
1926     AFS_GLOCK();
1927     if (code) {
1928         osi_Panic("VnodeToDev");
1929     }
1930     ReleaseWriteLock(&afs_xosi);
1931     return (dev_t) vattr.va_fsid;
1932 }
1933
1934 off_t
1935 VnodeToSize(vnode_t * vp)
1936 {
1937     int code;
1938     struct vattr vattr;
1939
1940     ObtainWriteLock(&afs_xosi, 581);
1941     vattr.va_mask = AT_SIZE;
1942     AFS_GUNLOCK();
1943     AFS_VOP_GETATTR(vp, &vattr, 0, OSI_GET_CURRENT_CRED(), code);
1944     AFS_GLOCK();
1945     if (code) {
1946         osi_Panic("VnodeToSize");
1947     }
1948     ReleaseWriteLock(&afs_xosi);
1949     return vattr.va_size;
1950 }
1951 #endif /* AFS_SGI62_ENV */