include-afsconfig-before-param-h-20010712
[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 = (struct vnode *)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->flags & 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             bzero(c, 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 = (struct vnode*)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 = (struct vnode*)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, (long)acred->cr_uid,
971                             0L, 0L, 0L);
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 = (struct vnode*)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, 1);
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 = (struct vcache *)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 = (struct vcache *)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 = (struct vcache *)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)
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 int afs_fid2(OSI_VC_DECL(avc), struct fid *fidp)
1288 {
1289     return EINVAL;
1290 }
1291 #endif /* AFS_SGI64_ENV && CKPT */
1292
1293
1294 /*
1295  * check for any pages hashed that shouldn't be!
1296  * Only valid if PGCACHEDEBUG is set in os/page.c
1297  * Drop the global lock here, since we may not actually do the call.
1298  */
1299 void
1300 afs_chkpgoob(vnode_t *vp, pgno_t pgno)
1301 {
1302 #undef PGDEBUG
1303 #ifdef PGDEBUG
1304     AFS_GUNLOCK();
1305     pfindanyoob(vp, pgno);
1306     AFS_GLOCK();
1307 #endif
1308 }
1309
1310
1311 #ifdef MP
1312
1313 #ifdef AFS_SGI64_ENV
1314 #define AFS_MP_VC_ARG(A) bhv_desc_t A
1315 #else
1316 #define AFS_MP_VC_ARG(A) vnode_t A
1317 #endif
1318
1319 #ifdef AFS_SGI64_ENV
1320 int mp_afs_open(bhv_desc_t *bhp, vnode_t **a, mode_t b, struct cred *c)
1321 #else
1322 int mp_afs_open(vnode_t **a, mode_t b, struct cred *c)
1323 #endif
1324 {
1325         int rv;
1326         AFS_GLOCK();
1327 #ifdef AFS_SGI64_ENV
1328         rv = afs_lockedvnodeops.vop_open(bhp, a, b, c);
1329 #else
1330         rv = afs_lockedvnodeops.vop_open(a, b, c);
1331 #endif
1332         AFS_GUNLOCK();
1333         return rv;
1334 }
1335
1336 #if defined(AFS_SGI64_ENV)
1337 #if defined(AFS_SGI65_ENV)
1338 int mp_afs_close(AFS_MP_VC_ARG (*a), int b, lastclose_t c, struct cred *d)
1339 #else
1340 int mp_afs_close(AFS_MP_VC_ARG (*a), int b, lastclose_t c, off_t d,
1341                  struct cred *e, struct flid *f)
1342 #endif
1343 #else
1344 int mp_afs_close(AFS_MP_VC_ARG (*a), int b, lastclose_t c, off_t d,
1345                  struct cred *e)
1346 #endif
1347 {
1348         int rv;
1349         AFS_GLOCK();
1350         rv = afs_lockedvnodeops.vop_close(a, b, c, d
1351 #if !defined(AFS_SGI65_ENV)
1352                                           , e
1353 #if defined(AFS_SGI64_ENV)
1354                                           , f
1355 #endif
1356 #endif
1357                                           );
1358                                           
1359         AFS_GUNLOCK();
1360         return rv;
1361 }
1362
1363 #ifdef AFS_SGI64_ENV
1364 int mp_afs_read(AFS_MP_VC_ARG(*a), struct uio *b, int c, struct cred *d,
1365                 struct flid *f)
1366 #else
1367 int mp_afs_read(AFS_MP_VC_ARG(*a), struct uio *b, int c, struct cred *d)
1368 #endif
1369 {
1370         int rv;
1371         AFS_GLOCK();
1372 #ifdef AFS_SGI64_ENV
1373         rv = afs_lockedvnodeops.vop_read(a, b, c, d, f);
1374 #else
1375         rv = afs_lockedvnodeops.vop_read(a, b, c, d);
1376 #endif
1377         AFS_GUNLOCK();
1378         return rv;
1379 }
1380
1381
1382 #ifdef AFS_SGI64_ENV
1383 int mp_afs_write(AFS_MP_VC_ARG(*a), struct uio *b, int c, struct cred *d,
1384                  struct flid *f)
1385 #else
1386 int mp_afs_write(AFS_MP_VC_ARG(*a), struct uio *b, int c, struct cred *d)
1387 #endif
1388 {
1389         int rv;
1390         AFS_GLOCK();
1391 #ifdef AFS_SGI64_ENV
1392         rv = afs_lockedvnodeops.vop_write(a, b, c, d, f);
1393 #else
1394         rv = afs_lockedvnodeops.vop_write(a, b, c, d);
1395 #endif
1396         AFS_GUNLOCK();
1397         return rv;
1398 }
1399
1400 int mp_afs_ioctl(AFS_MP_VC_ARG(*a), int b, void *c, int d, struct cred *e,
1401                  int *f
1402 #ifdef AFS_SGI65_ENV
1403                  , struct vopbd *vbds
1404 #endif
1405                  )
1406 {
1407         int rv;
1408         AFS_GLOCK();
1409         rv = afs_lockedvnodeops.vop_ioctl(a, b, c, d, e, f
1410 #ifdef AFS_SGI65_ENV
1411                                           , vbds
1412 #endif
1413                                           );
1414         AFS_GUNLOCK();
1415         return rv;
1416 }
1417
1418 int mp_fs_setfl(AFS_MP_VC_ARG(*a), int b, int c, struct cred *d)
1419 {
1420         int rv;
1421         AFS_GLOCK();
1422         rv = afs_lockedvnodeops.vop_setfl(a, b, c, d);
1423         AFS_GUNLOCK();
1424         return rv;
1425 }
1426 int mp_afs_getattr(AFS_MP_VC_ARG(*a), struct vattr *b, int c, struct cred *d)
1427 {
1428         int rv;
1429         AFS_GLOCK();
1430         rv = afs_lockedvnodeops.vop_getattr(a, b, c, d);
1431         AFS_GUNLOCK();
1432         return rv;
1433 }
1434 int mp_afs_setattr(AFS_MP_VC_ARG(*a), struct vattr *b, int c, struct cred *d)
1435 {
1436         int rv;
1437         AFS_GLOCK();
1438         rv = afs_lockedvnodeops.vop_setattr(a, b, c, d);
1439         AFS_GUNLOCK();
1440         return rv;
1441 }
1442
1443 int mp_afs_access(AFS_MP_VC_ARG(*a), int b, 
1444 #ifndef AFS_SGI65_ENV
1445                   int c, 
1446 #endif
1447                   struct cred *d)
1448 {
1449         int rv;
1450         AFS_GLOCK();
1451         rv = afs_lockedvnodeops.vop_access(a, b,
1452 #ifndef AFS_SGI65_ENV
1453                                            c,
1454 #endif
1455                                            d);
1456         AFS_GUNLOCK();
1457         return rv;
1458 }
1459
1460 int mp_afs_lookup(AFS_MP_VC_ARG(*a), char *b, vnode_t **c, struct pathname *d,
1461                   int e, vnode_t *f, struct cred *g)
1462 {
1463         int rv;
1464         AFS_GLOCK();
1465         rv = afs_lockedvnodeops.vop_lookup(a, b, c, d, e, f, g);
1466         AFS_GUNLOCK();
1467         return rv;
1468 }
1469 #ifdef AFS_SGI64_ENV
1470 int mp_afs_create(AFS_MP_VC_ARG(*a), char *b, struct vattr *c, int d, int e,
1471                   vnode_t **f, struct cred *g)
1472 #else
1473 int mp_afs_create(AFS_MP_VC_ARG(*a), char *b, struct vattr *c, enum vcexcl d,
1474                   int e, vnode_t **f, struct cred *g)
1475 #endif
1476 {
1477         int rv;
1478         AFS_GLOCK();
1479         rv = afs_lockedvnodeops.vop_create(a, b, c, d, e, f, g);
1480         AFS_GUNLOCK();
1481         return rv;
1482 }
1483 int mp_afs_remove(AFS_MP_VC_ARG(*a), char *b, struct cred *c)
1484 {
1485         int rv;
1486         AFS_GLOCK();
1487         rv = afs_lockedvnodeops.vop_remove(a, b, c);
1488         AFS_GUNLOCK();
1489         return rv;
1490 }
1491 int mp_afs_link(AFS_MP_VC_ARG(*a), vnode_t *b, char *c, struct cred *d)
1492 {
1493         int rv;
1494         AFS_GLOCK();
1495         rv = afs_lockedvnodeops.vop_link(a, b, c, d);
1496         AFS_GUNLOCK();
1497         return rv;
1498 }
1499 int mp_afs_rename(AFS_MP_VC_ARG(*a), char *b, vnode_t *c, char *d,
1500                   struct pathname *e, struct cred *f)
1501 {
1502         int rv;
1503         AFS_GLOCK();
1504         rv = afs_lockedvnodeops.vop_rename(a, b, c, d, e, f);
1505         AFS_GUNLOCK();
1506         return rv;
1507 }
1508 int mp_afs_mkdir(AFS_MP_VC_ARG(*a), char *b, struct vattr *c, vnode_t **d,
1509                  struct cred *e)
1510 {
1511         int rv;
1512         AFS_GLOCK();
1513         rv = afs_lockedvnodeops.vop_mkdir(a, b, c, d, e);
1514         AFS_GUNLOCK();
1515         return rv;
1516 }
1517 int mp_afs_rmdir(AFS_MP_VC_ARG(*a), char *b, vnode_t *c, struct cred *d)
1518 {
1519         int rv;
1520         AFS_GLOCK();
1521         rv = afs_lockedvnodeops.vop_rmdir(a, b, c, d);
1522         AFS_GUNLOCK();
1523         return rv;
1524 }
1525 int mp_afs_readdir(AFS_MP_VC_ARG(*a), struct uio *b, struct cred *c, int *d)
1526 {
1527         int rv;
1528         AFS_GLOCK();
1529         rv = afs_lockedvnodeops.vop_readdir(a, b, c, d);
1530         AFS_GUNLOCK();
1531         return rv;
1532 }
1533 int mp_afs_symlink(AFS_MP_VC_ARG(*a), char *b, struct vattr *c, char *d,
1534                    struct cred *e)
1535 {
1536         int rv;
1537         AFS_GLOCK();
1538         rv = afs_lockedvnodeops.vop_symlink(a, b, c, d, e);
1539         AFS_GUNLOCK();
1540         return rv;
1541 }
1542 int mp_afs_readlink(AFS_MP_VC_ARG(*a), struct uio *b, struct cred *c)
1543 {
1544         int rv;
1545         AFS_GLOCK();
1546         rv = afs_lockedvnodeops.vop_readlink(a, b, c);
1547         AFS_GUNLOCK();
1548         return rv;
1549 }
1550
1551 int mp_afs_fsync(AFS_MP_VC_ARG(*a), int b, struct cred *c
1552 #ifdef AFS_SGI65_ENV
1553                  , off_t start, off_t stop
1554 #endif
1555                  )
1556 {
1557         int rv;
1558         AFS_GLOCK();
1559         rv = afs_lockedvnodeops.vop_fsync(a, b, c
1560 #ifdef AFS_SGI65_ENV
1561                                           , start, stop
1562 #endif
1563                                           );
1564         AFS_GUNLOCK();
1565         return rv;
1566 }
1567
1568 void mp_afs_inactive(AFS_MP_VC_ARG(*a), struct cred *b)
1569 {
1570         AFS_GLOCK();
1571         afs_lockedvnodeops.vop_inactive(a, b);
1572         AFS_GUNLOCK();
1573         return;
1574 }
1575 int mp_afs_fid(AFS_MP_VC_ARG(*a), struct fid **b)
1576 {
1577         int rv;
1578         AFS_GLOCK();
1579         rv = afs_lockedvnodeops.vop_fid(a, b);
1580         AFS_GUNLOCK();
1581         return rv;
1582 }
1583 int mp_afs_fid2(AFS_MP_VC_ARG(*a), struct fid *b)
1584 {
1585         int rv;
1586         AFS_GLOCK();
1587         rv = afs_lockedvnodeops.vop_fid2(a, b);
1588         AFS_GUNLOCK();
1589         return rv;
1590 }
1591 void mp_afs_rwlock(AFS_MP_VC_ARG(*a), AFS_RWLOCK_T b)
1592 {
1593         AFS_GLOCK();
1594         afs_rwlock(a, VRWLOCK_WRITE);
1595         AFS_GUNLOCK();
1596 }
1597 void mp_afs_rwunlock(AFS_MP_VC_ARG(*a), AFS_RWLOCK_T b)
1598 {
1599         AFS_GLOCK();
1600         afs_rwunlock(a, VRWLOCK_WRITE);
1601         AFS_GUNLOCK();
1602 }
1603 int mp_afs_seek(AFS_MP_VC_ARG(*a), off_t b, off_t*c)
1604 {
1605         int rv;
1606         AFS_GLOCK();
1607         rv = afs_lockedvnodeops.vop_seek(a, b, c);
1608         AFS_GUNLOCK();
1609         return rv;
1610 }
1611 int mp_fs_cmp(AFS_MP_VC_ARG(*a), vnode_t *b)
1612 {
1613         int rv;
1614         AFS_GLOCK();
1615         rv = afs_lockedvnodeops.vop_cmp(a, b);
1616         AFS_GUNLOCK();
1617         return rv;
1618 }
1619
1620 int mp_afs_frlock(AFS_MP_VC_ARG(*a), int b, struct flock *c, int d, off_t e,
1621 #ifdef AFS_SGI65_ENV
1622                   vrwlock_t vrwlock,
1623 #endif
1624                   struct cred *f)
1625 {
1626         int rv;
1627         AFS_GLOCK();
1628         rv = afs_lockedvnodeops.vop_frlock(a, b, c, d, e,
1629 #ifdef AFS_SGI65_ENV
1630                                            vrwlock,
1631 #endif
1632                                            f);
1633         AFS_GUNLOCK();
1634         return rv;
1635 }
1636
1637 int mp_afs_realvp(AFS_MP_VC_ARG(*a), vnode_t **b)
1638 {
1639         int rv;
1640         AFS_GLOCK();
1641         rv = afs_lockedvnodeops.vop_realvp(a, b);
1642         AFS_GUNLOCK();
1643         return rv;
1644 }
1645 int mp_afs_bmap(AFS_MP_VC_ARG(*a), off_t b, ssize_t c, int d, struct cred *e,
1646                 struct bmapval *f, int *g)
1647 {
1648         int rv;
1649         AFS_GLOCK();
1650         rv = afs_lockedvnodeops.vop_bmap(a, b, c, d, e, f, g);
1651         AFS_GUNLOCK();
1652         return rv;
1653 }
1654
1655 void mp_afs_strategy(AFS_MP_VC_ARG(*a), struct buf *b)
1656 {
1657         int rv;
1658         AFS_GLOCK();
1659         afs_lockedvnodeops.vop_strategy(a, b);
1660         AFS_GUNLOCK();
1661         return;
1662 }
1663
1664 #ifdef AFS_SGI65_ENV
1665 int mp_afs_map(AFS_MP_VC_ARG(*a), off_t b, size_t c, mprot_t d,
1666                   u_int e, struct cred *f, vnode_t **g)
1667 #else
1668 int mp_afs_map(AFS_MP_VC_ARG(*a), off_t b, struct pregion *c, char ** d,
1669                size_t e, u_int f, u_int g, u_int h, struct cred *i)
1670 #endif
1671 {
1672         int rv;
1673         AFS_GLOCK();
1674         rv = afs_lockedvnodeops.vop_map(a, b, c, d, e, f, g
1675 #ifndef AFS_SGI65_ENV
1676                                            , h, i
1677 #endif
1678                                            );
1679         AFS_GUNLOCK();
1680         return rv;
1681 }
1682
1683
1684 #ifndef AFS_SGI65_ENV
1685 /* As of Irix 6.5, addmap and delmap are only for devices */
1686 int mp_afs_addmap(AFS_MP_VC_ARG(*a), off_t b, struct pregion *c, addr_t d,
1687                   size_t e, u_int f, u_int g, u_int h, struct cred *i)
1688 {
1689         int rv;
1690         AFS_GLOCK();
1691         rv = afs_lockedvnodeops.vop_addmap(a, b, c, d, e, f, g, h, i);
1692         AFS_GUNLOCK();
1693         return rv;
1694 }
1695
1696 int mp_afs_delmap(AFS_MP_VC_ARG(*a), off_t b, struct pregion *c, addr_t d,
1697                   size_t e, u_int f, u_int g, u_int h, struct cred *i)
1698 {
1699         int rv;
1700         AFS_GLOCK();
1701         rv = afs_lockedvnodeops.vop_delmap(a, b, c, d, e, f, g, h, i);
1702         AFS_GUNLOCK();
1703         return rv;
1704 }
1705 #endif /* ! AFS_SGI65_ENV */
1706
1707 int mp_fs_poll(AFS_MP_VC_ARG(*a), short b, int c, short *d,
1708                struct pollhead **e
1709 #ifdef AFS_SGI65_ENV
1710                , unsigned int *f
1711 #endif
1712                )
1713 {
1714         int rv;
1715         AFS_GLOCK();
1716         rv = afs_lockedvnodeops.vop_poll(a, b, c, d, e
1717 #ifdef AFS_SGI65_ENV
1718                                          , f
1719 #endif
1720                                          );
1721         AFS_GUNLOCK();
1722         return rv;
1723 }
1724
1725
1726 struct vnodeops Afs_vnodeops = {
1727 #ifdef AFS_SGI64_ENV
1728 #ifdef AFS_SGI65_ENV
1729         BHV_IDENTITY_INIT_POSITION(VNODE_POSITION_BASE),
1730 #else
1731         VNODE_POSITION_BASE,
1732 #endif
1733 #endif
1734         mp_afs_open,
1735         mp_afs_close,
1736         mp_afs_read,
1737         mp_afs_write,
1738         mp_afs_ioctl,
1739         mp_fs_setfl,
1740         mp_afs_getattr,
1741         mp_afs_setattr,
1742         mp_afs_access,
1743         mp_afs_lookup,
1744         mp_afs_create,
1745         mp_afs_remove,
1746         mp_afs_link,
1747         mp_afs_rename,
1748         mp_afs_mkdir,
1749         mp_afs_rmdir,
1750         mp_afs_readdir,
1751         mp_afs_symlink,
1752         mp_afs_readlink,
1753         mp_afs_fsync,
1754         mp_afs_inactive,
1755         mp_afs_fid,
1756         mp_afs_fid2,
1757         mp_afs_rwlock,
1758         mp_afs_rwunlock,
1759         mp_afs_seek,
1760         mp_fs_cmp,
1761         mp_afs_frlock,
1762         fs_nosys,       /* realvp */
1763         mp_afs_bmap,
1764         mp_afs_strategy,
1765         mp_afs_map,
1766 #ifdef AFS_SGI65_ENV
1767         fs_noerr,       /* addmap - devices only */
1768         fs_noerr,       /* delmap - devices only */
1769 #else
1770         mp_afs_addmap,
1771         mp_afs_delmap,
1772 #endif
1773         mp_fs_poll,     /* poll */
1774         fs_nosys,       /* dump */
1775         fs_pathconf,
1776         fs_nosys,       /* allocstore */
1777         fs_nosys,       /* fcntl */
1778         afs_reclaim,    /* reclaim */
1779         fs_nosys,       /* attr_get */
1780         fs_nosys,       /* attr_set */
1781         fs_nosys,       /* attr_remove */
1782         fs_nosys,       /* attr_list */
1783 #ifdef AFS_SGI64_ENV
1784 #ifdef AFS_SGI65_ENV
1785         fs_cover,
1786         (vop_link_removed_t)fs_noval,
1787         fs_vnode_change,
1788         fs_tosspages,
1789         fs_flushinval_pages,
1790         fs_flush_pages,
1791         fs_invalfree_pages,
1792         fs_pages_sethole,
1793         (vop_commit_t)fs_nosys,
1794         (vop_readbuf_t)fs_nosys,
1795         fs_strgetmsg,
1796         fs_strputmsg,
1797 #else
1798         fs_mount,
1799 #endif
1800 #endif
1801 };
1802 struct vnodeops *afs_ops = &Afs_vnodeops;
1803 #endif /* MP */
1804
1805
1806 #if defined(AFS_SGI62_ENV) && defined(AFS_SGI_DUAL_FS_CACHE)
1807 /* Support for EFS and XFS caches. The assumption here is that the size of
1808  * a cache file also does not exceed 32 bits. 
1809  */
1810
1811 /* Initialized in osi_InitCacheFSType(). Used to determine inode type. */
1812 int afs_CacheFSType = -1;
1813 vnodeops_t *afs_efs_vnodeopsp;
1814 vnodeops_t *afs_xfs_vnodeopsp;
1815 vnode_t * (*afs_IGetVnode)(ino_t);
1816
1817 extern vnode_t *afs_EFSIGetVnode(ino_t); /* defined in osi_file.c */
1818 extern vnode_t *afs_XFSIGetVnode(ino_t); /* defined in osi_file.c */
1819
1820 extern afs_lock_t afs_xosi;              /* lock is for tvattr */
1821
1822 /* Initialize the cache operations. Called while initializing cache files. */
1823 void afs_InitDualFSCacheOps(struct vnode *vp)
1824 {
1825     static int inited = 0;
1826     struct vfssw *swp;
1827     int found = 0;
1828
1829     if (inited)
1830         return;
1831     inited = 1;
1832
1833
1834 #ifdef AFS_SGI_EFS_IOPS_ENV
1835     swp = vfs_getvfssw("efs");
1836     if (swp) {
1837         afs_efs_vnodeopsp = swp->vsw_vnodeops;
1838         if(vp && vp->v_op == afs_efs_vnodeopsp) {
1839             afs_CacheFSType = AFS_SGI_EFS_CACHE;
1840             afs_IGetVnode = afs_EFSIGetVnode;
1841             found = 1;
1842         }
1843     }
1844 #endif /* AFS_SGI_EFS_IOPS_ENV */
1845
1846     swp = vfs_getvfssw("xfs");
1847     if (swp) {
1848         afs_xfs_vnodeopsp = swp->vsw_vnodeops;
1849         if (!found) {
1850             if (vp &&vp->v_op == afs_xfs_vnodeopsp) {
1851                 afs_CacheFSType = AFS_SGI_XFS_CACHE;
1852                 afs_IGetVnode = afs_XFSIGetVnode;
1853                 found = 1;
1854             }
1855         }
1856     }
1857
1858     if (vp && !found) 
1859         osi_Panic("osi_InitCacheFSType: Can't find fstype for vnode 0x%llx\n",
1860                   vp);
1861 }
1862
1863 ino_t VnodeToIno(vnode_t *vp)
1864 {
1865     int code;
1866     struct vattr vattr;
1867
1868     MObtainWriteLock(&afs_xosi,579);
1869     vattr.va_mask = AT_FSID|AT_NODEID; /* quick return using this mask. */
1870     AFS_GUNLOCK();
1871     AFS_VOP_GETATTR(vp, &vattr, 0, OSI_GET_CURRENT_CRED(), code);
1872     AFS_GLOCK();
1873     if (code) {
1874         osi_Panic("VnodeToIno");
1875     }
1876     MReleaseWriteLock(&afs_xosi);
1877     return vattr.va_nodeid;
1878 }
1879
1880 dev_t VnodeToDev(vnode_t *vp)
1881 {
1882     int code;
1883     struct vattr vattr;
1884
1885     MObtainWriteLock(&afs_xosi,580);
1886     vattr.va_mask = AT_FSID|AT_NODEID; /* quick return using this mask. */
1887     AFS_GUNLOCK();
1888     AFS_VOP_GETATTR(vp, &vattr, 0, OSI_GET_CURRENT_CRED(), code);
1889     AFS_GLOCK();
1890     if (code) {
1891         osi_Panic("VnodeToDev");
1892     }
1893     MReleaseWriteLock(&afs_xosi);
1894     return (dev_t)vattr.va_fsid;
1895 }
1896
1897 off_t VnodeToSize(vnode_t *vp)
1898 {
1899     int code;
1900     struct vattr vattr;
1901
1902     MObtainWriteLock(&afs_xosi,581);
1903     vattr.va_mask = AT_SIZE;
1904     AFS_GUNLOCK();
1905     AFS_VOP_GETATTR(vp, &vattr, 0, OSI_GET_CURRENT_CRED(), code);
1906     AFS_GLOCK();
1907     if (code) {
1908         osi_Panic("VnodeToSize");
1909     }
1910     MReleaseWriteLock(&afs_xosi);
1911     return vattr.va_size;
1912 }
1913 #endif /* 6.2 and dual fs cache */
1914 #endif /* AFS_SGI62_ENV */