windows-dnlc-20080226
authorJeffrey Altman <jaltman@secure-endpoints.com>
Wed, 27 Feb 2008 04:53:45 +0000 (04:53 +0000)
committerJeffrey Altman <jaltman@secure-endpoints.com>
Wed, 27 Feb 2008 04:53:45 +0000 (04:53 +0000)
LICENSE MIT

Remove race conditions in the statistics code by switching to
Interlocked functions.

Speed up cm_dnlcEnter() by searching first with a read lock and
then switching to a write lock if not found.

Add HKLM\SOFTWARE\OpenAFS\Client registry values "UseDNLC" and "Debug"DNLC".
I suspect with the B+tree code that the DNLC is unnecessary overhead but
leave it on by default for now.

src/WINNT/afsd/cm_dnlc.c
src/WINNT/afsd/cm_dnlc.h

index c6a98d4..b0e7338 100644 (file)
@@ -24,6 +24,7 @@
 #include <stdlib.h>
 #include <osi.h>
 #include "afsd.h"
+#include <WINNT/afsreg.h>
 
 osi_rwlock_t cm_dnlcLock;
 
@@ -111,6 +112,7 @@ cm_dnlcEnter ( cm_scache_t *adp,
     unsigned int key, skey, new=0;
     char *ts = aname;
     int safety;
+    int writeLocked = 0;
 
     if (!cm_useDnlc)
        return ;
@@ -127,9 +129,9 @@ cm_dnlcEnter ( cm_scache_t *adp,
        return ;
     skey = key & (NHSIZE -1);
 
-    lock_ObtainWrite(&cm_dnlcLock);
-    dnlcstats.enters++;
-  
+    InterlockedIncrement(&dnlcstats.enters);
+    lock_ObtainRead(&cm_dnlcLock);
+  retry:
     for (tnc = cm_data.nameHash[skey], safety=0; tnc; tnc = tnc->next, safety++ )
        if ((tnc->dirp == adp) && (!strcmp(tnc->name, aname)))
            break;                              /* preexisting entry */
@@ -140,8 +142,11 @@ cm_dnlcEnter ( cm_scache_t *adp,
        }
        else if (safety > NCSIZE) 
        {
-           dnlcstats.cycles++;
-           lock_ReleaseWrite(&cm_dnlcLock);
+           InterlockedIncrement(&dnlcstats.cycles);
+            if (writeLocked)
+                lock_ReleaseWrite(&cm_dnlcLock);
+            else
+                lock_ReleaseRead(&cm_dnlcLock);
 
            if ( cm_debugDnlc )
                 osi_Log0(afsd_logp, "DNLC cycle");
@@ -151,6 +156,12 @@ cm_dnlcEnter ( cm_scache_t *adp,
        
     if ( !tnc )
     {
+        if ( !writeLocked ) {
+            lock_ReleaseRead(&cm_dnlcLock);
+            lock_ObtainWrite(&cm_dnlcLock);
+            writeLocked = 1;
+            goto retry;
+        }
        new = 1;        /* entry does not exist, we are creating a new entry*/
        tnc = GetMeAnEntry();
     }
@@ -165,7 +176,10 @@ cm_dnlcEnter ( cm_scache_t *adp,
                InsertEntry(tnc);
 
     }
-    lock_ReleaseWrite(&cm_dnlcLock);
+    if (writeLocked)
+        lock_ReleaseWrite(&cm_dnlcLock);
+    else
+        lock_ReleaseRead(&cm_dnlcLock);
 
     if ( !tnc)
        cm_dnlcPurge();
@@ -186,18 +200,23 @@ cm_dnlcLookup (cm_scache_t *adp, cm_lookupSearch_t* sp)
   
     if (!cm_useDnlc)
        return NULL;
+
     if ( cm_debugDnlc ) 
        osi_Log2(afsd_logp, "cm_dnlcLookup dir %x name %s", 
                adp, osi_LogSaveString(afsd_logp,aname));
 
     dnlcHash( ts, key );  /* leaves ts pointing at the NULL */
-    if (ts - aname >= CM_AFSNCNAMESIZE) 
+
+    if (ts - aname >= CM_AFSNCNAMESIZE) {
+        InterlockedIncrement(&dnlcstats.lookups);
+        InterlockedIncrement(&dnlcstats.misses);
        return NULL;
+    }
 
     skey = key & (NHSIZE -1);
 
     lock_ObtainRead(&cm_dnlcLock);
-    dnlcstats.lookups++;            /* Is a dnlcread lock sufficient? */
+    InterlockedIncrement(&dnlcstats.lookups);
 
     ts = 0;
     tnc_begin = cm_data.nameHash[skey];
@@ -256,7 +275,7 @@ cm_dnlcLookup (cm_scache_t *adp, cm_lookupSearch_t* sp)
        }
        else if (tnc->next == tnc_begin || safety > NCSIZE) 
        {
-           dnlcstats.cycles++;
+           InterlockedIncrement(&dnlcstats.cycles);
            lock_ReleaseRead(&cm_dnlcLock);
 
            if ( cm_debugDnlc ) 
@@ -274,7 +293,7 @@ cm_dnlcLookup (cm_scache_t *adp, cm_lookupSearch_t* sp)
     }
 
     if (!tvc) 
-        dnlcstats.misses++;    /* Is a dnlcread lock sufficient? */
+        InterlockedIncrement(&dnlcstats.misses);
     else 
     {
         sp->found = 1;
@@ -339,7 +358,7 @@ cm_dnlcRemove (cm_scache_t *adp, char *aname)
 
     skey = key & (NHSIZE -1);
     lock_ObtainWrite(&cm_dnlcLock);
-    dnlcstats.removes++;
+    InterlockedIncrement(&dnlcstats.removes);
 
     for (tnc = cm_data.nameHash[skey], safety=0; tnc; safety++) 
     {
@@ -363,7 +382,7 @@ cm_dnlcRemove (cm_scache_t *adp, char *aname)
            tnc = tnc->next;
        if ( safety > NCSIZE )
        {
-           dnlcstats.cycles++;
+           InterlockedIncrement(&dnlcstats.cycles);
            lock_ReleaseWrite(&cm_dnlcLock);
 
            if ( cm_debugDnlc ) 
@@ -395,7 +414,7 @@ cm_dnlcPurgedp (cm_scache_t *adp)
        osi_Log1(afsd_logp, "cm_dnlcPurgedp dir %x", adp);
 
     lock_ObtainWrite(&cm_dnlcLock);
-    dnlcstats.purgeds++;
+    InterlockedIncrement(&dnlcstats.purgeds);
 
     for (i=0; i<NCSIZE && !err; i++) 
     {
@@ -432,7 +451,7 @@ cm_dnlcPurgevp (cm_scache_t *avc)
        osi_Log1(afsd_logp, "cm_dnlcPurgevp scache %x", avc);
 
     lock_ObtainWrite(&cm_dnlcLock);
-    dnlcstats.purgevs++;
+    InterlockedIncrement(&dnlcstats.purgevs);
 
     for (i=0; i<NCSIZE && !err ; i++) 
     {
@@ -467,7 +486,7 @@ void cm_dnlcPurge(void)
        osi_Log0(afsd_logp, "cm_dnlcPurge");
 
     lock_ObtainWrite(&cm_dnlcLock);
-    dnlcstats.purges++;
+    InterlockedIncrement(&dnlcstats.purges);
     
     cm_data.ncfreelist = (cm_nc_t *) 0;
     memset (cm_data.nameCache, 0, sizeof(cm_nc_t) * NCSIZE);
@@ -491,7 +510,7 @@ cm_dnlcPurgeVol(AFSFid *fidp)
     if (!cm_useDnlc)
         return ;
 
-    dnlcstats.purgevols++;
+    InterlockedIncrement(&dnlcstats.purgevols);
     cm_dnlcPurge();
 }
 
@@ -625,6 +644,29 @@ void
 cm_dnlcInit(int newFile)
 {
     int i;
+    HKEY parmKey;
+    DWORD dummyLen;
+    DWORD dwValue;
+    DWORD code;
+
+    code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
+                         0, KEY_QUERY_VALUE, &parmKey);
+    if (code == ERROR_SUCCESS) {
+        dummyLen = sizeof(DWORD);
+        code = RegQueryValueEx(parmKey, "UseDNLC", NULL, NULL,
+                                (BYTE *) &dwValue, &dummyLen);
+        if (code == ERROR_SUCCESS)
+            cm_useDnlc = dwValue ? 1 : 0;
+        afsi_log("CM UseDNLC = %d", cm_useDnlc);
+
+        dummyLen = sizeof(DWORD);
+        code = RegQueryValueEx(parmKey, "DebugDNLC", NULL, NULL,
+                                (BYTE *) &dwValue, &dummyLen);
+        if (code == ERROR_SUCCESS)
+            cm_debugDnlc = dwValue ? 1 : 0;
+        afsi_log("CM DebugDNLC = %d", cm_debugDnlc);
+        RegCloseKey (parmKey);
+    }
 
     if (!cm_useDnlc)
         return ;
index 21428cd..c1c0ba3 100644 (file)
@@ -24,9 +24,9 @@ typedef struct nc {
 } cm_nc_t;
 
 typedef struct {
-    unsigned int enters, lookups, misses, removes;
-    unsigned int purgeds, purgevs, purgevols, purges;
-    unsigned int cycles, lookuprace;
+    afs_int32 enters, lookups, misses, removes;
+    afs_int32 purgeds, purgevs, purgevols, purges;
+    afs_int32 cycles, lookuprace;
 } cm_dnlcstats_t;
 
 #define dnlcHash(ts, hval) for (hval=0; *ts; ts++) {    \