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