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
15 #include "../afs/param.h" /* Should be always first */
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"
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.
26 #define AFSBSIZE _PAGESZ
27 extern struct afs_exporter *root_exported;
28 extern void afs_chkpgoob(vnode_t *, pgno_t);
30 static void afs_strategy();
31 static int afs_xread(), afs_xwrite();
32 static int afs_xbmap(), afs_map(), afs_reclaim();
34 static int afs_addmap(), afs_delmap();
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);
43 extern int afs_xinactive();
45 extern void afs_xinactive();
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);
51 extern int afs_fid2();
53 static int afsrwvp(register struct vcache *avc,
54 register struct uio *uio,
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 =
68 struct vnodeops Afs_vnodeops =
73 BHV_IDENTITY_INIT_POSITION(VNODE_POSITION_BASE),
106 fs_nosys, /* realvp */
111 fs_noerr, /* addmap - devices only */
112 fs_noerr, /* delmap - devices only */
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 */
130 (vop_link_removed_t)fs_noval,
137 (vop_commit_t)fs_nosys,
138 (vop_readbuf_t)fs_nosys,
147 struct vnodeops *afs_ops = &Afs_vnodeops;
150 int afs_frlock(OSI_VN_DECL(vp), int cmd, struct flock *lfp, int flag,
162 get_current_flid(&flid);
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 ...
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
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);
183 error = fs_frlock(OSI_VN_ARG(vp), cmd, lfp, flag, offset,
186 error = fs_frlock(vp, cmd, lfp, flag, offset, cr);
189 AFS_RWUNLOCK(vp, VRWLOCK_WRITE);
190 if (error || cmd != F_GETLK)
192 if (lfp->l_type != F_UNLCK)
193 /* found some blocking lock */
195 /* fall through to check for full AFS file locks */
198 /* map BSD style to plain - we don't call reclock()
199 * and its only there that the difference is important
223 error = convoff(vp, lfp, 0, offset
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....
264 static int afs_xread(OSI_VC_ARG(avc), uiop, ioflag, cr, flp)
267 static int afs_xread(OSI_VC_ARG(avc), uiop, ioflag, cr)
277 osi_Assert(avc->v.v_count > 0);
278 if (avc->v.v_type != VREG)
283 if (!(ioflag & IO_ISLOCKED))
284 AFS_RWLOCK((vnode_t*)avc, VRWLOCK_READ);
286 code = afsrwvp(avc, uiop, UIO_READ, ioflag, cr, flp);
288 if (!(ioflag & IO_ISLOCKED))
289 AFS_RWUNLOCK((vnode_t*)avc, VRWLOCK_READ);
292 code = afsrwvp(avc, uiop, UIO_READ, ioflag, cr);
299 static int afs_xwrite(OSI_VC_ARG(avc), uiop, ioflag, cr, flp)
302 static int afs_xwrite(OSI_VC_ARG(avc), uiop, ioflag, cr)
312 osi_Assert(avc->v.v_count > 0);
313 if (avc->v.v_type != VREG)
316 if (ioflag & IO_APPEND)
317 uiop->uio_offset = avc->m.Length;
320 if (!(ioflag & IO_ISLOCKED))
321 AFS_RWLOCK(((vnode_t*)avc), VRWLOCK_WRITE);
323 code = afsrwvp(avc, uiop, UIO_WRITE, ioflag, cr, flp);
325 if (!(ioflag & IO_ISLOCKED))
326 AFS_RWUNLOCK((vnode_t*)avc, VRWLOCK_WRITE);
329 code = afsrwvp(avc, uiop, UIO_WRITE, ioflag, cr);
335 static int prnra = 0;
336 static int acchk = 0;
337 static int acdrop = 0;
339 static int afsrwvp(register struct vcache *avc,
340 register struct uio *uio,
350 register struct vnode *vp = (struct vnode *)avc;
355 ssize_t bsize, rem, len;
357 struct bmapval bmv[2];
358 int nmaps, didFakeOpen = 0;
359 struct vrequest treq;
363 osi_Assert((valusema(&avc->vc_rwlock) <= 0) &&
364 (OSI_GET_LOCKID() == avc->vc_rwlockid));
367 newoff = uio->uio_resid + uio->uio_offset;
368 if (uio->uio_resid <= 0) {
371 if (uio->uio_offset < 0
372 || (signed long)newoff < 0) {
375 if (ioflag & IO_DIRECT)
378 if (rw == UIO_WRITE && vp->v_type == VREG
379 && newoff > uio->uio_limit) {
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);
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);
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) {
399 if (!afs_AccessOK(avc, PRSFS_READ, &treq,
400 CHECK_MODE_BITS|CMB_ALLOW_EXEC_AS_READ))
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
408 if (rw == UIO_WRITE || (rw == UIO_READ && avc->cred == NULL)) {
409 ObtainWriteLock(&avc->lock,92);
414 ReleaseWriteLock(&avc->lock);
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.
422 if (root_exported && rw == UIO_WRITE) {
423 ObtainWriteLock(&avc->lock,234);
428 ReleaseWriteLock(&avc->lock);
432 if (rw == UIO_WRITE) {
433 ObtainWriteLock(&avc->lock,330);
434 avc->states |= CDirty;
435 ReleaseWriteLock(&avc->lock);
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
447 while (VN_GET_DPAGES(vp))
451 error = avc->vc_error;
454 bsize = AFSBSIZE; /* why not?? */
455 off = uio->uio_offset % bsize;
456 bn = BTOBBT(uio->uio_offset - off);
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.
469 if (rw == UIO_READ) {
471 * read/paging in a normal file
473 rem = avc->m.Length - (afs_int32)uio->uio_offset;
478 * compute minimum of rest of block and rest of file
480 cnt = MIN(bsize - off, rem);
481 osi_Assert((off + cnt) <= bsize);
482 bsize = ctob(btoc(off + cnt));
485 bmv[0].bn = bmv[0].offset = bn;
487 bmv[0].bsize = bsize;
489 bmv[0].pbsize = MIN(cnt, uio->uio_resid);
492 bmv[0].pbdev = vp->v_rdev;
493 bmv[0].pmp = uio->uio_pmp;
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
504 if ((avc->lastr + BTOBB(AFSBSIZE) == bn ||
505 uio->uio_resid > AFSBSIZE)
507 && (!AFS_VN_MAPPED(vp))
508 #else /* AFS_SGI61_ENV */
509 && ((vp->v_flag & VWASMAP) == 0)
510 #endif /* AFS_SGI61_ENV */
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));
523 bmv[1].bsize = bsize;
525 bmv[1].pbsize = acnt;
527 bmv[1].pmp = uio->uio_pmp;
528 bmv[1].pbdev = vp->v_rdev;
534 printf("NRA:vp 0x%x lastr %d bn %d len %d cnt %d bsize %d rem %d resid %d\n",
536 len, cnt, bsize, rem,
541 bp = chunkread(vp, bmv, nmaps, cr);
543 * If at a chunk boundary, start prefetch of next chunk.
545 if (counter == 0 || AFS_CHUNKOFFSET(off) == 0) {
547 ObtainWriteLock(&avc->lock,562);
548 tdc = afs_FindDCache(avc, off);
550 if (!(tdc->flags & DFNextStarted))
551 afs_PrefetchChunk(avc, tdc, cr, &treq);
554 ReleaseWriteLock(&avc->lock);
560 * writing a normal file
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.
567 if (counter > 0 && AFS_CHUNKOFFSET(uio->uio_offset) == 0) {
569 ObtainWriteLock(&avc->lock,90);
570 error = afs_DoPartialWrite(avc, &treq);
572 avc->states |= CDirty;
573 ReleaseWriteLock(&avc->lock);
579 cnt = MIN(bsize - off, uio->uio_resid);
580 bsize = ctob(btoc(off + cnt));
586 bmv[0].bsize = bsize;
590 bmv[0].pmp = uio->uio_pmp;
594 bp = getchunk(vp, bmv, cr);
596 bp = chunkread(vp, bmv, 1, cr);
598 avc->m.Date = osi_Time(); /* Set file date (for ranlib) */
600 if (bp->b_flags & B_ERROR) {
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
607 error = (unsigned char)(bp->b_error);
611 if (acchk && error) {
612 cmn_err(CE_WARN, "bp 0x%x has error %d\n", bp, error);
621 osi_Assert(bp->b_error == 0);
623 if (uio->uio_segflg != UIO_NOSPACE)
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) {
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
637 if (avc->m.Length < (afs_int32)uio->uio_offset) {
639 ObtainWriteLock(&avc->lock,235);
640 avc->m.Length = uio->uio_offset;
641 ReleaseWriteLock(&avc->lock);
644 if (uio->uio_fmode & FSYNC) {
646 } else if (off + cnt < bsize) {
647 bawrite(bp); /* was bdwrite */
649 bp->b_flags |= B_AGE;
653 * Since EIO on an unlinked file is non-intuitive - give some
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);
662 } while (!error && uio->uio_resid > 0);
663 afs_chkpgoob(&avc->v, btoc(avc->m.Length));
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);
675 if (((ioflag & IO_SYNC) || (ioflag & IO_DSYNC)) && (rw == UIO_WRITE) &&
676 !AFS_NFSXLATORREQ(cr)) {
677 error = afs_fsync(avc, 0, cr);
679 #else /* AFS_SGI61_ENV */
680 if ((ioflag & IO_SYNC) && (rw == UIO_WRITE) && !AFS_NFSXLATORREQ(cr)) {
681 error = afs_fsync(avc, 0, cr);
683 #endif /* AFS_SGI61_ENV */
686 ObtainWriteLock(&avc->lock,236);
687 afs_FakeClose(avc, cr); /* XXXX For nfs trans XXXX */
688 ReleaseWriteLock(&avc->lock);
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);
697 int afs_xbmap(OSI_VC_ARG(avc), offset, count, flag, cr, bmv, nbmv)
706 int bsize; /* server's block size in bytes */
712 off = offset % bsize; /* offset into block */
713 bmv->bn = BTOBBT(offset - off);
714 bmv->offset = bmv->bn;
716 rem = avc->m.Length - offset;
720 cnt = MIN(bsize - off, rem);
723 * It is benign to ignore *nbmv > 1, since it is only for requesting
728 * Don't map more than up to next page if at end of file
729 * See comment in afsrwvp
731 osi_Assert((off + cnt) <= bsize);
732 bsize = ctob(btoc(off + cnt));
733 bmv->pbsize = MIN(cnt, count);
737 bmv->pbdev = avc->v.v_rdev;
740 bmv->length = BTOBBT(bsize);
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.
753 afs_strategy(OSI_VC_ARG(avc), bp)
763 vnode_t *vp = (vnode_t *)avc;
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
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
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);
793 bp->b_flags |= B_ERROR;
797 if (bp->b_error != 0)
798 printf("WARNING: afs_strategy3 vp=%x, bp=%x, err=%x\n", vp, bp, bp->b_error);
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
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 */
811 bzero(c, bp->b_bcount);
813 ReleaseReadLock(&avc->lock);
816 } else if ((avc->states & CWritingUFS) && (bp->b_flags & B_DELWRI)) {
818 ReleaseReadLock(&avc->lock);
825 ReleaseReadLock(&avc->lock);
827 aiovec.iov_base = bp_mapin(bp);
828 uio->uio_iov = &aiovec;
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 */
838 if (bp->b_flags & B_READ) {
839 uio->uio_fmode = FREAD;
840 error = afs_read(vp, uio, cr, 0, 0, 0);
842 uio->uio_fmode = FWRITE;
843 error = afs_write(vp, uio, 0, cr, 0);
848 if (acchk && error) {
849 cmn_err(CE_WARN, "vp 0x%x has error %d\n", vp, error);
856 bp->b_flags |= B_ERROR;
857 if ((uio->uio_fmode == FWRITE) && !avc->vc_error)
858 avc->vc_error = error;
865 static int afs_seek(OSI_VC_ARG(avc), ooff, noffp)
870 return *noffp < 0 ? EINVAL : 0;
873 #if !defined(AFS_SGI65_ENV)
874 /* Irix 6.5 uses addmap/delmap only for devices. */
876 static int afs_addmap(OSI_VC_ARG(avc), off, prp, addr, len, prot, maxprot,
888 struct vnode *vp = (struct vnode*)avc;
890 if (vp->v_flag & VNOMAP)
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++;
900 ReleaseWriteLock(&avc->lock);
902 avc->mapcnt += btoc(len);
903 AFS_RWUNLOCK(vp, VRWLOCK_WRITE);
908 static int afs_delmap(OSI_VC_ARG(avc), off, prp, addr, len, prot, maxprot,
920 struct vnode *vp = (struct vnode*)avc;
921 register struct brequest *tb;
922 struct vrequest treq;
925 if (vp->v_flag & VNOMAP)
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);
940 PTOSSVP(vp, (off_t)0, (off_t)MAXLONG);
942 ReleaseWriteLock(&avc->lock);
947 afs_InitReq(&treq, acred);
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
957 if (code == VNOVNODE)
960 afs_StoreWarn(code, avc->fid.Fid.Volume, /* /dev/console */ 1);
962 code = afs_CheckCode(code, &treq, 52);
963 AFS_RWUNLOCK(vp, VRWLOCK_WRITE);
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,
970 /* sleep waiting for the store to start, then retrieve error code */
971 while ((tb->flags & BUVALID) == 0) {
979 AFS_RWUNLOCK(vp, VRWLOCK_WRITE);
983 #endif /* ! AFS_SGI65_ENV */
988 * Note - if mapping in an ELF interpreter, one can get called without vp
989 * ever having been 'opened'
992 static int afs_map(OSI_VC_ARG(avc), off, len, prot, flags, cr, vpp)
1001 static int afs_map(OSI_VC_ARG(avc), off, prp, addrp, len, prot, maxprot,
1005 struct pregion *prp;
1008 u_int prot, maxprot;
1014 struct vnode *vp = (struct vnode*)avc;
1015 struct vrequest treq;
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);
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.
1029 AFS_RWLOCK(vp, VRWLOCK_WRITE);
1030 ObtainWriteLock(&avc->lock, 501);
1031 if (avc->execsOrWriters > 0) {
1032 avc->execsOrWriters ++;
1034 avc->mapcnt ++; /* count eow's due to mappings. */
1036 ReleaseWriteLock(&avc->lock);
1037 AFS_RWUNLOCK(vp, VRWLOCK_WRITE);
1039 AFS_RWLOCK(vp, VRWLOCK_WRITE);
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);
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,
1050 ICL_TYPE_POINTER, *addrp,
1052 ICL_TYPE_INT32, len, ICL_TYPE_INT32, off);
1057 extern afs_rwlock_t afs_xvcache;
1058 extern afs_lock_t afs_xdcache;
1059 #ifdef AFS_SGI64_ENV
1064 afs_xinactive(OSI_VC_ARG(avc), acred)
1066 struct ucred *acred;
1070 vnode_t *vp = (vnode_t *)avc;
1071 int mapcnt = avc->mapcnt; /* We just clear off this many. */
1073 AFS_STATCNT(afs_inactive);
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;
1080 #ifdef AFS_SGI64_ENV
1081 return VN_INACTIVE_CACHE;
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
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.
1097 if (!afs_rwlock_nowait((vnode_t*)avc, VRWLOCK_WRITE)) {
1098 return VN_INACTIVE_CACHE;
1100 if (NBObtainWriteLock(&avc->lock, 502)) {
1101 AFS_RWUNLOCK(vp, VRWLOCK_WRITE);
1102 return VN_INACTIVE_CACHE;
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);
1110 ReleaseWriteLock(&avc->lock);
1111 AFS_RWUNLOCK(vp, VRWLOCK_WRITE);
1112 afs_remunlink(avc, 1); /* ignore any return code */
1114 return VN_INACTIVE_CACHE;
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
1123 struct vrequest treq;
1124 if (!afs_InitReq(&treq, acred)) {
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)
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,
1143 afs_InvalidateAllSegments(avc, 1);
1147 code = (vp->v_count == 0);
1149 /* If the vnode is now in use by someone else, return early. */
1151 ReleaseWriteLock(&avc->lock);
1152 AFS_RWUNLOCK(vp, VRWLOCK_WRITE);
1153 return VN_INACTIVE_CACHE;
1159 osi_Assert((avc->states & (CCore|CMAPPED)) == 0);
1165 ReleaseWriteLock(&avc->lock);
1166 AFS_RWUNLOCK(vp, VRWLOCK_WRITE);
1169 * If someone unlinked a file and this is the last hurrah -
1170 * nuke all the pages.
1172 if (avc->m.LinkCount == 0) {
1174 PTOSSVP(vp, (off_t)0, (off_t)MAXLONG);
1178 #ifndef AFS_SGI65_ENV
1179 osi_Assert(avc->mapcnt == 0);
1180 afs_chkpgoob(&avc->v, btoc(avc->m.Length));
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;
1187 afs_remunlink(avc, 1); /* ignore any return code */
1191 #ifdef AFS_SGI64_ENV
1192 return VN_INACTIVE_CACHE;
1197 afs_reclaim(OSI_VC_DECL(avc), int flag)
1199 #ifdef AFS_SGI64_ENV
1200 /* Get's called via VOP_RELCAIM in afs_FlushVCache to clear repl_vnodeops*/
1203 panic("afs_reclaim");
1207 void afs_rwlock(OSI_VN_DECL(vp), AFS_RWLOCK_T flag)
1210 struct vcache *avc = (struct vcache *)vp;
1212 if (OSI_GET_LOCKID() == avc->vc_rwlockid) {
1213 avc->vc_locktrips++;
1217 psema(&avc->vc_rwlock, PINOD);
1219 avc->vc_rwlockid = OSI_GET_LOCKID();
1222 void afs_rwunlock(OSI_VN_DECL(vp), AFS_RWLOCK_T flag)
1225 struct vcache *avc = (struct vcache *)vp;
1228 osi_Assert(OSI_GET_LOCKID() == avc->vc_rwlockid);
1229 if (avc->vc_locktrips > 0) {
1230 --avc->vc_locktrips;
1233 avc->vc_rwlockid = OSI_NO_LOCKID;
1234 vsema(&avc->vc_rwlock);
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.
1243 int afs_rwlock_nowait(vnode_t *vp, AFS_RWLOCK_T flag)
1245 struct vcache *avc = (struct vcache *)vp;
1248 if (OSI_GET_LOCKID() == avc->vc_rwlockid) {
1249 avc->vc_locktrips++;
1252 if (cpsema(&avc->vc_rwlock)) {
1253 avc->vc_rwlockid = OSI_GET_LOCKID();
1259 #if defined(AFS_SGI64_ENV) && defined(CKPT)
1260 int afs_fid2(OSI_VC_DECL(avc), struct fid *fidp)
1263 afs_fid2_t *afid = (afs_fid2_t*)fidp;
1266 osi_Assert(sizeof(fid_t) >= sizeof(afs_fid2_t));
1267 afid->af_len = sizeof(afs_fid2_t) - sizeof(afid->af_len);
1269 tcell = afs_GetCell(avc->fid.Cell, READ_LOCK);
1270 afid->af_cell = tcell->cellIndex & 0xffff;
1271 afs_PutCell(tcell, READ_LOCK);
1273 afid->af_volid = avc->fid.Fid.Volume;
1274 afid->af_vno = avc->fid.Fid.Vnode;
1275 afid->af_uniq = avc->fid.Fid.Unique;
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.
1285 int afs_fid2(OSI_VC_DECL(avc), struct fid *fidp)
1289 #endif /* AFS_SGI64_ENV && CKPT */
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.
1298 afs_chkpgoob(vnode_t *vp, pgno_t pgno)
1303 pfindanyoob(vp, pgno);
1311 #ifdef AFS_SGI64_ENV
1312 #define AFS_MP_VC_ARG(A) bhv_desc_t A
1314 #define AFS_MP_VC_ARG(A) vnode_t A
1317 #ifdef AFS_SGI64_ENV
1318 int mp_afs_open(bhv_desc_t *bhp, vnode_t **a, mode_t b, struct cred *c)
1320 int mp_afs_open(vnode_t **a, mode_t b, struct cred *c)
1325 #ifdef AFS_SGI64_ENV
1326 rv = afs_lockedvnodeops.vop_open(bhp, a, b, c);
1328 rv = afs_lockedvnodeops.vop_open(a, b, c);
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)
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)
1342 int mp_afs_close(AFS_MP_VC_ARG (*a), int b, lastclose_t c, off_t d,
1348 rv = afs_lockedvnodeops.vop_close(a, b, c, d
1349 #if !defined(AFS_SGI65_ENV)
1351 #if defined(AFS_SGI64_ENV)
1361 #ifdef AFS_SGI64_ENV
1362 int mp_afs_read(AFS_MP_VC_ARG(*a), struct uio *b, int c, struct cred *d,
1365 int mp_afs_read(AFS_MP_VC_ARG(*a), struct uio *b, int c, struct cred *d)
1370 #ifdef AFS_SGI64_ENV
1371 rv = afs_lockedvnodeops.vop_read(a, b, c, d, f);
1373 rv = afs_lockedvnodeops.vop_read(a, b, c, d);
1380 #ifdef AFS_SGI64_ENV
1381 int mp_afs_write(AFS_MP_VC_ARG(*a), struct uio *b, int c, struct cred *d,
1384 int mp_afs_write(AFS_MP_VC_ARG(*a), struct uio *b, int c, struct cred *d)
1389 #ifdef AFS_SGI64_ENV
1390 rv = afs_lockedvnodeops.vop_write(a, b, c, d, f);
1392 rv = afs_lockedvnodeops.vop_write(a, b, c, d);
1398 int mp_afs_ioctl(AFS_MP_VC_ARG(*a), int b, void *c, int d, struct cred *e,
1400 #ifdef AFS_SGI65_ENV
1401 , struct vopbd *vbds
1407 rv = afs_lockedvnodeops.vop_ioctl(a, b, c, d, e, f
1408 #ifdef AFS_SGI65_ENV
1416 int mp_fs_setfl(AFS_MP_VC_ARG(*a), int b, int c, struct cred *d)
1420 rv = afs_lockedvnodeops.vop_setfl(a, b, c, d);
1424 int mp_afs_getattr(AFS_MP_VC_ARG(*a), struct vattr *b, int c, struct cred *d)
1428 rv = afs_lockedvnodeops.vop_getattr(a, b, c, d);
1432 int mp_afs_setattr(AFS_MP_VC_ARG(*a), struct vattr *b, int c, struct cred *d)
1436 rv = afs_lockedvnodeops.vop_setattr(a, b, c, d);
1441 int mp_afs_access(AFS_MP_VC_ARG(*a), int b,
1442 #ifndef AFS_SGI65_ENV
1449 rv = afs_lockedvnodeops.vop_access(a, b,
1450 #ifndef AFS_SGI65_ENV
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)
1463 rv = afs_lockedvnodeops.vop_lookup(a, b, c, d, e, f, g);
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)
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)
1477 rv = afs_lockedvnodeops.vop_create(a, b, c, d, e, f, g);
1481 int mp_afs_remove(AFS_MP_VC_ARG(*a), char *b, struct cred *c)
1485 rv = afs_lockedvnodeops.vop_remove(a, b, c);
1489 int mp_afs_link(AFS_MP_VC_ARG(*a), vnode_t *b, char *c, struct cred *d)
1493 rv = afs_lockedvnodeops.vop_link(a, b, c, d);
1497 int mp_afs_rename(AFS_MP_VC_ARG(*a), char *b, vnode_t *c, char *d,
1498 struct pathname *e, struct cred *f)
1502 rv = afs_lockedvnodeops.vop_rename(a, b, c, d, e, f);
1506 int mp_afs_mkdir(AFS_MP_VC_ARG(*a), char *b, struct vattr *c, vnode_t **d,
1511 rv = afs_lockedvnodeops.vop_mkdir(a, b, c, d, e);
1515 int mp_afs_rmdir(AFS_MP_VC_ARG(*a), char *b, vnode_t *c, struct cred *d)
1519 rv = afs_lockedvnodeops.vop_rmdir(a, b, c, d);
1523 int mp_afs_readdir(AFS_MP_VC_ARG(*a), struct uio *b, struct cred *c, int *d)
1527 rv = afs_lockedvnodeops.vop_readdir(a, b, c, d);
1531 int mp_afs_symlink(AFS_MP_VC_ARG(*a), char *b, struct vattr *c, char *d,
1536 rv = afs_lockedvnodeops.vop_symlink(a, b, c, d, e);
1540 int mp_afs_readlink(AFS_MP_VC_ARG(*a), struct uio *b, struct cred *c)
1544 rv = afs_lockedvnodeops.vop_readlink(a, b, c);
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
1557 rv = afs_lockedvnodeops.vop_fsync(a, b, c
1558 #ifdef AFS_SGI65_ENV
1566 void mp_afs_inactive(AFS_MP_VC_ARG(*a), struct cred *b)
1569 afs_lockedvnodeops.vop_inactive(a, b);
1573 int mp_afs_fid(AFS_MP_VC_ARG(*a), struct fid **b)
1577 rv = afs_lockedvnodeops.vop_fid(a, b);
1581 int mp_afs_fid2(AFS_MP_VC_ARG(*a), struct fid *b)
1585 rv = afs_lockedvnodeops.vop_fid2(a, b);
1589 void mp_afs_rwlock(AFS_MP_VC_ARG(*a), AFS_RWLOCK_T b)
1592 afs_rwlock(a, VRWLOCK_WRITE);
1595 void mp_afs_rwunlock(AFS_MP_VC_ARG(*a), AFS_RWLOCK_T b)
1598 afs_rwunlock(a, VRWLOCK_WRITE);
1601 int mp_afs_seek(AFS_MP_VC_ARG(*a), off_t b, off_t*c)
1605 rv = afs_lockedvnodeops.vop_seek(a, b, c);
1609 int mp_fs_cmp(AFS_MP_VC_ARG(*a), vnode_t *b)
1613 rv = afs_lockedvnodeops.vop_cmp(a, b);
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
1626 rv = afs_lockedvnodeops.vop_frlock(a, b, c, d, e,
1627 #ifdef AFS_SGI65_ENV
1635 int mp_afs_realvp(AFS_MP_VC_ARG(*a), vnode_t **b)
1639 rv = afs_lockedvnodeops.vop_realvp(a, b);
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)
1648 rv = afs_lockedvnodeops.vop_bmap(a, b, c, d, e, f, g);
1653 void mp_afs_strategy(AFS_MP_VC_ARG(*a), struct buf *b)
1657 afs_lockedvnodeops.vop_strategy(a, b);
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)
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)
1672 rv = afs_lockedvnodeops.vop_map(a, b, c, d, e, f, g
1673 #ifndef AFS_SGI65_ENV
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)
1689 rv = afs_lockedvnodeops.vop_addmap(a, b, c, d, e, f, g, h, i);
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)
1699 rv = afs_lockedvnodeops.vop_delmap(a, b, c, d, e, f, g, h, i);
1703 #endif /* ! AFS_SGI65_ENV */
1705 int mp_fs_poll(AFS_MP_VC_ARG(*a), short b, int c, short *d,
1707 #ifdef AFS_SGI65_ENV
1714 rv = afs_lockedvnodeops.vop_poll(a, b, c, d, e
1715 #ifdef AFS_SGI65_ENV
1724 struct vnodeops Afs_vnodeops = {
1725 #ifdef AFS_SGI64_ENV
1726 #ifdef AFS_SGI65_ENV
1727 BHV_IDENTITY_INIT_POSITION(VNODE_POSITION_BASE),
1729 VNODE_POSITION_BASE,
1760 fs_nosys, /* realvp */
1764 #ifdef AFS_SGI65_ENV
1765 fs_noerr, /* addmap - devices only */
1766 fs_noerr, /* delmap - devices only */
1771 mp_fs_poll, /* poll */
1772 fs_nosys, /* dump */
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
1784 (vop_link_removed_t)fs_noval,
1787 fs_flushinval_pages,
1791 (vop_commit_t)fs_nosys,
1792 (vop_readbuf_t)fs_nosys,
1800 struct vnodeops *afs_ops = &Afs_vnodeops;
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.
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);
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 */
1818 extern afs_lock_t afs_xosi; /* lock is for tvattr */
1820 /* Initialize the cache operations. Called while initializing cache files. */
1821 void afs_InitDualFSCacheOps(struct vnode *vp)
1823 static int inited = 0;
1832 #ifdef AFS_SGI_EFS_IOPS_ENV
1833 swp = vfs_getvfssw("efs");
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;
1842 #endif /* AFS_SGI_EFS_IOPS_ENV */
1844 swp = vfs_getvfssw("xfs");
1846 afs_xfs_vnodeopsp = swp->vsw_vnodeops;
1848 if (vp &&vp->v_op == afs_xfs_vnodeopsp) {
1849 afs_CacheFSType = AFS_SGI_XFS_CACHE;
1850 afs_IGetVnode = afs_XFSIGetVnode;
1857 osi_Panic("osi_InitCacheFSType: Can't find fstype for vnode 0x%llx\n",
1861 ino_t VnodeToIno(vnode_t *vp)
1866 MObtainWriteLock(&afs_xosi,579);
1867 vattr.va_mask = AT_FSID|AT_NODEID; /* quick return using this mask. */
1869 AFS_VOP_GETATTR(vp, &vattr, 0, OSI_GET_CURRENT_CRED(), code);
1872 osi_Panic("VnodeToIno");
1874 MReleaseWriteLock(&afs_xosi);
1875 return vattr.va_nodeid;
1878 dev_t VnodeToDev(vnode_t *vp)
1883 MObtainWriteLock(&afs_xosi,580);
1884 vattr.va_mask = AT_FSID|AT_NODEID; /* quick return using this mask. */
1886 AFS_VOP_GETATTR(vp, &vattr, 0, OSI_GET_CURRENT_CRED(), code);
1889 osi_Panic("VnodeToDev");
1891 MReleaseWriteLock(&afs_xosi);
1892 return (dev_t)vattr.va_fsid;
1895 off_t VnodeToSize(vnode_t *vp)
1900 MObtainWriteLock(&afs_xosi,581);
1901 vattr.va_mask = AT_SIZE;
1903 AFS_VOP_GETATTR(vp, &vattr, 0, OSI_GET_CURRENT_CRED(), code);
1906 osi_Panic("VnodeToSize");
1908 MReleaseWriteLock(&afs_xosi);
1909 return vattr.va_size;
1911 #endif /* 6.2 and dual fs cache */
1912 #endif /* AFS_SGI62_ENV */