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