Windows: cm_RemoveSCacheFromHashTable scp not found
[openafs.git] / src / WINNT / afsd / cm_scache.c
index caa2d24..a2432b5 100644 (file)
@@ -72,28 +72,61 @@ void cm_AdjustScacheLRU(cm_scache_t *scp)
     }
 }
 
-/* call with cm_scacheLock write-locked and scp rw held */
-void cm_RemoveSCacheFromHashTable(cm_scache_t *scp)
+static int
+cm_RemoveSCacheFromHashChain(cm_scache_t *scp, int index)
 {
     cm_scache_t **lscpp;
     cm_scache_t *tscp;
-    int i;
+    int found = 0;
+
+    for (lscpp = &cm_data.scacheHashTablep[index], tscp = cm_data.scacheHashTablep[index];
+         tscp;
+         lscpp = &tscp->nextp, tscp = tscp->nextp) {
+       if (tscp == scp) {
+           *lscpp = scp->nextp;
+           scp->nextp = NULL;
+           found = 1;
+           break;
+       }
+    }
+
+    return found;
+}
 
+/* call with cm_scacheLock write-locked and scp rw held */
+void cm_RemoveSCacheFromHashTable(cm_scache_t *scp)
+{
     lock_AssertWrite(&cm_scacheLock);
     lock_AssertWrite(&scp->rw);
     if (scp->flags & CM_SCACHEFLAG_INHASH) {
+       int h,i;
+       int found = 0;
+
        /* hash it out first */
-       i = CM_SCACHE_HASH(&scp->fid);
-       for (lscpp = &cm_data.scacheHashTablep[i], tscp = cm_data.scacheHashTablep[i];
-            tscp;
-            lscpp = &tscp->nextp, tscp = tscp->nextp) {
-           if (tscp == scp) {
-               *lscpp = scp->nextp;
-                scp->nextp = NULL;
-               _InterlockedAnd(&scp->flags, ~CM_SCACHEFLAG_INHASH);
-               break;
+       h = CM_SCACHE_HASH(&scp->fid);
+       found = cm_RemoveSCacheFromHashChain(scp, h);
+
+       if (!found) {
+           /*
+            * The CM_SCACHEFLAG_INHASH is set on the cm_scache_t but
+            * we didn't find the entry in the expected hash chain.
+            * Did the fid change?
+            * In any case, we will search the entire hashtable for
+            * the object.  If we don't find it, then we know it is
+            * safe to remove the flag.
+            */
+           for (i=0; !found && i<cm_data.scacheHashTableSize; i++) {
+               if (i != h)
+                   found = cm_RemoveSCacheFromHashChain(scp, i);
            }
+
+           if (found)
+               osi_Log1(afsd_logp,"cm_RemoveSCacheFromHashTable scp 0x%p found in wrong hash chain", scp);
+           else
+               osi_Log1(afsd_logp,"cm_RemoveSCacheFromHashTable scp 0x%p not found in hash table", scp);
        }
+
+       _InterlockedAnd(&scp->flags, ~CM_SCACHEFLAG_INHASH);
     }
 }
 
@@ -484,16 +517,40 @@ cm_ValidateSCache(void)
     for ( scp = cm_data.scacheLRUFirstp, lscp = NULL, i = 0;
           scp;
           lscp = scp, scp = (cm_scache_t *) osi_QNext(&scp->q), i++ ) {
+
+       if ( scp < (cm_scache_t *)cm_data.scacheBaseAddress ||
+            scp >= (cm_scache_t *)cm_data.dnlcBaseAddress) {
+           afsi_log("cm_ValidateSCache failure: out of range cm_scache_t pointers");
+           fprintf(stderr, "cm_ValidateSCache failure: out of range cm_scache_t pointers\n");
+           return -18;
+       }
+
         if (scp->magic != CM_SCACHE_MAGIC) {
             afsi_log("cm_ValidateSCache failure: scp->magic != CM_SCACHE_MAGIC");
             fprintf(stderr, "cm_ValidateSCache failure: scp->magic != CM_SCACHE_MAGIC\n");
             return -1;
         }
+
+       if ( scp->nextp < (cm_scache_t *)cm_data.scacheBaseAddress ||
+            scp->nextp >= (cm_scache_t *)cm_data.dnlcBaseAddress) {
+           afsi_log("cm_ValidateSCache failure: out of range cm_scache_t pointers");
+           fprintf(stderr, "cm_ValidateSCache failure: out of range cm_scache_t pointers\n");
+           return -21;
+       }
+
         if (scp->nextp && scp->nextp->magic != CM_SCACHE_MAGIC) {
             afsi_log("cm_ValidateSCache failure: scp->nextp->magic != CM_SCACHE_MAGIC");
             fprintf(stderr, "cm_ValidateSCache failure: scp->nextp->magic != CM_SCACHE_MAGIC\n");
             return -2;
         }
+
+       if ( scp->randomACLp < (cm_aclent_t *)cm_data.aclBaseAddress ||
+            scp->randomACLp >= (cm_aclent_t *)cm_data.scacheBaseAddress) {
+           afsi_log("cm_ValidateSCache failure: out of range cm_aclent_t pointers");
+           fprintf(stderr, "cm_ValidateSCache failure: out of range cm_aclent_t pointers\n");
+           return -32;
+       }
+
         if (scp->randomACLp && scp->randomACLp->magic != CM_ACLENT_MAGIC) {
             afsi_log("cm_ValidateSCache failure: scp->randomACLp->magic != CM_ACLENT_MAGIC");
             fprintf(stderr, "cm_ValidateSCache failure: scp->randomACLp->magic != CM_ACLENT_MAGIC\n");
@@ -513,16 +570,40 @@ cm_ValidateSCache(void)
 
     for ( scp = cm_data.scacheLRULastp, lscp = NULL, i = 0; scp;
           lscp = scp, scp = (cm_scache_t *) osi_QPrev(&scp->q), i++ ) {
+
+       if ( scp < (cm_scache_t *)cm_data.scacheBaseAddress ||
+            scp >= (cm_scache_t *)cm_data.dnlcBaseAddress) {
+           afsi_log("cm_ValidateSCache failure: out of range cm_scache_t pointers");
+           fprintf(stderr, "cm_ValidateSCache failure: out of range cm_scache_t pointers\n");
+           return -19;
+       }
+
         if (scp->magic != CM_SCACHE_MAGIC) {
             afsi_log("cm_ValidateSCache failure: scp->magic != CM_SCACHE_MAGIC");
             fprintf(stderr, "cm_ValidateSCache failure: scp->magic != CM_SCACHE_MAGIC\n");
             return -5;
         }
+
+       if ( scp->nextp < (cm_scache_t *)cm_data.scacheBaseAddress ||
+            scp->nextp >= (cm_scache_t *)cm_data.dnlcBaseAddress) {
+           afsi_log("cm_ValidateSCache failure: out of range cm_scache_t pointers");
+           fprintf(stderr, "cm_ValidateSCache failure: out of range cm_scache_t pointers\n");
+           return -22;
+       }
+
         if (scp->nextp && scp->nextp->magic != CM_SCACHE_MAGIC) {
             afsi_log("cm_ValidateSCache failure: scp->nextp->magic != CM_SCACHE_MAGIC");
             fprintf(stderr, "cm_ValidateSCache failure: scp->nextp->magic != CM_SCACHE_MAGIC\n");
             return -6;
         }
+
+       if ( scp->randomACLp < (cm_aclent_t *)cm_data.aclBaseAddress ||
+            scp->randomACLp >= (cm_aclent_t *)cm_data.scacheBaseAddress) {
+           afsi_log("cm_ValidateSCache failure: out of range cm_aclent_t pointers");
+           fprintf(stderr, "cm_ValidateSCache failure: out of range cm_aclent_t pointers\n");
+           return -31;
+       }
+
         if (scp->randomACLp && scp->randomACLp->magic != CM_ACLENT_MAGIC) {
             afsi_log("cm_ValidateSCache failure: scp->randomACLp->magic != CM_ACLENT_MAGIC");
             fprintf(stderr, "cm_ValidateSCache failure: scp->randomACLp->magic != CM_ACLENT_MAGIC\n");
@@ -543,17 +624,42 @@ cm_ValidateSCache(void)
     for ( i=0; i < cm_data.scacheHashTableSize; i++ ) {
         for ( scp = cm_data.scacheHashTablep[i]; scp; scp = scp->nextp ) {
             afs_uint32 hash;
+
+           if ( scp < (cm_scache_t *)cm_data.scacheBaseAddress ||
+                scp >= (cm_scache_t *)cm_data.dnlcBaseAddress) {
+               afsi_log("cm_ValidateSCache failure: out of range cm_scache_t pointers");
+               fprintf(stderr, "cm_ValidateSCache failure: out of range cm_scache_t pointers\n");
+               return -20;
+           }
+
             hash = CM_SCACHE_HASH(&scp->fid);
+
             if (scp->magic != CM_SCACHE_MAGIC) {
                 afsi_log("cm_ValidateSCache failure: scp->magic != CM_SCACHE_MAGIC");
                 fprintf(stderr, "cm_ValidateSCache failure: scp->magic != CM_SCACHE_MAGIC\n");
                 return -9;
             }
+
+           if ( scp->nextp < (cm_scache_t *)cm_data.scacheBaseAddress ||
+                scp->nextp >= (cm_scache_t *)cm_data.dnlcBaseAddress) {
+               afsi_log("cm_ValidateSCache failure: out of range cm_scache_t pointers");
+               fprintf(stderr, "cm_ValidateSCache failure: out of range cm_scache_t pointers\n");
+               return -23;
+           }
+
             if (scp->nextp && scp->nextp->magic != CM_SCACHE_MAGIC) {
                 afsi_log("cm_ValidateSCache failure: scp->nextp->magic != CM_SCACHE_MAGIC");
                 fprintf(stderr, "cm_ValidateSCache failure: scp->nextp->magic != CM_SCACHE_MAGIC\n");
                 return -10;
             }
+
+           if ( scp->randomACLp < (cm_aclent_t *)cm_data.aclBaseAddress ||
+                scp->randomACLp >= (cm_aclent_t *)cm_data.scacheBaseAddress) {
+               afsi_log("cm_ValidateSCache failure: out of range cm_aclent_t pointers");
+               fprintf(stderr, "cm_ValidateSCache failure: out of range cm_aclent_t pointers\n");
+               return -30;
+           }
+
             if (scp->randomACLp && scp->randomACLp->magic != CM_ACLENT_MAGIC) {
                 afsi_log("cm_ValidateSCache failure: scp->randomACLp->magic != CM_ACLENT_MAGIC");
                 fprintf(stderr, "cm_ValidateSCache failure: scp->randomACLp->magic != CM_ACLENT_MAGIC\n");
@@ -1902,7 +2008,8 @@ long cm_MergeStatus(cm_scache_t *dscp,
              * so leave it in place.
              */
             if (cm_FidCmp(&scp->fid, &bp->fid) == 0 &&
-                 lock_TryMutex(&bp->mx)) {
+                bp->refCount == 0 &&
+                lock_TryMutex(&bp->mx)) {
                 if (bp->refCount == 0 &&
                     !(bp->flags & (CM_BUF_READING | CM_BUF_WRITING | CM_BUF_DIRTY)) &&
                     !(bp->qFlags & CM_BUF_QREDIR)) {
@@ -2139,34 +2246,6 @@ void cm_ReleaseSCacheNoLock(cm_scache_t *scp)
     osi_Log2(afsd_logp,"cm_ReleaseSCacheNoLock scp 0x%p ref %d",scp, refCount);
     afsi_log("%s:%d cm_ReleaseSCacheNoLock scp 0x%p ref %d", file, line, scp, refCount);
 #endif
-
-    if (refCount == 0 && (scp->flags & CM_SCACHEFLAG_DELETED)) {
-        int deleted = 0;
-        long      lockstate;
-
-        lockstate = lock_GetRWLockState(&cm_scacheLock);
-        if (lockstate != OSI_RWLOCK_WRITEHELD)
-            lock_ReleaseRead(&cm_scacheLock);
-        else
-            lock_ReleaseWrite(&cm_scacheLock);
-
-        lock_ObtainWrite(&scp->rw);
-        if (scp->flags & CM_SCACHEFLAG_DELETED)
-            deleted = 1;
-
-        if (refCount == 0 && deleted) {
-            lock_ObtainWrite(&cm_scacheLock);
-            cm_RecycleSCache(scp, 0);
-            if (lockstate != OSI_RWLOCK_WRITEHELD)
-                lock_ConvertWToR(&cm_scacheLock);
-        } else {
-            if (lockstate != OSI_RWLOCK_WRITEHELD)
-                lock_ObtainRead(&cm_scacheLock);
-            else
-                lock_ObtainWrite(&cm_scacheLock);
-        }
-        lock_ReleaseWrite(&scp->rw);
-    }
 }
 
 #ifdef DEBUG_REFCOUNT
@@ -2190,19 +2269,6 @@ void cm_ReleaseSCache(cm_scache_t *scp)
     afsi_log("%s:%d cm_ReleaseSCache scp 0x%p ref %d", file, line, scp, refCount);
 #endif
     lock_ReleaseRead(&cm_scacheLock);
-
-    if (scp->flags & CM_SCACHEFLAG_DELETED) {
-        int deleted = 0;
-        lock_ObtainWrite(&scp->rw);
-        if (scp->flags & CM_SCACHEFLAG_DELETED)
-            deleted = 1;
-        if (deleted) {
-            lock_ObtainWrite(&cm_scacheLock);
-            cm_RecycleSCache(scp, 0);
-            lock_ReleaseWrite(&cm_scacheLock);
-        }
-        lock_ReleaseWrite(&scp->rw);
-    }
 }
 
 /* just look for the scp entry to get filetype */