windows-dnlc-20080229
[openafs.git] / src / WINNT / afsd / cm_dnlc.c
index 9cc0bf9..91a474c 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,11 @@ cm_dnlcEnter ( cm_scache_t *adp,
        
     if ( !tnc )
     {
+        if ( !writeLocked ) {
+            lock_ConvertRToW(&cm_dnlcLock);
+            writeLocked = 1;
+            goto retry;
+        }
        new = 1;        /* entry does not exist, we are creating a new entry*/
        tnc = GetMeAnEntry();
     }
@@ -165,7 +175,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();
@@ -185,23 +198,28 @@ cm_dnlcLookup (cm_scache_t *adp, cm_lookupSearch_t* sp)
     int safety, match;
   
     if (!cm_useDnlc)
-       return 0;
+       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) 
-       return 0;
+
+    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];
-    for ( tvc = (cm_scache_t *) 0, tnc = tnc_begin, safety=0; 
+    for ( tvc = (cm_scache_t *) NULL, tnc = tnc_begin, safety=0; 
           tnc; tnc = tnc->next, safety++ ) 
     {
        if (tnc->dirp == adp) 
@@ -256,13 +274,13 @@ 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 ) 
                osi_Log0(afsd_logp, "DNLC cycle"); 
            cm_dnlcPurge();
-           return(0);
+           return(NULL);
        }
     }
 
@@ -274,7 +292,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 +357,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 +381,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 +413,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 +450,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 +485,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 +509,7 @@ cm_dnlcPurgeVol(AFSFid *fidp)
     if (!cm_useDnlc)
         return ;
 
-    dnlcstats.purgevols++;
+    InterlockedIncrement(&dnlcstats.purgevols);
     cm_dnlcPurge();
 }
 
@@ -625,9 +643,29 @@ void
 cm_dnlcInit(int newFile)
 {
     int i;
-
-    if (!cm_useDnlc)
-        return ;
+    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_debugDnlc )
        osi_Log0(afsd_logp,"cm_dnlcInit");