afs: more cache truncation stats
[openafs.git] / src / afs / SOLARIS / osi_vnodeops.c
index 93d717a..81147d5 100644 (file)
@@ -76,13 +76,16 @@ extern struct as kas;               /* kernel addr space */
 extern unsigned char *afs_indexFlags;
 extern afs_lock_t afs_xdcache;
 
-/* Additional vnodeops for SunOS 4.0.x */
-int afs_nfsrdwr(), afs_getpage(), afs_putpage(), afs_map();
-int afs_dump(), afs_cmp(), afs_realvp(), afs_GetOnePage();
+static int afs_nfsrdwr(struct vcache *avc, struct uio *auio, enum uio_rw arw,
+                       int ioflag, afs_ucred_t *acred);
+static int afs_GetOnePage(struct vnode *vp, u_offset_t off, u_int alen,
+                          u_int *protp, struct page *pl[], u_int plsz,
+                          struct seg *seg, caddr_t addr, enum seg_rw rw,
+                          afs_ucred_t *acred);
 
 int afs_pvn_vptrunc;
 
-int
+static int
 afs_addmap(struct vnode *avp, offset_t offset, struct as *asp, 
           caddr_t addr, int length, int prot, int maxprot, int flags, 
           afs_ucred_t *credp)
@@ -91,7 +94,7 @@ afs_addmap(struct vnode *avp, offset_t offset, struct as *asp,
     return (0);
 }
 
-int
+static int
 afs_delmap(struct vnode *avp, offset_t offset, struct as *asp, 
           caddr_t addr, int length, int prot, int maxprot, int flags, 
           afs_ucred_t *credp)
@@ -100,12 +103,11 @@ afs_delmap(struct vnode *avp, offset_t offset, struct as *asp,
     return (0);
 }
 
+static int
 #ifdef AFS_SUN510_ENV
-int
 afs_vmread(struct vnode *avp, struct uio *auio, int ioflag, 
           afs_ucred_t *acred, caller_context_t *ct)
 #else
-int
 afs_vmread(struct vnode *avp, struct uio *auio, int ioflag, 
           afs_ucred_t *acred)
 #endif
@@ -121,12 +123,11 @@ afs_vmread(struct vnode *avp, struct uio *auio, int ioflag,
 }
 
 
+static int
 #ifdef AFS_SUN510_ENV
-int
 afs_vmwrite(struct vnode *avp, struct uio *auio, int ioflag, 
            afs_ucred_t *acred, caller_context_t *ct)
 #else
-int
 afs_vmwrite(struct vnode *avp, struct uio *auio, int ioflag, 
            afs_ucred_t *acred)
 #endif
@@ -141,7 +142,7 @@ afs_vmwrite(struct vnode *avp, struct uio *auio, int ioflag,
     return code;
 }
 
-int
+static int
 afs_getpage(struct vnode *vp, offset_t off, u_int len, u_int *protp, 
            struct page *pl[], u_int plsz, struct seg *seg, caddr_t addr, 
            enum seg_rw rw, afs_ucred_t *acred)
@@ -198,7 +199,7 @@ afs_getpage(struct vnode *vp, offset_t off, u_int len, u_int *protp,
 }
 
 /* Return all the pages from [off..off+len) in file */
-int
+static int
 afs_GetOnePage(struct vnode *vp, u_offset_t off, u_int alen, u_int *protp, 
               struct page *pl[], u_int plsz, struct seg *seg, caddr_t addr, 
               enum seg_rw rw, afs_ucred_t *acred)
@@ -349,7 +350,7 @@ afs_GetOnePage(struct vnode *vp, u_offset_t off, u_int alen, u_int *protp,
 
     /* Check to see whether the cache entry is still valid */
     if (!(avc->f.states & CStatd)
-       || !hsame(avc->f.m.DataVersion, tdc->f.versionNo)) {
+       || !afs_IsDCacheFresh(tdc, avc)) {
        ReleaseReadLock(&tdc->lock);
        ReleaseReadLock(&avc->lock);
        afs_PutDCache(tdc);
@@ -463,6 +464,19 @@ afs_GetOnePage(struct vnode *vp, u_offset_t off, u_int alen, u_int *protp,
     return code;
 }
 
+/**
+ * Dummy pvn_vplist_dirty() handler for non-writable vnodes.
+ */
+static int
+afs_never_putapage(struct vnode *vp, struct page *pages, u_offset_t * offp,
+            size_t * lenp, int flags, afs_ucred_t *credp)
+{
+    struct vcache *avc = VTOAFS(vp);
+    osi_Assert((avc->f.states & CRO) != 0);
+    osi_Panic("Dirty pages while flushing a read-only volume vnode.");
+    AFS_UNREACHED(return EIO);
+}
+
 int
 afs_putpage(struct vnode *vp, offset_t off, u_int len, int flags, 
            afs_ucred_t *cred)
@@ -474,7 +488,7 @@ afs_putpage(struct vnode *vp, offset_t off, u_int len, int flags,
     afs_offs_t endPos;
     afs_int32 NPages = 0;
     u_offset_t toff = off;
-    int didWriteLock;
+    int didLock = 0;
 
     AFS_STATCNT(afs_putpage);
     if (vp->v_flag & VNOMAP)   /* file doesn't allow mapping */
@@ -488,11 +502,11 @@ afs_putpage(struct vnode *vp, offset_t off, u_int len, int flags,
               (afs_int32) vp, ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(off),
               ICL_TYPE_INT32, (afs_int32) len, ICL_TYPE_LONG, (int)flags);
     avc = VTOAFS(vp);
-    ObtainSharedLock(&avc->lock, 247);
-    didWriteLock = 0;
 
     /* Get a list of modified (or whatever) pages */
     if (len) {
+       ObtainSharedLock(&avc->lock, 247);
+       didLock = SHARED_LOCK;
        endPos = (afs_offs_t) off + len;        /* position we're supposed to write up to */
        while ((afs_offs_t) toff < endPos
               && (afs_offs_t) toff < avc->f.m.Length) {
@@ -507,9 +521,9 @@ afs_putpage(struct vnode *vp, offset_t off, u_int len, int flags,
            if (!pages || !pvn_getdirty(pages, flags))
                tlen = PAGESIZE;
            else {
-               if (!didWriteLock) {
+               if (didLock == SHARED_LOCK) {
                    AFS_GLOCK();
-                   didWriteLock = 1;
+                   didLock = WRITE_LOCK;
                    UpgradeSToWLock(&avc->lock, 671);
                    AFS_GUNLOCK();
                }
@@ -524,27 +538,50 @@ afs_putpage(struct vnode *vp, offset_t off, u_int len, int flags,
            AFS_GLOCK();
        }
     } else {
-       if (!didWriteLock) {
-           UpgradeSToWLock(&avc->lock, 670);
-           didWriteLock = 1;
+       /*
+        * We normally arrive here due to a vm flush.
+        *
+        * If this vnode belongs to a writable volume, obtain a vcache lock
+        * then call pvn_vplist_dirty to free, invalidate, or to write out
+        * dirty pages with afs_putapage.  The afs_putapage routine requires a
+        * vcache lock, so we obtain it here before any page locks are taken.
+        * This locking order is done to avoid deadlocking due to races with
+        * afs_getpage, which also takes vcache and page locks.
+        *
+        * If this vnode belongs to a non-writable volume, then it will not
+        * contain dirty pages, so we do not need to lock the vcache and since
+        * afs_putapage will not be called.  Instead, forgo the vcache lock and
+        * call pvn_vplist_dirty to free, or invalidate pages. Pass a dummy
+        * page out handler to pvn_vplist_dirty which we do not expect to be
+        * called.  Panic if the dummy handler is called, since something went
+        * horribly wrong.
+        */
+       if ((avc->f.states & CRO) == 0) {
+           ObtainWriteLock(&avc->lock, 670);
+           didLock = WRITE_LOCK;
        }
-
        AFS_GUNLOCK();
-       code = pvn_vplist_dirty(vp, toff, afs_putapage, flags, cred);
+       if ((avc->f.states & CRO) == 0)
+           code = pvn_vplist_dirty(vp, toff, afs_putapage, flags, cred);
+       else
+           code = pvn_vplist_dirty(vp, toff, afs_never_putapage, flags, cred);
        AFS_GLOCK();
     }
 
     if (code && !avc->vc_error) {
-       if (!didWriteLock) {
+       if (didLock == 0) {
+           ObtainWriteLock(&avc->lock, 668);
+           didLock = WRITE_LOCK;
+       } else if (didLock == SHARED_LOCK) {
            UpgradeSToWLock(&avc->lock, 669);
-           didWriteLock = 1;
+           didLock = WRITE_LOCK;
        }
        avc->vc_error = code;
     }
 
-    if (didWriteLock)
+    if (didLock == WRITE_LOCK)
        ReleaseWriteLock(&avc->lock);
-    else
+    else if (didLock == SHARED_LOCK)
        ReleaseSharedLock(&avc->lock);
     afs_Trace2(afs_iclSetp, CM_TRACE_PAGEOUTDONE, ICL_TYPE_LONG, code,
               ICL_TYPE_LONG, NPages);
@@ -552,7 +589,6 @@ afs_putpage(struct vnode *vp, offset_t off, u_int len, int flags,
     return (code);
 }
 
-
 int
 afs_putapage(struct vnode *vp, struct page *pages, u_offset_t * offp,
             size_t * lenp, int flags, afs_ucred_t *credp)
@@ -604,7 +640,7 @@ afs_putapage(struct vnode *vp, struct page *pages, u_offset_t * offp,
     return code;
 }
 
-int
+static int
 afs_nfsrdwr(struct vcache *avc, struct uio *auio, enum uio_rw arw,
            int ioflag, afs_ucred_t *acred)
 {
@@ -661,6 +697,8 @@ afs_nfsrdwr(struct vcache *avc, struct uio *auio, enum uio_rw arw,
           && (afs_blocksUsed > PERCENT(CM_WAITFORDRAINPCT, afs_cacheBlocks))) {
        if (afs_blocksUsed - afs_blocksDiscarded >
            PERCENT(CM_WAITFORDRAINPCT, afs_cacheBlocks)) {
+           if (afs_WaitForCacheDrain == 0)
+               afs_WaitForCacheDrainCount++;
            afs_WaitForCacheDrain = 1;
            afs_osi_Sleep(&afs_WaitForCacheDrain);
        }
@@ -823,7 +861,7 @@ afs_nfsrdwr(struct vcache *avc, struct uio *auio, enum uio_rw arw,
            afs_size_t toff, tlen;
            dcp = afs_GetDCache(avc, fileBase, &treq, &toff, &tlen, 2);
            if (!dcp) {
-               code = ENOENT;
+               code = EIO;
                break;
            }
        }
@@ -850,12 +888,12 @@ afs_nfsrdwr(struct vcache *avc, struct uio *auio, enum uio_rw arw,
                AFS_GLOCK();
                dcp_newpage = afs_FindDCache(avc, pageBase);
                if (dcp_newpage
-                   && hsame(avc->f.m.DataVersion, dcp_newpage->f.versionNo)) {
+                   && afs_IsDCacheFresh(dcp_newpage, avc)) {
                    ObtainWriteLock(&avc->lock, 251);
                    ObtainWriteLock(&avc->vlock, 576);
                    ObtainReadLock(&dcp_newpage->lock);
                    if ((avc->activeV == 0)
-                       && hsame(avc->f.m.DataVersion, dcp_newpage->f.versionNo)
+                       && afs_IsDCacheFresh(dcp_newpage, avc)
                        && !(dcp_newpage->dflags & (DFFetching))) {
                        AFS_GUNLOCK();
                        segmap_pagecreate(segkmap, raddr, rsize, 1);
@@ -930,8 +968,8 @@ afs_nfsrdwr(struct vcache *avc, struct uio *auio, enum uio_rw arw,
     }
 }
 
-int
-afs_map(struct vnode *vp, offset_t off, struct as *as, caddr_t *addr, u_int len, u_char prot, u_char maxprot, u_int flags, afs_ucred_t *cred)
+static int
+afs_map(struct vnode *vp, offset_t off, struct as *as, caddr_t *addr, size_t len, u_char prot, u_char maxprot, u_int flags, afs_ucred_t *cred)
 {
     struct segvn_crargs crargs;
     afs_int32 code;
@@ -977,7 +1015,11 @@ afs_map(struct vnode *vp, offset_t off, struct as *as, caddr_t *addr, u_int len,
     AFS_GUNLOCK();
     as_rangelock(as);
     if ((flags & MAP_FIXED) == 0) {
+#ifdef MAPADDR_LACKS_VACALIGN
+       map_addr(addr, len, off, flags);
+#else
        map_addr(addr, len, off, 1, flags);
+#endif
        if (*addr == NULL) {
            as_rangeunlock(as);
            code = ENOMEM;
@@ -987,7 +1029,7 @@ afs_map(struct vnode *vp, offset_t off, struct as *as, caddr_t *addr, u_int len,
        (void)as_unmap(as, *addr, len); /* unmap old address space use */
     /* setup the create parameter block for the call */
     crargs.vp = AFSTOV(avc);
-    crargs.offset = (u_int) off;
+    crargs.offset = (u_offset_t)off;
     crargs.cred = cred;
     crargs.type = flags & MAP_TYPE;
     crargs.prot = prot;
@@ -1013,7 +1055,7 @@ afs_map(struct vnode *vp, offset_t off, struct as *as, caddr_t *addr, u_int len,
  * For Now We use standard local kernel params for AFS system values. Change this
  * at some point.
  */
-int
+static int
 #ifdef AFS_SUN511_ENV
 afs_pathconf(struct vnode *vp, int cmd, u_long *outdatap,
             afs_ucred_t *credp, caller_context_t *ct)
@@ -1056,21 +1098,21 @@ afs_pathconf(struct vnode *vp, int cmd, u_long *outdatap,
     return 0;
 }
 
-int
+static int
 afs_ioctl(struct vnode *vnp, int com, int arg, int flag, cred_t *credp, 
          int *rvalp)
 {
     return (ENOTTY);
 }
 
-void
+static void
 afs_rwlock(struct vnode *vnp, int wlock)
 {
     rw_enter(&(VTOAFS(vnp))->rwlock, (wlock ? RW_WRITER : RW_READER));
 }
 
 
-void
+static void
 afs_rwunlock(struct vnode *vnp, int wlock)
 {
     rw_exit(&(VTOAFS(vnp))->rwlock);
@@ -1078,7 +1120,7 @@ afs_rwunlock(struct vnode *vnp, int wlock)
 
 
 /* NOT SUPPORTED */
-int
+static int
 afs_seek(struct vnode *vnp, offset_t ooff, offset_t *noffp)
 {
     int code = 0;
@@ -1094,7 +1136,7 @@ afs_seek(struct vnode *vnp, offset_t ooff, offset_t *noffp)
     return code;
 }
 
-int
+static int
 #ifdef AFS_SUN59_ENV
 afs_frlock(struct vnode *vnp, int cmd, struct flock64 *ap, int flag, 
           offset_t off, struct flk_callback *flkcb, afs_ucred_t *credp)
@@ -1130,7 +1172,7 @@ afs_frlock(struct vnode *vnp, int cmd, struct flock64 *ap, int flag,
 }
 
 
-int
+static int
 afs_space(struct vnode *vnp, int cmd, struct flock64 *ap, int flag, 
          offset_t off, afs_ucred_t *credp)
 {
@@ -1150,7 +1192,7 @@ afs_space(struct vnode *vnp, int cmd, struct flock64 *ap, int flag,
     return (code);
 }
 
-int
+static int
 afs_dump(struct vnode *vp, caddr_t addr, int i1, int i2)
 {
     AFS_STATCNT(afs_dump);
@@ -1160,7 +1202,7 @@ afs_dump(struct vnode *vp, caddr_t addr, int i1, int i2)
 
 
 /* Nothing fancy here; just compare if vnodes are identical ones */
-int
+static int
 afs_cmp(struct vnode *vp1, struct vnode *vp2)
 {
     AFS_STATCNT(afs_cmp);
@@ -1168,7 +1210,7 @@ afs_cmp(struct vnode *vp1, struct vnode *vp2)
 }
 
 
-int
+static int
 afs_realvp(struct vnode *vp, struct vnode **vpp)
 {
     AFS_STATCNT(afs_realvp);
@@ -1176,7 +1218,7 @@ afs_realvp(struct vnode *vp, struct vnode **vpp)
 }
 
 
-int
+static int
 afs_pageio(struct vnode *vp, struct page *pp, u_int ui1, u_int ui2, int i1, 
           struct cred *credp)
 {
@@ -1184,7 +1226,7 @@ afs_pageio(struct vnode *vp, struct page *pp, u_int ui1, u_int ui2, int i1,
     return EINVAL;
 }
 
-int
+static int
 #ifdef AFS_SUN59_ENV
 afs_dumpctl(struct vnode *vp, int i, int *blkp)
 #else
@@ -1196,38 +1238,38 @@ afs_dumpctl(struct vnode *vp, int i)
 }
 
 #ifdef AFS_SUN511_ENV
-extern void
+static void
 afs_dispose(struct vnode *vp, struct page *p, int fl, int dn, struct cred *cr, struct caller_context_t *ct)
 {
     fs_dispose(vp, p, fl, dn, cr,ct);
 }
 
-int
+static int
 afs_setsecattr(struct vnode *vp, vsecattr_t *vsecattr, int flag, struct cred *creds, struct caller_context_t *ct)
 {
     return ENOSYS;
 }
 
-int
+static int
 afs_getsecattr(struct vnode *vp, vsecattr_t *vsecattr, int flag, struct cred *creds, struct caller_context_t *ct)
 {
   return fs_fab_acl(vp, vsecattr, flag, creds,ct);
 }
 #else
-extern void
+static void
 afs_dispose(struct vnode *vp, struct page *p, int fl, int dn, struct cred *cr)
 {
     fs_dispose(vp, p, fl, dn, cr);
 }
 
-int
+static int
 afs_setsecattr(struct vnode *vp, vsecattr_t *vsecattr, int flag, 
               struct cred *creds)
 {
     return ENOSYS;
 }
 
-int
+static int
 afs_getsecattr(struct vnode *vp, vsecattr_t *vsecattr, int flag, struct cred *creds)
 {
     return fs_fab_acl(vp, vsecattr, flag, creds);
@@ -1235,323 +1277,141 @@ afs_getsecattr(struct vnode *vp, vsecattr_t *vsecattr, int flag, struct cred *cr
 #endif
 
 #ifdef AFS_GLOBAL_SUNLOCK
-extern int gafs_open(struct vcache **avcp, afs_int32 aflags, 
-                    afs_ucred_t *acred);
-extern int gafs_close(struct vcache *avc, afs_int32 aflags, 
-                     int count, offset_t offset, afs_ucred_t *acred);
-extern int afs_ioctl(struct vnode *vnp, int com, int arg, int flag, 
-                    cred_t *credp, int *rvalp);
-extern int gafs_access(struct vcache *avc, afs_int32 amode,
-                      int flags, afs_ucred_t *acred);
-extern int gafs_getattr(struct vcache *avc, 
-                       struct vattr *attrs, int flags, 
-                       afs_ucred_t *acred);
-extern int gafs_setattr(struct vcache *avc, 
-                       struct vattr *attrs, int flags, 
-                       afs_ucred_t *acred);
-extern int gafs_lookup(struct vcache *adp, char *aname, 
-                      struct vcache **avcp, struct pathname *pnp,
-                      int flags, struct vnode *rdir, afs_ucred_t *acred);
-extern int gafs_remove(struct vcache *adp, char *aname, 
-                      afs_ucred_t *acred);
-extern int gafs_link(struct vcache *adp, struct vcache *avc,
-                    char *aname, afs_ucred_t *acred);
-extern int gafs_rename(struct vcache *aodp, char *aname1,
-                      struct vcache *andp, char *aname2,
-                      afs_ucred_t *acred);
-extern int gafs_symlink(struct vcache *adp, char *aname, 
-                       struct vattr *attrs, char *atargetName, 
-                       afs_ucred_t *acred);
-extern int gafs_rmdir(struct vcache *adp, char *aname, 
-                     struct vnode *cdirp, afs_ucred_t *acred);
-extern int gafs_mkdir(struct vcache *adp, char *aname, 
-                     struct vattr *attrs, struct vcache **avcp, 
-                     afs_ucred_t *acred);
-extern int gafs_fsync(struct vcache *avc, int flag, afs_ucred_t *acred);
-extern int gafs_readlink(struct vcache *avc, struct uio *auio, 
-                        afs_ucred_t *acred);
-extern int gafs_readdir(struct vcache *avc, struct uio *auio,
-                       afs_ucred_t *acred, int *eofp);
-extern void gafs_inactive(struct vcache *avc, 
-                         afs_ucred_t *acred);
-extern int gafs_fid(struct vcache *avc, struct fid **fidpp);
-extern int gafs_create(struct vcache *adp, char *aname, 
-                      struct vattr *attrs, enum vcexcl aexcl, int amode, 
-                      struct vcache **avcp, afs_ucred_t *acred);
-#ifdef AFS_SUN511_ENV
-extern int afs_pathconf(struct vnode *vp, int cmd, u_long *outdatap,
-                       afs_ucred_t *credp, caller_context_t *ct);
-#else
-extern int afs_pathconf(struct vnode *vp, int cmd, u_long *outdatap,
-                       afs_ucred_t *credp);
-#endif /* AFS_SUN511_ENV */
-
-#if defined(AFS_SUN511_ENV)
-/* The following list must always be NULL-terminated */
-const fs_operation_def_t afs_vnodeops_template[] = {
-    VOPNAME_OPEN,              { .vop_open = gafs_open },
-    VOPNAME_CLOSE,             { .vop_close = gafs_close },
-    VOPNAME_READ,              { .vop_read = afs_vmread },
-    VOPNAME_WRITE,             { .vop_write = afs_vmwrite },
-    VOPNAME_IOCTL,             { .vop_ioctl = afs_ioctl },
-    VOPNAME_SETFL,             { .vop_setfl = fs_setfl },
-    VOPNAME_GETATTR,           { .vop_getattr = gafs_getattr },
-    VOPNAME_SETATTR,           { .vop_setattr = gafs_setattr },
-    VOPNAME_ACCESS,            { .vop_access = gafs_access },
-    VOPNAME_LOOKUP,            { .vop_lookup = gafs_lookup },
-    VOPNAME_CREATE,            { .vop_create = gafs_create },
-    VOPNAME_REMOVE,            { .vop_remove = gafs_remove },
-    VOPNAME_LINK,              { .vop_link = gafs_link },
-    VOPNAME_RENAME,            { .vop_rename = gafs_rename },
-    VOPNAME_MKDIR,             { .vop_mkdir = gafs_mkdir },
-    VOPNAME_RMDIR,             { .vop_rmdir = gafs_rmdir },
-    VOPNAME_READDIR,           { .vop_readdir = gafs_readdir },
-    VOPNAME_SYMLINK,           { .vop_symlink = gafs_symlink },   
-    VOPNAME_READLINK,          { .vop_readlink = gafs_readlink },
-    VOPNAME_FSYNC,             { .vop_fsync = gafs_fsync },
-    VOPNAME_INACTIVE,          { .vop_inactive = gafs_inactive },
-    VOPNAME_FID,               { .vop_fid = gafs_fid },
-    VOPNAME_RWLOCK,            { .vop_rwlock = afs_rwlock },
-    VOPNAME_RWUNLOCK,          { .vop_rwunlock = afs_rwunlock },
-    VOPNAME_SEEK,              { .vop_seek = afs_seek },
-    VOPNAME_CMP,               { .vop_cmp = afs_cmp },
-    VOPNAME_FRLOCK,            { .vop_frlock = afs_frlock },
-    VOPNAME_SPACE,             { .vop_space = afs_space },
-    VOPNAME_REALVP,            { .vop_realvp = afs_realvp },
-    VOPNAME_GETPAGE,           { .vop_getpage = afs_getpage },
-    VOPNAME_PUTPAGE,           { .vop_putpage = afs_putpage },
-    VOPNAME_MAP,               { .vop_map = afs_map },
-    VOPNAME_ADDMAP,            { .vop_addmap = afs_addmap },
-    VOPNAME_DELMAP,            { .vop_delmap = afs_delmap },
-    VOPNAME_POLL,              { .vop_poll = fs_poll },
-    VOPNAME_PATHCONF,          { .vop_pathconf = afs_pathconf },
-    VOPNAME_PAGEIO,            { .vop_pageio = afs_pageio },
-    VOPNAME_DUMP,              { .vop_dump = afs_dump },
-    VOPNAME_DUMPCTL,           { .vop_dumpctl = afs_dumpctl },   
-    VOPNAME_DISPOSE,           { .vop_dispose = afs_dispose },
-    VOPNAME_GETSECATTR,                { .vop_getsecattr = afs_getsecattr },
-    VOPNAME_SETSECATTR,        { .vop_setsecattr = afs_setsecattr },
-    VOPNAME_SHRLOCK,           { .vop_shrlock = fs_shrlock },
-    NULL,                      NULL
-};
-vnodeops_t *afs_ops;
-#elif defined(AFS_SUN510_ENV)
-/* The following list must always be NULL-terminated */
-const fs_operation_def_t afs_vnodeops_template[] = {
-    VOPNAME_OPEN,              gafs_open,
-    VOPNAME_CLOSE,             gafs_close,
-    VOPNAME_READ,              afs_vmread,
-    VOPNAME_WRITE,             afs_vmwrite,
-    VOPNAME_IOCTL,             afs_ioctl,
-    VOPNAME_SETFL,             fs_setfl,
-    VOPNAME_GETATTR,           gafs_getattr,
-    VOPNAME_SETATTR,           gafs_setattr,
-    VOPNAME_ACCESS,            gafs_access,
-    VOPNAME_LOOKUP,            gafs_lookup,
-    VOPNAME_CREATE,            gafs_create,
-    VOPNAME_REMOVE,            gafs_remove,
-    VOPNAME_LINK,              gafs_link,
-    VOPNAME_RENAME,            gafs_rename,
-    VOPNAME_MKDIR,             gafs_mkdir,
-    VOPNAME_RMDIR,             gafs_rmdir,
-    VOPNAME_READDIR,           gafs_readdir,
-    VOPNAME_SYMLINK,           gafs_symlink,   
-    VOPNAME_READLINK,          gafs_readlink,
-    VOPNAME_FSYNC,             gafs_fsync,
-    VOPNAME_INACTIVE,          gafs_inactive,
-    VOPNAME_FID,               gafs_fid,
-    VOPNAME_RWLOCK,            afs_rwlock,
-    VOPNAME_RWUNLOCK,          afs_rwunlock,
-    VOPNAME_SEEK,              afs_seek,
-    VOPNAME_CMP,               afs_cmp,
-    VOPNAME_FRLOCK,            afs_frlock,
-    VOPNAME_SPACE,             afs_space,
-    VOPNAME_REALVP,            afs_realvp,
-    VOPNAME_GETPAGE,           afs_getpage,
-    VOPNAME_PUTPAGE,           afs_putpage,
-    VOPNAME_MAP,               afs_map,
-    VOPNAME_ADDMAP,            afs_addmap,
-    VOPNAME_DELMAP,            afs_delmap,
-    VOPNAME_POLL,              fs_poll,
-    VOPNAME_DUMP,              afs_dump,
-    VOPNAME_PATHCONF,          afs_pathconf,
-    VOPNAME_PAGEIO,            afs_pageio,
-    VOPNAME_DUMPCTL,           afs_dumpctl,   
-    VOPNAME_DISPOSE,           afs_dispose,
-    VOPNAME_GETSECATTR,       afs_getsecattr,
-    VOPNAME_SETSECATTR,        afs_setsecattr,
-    VOPNAME_SHRLOCK,           fs_shrlock,
-    NULL,                     NULL
-};
-struct vnodeops *afs_ops;
-#else
-struct vnodeops Afs_vnodeops = {
-    gafs_open,
-    gafs_close,
-    afs_vmread,
-    afs_vmwrite,
-    afs_ioctl,
-    fs_setfl,
-    gafs_getattr,
-    gafs_setattr,
-    gafs_access,
-    gafs_lookup,
-    gafs_create,
-    gafs_remove,
-    gafs_link,
-    gafs_rename,
-    gafs_mkdir,
-    gafs_rmdir,
-    gafs_readdir,
-    gafs_symlink,
-    gafs_readlink,
-    gafs_fsync,
-    gafs_inactive,
-    gafs_fid,
-    afs_rwlock,
-    afs_rwunlock,
-    afs_seek,
-    afs_cmp,
-    afs_frlock,
-    afs_space,
-    afs_realvp,
-    afs_getpage,
-    afs_putpage,
-    afs_map,
-    afs_addmap,
-    afs_delmap,
-    fs_poll,
-    afs_dump,
-    afs_pathconf,
-    afs_pageio,
-    afs_dumpctl,
-    afs_dispose,
-    afs_setsecattr,
-    afs_getsecattr,
-    fs_shrlock,
-};
-struct vnodeops *afs_ops = &Afs_vnodeops;
-#endif
 
-int
-gafs_open(struct vcache **avcp, afs_int32 aflags, 
+static int
+gafs_open(struct vnode **vpp, afs_int32 aflags, 
          afs_ucred_t *acred)
 {
     int code;
+    struct vcache *avc = VTOAFS(*vpp);
 
     AFS_GLOCK();
-    code = afs_open(avcp, aflags, acred);
+    code = afs_open(&avc, aflags, acred);
     AFS_GUNLOCK();
+
+    /* afs_open currently never changes avc, but just in case... */
+    *vpp = AFSTOV(avc);
+
     return (code);
 }
 
-int
-gafs_close(struct vcache *avc, afs_int32 aflags, int count, 
+static int
+gafs_close(struct vnode *vp, afs_int32 aflags, int count, 
           offset_t offset, afs_ucred_t *acred)
 {
     int code;
-
     AFS_GLOCK();
-    code = afs_close(avc, aflags, count, offset, acred);
+    code = afs_close(VTOAFS(vp), aflags, count, offset, acred);
     AFS_GUNLOCK();
     return (code);
 }
 
-int
-gafs_getattr(struct vcache *avc, struct vattr *attrs, 
+static int
+gafs_getattr(struct vnode *vp, struct vattr *attrs, 
             int flags, afs_ucred_t *acred)
 {
     int code;
-
     AFS_GLOCK();
-    code = afs_getattr(avc, attrs, flags, acred);
+    code = afs_getattr(VTOAFS(vp), attrs, flags, acred);
     AFS_GUNLOCK();
     return (code);
 }
 
 
-int
-gafs_setattr(struct vcache *avc, struct vattr *attrs, 
+static int
+gafs_setattr(struct vnode *vp, struct vattr *attrs, 
             int flags, afs_ucred_t *acred)
 {
     int code;
-
     AFS_GLOCK();
-    code = afs_setattr(avc, attrs, flags, acred);
+    code = afs_setattr(VTOAFS(vp), attrs, flags, acred);
     AFS_GUNLOCK();
     return (code);
 }
 
 
-int
-gafs_access(struct vcache *avc, afs_int32 amode, int flags, 
+static int
+gafs_access(struct vnode *vp, afs_int32 amode, int flags, 
            afs_ucred_t *acred)
 {
     int code;
-
     AFS_GLOCK();
-    code = afs_access(avc, amode, flags, acred);
+    code = afs_access(VTOAFS(vp), amode, flags, acred);
     AFS_GUNLOCK();
     return (code);
 }
 
 
-int
-gafs_lookup(struct vcache *adp, char *aname, 
-           struct vcache **avcp, struct pathname *pnp, int flags, 
+static int
+gafs_lookup(struct vnode *dvp, char *aname, 
+           struct vnode **vpp, struct pathname *pnp, int flags, 
            struct vnode *rdir, afs_ucred_t *acred)
 {
     int code;
+    struct vcache *tvc = NULL;
 
     AFS_GLOCK();
-    code = afs_lookup(adp, aname, avcp, pnp, flags, rdir, acred);
+    code = afs_lookup(VTOAFS(dvp), aname, &tvc, pnp, flags, rdir, acred);
     AFS_GUNLOCK();
+
+    *vpp = NULL;
+    if (tvc) {
+        *vpp = AFSTOV(tvc);
+    }
+
     return (code);
 }
 
 
-int
-gafs_create(struct vcache *adp, char *aname, struct vattr *attrs, 
-           enum vcexcl aexcl, int amode, struct vcache **avcp, 
+static int
+gafs_create(struct vnode *dvp, char *aname, struct vattr *attrs, 
+           enum vcexcl aexcl, int amode, struct vnode **vpp, 
            afs_ucred_t *acred)
 {
     int code;
+    struct vcache *tvc = NULL;
 
     AFS_GLOCK();
-    code = afs_create(adp, aname, attrs, aexcl, amode, avcp, acred);
+    code = afs_create(VTOAFS(dvp), aname, attrs, aexcl, amode, &tvc, acred);
     AFS_GUNLOCK();
+
+    *vpp = NULL;
+    if (tvc) {
+        *vpp = AFSTOV(tvc);
+    }
+
     return (code);
 }
 
-int
-gafs_remove(struct vcache *adp, char *aname, afs_ucred_t *acred)
+static int
+gafs_remove(struct vnode *vp, char *aname, afs_ucred_t *acred)
 {
     int code;
-
     AFS_GLOCK();
-    code = afs_remove(adp, aname, acred);
+    code = afs_remove(VTOAFS(vp), aname, acred);
     AFS_GUNLOCK();
     return (code);
 }
 
-int
-gafs_link(struct vcache *adp, struct vcache *avc, 
+static int
+gafs_link(struct vnode *dvp, struct vnode *svp, 
          char *aname, afs_ucred_t *acred)
 {
     int code;
-
     AFS_GLOCK();
-    code = afs_link(adp, avc, aname, acred);
+    code = afs_link(VTOAFS(dvp), VTOAFS(svp), aname, acred);
     AFS_GUNLOCK();
     return (code);
 }
 
-int
-gafs_rename(struct vcache *aodp, char *aname1, 
-           struct vcache *andp, char *aname2, 
+static int
+gafs_rename(struct vnode *odvp, char *aname1, 
+           struct vnode *ndvp, char *aname2, 
            afs_ucred_t *acred)
 {
     int code;
+    struct vcache *aodp = VTOAFS(odvp);
+    struct vcache *andp = VTOAFS(ndvp);
 
     AFS_GLOCK();
     code = afs_rename(aodp, aname1, andp, aname2, acred);
@@ -1575,7 +1435,7 @@ gafs_rename(struct vcache *aodp, char *aname1,
            vn_setpath(afs_globalVp, pvp, vp, aname2, strlen(aname2));
 # endif /* !HAVE_VN_RENAMEPATH */
 
-           AFS_RELE(avcp);
+           AFS_RELE(AFSTOV(avcp));
        }
     }
 #endif
@@ -1583,83 +1443,85 @@ gafs_rename(struct vcache *aodp, char *aname1,
     return (code);
 }
 
-int
-gafs_mkdir(struct vcache *adp, char *aname, struct vattr *attrs, 
-          struct vcache **avcp, afs_ucred_t *acred)
+static int
+gafs_mkdir(struct vnode *dvp, char *aname, struct vattr *attrs, 
+          struct vnode **vpp, afs_ucred_t *acred)
 {
     int code;
+    struct vcache *tvc = NULL;
 
     AFS_GLOCK();
-    code = afs_mkdir(adp, aname, attrs, avcp, acred);
+    code = afs_mkdir(VTOAFS(dvp), aname, attrs, &tvc, acred);
     AFS_GUNLOCK();
+
+    *vpp = NULL;
+    if (tvc) {
+        *vpp = AFSTOV(tvc);
+    }
+
     return (code);
 }
 
-int
-gafs_rmdir(struct vcache *adp, char *aname, struct vnode *cdirp, 
+static int
+gafs_rmdir(struct vnode *vp, char *aname, struct vnode *cdirp, 
           afs_ucred_t *acred)
 {
     int code;
-
     AFS_GLOCK();
-    code = afs_rmdir(adp, aname, cdirp, acred);
+    code = afs_rmdir(VTOAFS(vp), aname, cdirp, acred);
     AFS_GUNLOCK();
     return (code);
 }
 
 
-int
-gafs_readdir(struct vcache *avc, struct uio *auio,
+static int
+gafs_readdir(struct vnode *vp, struct uio *auio,
             afs_ucred_t *acred, int *eofp)
 {
     int code;
-
     AFS_GLOCK();
-    code = afs_readdir(avc, auio, acred, eofp);
+    code = afs_readdir(VTOAFS(vp), auio, acred, eofp);
     AFS_GUNLOCK();
     return (code);
 }
 
-int
-gafs_symlink(struct vcache *adp, char *aname, struct vattr *attrs,
+static int
+gafs_symlink(struct vnode *vp, char *aname, struct vattr *attrs,
             char *atargetName, afs_ucred_t *acred)
 {
     int code;
-
     AFS_GLOCK();
-    code = afs_symlink(adp, aname, attrs, atargetName, NULL, acred);
+    code = afs_symlink(VTOAFS(vp), aname, attrs, atargetName, NULL, acred);
     AFS_GUNLOCK();
     return (code);
 }
 
 
-int
-gafs_readlink(struct vcache *avc, struct uio *auio, afs_ucred_t *acred)
+static int
+gafs_readlink(struct vnode *vp, struct uio *auio, afs_ucred_t *acred)
 {
     int code;
-
     AFS_GLOCK();
-    code = afs_readlink(avc, auio, acred);
+    code = afs_readlink(VTOAFS(vp), auio, acred);
     AFS_GUNLOCK();
     return (code);
 }
 
-int
-gafs_fsync(struct vcache *avc, int flag, afs_ucred_t *acred)
+static int
+gafs_fsync(struct vnode *vp, int flag, afs_ucred_t *acred)
 {
     int code;
-
     AFS_GLOCK();
-    code = afs_fsync(avc, flag, acred);
+    code = afs_fsync(VTOAFS(vp), flag, acred);
     AFS_GUNLOCK();
     return (code);
 }
 
-int
+static int
 afs_inactive(struct vcache *avc, afs_ucred_t *acred)
 {
     struct vnode *vp = AFSTOV(avc);
-    if (afs_shuttingdown)
+    if (afs_shuttingdown != AFS_RUNNING)
        return 0;
 
     /*
@@ -1685,11 +1547,11 @@ afs_inactive(struct vcache *avc, afs_ucred_t *acred)
      * Solaris calls VOP_OPEN on exec, but doesn't call VOP_CLOSE when
      * the executable exits.  So we clean up the open count here.
      *
-     * Only do this for mvstat 0 vnodes: when using fakestat, we can't
-     * lose the open count for volume roots (mvstat 2), even though they
+     * Only do this for AFS_MVSTAT_FILE vnodes: when using fakestat, we can't
+     * lose the open count for volume roots (AFS_MVSTAT_ROOT), even though they
      * will get VOP_INACTIVE'd when released by afs_PutFakeStat().
      */
-    if (avc->opens > 0 && avc->mvstat == 0 && !(avc->f.states & CCore))
+    if (avc->opens > 0 && avc->mvstat == AFS_MVSTAT_FILE && !(avc->f.states & CCore))
        avc->opens = avc->execsOrWriters = 0;
 #endif
 
@@ -1704,24 +1566,170 @@ afs_inactive(struct vcache *avc, afs_ucred_t *acred)
     return 0;
 }
 
-void
-gafs_inactive(struct vcache *avc, afs_ucred_t *acred)
+static void
+gafs_inactive(struct vnode *vp, afs_ucred_t *acred)
 {
     AFS_GLOCK();
-    (void)afs_inactive(avc, acred);
+    (void)afs_inactive(VTOAFS(vp), acred);
     AFS_GUNLOCK();
 }
 
 
-int
-gafs_fid(struct vcache *avc, struct fid **fidpp)
+static int
+gafs_fid(struct vnode *vp, struct fid **fidpp)
 {
     int code;
-
     AFS_GLOCK();
-    code = afs_fid(avc, fidpp);
+    code = afs_fid(VTOAFS(vp), fidpp);
     AFS_GUNLOCK();
     return (code);
 }
 
+#if defined(AFS_SUN511_ENV)
+/* The following list must always be NULL-terminated */
+const fs_operation_def_t afs_vnodeops_template[] = {
+    VOPNAME_OPEN,              { .vop_open = gafs_open },
+    VOPNAME_CLOSE,             { .vop_close = gafs_close },
+    VOPNAME_READ,              { .vop_read = afs_vmread },
+    VOPNAME_WRITE,             { .vop_write = afs_vmwrite },
+    VOPNAME_IOCTL,             { .vop_ioctl = afs_ioctl },
+    VOPNAME_SETFL,             { .vop_setfl = fs_setfl },
+    VOPNAME_GETATTR,           { .vop_getattr = gafs_getattr },
+    VOPNAME_SETATTR,           { .vop_setattr = gafs_setattr },
+    VOPNAME_ACCESS,            { .vop_access = gafs_access },
+    VOPNAME_LOOKUP,            { .vop_lookup = gafs_lookup },
+    VOPNAME_CREATE,            { .vop_create = gafs_create },
+    VOPNAME_REMOVE,            { .vop_remove = gafs_remove },
+    VOPNAME_LINK,              { .vop_link = gafs_link },
+    VOPNAME_RENAME,            { .vop_rename = gafs_rename },
+    VOPNAME_MKDIR,             { .vop_mkdir = gafs_mkdir },
+    VOPNAME_RMDIR,             { .vop_rmdir = gafs_rmdir },
+    VOPNAME_READDIR,           { .vop_readdir = gafs_readdir },
+    VOPNAME_SYMLINK,           { .vop_symlink = gafs_symlink },
+    VOPNAME_READLINK,          { .vop_readlink = gafs_readlink },
+    VOPNAME_FSYNC,             { .vop_fsync = gafs_fsync },
+    VOPNAME_INACTIVE,          { .vop_inactive = gafs_inactive },
+    VOPNAME_FID,               { .vop_fid = gafs_fid },
+    VOPNAME_RWLOCK,            { .vop_rwlock = afs_rwlock },
+    VOPNAME_RWUNLOCK,          { .vop_rwunlock = afs_rwunlock },
+    VOPNAME_SEEK,              { .vop_seek = afs_seek },
+    VOPNAME_CMP,               { .vop_cmp = afs_cmp },
+    VOPNAME_FRLOCK,            { .vop_frlock = afs_frlock },
+    VOPNAME_SPACE,             { .vop_space = afs_space },
+    VOPNAME_REALVP,            { .vop_realvp = afs_realvp },
+    VOPNAME_GETPAGE,           { .vop_getpage = afs_getpage },
+    VOPNAME_PUTPAGE,           { .vop_putpage = afs_putpage },
+    VOPNAME_MAP,               { .vop_map = afs_map },
+    VOPNAME_ADDMAP,            { .vop_addmap = afs_addmap },
+    VOPNAME_DELMAP,            { .vop_delmap = afs_delmap },
+    VOPNAME_POLL,              { .vop_poll = fs_poll },
+    VOPNAME_PATHCONF,          { .vop_pathconf = afs_pathconf },
+    VOPNAME_PAGEIO,            { .vop_pageio = afs_pageio },
+    VOPNAME_DUMP,              { .vop_dump = afs_dump },
+    VOPNAME_DUMPCTL,           { .vop_dumpctl = afs_dumpctl },
+    VOPNAME_DISPOSE,           { .vop_dispose = afs_dispose },
+    VOPNAME_GETSECATTR,                { .vop_getsecattr = afs_getsecattr },
+    VOPNAME_SETSECATTR,        { .vop_setsecattr = afs_setsecattr },
+    VOPNAME_SHRLOCK,           { .vop_shrlock = fs_shrlock },
+    NULL,                      NULL
+};
+vnodeops_t *afs_ops;
+#elif defined(AFS_SUN510_ENV)
+/* The following list must always be NULL-terminated */
+const fs_operation_def_t afs_vnodeops_template[] = {
+    VOPNAME_OPEN,              gafs_open,
+    VOPNAME_CLOSE,             gafs_close,
+    VOPNAME_READ,              afs_vmread,
+    VOPNAME_WRITE,             afs_vmwrite,
+    VOPNAME_IOCTL,             afs_ioctl,
+    VOPNAME_SETFL,             fs_setfl,
+    VOPNAME_GETATTR,           gafs_getattr,
+    VOPNAME_SETATTR,           gafs_setattr,
+    VOPNAME_ACCESS,            gafs_access,
+    VOPNAME_LOOKUP,            gafs_lookup,
+    VOPNAME_CREATE,            gafs_create,
+    VOPNAME_REMOVE,            gafs_remove,
+    VOPNAME_LINK,              gafs_link,
+    VOPNAME_RENAME,            gafs_rename,
+    VOPNAME_MKDIR,             gafs_mkdir,
+    VOPNAME_RMDIR,             gafs_rmdir,
+    VOPNAME_READDIR,           gafs_readdir,
+    VOPNAME_SYMLINK,           gafs_symlink,
+    VOPNAME_READLINK,          gafs_readlink,
+    VOPNAME_FSYNC,             gafs_fsync,
+    VOPNAME_INACTIVE,          gafs_inactive,
+    VOPNAME_FID,               gafs_fid,
+    VOPNAME_RWLOCK,            afs_rwlock,
+    VOPNAME_RWUNLOCK,          afs_rwunlock,
+    VOPNAME_SEEK,              afs_seek,
+    VOPNAME_CMP,               afs_cmp,
+    VOPNAME_FRLOCK,            afs_frlock,
+    VOPNAME_SPACE,             afs_space,
+    VOPNAME_REALVP,            afs_realvp,
+    VOPNAME_GETPAGE,           afs_getpage,
+    VOPNAME_PUTPAGE,           afs_putpage,
+    VOPNAME_MAP,               afs_map,
+    VOPNAME_ADDMAP,            afs_addmap,
+    VOPNAME_DELMAP,            afs_delmap,
+    VOPNAME_POLL,              fs_poll,
+    VOPNAME_DUMP,              afs_dump,
+    VOPNAME_PATHCONF,          afs_pathconf,
+    VOPNAME_PAGEIO,            afs_pageio,
+    VOPNAME_DUMPCTL,           afs_dumpctl,
+    VOPNAME_DISPOSE,           afs_dispose,
+    VOPNAME_GETSECATTR,       afs_getsecattr,
+    VOPNAME_SETSECATTR,        afs_setsecattr,
+    VOPNAME_SHRLOCK,           fs_shrlock,
+    NULL,                     NULL
+};
+struct vnodeops *afs_ops;
+#else
+struct vnodeops Afs_vnodeops = {
+    gafs_open,
+    gafs_close,
+    afs_vmread,
+    afs_vmwrite,
+    afs_ioctl,
+    fs_setfl,
+    gafs_getattr,
+    gafs_setattr,
+    gafs_access,
+    gafs_lookup,
+    gafs_create,
+    gafs_remove,
+    gafs_link,
+    gafs_rename,
+    gafs_mkdir,
+    gafs_rmdir,
+    gafs_readdir,
+    gafs_symlink,
+    gafs_readlink,
+    gafs_fsync,
+    gafs_inactive,
+    gafs_fid,
+    afs_rwlock,
+    afs_rwunlock,
+    afs_seek,
+    afs_cmp,
+    afs_frlock,
+    afs_space,
+    afs_realvp,
+    afs_getpage,
+    afs_putpage,
+    afs_map,
+    afs_addmap,
+    afs_delmap,
+    fs_poll,
+    afs_dump,
+    afs_pathconf,
+    afs_pageio,
+    afs_dumpctl,
+    afs_dispose,
+    afs_setsecattr,
+    afs_getsecattr,
+    fs_shrlock,
+};
+struct vnodeops *afs_ops = &Afs_vnodeops;
+#endif
+
 #endif /* AFS_GLOBAL_SUNLOCK */