2 * Copyright 2000, International Business Machines Corporation and others.
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
11 * SGI specific vnodeops + other misc interface glue
13 #include <afsconfig.h>
14 #include "afs/param.h"
18 #include "afs/sysincludes.h" /* Standard vendor system headers */
19 #include "afsincludes.h" /* Afs-based standard headers */
20 #include "afs/afs_stats.h" /* statistics */
21 #include "sys/flock.h"
22 #include "afs/nfsclient.h"
24 /* AFSBSIZE must be at least the size of a page, else the client will hang.
25 * For 64 bit platforms, the page size is more than 8K.
27 #define AFSBSIZE _PAGESZ
28 extern struct afs_exporter *root_exported;
29 extern void afs_chkpgoob(vnode_t *, pgno_t);
31 static void afs_strategy();
32 static int afs_xread(), afs_xwrite();
33 static int afs_xbmap(), afs_map(), afs_reclaim();
35 static int afs_addmap(), afs_delmap();
37 extern int afs_open(), afs_close(), afs_ioctl(), afs_getattr(), afs_setattr();
38 extern int afs_access(), afs_lookup();
39 extern int afs_create(), afs_remove(), afs_link(), afs_rename();
40 extern int afs_mkdir(), afs_rmdir(), afs_readdir();
41 extern int afs_symlink(), afs_readlink(), afs_fsync(), afs_fid(),
43 static int afs_seek(OSI_VC_DECL(a), off_t b, off_t * c);
45 extern int afs_xinactive();
47 extern void afs_xinactive();
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);
53 extern int afs_fid2();
55 static int afsrwvp(struct vcache *avc, struct uio *uio,
56 enum uio_rw rw, int ioflag,
58 struct cred *cr, struct flid *flp);
63 static void mp_afs_rwlock(OSI_VN_DECL(a), AFS_RWLOCK_T b);
64 static void mp_afs_rwunlock(OSI_VN_DECL(a), AFS_RWLOCK_T b);
65 struct vnodeops afs_lockedvnodeops =
67 struct vnodeops Afs_vnodeops =
72 BHV_IDENTITY_INIT_POSITION(VNODE_POSITION_BASE),
105 fs_nosys, /* realvp */
110 fs_noerr, /* addmap - devices only */
111 fs_noerr, /* delmap - devices only */
119 fs_nosys, /* allocstore */
120 fs_nosys, /* fcntl */
121 afs_reclaim, /* reclaim */
122 fs_nosys, /* attr_get */
123 fs_nosys, /* attr_set */
124 fs_nosys, /* attr_remove */
125 fs_nosys, /* attr_list */
129 (vop_link_removed_t) fs_noval,
136 (vop_commit_t) fs_nosys,
137 (vop_readbuf_t) fs_nosys,
147 struct vnodeops *afs_ops = &Afs_vnodeops;
151 afs_frlock(OSI_VN_DECL(vp), int cmd, struct flock *lfp, int flag,
163 get_current_flid(&flid);
168 * Since AFS doesn't support byte-wise locks (and simply
169 * says yes! we handle byte locking locally only.
170 * This makes lots of things work much better
171 * XXX This doesn't properly handle moving from a
172 * byte-wise lock up to a full file lock (we should
173 * remove the byte locks ..) Of course neither did the
174 * regular AFS way ...
176 * For GETLK we do a bit more - we first check any byte-wise
177 * locks - if none then check for full AFS file locks
179 if (cmd == F_GETLK || lfp->l_whence != 0 || lfp->l_start != 0
180 || (lfp->l_len != MAXEND && lfp->l_len != 0)) {
181 AFS_RWLOCK(vp, VRWLOCK_WRITE);
185 fs_frlock(OSI_VN_ARG(vp), cmd, lfp, flag, offset, vrwlock, cr);
187 error = fs_frlock(vp, cmd, lfp, flag, offset, cr);
190 AFS_RWUNLOCK(vp, VRWLOCK_WRITE);
191 if (error || cmd != F_GETLK)
193 if (lfp->l_type != F_UNLCK)
194 /* found some blocking lock */
196 /* fall through to check for full AFS file locks */
199 /* map BSD style to plain - we don't call reclock()
200 * and its only there that the difference is important
224 error = convoff(vp, lfp, 0, offset, SEEKLIMIT
226 , OSI_GET_CURRENT_CRED()
227 #endif /* AFS_SGI64_ENV */
233 error = afs_lockctl(vp, lfp, cmd, cr, pid);
235 error = afs_lockctl(vp, lfp, cmd, cr, OSI_GET_CURRENT_PID());
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....
265 afs_xread(OSI_VC_ARG(avc), uiop, ioflag, cr, flp)
269 afs_xread(OSI_VC_ARG(avc), uiop, ioflag, cr)
279 osi_Assert(avc->v.v_count > 0);
280 if (avc->v.v_type != VREG)
285 if (!(ioflag & IO_ISLOCKED))
286 AFS_RWLOCK((vnode_t *) avc, VRWLOCK_READ);
288 code = afsrwvp(avc, uiop, UIO_READ, ioflag, cr, flp);
290 if (!(ioflag & IO_ISLOCKED))
291 AFS_RWUNLOCK((vnode_t *) avc, VRWLOCK_READ);
294 code = afsrwvp(avc, uiop, UIO_READ, ioflag, cr);
302 afs_xwrite(OSI_VC_ARG(avc), uiop, ioflag, cr, flp)
306 afs_xwrite(OSI_VC_ARG(avc), uiop, ioflag, cr)
316 osi_Assert(avc->v.v_count > 0);
317 if (avc->v.v_type != VREG)
320 if (ioflag & IO_APPEND)
321 uiop->uio_offset = avc->f.m.Length;
324 if (!(ioflag & IO_ISLOCKED))
325 AFS_RWLOCK(((vnode_t *) avc), VRWLOCK_WRITE);
327 code = afsrwvp(avc, uiop, UIO_WRITE, ioflag, cr, flp);
329 if (!(ioflag & IO_ISLOCKED))
330 AFS_RWUNLOCK((vnode_t *) avc, VRWLOCK_WRITE);
333 code = afsrwvp(avc, uiop, UIO_WRITE, ioflag, cr);
339 static int prnra = 0;
340 static int acchk = 0;
341 static int acdrop = 0;
344 afsrwvp(struct vcache *avc, struct uio *uio, enum uio_rw rw,
347 struct cred *cr, struct flid *flp)
352 struct vnode *vp = AFSTOV(avc);
357 off_t bsize, rem, len;
359 struct bmapval bmv[2];
360 int nmaps, didFakeOpen = 0;
361 struct vrequest treq;
365 osi_Assert((valusema(&avc->vc_rwlock) <= 0)
366 && (OSI_GET_LOCKID() == avc->vc_rwlockid));
369 newoff = uio->uio_resid + uio->uio_offset;
370 if (uio->uio_resid <= 0) {
373 if (uio->uio_offset < 0 || newoff < 0) {
376 if (ioflag & IO_DIRECT)
379 if (rw == UIO_WRITE && vp->v_type == VREG && newoff > uio->uio_limit) {
383 afs_Trace4(afs_iclSetp, CM_TRACE_GRDWR, ICL_TYPE_POINTER, avc,
384 ICL_TYPE_INT32, ioflag, ICL_TYPE_INT32, rw, ICL_TYPE_INT32, 0);
386 /* get a validated vcache entry */
387 afs_InitReq(&treq, cr);
388 error = afs_VerifyVCache(avc, &treq);
390 return afs_CheckCode(error, &treq, 51);
393 * flush any stale pages - this will unmap
394 * and invalidate all pages for vp (NOT writing them back!)
396 osi_FlushPages(avc, cr);
398 if (cr && AFS_NFSXLATORREQ(cr) && rw == UIO_READ) {
400 (avc, PRSFS_READ, &treq,
401 CHECK_MODE_BITS | CMB_ALLOW_EXEC_AS_READ))
405 * To handle anonymous calls to VOP_STRATEGY from afs_sync/sync/bdflush
406 * we need better than the callers credentials. So we squirrel away
407 * the last writers credentials
409 if (rw == UIO_WRITE || (rw == UIO_READ && avc->cred == NULL)) {
410 ObtainWriteLock(&avc->lock, 92);
415 ReleaseWriteLock(&avc->lock);
419 * We have to bump the open/exwriters field here
420 * courtesy of the nfs xlator
421 * because there're no open/close nfs rpc's to call our afs_open/close.
423 if (root_exported && rw == UIO_WRITE) {
424 ObtainWriteLock(&avc->lock, 234);
429 ReleaseWriteLock(&avc->lock);
433 if (rw == UIO_WRITE) {
434 ObtainWriteLock(&avc->lock, 330);
435 avc->f.states |= CDirty;
436 ReleaseWriteLock(&avc->lock);
442 /* If v_dpages is set SGI 5.3 will convert those pages to
443 * B_DELWRI in chunkread and getchunk. Write the pages out
444 * before we trigger that behavior. For 6.1, dirty pages stay
445 * around too long and we should get rid of them as quickly
448 while (VN_GET_DPAGES(vp))
452 error = avc->vc_error;
455 bsize = AFSBSIZE; /* why not?? */
456 off = uio->uio_offset % bsize;
457 bn = BTOBBT(uio->uio_offset - off);
459 * decrease bsize - otherwise we will
460 * get 'extra' pages in the cache for this
461 * vnode that we would need to flush when
462 * calling e.g. ptossvp.
463 * So we can use Length in ptossvp,
464 * we make sure we never go more than to the file size
465 * rounded up to a page boundary.
466 * That doesn't quite work, since we may get a page hashed to
467 * the vnode w/o updating the length. Thus we always use
468 * MAXLONG in ptossvp to be safe.
470 if (rw == UIO_READ) {
472 * read/paging in a normal file
474 rem = avc->f.m.Length - uio->uio_offset;
479 * compute minimum of rest of block and rest of file
481 cnt = MIN(bsize - off, rem);
482 osi_Assert((off + cnt) <= bsize);
483 bsize = ctob(btoc(off + cnt));
486 bmv[0].bn = bmv[0].offset = bn;
488 bmv[0].bsize = bsize;
490 bmv[0].pbsize = MIN(cnt, uio->uio_resid);
493 bmv[0].pbdev = vp->v_rdev;
494 bmv[0].pmp = uio->uio_pmp;
498 * initiate read-ahead if it looks like
499 * we are reading sequentially OR they want
500 * more than one 'bsize' (==AFSBSIZE) worth
501 * XXXHack - to avoid DELWRI buffers we can't
502 * do read-ahead on any file that has potentially
505 if ((avc->lastr + BTOBB(AFSBSIZE) == bn
506 || uio->uio_resid > AFSBSIZE)
508 && (!AFS_VN_MAPPED(vp))
509 #else /* AFS_SGI61_ENV */
510 && ((vp->v_flag & VWASMAP) == 0)
511 #endif /* AFS_SGI61_ENV */
516 bmv[1].bn = bmv[1].offset = bn + len;
517 osi_Assert((BBTOB(bn + len) % bsize) == 0);
518 acnt = MIN(bsize, rem);
519 bsize = ctob(btoc(acnt));
524 bmv[1].bsize = bsize;
526 bmv[1].pbsize = acnt;
528 bmv[1].pmp = uio->uio_pmp;
529 bmv[1].pbdev = vp->v_rdev;
536 ("NRA:vp 0x%x lastr %d bn %d len %d cnt %d bsize %d rem %d resid %d\n",
537 vp, avc->lastr, bn, len, cnt, bsize, rem,
542 bp = chunkread(vp, bmv, nmaps, cr);
544 * If at a chunk boundary, start prefetch of next chunk.
546 if (counter == 0 || AFS_CHUNKOFFSET(off) == 0) {
548 ObtainWriteLock(&avc->lock, 562);
549 tdc = afs_FindDCache(avc, off);
551 if (!(tdc->mflags & DFNextStarted))
552 afs_PrefetchChunk(avc, tdc, cr, &treq);
555 ReleaseWriteLock(&avc->lock);
561 * writing a normal file
564 * Purge dirty chunks of file if there are too many dirty chunks.
565 * Inside the write loop, we only do this at a chunk boundary.
566 * Clean up partial chunk if necessary at end of loop.
568 if (counter > 0 && AFS_CHUNKOFFSET(uio->uio_offset) == 0) {
570 ObtainWriteLock(&avc->lock, 90);
571 error = afs_DoPartialWrite(avc, &treq);
573 avc->f.states |= CDirty;
574 ReleaseWriteLock(&avc->lock);
581 cnt = MIN(bsize - off, uio->uio_resid);
582 bsize = ctob(btoc(off + cnt));
588 bmv[0].bsize = bsize;
592 bmv[0].pmp = uio->uio_pmp;
596 bp = getchunk(vp, bmv, cr);
598 bp = chunkread(vp, bmv, 1, cr);
600 avc->f.m.Date = osi_Time(); /* Set file date (for ranlib) */
602 if (bp->b_flags & B_ERROR) {
604 * Since we compile -signed, b_error is a signed
605 * char when it should be an unsigned char.
606 * This can cause some errors codes to be interpreted
609 error = (unsigned char)(bp->b_error);
613 if (acchk && error) {
614 cmn_err(CE_WARN, "bp 0x%x has error %d\n", bp, error);
623 osi_Assert(bp->b_error == 0);
625 if (uio->uio_segflg != UIO_NOSPACE)
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) {
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
639 if (avc->f.m.Length < uio->uio_offset) {
641 ObtainWriteLock(&avc->lock, 235);
642 avc->f.m.Length = uio->uio_offset;
643 ReleaseWriteLock(&avc->lock);
646 if (uio->uio_fmode & FSYNC) {
648 } else if (off + cnt < bsize) {
649 bawrite(bp); /* was bdwrite */
651 bp->b_flags |= B_AGE;
655 * Since EIO on an unlinked file is non-intuitive - give some
659 if (avc->f.m.LinkCount == 0)
661 "AFS: Process pid %d write error %d writing to unlinked file.",
662 OSI_GET_CURRENT_PID(), error);
665 } while (!error && uio->uio_resid > 0);
666 afs_chkpgoob(&avc->v, btoc(avc->f.m.Length));
670 if (rw == UIO_WRITE && error == 0 && (avc->f.states & CDirty)) {
671 ObtainWriteLock(&avc->lock, 405);
672 error = afs_DoPartialWrite(avc, &treq);
673 ReleaseWriteLock(&avc->lock);
678 if (((ioflag & IO_SYNC) || (ioflag & IO_DSYNC)) && (rw == UIO_WRITE)
679 && !AFS_NFSXLATORREQ(cr)) {
680 error = afs_fsync(avc, 0, cr
686 #else /* AFS_SGI61_ENV */
687 if ((ioflag & IO_SYNC) && (rw == UIO_WRITE) && !AFS_NFSXLATORREQ(cr)) {
688 error = afs_fsync(avc, 0, cr);
690 #endif /* AFS_SGI61_ENV */
693 ObtainWriteLock(&avc->lock, 236);
694 afs_FakeClose(avc, cr); /* XXXX For nfs trans XXXX */
695 ReleaseWriteLock(&avc->lock);
697 afs_Trace4(afs_iclSetp, CM_TRACE_GRDWR, ICL_TYPE_POINTER, avc,
698 ICL_TYPE_INT32, ioflag, ICL_TYPE_INT32, rw, ICL_TYPE_INT32,
705 afs_xbmap(OSI_VC_ARG(avc), offset, count, flag, cr, bmv, nbmv)
714 int bsize; /* server's block size in bytes */
720 off = offset % bsize; /* offset into block */
721 bmv->bn = BTOBBT(offset - off);
722 bmv->offset = bmv->bn;
724 rem = avc->f.m.Length - offset;
728 cnt = MIN(bsize - off, rem);
731 * It is benign to ignore *nbmv > 1, since it is only for requesting
736 * Don't map more than up to next page if at end of file
737 * See comment in afsrwvp
739 osi_Assert((off + cnt) <= bsize);
740 bsize = ctob(btoc(off + cnt));
741 bmv->pbsize = MIN(cnt, count);
745 bmv->pbdev = avc->v.v_rdev;
748 bmv->length = BTOBBT(bsize);
754 * called out of chunkread from afs_xread & clusterwrite to push dirty
755 * pages back - this routine
756 * actually does the reading/writing by calling afs_read/afs_write
757 * bp points to a set of pages that have been inserted into
758 * the page cache hashed on afs vp.
761 afs_strategy(OSI_VC_ARG(avc), bp)
771 vnode_t *vp = (vnode_t *) avc;
774 * We can't afford DELWRI buffers for 2 reasons:
775 * 1) Since we can call underlying EFS, we can require a
776 * buffer to flush a buffer. This leads to 2 potential
777 * recursions/deadlocks
778 * a) if all buffers are DELWRI afs buffers, then
779 * ngeteblk -> bwrite -> afs_strategy -> afs_write ->
780 * UFS_Write -> efs_write -> ngeteblk .... could
781 * recurse a long ways!
782 * b) brelse -> chunkhold which can call dchunkpush
783 * will look for any DELWRI buffers and call strategy
784 * on them. This can then end up via UFS_Write
787 * a) We never do bdwrite(s) on AFS buffers.
788 * b) We call pdflush with B_ASYNC
789 * c) in chunkhold where it can set a buffer DELWRI
790 * we immediatly do a clusterwrite for AFS vp's
791 * XXX Alas, 'c' got dropped in 5.1 so its possible to get DELWRI
792 * buffers if someone has mmaped the file and dirtied it then
793 * reads/faults it again.
794 * Instead - wherever we call chunkread/getchunk we check for a
795 * returned bp with DELWRI set, and write it out immediately
797 if (CheckLock(&avc->lock) && VN_GET_DBUF(vp)) {
798 printf("WARN: afs_strategy vp=%x, v_dbuf=%x bp=%x\n", vp,
799 VN_GET_DBUF(vp), bp);
801 bp->b_flags |= B_ERROR;
805 if (bp->b_error != 0)
806 printf("WARNING: afs_strategy3 vp=%x, bp=%x, err=%x\n", vp, bp,
810 * To get credentials somewhat correct (we may be called from bdflush/
811 * sync) we use saved credentials in Vcache.
812 * We must hold them since someone else could change them
814 ObtainReadLock(&avc->lock);
815 if (bp->b_flags & B_READ) {
816 if (BBTOB(bp->b_blkno) >= avc->f.m.Length) {
817 /* we are responsible for zero'ing the page */
820 memset(c, 0, bp->b_bcount);
822 ReleaseReadLock(&avc->lock);
825 } else if ((avc->f.states & CWritingUFS) && (bp->b_flags & B_DELWRI)) {
827 ReleaseReadLock(&avc->lock);
834 ReleaseReadLock(&avc->lock);
836 aiovec.iov_base = bp_mapin(bp);
837 uio->uio_iov = &aiovec;
839 uio->uio_resid = aiovec.iov_len = bp->b_bcount;
840 uio->uio_offset = BBTOB(bp->b_blkno);
841 uio->uio_segflg = UIO_SYSSPACE;
842 uio->uio_limit = RLIM_INFINITY; /* we checked the limit earlier */
847 if (bp->b_flags & B_READ) {
848 uio->uio_fmode = FREAD;
849 error = afs_read(vp, uio, cr, 0);
851 uio->uio_fmode = FWRITE;
852 error = afs_write(vp, uio, 0, cr, 0);
857 if (acchk && error) {
858 cmn_err(CE_WARN, "vp 0x%x has error %d\n", vp, error);
865 bp->b_flags |= B_ERROR;
866 if ((uio->uio_fmode == FWRITE) && !avc->vc_error)
867 avc->vc_error = error;
875 afs_seek(OSI_VC_ARG(avc), ooff, noffp)
880 return *noffp < 0 ? EINVAL : 0;
883 #if !defined(AFS_SGI65_ENV)
884 /* Irix 6.5 uses addmap/delmap only for devices. */
887 afs_addmap(OSI_VC_ARG(avc), off, prp, addr, len, prot, maxprot, flags, cr)
898 struct vnode *vp = AFSTOV(avc);
900 if (vp->v_flag & VNOMAP)
904 AFS_RWLOCK(vp, VRWLOCK_WRITE);
905 if (avc->mapcnt == 0) {
906 /* on first mapping add a open reference */
907 ObtainWriteLock(&avc->lock, 237);
908 avc->execsOrWriters++;
910 ReleaseWriteLock(&avc->lock);
912 avc->mapcnt += btoc(len);
913 AFS_RWUNLOCK(vp, VRWLOCK_WRITE);
917 /*ARGSUSED*/ static int
918 afs_delmap(OSI_VC_ARG(avc), off, prp, addr, len, prot, maxprot, flags, acred)
929 struct vnode *vp = AFSTOV(avc);
931 struct vrequest treq;
934 if (vp->v_flag & VNOMAP)
938 AFS_RWLOCK(vp, VRWLOCK_WRITE);
939 osi_Assert(avc->mapcnt > 0);
940 avc->mapcnt -= btoc(len);
941 osi_Assert(avc->mapcnt >= 0);
942 if (avc->mapcnt == 0) {
943 /* on last mapping push back and remove our reference */
944 osi_Assert(avc->execsOrWriters > 0);
945 osi_Assert(avc->opens > 0);
946 if (avc->f.m.LinkCount == 0) {
947 ObtainWriteLock(&avc->lock, 238);
949 PTOSSVP(vp, (off_t) 0, (off_t) MAXLONG);
951 ReleaseWriteLock(&avc->lock);
956 afs_InitReq(&treq, acred);
958 /* do it yourself if daemons are all busy */
959 ObtainWriteLock(&avc->lock, 239);
960 code = afs_StoreOnLastReference(avc, &treq);
961 ReleaseWriteLock(&avc->lock);
962 /* BStore does CheckCode so we should also */
963 /* VNOVNODE is "acceptable" error code from close, since
964 * may happen when deleting a file on another machine while
965 * it is open here. */
966 if (code == VNOVNODE)
969 afs_StoreWarn(code, avc->f.fid.Fid.Volume, /* /dev/console */
972 code = afs_CheckCode(code, &treq, 52);
973 AFS_RWUNLOCK(vp, VRWLOCK_WRITE);
975 AFS_RWUNLOCK(vp, VRWLOCK_WRITE);
976 /* at least one daemon is idle, so ask it to do the store.
977 * Also, note that we don't lock it any more... */
978 tb = afs_BQueue(BOP_STORE, avc, 0, 1, acred,
979 (afs_size_t) afs_cr_uid(acred), 0L, (void *)0,
980 (void *)0, (void *)0);
981 /* sleep waiting for the store to start, then retrieve error code */
982 while ((tb->flags & BUVALID) == 0) {
990 AFS_RWUNLOCK(vp, VRWLOCK_WRITE);
994 #endif /* ! AFS_SGI65_ENV */
999 * Note - if mapping in an ELF interpreter, one can get called without vp
1000 * ever having been 'opened'
1002 #ifdef AFS_SGI65_ENV
1004 afs_map(OSI_VC_ARG(avc), off, len, prot, flags, cr, vpp)
1014 afs_map(OSI_VC_ARG(avc), off, prp, addrp, len, prot, maxprot, flags, cr)
1017 struct pregion *prp;
1020 u_int prot, maxprot;
1025 OSI_VC_CONVERT(avc);
1026 struct vnode *vp = AFSTOV(avc);
1027 struct vrequest treq;
1030 /* get a validated vcache entry */
1031 afs_InitReq(&treq, cr);
1032 error = afs_VerifyVCache(avc, &treq);
1034 return afs_CheckCode(error, &treq, 53);
1036 osi_FlushPages(avc, cr); /* ensure old pages are gone */
1037 #ifdef AFS_SGI65_ENV
1038 /* If the vnode is currently opened for write, there's the potential
1039 * that this mapping might (now or in the future) have PROT_WRITE.
1040 * So assume it does and we'll have to call afs_StoreOnLastReference.
1042 AFS_RWLOCK(vp, VRWLOCK_WRITE);
1043 ObtainWriteLock(&avc->lock, 501);
1044 if (avc->execsOrWriters > 0) {
1045 avc->execsOrWriters++;
1047 avc->mapcnt++; /* count eow's due to mappings. */
1049 ReleaseWriteLock(&avc->lock);
1050 AFS_RWUNLOCK(vp, VRWLOCK_WRITE);
1052 AFS_RWLOCK(vp, VRWLOCK_WRITE);
1055 fs_map_subr(vp, (off_t) avc->f.m.Length, (u_int) avc->f.m.Mode, off, prp,
1056 *addrp, len, prot, maxprot, flags, cr);
1058 AFS_RWUNLOCK(vp, VRWLOCK_WRITE);
1059 #endif /* AFS_SGI65_ENV */
1060 afs_Trace4(afs_iclSetp, CM_TRACE_GMAP, ICL_TYPE_POINTER, vp,
1061 #ifdef AFS_SGI65_ENV
1062 ICL_TYPE_POINTER, NULL,
1064 ICL_TYPE_POINTER, *addrp,
1066 ICL_TYPE_INT32, len, ICL_TYPE_INT32, off);
1071 extern afs_rwlock_t afs_xvcache;
1072 extern afs_lock_t afs_xdcache;
1073 #ifdef AFS_SGI64_ENV
1078 afs_xinactive(OSI_VC_ARG(avc), acred)
1080 struct ucred *acred;
1083 OSI_VC_CONVERT(avc);
1084 vnode_t *vp = (vnode_t *) avc;
1085 int mapcnt = avc->mapcnt; /* We just clear off this many. */
1087 AFS_STATCNT(afs_inactive);
1090 if (!(vp->v_flag & VINACT) || (vp->v_count > 0)) {
1091 /* inactive was already done, or someone did a VN_HOLD; just return */
1092 vp->v_flag &= ~VINACT;
1094 #ifdef AFS_SGI64_ENV
1095 return VN_INACTIVE_CACHE;
1100 osi_Assert((vp->v_flag & VSHARE) == 0);
1101 vp->v_flag &= ~VINACT;
1102 /* Removed broadcast to waiters, since no one ever will. Only for vnodes
1107 #ifdef AFS_SGI65_ENV
1108 /* In Irix 6.5, the last unmap of a dirty mmap'd file does not
1109 * get an explicit vnode op. Instead we only find out at VOP_INACTIVE.
1111 if (!afs_rwlock_nowait((vnode_t *) avc, VRWLOCK_WRITE)) {
1112 return VN_INACTIVE_CACHE;
1114 if (NBObtainWriteLock(&avc->lock, 502)) {
1115 AFS_RWUNLOCK(vp, VRWLOCK_WRITE);
1116 return VN_INACTIVE_CACHE;
1118 if (avc->f.states & CUnlinked) {
1119 if (CheckLock(&afs_xvcache) || CheckLock(&afs_xdcache)) {
1120 avc->f.states |= CUnlinkedDel;
1121 ReleaseWriteLock(&avc->lock);
1122 AFS_RWUNLOCK(vp, VRWLOCK_WRITE);
1124 ReleaseWriteLock(&avc->lock);
1125 AFS_RWUNLOCK(vp, VRWLOCK_WRITE);
1126 afs_remunlink(avc, 1); /* ignore any return code */
1128 return VN_INACTIVE_CACHE;
1130 if ((avc->f.states & CDirty) || (avc->execsOrWriters > 0)) {
1131 /* File either already has dirty chunks (CDirty) or was mapped at
1132 * time in its life with the potential for being written into.
1133 * Note that afs_close defers storebacks if the vnode's ref count
1137 struct vrequest treq;
1138 if (!afs_InitReq(&treq, acred)) {
1142 avc->execsOrWriters -= mapcnt - 1;
1143 avc->opens -= mapcnt - 1;
1144 avc->mapcnt -= mapcnt;
1145 code = afs_StoreOnLastReference(avc, &treq);
1146 /* The following behavior mimics the behavior in afs_close. */
1147 if (code == VNOVNODE || code == ENOENT)
1152 "AFS: Failed to store FID (%x:%lu.%lu.%lu) in VOP_INACTIVE, error = %d\n",
1153 (int)(avc->f.fid.Cell) & 0xffffffff,
1154 avc->f.fid.Fid.Volume, avc->f.fid.Fid.Vnode,
1155 avc->f.fid.Fid.Unique, code);
1157 afs_InvalidateAllSegments(avc);
1161 code = (vp->v_count == 0);
1163 /* If the vnode is now in use by someone else, return early. */
1165 ReleaseWriteLock(&avc->lock);
1166 AFS_RWUNLOCK(vp, VRWLOCK_WRITE);
1167 return VN_INACTIVE_CACHE;
1173 osi_Assert((avc->f.states & (CCore | CMAPPED)) == 0);
1179 ReleaseWriteLock(&avc->lock);
1180 AFS_RWUNLOCK(vp, VRWLOCK_WRITE);
1183 * If someone unlinked a file and this is the last hurrah -
1184 * nuke all the pages.
1186 if (avc->f.m.LinkCount == 0) {
1188 PTOSSVP(vp, (off_t) 0, (off_t) MAXLONG);
1191 #ifndef AFS_SGI65_ENV
1192 osi_Assert(avc->mapcnt == 0);
1193 afs_chkpgoob(&avc->v, btoc(avc->f.m.Length));
1195 avc->f.states &= ~CDirty; /* Give up on store-backs */
1196 if (avc->f.states & CUnlinked) {
1197 if (CheckLock(&afs_xvcache) || CheckLock(&afs_xdcache)) {
1198 avc->f.states |= CUnlinkedDel;
1200 afs_remunlink(avc, 1); /* ignore any return code */
1204 #ifdef AFS_SGI64_ENV
1205 return VN_INACTIVE_CACHE;
1210 afs_reclaim(OSI_VC_DECL(avc), int flag)
1212 #ifdef AFS_SGI64_ENV
1213 /* Get's called via VOP_RELCAIM in afs_FlushVCache to clear repl_vnodeops */
1216 panic("afs_reclaim");
1221 afs_rwlock(OSI_VN_DECL(vp), AFS_RWLOCK_T flag)
1224 struct vcache *avc = VTOAFS(vp);
1226 if (OSI_GET_LOCKID() == avc->vc_rwlockid) {
1227 avc->vc_locktrips++;
1231 psema(&avc->vc_rwlock, PINOD);
1233 avc->vc_rwlockid = OSI_GET_LOCKID();
1237 afs_rwunlock(OSI_VN_DECL(vp), AFS_RWLOCK_T flag)
1240 struct vcache *avc = VTOAFS(vp);
1243 osi_Assert(OSI_GET_LOCKID() == avc->vc_rwlockid);
1244 if (avc->vc_locktrips > 0) {
1245 --avc->vc_locktrips;
1248 avc->vc_rwlockid = OSI_NO_LOCKID;
1249 vsema(&avc->vc_rwlock);
1253 /* The flag argument is for symmetry with the afs_rwlock and afs_rwunlock
1254 * calls. SGI currently only uses the flag to assert if the unlock flag
1255 * does not match the corresponding lock flag. But they may start using this
1256 * flag for a real rw lock at some time.
1259 afs_rwlock_nowait(vnode_t * vp, AFS_RWLOCK_T flag)
1261 struct vcache *avc = VTOAFS(vp);
1264 if (OSI_GET_LOCKID() == avc->vc_rwlockid) {
1265 avc->vc_locktrips++;
1268 if (cpsema(&avc->vc_rwlock)) {
1269 avc->vc_rwlockid = OSI_GET_LOCKID();
1275 #if defined(AFS_SGI64_ENV) && defined(CKPT) && !defined(_R5000_CVT_WAR)
1277 afs_fid2(OSI_VC_DECL(avc), struct fid *fidp)
1280 afs_fid2_t *afid = (afs_fid2_t *) fidp;
1281 OSI_VC_CONVERT(avc);
1283 osi_Assert(sizeof(fid_t) >= sizeof(afs_fid2_t));
1284 afid->af_len = sizeof(afs_fid2_t) - sizeof(afid->af_len);
1286 tcell = afs_GetCell(avc->f.fid.Cell, READ_LOCK);
1287 afid->af_cell = tcell->cellIndex & 0xffff;
1288 afs_PutCell(tcell, READ_LOCK);
1290 afid->af_volid = avc->f.fid.Fid.Volume;
1291 afid->af_vno = avc->f.fid.Fid.Vnode;
1292 afid->af_uniq = avc->f.fid.Fid.Unique;
1297 /* Only use so far is in checkpoint/restart for IRIX 6.4. In ckpt_fid, a
1298 * return of ENOSYS would make the code fail over to VOP_FID. We can't let
1299 * that happen, since we do a VN_HOLD there in the expectation that
1300 * posthandle will be called to release the vnode.
1302 * afs_fid2 is used to support the R5000 workarounds (_R5000_CVT_WAR)
1305 afs_fid2(OSI_VC_DECL(avc), struct fid *fidp)
1307 #if defined(_R5000_CVT_WAR)
1308 extern int R5000_cvt_war;
1318 #endif /* AFS_SGI64_ENV && CKPT */
1322 * check for any pages hashed that shouldn't be!
1323 * Only valid if PGCACHEDEBUG is set in os/page.c
1324 * Drop the global lock here, since we may not actually do the call.
1327 afs_chkpgoob(vnode_t * vp, pgno_t pgno)
1332 pfindanyoob(vp, pgno);
1340 #ifdef AFS_SGI64_ENV
1341 #define AFS_MP_VC_ARG(A) bhv_desc_t A
1343 #define AFS_MP_VC_ARG(A) vnode_t A
1346 #ifdef AFS_SGI64_ENV
1348 mp_afs_open(bhv_desc_t * bhp, vnode_t ** a, mode_t b, struct cred *c)
1351 mp_afs_open(vnode_t ** a, mode_t b, struct cred *c)
1356 #ifdef AFS_SGI64_ENV
1357 rv = afs_lockedvnodeops.vop_open(bhp, a, b, c);
1359 rv = afs_lockedvnodeops.vop_open(a, b, c);
1365 #if defined(AFS_SGI64_ENV)
1366 #if defined(AFS_SGI65_ENV)
1368 mp_afs_close(AFS_MP_VC_ARG(*a), int b, lastclose_t c, struct cred *d)
1371 mp_afs_close(AFS_MP_VC_ARG(*a), int b, lastclose_t c, off_t d, struct cred *e,
1376 mp_afs_close(AFS_MP_VC_ARG(*a), int b, lastclose_t c, off_t d, struct cred *e)
1381 rv = afs_lockedvnodeops.vop_close(a, b, c, d
1382 #if !defined(AFS_SGI65_ENV)
1384 #if defined(AFS_SGI64_ENV)
1394 #ifdef AFS_SGI64_ENV
1396 mp_afs_read(AFS_MP_VC_ARG(*a), struct uio *b, int c, struct cred *d,
1400 mp_afs_read(AFS_MP_VC_ARG(*a), struct uio *b, int c, struct cred *d)
1405 #ifdef AFS_SGI64_ENV
1406 rv = afs_lockedvnodeops.vop_read(a, b, c, d, f);
1408 rv = afs_lockedvnodeops.vop_read(a, b, c, d);
1415 #ifdef AFS_SGI64_ENV
1417 mp_afs_write(AFS_MP_VC_ARG(*a), struct uio *b, int c, struct cred *d,
1421 mp_afs_write(AFS_MP_VC_ARG(*a), struct uio *b, int c, struct cred *d)
1426 #ifdef AFS_SGI64_ENV
1427 rv = afs_lockedvnodeops.vop_write(a, b, c, d, f);
1429 rv = afs_lockedvnodeops.vop_write(a, b, c, d);
1436 mp_afs_ioctl(AFS_MP_VC_ARG(*a), int b, void *c, int d, struct cred *e, int *f
1437 #ifdef AFS_SGI65_ENV
1438 , struct vopbd *vbds
1444 rv = afs_lockedvnodeops.vop_ioctl(a, b, c, d, e, f
1445 #ifdef AFS_SGI65_ENV
1454 mp_fs_setfl(AFS_MP_VC_ARG(*a), int b, int c, struct cred *d)
1458 rv = afs_lockedvnodeops.vop_setfl(a, b, c, d);
1464 mp_afs_getattr(AFS_MP_VC_ARG(*a), struct vattr *b, int c, struct cred *d)
1468 rv = afs_lockedvnodeops.vop_getattr(a, b, c, d);
1474 mp_afs_setattr(AFS_MP_VC_ARG(*a), struct vattr *b, int c, struct cred *d)
1478 rv = afs_lockedvnodeops.vop_setattr(a, b, c, d);
1484 mp_afs_access(AFS_MP_VC_ARG(*a), int b,
1485 #ifndef AFS_SGI65_ENV
1492 rv = afs_lockedvnodeops.vop_access(a, b,
1493 #ifndef AFS_SGI65_ENV
1502 mp_afs_lookup(AFS_MP_VC_ARG(*a), char *b, vnode_t ** c, struct pathname *d,
1503 int e, vnode_t * f, struct cred *g)
1507 rv = afs_lockedvnodeops.vop_lookup(a, b, c, d, e, f, g);
1512 #ifdef AFS_SGI64_ENV
1514 mp_afs_create(AFS_MP_VC_ARG(*a), char *b, struct vattr *c, int d, int e,
1515 vnode_t ** f, struct cred *g)
1518 mp_afs_create(AFS_MP_VC_ARG(*a), char *b, struct vattr *c, enum vcexcl d,
1519 int e, vnode_t ** f, struct cred *g)
1524 rv = afs_lockedvnodeops.vop_create(a, b, c, d, e, f, g);
1530 mp_afs_remove(AFS_MP_VC_ARG(*a), char *b, struct cred *c)
1534 rv = afs_lockedvnodeops.vop_remove(a, b, c);
1540 mp_afs_link(AFS_MP_VC_ARG(*a), vnode_t * b, char *c, struct cred *d)
1544 rv = afs_lockedvnodeops.vop_link(a, b, c, d);
1550 mp_afs_rename(AFS_MP_VC_ARG(*a), char *b, vnode_t * c, char *d,
1551 struct pathname *e, struct cred *f)
1555 rv = afs_lockedvnodeops.vop_rename(a, b, c, d, e, f);
1561 mp_afs_mkdir(AFS_MP_VC_ARG(*a), char *b, struct vattr *c, vnode_t ** d,
1566 rv = afs_lockedvnodeops.vop_mkdir(a, b, c, d, e);
1572 mp_afs_rmdir(AFS_MP_VC_ARG(*a), char *b, vnode_t * c, struct cred *d)
1576 rv = afs_lockedvnodeops.vop_rmdir(a, b, c, d);
1582 mp_afs_readdir(AFS_MP_VC_ARG(*a), struct uio *b, struct cred *c, int *d)
1586 rv = afs_lockedvnodeops.vop_readdir(a, b, c, d);
1592 mp_afs_symlink(AFS_MP_VC_ARG(*a), char *b, struct vattr *c, char *d,
1597 rv = afs_lockedvnodeops.vop_symlink(a, b, c, d, e);
1603 mp_afs_readlink(AFS_MP_VC_ARG(*a), struct uio *b, struct cred *c)
1607 rv = afs_lockedvnodeops.vop_readlink(a, b, c);
1613 mp_afs_fsync(AFS_MP_VC_ARG(*a), int b, struct cred *c
1614 #ifdef AFS_SGI65_ENV
1615 , off_t start, off_t stop
1621 rv = afs_lockedvnodeops.vop_fsync(a, b, c
1622 #ifdef AFS_SGI65_ENV
1631 mp_afs_inactive(AFS_MP_VC_ARG(*a), struct cred *b)
1634 afs_lockedvnodeops.vop_inactive(a, b);
1640 mp_afs_fid(AFS_MP_VC_ARG(*a), struct fid **b)
1644 rv = afs_lockedvnodeops.vop_fid(a, b);
1650 mp_afs_fid2(AFS_MP_VC_ARG(*a), struct fid *b)
1654 rv = afs_lockedvnodeops.vop_fid2(a, b);
1660 mp_afs_rwlock(AFS_MP_VC_ARG(*a), AFS_RWLOCK_T b)
1663 afs_rwlock(a, VRWLOCK_WRITE);
1668 mp_afs_rwunlock(AFS_MP_VC_ARG(*a), AFS_RWLOCK_T b)
1671 afs_rwunlock(a, VRWLOCK_WRITE);
1676 mp_afs_seek(AFS_MP_VC_ARG(*a), off_t b, off_t * c)
1680 rv = afs_lockedvnodeops.vop_seek(a, b, c);
1686 mp_fs_cmp(AFS_MP_VC_ARG(*a), vnode_t * b)
1690 rv = afs_lockedvnodeops.vop_cmp(a, b);
1696 mp_afs_frlock(AFS_MP_VC_ARG(*a), int b, struct flock *c, int d, off_t e,
1697 #ifdef AFS_SGI65_ENV
1704 rv = afs_lockedvnodeops.vop_frlock(a, b, c, d, e,
1705 #ifdef AFS_SGI65_ENV
1714 mp_afs_realvp(AFS_MP_VC_ARG(*a), vnode_t ** b)
1718 rv = afs_lockedvnodeops.vop_realvp(a, b);
1724 mp_afs_bmap(AFS_MP_VC_ARG(*a), off_t b, ssize_t c, int d, struct cred *e,
1725 struct bmapval *f, int *g)
1729 rv = afs_lockedvnodeops.vop_bmap(a, b, c, d, e, f, g);
1735 mp_afs_strategy(AFS_MP_VC_ARG(*a), struct buf *b)
1739 afs_lockedvnodeops.vop_strategy(a, b);
1744 #ifdef AFS_SGI65_ENV
1746 mp_afs_map(AFS_MP_VC_ARG(*a), off_t b, size_t c, mprot_t d, u_int e,
1747 struct cred *f, vnode_t ** g)
1750 mp_afs_map(AFS_MP_VC_ARG(*a), off_t b, struct pregion *c, char **d, size_t e,
1751 u_int f, u_int g, u_int h, struct cred *i)
1756 rv = afs_lockedvnodeops.vop_map(a, b, c, d, e, f, g
1757 #ifndef AFS_SGI65_ENV
1766 #ifndef AFS_SGI65_ENV
1767 /* As of Irix 6.5, addmap and delmap are only for devices */
1769 mp_afs_addmap(AFS_MP_VC_ARG(*a), off_t b, struct pregion *c, addr_t d,
1770 size_t e, u_int f, u_int g, u_int h, struct cred *i)
1774 rv = afs_lockedvnodeops.vop_addmap(a, b, c, d, e, f, g, h, i);
1780 mp_afs_delmap(AFS_MP_VC_ARG(*a), off_t b, struct pregion *c, addr_t d,
1781 size_t e, u_int f, u_int g, u_int h, struct cred *i)
1785 rv = afs_lockedvnodeops.vop_delmap(a, b, c, d, e, f, g, h, i);
1789 #endif /* ! AFS_SGI65_ENV */
1792 mp_fs_poll(AFS_MP_VC_ARG(*a), short b, int c, short *d, struct pollhead **e
1793 #ifdef AFS_SGI65_ENV
1800 rv = afs_lockedvnodeops.vop_poll(a, b, c, d, e
1801 #ifdef AFS_SGI65_ENV
1810 struct vnodeops Afs_vnodeops = {
1811 #ifdef AFS_SGI64_ENV
1812 #ifdef AFS_SGI65_ENV
1813 BHV_IDENTITY_INIT_POSITION(VNODE_POSITION_BASE),
1815 VNODE_POSITION_BASE,
1846 fs_nosys, /* realvp */
1850 #ifdef AFS_SGI65_ENV
1851 fs_noerr, /* addmap - devices only */
1852 fs_noerr, /* delmap - devices only */
1857 mp_fs_poll, /* poll */
1858 fs_nosys, /* dump */
1860 fs_nosys, /* allocstore */
1861 fs_nosys, /* fcntl */
1862 afs_reclaim, /* reclaim */
1863 fs_nosys, /* attr_get */
1864 fs_nosys, /* attr_set */
1865 fs_nosys, /* attr_remove */
1866 fs_nosys, /* attr_list */
1867 #ifdef AFS_SGI64_ENV
1868 #ifdef AFS_SGI65_ENV
1870 (vop_link_removed_t) fs_noval,
1873 fs_flushinval_pages,
1877 (vop_commit_t) fs_nosys,
1878 (vop_readbuf_t) fs_nosys,
1886 struct vnodeops *afs_ops = &Afs_vnodeops;
1890 /* Support for XFS caches. The assumption here is that the size of
1891 * a cache file also does not exceed 32 bits.
1894 /* Initialized in osi_InitCacheFSType(). Used to determine inode type. */
1895 vnodeops_t *afs_xfs_vnodeopsp;
1897 extern afs_lock_t afs_xosi; /* lock is for tvattr */
1900 VnodeToIno(vnode_t * vp)
1905 ObtainWriteLock(&afs_xosi, 579);
1906 vattr.va_mask = AT_FSID | AT_NODEID; /* quick return using this mask. */
1908 AFS_VOP_GETATTR(vp, &vattr, 0, OSI_GET_CURRENT_CRED(), code);
1911 osi_Panic("VnodeToIno");
1913 ReleaseWriteLock(&afs_xosi);
1914 return vattr.va_nodeid;
1918 VnodeToDev(vnode_t * vp)
1923 ObtainWriteLock(&afs_xosi, 580);
1924 vattr.va_mask = AT_FSID | AT_NODEID; /* quick return using this mask. */
1926 AFS_VOP_GETATTR(vp, &vattr, 0, OSI_GET_CURRENT_CRED(), code);
1929 osi_Panic("VnodeToDev");
1931 ReleaseWriteLock(&afs_xosi);
1932 return (dev_t) vattr.va_fsid;
1936 VnodeToSize(vnode_t * vp)
1941 ObtainWriteLock(&afs_xosi, 581);
1942 vattr.va_mask = AT_SIZE;
1944 AFS_VOP_GETATTR(vp, &vattr, 0, OSI_GET_CURRENT_CRED(), code);
1947 osi_Panic("VnodeToSize");
1949 ReleaseWriteLock(&afs_xosi);
1950 return vattr.va_size;
1952 #endif /* AFS_SGI62_ENV */