Windows: Do not leak cm_volume_t objects from the LRU queue
authorJeffrey Altman <jaltman@your-file-system.com>
Tue, 2 Nov 2010 20:16:20 +0000 (16:16 -0400)
committerJeffrey Altman <jaltman@openafs.org>
Wed, 3 Nov 2010 03:22:25 +0000 (20:22 -0700)
During cm_volume_t object recycling the object is removed
from the LRU to ensure that a single object is not recycled
by multiple threads at the same time.  Before cm_FindVolumeByName()
exits the object must be re-inserted into the LRU if it is not
present.

LICENSE MIT

Change-Id: I3feb3fb55beddffdbbf52a79efcc8d44af39b891
Reviewed-on: http://gerrit.openafs.org/3220
Reviewed-by: Derrick Brashear <shadow@dementia.org>
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Tested-by: Jeffrey Altman <jaltman@openafs.org>
Reviewed-by: Jeffrey Altman <jaltman@openafs.org>

src/WINNT/afsd/cm_volume.c

index 6a85c05..23ee84d 100644 (file)
@@ -900,6 +900,11 @@ long cm_FindVolumeByName(struct cm_cell *cellp, char *volumeNamep,
             osi_Log2(afsd_logp, "Recycling Volume %s:%s",
                      volp->cellp->name, volp->namep);
 
+            /* The volp is removed from the LRU queue in order to
+             * prevent two threads from attempting to recycle the
+             * same object.  This volp must be re-inserted back into
+             * the LRU queue before this function exits.
+             */
             if (volp->flags & CM_VOLUMEFLAG_IN_LRU_QUEUE)
                 cm_RemoveVolumeFromLRU(volp);
             if (volp->flags & CM_VOLUMEFLAG_IN_HASH)
@@ -968,12 +973,11 @@ long cm_FindVolumeByName(struct cm_cell *cellp, char *volumeNamep,
     if (code == 0) {
         *outVolpp = volp;
                
-        if ((volp->flags & CM_VOLUMEFLAG_IN_LRU_QUEUE) &&
-            !(flags & CM_GETVOL_FLAG_NO_LRU_UPDATE)) {
-            lock_ObtainWrite(&cm_volumeLock);
+        lock_ObtainRead(&cm_volumeLock);
+        if (!(volp->flags & CM_VOLUMEFLAG_IN_LRU_QUEUE) ||
+             (flags & CM_GETVOL_FLAG_NO_LRU_UPDATE))
             cm_AdjustVolumeLRU(volp);
-            lock_ReleaseWrite(&cm_volumeLock);
-        }
+        lock_ReleaseRead(&cm_volumeLock);
     } else {
         /*
          * do not return it to the caller but do insert it in the LRU