afs: more cache truncation stats
[openafs.git] / src / afs / SOLARIS / osi_vnodeops.c
index 2f379c2..81147d5 100644 (file)
@@ -10,9 +10,7 @@
 #include <afsconfig.h>
 #include "afs/param.h"
 
-RCSID("$Header$");
 
-#if    defined(AFS_SUN_ENV) || defined(AFS_SUN5_ENV)
 /*
  * SOLARIS/osi_vnodeops.c
  *
@@ -34,8 +32,8 @@ RCSID("$Header$");
  */
 #include "afs/sysincludes.h"   /* Standard vendor system headers */
 #include "afsincludes.h"       /* Afs-based standard headers */
-#include "afs/afs_stats.h"  /* statistics */
-#include "afs/nfsclient.h"  
+#include "afs/afs_stats.h"     /* statistics */
+#include "afs/nfsclient.h"
 
 
 #include <sys/mman.h>
@@ -47,39 +45,13 @@ RCSID("$Header$");
 #include <vm/seg_map.h>
 #include <vm/seg_vn.h>
 #include <vm/rm.h>
-#if    defined(AFS_SUN5_ENV) 
+#if defined(AFS_SUN511_ENV)
+#include <sys/vfs_opreg.h>
+#endif
 #include <sys/modctl.h>
 #include <sys/syscall.h>
-#else
-#include <vm/swap.h>
-#endif
 #include <sys/debug.h>
-#if    defined(AFS_SUN5_ENV)
 #include <sys/fs_subr.h>
-#endif
-
-#if    defined(AFS_SUN5_ENV)
-/* 
- * XXX Temporary fix for problems with Solaris rw_tryupgrade() lock.
- * It isn't very persistent in getting the upgrade when others are
- * waiting for it and returns 0.  So the UpgradeSToW() macro that the
- * rw_tryupgrade used to map to wasn't good enough and we need to use
- * the following code instead.  Obviously this isn't the proper place
- * for it but it's only called from here for now
- * 
- */
-#ifndef        AFS_SUN54_ENV
-AFS_TRYUP(lock)
-     afs_rwlock_t *lock;
-{
-    if (!rw_tryupgrade(lock)) {
-       rw_exit(lock);
-       rw_enter(lock, RW_WRITER);
-    }
-}
-#endif
-#endif
-
 
 /* Translate a faultcode_t as returned by some of the vm routines
  * into a suitable errno value.
@@ -100,49 +72,47 @@ afs_fc2errno(faultcode_t fc)
 }
 
 
-extern struct as kas;  /* kernel addr space */
-extern unsigned char *afs_indexFlags;         
-extern afs_lock_t afs_xdcache;         
+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;
 
-#ifdef AFS_SUN5_ENV
-
-int afs_addmap(avp, offset, asp, addr, length, prot, maxprot, flags, credp)
-    register struct vnode *avp;
-    offset_t offset;
-    struct as *asp;
-    caddr_t addr;
-    int length, prot, maxprot, flags;
-    struct AFS_UCRED *credp;
+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)
 {
     /* XXX What should we do here?? XXX */
     return (0);
 }
 
-int afs_delmap(avp, offset, asp, addr, length, prot, maxprot, flags, credp)
-    register struct vnode *avp;
-    offset_t offset;
-    struct as *asp;
-    caddr_t addr;
-    int length, prot, maxprot, flags;
-    struct AFS_UCRED *credp;
+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)
 {
     /* XXX What should we do here?? XXX */
     return (0);
 }
 
-int afs_vmread(avp, auio, ioflag, acred)
-    register struct vnode *avp;
-    struct uio *auio;
-    int ioflag;
-    struct AFS_UCRED *acred;
+static int
+#ifdef AFS_SUN510_ENV
+afs_vmread(struct vnode *avp, struct uio *auio, int ioflag, 
+          afs_ucred_t *acred, caller_context_t *ct)
+#else
+afs_vmread(struct vnode *avp, struct uio *auio, int ioflag, 
+          afs_ucred_t *acred)
+#endif
 {
-    register int code;
+    int code;
 
     if (!RW_READ_HELD(&(VTOAFS(avp))->rwlock))
        osi_Panic("afs_vmread: !rwlock");
@@ -153,13 +123,16 @@ int afs_vmread(avp, auio, ioflag, acred)
 }
 
 
-int afs_vmwrite(avp, auio, ioflag, acred)
-    register struct vnode *avp;
-    struct uio *auio;
-    int ioflag;
-    struct AFS_UCRED *acred;
+static int
+#ifdef AFS_SUN510_ENV
+afs_vmwrite(struct vnode *avp, struct uio *auio, int ioflag, 
+           afs_ucred_t *acred, caller_context_t *ct)
+#else
+afs_vmwrite(struct vnode *avp, struct uio *auio, int ioflag, 
+           afs_ucred_t *acred)
+#endif
 {
-    register int code;
+    int code;
 
     if (!RW_WRITE_HELD(&(VTOAFS(avp))->rwlock))
        osi_Panic("afs_vmwrite: !rwlock");
@@ -169,148 +142,106 @@ int afs_vmwrite(avp, auio, ioflag, acred)
     return code;
 }
 
-#endif /* AFS_SUN5_ENV */
-
-int afs_getpage(vp, off, len, protp, pl, plsz, seg, addr, rw, acred)
-struct vnode *vp;
-u_int len;
-u_int *protp;
-struct page *pl[];
-u_int plsz;
-struct seg *seg;
-#ifdef AFS_SUN5_ENV
-offset_t off;
-caddr_t addr;
-#else
-u_int off;
-addr_t addr;
-#endif
-enum seg_rw rw;
-struct AFS_UCRED *acred;
+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)
 {
-    register afs_int32 code = 0;
+    afs_int32 code = 0;
     AFS_STATCNT(afs_getpage);
 
-#ifdef AFS_SUN5_ENV
     if (vp->v_flag & VNOMAP)   /* File doesn't allow mapping */
        return (ENOSYS);
-#endif
 
     AFS_GLOCK();
 
-#if    defined(AFS_SUN56_ENV)
     if (len <= PAGESIZE)
-       code = afs_GetOnePage(vp, off, len, protp, pl, plsz,
-                             seg, addr, rw, acred);
-#else
-#ifdef AFS_SUN5_ENV
-    if (len <= PAGESIZE)
-       code = afs_GetOnePage(vp, (u_int)off, len, protp, pl, plsz,
-                             seg, addr, rw, acred);
-#else
-    if (len == PAGESIZE)
-       code = afs_GetOnePage(vp, off, protp, pl, plsz,
-                             seg, addr, rw, acred);
-#endif
-#endif
+       code =
+           afs_GetOnePage(vp, off, len, protp, pl, plsz, seg, addr, rw, acred);
     else {
+       struct multiPage_range range;
        struct vcache *vcp = VTOAFS(vp);
-#ifdef AFS_SUN5_ENV
+
+       /* We've been asked to get more than one page. We must return all
+        * requested pages at once, all of them locked, which means all of
+        * these dcache entries cannot be kicked out of the cache before we
+        * return (since their pages cannot be invalidated).
+        *
+        * afs_GetOnePage will be called multiple times by pvn_getpages in
+        * order to get all of the requested pages. One of the later
+        * afs_GetOnePage calls may need to evict some cache entries in order
+        * to perform its read. If we try to kick out one of the entries an
+        * earlier afs_GetOnePage call used, we will deadlock since we have
+        * the page locked. So, to tell afs_GetDownD that it should skip over
+        * any entries we've read in due to this afs_getpage call, record the
+        * offset and length in avc->multiPage.
+        *
+        * Ideally we would just set something in each dcache as we get it,
+        * but that is rather difficult, since pvn_getpages doesn't let us
+        * retain any information between calls to afs_GetOnePage. So instead
+        * just record the offset and length, and let afs_GetDownD calculate
+        * which dcache entries should be skipped. */
+
+       range.off = off;
+       range.len = len;
+
        ObtainWriteLock(&vcp->vlock, 548);
-       vcp->multiPage++;
+       QAdd(&vcp->multiPage, &range.q);
        ReleaseWriteLock(&vcp->vlock);
-#endif
-       afs_BozonLock(&vcp->pvnLock, vcp);
-#if    defined(AFS_SUN56_ENV)
-       code = pvn_getpages(afs_GetOnePage, vp, off, 
-                           len, protp, pl, plsz, seg, addr, rw, acred);
-#else
-       code = pvn_getpages(afs_GetOnePage, vp, (u_int)off, 
-                           len, protp, pl, plsz, seg, addr, rw, acred);
-#endif
-       afs_BozonUnlock(&vcp->pvnLock, vcp);
-#ifdef AFS_SUN5_ENV
+       code =
+           pvn_getpages(afs_GetOnePage, vp, off, len, protp, pl, plsz, seg, addr, rw, acred);
        ObtainWriteLock(&vcp->vlock, 549);
-       vcp->multiPage--;
+       QRemove(&range.q);
        ReleaseWriteLock(&vcp->vlock);
-#endif
     }
     AFS_GUNLOCK();
     return code;
 }
 
 /* Return all the pages from [off..off+len) in file */
-#ifdef AFS_SUN5_ENV
-int afs_GetOnePage(vp, off, alen, protp, pl, plsz, seg, addr, rw, acred)
-u_int alen;
-#else
-int afs_GetOnePage(vp, off, protp, pl, plsz, seg, addr, rw, acred)
-#endif
-struct vnode *vp;
-#if    defined(AFS_SUN56_ENV)
-u_offset_t off;
-#else
-u_int off;
-#endif
-u_int *protp;
-struct page *pl[];
-u_int plsz;
-struct seg *seg;
-#ifdef AFS_SUN5_ENV
-caddr_t addr;
-#else
-addr_t addr;
-#endif
-enum seg_rw rw;
-struct AFS_UCRED *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)
 {
-    register struct page *page;
-    register afs_int32 code = 0;
+    struct page *page;
+    afs_int32 code = 0;
     u_int len;
     struct buf *buf;
     afs_int32 tlen;
-    register struct vcache *avc;
-    register struct dcache *tdc;
+    struct vcache *avc;
+    struct dcache *tdc;
     int i, s, pexists;
     int slot;
-    afs_size_t offset, nlen;
+    afs_size_t offset, nlen = 0;
     struct vrequest treq;
-    afs_int32 mapForRead = 0, Code=0;
-#if    defined(AFS_SUN56_ENV)
-    u_offset_t  toffset;
-#else
-    afs_int32       toffset;
-#endif
+    afs_int32 mapForRead = 0, Code = 0;
+    u_offset_t toffset;
 
-    if (!acred) 
-#ifdef AFS_SUN5_ENV
+    if (!acred)
        osi_Panic("GetOnePage: !acred");
-#else
-       acred = u.u_cred;               /* better than nothing */
-#endif
 
-    avc = VTOAFS(vp);  /* cast to afs vnode */
+    avc = VTOAFS(vp);          /* cast to afs vnode */
 
-#ifdef AFS_SUN5_ENV
-    if (avc->credp /*&& AFS_NFSXLATORREQ(acred)*/ && AFS_NFSXLATORREQ(avc->credp)) {
+    if (avc->credp             /*&& AFS_NFSXLATORREQ(acred) */
+       && AFS_NFSXLATORREQ(avc->credp)) {
        acred = avc->credp;
     }
-#endif
-    if (code = afs_InitReq(&treq, acred)) return code;
+    if (code = afs_InitReq(&treq, acred))
+       return code;
 
     if (!pl) {
        /* This is a read-ahead request, e.g. due to madvise.  */
-#ifdef AFS_SUN5_ENV
        int plen = alen;
-#else
-       int plen = PAGESIZE;
-#endif
        ObtainReadLock(&avc->lock);
 
        while (plen > 0 && !afs_BBusy()) {
            /* Obtain a dcache entry at off.  2 means don't fetch data. */
-           tdc = afs_GetDCache(avc, (afs_offs_t)off, &treq, &offset, &nlen, 2);
-           if (!tdc) break;
+           tdc =
+               afs_GetDCache(avc, (afs_offs_t) off, &treq, &offset, &nlen,
+                             2);
+           if (!tdc)
+               break;
 
            /* Write-lock the dcache entry, if we don't succeed, just go on */
            if (0 != NBObtainWriteLock(&tdc->lock, 642)) {
@@ -324,7 +255,8 @@ struct AFS_UCRED *acred;
 
                tdc->mflags |= DFFetchReq;
                bp = afs_BQueue(BOP_FETCH, avc, B_DONTWAIT, 0, acred,
-                               (afs_size_t) off, (afs_size_t) 1, tdc);
+                               (afs_size_t) off, (afs_size_t) 1, tdc,
+                               (void *)0, (void *)0);
                if (!bp) {
                    /* Unable to start background fetch; might as well stop */
                    tdc->mflags &= ~DFFetchReq;
@@ -338,13 +270,14 @@ struct AFS_UCRED *acred;
                afs_PutDCache(tdc);
            }
 
-next_prefetch:
+         next_prefetch:
            /* Adjust our offset and remaining length values */
            off += nlen;
            plen -= nlen;
 
            /* If we aren't making progress for some reason, bail out */
-           if (nlen <= 0) break;
+           if (nlen <= 0)
+               break;
        }
 
        ReleaseReadLock(&avc->lock);
@@ -352,7 +285,7 @@ next_prefetch:
     }
 
     len = PAGESIZE;
-    pl[0] = NULL;                      /* Make sure it's empty */
+    pl[0] = NULL;              /* Make sure it's empty */
 
     /* first, obtain the proper lock for the VM system */
 
@@ -363,57 +296,41 @@ next_prefetch:
      * pages for the range covered by a chunk when we swap out the
      * chunk.
      */
-    if (rw == S_READ || rw == S_EXEC) 
+    if (rw == S_READ || rw == S_EXEC)
        mapForRead = 1;
 
-    if (protp) *protp = PROT_ALL;
-#ifndef        AFS_SUN5_ENV
-    if (AFS_NFSXLATORREQ(acred)) {
-       if (rw == S_READ) {
-           if (!afs_AccessOK(avc, PRSFS_READ, &treq,
-                             CHECK_MODE_BITS|CMB_ALLOW_EXEC_AS_READ)) {
-               return EACCES;
-           }
-       }
-    }
-#endif
+    if (protp)
+       *protp = PROT_ALL;
 
-retry:
-#ifdef AFS_SUN5_ENV
+  retry:
     if (rw == S_WRITE || rw == S_CREATE)
-       tdc = afs_GetDCache(avc, (afs_offs_t)off, &treq, &offset, &nlen, 5);
+       tdc = afs_GetDCache(avc, (afs_offs_t) off, &treq, &offset, &nlen, 5);
     else
-       tdc = afs_GetDCache(avc, (afs_offs_t)off, &treq, &offset, &nlen, 1);
-    if (!tdc) return EINVAL;
-#endif
+       tdc = afs_GetDCache(avc, (afs_offs_t) off, &treq, &offset, &nlen, 1);
+    if (!tdc)
+       return afs_CheckCode(EINVAL, &treq, 62);
     code = afs_VerifyVCache(avc, &treq);
     if (code) {
-#ifdef  AFS_SUN5_ENV
        afs_PutDCache(tdc);
-#endif 
-       return afs_CheckCode(code, &treq, 44); /* failed to get it */
+       return afs_CheckCode(code, &treq, 44);  /* failed to get it */
     }
 
-    afs_BozonLock(&avc->pvnLock, avc);
     ObtainReadLock(&avc->lock);
 
     afs_Trace4(afs_iclSetp, CM_TRACE_PAGEIN, ICL_TYPE_POINTER, (afs_int32) vp,
-               ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(off), 
-               ICL_TYPE_LONG, len,
-               ICL_TYPE_LONG, (int) rw);
+              ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(off), ICL_TYPE_LONG, len,
+              ICL_TYPE_LONG, (int)rw);
 
     tlen = len;
     slot = 0;
     toffset = off;
-#ifdef AFS_SUN5_ENV
     /* Check to see if we're in the middle of a VM purge, and if we are, release
      * the locks and try again when the VM purge is done. */
     ObtainWriteLock(&avc->vlock, 550);
     if (avc->activeV) {
-       ReleaseReadLock(&avc->lock); 
-       ReleaseWriteLock(&avc->vlock); 
-       afs_BozonUnlock(&avc->pvnLock, avc);
-       afs_PutDCache(tdc);
+       ReleaseReadLock(&avc->lock);
+       ReleaseWriteLock(&avc->vlock);
+       afs_PutDCache(tdc);
        /* Check activeV again, it may have been turned off
         * while we were waiting for a lock in afs_PutDCache */
        ObtainWriteLock(&avc->vlock, 574);
@@ -426,150 +343,90 @@ retry:
        }
        goto retry;
     }
-    ReleaseWriteLock(&avc->vlock); 
-#endif
+    ReleaseWriteLock(&avc->vlock);
 
     /* We're about to do stuff with our dcache entry..  Lock it. */
     ObtainReadLock(&tdc->lock);
 
     /* Check to see whether the cache entry is still valid */
-    if (!(avc->states & CStatd)
-       || !hsame(avc->m.DataVersion, tdc->f.versionNo)) {
+    if (!(avc->f.states & CStatd)
+       || !afs_IsDCacheFresh(tdc, avc)) {
        ReleaseReadLock(&tdc->lock);
-       ReleaseReadLock(&avc->lock); 
-       afs_BozonUnlock(&avc->pvnLock, avc);
+       ReleaseReadLock(&avc->lock);
        afs_PutDCache(tdc);
        goto retry;
     }
 
     AFS_GUNLOCK();
-    while (1) {        /* loop over all pages */
+    while (1) {                        /* loop over all pages */
        /* now, try to find the page in memory (it may already be intransit or laying
-          around the free list */
-       page = page_lookup( vp, toffset, (rw == S_CREATE ? SE_EXCL : SE_SHARED) );
-       if (page) 
+        * around the free list */
+       page =
+           page_lookup(vp, toffset, (rw == S_CREATE ? SE_EXCL : SE_SHARED));
+       if (page)
            goto nextpage;
 
        /* if we make it here, we can't find the page in memory.  Do a real disk read
-          from the cache to get the data */
+        * from the cache to get the data */
        Code |= 0x200;          /* XXX */
-#ifdef AFS_SUN5_ENV
-#if    defined(AFS_SUN54_ENV)
        /* use PG_EXCL because we know the page does not exist already.  If it 
         * actually does exist, we have somehow raced between lookup and create.
         * As of 4/98, that shouldn't be possible, but we'll be defensive here
         * in case someone tries to relax all the serialization of read and write
         * operations with harmless things like stat. */
-#if    defined(AFS_SUN58_ENV)
-        page = page_create_va(vp, toffset, PAGESIZE, PG_WAIT|PG_EXCL, seg, addr);
-#else
-       page = page_create_va(vp, toffset, PAGESIZE, PG_WAIT|PG_EXCL, seg->s_as, addr);
-#endif
-#else
-       page = page_create(vp, toffset, PAGESIZE, PG_WAIT);
-#endif
+       page =
+           page_create_va(vp, toffset, PAGESIZE, PG_WAIT | PG_EXCL, seg,
+                          addr);
        if (!page) {
            continue;
        }
        if (alen < PAGESIZE)
-           pagezero(page, alen, PAGESIZE-alen); 
-#else
-       page = rm_allocpage(seg, addr, PAGESIZE, 1);    /* can't fail */
-       if (!page) osi_Panic("afs_getpage alloc page");
-       /* we get a circularly-linked list of pages back, but we expect only
-          one, since that's what we asked for */
-       if (page->p_next != page) osi_Panic("afs_getpage list");
-       /* page enter returns a locked page; we'll drop the lock as a side-effect
-          of the pvn_done done by afs_ustrategy.  If we decide not to call
-          strategy, we must be sure to call pvn_fail, at least, to release the
-          page locks and otherwise reset the pages.  The page, while locked, is
-          not held, for what it is worth */
-       page->p_intrans = 1;    /* set appropriate flags */
-       page->p_pagein = 1;
-       /* next call shouldn't fail, since we have pvnLock set */
-       if (page_enter(page, vp, toffset)) osi_Panic("afs_getpage enter race");
-#endif /* AFS_SUN5_ENV */
-
-#ifdef AFS_SUN5_ENV
-        if (rw == S_CREATE) {
+           pagezero(page, alen, PAGESIZE - alen);
+
+       if (rw == S_CREATE) {
            /* XXX Don't read from AFS in write only cases XXX */
            page_io_unlock(page);
-       } else 
-#else
-       if (0) {
-           /* XXX Don't read from AFS in write only cases XXX */
-           page->p_intrans = page->p_pagein = 0;
-           page_unlock(page);  /* XXX */
-       } else 
-#endif
-           {
-#ifndef        AFS_SUN5_ENV
-           PAGE_HOLD(page);
-#endif
+       } else
+       {
            /* now it is time to start I/O operation */
            buf = pageio_setup(page, PAGESIZE, vp, B_READ);     /* allocate a buf structure */
-#if    defined(AFS_SUN5_ENV)
            buf->b_edev = 0;
-#endif
            buf->b_dev = 0;
-           buf->b_blkno = btodb(toffset);
-           bp_mapin(buf);              /* map it in to our address space */
+           buf->b_lblkno = lbtodb(toffset);
+           bp_mapin(buf);      /* map it in to our address space */
 
-#if    defined(AFS_SUN5_ENV)
            AFS_GLOCK();
            /* afs_ustrategy will want to lock the dcache entry */
            ReleaseReadLock(&tdc->lock);
            code = afs_ustrategy(buf, acred);   /* do the I/O */
            ObtainReadLock(&tdc->lock);
            AFS_GUNLOCK();
-#else
-           ReleaseReadLock(&tdc->lock);
-           ReleaseReadLock(&avc->lock);
-           code = afs_ustrategy(buf);  /* do the I/O */
-           ObtainReadLock(&avc->lock);
-           ObtainReadLock(&tdc->lock);
-#endif
 
-#ifdef AFS_SUN5_ENV
            /* Before freeing unmap the buffer */
            bp_mapout(buf);
            pageio_done(buf);
-#endif
            if (code) {
-#ifndef        AFS_SUN5_ENV
-               PAGE_RELE(page);
-#endif
                goto bad;
            }
-#ifdef AFS_SUN5_ENV
            page_io_unlock(page);
-#endif
        }
 
        /* come here when we have another page (already held) to enter */
       nextpage:
        /* put page in array and continue */
-#ifdef AFS_SUN5_ENV
        /* The p_selock must be downgraded to a shared lock after the page is read */
-#if    defined(AFS_SUN56_ENV)
-       if ((rw != S_CREATE) && !(PAGE_SHARED(page))) 
-#else
-       if ((rw != S_CREATE) && !(se_shared_assert(&page->p_selock))) 
-#endif
-       {
+       if ((rw != S_CREATE) && !(PAGE_SHARED(page))) {
            page_downgrade(page);
        }
-#endif
        pl[slot++] = page;
-#ifdef AFS_SUN5_ENV
        code = page_iolock_assert(page);
-#endif
        code = 0;
        toffset += PAGESIZE;
        addr += PAGESIZE;
        tlen -= PAGESIZE;
-       if (tlen <= 0) break;   /* done all the pages */
-    } /* while (1) ... */
+       if (tlen <= 0)
+           break;              /* done all the pages */
+    }                          /* while (1) ... */
 
     AFS_GLOCK();
     pl[slot] = NULL;
@@ -582,104 +439,91 @@ retry:
     }
 
     ReleaseReadLock(&avc->lock);
-#ifdef AFS_SUN5_ENV
-    ObtainWriteLock(&afs_xdcache,246);
+    ObtainWriteLock(&afs_xdcache, 246);
     if (!mapForRead) {
        /* track that we have dirty (or dirty-able) pages for this chunk. */
        afs_indexFlags[tdc->index] |= IFDirtyPages;
     }
     afs_indexFlags[tdc->index] |= IFAnyPages;
     ReleaseWriteLock(&afs_xdcache);
-#endif
-    afs_BozonUnlock(&avc->pvnLock, avc);
-#ifdef AFS_SUN5_ENV
     afs_PutDCache(tdc);
-#endif
-    afs_Trace3(afs_iclSetp, CM_TRACE_PAGEINDONE, ICL_TYPE_LONG, code, ICL_TYPE_LONG, (int)page, 
-              ICL_TYPE_LONG, Code);
+    afs_Trace3(afs_iclSetp, CM_TRACE_PAGEINDONE, ICL_TYPE_LONG, code,
+              ICL_TYPE_LONG, (int)page, ICL_TYPE_LONG, Code);
     return 0;
 
   bad:
     AFS_GLOCK();
-    afs_Trace3(afs_iclSetp, CM_TRACE_PAGEINDONE, ICL_TYPE_LONG, code, ICL_TYPE_LONG, (int)page, 
-              ICL_TYPE_LONG, Code);
+    afs_Trace3(afs_iclSetp, CM_TRACE_PAGEINDONE, ICL_TYPE_LONG, code,
+              ICL_TYPE_LONG, (int)page, ICL_TYPE_LONG, Code);
     /* release all pages, drop locks, return code */
-#ifdef AFS_SUN5_ENV
-    if (page) 
+    if (page)
        pvn_read_done(page, B_ERROR);
-#else
-    for(i=0; i<slot; i++)
-       PAGE_RELE(pl[i]);
-#endif
     ReleaseReadLock(&avc->lock);
-    afs_BozonUnlock(&avc->pvnLock, avc);
-#ifdef AFS_SUN5_ENV
     ReleaseReadLock(&tdc->lock);
     afs_PutDCache(tdc);
-#endif
     return code;
 }
 
-#ifdef AFS_SUN5_ENV
-int afs_putpage(vp, off, len, flags, cred)
-    struct vnode *vp;
-    offset_t off;
-    u_int len;
-    int flags;
-    struct AFS_UCRED *cred;
+/**
+ * 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)
 {
     struct vcache *avc;
     struct page *pages;
     afs_int32 code = 0;
-#if    defined(AFS_SUN58_ENV)
     size_t tlen;
-#else
-    afs_int32 tlen;
-#endif
     afs_offs_t endPos;
-    afs_int32 NPages=0;
-#if    defined(AFS_SUN56_ENV)
+    afs_int32 NPages = 0;
     u_offset_t toff = off;
-#else
-    int toff = (int)off;
-#endif
-    int didWriteLock;
+    int didLock = 0;
 
     AFS_STATCNT(afs_putpage);
-    if (vp->v_flag & VNOMAP)           /* file doesn't allow mapping */
+    if (vp->v_flag & VNOMAP)   /* file doesn't allow mapping */
        return (ENOSYS);
 
     /*
      * Putpage (ASYNC) is called every sec to flush out dirty vm pages 
      */
     AFS_GLOCK();
-    afs_Trace4(afs_iclSetp, CM_TRACE_PAGEOUT, ICL_TYPE_POINTER, (afs_int32) vp,
-               ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(off),
-               ICL_TYPE_INT32, (afs_int32) len,
-               ICL_TYPE_LONG, (int) flags);
+    afs_Trace4(afs_iclSetp, CM_TRACE_PAGEOUT, ICL_TYPE_POINTER,
+              (afs_int32) vp, ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(off),
+              ICL_TYPE_INT32, (afs_int32) len, ICL_TYPE_LONG, (int)flags);
     avc = VTOAFS(vp);
-    afs_BozonLock(&avc->pvnLock, avc);
-    ObtainSharedLock(&avc->lock,247);
-    didWriteLock = 0;
 
     /* Get a list of modified (or whatever) pages */
     if (len) {
-       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->m.Length) {
+       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) {
            /* If not invalidating pages use page_lookup_nowait to avoid reclaiming
             * them from the free list
             */
            AFS_GUNLOCK();
-           if (flags & (B_FREE|B_INVAL))
+           if (flags & (B_FREE | B_INVAL))
                pages = page_lookup(vp, toff, SE_EXCL);
            else
                pages = page_lookup_nowait(vp, toff, SE_SHARED);
-           if (!pages || !pvn_getdirty(pages, 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();
                }
@@ -694,68 +538,77 @@ int afs_putpage(vp, off, len, flags, cred)
            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();
-#if    defined(AFS_SUN56_ENV) 
-       code = pvn_vplist_dirty(vp, toff, afs_putapage, flags, cred);
-#else
-       code = pvn_vplist_dirty(vp, (u_int)off, afs_putapage, flags, cred);
-#endif
+       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_BozonUnlock(&avc->pvnLock, avc);
-    afs_Trace2(afs_iclSetp, CM_TRACE_PAGEOUTDONE, ICL_TYPE_LONG, code, ICL_TYPE_LONG, NPages);
+    afs_Trace2(afs_iclSetp, CM_TRACE_PAGEOUTDONE, ICL_TYPE_LONG, code,
+              ICL_TYPE_LONG, NPages);
     AFS_GUNLOCK();
     return (code);
 }
 
-
-int afs_putapage(struct vnode *vp, struct page *pages,
-#if    defined(AFS_SUN56_ENV)
-                u_offset_t *offp,
-#else
-                u_int *offp,
-#endif
-#if    defined(AFS_SUN58_ENV)
-                 size_t *lenp,
-#else
-                 u_int *lenp,
-#endif
-                 int flags, struct AFS_UCRED *credp)
+int
+afs_putapage(struct vnode *vp, struct page *pages, u_offset_t * offp,
+            size_t * lenp, int flags, afs_ucred_t *credp)
 {
     struct buf *tbuf;
     struct vcache *avc = VTOAFS(vp);
     afs_int32 code = 0;
     u_int tlen = PAGESIZE;
-    afs_offs_t off = (pages->p_offset/PAGESIZE)*PAGESIZE;
+    afs_offs_t off = (pages->p_offset / PAGESIZE) * PAGESIZE;
 
     /*
      * Now we've got the modified pages.  All pages are locked and held 
      * XXX Find a kluster that fits in one block (or page). We also
      * adjust the i/o if the file space is less than a while page. XXX
      */
-    if (off + tlen > avc->m.Length) {
-       tlen = avc->m.Length - off;
+    if (off + tlen > avc->f.m.Length) {
+       tlen = avc->f.m.Length - off;
     }
     /* can't call mapout with 0 length buffers (rmfree panics) */
-    if (((tlen>>24)&0xff) == 0xff) {
+    if (((tlen >> 24) & 0xff) == 0xff) {
        tlen = 0;
     }
     if ((int)tlen > 0) {
@@ -763,166 +616,48 @@ int afs_putapage(struct vnode *vp, struct page *pages,
         * Can't call mapout with 0 length buffers since we'll get rmfree panics
         */
        tbuf = pageio_setup(pages, tlen, vp, B_WRITE | flags);
-       if (!tbuf) return (ENOMEM);
+       if (!tbuf)
+           return (ENOMEM);
 
        tbuf->b_dev = 0;
-       tbuf->b_blkno = btodb(pages->p_offset);
+       tbuf->b_lblkno = lbtodb(pages->p_offset);
        bp_mapin(tbuf);
        AFS_GLOCK();
-       afs_Trace4(afs_iclSetp, CM_TRACE_PAGEOUTONE, ICL_TYPE_LONG, avc, 
-               ICL_TYPE_LONG, pages,
-               ICL_TYPE_LONG, tlen, 
-               ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(off));
+       afs_Trace4(afs_iclSetp, CM_TRACE_PAGEOUTONE, ICL_TYPE_LONG, avc,
+                  ICL_TYPE_LONG, pages, ICL_TYPE_LONG, tlen, ICL_TYPE_OFFSET,
+                  ICL_HANDLE_OFFSET(off));
        code = afs_ustrategy(tbuf, credp);      /* unlocks page */
        AFS_GUNLOCK();
        bp_mapout(tbuf);
     }
-    pvn_write_done(pages, ((code) ? B_ERROR:0) | B_WRITE | flags);
+    pvn_write_done(pages, ((code) ? B_ERROR : 0) | B_WRITE | flags);
     if ((int)tlen > 0)
        pageio_done(tbuf);
-    if (offp) *offp = off;
-    if (lenp) *lenp = tlen;
+    if (offp)
+       *offp = off;
+    if (lenp)
+       *lenp = tlen;
     return code;
 }
 
-#else  AFS_SUN5_ENV
-
-int afs_putpage(vp, off, len, flags, cred)
-struct vnode *vp;
-u_int off;
-u_int len;
-int flags;
-struct AFS_UCRED *cred;
-{
-    int wholeEnchilada;        /* true if we must get all of the pages */
-    struct vcache *avc;
-    struct page *pages;
-    struct page *tpage;
-    struct buf *tbuf;
-    afs_int32 tlen;
-    afs_int32 code = 0, rcode;
-    afs_int32 poffset;
-    afs_int32 clusterStart, clusterEnd, endPos;
-
-    /* In the wholeEnchilada case, we must ensure that we get all of the pages
-       from the system, since we're doing this to shutdown the use of a vnode */
-
-    AFS_STATCNT(afs_putpage);
-    wholeEnchilada = (off == 0 && len == 0 && (flags & (B_INVAL|B_ASYNC)) == B_INVAL);
-
-    avc = VTOAFS(vp);
-    afs_BozonLock(&avc->pvnLock, avc);
-    ObtainWriteLock(&avc->lock,248);
-
-    while (1) {
-       /* in whole enchilada case, loop until call to pvn_getdirty can't find
-          any more modified pages */
-
-       /* first we try to get a list of modified (or whatever) pages */
-       if (len == 0) {
-           pages = pvn_vplist_dirty(vp, off, flags);
-       }
-       else {
-           endPos = off + len; /* position we're supposed to write up to */
-           if (endPos > avc->m.Length) endPos = avc->m.Length; /* bound by this */
-           clusterStart = off & ~(PAGESIZE-1); /* round down to nearest page */
-           clusterEnd = ((endPos-1) | (PAGESIZE-1))+1; /* round up to nearest page */
-           pages = pvn_range_dirty(vp, off, endPos, clusterStart, clusterEnd, flags);
-       }
-       
-       /* Now we've got the modified pages.  All pages are locked and held */
-       rcode = 0;              /* return code */
-       while(pages) {  /* look over all pages in the returned set */
-           tpage = pages;      /* get first page in the list */
-
-           /* write out the page */
-           poffset = tpage->p_offset;  /* where the page starts in the file */
-           /* tlen will represent the end of the range to write, for a while */
-           tlen = PAGESIZE+poffset;    /* basic place to end tpage write */
-           /* but we also don't want to write past end of off..off+len range */
-           if (len != 0 && tlen > off+len) tlen = off+len;
-           /* and we don't want to write past the end of the file */
-           if (tlen > avc->m.Length) tlen = avc->m.Length;
-           /* and we don't want to write at all if page starts after end */
-           if (poffset >= tlen) {
-               pvn_fail(pages, B_WRITE | flags);
-               goto done;
-           }
-           /* finally change tlen from end position to length */
-           tlen -= poffset;    /* compute bytes to write from this page */
-           page_sub(&pages, tpage);    /* remove tpage from "pages" list */
-           tbuf = pageio_setup(tpage, tlen, vp, B_WRITE | flags);
-           if (!tbuf) {
-               pvn_fail(tpage, B_WRITE|flags);
-               pvn_fail(pages, B_WRITE|flags);
-               goto done;
-           }
-           tbuf->b_dev = 0;
-           tbuf->b_blkno = btodb(tpage->p_offset);
-           bp_mapin(tbuf);
-           ReleaseWriteLock(&avc->lock);       /* can't hold during strategy call */
-           code = afs_ustrategy(tbuf);         /* unlocks page */
-           ObtainWriteLock(&avc->lock,249);    /* re-obtain */
-           if (code) {
-               /* unlocking of tpage is done by afs_ustrategy */
-               rcode = code;
-               if (pages)      /* may have already removed last page */
-                   pvn_fail(pages, B_WRITE|flags);
-               goto done;
-           }
-       }       /* for (tpage=pages....) */
-
-       /* see if we've gotten all of the pages in the whole enchilada case */
-       if (!wholeEnchilada || !vp->v_pages) break;
-    }  /* while(1) obtaining all pages */
-
-    /*
-     * If low on chunks, and if writing the last byte of a chunk, try to
-     * free some.  Note that afs_DoPartialWrite calls osi_SyncVM which now
-     * calls afs_putpage, so this is recursion.  It stops there because we
-     * insist on len being non-zero.
-     */
-    if (afs_stats_cmperf.cacheCurrDirtyChunks > afs_stats_cmperf.cacheMaxDirtyChunks
-       && len != 0 && AFS_CHUNKOFFSET((off + len)) == 0)  {
-       struct vrequest treq;
-       if (!afs_InitReq(&treq, cred ? cred : u.u_cred)) {
-           rcode = afs_DoPartialWrite(avc, &treq);     /* XXX */
-       }
-    }
-    
-  done:
-
-    if (rcode && !avc->vc_error)
-       avc->vc_error = rcode;
-
-    /* when we're here, we just return code. */
-    ReleaseWriteLock(&avc->lock);
-    afs_BozonUnlock(&avc->pvnLock, avc);
-    return rcode;
-}
-
-#endif /* AFS_SUN5_ENV */
-
-int afs_nfsrdwr(avc, auio, arw, ioflag, acred)
-register struct vcache *avc;
-struct uio *auio;
-enum uio_rw arw;
-int ioflag;
-struct AFS_UCRED *acred;
+static int
+afs_nfsrdwr(struct vcache *avc, struct uio *auio, enum uio_rw arw,
+           int ioflag, afs_ucred_t *acred)
 {
-    register afs_int32 code;
+    afs_int32 code;
     afs_int32 code2;
+    afs_int32 code_checkcode = 0;
     int counter;
     afs_int32 mode, sflags;
-    register char *data;
+    char *data;
     struct dcache *dcp, *dcp_newpage;
     afs_size_t fileBase, size;
     afs_size_t pageBase;
-    register afs_int32 tsize;
-    register afs_int32 pageOffset, extraResid=0;
-    register afs_size_t origLength;            /* length when reading/writing started */
-    register long appendLength;                /* length when this call will finish */
-    int created;                       /* created pages instead of faulting them */
+    afs_int32 tsize;
+    afs_int32 pageOffset, extraResid = 0;
+    afs_size_t origLength;     /* length when reading/writing started */
+    long appendLength; /* length when this call will finish */
+    int created;               /* created pages instead of faulting them */
     int lockCode;
     int didFakeOpen, eof;
     struct vrequest treq;
@@ -932,36 +667,38 @@ struct AFS_UCRED *acred;
     AFS_STATCNT(afs_nfsrdwr);
 
     /* can't read or write other things */
-    if (vType(avc) != VREG) return EISDIR;
+    if (vType(avc) != VREG)
+       return EISDIR;
 
     if (auio->uio_resid == 0)
        return (0);
 
-    afs_Trace4(afs_iclSetp, CM_TRACE_VMRW, ICL_TYPE_POINTER, (afs_int32)avc,
-              ICL_TYPE_LONG, (arw==UIO_WRITE? 1 : 0),
-              ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(auio->uio_offset),
-              ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(auio->uio_resid));
+    afs_Trace4(afs_iclSetp, CM_TRACE_VMRW, ICL_TYPE_POINTER, (afs_int32) avc,
+              ICL_TYPE_LONG, (arw == UIO_WRITE ? 1 : 0), ICL_TYPE_OFFSET,
+              ICL_HANDLE_OFFSET(auio->uio_loffset), ICL_TYPE_OFFSET,
+              ICL_HANDLE_OFFSET(auio->uio_resid));
 
 #ifndef AFS_64BIT_CLIENT
-    if ( AfsLargeFileUio(auio) )       /* file is larger than 2 GB */
+    if (AfsLargeFileUio(auio)) /* file is larger than 2 GB */
        return (EFBIG);
 #endif
-    
-#ifdef AFS_SUN5_ENV
-    if (!acred) osi_Panic("rdwr: !acred");
-#else
-    if (!acred) acred = u.u_cred;
-#endif
-    if (code = afs_InitReq(&treq, acred)) return code;
+
+    if (!acred)
+       osi_Panic("rdwr: !acred");
+
+    if (code = afs_InitReq(&treq, acred))
+       return code;
 
     /* It's not really possible to know if a write cause a growth in the
      * cache size, we we wait for a cache drain for any write.
      */
     afs_MaybeWakeupTruncateDaemon();
-    while ((arw == UIO_WRITE) &&
-          (afs_blocksUsed > (CM_WAITFORDRAINPCT*afs_cacheBlocks)/100)) {
+    while ((arw == UIO_WRITE)
+          && (afs_blocksUsed > PERCENT(CM_WAITFORDRAINPCT, afs_cacheBlocks))) {
        if (afs_blocksUsed - afs_blocksDiscarded >
-           (CM_WAITFORDRAINPCT*afs_cacheBlocks)/100) {
+           PERCENT(CM_WAITFORDRAINPCT, afs_cacheBlocks)) {
+           if (afs_WaitForCacheDrain == 0)
+               afs_WaitForCacheDrainCount++;
            afs_WaitForCacheDrain = 1;
            afs_osi_Sleep(&afs_WaitForCacheDrain);
        }
@@ -969,61 +706,35 @@ struct AFS_UCRED *acred;
        afs_MaybeWakeupTruncateDaemon();
     }
     code = afs_VerifyVCache(avc, &treq);
-    if (code) return afs_CheckCode(code, &treq, 45);
+    if (code)
+       return afs_CheckCode(code, &treq, 45);
 
-    afs_BozonLock(&avc->pvnLock, avc);
-    osi_FlushPages(avc, acred);        /* hold bozon lock, but not basic vnode lock */
+    osi_FlushPages(avc, acred);
 
-    ObtainWriteLock(&avc->lock,250);
+    ObtainWriteLock(&avc->lock, 250);
 
     /* adjust parameters when appending files */
-    if ((ioflag & IO_APPEND) && arw == UIO_WRITE)
-    {
-#if    defined(AFS_SUN56_ENV)
-       auio->uio_loffset = 0;
-#endif
-       auio->uio_offset = avc->m.Length;       /* write at EOF position */
+    if ((ioflag & IO_APPEND) && arw == UIO_WRITE) {
+       auio->uio_loffset = avc->f.m.Length;    /* write at EOF position */
     }
-    if (auio->uio_offset < 0 || (auio->uio_offset + auio->uio_resid) < 0) {
-       ReleaseWriteLock(&avc->lock);   
-       afs_BozonUnlock(&avc->pvnLock, avc);
+    if (auio->afsio_offset < 0 || (auio->afsio_offset + auio->uio_resid) < 0) {
+       ReleaseWriteLock(&avc->lock);
        return EINVAL;
     }
-
 #ifndef AFS_64BIT_CLIENT
-                                       /* file is larger than 2GB */
-    if ( AfsLargeFileSize(auio->uio_offset, auio->uio_resid) ) {
-       ReleaseWriteLock(&avc->lock);   
-       afs_BozonUnlock(&avc->pvnLock, avc);
+    /* file is larger than 2GB */
+    if (AfsLargeFileSize(auio->uio_offset, auio->uio_resid)) {
+       ReleaseWriteLock(&avc->lock);
        return EFBIG;
     }
 #endif
 
-    didFakeOpen=0;     /* keep track of open so we can do close */
+    didFakeOpen = 0;           /* keep track of open so we can do close */
     if (arw == UIO_WRITE) {
        /* do ulimit processing; shrink resid or fail */
-#if    defined(AFS_SUN56_ENV)
        if (auio->uio_loffset + auio->afsio_resid > auio->uio_llimit) {
-           if (auio->uio_llimit >= auio->uio_llimit) {
-                ReleaseWriteLock(&avc->lock);
-                afs_BozonUnlock(&avc->pvnLock, avc);
-                return EFBIG;
-            } else {
-                /* track # of bytes we should write, but won't because of
-                 * ulimit; we must add this into the final resid value
-                 * so caller knows we punted some data.
-                 */
-                extraResid = auio->uio_resid;
-                auio->uio_resid = auio->uio_llimit - auio->uio_loffset;
-                extraResid -= auio->uio_resid;
-            }
-        }
-#else
-#ifdef AFS_SUN52_ENV   
-       if (auio->afsio_offset + auio->afsio_resid > auio->uio_limit) {
-           if (auio->afsio_offset >= auio->uio_limit) {
-               ReleaseWriteLock(&avc->lock);   
-               afs_BozonUnlock(&avc->pvnLock, avc);
+           if (auio->uio_loffset >= auio->uio_llimit) {
+               ReleaseWriteLock(&avc->lock);
                return EFBIG;
            } else {
                /* track # of bytes we should write, but won't because of
@@ -1031,106 +742,99 @@ struct AFS_UCRED *acred;
                 * so caller knows we punted some data.
                 */
                extraResid = auio->uio_resid;
-               auio->uio_resid = auio->uio_limit - auio->afsio_offset;
+               auio->uio_resid = auio->uio_llimit - auio->uio_loffset;
                extraResid -= auio->uio_resid;
            }
        }
-#endif
-#endif /* SUN56 */
        mode = S_WRITE;         /* segment map-in mode */
        afs_FakeOpen(avc);      /* do this for writes, so data gets put back
-                                  when we want it to be put back */
+                                * when we want it to be put back */
        didFakeOpen = 1;        /* we'll be doing a fake open */
        /* before starting any I/O, we must ensure that the file is big enough
-          to hold the results (since afs_putpage will be called to force the I/O */
+        * to hold the results (since afs_putpage will be called to force the I/O */
        size = auio->afsio_resid + auio->afsio_offset;  /* new file size */
-       appendLength = size;            
-       origLength = avc->m.Length;
-       if (size > avc->m.Length) {
-           afs_Trace4(afs_iclSetp, CM_TRACE_SETLENGTH,
-               ICL_TYPE_STRING, __FILE__,
-               ICL_TYPE_LONG, __LINE__,
-               ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(avc->m.Length),
-               ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(size));
-           avc->m.Length = size;       /* file grew */
+       appendLength = size;
+       origLength = avc->f.m.Length;
+       if (size > avc->f.m.Length) {
+           afs_Trace4(afs_iclSetp, CM_TRACE_SETLENGTH, ICL_TYPE_STRING,
+                      __FILE__, ICL_TYPE_LONG, __LINE__, ICL_TYPE_OFFSET,
+                      ICL_HANDLE_OFFSET(avc->f.m.Length), ICL_TYPE_OFFSET,
+                      ICL_HANDLE_OFFSET(size));
+           avc->f.m.Length = size;     /* file grew */
        }
-       avc->states |= CDirty;          /* Set the dirty bit */
-       avc->m.Date = osi_Time();       /* Set file date (for ranlib) */
+       avc->f.states |= CDirty;        /* Set the dirty bit */
+       avc->f.m.Date = osi_Time();     /* Set file date (for ranlib) */
     } else {
-       mode = S_READ;                  /* map-in read-only */
-       origLength = avc->m.Length;
+       mode = S_READ;          /* map-in read-only */
+       origLength = avc->f.m.Length;
     }
 
     if (acred && AFS_NFSXLATORREQ(acred)) {
        if (arw == UIO_READ) {
-           if (!afs_AccessOK(avc, PRSFS_READ, &treq,
-                             CHECK_MODE_BITS|CMB_ALLOW_EXEC_AS_READ)) {
-               ReleaseWriteLock(&avc->lock);   
-               afs_BozonUnlock(&avc->pvnLock, avc);
+           if (!afs_AccessOK
+               (avc, PRSFS_READ, &treq,
+                CHECK_MODE_BITS | CMB_ALLOW_EXEC_AS_READ)) {
+               ReleaseWriteLock(&avc->lock);
                return EACCES;
            }
        }
-#ifdef AFS_SUN5_ENV
        crhold(acred);
        if (avc->credp) {
            crfree(avc->credp);
        }
        avc->credp = acred;
-#endif
     }
-    counter = 0; /* don't call afs_DoPartialWrite first time through. */
+    counter = 0;               /* don't call afs_DoPartialWrite first time through. */
     while (1) {
        /* compute the amount of data to move into this block,
-          based on auio->afsio_resid.  Note that we copy data in units of
-          MAXBSIZE, not PAGESIZE.  This is because segmap_getmap panics if you
-          call it with an offset based on blocks smaller than MAXBSIZE
-          (implying that it should be named BSIZE, since it is clearly both a
-          max and a min). */
-       size = auio->afsio_resid;               /* transfer size */
-       fileBase = auio->afsio_offset;          /* start file position for xfr */
-       pageBase = fileBase & ~(MAXBSIZE-1);    /* file position of the page */
-       pageOffset = fileBase & (MAXBSIZE-1);   /* xfr start's offset within page */
-       tsize = MAXBSIZE-pageOffset;            /* how much more fits in this page */
+        * based on auio->afsio_resid.  Note that we copy data in units of
+        * MAXBSIZE, not PAGESIZE.  This is because segmap_getmap panics if you
+        * call it with an offset based on blocks smaller than MAXBSIZE
+        * (implying that it should be named BSIZE, since it is clearly both a
+        * max and a min). */
+       size = auio->afsio_resid;       /* transfer size */     
+       fileBase = ((arw == UIO_READ) && (origLength < auio->uio_offset)) ? 
+           origLength : auio->afsio_offset;  /* start file position for xfr */
+       pageBase = fileBase & ~(MAXBSIZE - 1);  /* file position of the page */
+       pageOffset = fileBase & (MAXBSIZE - 1); /* xfr start's offset within page */
+       tsize = MAXBSIZE - pageOffset;  /* how much more fits in this page */
        /* we'll read tsize bytes, but first must make sure tsize isn't too big */
-       if (tsize > size) tsize = size; /* don't read past end of request */
-       eof = 0;        /* flag telling us if we hit the EOF on the read */
-       if (arw == UIO_READ) {          /* we're doing a read operation */
+       if (tsize > size)
+           tsize = size;       /* don't read past end of request */
+       eof = 0;                /* flag telling us if we hit the EOF on the read */
+       if (arw == UIO_READ) {  /* we're doing a read operation */
            /* don't read past EOF */
            if (fileBase + tsize > origLength) {
                tsize = origLength - fileBase;
-               eof = 1;                /* we did hit the EOF */
-               if (tsize < 0) tsize = 0;       /* better safe than sorry */
+               eof = 1;        /* we did hit the EOF */
+               if (tsize < 0)
+                   tsize = 0;  /* better safe than sorry */
            }
            sflags = 0;
-       }
-       else {
-#ifdef AFS_SUN5_ENV
+       } else {
            /* Purge dirty chunks of file if there are too many dirty
             * chunks. Inside the write loop, we only do this at a chunk
             * boundary. Clean up partial chunk if necessary at end of loop.
             */
-           if (counter > 0 && code == 0 && AFS_CHUNKOFFSET(fileBase) == 0)
-               {
-                   code = afs_DoPartialWrite(avc, &treq);
-                   if (code)
-                       break;
-               }
-#endif /* AFS_SUN5_ENV */
+           if (counter > 0 && code == 0 && AFS_CHUNKOFFSET(fileBase) == 0) {
+               code = afs_DoPartialWrite(avc, &treq);
+               if (code)
+                   break;
+           }
            /* write case, we ask segmap_release to call putpage.  Really, we
-              don't have to do this on every page mapin, but for now we're
-              lazy, and don't modify the rest of AFS to scan for modified
-              pages on a close or other "synchronize with file server"
-              operation.  This makes things a little cleaner, but probably
-              hurts performance. */
+            * don't have to do this on every page mapin, but for now we're
+            * lazy, and don't modify the rest of AFS to scan for modified
+            * pages on a close or other "synchronize with file server"
+            * operation.  This makes things a little cleaner, but probably
+            * hurts performance. */
            sflags = SM_WRITE;
        }
        if (tsize <= 0) {
            code = 0;
-           break;      /* nothing to transfer, we're done */
+           break;              /* nothing to transfer, we're done */
        }
-#ifdef AFS_SUN5_ENV
        if (arw == UIO_WRITE)
-           avc->states |= CDirty; /* may have been cleared by DoPartialWrite*/
+           avc->f.states |= CDirty;    /* may have been cleared by DoPartialWrite */
 
        /* Before dropping lock, hold the chunk (create it if necessary).  This
         * serves two purposes:  (1) Ensure Cache Truncate Daemon doesn't try
@@ -1157,38 +861,17 @@ struct AFS_UCRED *acred;
            afs_size_t toff, tlen;
            dcp = afs_GetDCache(avc, fileBase, &treq, &toff, &tlen, 2);
            if (!dcp) {
-               code = ENOENT;  
+               code = EIO;
                break;
            }
        }
-#endif
        ReleaseWriteLock(&avc->lock);   /* uiomove may page fault */
        AFS_GUNLOCK();
-#if    defined(AFS_SUN56_ENV)
-       data = segmap_getmap(segkmap,AFSTOV(avc),(u_offset_t)pageBase);
-#else
-       data = segmap_getmap(segkmap, AFSTOV(avc), pageBase);
-#endif
-#ifndef        AFS_SUN5_ENV
-       code = afs_fc2errno(as_fault(&kas, data+pageOffset, tsize,
-                                    F_SOFTLOCK, mode));
-       if (code == 0) {
-           AFS_UIOMOVE(data+pageOffset, tsize, arw, auio, code);
-           as_fault(&kas, data+pageOffset, tsize, F_SOFTUNLOCK, mode);
-           code2 = segmap_release(segkmap, data, sflags);
-           if (!code)
-               code = code2;
-       }
-       else {
-           (void) segmap_release(segkmap, data, 0);
-       }
-#else
-#if defined(AFS_SUN56_ENV)
-       raddr = (caddr_t) (((uintptr_t)data +pageOffset) & PAGEMASK);
-#else
-        raddr = (caddr_t) (((u_int)data +pageOffset) & PAGEMASK);
-#endif
-       rsize = (((u_int)data+pageOffset+tsize+PAGEOFFSET) & PAGEMASK)-(u_int)raddr;
+       data = segmap_getmap(segkmap, AFSTOV(avc), (u_offset_t) pageBase);
+       raddr = (caddr_t) (((uintptr_t) data + pageOffset) & PAGEMASK);
+       rsize =
+           (((u_int) data + pageOffset + tsize + PAGEOFFSET) & PAGEMASK) -
+           (u_int) raddr;
        if (code == 0) {
            /* if we're doing a write, and we're starting at the rounded
             * down page base, and we're writing enough data to cover all
@@ -1196,9 +879,8 @@ struct AFS_UCRED *acred;
             * in this MAXBSIZE window that we're creating.
             */
            created = 0;
-           if (arw == UIO_WRITE
-                   && ((long)raddr == (long)data+pageOffset)
-                   && tsize >= rsize) {
+           if (arw == UIO_WRITE && ((long)raddr == (long)data + pageOffset)
+               && tsize >= rsize) {
                /* probably the dcache backing this guy is around, but if
                 * not, we can't do this optimization, since we're creating
                 * writable pages, which must be backed by a chunk.
@@ -1206,337 +888,264 @@ struct AFS_UCRED *acred;
                AFS_GLOCK();
                dcp_newpage = afs_FindDCache(avc, pageBase);
                if (dcp_newpage
-                   && hsame(avc->m.DataVersion, dcp_newpage->f.versionNo)) {
-                   ObtainWriteLock(&avc->lock,251);
-                   ObtainWriteLock(&avc->vlock,576);
+                   && afs_IsDCacheFresh(dcp_newpage, avc)) {
+                   ObtainWriteLock(&avc->lock, 251);
+                   ObtainWriteLock(&avc->vlock, 576);
                    ObtainReadLock(&dcp_newpage->lock);
                    if ((avc->activeV == 0)
-                       && hsame(avc->m.DataVersion, dcp_newpage->f.versionNo)
+                       && afs_IsDCacheFresh(dcp_newpage, avc)
                        && !(dcp_newpage->dflags & (DFFetching))) {
                        AFS_GUNLOCK();
                        segmap_pagecreate(segkmap, raddr, rsize, 1);
                        AFS_GLOCK();
-                       ObtainWriteLock(&afs_xdcache,252);
+                       ObtainWriteLock(&afs_xdcache, 252);
                        /* Mark the pages as created and dirty */
                        afs_indexFlags[dcp_newpage->index]
                            |= (IFAnyPages | IFDirtyPages);
-                       ReleaseWriteLock(&afs_xdcache);             
+                       ReleaseWriteLock(&afs_xdcache);
                        created = 1;
                    }
                    ReleaseReadLock(&dcp_newpage->lock);
                    afs_PutDCache(dcp_newpage);
                    ReleaseWriteLock(&avc->vlock);
                    ReleaseWriteLock(&avc->lock);
-               }
-               else if ( dcp_newpage )
+               } else if (dcp_newpage)
                    afs_PutDCache(dcp_newpage);
                AFS_GUNLOCK();
            }
            if (!created)
-               code = afs_fc2errno(segmap_fault(kas.a_hat, segkmap, raddr,
-                                                rsize, F_SOFTLOCK, mode));
+               code =
+                   afs_fc2errno(segmap_fault
+                                (kas.a_hat, segkmap, raddr, rsize,
+                                 F_SOFTLOCK, mode));
        }
        if (code == 0) {
-           AFS_UIOMOVE(data+pageOffset, tsize, arw, auio, code);
-           segmap_fault(kas.a_hat, segkmap, raddr, rsize, F_SOFTUNLOCK, mode);
+           AFS_UIOMOVE(data + pageOffset, tsize, arw, auio, code);
+           segmap_fault(kas.a_hat, segkmap, raddr, rsize, F_SOFTUNLOCK,
+                        mode);
        }
        if (code == 0) {
            code = segmap_release(segkmap, data, sflags);
        } else {
-           (void) segmap_release(segkmap, data, 0);
+           (void)segmap_release(segkmap, data, 0);
        }
-#endif /* AFS_SUN5_ENV */
        AFS_GLOCK();
-       ObtainWriteLock(&avc->lock,253);
-#ifdef AFS_SUN5_ENV
+       ObtainWriteLock(&avc->lock, 253);
        counter++;
-        if (dcp)       
-            afs_PutDCache(dcp);
-#endif /* AFS_SUN5_ENV */
-       if (code) break;
+       if (dcp)
+           afs_PutDCache(dcp);
+       if (code)
+           break;
     }
     if (didFakeOpen) {
        afs_FakeClose(avc, acred);
     }
-
-#ifdef AFS_SUN5_ENV
-    if (arw == UIO_WRITE && (avc->states & CDirty)) {
+    if (arw == UIO_WRITE && (avc->f.states & CDirty)) {
        code2 = afs_DoPartialWrite(avc, &treq);
        if (!code)
            code = code2;
     }
-#endif /* AFS_SUN5_ENV */
 
     if (!code && avc->vc_error) {
-       code = avc->vc_error;
+       code = code_checkcode = avc->vc_error;
     }
     ReleaseWriteLock(&avc->lock);
-    afs_BozonUnlock(&avc->pvnLock, avc);
     if (!code) {
-#ifdef AFS_SUN53_ENV
-       if ((ioflag & FSYNC) && (arw == UIO_WRITE) && !AFS_NFSXLATORREQ(acred))
-           code = afs_fsync(avc, 0, acred);
-#else
-       if ((ioflag & IO_SYNC) && (arw == UIO_WRITE)
+       if ((ioflag & FSYNC) && (arw == UIO_WRITE)
            && !AFS_NFSXLATORREQ(acred))
-           code = afs_fsync(avc, acred);
-#endif
+           code = afs_fsync(avc, 0, acred);
     }
-#ifdef AFS_SUN52_ENV   
     /* 
      * If things worked, add in as remaining in request any bytes
      * we didn't write due to file size ulimit.
      */
     if (code == 0 && extraResid > 0)
        auio->uio_resid += extraResid;
-#endif
-    return afs_CheckCode(code, &treq, 46);
+    if (code_checkcode) {
+       return code_checkcode;
+    } else {
+       return afs_CheckCode(code, &treq, 46);
+    }
 }
 
-afs_map(vp, off, as, addr, len, prot, maxprot, flags, cred)
-struct vnode *vp;
-struct as *as;
-#ifdef AFS_SUN5_ENV
-offset_t off;
-caddr_t *addr;
-#else
-u_int off;
-addr_t *addr;
-#endif
-u_int len;
-#ifdef AFS_SUN5_ENV
-u_char prot, maxprot;
-#else
-u_int prot, maxprot;
-#endif
-u_int flags;
-struct AFS_UCRED *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;
-       register afs_int32 code;
-       struct vrequest treq;
-       register struct vcache *avc = VTOAFS(vp);
+    struct segvn_crargs crargs;
+    afs_int32 code;
+    struct vrequest treq;
+    struct vcache *avc = VTOAFS(vp);
 
-       AFS_STATCNT(afs_map);
+    AFS_STATCNT(afs_map);
 
 
-       /* check for reasonableness on segment bounds; apparently len can be < 0 */
-       if (off < 0 || off + len < 0) {
-           return (EINVAL);
-       }
+    /* check for reasonableness on segment bounds; apparently len can be < 0 */
+    if (off < 0 || off + len < 0) {
+       return (EINVAL);
+    }
 #ifndef AFS_64BIT_CLIENT
-       if ( AfsLargeFileSize(off, len) ) /* file is larger than 2 GB */
-       {
-           code = EFBIG;
-           goto out;
-       }
+    if (AfsLargeFileSize(off, len)) {  /* file is larger than 2 GB */
+       code = EFBIG;
+       goto out;
+    }
 #endif
 
-#if    defined(AFS_SUN5_ENV)
-       if (vp->v_flag & VNOMAP)        /* File isn't allowed to be mapped */
-           return (ENOSYS);
+    if (vp->v_flag & VNOMAP)   /* File isn't allowed to be mapped */
+       return (ENOSYS);
 
-       if (vp->v_filocks)              /* if locked, disallow mapping */
-           return (EAGAIN);
-#endif
-       AFS_GLOCK();    
-       if (code = afs_InitReq(&treq, cred)) goto out;
+    if (vp->v_filocks)         /* if locked, disallow mapping */
+       return (EAGAIN);
 
-       if (vp->v_type != VREG) {
-           code = ENODEV;
-           goto out;
-        }
+    AFS_GLOCK();
+    if (code = afs_InitReq(&treq, cred))
+       goto out;
 
-       code = afs_VerifyVCache(avc, &treq);
-       if (code) {
-           goto out;
-       }
-       afs_BozonLock(&avc->pvnLock, avc);
-       osi_FlushPages(avc, cred);      /* ensure old pages are gone */
-       avc->states |= CMAPPED; /* flag cleared at afs_inactive */
-       afs_BozonUnlock(&avc->pvnLock, avc);
+    if (vp->v_type != VREG) {
+       code = ENODEV;
+       goto out;
+    }
 
-       AFS_GUNLOCK();
-#ifdef AFS_SUN5_ENV
-       as_rangelock(as);
-#endif
-       if ((flags & MAP_FIXED) == 0) {
-#if    defined(AFS_SUN57_ENV)
-          map_addr(addr, len, off, 1, flags); 
-#elif  defined(AFS_SUN56_ENV)
-           map_addr(addr, len, off, 1);
-#else
-           map_addr(addr, len, (off_t)off, 1);
-#endif
-           if (*addr == NULL) {
-#ifdef AFS_SUN5_ENV
-               as_rangeunlock(as);
-#endif
-               code = ENOMEM;
-               goto out1;
-           }
-       } else
-           (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.cred = cred;
-       crargs.type = flags&MAP_TYPE;
-       crargs.prot = prot;
-       crargs.maxprot = maxprot;
-       crargs.amp = (struct anon_map *) 0;
-#if    defined(AFS_SUN5_ENV)
-       crargs.flags = flags & ~MAP_TYPE;
-#endif
+    code = afs_VerifyVCache(avc, &treq);
+    if (code) {
+       goto out;
+    }
+    osi_FlushPages(avc, cred); /* ensure old pages are gone */
+    avc->f.states |= CMAPPED;  /* flag cleared at afs_inactive */
 
-       code = as_map(as, *addr, len, segvn_create, (char *) &crargs);
-#ifdef AFS_SUN5_ENV
-       as_rangeunlock(as);
+    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
-out1:
-       AFS_GLOCK();
-       code = afs_CheckCode(code, &treq, 47);
-       AFS_GUNLOCK();
-        return code;
-out:
-       code = afs_CheckCode(code, &treq, 48);
-       AFS_GUNLOCK();
-        return code;
-}
-
-/* Sun 4.0.X-specific code.  It computes the number of bytes that need
-    to be zeroed at the end of a page by pvn_vptrunc, given that you're
-    trying to get vptrunc to truncate a file to alen bytes.  The result
-    will be passed to pvn_vptrunc by the truncate code */
-#ifndef        AFS_SUN5_ENV            /* Not good for Solaris */
-afs_PageLeft(alen)
-register afs_int32 alen; {
-    register afs_int32 nbytes;
-
-    AFS_STATCNT(afs_PageLeft);
-    nbytes = PAGESIZE - (alen & PAGEOFFSET); /* amount to zap in last page */
-    /* now check if we'd zero the entire last page.  Don't need to do this
-       since pvn_vptrunc will handle this case properly (it will invalidate
-       this page) */
-    if (nbytes == PAGESIZE) nbytes = 0;
-    if (nbytes < 0) nbytes = 0;        /* just in case */
-    return nbytes;
+       if (*addr == NULL) {
+           as_rangeunlock(as);
+           code = ENOMEM;
+           goto out1;
+       }
+    } else
+       (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_offset_t)off;
+    crargs.cred = cred;
+    crargs.type = flags & MAP_TYPE;
+    crargs.prot = prot;
+    crargs.maxprot = maxprot;
+    crargs.amp = (struct anon_map *)0;
+    crargs.flags = flags & ~MAP_TYPE;
+
+    code = as_map(as, *addr, len, segvn_create, (char *)&crargs);
+    as_rangeunlock(as);
+  out1:
+    AFS_GLOCK();
+    code = afs_CheckCode(code, &treq, 47);
+    AFS_GUNLOCK();
+    return code;
+  out:
+    code = afs_CheckCode(code, &treq, 48);
+    AFS_GUNLOCK();
+    return code;
 }
-#endif
 
 
 /*
  * For Now We use standard local kernel params for AFS system values. Change this
  * at some point.
  */
-#if    defined(AFS_SUN5_ENV)
-afs_pathconf(vp, cmd, outdatap, credp)
-    register struct AFS_UCRED *credp;
+static int
+#ifdef AFS_SUN511_ENV
+afs_pathconf(struct vnode *vp, int cmd, u_long *outdatap,
+            afs_ucred_t *credp, caller_context_t *ct)
 #else
-afs_cntl(vp, cmd, indatap, outdatap, inflag, outflag)
-    int inflag, outflag;
-    char *indatap;
-#endif
-    struct vnode *vp;
-    int cmd;
-    u_long *outdatap;
+afs_pathconf(struct vnode *vp, int cmd, u_long *outdatap,
+            afs_ucred_t *credp)
+#endif /* AFS_SUN511_ENV */
 {
     AFS_STATCNT(afs_cntl);
     switch (cmd) {
-      case _PC_LINK_MAX:
+    case _PC_LINK_MAX:
        *outdatap = MAXLINK;
        break;
-      case _PC_NAME_MAX:
+    case _PC_NAME_MAX:
        *outdatap = MAXNAMLEN;
        break;
-      case _PC_PATH_MAX:
+    case _PC_PATH_MAX:
        *outdatap = MAXPATHLEN;
        break;
-      case _PC_CHOWN_RESTRICTED:
+    case _PC_CHOWN_RESTRICTED:
        *outdatap = 1;
        break;
-      case _PC_NO_TRUNC:
+    case _PC_NO_TRUNC:
        *outdatap = 1;
        break;
-#if    !defined(AFS_SUN5_ENV)
-      case _PC_MAX_CANON:
-       *outdatap = CANBSIZ;
-       break;
-      case _PC_VDISABLE:
-       *outdatap = VDISABLE;
-       break;
-      case _PC_PIPE_BUF:
-       return EINVAL;
-       break;
+    case _PC_FILESIZEBITS:
+#ifdef AFS_64BIT_CLIENT
+       *outdatap = 64;
+#else
+       *outdatap = 32;
 #endif
-      default:
-       return EINVAL;
+       break;
+    default:
+#ifdef AFS_SUN511_ENV
+       return fs_pathconf(vp, cmd, outdatap, credp, ct);
+#else
+       return fs_pathconf(vp, cmd, outdatap, credp);
+#endif /* AFS_SUN511_ENV */
     }
     return 0;
 }
 
-#endif /* AFS_SUN_ENV */
-
-#if    defined(AFS_SUN5_ENV)
-
-afs_ioctl(vnp, com, arg, flag, credp, rvalp)
-    struct vnode *vnp;
-    int com, arg, flag;
-    cred_t *credp;
-    int *rvalp;
+static int
+afs_ioctl(struct vnode *vnp, int com, int arg, int flag, cred_t *credp, 
+         int *rvalp)
 {
     return (ENOTTY);
 }
 
-void afs_rwlock(vnp, wlock)
-    struct vnode *vnp;
-    int wlock;
+static void
+afs_rwlock(struct vnode *vnp, int wlock)
 {
     rw_enter(&(VTOAFS(vnp))->rwlock, (wlock ? RW_WRITER : RW_READER));
 }
 
 
-void afs_rwunlock(vnp, wlock)
-    struct vnode *vnp;
-    int wlock;
+static void
+afs_rwunlock(struct vnode *vnp, int wlock)
 {
     rw_exit(&(VTOAFS(vnp))->rwlock);
 }
 
 
 /* NOT SUPPORTED */
-afs_seek(vnp, ooff, noffp)
-    struct vnode *vnp;
-    offset_t ooff;
-    offset_t *noffp;
+static int
+afs_seek(struct vnode *vnp, offset_t ooff, offset_t *noffp)
 {
-    register int code = 0;
+    int code = 0;
 
-    if ((*noffp < 0 || *noffp > MAXOFF_T))
+#ifndef AFS_64BIT_CLIENT
+# define __MAXOFF_T MAXOFF_T
+#else
+# define __MAXOFF_T MAXOFFSET_T
+#endif
+
+    if ((*noffp < 0 || *noffp > __MAXOFF_T))
        code = EINVAL;
     return code;
 }
 
-int afs_frlock(vnp, cmd, ap, flag, off,
+static int
 #ifdef AFS_SUN59_ENV
-              flkcb,
-#endif
-              credp)
-    struct vnode *vnp;
-    int cmd;
-#if    defined(AFS_SUN56_ENV)
-    struct flock64 *ap;
+afs_frlock(struct vnode *vnp, int cmd, struct flock64 *ap, int flag, 
+          offset_t off, struct flk_callback *flkcb, afs_ucred_t *credp)
 #else
-    struct flock *ap;
+afs_frlock(struct vnode *vnp, int cmd, struct flock64 *ap, int flag,
+          offset_t off, afs_ucred_t *credp)
 #endif
-    int flag;
-    offset_t off;
-#ifdef AFS_SUN59_ENV
-    struct flk_callback *flkcb;
-#endif
-    struct AFS_UCRED *credp;
 {
-    register afs_int32 code = 0;
+    afs_int32 code = 0;
     /*
      * Implement based on afs_lockctl
      */
@@ -1545,22 +1154,15 @@ int afs_frlock(vnp, cmd, ap, flag, off,
     if (flkcb)
        afs_warn("Don't know how to deal with flk_callback's!\n");
 #endif
-    if ((cmd == F_GETLK) || (cmd == F_O_GETLK) || (cmd == F_SETLK) || (cmd ==  F_SETLKW)) {
-#ifdef AFS_SUN53_ENV
+    if ((cmd == F_GETLK) || (cmd == F_O_GETLK) || (cmd == F_SETLK)
+       || (cmd == F_SETLKW)) {
        ap->l_pid = ttoproc(curthread)->p_pid;
        ap->l_sysid = 0;
-#else
-       ap->l_pid = ttoproc(curthread)->p_epid;
-       ap->l_sysid = ttoproc(curthread)->p_sysid;
-#endif
 
        AFS_GUNLOCK();
-#ifdef AFS_SUN56_ENV
        code = convoff(vnp, ap, 0, off);
-#else
-       code = convoff(vnp, ap, 0, (off_t)off);
-#endif
-       if (code) return code;
+       if (code)
+           return code;
        AFS_GLOCK();
     }
 
@@ -1570,45 +1172,28 @@ int afs_frlock(vnp, cmd, ap, flag, off,
 }
 
 
-int afs_space(vnp, cmd, ap, flag, off, credp)
-    struct vnode *vnp;
-    int cmd;
-#if    defined(AFS_SUN56_ENV)
-    struct flock64 *ap;
-#else
-    struct flock *ap;
-#endif
-    int flag;
-    offset_t off;
-    struct AFS_UCRED *credp;
+static int
+afs_space(struct vnode *vnp, int cmd, struct flock64 *ap, int flag, 
+         offset_t off, afs_ucred_t *credp)
 {
-    register afs_int32 code = EINVAL;
+    afs_int32 code = EINVAL;
     struct vattr vattr;
 
     if ((cmd == F_FREESP)
-#ifdef AFS_SUN56_ENV
        && ((code = convoff(vnp, ap, 0, off)) == 0)) {
-#else
-       && ((code = convoff(vnp, ap, 0, (off_t)off)) == 0)) {
-#endif
        AFS_GLOCK();
        if (!ap->l_len) {
            vattr.va_mask = AT_SIZE;
            vattr.va_size = ap->l_start;
            code = afs_setattr(VTOAFS(vnp), &vattr, 0, credp);
-       } 
+       }
        AFS_GUNLOCK();
     }
     return (code);
 }
 
-
-#endif
-
-int afs_dump(vp, addr, i1, i2)
-struct vnode *vp;
-caddr_t addr;
-int i1, i2;
+static int
+afs_dump(struct vnode *vp, caddr_t addr, int i1, int i2)
 {
     AFS_STATCNT(afs_dump);
     afs_warn("AFS_DUMP. MUST IMPLEMENT THIS!!!\n");
@@ -1617,432 +1202,534 @@ int i1, i2;
 
 
 /* Nothing fancy here; just compare if vnodes are identical ones */
-afs_cmp(vp1, vp2) 
-struct vnode *vp1, *vp2;
+static int
+afs_cmp(struct vnode *vp1, struct vnode *vp2)
 {
     AFS_STATCNT(afs_cmp);
-    return(vp1 == vp2);
+    return (vp1 == vp2);
 }
 
 
-int afs_realvp(struct vnode *vp, struct vnode **vpp) {
+static int
+afs_realvp(struct vnode *vp, struct vnode **vpp)
+{
     AFS_STATCNT(afs_realvp);
     return EINVAL;
 }
 
 
-int  afs_pageio(vp, pp, ui1, ui2, i1, credp)
-struct vnode *vp;
-struct page *pp;
-u_int ui1, ui2;
-int i1;
-struct cred *credp;
+static int
+afs_pageio(struct vnode *vp, struct page *pp, u_int ui1, u_int ui2, int i1, 
+          struct cred *credp)
 {
     afs_warn("afs_pageio: Not implemented\n");
     return EINVAL;
 }
 
-int  afs_dumpctl(vp, i
-#ifdef AFS_SUN59_ENV
-                , blkp
-#endif
-                )
-struct vnode *vp;
-int i;
+static int
 #ifdef AFS_SUN59_ENV
-int *blkp;
+afs_dumpctl(struct vnode *vp, int i, int *blkp)
+#else
+afs_dumpctl(struct vnode *vp, int i)
 #endif
 {
     afs_warn("afs_dumpctl: Not implemented\n");
     return EINVAL;
 }
 
-#ifdef AFS_SUN54_ENV
-extern void afs_dispose(vp, p, fl, dn, cr) 
-    struct vnode *vp;
-    struct page *p;
-    int fl, dn;
-    struct cred *cr;
+#ifdef AFS_SUN511_ENV
+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);
+}
+
+static int
+afs_setsecattr(struct vnode *vp, vsecattr_t *vsecattr, int flag, struct cred *creds, struct caller_context_t *ct)
+{
+    return ENOSYS;
+}
+
+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
+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  afs_setsecattr(vp, vsecattr, flag, creds)
-struct vnode *vp;
-vsecattr_t *vsecattr;
-int flag;
-struct cred *creds;
+static int
+afs_setsecattr(struct vnode *vp, vsecattr_t *vsecattr, int flag, 
+              struct cred *creds)
 {
     return ENOSYS;
 }
 
-int  afs_getsecattr(vp, vsecattr, flag, creds)
-struct vnode *vp;
-vsecattr_t *vsecattr;
-int flag;
-struct cred *creds;
+static int
+afs_getsecattr(struct vnode *vp, vsecattr_t *vsecattr, int flag, struct cred *creds)
 {
     return fs_fab_acl(vp, vsecattr, flag, creds);
 }
 #endif
 
 #ifdef AFS_GLOBAL_SUNLOCK
-extern int gafs_open(), gafs_close(), afs_ioctl(), gafs_access();
-extern int gafs_getattr(), gafs_setattr(), gafs_lookup(), gafs_create();
-extern int gafs_remove(), gafs_link(), gafs_rename(), gafs_mkdir();
-extern int gafs_rmdir(), gafs_readdir(), gafs_fsync(), gafs_symlink();
-extern int gafs_fid(), gafs_readlink(), fs_setfl(), afs_pathconf();
-extern int afs_lockctl();
-extern void gafs_inactive();
 
-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,
-#ifdef AFS_SUN54_ENV
-       afs_dispose,
-       afs_setsecattr,
-       afs_getsecattr,
-#endif
-#if    defined(AFS_SUN56_ENV)
-       fs_shrlock,
-#endif
-};
-struct vnodeops *afs_ops = &Afs_vnodeops;
-
-
-
-gafs_open(avcp, aflags, acred)
-    register struct vcache **avcp;
-    afs_int32 aflags;
-    struct AFS_UCRED *acred; 
+static int
+gafs_open(struct vnode **vpp, afs_int32 aflags, 
+         afs_ucred_t *acred)
 {
-    register int code;
+    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);
 }
 
-
-gafs_close(avc, aflags, count, offset, acred)
-    offset_t offset;
-    int count;
-    register struct vcache *avc;
-    afs_int32 aflags;
-    struct AFS_UCRED *acred; 
+static int
+gafs_close(struct vnode *vp, afs_int32 aflags, int count, 
+          offset_t offset, afs_ucred_t *acred)
 {
-    register int code;
-
+    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);
 }
 
-
-gafs_getattr(avc, attrs, flags, acred)
-    int flags;
-    register struct vcache *avc;
-    register struct vattr *attrs;
-    struct AFS_UCRED *acred; 
+static int
+gafs_getattr(struct vnode *vp, struct vattr *attrs, 
+            int flags, afs_ucred_t *acred)
 {
-    register int code;
-
+    int code;
     AFS_GLOCK();
-    code = afs_getattr(avc, attrs, flags, acred);
+    code = afs_getattr(VTOAFS(vp), attrs, flags, acred);
     AFS_GUNLOCK();
     return (code);
 }
 
 
-gafs_setattr(avc, attrs, flags, acred)
-    int flags;
-    register struct vcache *avc;
-    register struct vattr *attrs;
-    struct AFS_UCRED *acred; 
+static int
+gafs_setattr(struct vnode *vp, struct vattr *attrs, 
+            int flags, afs_ucred_t *acred)
 {
-    register int code;
-
+    int code;
     AFS_GLOCK();
-    code = afs_setattr(avc, attrs, flags, acred);
+    code = afs_setattr(VTOAFS(vp), attrs, flags, acred);
     AFS_GUNLOCK();
     return (code);
 }
 
 
-gafs_access(avc, amode, flags, acred)
-    int flags;         
-    register struct vcache *avc;
-    register afs_int32 amode;
-    struct AFS_UCRED *acred; 
+static int
+gafs_access(struct vnode *vp, afs_int32 amode, int flags, 
+           afs_ucred_t *acred)
 {
-    register int code;
-
+    int code;
     AFS_GLOCK();
-    code = afs_access(avc, amode, flags, acred);
+    code = afs_access(VTOAFS(vp), amode, flags, acred);
     AFS_GUNLOCK();
     return (code);
 }
 
 
-gafs_lookup(adp, aname, avcp, pnp, flags, rdir, acred)
-    struct pathname *pnp;
-    int flags;
-    struct vnode *rdir;
-    register struct vcache *adp, **avcp;
-    char *aname;
-    struct AFS_UCRED *acred; 
+static int
+gafs_lookup(struct vnode *dvp, char *aname, 
+           struct vnode **vpp, struct pathname *pnp, int flags, 
+           struct vnode *rdir, afs_ucred_t *acred)
 {
-    register int code;
+    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);
 }
 
 
-gafs_create(adp, aname, attrs, aexcl, amode, avcp, acred)
-    register struct vcache *adp;
-    char *aname;
-    struct vattr *attrs;
-    enum vcexcl aexcl;
-    int amode;
-    struct vcache **avcp;
-    struct AFS_UCRED *acred; 
+static int
+gafs_create(struct vnode *dvp, char *aname, struct vattr *attrs, 
+           enum vcexcl aexcl, int amode, struct vnode **vpp, 
+           afs_ucred_t *acred)
 {
-    register int code;
+    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);
 }
 
-gafs_remove(adp, aname, acred)
-    register struct vcache *adp;
-    char *aname;
-    struct AFS_UCRED *acred; 
+static int
+gafs_remove(struct vnode *vp, char *aname, afs_ucred_t *acred)
 {
-    register int code;
-
+    int code;
     AFS_GLOCK();
-    code = afs_remove(adp, aname, acred);
+    code = afs_remove(VTOAFS(vp), aname, acred);
     AFS_GUNLOCK();
     return (code);
 }
 
-gafs_link(adp, avc, aname, acred)
-    register struct vcache *avc;
-    register struct vcache *adp;
-    char *aname;
-    struct AFS_UCRED *acred; 
+static int
+gafs_link(struct vnode *dvp, struct vnode *svp, 
+         char *aname, afs_ucred_t *acred)
 {
-    register int code;
-
+    int code;
     AFS_GLOCK();
-    code = afs_link(adp, avc, aname, acred);
+    code = afs_link(VTOAFS(dvp), VTOAFS(svp), aname, acred);
     AFS_GUNLOCK();
     return (code);
 }
 
-gafs_rename(aodp, aname1, andp, aname2, acred)
-    register struct vcache *aodp, *andp;
-    char *aname1, *aname2;
-    struct AFS_UCRED *acred; 
+static int
+gafs_rename(struct vnode *odvp, char *aname1, 
+           struct vnode *ndvp, char *aname2, 
+           afs_ucred_t *acred)
 {
-    register int code;
+    int code;
+    struct vcache *aodp = VTOAFS(odvp);
+    struct vcache *andp = VTOAFS(ndvp);
 
     AFS_GLOCK();
     code = afs_rename(aodp, aname1, andp, aname2, acred);
+#ifdef AFS_SUN510_ENV
+    if (code == 0) {
+       struct vcache *avcp = NULL;
+       
+       (void) afs_lookup(andp, aname2, &avcp, NULL, 0, NULL, acred);
+       if (avcp) {
+           struct vnode *vp = AFSTOV(avcp), *pvp = AFSTOV(andp);
+
+# ifdef HAVE_VN_RENAMEPATH
+           vn_renamepath(pvp, vp, aname2, strlen(aname2));
+# else
+           mutex_enter(&vp->v_lock);
+           if (vp->v_path != NULL) {
+               kmem_free(vp->v_path, strlen(vp->v_path) + 1);
+               vp->v_path = NULL;
+           }
+           mutex_exit(&vp->v_lock);
+           vn_setpath(afs_globalVp, pvp, vp, aname2, strlen(aname2));
+# endif /* !HAVE_VN_RENAMEPATH */
+
+           AFS_RELE(AFSTOV(avcp));
+       }
+    }
+#endif
     AFS_GUNLOCK();
     return (code);
 }
 
-gafs_mkdir(adp, aname, attrs, avcp, acred)
-    register struct vcache *adp;
-    register struct vcache **avcp;
-    char *aname;
-    struct vattr *attrs;
-    struct AFS_UCRED *acred;
+static int
+gafs_mkdir(struct vnode *dvp, char *aname, struct vattr *attrs, 
+          struct vnode **vpp, afs_ucred_t *acred)
 {
-    register int code;
+    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);
 }
 
-
-gafs_rmdir(adp, aname, cdirp, acred)
-    struct vnode *cdirp;
-    register struct vcache *adp;
-    char *aname;
-    struct AFS_UCRED *acred; 
+static int
+gafs_rmdir(struct vnode *vp, char *aname, struct vnode *cdirp, 
+          afs_ucred_t *acred)
 {
-    register int code;
-
+    int code;
     AFS_GLOCK();
-    code = afs_rmdir(adp, aname, cdirp, acred);
+    code = afs_rmdir(VTOAFS(vp), aname, cdirp, acred);
     AFS_GUNLOCK();
     return (code);
 }
 
 
-gafs_readdir(avc, auio, acred, eofp)
-    int *eofp;
-    register struct vcache *avc;
-    struct uio *auio;
-    struct AFS_UCRED *acred; 
+static int
+gafs_readdir(struct vnode *vp, struct uio *auio,
+            afs_ucred_t *acred, int *eofp)
 {
-    register int code;
-
+    int code;
     AFS_GLOCK();
-    code = afs_readdir(avc, auio, acred, eofp);
+    code = afs_readdir(VTOAFS(vp), auio, acred, eofp);
     AFS_GUNLOCK();
-    return (code); 
+    return (code);
 }
 
-gafs_symlink(adp, aname, attrs, atargetName, acred)
-    register struct vcache *adp;
-    register char *atargetName;
-    char *aname;
-    struct vattr *attrs;
-    struct AFS_UCRED *acred; 
+static int
+gafs_symlink(struct vnode *vp, char *aname, struct vattr *attrs,
+            char *atargetName, afs_ucred_t *acred)
 {
-    register int code;
-
+    int code;
     AFS_GLOCK();
-    code = afs_symlink(adp, aname, attrs, atargetName, acred);
+    code = afs_symlink(VTOAFS(vp), aname, attrs, atargetName, NULL, acred);
     AFS_GUNLOCK();
     return (code);
 }
 
 
-gafs_readlink(avc, auio, acred)
-    register struct vcache *avc;
-    struct uio *auio;
-    struct AFS_UCRED *acred; 
+static int
+gafs_readlink(struct vnode *vp, struct uio *auio, afs_ucred_t *acred)
 {
-    register int code;
-
+    int code;
     AFS_GLOCK();
-    code = afs_readlink(avc, auio, acred);
+    code = afs_readlink(VTOAFS(vp), auio, acred);
     AFS_GUNLOCK();
     return (code);
 }
 
-#ifdef AFS_SUN53_ENV
-gafs_fsync(avc, flag, acred)
-    int flag;
-#else
-gafs_fsync(avc, acred)
-#endif
-    register struct vcache *avc;
-    struct AFS_UCRED *acred; 
+static int
+gafs_fsync(struct vnode *vp, int flag, afs_ucred_t *acred)
 {
-    register int code;
-
+    int code;
     AFS_GLOCK();
-#ifdef AFS_SUN53_ENV
-    code = afs_fsync(avc, flag, acred);
-#else
-    code = afs_fsync(avc, acred);
-#endif
+    code = afs_fsync(VTOAFS(vp), flag, acred);
     AFS_GUNLOCK();
     return (code);
 }
 
-void afs_inactive(struct vcache *avc, struct AFS_UCRED *acred)
+static int
+afs_inactive(struct vcache *avc, afs_ucred_t *acred)
 {
     struct vnode *vp = AFSTOV(avc);
-    if (afs_shuttingdown) return ;
+    if (afs_shuttingdown != AFS_RUNNING)
+       return 0;
 
     /*
      * In Solaris and HPUX s800 and HP-UX10.0 they actually call us with
      * v_count 1 on last reference!
      */
     mutex_enter(&vp->v_lock);
-    if (avc->vrefCount <= 0) osi_Panic("afs_inactive : v_count <=0\n");
+    if (avc->vrefCount <= 0)
+       osi_Panic("afs_inactive : v_count <=0\n");
 
     /*
      * If more than 1 don't unmap the vnode but do decrement the ref count
      */
     vp->v_count--;
     if (vp->v_count > 0) {
-        mutex_exit(&vp->v_lock);
-        return;
-    }  
-    mutex_exit(&vp->v_lock);    
+       mutex_exit(&vp->v_lock);
+       return 0;
+    }
+    mutex_exit(&vp->v_lock);
+
+#ifndef AFS_SUN511_ENV
     /*
-     * Solaris calls VOP_OPEN on exec, but isn't very diligent about calling
-     * VOP_CLOSE when executable exits.
+     * 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 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->states & CCore))
+    if (avc->opens > 0 && avc->mvstat == AFS_MVSTAT_FILE && !(avc->f.states & CCore))
        avc->opens = avc->execsOrWriters = 0;
+#endif
 
     afs_InactiveVCache(avc, acred);
+
+    AFS_GUNLOCK();
+    /* VFS_RELE must be called outside of GLOCK, since it can potentially
+     * call afs_freevfs, which acquires GLOCK */
+    VFS_RELE(afs_globalVFS);
+    AFS_GLOCK();
+
+    return 0;
 }
 
-void gafs_inactive(avc, acred)
-    register struct vcache *avc;
-    struct AFS_UCRED *acred; 
+static void
+gafs_inactive(struct vnode *vp, afs_ucred_t *acred)
 {
     AFS_GLOCK();
-    afs_inactive(avc, acred);
+    (void)afs_inactive(VTOAFS(vp), acred);
     AFS_GUNLOCK();
 }
 
 
-gafs_fid(avc, fidpp)
-struct vcache *avc;
-struct fid **fidpp;
+static int
+gafs_fid(struct vnode *vp, struct fid **fidpp)
 {
-    register int code;
-
+    int code;
     AFS_GLOCK();
-    code = afs_fid(avc, fidpp);
+    code = afs_fid(VTOAFS(vp), fidpp);
     AFS_GUNLOCK();
     return (code);
 }
 
-#endif  /* AFS_GLOBAL_SUNLOCK */
+#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 */