vclosevnodefiles-ihandle-leak-20090216
[openafs.git] / src / vol / vnode.c
index 8ed9a89..8918f5e 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright 2000, International Business Machines Corporation and others.
  * All Rights Reserved.
- * 
+ *
  * This software has been released under the terms of the IBM Public
  * License.  For details, see the LICENSE file in the top-level source
  * directory or online at http://www.openafs.org/dl/license10.html
@@ -17,6 +17,9 @@
  */
 #include <afsconfig.h>
 #include <afs/param.h>
+
+#include <roken.h>
+
 #define MAXINT     (~(1<<((sizeof(int)*8)-1)))
 
 
 #include <stdio.h>
 #include <string.h>
 #include <stdarg.h>
-#ifdef AFS_PTHREAD_ENV
-#include <assert.h>
-#else /* AFS_PTHREAD_ENV */
-#include <afs/assert.h>
-#endif /* AFS_PTHREAD_ENV */
+#include <afs/afs_assert.h>
 
 #include <rx/xdr.h>
 #include "rx/rx_queue.h"
@@ -45,6 +44,7 @@
 #include "vnode_inline.h"
 #include "partition.h"
 #include "salvsync.h"
+#include "common.h"
 #if defined(AFS_SGI_ENV)
 #include "sys/types.h"
 #include "fcntl.h"
 # include <stdint.h>
 #endif
 
-/*@printflike@*/ extern void Log(const char *format, ...);
-
-/*@printflike@*/ extern void Abort(const char *format, ...) AFS_NORETURN;
-
-
 struct VnodeClassInfo VnodeClassInfo[nVNODECLASSES];
 
 void VNLog(afs_int32 aop, afs_int32 anparms, ... );
@@ -113,7 +108,7 @@ static afs_int32 vnLogPtr = 0;
 void
 VNLog(afs_int32 aop, afs_int32 anparms, ... )
 {
-    register afs_int32 temp;
+    afs_int32 temp;
     va_list ap;
 
     va_start(ap, anparms);
@@ -200,7 +195,7 @@ AddToVVnList(Volume * vp, Vnode * vnp)
  * @internal volume package internal use only
  */
 void
-DeleteFromVVnList(register Vnode * vnp)
+DeleteFromVVnList(Vnode * vnp)
 {
     Vn_volume(vnp) = NULL;
 
@@ -263,7 +258,7 @@ DeleteFromVnLRU(struct VnodeClassInfo * vcp, Vnode * vnp)
     if (vnp == vcp->lruHead)
        vcp->lruHead = vcp->lruHead->lruNext;
 
-    if ((vnp == vcp->lruHead) || 
+    if ((vnp == vcp->lruHead) ||
        (vcp->lruHead == NULL))
        Abort("DeleteFromVnLRU: lru chain addled!\n");
 
@@ -348,7 +343,7 @@ DeleteFromVnHash(Vnode * vnp)
  * @internal vnode package internal use only
  */
 void
-VInvalidateVnode_r(register struct Vnode *avnode)
+VInvalidateVnode_r(struct Vnode *avnode)
 {
     avnode->changed_newTime = 0;       /* don't let it get flushed out again */
     avnode->changed_oldTime = 0;
@@ -379,13 +374,13 @@ int
 VInitVnodes(VnodeClass class, int nVnodes)
 {
     byte *va;
-    register struct VnodeClassInfo *vcp = &VnodeClassInfo[class];
+    struct VnodeClassInfo *vcp = &VnodeClassInfo[class];
 
     vcp->allocs = vcp->gets = vcp->reads = vcp->writes = 0;
     vcp->cacheSize = nVnodes;
     switch (class) {
     case vSmall:
-       assert(CHECKSIZE_SMALLVNODE);
+       osi_Assert(CHECKSIZE_SMALLVNODE);
        vcp->lruHead = NULL;
        vcp->residentSize = SIZEOF_SMALLVNODE;
        vcp->diskSize = SIZEOF_SMALLDISKVNODE;
@@ -410,13 +405,13 @@ VInitVnodes(VnodeClass class, int nVnodes)
        return 0;
 
     va = (byte *) calloc(nVnodes, vcp->residentSize);
-    assert(va != NULL);
+    osi_Assert(va != NULL);
     while (nVnodes--) {
        Vnode *vnp = (Vnode *) va;
        Vn_refcount(vnp) = 0;   /* no context switches */
        Vn_stateFlags(vnp) |= VN_ON_LRU;
 #ifdef AFS_DEMAND_ATTACH_FS
-       assert(pthread_cond_init(&Vn_stateCV(vnp), NULL) == 0);
+       CV_INIT(&Vn_stateCV(vnp), "vnode state", CV_DEFAULT, 0);
        Vn_state(vnp) = VN_STATE_INVALID;
        Vn_readers(vnp) = 0;
 #else /* !AFS_DEMAND_ATTACH_FS */
@@ -462,9 +457,9 @@ VInitVnodes(VnodeClass class, int nVnodes)
  *       state is set to VN_STATE_INVALID.
  *       inode handle is released.
  *
- * @note we traverse backwards along the lru circlist.  It shouldn't 
- *       be necessary to specify that nUsers == 0 since if it is in the list, 
- *       nUsers should be 0.  Things shouldn't be in lruq unless no one is 
+ * @note we traverse backwards along the lru circlist.  It shouldn't
+ *       be necessary to specify that nUsers == 0 since if it is in the list,
+ *       nUsers should be 0.  Things shouldn't be in lruq unless no one is
  *       using them.
  *
  * @warning DAFS: VOL_LOCK is dropped while doing inode handle release
@@ -474,7 +469,7 @@ VInitVnodes(VnodeClass class, int nVnodes)
 Vnode *
 VGetFreeVnode_r(struct VnodeClassInfo * vcp)
 {
-    register Vnode *vnp;
+    Vnode *vnp;
 
     vnp = vcp->lruHead->lruPrev;
 #ifdef AFS_DEMAND_ATTACH_FS
@@ -487,9 +482,9 @@ VGetFreeVnode_r(struct VnodeClassInfo * vcp)
 #endif
     VNLog(1, 2, Vn_id(vnp), (intptr_t)vnp, 0, 0);
 
-    /* 
+    /*
      * it's going to be overwritten soon enough.
-     * remove from LRU, delete hash entry, and 
+     * remove from LRU, delete hash entry, and
      * disassociate from old parent volume before
      * we have a chance to drop the vol glock
      */
@@ -510,7 +505,7 @@ VGetFreeVnode_r(struct VnodeClassInfo * vcp)
         *   - ihandle package lock contention
         *   - closing file descriptor(s) associated with ih
         *
-        * Hance, we perform outside of the volume package lock in order to 
+        * Hance, we perform outside of the volume package lock in order to
         * reduce the probability of contention.
         */
        IH_RELEASE(vnp->handle);
@@ -552,8 +547,8 @@ VLookupVnode(Volume * vp, VnodeId vnodeId)
 
     newHash = VNODE_HASH(vp, vnodeId);
     for (vnp = VnodeHashTable[newHash];
-        (vnp && 
-         ((Vn_id(vnp) != vnodeId) || 
+        (vnp &&
+         ((Vn_id(vnp) != vnodeId) ||
           (Vn_volume(vnp) != vp) ||
           (vp->cacheCheck != Vn_cacheCheck(vnp))));
         vnp = vnp->hashNext);
@@ -589,10 +584,10 @@ VAllocVnode(Error * ec, Volume * vp, VnodeType type)
 Vnode *
 VAllocVnode_r(Error * ec, Volume * vp, VnodeType type)
 {
-    register Vnode *vnp;
+    Vnode *vnp;
     VnodeId vnodeNumber;
     int bitNumber;
-    register struct VnodeClassInfo *vcp;
+    struct VnodeClassInfo *vcp;
     VnodeClass class;
     Unique unique;
 #ifdef AFS_DEMAND_ATTACH_FS
@@ -674,9 +669,6 @@ VAllocVnode_r(Error * ec, Volume * vp, VnodeType type)
            /* This won't block */
            VnLock(vnp, WRITE_LOCK, VOL_LOCK_HELD, WILL_NOT_DEADLOCK);
        } else {
-           /* other users present; follow locking hierarchy */
-           VnLock(vnp, WRITE_LOCK, VOL_LOCK_HELD, MIGHT_DEADLOCK);
-
 #ifdef AFS_DEMAND_ATTACH_FS
            /*
             * DAFS:
@@ -694,6 +686,9 @@ VAllocVnode_r(Error * ec, Volume * vp, VnodeType type)
            }
 #endif
 
+           /* other users present; follow locking hierarchy */
+           VnLock(vnp, WRITE_LOCK, VOL_LOCK_HELD, MIGHT_DEADLOCK);
+
            /*
             * verify state of the world hasn't changed
             *
@@ -708,6 +703,28 @@ VAllocVnode_r(Error * ec, Volume * vp, VnodeType type)
            }
        }
 
+       /* sanity check: vnode should be blank if it was deleted. If it's
+        * not blank, it is still in use somewhere; but the bitmap told us
+        * this vnode number was free, so something is wrong. */
+       if (vnp->disk.type != vNull) {
+           Error tmp;
+           Log("VAllocVnode:  addled bitmap or vnode object! (vol %ld, "
+               "vnode %p, number %ld, type %ld)\n", (long)vp->hashid, vnp,
+               (long)Vn_id(vnp), (long)vnp->disk.type);
+           *ec = EIO;
+           VFreeBitMapEntry_r(&tmp, vp, &vp->vnodeIndex[class], bitNumber,
+                              VOL_FREE_BITMAP_WAIT);
+           VInvalidateVnode_r(vnp);
+           VnUnlock(vnp, WRITE_LOCK);
+           VnCancelReservation_r(vnp);
+#ifdef AFS_DEMAND_ATTACH_FS
+           VRequestSalvage_r(ec, vp, SALVSYNC_ERROR, 0);
+#else
+           VForceOffline_r(vp, 0);
+#endif
+           return NULL;
+       }
+
     } else {
        /* no such vnode in the cache */
 
@@ -749,7 +766,7 @@ VAllocVnode_r(Error * ec, Volume * vp, VnodeType type)
             *
             * if this becomes a bottleneck, there are ways to
             * improve parallelism for this code path
-            *   -- tkeiser 11/28/2007 
+            *   -- tkeiser 11/28/2007
             */
            VCreateReservation_r(vp);
            VWaitExclusiveState_r(vp);
@@ -768,13 +785,8 @@ VAllocVnode_r(Error * ec, Volume * vp, VnodeType type)
                *ec = EIO;
                goto error_encountered;
            }
-           if (FDH_SEEK(fdP, off, SEEK_SET) < 0) {
-               Log("VAllocVnode: can't seek on index file!\n");
-               *ec = EIO;
-               goto error_encountered;
-           }
            if (off + vcp->diskSize <= size) {
-               if (FDH_READ(fdP, &vnp->disk, vcp->diskSize) != vcp->diskSize) {
+             if (FDH_PREAD(fdP, &vnp->disk, vcp->diskSize, off) != vcp->diskSize) {
                    Log("VAllocVnode: can't read index file!\n");
                    *ec = EIO;
                    goto error_encountered;
@@ -788,12 +800,13 @@ VAllocVnode_r(Error * ec, Volume * vp, VnodeType type)
                /* growing file - grow in a reasonable increment */
                char *buf = (char *)malloc(16 * 1024);
                if (!buf) {
+                   Log("VAllocVnode: can't grow vnode index: out of memory\n");
                    *ec = ENOMEM;
                    goto error_encountered;
                }
                memset(buf, 0, 16 * 1024);
-               if ((FDH_WRITE(fdP, buf, 16 * 1024)) != 16 * 1024) {
-                   Log("VAllocVnode: can't grow vnode index: out of memory\n");
+               if ((FDH_PWRITE(fdP, buf, 16 * 1024, off)) != 16 * 1024) {
+                   Log("VAllocVnode: can't grow vnode index: write failed\n");
                    *ec = EIO;
                    free(buf);
                    goto error_encountered;
@@ -811,7 +824,7 @@ VAllocVnode_r(Error * ec, Volume * vp, VnodeType type)
 
 
        error_encountered:
-           /* 
+           /*
             * close the file handle
             * acquire VOL_LOCK
             * invalidate the vnode
@@ -822,7 +835,7 @@ VAllocVnode_r(Error * ec, Volume * vp, VnodeType type)
            if (fdP)
                FDH_CLOSE(fdP);
            VOL_LOCK;
-           VFreeBitMapEntry_r(&tmp, &vp->vnodeIndex[class], bitNumber);
+           VFreeBitMapEntry_r(&tmp, vp, &vp->vnodeIndex[class], bitNumber, 0 /*flags*/);
            VInvalidateVnode_r(vnp);
            VnUnlock(vnp, WRITE_LOCK);
            VnCancelReservation_r(vnp);
@@ -877,7 +890,7 @@ VAllocVnode_r(Error * ec, Volume * vp, VnodeType type)
  * @internal vnode package internal use only
  */
 static void
-VnLoad(Error * ec, Volume * vp, Vnode * vnp, 
+VnLoad(Error * ec, Volume * vp, Vnode * vnp,
        struct VnodeClassInfo * vcp, VnodeClass class)
 {
     /* vnode not cached */
@@ -886,6 +899,7 @@ VnLoad(Error * ec, Volume * vp, Vnode * vnp,
     ssize_t nBytes;
     IHandle_t *ihP = vp->vnodeIndex[class].handle;
     FdHandle_t *fdP;
+    afs_ino_str_t stmp;
 
     *ec = 0;
     vcp->reads++;
@@ -901,21 +915,16 @@ VnLoad(Error * ec, Volume * vp, Vnode * vnp,
     fdP = IH_OPEN(ihP);
     if (fdP == NULL) {
        Log("VnLoad: can't open index dev=%u, i=%s\n", vp->device,
-           PrintInode(NULL, vp->vnodeIndex[class].handle->ih_ino));
+           PrintInode(stmp, vp->vnodeIndex[class].handle->ih_ino));
        *ec = VIO;
        goto error_encountered_nolock;
-    } else if (FDH_SEEK(fdP, vnodeIndexOffset(vcp, Vn_id(vnp)), SEEK_SET)
-              < 0) {
-       Log("VnLoad: can't seek on index file vn=%u\n", Vn_id(vnp));
-       *ec = VIO;
-       goto error_encountered_nolock;
-    } else if ((nBytes = FDH_READ(fdP, (char *)&vnp->disk, vcp->diskSize))
+    } else if ((nBytes = FDH_PREAD(fdP, (char *)&vnp->disk, vcp->diskSize, vnodeIndexOffset(vcp, Vn_id(vnp))))
               != vcp->diskSize) {
        /* Don't take volume off line if the inumber is out of range
         * or the inode table is full. */
        if (nBytes == BAD_IGET) {
            Log("VnLoad: bad inumber %s\n",
-               PrintInode(NULL, vp->vnodeIndex[class].handle->ih_ino));
+               PrintInode(stmp, vp->vnodeIndex[class].handle->ih_ino));
            *ec = VIO;
            dosalv = 0;
        } else if (nBytes == -1 && errno == EIO) {
@@ -923,8 +932,8 @@ VnLoad(Error * ec, Volume * vp, Vnode * vnp,
            Log("VnLoad: Couldn't read vnode %u, volume %u (%s); volume needs salvage\n", Vn_id(vnp), V_id(vp), V_name(vp));
        } else {
            /* vnode is not allocated */
-           if (LogLevel >= 5) 
-               Log("VnLoad: Couldn't read vnode %u, volume %u (%s); read %d bytes, errno %d\n", 
+           if (LogLevel >= 5)
+               Log("VnLoad: Couldn't read vnode %u, volume %u (%s); read %d bytes, errno %d\n",
                    Vn_id(vnp), V_id(vp), V_name(vp), (int)nBytes, errno);
            *ec = VIO;
            dosalv = 0;
@@ -944,6 +953,12 @@ VnLoad(Error * ec, Volume * vp, Vnode * vnp,
            unsigned int bitNumber = vnodeIdToBitNumber(Vn_id(vnp));
            unsigned int offset = bitNumber >> 3;
 
+#ifdef AFS_DEMAND_ATTACH_FS
+           /* Make sure the volume bitmap isn't getting updated while we are
+            * checking it */
+           VWaitExclusiveState_r(vp);
+#endif
+
            /* Test to see if vnode number is valid. */
            if ((offset >= index->bitmapSize)
                || ((*(index->bitmap + offset) & (1 << (bitNumber & 0x7)))
@@ -1006,13 +1021,14 @@ VnLoad(Error * ec, Volume * vp, Vnode * vnp,
  * @internal vnode package internal use only
  */
 static void
-VnStore(Error * ec, Volume * vp, Vnode * vnp, 
+VnStore(Error * ec, Volume * vp, Vnode * vnp,
        struct VnodeClassInfo * vcp, VnodeClass class)
 {
     ssize_t nBytes;
     afs_foff_t offset;
     IHandle_t *ihP = vp->vnodeIndex[class].handle;
     FdHandle_t *fdP;
+    afs_ino_str_t stmp;
 #ifdef AFS_DEMAND_ATTACH_FS
     VnState vn_state_save;
 #endif
@@ -1030,13 +1046,7 @@ VnStore(Error * ec, Volume * vp, Vnode * vnp,
        Log("VnStore: can't open index file!\n");
        goto error_encountered;
     }
-    if (FDH_SEEK(fdP, offset, SEEK_SET) < 0) {
-       Log("VnStore: can't seek on index file! fdp=0x%x offset=%d, errno=%d\n",
-           fdP, offset, errno);
-       goto error_encountered;
-    }
-
-    nBytes = FDH_WRITE(fdP, &vnp->disk, vcp->diskSize);
+    nBytes = FDH_PWRITE(fdP, &vnp->disk, vcp->diskSize, offset);
     if (nBytes != vcp->diskSize) {
        /* Don't force volume offline if the inumber is out of
         * range or the inode table is full.
@@ -1044,7 +1054,7 @@ VnStore(Error * ec, Volume * vp, Vnode * vnp,
        FDH_REALLYCLOSE(fdP);
        if (nBytes == BAD_IGET) {
            Log("VnStore: bad inumber %s\n",
-               PrintInode(NULL,
+               PrintInode(stmp,
                           vp->vnodeIndex[class].handle->ih_ino));
            *ec = VIO;
            VOL_LOCK;
@@ -1071,7 +1081,7 @@ VnStore(Error * ec, Volume * vp, Vnode * vnp,
     VnChangeState_r(vnp, vn_state_save);
 #endif
     return;
-    
+
  error_encountered:
 #ifdef AFS_DEMAND_ATTACH_FS
     /* XXX instead of dumping core, let's try to request a salvage
@@ -1082,7 +1092,7 @@ VnStore(Error * ec, Volume * vp, Vnode * vnp,
     VnChangeState_r(vnp, VN_STATE_ERROR);
     VRequestSalvage_r(ec, vp, SALVSYNC_ERROR, 0);
 #else
-    assert(1 == 2);
+    osi_Assert(1 == 2);
 #endif
 }
 
@@ -1126,7 +1136,7 @@ VGetVnode(Error * ec, Volume * vp, VnodeId vnodeNumber, int locktype)
 Vnode *
 VGetVnode_r(Error * ec, Volume * vp, VnodeId vnodeNumber, int locktype)
 {                              /* READ_LOCK or WRITE_LOCK, as defined in lock.h */
-    register Vnode *vnp;
+    Vnode *vnp;
     VnodeClass class;
     struct VnodeClassInfo *vcp;
 
@@ -1300,7 +1310,7 @@ int TrustVnodeCacheEntry = 1;
 /* This variable is bogus--when it's set to 0, the hash chains fill
    up with multiple versions of the same vnode.  Should fix this!! */
 void
-VPutVnode(Error * ec, register Vnode * vnp)
+VPutVnode(Error * ec, Vnode * vnp)
 {
     VOL_LOCK;
     VPutVnode_r(ec, vnp);
@@ -1323,17 +1333,17 @@ VPutVnode(Error * ec, register Vnode * vnp)
  * @internal volume package internal use only
  */
 void
-VPutVnode_r(Error * ec, register Vnode * vnp)
+VPutVnode_r(Error * ec, Vnode * vnp)
 {
     int writeLocked;
     VnodeClass class;
     struct VnodeClassInfo *vcp;
 
     *ec = 0;
-    assert(Vn_refcount(vnp) != 0);
+    osi_Assert(Vn_refcount(vnp) != 0);
     class = vnodeIdToClass(Vn_id(vnp));
     vcp = &VnodeClassInfo[class];
-    assert(vnp->disk.vnodeMagic == vcp->magic);
+    osi_Assert(vnp->disk.vnodeMagic == vcp->magic);
     VNLog(200, 2, Vn_id(vnp), (intptr_t) vnp, 0, 0);
 
 #ifdef AFS_DEMAND_ATTACH_FS
@@ -1355,14 +1365,14 @@ VPutVnode_r(Error * ec, register Vnode * vnp)
                                                changed_oldTime) << 1) | vnp->
              delete, 0, 0);
        if (thisProcess != vnp->writer)
-           Abort("VPutVnode: Vnode at 0x%x locked by another process!\n",
+           Abort("VPutVnode: Vnode at %"AFS_PTR_FMT" locked by another process!\n",
                  vnp);
 
 
        if (vnp->changed_oldTime || vnp->changed_newTime || vnp->delete) {
            Volume *vp = Vn_volume(vnp);
            afs_uint32 now = FT_ApproxTime();
-           assert(Vn_cacheCheck(vnp) == vp->cacheCheck);
+           osi_Assert(Vn_cacheCheck(vnp) == vp->cacheCheck);
 
            if (vnp->delete) {
                /* No longer any directory entries for this vnode. Free the Vnode */
@@ -1384,7 +1394,7 @@ VPutVnode_r(Error * ec, register Vnode * vnp)
 #ifdef AFS_DEMAND_ATTACH_FS
                VRequestSalvage_r(ec, vp, SALVSYNC_ERROR, 0);
 #else
-               assert(V_needsSalvaged(vp));
+               osi_Assert(V_needsSalvaged(vp));
                *ec = VSALVAGE;
 #endif
            } else {
@@ -1398,8 +1408,9 @@ VPutVnode_r(Error * ec, register Vnode * vnp)
                if (vnp->delete && !*ec) {
                    if (Vn_volume(vnp)->header->diskstuff.filecount-- < 1)
                        Vn_volume(vnp)->header->diskstuff.filecount = 0;
-                   VFreeBitMapEntry_r(ec, &vp->vnodeIndex[class],
-                                      vnodeIdToBitNumber(Vn_id(vnp)));
+                   VFreeBitMapEntry_r(ec, vp, &vp->vnodeIndex[class],
+                                      vnodeIdToBitNumber(Vn_id(vnp)),
+                                      VOL_FREE_BITMAP_WAIT);
                }
            }
            vcp->writes++;
@@ -1411,7 +1422,8 @@ VPutVnode_r(Error * ec, register Vnode * vnp)
     } else {                   /* Not write locked */
        if (vnp->changed_newTime || vnp->changed_oldTime || vnp->delete)
            Abort
-               ("VPutVnode: Change or delete flag for vnode 0x%x is set but vnode is not write locked!\n",
+               ("VPutVnode: Change or delete flag for vnode "
+                "%"AFS_PTR_FMT" is set but vnode is not write locked!\n",
                 vnp);
 #ifdef AFS_DEMAND_ATTACH_FS
        VnEndRead_r(vnp);
@@ -1431,7 +1443,7 @@ VPutVnode_r(Error * ec, register Vnode * vnp)
  * been deleted.
  */
 int
-VVnodeWriteToRead(Error * ec, register Vnode * vnp)
+VVnodeWriteToRead(Error * ec, Vnode * vnp)
 {
     int retVal;
     VOL_LOCK;
@@ -1458,7 +1470,7 @@ VVnodeWriteToRead(Error * ec, register Vnode * vnp)
  * @internal volume package internal use only
  */
 int
-VVnodeWriteToRead_r(Error * ec, register Vnode * vnp)
+VVnodeWriteToRead_r(Error * ec, Vnode * vnp)
 {
     int writeLocked;
     VnodeClass class;
@@ -1470,10 +1482,10 @@ VVnodeWriteToRead_r(Error * ec, register Vnode * vnp)
 #endif /* AFS_PTHREAD_ENV */
 
     *ec = 0;
-    assert(Vn_refcount(vnp) != 0);
+    osi_Assert(Vn_refcount(vnp) != 0);
     class = vnodeIdToClass(Vn_id(vnp));
     vcp = &VnodeClassInfo[class];
-    assert(vnp->disk.vnodeMagic == vcp->magic);
+    osi_Assert(vnp->disk.vnodeMagic == vcp->magic);
     VNLog(300, 2, Vn_id(vnp), (intptr_t) vnp, 0, 0);
 
 #ifdef AFS_DEMAND_ATTACH_FS
@@ -1498,8 +1510,8 @@ VVnodeWriteToRead_r(Error * ec, register Vnode * vnp)
     LWP_CurrentProcess(&thisProcess);
 #endif /* AFS_PTHREAD_ENV */
     if (thisProcess != vnp->writer)
-       Abort("VPutVnode: Vnode at 0x%x locked by another process!\n",
-             (intptr_t)vnp);
+       Abort("VPutVnode: Vnode at %"AFS_PTR_FMT
+             " locked by another process!\n", vnp);
 
     if (vnp->delete) {
        return 0;
@@ -1507,7 +1519,7 @@ VVnodeWriteToRead_r(Error * ec, register Vnode * vnp)
     if (vnp->changed_oldTime || vnp->changed_newTime) {
        Volume *vp = Vn_volume(vnp);
        afs_uint32 now = FT_ApproxTime();
-       assert(Vn_cacheCheck(vnp) == vp->cacheCheck);
+       osi_Assert(Vn_cacheCheck(vnp) == vp->cacheCheck);
        if (vnp->changed_newTime)
            vnp->disk.serverModifyTime = now;
        if (vnp->changed_newTime)
@@ -1518,7 +1530,7 @@ VVnodeWriteToRead_r(Error * ec, register Vnode * vnp)
 #ifdef AFS_DEMAND_ATTACH_FS
            VRequestSalvage_r(ec, vp, SALVSYNC_ERROR, 0);
 #else
-           assert(V_needsSalvaged(vp));
+           osi_Assert(V_needsSalvaged(vp));
            *ec = VSALVAGE;
 #endif
        } else {
@@ -1538,7 +1550,7 @@ VVnodeWriteToRead_r(Error * ec, register Vnode * vnp)
     return 0;
 }
 
-/** 
+/**
  * initial size of ihandle pointer vector.
  *
  * @see VInvalidateVnodesByVolume_r
@@ -1596,8 +1608,8 @@ VInvalidateVnodesByVolume_r(Volume * vp,
     if (ih_vec == NULL)
        return ENOMEM;
 
-    /* 
-     * Traverse the volume's vnode list.  Pull all the ihandles out into a 
+    /*
+     * Traverse the volume's vnode list.  Pull all the ihandles out into a
      * thread-private array for later asynchronous processing.
      */
 #ifdef AFS_DEMAND_ATTACH_FS
@@ -1621,7 +1633,7 @@ restart_traversal:
                ih_vec = ih_vec_new;
 #ifdef AFS_DEMAND_ATTACH_FS
                /*
-                * Theoretically, the volume's VVn list should not change 
+                * Theoretically, the volume's VVn list should not change
                 * because the volume is in an exclusive state.  For the
                 * sake of safety, we will restart the traversal from the
                 * the beginning (which is not expensive because we're
@@ -1662,7 +1674,7 @@ VCloseVnodeFiles_r(Volume * vp)
 #endif /* AFS_DEMAND_ATTACH_FS */
 
     /* XXX need better error handling here */
-    assert(VInvalidateVnodesByVolume_r(vp,
+    osi_Assert(VInvalidateVnodesByVolume_r(vp,
                                       &ih_vec,
                                       &vec_len) == 0);
 
@@ -1677,6 +1689,7 @@ VCloseVnodeFiles_r(Volume * vp)
 
     for (i = 0; i < vec_len; i++) {
        IH_REALLYCLOSE(ih_vec[i]);
+        IH_RELEASE(ih_vec[i]);
     }
 
     free(ih_vec);
@@ -1705,7 +1718,7 @@ VCloseVnodeFiles_r(Volume * vp)
  *       during this exclusive operation.  This is due to the fact that we are
  *       generally called during the refcount 1->0 transition.
  *
- * @todo we should handle failures in VInvalidateVnodesByVolume_r more 
+ * @todo we should handle failures in VInvalidateVnodesByVolume_r more
  *       gracefully.
  *
  * @see VInvalidateVnodesByVolume_r
@@ -1726,7 +1739,7 @@ VReleaseVnodeFiles_r(Volume * vp)
 #endif /* AFS_DEMAND_ATTACH_FS */
 
     /* XXX need better error handling here */
-    assert(VInvalidateVnodesByVolume_r(vp,
+    osi_Assert(VInvalidateVnodesByVolume_r(vp,
                                       &ih_vec,
                                       &vec_len) == 0);