#include <afs/param.h>
#include <afs/stds.h>
-#ifndef DJGPP
#include <windows.h>
#include <winsock2.h>
-#endif /* !DJGPP */
#include <string.h>
#include <stdlib.h>
#include <osi.h>
#include "afsd.h"
+#include <WINNT/afsreg.h>
osi_rwlock_t cm_dnlcLock;
* 1. If nameHash[i] is NULL, list is empty
* 2. A single element in a hash bucket has itself as prev and next.
*/
-#ifndef DJGPP
-#define dnlcNotify(x,debug){ \
- HANDLE hh; \
- char *ptbuf[1]; \
- ptbuf[0] = x; \
- if ( debug ) { \
- hh = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME); \
- ReportEvent(hh,EVENTLOG_ERROR_TYPE,0,__LINE__, \
- NULL, 1, 0, ptbuf, NULL); \
- DeregisterEventSource(hh); \
- } \
- }
-#else
-#define dnlcNotify(x,debug)
-#endif /* !DJGPP */
+/* Must be called with cm_dnlcLock write locked */
static cm_nc_t *
GetMeAnEntry()
{
tnc = cm_data.nameHash[nameptr];
if (!tnc)
{
- dnlcNotify("null tnc in GetMeAnEntry",1);
osi_Log0(afsd_logp,"null tnc in GetMeAnEntry");
return 0;
}
}
static void
-InsertEntry(tnc)
- cm_nc_t *tnc;
+InsertEntry(cm_nc_t *tnc)
{
unsigned int key;
key = tnc->key & (NHSIZE -1);
unsigned int key, skey, new=0;
char *ts = aname;
int safety;
+ int writeLocked = 0;
if (!cm_useDnlc)
return ;
-
+
+ if (!strcmp(aname,".") || !strcmp(aname,".."))
+ return ;
+
if ( cm_debugDnlc )
osi_Log3(afsd_logp,"cm_dnlcEnter dir %x name %s scache %x",
adp, osi_LogSaveString(afsd_logp,aname), avc);
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 */
}
else if (safety > NCSIZE)
{
- dnlcstats.cycles++;
- lock_ReleaseWrite(&cm_dnlcLock);
+ InterlockedIncrement(&dnlcstats.cycles);
+ if (writeLocked)
+ lock_ReleaseWrite(&cm_dnlcLock);
+ else
+ lock_ReleaseRead(&cm_dnlcLock);
- dnlcNotify("DNLC cycle",1);
if ( cm_debugDnlc )
osi_Log0(afsd_logp, "DNLC cycle");
cm_dnlcPurge();
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();
}
InsertEntry(tnc);
}
- lock_ReleaseWrite(&cm_dnlcLock);
+ if (writeLocked)
+ lock_ReleaseWrite(&cm_dnlcLock);
+ else
+ lock_ReleaseRead(&cm_dnlcLock);
if ( !tnc)
cm_dnlcPurge();
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)
}
else if (tnc->next == tnc_begin || safety > NCSIZE)
{
- dnlcstats.cycles++;
+ InterlockedIncrement(&dnlcstats.cycles);
lock_ReleaseRead(&cm_dnlcLock);
- dnlcNotify("DNLC cycle",1);
if ( cm_debugDnlc )
osi_Log0(afsd_logp, "DNLC cycle");
cm_dnlcPurge();
- return(0);
+ return(NULL);
}
}
}
if (!tvc)
- dnlcstats.misses++; /* Is a dnlcread lock sufficient? */
+ InterlockedIncrement(&dnlcstats.misses);
else
{
sp->found = 1;
static int
-RemoveEntry (tnc, key)
- cm_nc_t *tnc;
- unsigned int key;
+RemoveEntry (cm_nc_t *tnc, unsigned int key)
{
if (!tnc->prev) /* things on freelist always have null prev ptrs */
{
- dnlcNotify("Bogus dnlc freelist", 1);
osi_Log0(afsd_logp,"Bogus dnlc freelist");
return 1; /* error */
}
tnc->next->prev = tnc->prev;
}
- tnc->prev = (cm_nc_t *) 0; /* everything not in hash table has 0 prev */
- tnc->key = 0; /* just for safety's sake */
+ memset(tnc, 0, sizeof(cm_nc_t));
+ tnc->magic = CM_DNLC_MAGIC;
return 0; /* success */
}
void
-cm_dnlcRemove ( adp, aname)
- cm_scache_t *adp;
- char *aname;
+cm_dnlcRemove (cm_scache_t *adp, char *aname)
{
unsigned int key, skey, error=0;
int found= 0, safety;
skey = key & (NHSIZE -1);
lock_ObtainWrite(&cm_dnlcLock);
- dnlcstats.removes++;
+ InterlockedIncrement(&dnlcstats.removes);
for (tnc = cm_data.nameHash[skey], safety=0; tnc; safety++)
{
if ( (tnc->dirp == adp) && (tnc->key == key)
&& !strcmp(tnc->name,aname) )
{
- tnc->dirp = (cm_scache_t *) 0; /* now it won't match anything */
tmp = tnc->next;
error = RemoveEntry(tnc, skey);
if ( error )
tnc->next = cm_data.ncfreelist; /* insert entry into freelist */
cm_data.ncfreelist = tnc;
- found = 1; /* found atleast one entry */
+ found = 1; /* found at least one entry */
tnc = tmp; /* continue down the linked list */
}
tnc = tnc->next;
if ( safety > NCSIZE )
{
- dnlcstats.cycles++;
+ InterlockedIncrement(&dnlcstats.cycles);
lock_ReleaseWrite(&cm_dnlcLock);
- dnlcNotify("DNLC cycle",1);
if ( cm_debugDnlc )
osi_Log0(afsd_logp, "DNLC cycle");
cm_dnlcPurge();
/* remove anything pertaining to this directory */
void
-cm_dnlcPurgedp (adp)
- cm_scache_t *adp;
+cm_dnlcPurgedp (cm_scache_t *adp)
{
int i;
int err=0;
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++)
{
if (cm_data.nameCache[i].dirp == adp )
{
- cm_data.nameCache[i].dirp = cm_data.nameCache[i].vp = (cm_scache_t *) 0;
- if (cm_data.nameCache[i].prev && !err)
- {
- err = RemoveEntry(&cm_data.nameCache[i], cm_data.nameCache[i].key & (NHSIZE-1));
- cm_data.nameCache[i].next = cm_data.ncfreelist;
- cm_data.ncfreelist = &cm_data.nameCache[i];
- }
+ if (cm_data.nameCache[i].prev) {
+ err = RemoveEntry(&cm_data.nameCache[i], cm_data.nameCache[i].key & (NHSIZE-1));
+ if (!err)
+ {
+ cm_data.nameCache[i].next = cm_data.ncfreelist;
+ cm_data.ncfreelist = &cm_data.nameCache[i];
+ }
+ } else {
+ cm_data.nameCache[i].dirp = cm_data.nameCache[i].vp = (cm_scache_t *) 0;
+ }
}
}
lock_ReleaseWrite(&cm_dnlcLock);
/* remove anything pertaining to this file */
void
-cm_dnlcPurgevp ( avc )
- cm_scache_t *avc;
+cm_dnlcPurgevp (cm_scache_t *avc)
{
int i;
int err=0;
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++)
{
if (cm_data.nameCache[i].vp == avc)
{
- cm_data.nameCache[i].dirp = cm_data.nameCache[i].vp = (cm_scache_t *) 0;
- /* can't simply break; because of hard links -- might be two */
- /* different entries with same vnode */
- if (!err && cm_data.nameCache[i].prev)
- {
- err=RemoveEntry(&cm_data.nameCache[i], cm_data.nameCache[i].key & (NHSIZE-1));
- cm_data.nameCache[i].next = cm_data.ncfreelist;
- cm_data.ncfreelist = &cm_data.nameCache[i];
- }
+ if (cm_data.nameCache[i].prev) {
+ err = RemoveEntry(&cm_data.nameCache[i], cm_data.nameCache[i].key & (NHSIZE-1));
+ if (!err)
+ {
+ cm_data.nameCache[i].next = cm_data.ncfreelist;
+ cm_data.ncfreelist = &cm_data.nameCache[i];
+ }
+ } else {
+ cm_data.nameCache[i].dirp = cm_data.nameCache[i].vp = (cm_scache_t *) 0;
+ }
}
}
lock_ReleaseWrite(&cm_dnlcLock);
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);
memset (cm_data.nameHash, 0, sizeof(cm_nc_t *) * NHSIZE);
- for (i=0; i<NCSIZE; i++)
+ for (i=0; i<NCSIZE; i++)
{
- cm_data.nameCache[i].next = cm_data.ncfreelist;
- cm_data.ncfreelist = &cm_data.nameCache[i];
+ cm_data.nameCache[i].magic = CM_DNLC_MAGIC;
+ cm_data.nameCache[i].next = cm_data.ncfreelist;
+ cm_data.ncfreelist = &cm_data.nameCache[i];
}
lock_ReleaseWrite(&cm_dnlcLock);
}
/* remove everything referencing a specific volume */
+/* is this function ever called? */
void
-cm_dnlcPurgeVol( fidp )
- AFSFid *fidp;
+cm_dnlcPurgeVol(AFSFid *fidp)
{
if (!cm_useDnlc)
return ;
- dnlcstats.purgevols++;
+ InterlockedIncrement(&dnlcstats.purgevols);
cm_dnlcPurge();
}
long
cm_dnlcValidate(void)
{
- int i;
+ int i, purged = 0;
cm_nc_t * ncp;
-
+
+ retry:
// are all nameCache entries marked with the magic bit?
for (i=0; i<NCSIZE; i++)
{
if (cm_data.nameCache[i].magic != CM_DNLC_MAGIC) {
afsi_log("cm_dnlcValidate failure: cm_data.nameCache[%d].magic != CM_DNLC_MAGIC", i);
fprintf(stderr, "cm_dnlcValidate failure: cm_data.nameCache[%d].magic != CM_DNLC_MAGIC\n", i);
- return -1;
+ goto purge;
}
if (cm_data.nameCache[i].next &&
cm_data.nameCache[i].next->magic != CM_DNLC_MAGIC) {
afsi_log("cm_dnlcValidate failure: cm_data.nameCache[%d].next->magic != CM_DNLC_MAGIC", i);
fprintf(stderr, "cm_dnlcValidate failure: cm_data.nameCache[%d].next->magic != CM_DNLC_MAGIC\n", i);
- return -2;
+ goto purge;
}
if (cm_data.nameCache[i].prev &&
cm_data.nameCache[i].prev->magic != CM_DNLC_MAGIC) {
afsi_log("cm_dnlcValidate failure: cm_data.nameCache[%d].prev->magic != CM_DNLC_MAGIC", i);
fprintf(stderr, "cm_dnlcValidate failure: cm_data.nameCache[%d].prev->magic != CM_DNLC_MAGIC\n", i);
- return -3;
+ goto purge;
}
if (cm_data.nameCache[i].dirp &&
cm_data.nameCache[i].dirp->magic != CM_SCACHE_MAGIC) {
afsi_log("cm_dnlcValidate failure: cm_data.nameCache[%d].dirp->magic != CM_SCACHE_MAGIC", i);
fprintf(stderr, "cm_dnlcValidate failure: cm_data.nameCache[%d].dirp->magic != CM_SCACHE_MAGIC\n", i);
- return -4;
+ goto purge;
}
if (cm_data.nameCache[i].vp &&
cm_data.nameCache[i].vp->magic != CM_SCACHE_MAGIC) {
afsi_log("cm_dnlcValidate failure: cm_data.nameCache[%d].vp->magic != CM_SCACHE_MAGIC", i);
fprintf(stderr, "cm_dnlcValidate failure: cm_data.nameCache[%d].vp->magic != CM_SCACHE_MAGIC\n", i);
- return -5;
+ goto purge;
}
}
if (ncp->magic != CM_DNLC_MAGIC) {
afsi_log("cm_dnlcValidate failure: ncp->magic != CM_DNLC_MAGIC");
fprintf(stderr, "cm_dnlcValidate failure: ncp->magic != CM_DNLC_MAGIC\n");
- return -6;
+ goto purge;
}
if (ncp->prev && ncp->prev->magic != CM_DNLC_MAGIC) {
afsi_log("cm_dnlcValidate failure: ncp->prev->magic != CM_DNLC_MAGIC");
fprintf(stderr, "cm_dnlcValidate failure: ncp->prev->magic != CM_DNLC_MAGIC\n");
- return -7;
+ goto purge;
}
if (ncp->dirp && ncp->dirp->magic != CM_SCACHE_MAGIC) {
afsi_log("cm_dnlcValidate failure: ncp->dirp->magic != CM_DNLC_MAGIC");
fprintf(stderr, "cm_dnlcValidate failure: ncp->dirp->magic != CM_DNLC_MAGIC\n");
- return -8;
+ goto purge;
}
if (ncp->vp && ncp->vp->magic != CM_SCACHE_MAGIC) {
afsi_log("cm_dnlcValidate failure: ncp->vp->magic != CM_DNLC_MAGIC");
fprintf(stderr, "cm_dnlcValidate failure: ncp->vp->magic != CM_DNLC_MAGIC\n");
- return -9;
+ goto purge;
}
}
}
// is the freelist stable?
if ( cm_data.ncfreelist ) {
- for (ncp = cm_data.ncfreelist; ncp;
- ncp = ncp->next != cm_data.ncfreelist ? ncp->next : NULL) {
+ for (ncp = cm_data.ncfreelist, i = 0; ncp && i < NCSIZE;
+ ncp = ncp->next != cm_data.ncfreelist ? ncp->next : NULL, i++) {
if (ncp->magic != CM_DNLC_MAGIC) {
afsi_log("cm_dnlcValidate failure: ncp->magic != CM_DNLC_MAGIC");
fprintf(stderr, "cm_dnlcValidate failure: ncp->magic != CM_DNLC_MAGIC\n");
- return -10;
+ goto purge;
}
- if (ncp->prev && ncp->prev->magic != CM_DNLC_MAGIC) {
- afsi_log("cm_dnlcValidate failure: ncp->prev->magic != CM_DNLC_MAGIC");
- fprintf(stderr, "cm_dnlcValidate failure: ncp->prev->magic != CM_DNLC_MAGIC\n");
- return -11;
+ if (ncp->prev) {
+ afsi_log("cm_dnlcValidate failure: ncp->prev != NULL");
+ fprintf(stderr, "cm_dnlcValidate failure: ncp->prev != NULL\n");
+ goto purge;
}
- if (ncp->dirp && ncp->dirp->magic != CM_SCACHE_MAGIC) {
- afsi_log("cm_dnlcValidate failure: ncp->dirp->magic != CM_DNLC_MAGIC");
- fprintf(stderr, "cm_dnlcValidate failure: ncp->dirp->magic != CM_DNLC_MAGIC\n");
- return -12;
+ if (ncp->key) {
+ afsi_log("cm_dnlcValidate failure: ncp->key != 0");
+ fprintf(stderr, "cm_dnlcValidate failure: ncp->key != 0\n");
+ goto purge;
}
- if (ncp->vp && ncp->vp->magic != CM_SCACHE_MAGIC) {
- afsi_log("cm_dnlcValidate failure: ncp->vp->magic != CM_DNLC_MAGIC");
- fprintf(stderr, "cm_dnlcValidate failure: ncp->vp->magic != CM_DNLC_MAGIC\n");
- return -13;
+ if (ncp->dirp) {
+ afsi_log("cm_dnlcValidate failure: ncp->dirp != NULL");
+ fprintf(stderr, "cm_dnlcValidate failure: ncp->dirp != NULL\n");
+ goto purge;
+ }
+ if (ncp->vp) {
+ afsi_log("cm_dnlcValidate failure: ncp->vp != NULL");
+ fprintf(stderr, "cm_dnlcValidate failure: ncp->vp != NULL\n");
+ goto purge;
}
}
- }
+ if ( i == NCSIZE && ncp ) {
+ afsi_log("cm_dnlcValidate failure: dnlc freeList corrupted");
+ fprintf(stderr, "cm_dnlcValidate failure: dnlc freeList corrupted\n");
+ goto purge;
+ }
+ }
return 0;
+
+ purge:
+ if ( purged )
+ return -1;
+
+ afsi_log("cm_dnlcValidate information: purging");
+ fprintf(stderr, "cm_dnlcValidate information: purging\n");
+ cm_data.ncfreelist = (cm_nc_t *) 0;
+ memset (cm_data.nameCache, 0, sizeof(cm_nc_t) * NCSIZE);
+ memset (cm_data.nameHash, 0, sizeof(cm_nc_t *) * NHSIZE);
+ for (i=0; i<NCSIZE; i++)
+ {
+ cm_data.nameCache[i].magic = CM_DNLC_MAGIC;
+ cm_data.nameCache[i].next = cm_data.ncfreelist;
+ cm_data.ncfreelist = &cm_data.nameCache[i];
+ }
+ purged = 1;
+ goto retry;
}
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 ;