FBSD CM: don't call afs_close when recycling
[openafs.git] / src / afs / VNOPS / afs_vnop_write.c
index 5b08d42..ac0894e 100644 (file)
  * afs_MemWrite
  * afs_StoreOnLastReference
  * afs_close
- * afs_closex
  * afs_fsync
  */
 
 #include <afsconfig.h>
 #include "afs/param.h"
 
-RCSID
-    ("$Header$");
 
 #include "afs/sysincludes.h"   /* Standard vendor system headers */
 #include "afsincludes.h"       /* Afs-based standard headers */
@@ -39,8 +36,8 @@ extern unsigned char *afs_indexFlags;
  * avc->lock must be write-locked.
  */
 int
-afs_StoreOnLastReference(register struct vcache *avc,
-                        register struct vrequest *treq)
+afs_StoreOnLastReference(struct vcache *avc,
+                        struct vrequest *treq)
 {
     int code = 0;
 
@@ -49,8 +46,8 @@ afs_StoreOnLastReference(register struct vcache *avc,
      * ourselves now. If we're called by the CCore clearer, the CCore
      * flag will already be clear, so we don't have to worry about
      * clearing it twice. */
-    if (avc->states & CCore) {
-       avc->states &= ~CCore;
+    if (avc->f.states & CCore) {
+       avc->f.states &= ~CCore;
 #if defined(AFS_SGI_ENV)
        osi_Assert(avc->opens > 0 && avc->execsOrWriters > 0);
 #endif
@@ -61,7 +58,7 @@ afs_StoreOnLastReference(register struct vcache *avc,
        avc->opens--;
        avc->execsOrWriters--;
        AFS_RELE(AFSTOV(avc));  /* VN_HOLD at set CCore(afs_FakeClose) */
-       crfree((struct AFS_UCRED *)avc->linkData);      /* "crheld" in afs_FakeClose */
+       crfree((afs_ucred_t *)avc->linkData);   /* "crheld" in afs_FakeClose */
        avc->linkData = NULL;
     }
 
@@ -84,21 +81,9 @@ afs_StoreOnLastReference(register struct vcache *avc,
         * afs_{rd,wr} routines which means the vcache is a perfect candidate
         * for flushing!
         */
-
-#ifdef AFS_DISCON_ENV
      } else if (AFS_IS_DISCON_RW) {
-       /* Disconnected. */
-
-       if (!avc->ddirty_flags ||
-               (avc->ddirty_flags == VDisconShadowed)) {
-           /* Add to disconnected dirty list. */
-           AFS_DISCON_ADD_DIRTY(avc);
-       }
-
-       /* Set disconnected write flag. */
-       avc->ddirty_flags |= VDisconWriteClose;
-#endif
-    }          /* if not disconnected */
+       afs_DisconAddDirty(avc, VDisconWriteClose, 0);
+     }         /* if not disconnected */
 
 #if defined(AFS_SGI_ENV)
     osi_Assert(avc->opens > 0 && avc->execsOrWriters > 0);
@@ -109,11 +94,9 @@ afs_StoreOnLastReference(register struct vcache *avc,
     return code;
 }
 
-
-
 int
-afs_MemWrite(register struct vcache *avc, struct uio *auio, int aio,
-            struct AFS_UCRED *acred, int noLock)
+afs_MemWrite(struct vcache *avc, struct uio *auio, int aio,
+            afs_ucred_t *acred, int noLock)
 {
     afs_size_t totalLength;
     afs_size_t transferLength;
@@ -122,7 +105,7 @@ afs_MemWrite(register struct vcache *avc, struct uio *auio, int aio,
     afs_int32 tlen, trimlen;
     afs_int32 startDate;
     afs_int32 max;
-    register struct dcache *tdc;
+    struct dcache *tdc;
 #ifdef _HIGHC_
     volatile
 #endif
@@ -134,7 +117,7 @@ afs_MemWrite(register struct vcache *avc, struct uio *auio, int aio,
     struct uio *tuiop = &tuio;
     struct iovec *tvec;                /* again, should have define */
 #endif
-    register afs_int32 code;
+    afs_int32 code;
     struct vrequest treq;
 
     AFS_STATCNT(afs_MemWrite);
@@ -152,7 +135,7 @@ afs_MemWrite(register struct vcache *avc, struct uio *auio, int aio,
     afs_Trace4(afs_iclSetp, CM_TRACE_WRITE, ICL_TYPE_POINTER, avc,
               ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(filePos), ICL_TYPE_OFFSET,
               ICL_HANDLE_OFFSET(totalLength), ICL_TYPE_OFFSET,
-              ICL_HANDLE_OFFSET(avc->m.Length));
+              ICL_HANDLE_OFFSET(avc->f.m.Length));
     if (!noLock) {
        afs_MaybeWakeupTruncateDaemon();
        ObtainWriteLock(&avc->lock, 126);
@@ -166,8 +149,8 @@ afs_MemWrite(register struct vcache *avc, struct uio *auio, int aio,
         * Since we are called via strategy, we need to trim the write to
         * the actual size of the file
         */
-       osi_Assert(filePos <= avc->m.Length);
-       diff = avc->m.Length - filePos;
+       osi_Assert(filePos <= avc->f.m.Length);
+       diff = avc->f.m.Length - filePos;
        AFS_UIO_SETRESID(auio, MIN(totalLength, diff));
        totalLength = AFS_UIO_RESID(auio);
     }
@@ -177,7 +160,7 @@ afs_MemWrite(register struct vcache *avc, struct uio *auio, int aio,
 #if    defined(AFS_SUN56_ENV)
        auio->uio_loffset = 0;
 #endif
-       filePos = avc->m.Length;
+       filePos = avc->f.m.Length;
        AFS_UIO_SETOFFSET(auio, filePos);
     }
 #endif
@@ -185,7 +168,7 @@ afs_MemWrite(register struct vcache *avc, struct uio *auio, int aio,
      * Note that we use startDate rather than calling osi_Time() here.
      * This is to avoid counting lock-waiting time in file date (for ranlib).
      */
-    avc->m.Date = startDate;
+    avc->f.m.Date = startDate;
 
 #if    defined(AFS_HPUX_ENV)
 #if    defined(AFS_HPUX101_ENV)
@@ -205,77 +188,24 @@ afs_MemWrite(register struct vcache *avc, struct uio *auio, int aio,
      * high-level write op.
      */
     if (avc->execsOrWriters <= 0) {
-       printf("WARNING: afs_ufswr vp=%lx, exOrW=%d\n", (unsigned long)avc,
+       afs_warn("WARNING: afs_ufswr vp=%lx, exOrW=%d\n", (unsigned long)avc,
               avc->execsOrWriters);
     }
 #else
     afs_FakeOpen(avc);
 #endif
-    avc->states |= CDirty;
+    avc->f.states |= CDirty;
 #ifndef AFS_DARWIN80_ENV
     tvec = (struct iovec *)osi_AllocSmallSpace(sizeof(struct iovec));
 #endif
     while (totalLength > 0) {
-       /* 
-        *  The following line is necessary because afs_GetDCache with
-        *  flag == 4 expects the length field to be filled. It decides
-        *  from this whether it's necessary to fetch data into the chunk
-        *  before writing or not (when the whole chunk is overwritten!).
-        */
-       len = totalLength;      /* write this amount by default */
-       if (noLock) {
-           tdc = afs_FindDCache(avc, filePos);
-           if (tdc)
-               ObtainWriteLock(&tdc->lock, 653);
-       } else if (afs_blocksUsed >
-                  PERCENT(CM_WAITFORDRAINPCT, afs_cacheBlocks)) {
-           tdc = afs_FindDCache(avc, filePos);
-           if (tdc) {
-               ObtainWriteLock(&tdc->lock, 654);
-               if (!hsame(tdc->f.versionNo, avc->m.DataVersion)
-                   || (tdc->dflags & DFFetching)) {
-                   ReleaseWriteLock(&tdc->lock);
-                   afs_PutDCache(tdc);
-                   tdc = NULL;
-               }
-           }
-           if (!tdc) {
-               afs_MaybeWakeupTruncateDaemon();
-               while (afs_blocksUsed >
-                      PERCENT(CM_WAITFORDRAINPCT, afs_cacheBlocks)) {
-                   ReleaseWriteLock(&avc->lock);
-                   if (afs_blocksUsed - afs_blocksDiscarded >
-                       PERCENT(CM_WAITFORDRAINPCT, afs_cacheBlocks)) {
-                       afs_WaitForCacheDrain = 1;
-                       afs_osi_Sleep(&afs_WaitForCacheDrain);
-                   }
-                   afs_MaybeFreeDiscardedDCache();
-                   afs_MaybeWakeupTruncateDaemon();
-                   ObtainWriteLock(&avc->lock, 506);
-               }
-               avc->states |= CDirty;
-               tdc = afs_GetDCache(avc, filePos, &treq, &offset, &len, 4);
-               if (tdc)
-                   ObtainWriteLock(&tdc->lock, 655);
-           }
-       } else {
-           tdc = afs_GetDCache(avc, filePos, &treq, &offset, &len, 4);
-           if (tdc)
-               ObtainWriteLock(&tdc->lock, 656);
-       }
+       tdc = afs_ObtainDCacheForWriting(avc, filePos, totalLength, &treq, 
+                                        noLock);
        if (!tdc) {
            error = EIO;
            break;
        }
-       if (!(afs_indexFlags[tdc->index] & IFDataMod)) {
-           afs_stats_cmperf.cacheCurrDirtyChunks++;
-           afs_indexFlags[tdc->index] |= IFDataMod;    /* so it doesn't disappear */
-       }
-       if (!(tdc->f.states & DWriting)) {
-           /* don't mark entry as mod if we don't have to */
-           tdc->f.states |= DWriting;
-           tdc->dflags |= DFEntryMod;
-       }
+
        len = totalLength;      /* write this amount by default */
        offset = filePos - AFS_CHUNKTOBASE(tdc->f.chunk);
        max = AFS_CHUNKTOSIZE(tdc->f.chunk);    /* max size of this chunk */
@@ -298,12 +228,12 @@ afs_MemWrite(register struct vcache *avc, struct uio *auio, int aio,
 #endif
        AFS_UIO_SETOFFSET(tuiop, offset);
 
-       code = afs_MemWriteUIO(tdc->f.inode, tuiop);
+       code = afs_MemWriteUIO(&tdc->f.inode, tuiop);
        if (code) {
            void *mep;          /* XXX in prototype world is struct memCacheEntry * */
            error = code;
            ZapDCE(tdc);        /* bad data */
-           mep = afs_MemCacheOpen(tdc->f.inode);
+           mep = afs_MemCacheOpen(&tdc->f.inode);
            afs_MemCacheTruncate(mep, 0);
            afs_MemCacheClose(mep);
            afs_stats_cmperf.cacheCurrDirtyChunks--;
@@ -328,14 +258,16 @@ afs_MemWrite(register struct vcache *avc, struct uio *auio, int aio,
        filePos += len;
 #if defined(AFS_SGI_ENV)
        /* afs_xwrite handles setting m.Length */
-       osi_Assert(filePos <= avc->m.Length);
+       osi_Assert(filePos <= avc->f.m.Length);
 #else
-       if (filePos > avc->m.Length) {
+       if (filePos > avc->f.m.Length) {
+           if (AFS_IS_DISCON_RW)
+               afs_PopulateDCache(avc, filePos, &treq);
            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(avc->f.m.Length), ICL_TYPE_OFFSET,
                       ICL_HANDLE_OFFSET(filePos));
-           avc->m.Length = filePos;
+           avc->f.m.Length = filePos;
        }
 #endif
        ReleaseWriteLock(&tdc->lock);
@@ -373,8 +305,8 @@ afs_MemWrite(register struct vcache *avc, struct uio *auio, int aio,
 
 /* called on writes */
 int
-afs_UFSWrite(register struct vcache *avc, struct uio *auio, int aio,
-            struct AFS_UCRED *acred, int noLock)
+afs_UFSWrite(struct vcache *avc, struct uio *auio, int aio,
+            afs_ucred_t *acred, int noLock)
 {
     afs_size_t totalLength;
     afs_size_t transferLength;
@@ -384,7 +316,7 @@ afs_UFSWrite(register struct vcache *avc, struct uio *auio, int aio,
     afs_int32 trimlen;
     afs_int32 startDate;
     afs_int32 max;
-    register struct dcache *tdc;
+    struct dcache *tdc;
 #ifdef _HIGHC_
     volatile
 #endif
@@ -397,7 +329,7 @@ afs_UFSWrite(register struct vcache *avc, struct uio *auio, int aio,
     struct iovec *tvec;                /* again, should have define */
 #endif
     struct osi_file *tfile;
-    register afs_int32 code;
+    afs_int32 code;
     struct vrequest treq;
 
     AFS_STATCNT(afs_UFSWrite);
@@ -418,7 +350,7 @@ afs_UFSWrite(register struct vcache *avc, struct uio *auio, int aio,
     afs_Trace4(afs_iclSetp, CM_TRACE_WRITE, ICL_TYPE_POINTER, avc,
               ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(filePos), ICL_TYPE_OFFSET,
               ICL_HANDLE_OFFSET(totalLength), ICL_TYPE_OFFSET,
-              ICL_HANDLE_OFFSET(avc->m.Length));
+              ICL_HANDLE_OFFSET(avc->f.m.Length));
     if (!noLock) {
        afs_MaybeWakeupTruncateDaemon();
        ObtainWriteLock(&avc->lock, 556);
@@ -432,8 +364,8 @@ afs_UFSWrite(register struct vcache *avc, struct uio *auio, int aio,
         * Since we are called via strategy, we need to trim the write to
         * the actual size of the file
         */
-       osi_Assert(filePos <= avc->m.Length);
-       diff = avc->m.Length - filePos;
+       osi_Assert(filePos <= avc->f.m.Length);
+       diff = avc->f.m.Length - filePos;
        AFS_UIO_SETRESID(auio, MIN(totalLength, diff));
        totalLength = AFS_UIO_RESID(auio);
     }
@@ -443,15 +375,15 @@ afs_UFSWrite(register struct vcache *avc, struct uio *auio, int aio,
 #if     defined(AFS_SUN56_ENV)
        auio->uio_loffset = 0;
 #endif
-       filePos = avc->m.Length;
-       AFS_UIO_SETOFFSET(auio, avc->m.Length);
+       filePos = avc->f.m.Length;
+       AFS_UIO_SETOFFSET(auio, avc->f.m.Length);
     }
 #endif
     /*
      * Note that we use startDate rather than calling osi_Time() here.
      * This is to avoid counting lock-waiting time in file date (for ranlib).
      */
-    avc->m.Date = startDate;
+    avc->f.m.Date = startDate;
 
 #if    defined(AFS_HPUX_ENV)
 #if    defined(AFS_HPUX101_ENV)
@@ -471,83 +403,24 @@ afs_UFSWrite(register struct vcache *avc, struct uio *auio, int aio,
      * high-level write op.
      */
     if (avc->execsOrWriters <= 0) {
-       printf("WARNING: afs_ufswr vcp=%lx, exOrW=%d\n", (unsigned long)avc,
+       afs_warn("WARNING: afs_ufswr vcp=%lx, exOrW=%d\n", (unsigned long)avc,
               avc->execsOrWriters);
     }
 #else
     afs_FakeOpen(avc);
 #endif
-    avc->states |= CDirty;
+    avc->f.states |= CDirty;
 #ifndef AFS_DARWIN80_ENV
     tvec = (struct iovec *)osi_AllocSmallSpace(sizeof(struct iovec));
 #endif
     while (totalLength > 0) {
-       /* 
-        *  The following line is necessary because afs_GetDCache with
-        *  flag == 4 expects the length field to be filled. It decides
-        *  from this whether it's necessary to fetch data into the chunk
-        *  before writing or not (when the whole chunk is overwritten!).
-        */
-       len = totalLength;      /* write this amount by default */
-       /* read the cached info */
-       if (noLock) {
-           tdc = afs_FindDCache(avc, filePos);
-           if (tdc)
-               ObtainWriteLock(&tdc->lock, 657);
-       } else if (afs_blocksUsed >
-                  PERCENT(CM_WAITFORDRAINPCT, afs_cacheBlocks)) {
-           tdc = afs_FindDCache(avc, filePos);
-           if (tdc) {
-               ObtainWriteLock(&tdc->lock, 658);
-               if (!hsame(tdc->f.versionNo, avc->m.DataVersion)
-                   || (tdc->dflags & DFFetching)) {
-                   ReleaseWriteLock(&tdc->lock);
-                   afs_PutDCache(tdc);
-                   tdc = NULL;
-               }
-           }
-           if (!tdc) {
-               afs_MaybeWakeupTruncateDaemon();
-               while (afs_blocksUsed >
-                      PERCENT(CM_WAITFORDRAINPCT, afs_cacheBlocks)) {
-                   ReleaseWriteLock(&avc->lock);
-                   if (afs_blocksUsed - afs_blocksDiscarded >
-                       PERCENT(CM_WAITFORDRAINPCT, afs_cacheBlocks)) {
-                       afs_WaitForCacheDrain = 1;
-                       afs_osi_Sleep(&afs_WaitForCacheDrain);
-                   }
-                   afs_MaybeFreeDiscardedDCache();
-                   afs_MaybeWakeupTruncateDaemon();
-                   ObtainWriteLock(&avc->lock, 509);
-               }
-               avc->states |= CDirty;
-               tdc = afs_GetDCache(avc, filePos, &treq, &offset, &len, 4);
-               if (tdc)
-                   ObtainWriteLock(&tdc->lock, 659);
-           }
-       } else {
-           tdc = afs_GetDCache(avc, filePos, &treq, &offset, &len, 4);
-           if (tdc)
-               ObtainWriteLock(&tdc->lock, 660);
-       }
+       tdc = afs_ObtainDCacheForWriting(avc, filePos, totalLength, &treq, 
+                                        noLock);
        if (!tdc) {
            error = EIO;
            break;
        }
-       if (!(afs_indexFlags[tdc->index] & IFDataMod)) {
-           afs_stats_cmperf.cacheCurrDirtyChunks++;
-           afs_indexFlags[tdc->index] |= IFDataMod;    /* so it doesn't disappear */
-       }
-       if (!(tdc->f.states & DWriting)) {
-           /* don't mark entry as mod if we don't have to */
-           tdc->f.states |= DWriting;
-           tdc->dflags |= DFEntryMod;
-       }
-#if defined(LINUX_USE_FH)
-       tfile = (struct osi_file *)osi_UFSOpen_fh(&tdc->f.fh, tdc->f.fh_type);
-#else
-       tfile = (struct osi_file *)osi_UFSOpen(tdc->f.inode);
-#endif
+       tfile = (struct osi_file *)osi_UFSOpen(&tdc->f.inode);
        len = totalLength;      /* write this amount by default */
        offset = filePos - AFS_CHUNKTOBASE(tdc->f.chunk);
        max = AFS_CHUNKTOSIZE(tdc->f.chunk);    /* max size of this chunk */
@@ -603,22 +476,12 @@ afs_UFSWrite(register struct vcache *avc, struct uio *auio, int aio,
                ("\n\n\n*** Cache partition is full - decrease cachesize!!! ***\n\n\n");
 #elif defined(AFS_SGI_ENV)
        AFS_GUNLOCK();
-       avc->states |= CWritingUFS;
+       avc->f.states |= CWritingUFS;
        AFS_VOP_RWLOCK(tfile->vnode, VRWLOCK_WRITE);
        AFS_VOP_WRITE(tfile->vnode, &tuio, IO_ISLOCKED, afs_osi_credp, code);
        AFS_VOP_RWUNLOCK(tfile->vnode, VRWLOCK_WRITE);
-       avc->states &= ~CWritingUFS;
+       avc->f.states &= ~CWritingUFS;
        AFS_GLOCK();
-#elif defined(AFS_OSF_ENV)
-       {
-           struct ucred *tmpcred = u.u_cred;
-           u.u_cred = afs_osi_credp;
-           tuio.uio_rw = UIO_WRITE;
-           AFS_GUNLOCK();
-           VOP_WRITE(tfile->vnode, &tuio, 0, afs_osi_credp, code);
-           AFS_GLOCK();
-           u.u_cred = tmpcred;
-       }
 #elif defined(AFS_HPUX100_ENV)
        {
            AFS_GUNLOCK();
@@ -645,12 +508,18 @@ afs_UFSWrite(register struct vcache *avc, struct uio *auio, int aio,
        code = VOP_WRITE(tfile->vnode, &tuio, 0, afs_osi_credp);
        VOP_UNLOCK(tfile->vnode, 0);
        AFS_GLOCK();
-#elif defined(AFS_FBSD50_ENV)
+#elif defined(AFS_FBSD_ENV)
        AFS_GUNLOCK();
        VOP_LOCK(tfile->vnode, LK_EXCLUSIVE, curthread);
        code = VOP_WRITE(tfile->vnode, &tuio, 0, afs_osi_credp);
        VOP_UNLOCK(tfile->vnode, 0, curthread);
        AFS_GLOCK();
+#elif defined(AFS_NBSD_ENV)
+       AFS_GUNLOCK();
+       VOP_LOCK(tfile->vnode, LK_EXCLUSIVE);
+       code = VOP_WRITE(tfile->vnode, &tuio, 0, afs_osi_credp);
+       VOP_UNLOCK(tfile->vnode, 0);
+       AFS_GLOCK();
 #elif defined(AFS_XBSD_ENV)
        AFS_GUNLOCK();
        VOP_LOCK(tfile->vnode, LK_EXCLUSIVE, curproc);
@@ -691,14 +560,16 @@ afs_UFSWrite(register struct vcache *avc, struct uio *auio, int aio,
        filePos += len;
 #if defined(AFS_SGI_ENV)
        /* afs_xwrite handles setting m.Length */
-       osi_Assert(filePos <= avc->m.Length);
+       osi_Assert(filePos <= avc->f.m.Length);
 #else
-       if (filePos > avc->m.Length) {
+       if (filePos > avc->f.m.Length) {
+           if (AFS_IS_DISCON_RW)
+               afs_PopulateDCache(avc, filePos, &treq);
            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(avc->f.m.Length), ICL_TYPE_OFFSET,
                       ICL_HANDLE_OFFSET(filePos));
-           avc->m.Length = filePos;
+           avc->f.m.Length = filePos;
        }
 #endif
        osi_UFSClose(tfile);
@@ -759,16 +630,17 @@ afs_UFSWrite(register struct vcache *avc, struct uio *auio, int aio,
 
 /* do partial write if we're low on unmodified chunks */
 int
-afs_DoPartialWrite(register struct vcache *avc, struct vrequest *areq)
+afs_DoPartialWrite(struct vcache *avc, struct vrequest *areq)
 {
-    register afs_int32 code;
+    afs_int32 code;
 
     if (afs_stats_cmperf.cacheCurrDirtyChunks <=
-       afs_stats_cmperf.cacheMaxDirtyChunks)
+       afs_stats_cmperf.cacheMaxDirtyChunks
+       || AFS_IS_DISCONNECTED)
        return 0;               /* nothing to do */
     /* otherwise, call afs_StoreDCache (later try to do this async, if possible) */
     afs_Trace2(afs_iclSetp, CM_TRACE_PARTIALWRITE, ICL_TYPE_POINTER, avc,
-              ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(avc->m.Length));
+              ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(avc->f.m.Length));
 
 #if    defined(AFS_SUN5_ENV)
     code = afs_StoreAllSegments(avc, areq, AFS_ASYNC | AFS_VMSYNC_INVAL);
@@ -778,108 +650,26 @@ afs_DoPartialWrite(register struct vcache *avc, struct vrequest *areq)
     return code;
 }
 
-#ifdef AFS_OSF_ENV
-#ifdef AFS_DUX50_ENV
-#define vno_close(X) vn_close((X), 0, NOCRED)
-#elif defined(AFS_DUX40_ENV)
-#define      vno_close       vn_close
-#endif
-/* We don't need this for AIX since: 
- * (1) aix doesn't use fileops and it call close directly intead
- * (where the unlocking should be done) and 
- * (2) temporarily, the aix lockf isn't supported yet.
- *
- *  this stupid routine is used to release the flocks held on a
- *  particular file descriptor.  Sun doesn't pass file descr. info
- *  through to the vnode layer, and yet we must unlock flocked files
- *  on the *appropriate* (not first, as in System V) close call.  Thus
- *  this code.
- * How does this code get invoked? The afs AFS_FLOCK plugs in the new afs
- * file ops structure into any afs file when it gets flocked. 
- * N.B: Intercepting close syscall doesn't trap aborts or exit system
- * calls.
-*/
-int
-afs_closex(register struct file *afd)
-{
-    struct vrequest treq;
-    struct vcache *tvc;
-    afs_int32 flags;
-    int closeDone;
-    afs_int32 code = 0;
-    struct afs_fakestat_state fakestat;
-
-    AFS_STATCNT(afs_closex);
-    /* setup the credentials */
-    if ((code = afs_InitReq(&treq, u.u_cred)))
-       return code;
-    afs_InitFakeStat(&fakestat);
-
-    closeDone = 0;
-    /* we're the last one.  If we're an AFS vnode, clear the flags,
-     * close the file and release the lock when done.  Otherwise, just
-     * let the regular close code work.      */
-    if (afd->f_type == DTYPE_VNODE) {
-       tvc = VTOAFS(afd->f_data);
-       if (IsAfsVnode(AFSTOV(tvc))) {
-           code = afs_EvalFakeStat(&tvc, &fakestat, &treq);
-           if (code) {
-               afs_PutFakeStat(&fakestat);
-               return code;
-           }
-           VN_HOLD(AFSTOV(tvc));
-           flags = afd->f_flag & (FSHLOCK | FEXLOCK);
-           afd->f_flag &= ~(FSHLOCK | FEXLOCK);
-           code = vno_close(afd);
-           if (flags)
-               HandleFlock(tvc, LOCK_UN, &treq, u.u_procp->p_pid,
-                           1 /*onlymine */ );
-           AFS_RELE(AFSTOV(tvc));
-           closeDone = 1;
-       }
-    }
-    /* now, if close not done, do it */
-    if (!closeDone) {
-       code = vno_close(afd);
-    }
-    afs_PutFakeStat(&fakestat);
-    return code;               /* return code from vnode layer */
-}
-#endif
-
-
 /* handle any closing cleanup stuff */
 int
-#ifdef AFS_SGI_ENV
-afs_close(OSI_VC_ARG(avc), aflags, lastclose,
-#if !defined(AFS_SGI65_ENV)
-         offset,
-#endif
-         acred
-#if defined(AFS_SGI64_ENV) && !defined(AFS_SGI65_ENV)
-         , flp
-#endif
-    )
-     lastclose_t lastclose;
-#if !defined(AFS_SGI65_ENV)
-     off_t offset;
-#if defined(AFS_SGI64_ENV)
-     struct flid *flp;
-#endif
-#endif
+#if defined(AFS_SGI65_ENV)
+afs_close(OSI_VC_DECL(avc), afs_int32 aflags, lastclose_t lastclose,
+         afs_ucred_t *acred)
+#elif defined(AFS_SGI64_ENV)
+afs_close(OSI_VC_DECL(avc), afs_int32 aflags, lastclose_t lastclose,
+         off_t offset, afs_ucred_t *acred, struct flid *flp)
+#elif defined(AFS_SGI_ENV)
+afs_close(OSI_VC_DECL(avc), afs_int32 aflags, lastclose_t lastclose
+         off_t offset, afs_ucred_t *acred)
 #elif defined(AFS_SUN5_ENV)
-afs_close(OSI_VC_ARG(avc), aflags, count, offset, acred)
-     offset_t offset;
-     int count;
+afs_close(OSI_VC_DECL(avc), afs_int32 aflags, int count, offset_t offset, 
+        afs_ucred_t *acred)
 #else
-afs_close(OSI_VC_ARG(avc), aflags, acred)
+afs_close(OSI_VC_DECL(avc), afs_int32 aflags, afs_ucred_t *acred)
 #endif
-     OSI_VC_DECL(avc);
-     afs_int32 aflags;
-     struct AFS_UCRED *acred;
 {
-    register afs_int32 code;
-    register struct brequest *tb;
+    afs_int32 code;
+    struct brequest *tb;
     struct vrequest treq;
 #ifdef AFS_SGI65_ENV
     struct flid flid;
@@ -913,36 +703,34 @@ afs_close(OSI_VC_ARG(avc), aflags, acred)
     }
     /* unlock any locks for pid - could be wrong for child .. */
     AFS_RWLOCK((vnode_t *) avc, VRWLOCK_WRITE);
-#ifdef AFS_SGI65_ENV
+# ifdef AFS_SGI65_ENV
     get_current_flid(&flid);
     cleanlocks((vnode_t *) avc, flid.fl_pid, flid.fl_sysid);
     HandleFlock(avc, LOCK_UN, &treq, flid.fl_pid, 1 /*onlymine */ );
-#else
-#ifdef AFS_SGI64_ENV
+# else
+#  ifdef AFS_SGI64_ENV
     cleanlocks((vnode_t *) avc, flp);
-#else /* AFS_SGI64_ENV */
+#  else /* AFS_SGI64_ENV */
     cleanlocks((vnode_t *) avc, u.u_procp->p_epid, u.u_procp->p_sysid);
-#endif /* AFS_SGI64_ENV */
+#  endif /* AFS_SGI64_ENV */
     HandleFlock(avc, LOCK_UN, &treq, OSI_GET_CURRENT_PID(), 1 /*onlymine */ );
-#endif /* AFS_SGI65_ENV */
+# endif /* AFS_SGI65_ENV */
     /* afs_chkpgoob will drop and re-acquire the global lock. */
-    afs_chkpgoob(&avc->v, btoc(avc->m.Length));
-#elif  defined(AFS_SUN5_ENV)
+    afs_chkpgoob(&avc->v, btoc(avc->f.m.Length));
+#elif defined(AFS_SUN5_ENV)
     if (count > 1) {
-       /* The vfs layer may call this repeatedly with higher "count"; only on the last close (i.e. count = 1) we should actually proceed with the close. */
+       /* The vfs layer may call this repeatedly with higher "count"; only
+        * on the last close (i.e. count = 1) we should actually proceed
+        * with the close. */
        afs_PutFakeStat(&fakestat);
        AFS_DISCON_UNLOCK();
        return 0;
     }
-#else /* AFS_SGI_ENV */
-    if (avc->flockCount) {     /* Release Lock */
-#if    defined(AFS_OSF_ENV) 
-       HandleFlock(avc, LOCK_UN, &treq, u.u_procp->p_pid, 1 /*onlymine */ );
 #else
+    if (avc->flockCount) {     /* Release Lock */
        HandleFlock(avc, LOCK_UN, &treq, 0, 1 /*onlymine */ );
-#endif
     }
-#endif /* AFS_SGI_ENV */
+#endif
     if (aflags & (FWRITE | FTRUNC)) {
        if (afs_BBusy() || (AFS_NFSXLATORREQ(acred)) || AFS_IS_DISCONNECTED) {
            /* do it yourself if daemons are all busy */
@@ -959,8 +747,8 @@ afs_close(OSI_VC_ARG(avc), aflags, acred)
            /* at least one daemon is idle, so ask it to do the store.
             * Also, note that  we don't lock it any more... */
            tb = afs_BQueue(BOP_STORE, avc, 0, 1, acred,
-                           (afs_size_t) acred->cr_uid, (afs_size_t) 0,
-                           (void *)0);
+                           (afs_size_t) afs_cr_uid(acred), (afs_size_t) 0,
+                           (void *)0, (void *)0, (void *)0);
            /* sleep waiting for the store to start, then retrieve error code */
            while ((tb->flags & BUVALID) == 0) {
                tb->flags |= BUWAIT;
@@ -985,7 +773,7 @@ afs_close(OSI_VC_ARG(avc), aflags, acred)
 #ifdef AFS_AIX32_ENV
            osi_ReleaseVM(avc, acred);
 #endif
-           printf("avc->vc_error=%d\n", avc->vc_error);
+           /* printf("avc->vc_error=%d\n", avc->vc_error); */
            code = avc->vc_error;
            avc->vc_error = 0;
        }
@@ -1027,14 +815,25 @@ afs_close(OSI_VC_ARG(avc), aflags, acred)
            code = avc->vc_error;
            avc->vc_error = 0;
        }
+#if defined(AFS_FBSD80_ENV)
+        /* XXX */
+        if (!avc->opens) {
+            afs_int32 opens, is_free, is_gone, is_doomed, iflag;
+            struct vnode *vp = AFSTOV(avc);
+            VI_LOCK(vp);
+            is_doomed =  vp->v_iflag & VI_DOOMED;
+            is_free = vp->v_iflag & VI_FREE;
+            is_gone = vp->v_iflag & VI_DOINGINACT;
+            iflag = vp->v_iflag;
+            VI_UNLOCK(vp);
+            opens = avc->opens;
+            afs_warn("afs_close avc %p vp %p opens %d free %d doinginact %d doomed %d iflag %d\n",
+                     avc, vp, opens, is_free, is_gone, is_doomed, iflag);
+        }
+#endif
        avc->opens--;
        ReleaseWriteLock(&avc->lock);
     }
-#ifdef AFS_OSF_ENV
-    if ((VREFCOUNT(avc) <= 2) && (avc->states & CUnlinked)) {
-       afs_remunlink(avc, 1);  /* ignore any return code */
-    }
-#endif
     AFS_DISCON_UNLOCK();
     afs_PutFakeStat(&fakestat);
     code = afs_CheckCode(code, &treq, 5);
@@ -1043,21 +842,17 @@ afs_close(OSI_VC_ARG(avc), aflags, acred)
 
 
 int
-#ifdef AFS_OSF_ENV
-afs_fsync(OSI_VC_DECL(avc), int fflags, struct AFS_UCRED *acred, int waitfor)
-#else                          /* AFS_OSF_ENV */
 #if defined(AFS_SGI_ENV) || defined(AFS_SUN53_ENV)
-afs_fsync(OSI_VC_DECL(avc), int flag, struct AFS_UCRED *acred
-#ifdef AFS_SGI65_ENV
+afs_fsync(OSI_VC_DECL(avc), int flag, afs_ucred_t *acred
+# ifdef AFS_SGI65_ENV
          , off_t start, off_t stop
-#endif /* AFS_SGI65_ENV */
+# endif /* AFS_SGI65_ENV */
     )
-#else /* !OSF && !SUN53 && !SGI */
-afs_fsync(OSI_VC_DECL(avc), struct AFS_UCRED *acred)
+#else /* !SUN53 && !SGI */
+afs_fsync(OSI_VC_DECL(avc), afs_ucred_t *acred)
 #endif 
-#endif
 {
-    register afs_int32 code;
+    afs_int32 code;
     struct vrequest treq;
     OSI_VC_CONVERT(avc);
 
@@ -1084,34 +879,17 @@ afs_fsync(OSI_VC_DECL(avc), struct AFS_UCRED *acred)
     ObtainSharedLock(&avc->lock, 18);
     code = 0;
     if (avc->execsOrWriters > 0) {
-
        if (!AFS_IS_DISCONNECTED && !AFS_IS_DISCON_RW) {
-               /* Your average flush. */
-
-               /* put the file back */
-               UpgradeSToWLock(&avc->lock, 41);
-               code = afs_StoreAllSegments(avc, &treq, AFS_SYNC);
-               ConvertWToSLock(&avc->lock);
-
-#if defined(AFS_DISCON_ENV)
+           /* Your average flush. */
+           
+           /* put the file back */
+           UpgradeSToWLock(&avc->lock, 41);
+           code = afs_StoreAllSegments(avc, &treq, AFS_SYNC);
+           ConvertWToSLock(&avc->lock);
        } else {
-           /* Disconnected flush. */
-           ObtainWriteLock(&afs_DDirtyVCListLock, 708);
-
-           if (!avc->ddirty_flags ||
-               (avc->ddirty_flags == VDisconShadowed)) {
-
-               /* Add to disconnected dirty list. */
-               AFS_DISCON_ADD_DIRTY(avc);
-           }
-
            UpgradeSToWLock(&avc->lock, 711);
-           /* Set disconnected write flag. */
-           avc->ddirty_flags |= VDisconWriteFlush;
+           afs_DisconAddDirty(avc, VDisconWriteFlush, 1);
            ConvertWToSLock(&avc->lock);
-
-           ReleaseWriteLock(&afs_DDirtyVCListLock);
-#endif
        }               /* if not disconnected */
     }                  /* if (avc->execsOrWriters > 0) */