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