Index: openafs/src/WINNT/afsapplib/NTMakefile diff -c openafs/src/WINNT/afsapplib/NTMakefile:1.5 openafs/src/WINNT/afsapplib/NTMakefile:1.5.2.1 *** openafs/src/WINNT/afsapplib/NTMakefile:1.5 Fri Nov 21 02:59:39 2003 --- openafs/src/WINNT/afsapplib/NTMakefile Fri Nov 5 14:21:40 2004 *************** *** 126,131 **** --- 126,134 ---- $(DEL) $*.lib $*.exp clean:: + $(CD) lang + for /f %l in ('dir /B ??_??') do @$(NTLANG) %l $(MAKECMD) /nologo /f NTMakefile clean + $(CD) .. ############################################################################ Index: openafs/src/WINNT/afsd/NTMakefile diff -c openafs/src/WINNT/afsd/NTMakefile:1.27.2.1 openafs/src/WINNT/afsd/NTMakefile:1.27.2.2 *** openafs/src/WINNT/afsd/NTMakefile:1.27.2.1 Thu Aug 19 15:50:58 2004 --- openafs/src/WINNT/afsd/NTMakefile Fri Nov 5 14:21:42 2004 *************** *** 339,364 **** AFSD_SDKLIBS =\ largeint.lib \ netapi32.lib \ ! dnsapi.lib mpr.lib \ rpcrt4.lib \ user32.lib \ ! Dbghelp.lib \ ! strsafe.lib \ ! mpr.lib \ ! secur32.lib \ ! ole32.lib \ ! oleaut32.lib AFSD_EXELIBS =\ $(DESTDIR)\lib\libosi.lib \ $(DESTDIR)\lib\afsrpc.lib \ ! $(DESTDIR)\lib\afsrx.lib \ $(DESTDIR)\lib\afsauthent.lib \ $(DESTDIR)\lib\afs\mtafsvldb.lib \ $(DESTDIR)\lib\afs\mtafsint.lib \ $(DESTDIR)\lib\libafsconf.lib \ $(DESTDIR)\lib\afs\afsreg.lib \ ! $(LANAHELPERLIB) $(AFSD_EXEFILE): $(OUT)\afsd.obj $(AFSDOBJS) $(OUT)\afsd.res $(RXOBJS) $(AFSD_EXELIBS) $(EXEGUILINK) $(AFSD_SDKLIBS) --- 339,364 ---- AFSD_SDKLIBS =\ largeint.lib \ netapi32.lib \ ! dnsapi.lib mpr.lib \ rpcrt4.lib \ user32.lib \ ! Dbghelp.lib \ ! strsafe.lib \ ! mpr.lib \ ! secur32.lib \ ! ole32.lib \ ! oleaut32.lib AFSD_EXELIBS =\ $(DESTDIR)\lib\libosi.lib \ $(DESTDIR)\lib\afsrpc.lib \ ! $(DESTDIR)\lib\afsrx.lib \ $(DESTDIR)\lib\afsauthent.lib \ $(DESTDIR)\lib\afs\mtafsvldb.lib \ $(DESTDIR)\lib\afs\mtafsint.lib \ $(DESTDIR)\lib\libafsconf.lib \ $(DESTDIR)\lib\afs\afsreg.lib \ ! $(LANAHELPERLIB) $(AFSD_EXEFILE): $(OUT)\afsd.obj $(AFSDOBJS) $(OUT)\afsd.res $(RXOBJS) $(AFSD_EXELIBS) $(EXEGUILINK) $(AFSD_SDKLIBS) Index: openafs/src/WINNT/afsd/afsd.c diff -c openafs/src/WINNT/afsd/afsd.c:1.8 openafs/src/WINNT/afsd/afsd.c:1.8.2.1 *** openafs/src/WINNT/afsd/afsd.c:1.8 Wed Dec 3 14:44:59 2003 --- openafs/src/WINNT/afsd/afsd.c Fri Nov 5 14:21:42 2004 *************** *** 53,58 **** --- 53,59 ---- MessageBox(NULL, tbuffer, msgp, MB_OK|MB_ICONSTOP|MB_SETFOREGROUND); afsd_ForceTrace(TRUE); + buf_ForceTrace(TRUE); if (traceOnPanic) { _asm int 3h; Index: openafs/src/WINNT/afsd/afsd95.c diff -c openafs/src/WINNT/afsd/afsd95.c:1.2 openafs/src/WINNT/afsd/afsd95.c:1.2.8.1 *** openafs/src/WINNT/afsd/afsd95.c:1.2 Fri Oct 5 17:40:47 2001 --- openafs/src/WINNT/afsd/afsd95.c Fri Nov 5 14:21:42 2004 *************** *** 52,57 **** --- 52,58 ---- /*MessageBox(NULL, tbuffer, msgp, MB_OK|MB_ICONSTOP|MB_SETFOREGROUND);*/ afsd_ForceTrace(TRUE); + buf_ForceTrace(TRUE); if (traceOnPanic) { /*asm("int 3");*/ Index: openafs/src/WINNT/afsd/afsd_init.c diff -c openafs/src/WINNT/afsd/afsd_init.c:1.40.2.5 openafs/src/WINNT/afsd/afsd_init.c:1.40.2.6 *** openafs/src/WINNT/afsd/afsd_init.c:1.40.2.5 Mon Oct 18 00:09:25 2004 --- openafs/src/WINNT/afsd/afsd_init.c Fri Nov 5 14:21:42 2004 *************** *** 22,28 **** #include "afsd.h" #include #include - #include #include "smb.h" --- 22,27 ---- *************** *** 651,657 **** char * p, *q; afsi_log("Sys name %s", buf); ! for (p = q = buf; p < cm_sysName + dummyLen; p++) { if (*p == '\0' || isspace(*p)) { memcpy(cm_sysNameList[cm_sysNameCount],q,p-q); --- 650,656 ---- char * p, *q; afsi_log("Sys name %s", buf); ! for (p = q = buf; p < buf + dummyLen; p++) { if (*p == '\0' || isspace(*p)) { memcpy(cm_sysNameList[cm_sysNameCount],q,p-q); Index: openafs/src/WINNT/afsd/afsd_service.c diff -c openafs/src/WINNT/afsd/afsd_service.c:1.28.2.2 openafs/src/WINNT/afsd/afsd_service.c:1.28.2.3 *** openafs/src/WINNT/afsd/afsd_service.c:1.28.2.2 Mon Oct 18 00:09:25 2004 --- openafs/src/WINNT/afsd/afsd_service.c Fri Nov 5 14:21:42 2004 *************** *** 82,87 **** --- 82,88 ---- osi_LogEnable(afsd_logp); afsd_ForceTrace(TRUE); + buf_ForceTrace(TRUE); afsi_log("--- begin dump ---"); cm_DumpSCache(afsi_file, "a"); *************** *** 176,183 **** RegCloseKey (parmKey); if (code != ERROR_SUCCESS) doTrace = 0; ! if (doTrace) afsd_ForceTrace(FALSE); doneTrace: ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING; --- 177,186 ---- RegCloseKey (parmKey); if (code != ERROR_SUCCESS) doTrace = 0; ! if (doTrace) { afsd_ForceTrace(FALSE); + buf_ForceTrace(FALSE); + } doneTrace: ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING; *************** *** 239,246 **** RegCloseKey (parmKey); if (code != ERROR_SUCCESS) doTrace = 0; ! if (doTrace) afsd_ForceTrace(FALSE); doneTrace: ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING; --- 242,251 ---- RegCloseKey (parmKey); if (code != ERROR_SUCCESS) doTrace = 0; ! if (doTrace) { afsd_ForceTrace(FALSE); + buf_ForceTrace(FALSE); + } doneTrace: ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING; Index: openafs/src/WINNT/afsd/afskfw.c diff -c openafs/src/WINNT/afsd/afskfw.c:1.8.2.4 openafs/src/WINNT/afsd/afskfw.c:1.8.2.5 *** openafs/src/WINNT/afsd/afskfw.c:1.8.2.4 Mon Oct 18 00:09:25 2004 --- openafs/src/WINNT/afsd/afskfw.c Fri Nov 5 14:21:42 2004 *************** *** 56,62 **** #define USE_MS2MIT ! #define USE_KRB4 #include "afskfw-int.h" #include "afskfw.h" --- 56,62 ---- #define USE_MS2MIT ! #undef USE_KRB4 #include "afskfw-int.h" #include "afskfw.h" *************** *** 288,293 **** --- 288,294 ---- END_FUNC_INFO }; + #ifdef USE_KRB4 FUNC_INFO k4_fi[] = { MAKE_FUNC_INFO(krb_get_cred), MAKE_FUNC_INFO(krb_get_tf_realm), *************** *** 295,300 **** --- 296,302 ---- MAKE_FUNC_INFO(tkt_string), END_FUNC_INFO }; + #endif FUNC_INFO k524_fi[] = { MAKE_FUNC_INFO(krb524_init_ets), *************** *** 388,394 **** --- 390,398 ---- if ( !inited ) { inited = 1; LoadFuncs(KRB5_DLL, k5_fi, &hKrb5, 0, 1, 0, 0); + #ifdef USE_KRB4 LoadFuncs(KRB4_DLL, k4_fi, &hKrb4, 0, 1, 0, 0); + #endif /* USE_KRB4 */ LoadFuncs(COMERR_DLL, ce_fi, &hComErr, 0, 0, 1, 0); LoadFuncs(SERVICE_DLL, service_fi, &hService, 0, 1, 0, 0); #ifdef USE_MS2MIT *************** *** 457,476 **** len = sizeof(use524); code = RegQueryValueEx(parmKey, "Use524", NULL, NULL, (BYTE *) &use524, &len); ! if (code != ERROR_SUCCESS) { ! RegCloseKey(parmKey); ! ! code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, OpenAFSConfigKeyName, ! 0, KEY_QUERY_VALUE, &parmKey); ! if (code == ERROR_SUCCESS) { ! len = sizeof(use524); ! code = RegQueryValueEx(parmKey, "Use524", NULL, NULL, ! (BYTE *) &use524, &len); ! if (code != ERROR_SUCCESS) ! use524 = 0; ! } } - RegCloseKey (parmKey); } return use524; } --- 461,477 ---- len = sizeof(use524); code = RegQueryValueEx(parmKey, "Use524", NULL, NULL, (BYTE *) &use524, &len); ! RegCloseKey(parmKey); ! } ! if (code != ERROR_SUCCESS) { ! code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, OpenAFSConfigKeyName, ! 0, KEY_QUERY_VALUE, &parmKey); ! if (code == ERROR_SUCCESS) { ! len = sizeof(use524); ! code = RegQueryValueEx(parmKey, "Use524", NULL, NULL, ! (BYTE *) &use524, &len); ! RegCloseKey (parmKey); } } return use524; } *************** *** 488,508 **** len = sizeof(enableKFW); code = RegQueryValueEx(parmKey, "EnableKFW", NULL, NULL, (BYTE *) &enableKFW, &len); - if (code != ERROR_SUCCESS) { - RegCloseKey(parmKey); - - code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, OpenAFSConfigKeyName, - 0, KEY_QUERY_VALUE, &parmKey); - if (code == ERROR_SUCCESS) { - len = sizeof(enableKFW); - code = RegQueryValueEx(parmKey, "EnableKFW", NULL, NULL, - (BYTE *) &enableKFW, &len); - if (code != ERROR_SUCCESS) - enableKFW = 1; - } - } RegCloseKey (parmKey); } if ( !enableKFW ) return FALSE; --- 489,508 ---- len = sizeof(enableKFW); code = RegQueryValueEx(parmKey, "EnableKFW", NULL, NULL, (BYTE *) &enableKFW, &len); RegCloseKey (parmKey); } + + if (code != ERROR_SUCCESS) { + code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, OpenAFSConfigKeyName, + 0, KEY_QUERY_VALUE, &parmKey); + if (code == ERROR_SUCCESS) { + len = sizeof(enableKFW); + code = RegQueryValueEx(parmKey, "EnableKFW", NULL, NULL, + (BYTE *) &enableKFW, &len); + RegCloseKey (parmKey); + } + } + if ( !enableKFW ) return FALSE; *************** *** 2643,2649 **** } } #else ! goto cleanup; #endif strcpy(realm_of_cell, afs_realm_of_cell(ctx, &ak_cellconfig)); --- 2643,2650 ---- } } #else ! if (!try_krb5) ! goto cleanup; #endif strcpy(realm_of_cell, afs_realm_of_cell(ctx, &ak_cellconfig)); *************** *** 2700,2706 **** code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds); if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN || code == KRB5KRB_ERR_GENERIC /* heimdal */ || ! code == KRB5KRB_AP_ERR_MSG_TYPE) { /* Or service@REALM */ pkrb5_free_principal(ctx,increds.server); increds.server = 0; --- 2701,2707 ---- code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds); if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN || code == KRB5KRB_ERR_GENERIC /* heimdal */ || ! code == KRB5KRB_AP_ERR_MSG_TYPE) { /* Or service@REALM */ pkrb5_free_principal(ctx,increds.server); increds.server = 0; *************** *** 2730,2736 **** if ((code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN || code == KRB5KRB_ERR_GENERIC /* heimdal */ || ! code == KRB5KRB_AP_ERR_MSG_TYPE) && strcmp(RealmName, realm_of_cell)) { /* Or service/cell@REALM_OF_CELL */ strcpy(RealmName, realm_of_cell); --- 2731,2737 ---- if ((code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN || code == KRB5KRB_ERR_GENERIC /* heimdal */ || ! code == KRB5KRB_AP_ERR_MSG_TYPE) && strcmp(RealmName, realm_of_cell)) { /* Or service/cell@REALM_OF_CELL */ strcpy(RealmName, realm_of_cell); *************** *** 3021,3027 **** if (ctx && (ctx != alt_ctx)) pkrb5_free_context(ctx); ! return(rc? rc : code); } /**************************************/ --- 3022,3028 ---- if (ctx && (ctx != alt_ctx)) pkrb5_free_context(ctx); ! return(rc? rc : code); } /**************************************/ Index: openafs/src/WINNT/afsd/cm.h diff -c openafs/src/WINNT/afsd/cm.h:1.9 openafs/src/WINNT/afsd/cm.h:1.9.2.1 *** openafs/src/WINNT/afsd/cm.h:1.9 Mon Jul 26 19:22:20 2004 --- openafs/src/WINNT/afsd/cm.h Fri Nov 5 14:21:42 2004 *************** *** 245,252 **** #define CM_ERROR_BUFFERTOOSMALL (CM_ERROR_BASE+38) #define CM_ERROR_RENAME_IDENTICAL (CM_ERROR_BASE+39) #define CM_ERROR_ALLOFFLINE (CM_ERROR_BASE+40) ! #define CM_ERROR_AMBIGUOUS_FILENAME (CM_ERROR_BASE+41) ! #define CM_ERROR_BADLOGONTYPE (CM_ERROR_BASE+42) ! #define CM_ERROR_GSSCONTINUE (CM_ERROR_BASE+43) ! #define CM_ERROR_TIDIPC (CM_ERROR_BASE+44) #endif /* __CM_H_ENV__ */ --- 245,253 ---- #define CM_ERROR_BUFFERTOOSMALL (CM_ERROR_BASE+38) #define CM_ERROR_RENAME_IDENTICAL (CM_ERROR_BASE+39) #define CM_ERROR_ALLOFFLINE (CM_ERROR_BASE+40) ! #define CM_ERROR_AMBIGUOUS_FILENAME (CM_ERROR_BASE+41) ! #define CM_ERROR_BADLOGONTYPE (CM_ERROR_BASE+42) ! #define CM_ERROR_GSSCONTINUE (CM_ERROR_BASE+43) ! #define CM_ERROR_TIDIPC (CM_ERROR_BASE+44) ! #define CM_ERROR_TOO_MANY_SYMLINKS (CM_ERROR_BASE+45) #endif /* __CM_H_ENV__ */ Index: openafs/src/WINNT/afsd/cm_buf.c diff -c openafs/src/WINNT/afsd/cm_buf.c:1.13.2.2 openafs/src/WINNT/afsd/cm_buf.c:1.13.2.3 *** openafs/src/WINNT/afsd/cm_buf.c:1.13.2.2 Sun Oct 10 19:52:04 2004 --- openafs/src/WINNT/afsd/cm_buf.c Fri Nov 5 14:21:43 2004 *************** *** 19,27 **** --- 19,32 ---- #include #include #include + #include #include "afsd.h" + #ifdef DEBUG + #define TRACE_BUFFER 1 + #endif + extern void afsi_log(char *pattern, ...); /* This module implements the buffer package used by the local transaction *************** *** 306,317 **** OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hf == INVALID_HANDLE_VALUE) { afsi_log("Error creating cache file \"%s\" error %d", cm_CachePath, GetLastError()); return CM_ERROR_INVAL; } - FreeCacheFileSA(psa); } else { /* buf_cacheType == CM_BUF_CACHETYPE_VIRTUAL */ hf = INVALID_HANDLE_VALUE; } --- 311,322 ---- OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + FreeCacheFileSA(psa); if (hf == INVALID_HANDLE_VALUE) { afsi_log("Error creating cache file \"%s\" error %d", cm_CachePath, GetLastError()); return CM_ERROR_INVAL; } } else { /* buf_cacheType == CM_BUF_CACHETYPE_VIRTUAL */ hf = INVALID_HANDLE_VALUE; } *************** *** 378,385 **** /* just for safety's sake */ buf_maxReservedBufs = buf_nbuffers - 3; /* init the buffer trace log */ ! buf_logp = osi_LogCreate("buffer", 10); osi_EndOnce(&once); --- 383,393 ---- /* just for safety's sake */ buf_maxReservedBufs = buf_nbuffers - 3; + #ifdef TRACE_BUFFER /* init the buffer trace log */ ! buf_logp = osi_LogCreate("buffer", 1000); ! osi_LogEnable(buf_logp); ! #endif osi_EndOnce(&once); *************** *** 532,538 **** bp->flags |= CM_BUF_WAITING; osi_SleepM((long) bp, &bp->mx); lock_ObtainMutex(&bp->mx); ! osi_Log1(buf_logp, "buf_WaitIO conflict wait done for 0x%x", bp); } /* if we get here, the IO is done, but we may have to wakeup people waiting for --- 540,546 ---- bp->flags |= CM_BUF_WAITING; osi_SleepM((long) bp, &bp->mx); lock_ObtainMutex(&bp->mx); ! osi_Log1(buf_logp, "buf_WaitIO conflict wait done for 0x%x", bp); } /* if we get here, the IO is done, but we may have to wakeup people waiting for *************** *** 1481,1483 **** --- 1489,1512 ---- return 0; } + void buf_ForceTrace(BOOL flush) + { + HANDLE handle; + int len; + char buf[256]; + + if (!buf_logp) + return; + + len = GetTempPath(sizeof(buf)-10, buf); + StringCbCopyA(&buf[len], sizeof(buf)-len, "/afs-buffer.log"); + handle = CreateFile(buf, GENERIC_WRITE, FILE_SHARE_READ, + NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (handle == INVALID_HANDLE_VALUE) { + osi_panic("Cannot create log file", __FILE__, __LINE__); + } + osi_LogPrint(buf_logp, handle); + if (flush) + FlushFileBuffers(handle); + CloseHandle(handle); + } Index: openafs/src/WINNT/afsd/cm_buf.h diff -c openafs/src/WINNT/afsd/cm_buf.h:1.4.2.2 openafs/src/WINNT/afsd/cm_buf.h:1.4.2.3 *** openafs/src/WINNT/afsd/cm_buf.h:1.4.2.2 Mon Oct 18 00:09:25 2004 --- openafs/src/WINNT/afsd/cm_buf.h Fri Nov 5 14:21:43 2004 *************** *** 195,200 **** --- 195,202 ---- extern long buf_SetNBuffers(long nbuffers); + extern void buf_ForceTrace(BOOL flush); + /* error codes */ #define CM_BUF_EXISTS 1 /* buffer exists, and shouldn't */ #define CM_ERROR_BASEBUF 0x33333333 Index: openafs/src/WINNT/afsd/cm_conn.c diff -c openafs/src/WINNT/afsd/cm_conn.c:1.25.2.3 openafs/src/WINNT/afsd/cm_conn.c:1.25.2.4 *** openafs/src/WINNT/afsd/cm_conn.c:1.25.2.3 Mon Oct 18 00:09:25 2004 --- openafs/src/WINNT/afsd/cm_conn.c Fri Nov 5 14:21:43 2004 *************** *** 384,395 **** long cm_ConnByMServers(cm_serverRef_t *serversp, cm_user_t *usersp, cm_req_t *reqp, cm_conn_t **connpp) { ! long code; ! cm_serverRef_t *tsrp; cm_server_t *tsp; long firstError = 0; ! int someBusy = 0, someOffline = 0, allBusy = 1, allDown = 1; ! long timeUsed, timeLeft, hardTimeLeft; #ifdef DJGPP struct timeval now; #endif /* DJGPP */ --- 384,395 ---- long cm_ConnByMServers(cm_serverRef_t *serversp, cm_user_t *usersp, cm_req_t *reqp, cm_conn_t **connpp) { ! long code; ! cm_serverRef_t *tsrp; cm_server_t *tsp; long firstError = 0; ! int someBusy = 0, someOffline = 0, allBusy = 1, allDown = 1; ! long timeUsed, timeLeft, hardTimeLeft; #ifdef DJGPP struct timeval now; #endif /* DJGPP */ *************** *** 397,413 **** *connpp = NULL; #ifndef DJGPP ! timeUsed = (GetCurrentTime() - reqp->startTime) / 1000; #else gettimeofday(&now, NULL); timeUsed = sub_time(now, reqp->startTime) / 1000; #endif ! /* leave 5 seconds margin of safety */ ! timeLeft = ConnDeadtimeout - timeUsed - 5; ! hardTimeLeft = HardDeadtimeout - timeUsed - 5; ! lock_ObtainWrite(&cm_serverLock); for (tsrp = serversp; tsrp; tsrp=tsrp->next) { tsp = tsrp->server; cm_GetServerNoLock(tsp); --- 397,413 ---- *connpp = NULL; #ifndef DJGPP ! timeUsed = (GetCurrentTime() - reqp->startTime) / 1000; #else gettimeofday(&now, NULL); timeUsed = sub_time(now, reqp->startTime) / 1000; #endif ! /* leave 5 seconds margin of safety */ ! timeLeft = ConnDeadtimeout - timeUsed - 5; ! hardTimeLeft = HardDeadtimeout - timeUsed - 5; ! lock_ObtainWrite(&cm_serverLock); for (tsrp = serversp; tsrp; tsrp=tsrp->next) { tsp = tsrp->server; cm_GetServerNoLock(tsp); *************** *** 419,425 **** else if (tsrp->status == offline) someOffline = 1; else { ! allBusy = 0; code = cm_ConnByServer(tsp, usersp, connpp); if (code == 0) { cm_PutServer(tsp); --- 419,425 ---- else if (tsrp->status == offline) someOffline = 1; else { ! allBusy = 0; code = cm_ConnByServer(tsp, usersp, connpp); if (code == 0) { cm_PutServer(tsp); *************** *** 439,462 **** if (firstError == 0) firstError = code; } ! } lock_ObtainWrite(&cm_serverLock); cm_PutServerNoLock(tsp); } ! lock_ReleaseWrite(&cm_serverLock); ! if (firstError == 0) { if (serversp == NULL) ! firstError = CM_ERROR_NOSUCHVOLUME; else if (allDown) ! firstError = CM_ERROR_ALLOFFLINE; ! else if (allBusy) ! firstError = CM_ERROR_ALLBUSY; ! else ! firstError = CM_ERROR_TIMEDOUT; ! } ! osi_Log1(afsd_logp, "cm_ConnByMServers returning %x", firstError); return firstError; } --- 439,462 ---- if (firstError == 0) firstError = code; } ! } lock_ObtainWrite(&cm_serverLock); cm_PutServerNoLock(tsp); } ! lock_ReleaseWrite(&cm_serverLock); ! if (firstError == 0) { if (serversp == NULL) ! firstError = CM_ERROR_NOSUCHVOLUME; else if (allDown) ! firstError = CM_ERROR_ALLOFFLINE; ! else if (allBusy) ! firstError = CM_ERROR_ALLBUSY; ! else ! firstError = CM_ERROR_TIMEDOUT; ! } ! osi_Log1(afsd_logp, "cm_ConnByMServers returning %x", firstError); return firstError; } Index: openafs/src/WINNT/afsd/cm_freelance.c diff -c openafs/src/WINNT/afsd/cm_freelance.c:1.15.2.2 openafs/src/WINNT/afsd/cm_freelance.c:1.15.2.3 *** openafs/src/WINNT/afsd/cm_freelance.c:1.15.2.2 Mon Oct 18 00:09:26 2004 --- openafs/src/WINNT/afsd/cm_freelance.c Fri Nov 5 14:21:44 2004 *************** *** 73,78 **** --- 73,117 ---- } } } + + void cm_FreelanceSymlinkChangeNotifier(void * parmp) { + HANDLE hFreelanceSymlinkChangeEvent = 0; + HKEY hkFreelance = 0; + + if (RegOpenKeyEx( HKEY_LOCAL_MACHINE, + "SOFTWARE\\OpenAFS\\Client\\Freelance\\Symlinks", + 0, + KEY_NOTIFY, + &hkFreelance) == ERROR_SUCCESS) { + + hFreelanceSymlinkChangeEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + if (hFreelanceSymlinkChangeEvent == NULL) { + RegCloseKey(hkFreelance); + return; + } + } + + while ( TRUE ) { + /* check hFreelanceSymlinkChangeEvent to see if it is set. + * if so, call cm_noteLocalMountPointSymlinkChange() + */ + if (RegNotifyChangeKeyValue( hkFreelance, /* hKey */ + FALSE, /* bWatchSubtree */ + REG_NOTIFY_CHANGE_LAST_SET, /* dwNotifyFilter */ + hFreelanceSymlinkChangeEvent, /* hEvent */ + TRUE /* fAsynchronous */ + ) != ERROR_SUCCESS) { + RegCloseKey(hkFreelance); + CloseHandle(hFreelanceSymlinkChangeEvent); + return; + } + + if (WaitForSingleObject(hFreelanceSymlinkChangeEvent, INFINITE) == WAIT_OBJECT_0) + { + cm_noteLocalMountPointChange(); + } + } + } #endif void cm_InitFreelance() { *************** *** 98,110 **** NULL, 0, &lpid, "cm_FreelanceChangeNotifier"); osi_assert(phandle != NULL); thrd_CloseHandle(phandle); #endif } /* yj: Initialization of the fake root directory */ /* to be called while holding freelance lock unless during init. */ void cm_InitFakeRootDir() { - int i, t1, t2; char* currentPos; int noChunks; --- 137,153 ---- NULL, 0, &lpid, "cm_FreelanceChangeNotifier"); osi_assert(phandle != NULL); thrd_CloseHandle(phandle); + + phandle = thrd_Create(NULL, 65536, (ThreadFunc) cm_FreelanceSymlinkChangeNotifier, + NULL, 0, &lpid, "cm_FreelanceSymlinkChangeNotifier"); + osi_assert(phandle != NULL); + thrd_CloseHandle(phandle); #endif } /* yj: Initialization of the fake root directory */ /* to be called while holding freelance lock unless during init. */ void cm_InitFakeRootDir() { int i, t1, t2; char* currentPos; int noChunks; *************** *** 398,409 **** long code; char rootCellName[256]; #if !defined(DJGPP) ! HKEY hkFreelance = 0; DWORD dwType, dwSize; ! DWORD dwMountPoints; DWORD dwIndex; FILETIME ftLastWriteTime; - afs_uint32 unixTime; #endif #if !defined(DJGPP) --- 441,452 ---- long code; char rootCellName[256]; #if !defined(DJGPP) ! HKEY hkFreelance = 0, hkFreelanceSymlinks = 0; DWORD dwType, dwSize; ! DWORD dwMountPoints = 0; DWORD dwIndex; + DWORD dwSymlinks = 0; FILETIME ftLastWriteTime; #endif #if !defined(DJGPP) *************** *** 440,448 **** dwMountPoints = 2; } // get the number of entries there are from the first line // that we read ! cm_noLocalMountPoints = dwMountPoints; // create space to store the local mount points cm_localMountPoints = malloc(sizeof(cm_localMountPoint_t) * cm_noLocalMountPoints); --- 483,516 ---- dwMountPoints = 2; } + if (RegCreateKeyEx( HKEY_LOCAL_MACHINE, + "SOFTWARE\\OpenAFS\\Client\\Freelance\\Symlinks", + 0, + NULL, + REG_OPTION_NON_VOLATILE, + KEY_READ|KEY_WRITE|KEY_QUERY_VALUE, + NULL, + &hkFreelanceSymlinks, + NULL) == ERROR_SUCCESS) { + + RegQueryInfoKey( hkFreelanceSymlinks, + NULL, /* lpClass */ + NULL, /* lpcClass */ + NULL, /* lpReserved */ + NULL, /* lpcSubKeys */ + NULL, /* lpcMaxSubKeyLen */ + NULL, /* lpcMaxClassLen */ + &dwSymlinks, /* lpcValues */ + NULL, /* lpcMaxValueNameLen */ + NULL, /* lpcMaxValueLen */ + NULL, /* lpcbSecurityDescriptor */ + NULL /* lpftLastWriteTime */ + ); + } + // get the number of entries there are from the first line // that we read ! cm_noLocalMountPoints = dwMountPoints + dwSymlinks; // create space to store the local mount points cm_localMountPoints = malloc(sizeof(cm_localMountPoint_t) * cm_noLocalMountPoints); *************** *** 478,491 **** cm_noLocalMountPoints--; continue; } aLocalMountPoint->namep=malloc(t-line+1); strncpy(aLocalMountPoint->namep, line, t-line); aLocalMountPoint->namep[t-line] = '\0'; ! /* copy the mount point string without the trailing dot */ aLocalMountPoint->mountPointStringp=malloc(strlen(t)); ! strncpy(aLocalMountPoint->mountPointStringp, t, strlen(t)-1); ! aLocalMountPoint->mountPointStringp[strlen(t)-1] = '\0'; osi_Log2(afsd_logp,"found mount point: name %s, string %s", osi_LogSaveString(afsd_logp,aLocalMountPoint->namep), --- 546,561 ---- cm_noLocalMountPoints--; continue; } + + aLocalMountPoint->fileType = CM_SCACHETYPE_MOUNTPOINT; aLocalMountPoint->namep=malloc(t-line+1); strncpy(aLocalMountPoint->namep, line, t-line); aLocalMountPoint->namep[t-line] = '\0'; ! /* copy the mount point string */ aLocalMountPoint->mountPointStringp=malloc(strlen(t)); ! strncpy(aLocalMountPoint->mountPointStringp, t, strlen(t)-1); ! aLocalMountPoint->mountPointStringp[strlen(t)-1] = '\0'; osi_Log2(afsd_logp,"found mount point: name %s, string %s", osi_LogSaveString(afsd_logp,aLocalMountPoint->namep), *************** *** 494,499 **** --- 564,611 ---- aLocalMountPoint++; } + for ( dwIndex = 0 ; dwIndex < dwSymlinks; dwIndex++ ) { + TCHAR szValueName[16]; + DWORD dwValueSize = 16; + dwSize = sizeof(line); + RegEnumValue( hkFreelanceSymlinks, dwIndex, szValueName, &dwValueSize, NULL, + &dwType, line, &dwSize); + + /* find the trailing dot; null terminate after it */ + t2 = strrchr(line, '.'); + if (t2) + *(t2+1) = '\0'; + + // line is not empty, so let's parse it + t = strchr(line, ':'); + + // make sure that there is a ':' separator in the line + if (!t) { + afsi_log("error occurred while parsing symlink entry: no ':' separator in line %d", dwIndex); + fprintf(stderr, "error occurred while parsing symlink entry: no ':' separator in line %d", dwIndex); + cm_noLocalMountPoints--; + continue; + } + + aLocalMountPoint->fileType = CM_SCACHETYPE_SYMLINK; + aLocalMountPoint->namep=malloc(t-line+1); + strncpy(aLocalMountPoint->namep, line, t-line); + aLocalMountPoint->namep[t-line] = '\0'; + + /* copy the symlink string */ + aLocalMountPoint->mountPointStringp=malloc(strlen(t)-1); + strncpy(aLocalMountPoint->mountPointStringp, t+1, strlen(t)-2); + aLocalMountPoint->mountPointStringp[strlen(t)-2] = '\0'; + + osi_Log2(afsd_logp,"found symlink: name %s, string %s", + osi_LogSaveString(afsd_logp,aLocalMountPoint->namep), + osi_LogSaveString(afsd_logp,aLocalMountPoint->mountPointStringp)); + + aLocalMountPoint++; + } + + if ( hkFreelanceSymlinks ) + RegCloseKey( hkFreelanceSymlinks ); RegCloseKey(hkFreelance); return 0; } *************** *** 625,634 **** return cm_noLocalMountPoints; } - cm_localMountPoint_t* cm_getLocalMountPoint(int vnode) { - return 0; - } - long cm_FreelanceAddMount(char *filename, char *cellname, char *volume, int rw, cm_fid_t *fidp) { FILE *fp; --- 737,742 ---- *************** *** 688,709 **** ); if (rw) ! sprintf(line, "%s%%%s:%s\n", filename, fullname, volume); else ! sprintf(line, "%s#%s:%s\n", filename, fullname, volume); /* If we are adding a new value, there must be an unused name * within the range 0 to dwMountPoints */ for ( dwIndex = 0; dwIndex <= dwMountPoints; dwIndex++ ) { char szIndex[16]; sprintf(szIndex, "%d", dwIndex); ! if (RegQueryValueEx( hkFreelance, szIndex, 0, &dwType, NULL, &dwSize) != ERROR_SUCCESS) { /* found an unused value */ dwType = REG_SZ; dwSize = strlen(line) + 1; RegSetValueEx( hkFreelance, szIndex, 0, dwType, line, dwSize); break; } } RegCloseKey(hkFreelance); --- 796,830 ---- ); if (rw) ! sprintf(line, "%s%%%s:%s", filename, fullname, volume); else ! sprintf(line, "%s#%s:%s", filename, fullname, volume); /* If we are adding a new value, there must be an unused name * within the range 0 to dwMountPoints */ for ( dwIndex = 0; dwIndex <= dwMountPoints; dwIndex++ ) { char szIndex[16]; + char szMount[1024]; + + dwSize = sizeof(szMount); sprintf(szIndex, "%d", dwIndex); ! if (RegQueryValueEx( hkFreelance, szIndex, 0, &dwType, szMount, &dwSize) != ERROR_SUCCESS) { /* found an unused value */ dwType = REG_SZ; dwSize = strlen(line) + 1; RegSetValueEx( hkFreelance, szIndex, 0, dwType, line, dwSize); break; + } else { + int len = strlen(filename); + if ( dwType == REG_SZ && !strncmp(filename, szMount, len) && + (szMount[len] == '%' || szMount[len] == '#')) { + /* Replace the existing value */ + dwType = REG_SZ; + dwSize = strlen(line) + 1; + RegSetValueEx( hkFreelance, szIndex, 0, dwType, line, dwSize); + break; + } } } RegCloseKey(hkFreelance); *************** *** 847,850 **** --- 968,1127 ---- return 0; } + long cm_FreelanceAddSymlink(char *filename, char *destination, cm_fid_t *fidp) + { + FILE *fp; + char hfile[120]; + char line[512]; + char fullname[200]; + int n; + int alias = 0; + #if !defined(DJGPP) + HKEY hkFreelanceSymlinks = 0; + DWORD dwType, dwSize; + DWORD dwSymlinks; + DWORD dwIndex; + #endif + + /* before adding, verify the cell name; if it is not a valid cell, + don't add the mount point. + allow partial matches as a means of poor man's alias. */ + /* major performance issue? */ + osi_Log2(afsd_logp,"Freelance Add Symlink request: filename=%s destination=%s", + osi_LogSaveString(afsd_logp,filename), + osi_LogSaveString(afsd_logp,destination)); + + lock_ObtainMutex(&cm_Freelance_Lock); + + #if !defined(DJGPP) + if (RegCreateKeyEx( HKEY_LOCAL_MACHINE, + "SOFTWARE\\OpenAFS\\Client\\Freelance\\Symlinks", + 0, + NULL, + REG_OPTION_NON_VOLATILE, + KEY_READ|KEY_WRITE|KEY_QUERY_VALUE, + NULL, + &hkFreelanceSymlinks, + NULL) == ERROR_SUCCESS) { + + RegQueryInfoKey( hkFreelanceSymlinks, + NULL, /* lpClass */ + NULL, /* lpcClass */ + NULL, /* lpReserved */ + NULL, /* lpcSubKeys */ + NULL, /* lpcMaxSubKeyLen */ + NULL, /* lpcMaxClassLen */ + &dwSymlinks, /* lpcValues */ + NULL, /* lpcMaxValueNameLen */ + NULL, /* lpcMaxValueLen */ + NULL, /* lpcbSecurityDescriptor */ + NULL /* lpftLastWriteTime */ + ); + + sprintf(line, "%s:%s.", filename, destination); + + /* If we are adding a new value, there must be an unused name + * within the range 0 to dwSymlinks + */ + for ( dwIndex = 0; dwIndex <= dwSymlinks; dwIndex++ ) { + char szIndex[16]; + char szLink[1024]; + + dwSize = sizeof(szLink); + sprintf(szIndex, "%d", dwIndex); + if (RegQueryValueEx( hkFreelanceSymlinks, szIndex, 0, &dwType, szLink, &dwSize) != ERROR_SUCCESS) { + /* found an unused value */ + dwType = REG_SZ; + dwSize = strlen(line) + 1; + RegSetValueEx( hkFreelanceSymlinks, szIndex, 0, dwType, line, dwSize); + break; + } else { + int len = strlen(filename); + if ( dwType == REG_SZ && !strncmp(filename, szLink, len) && szLink[len] == ':') { + /* Replace the existing value */ + dwType = REG_SZ; + dwSize = strlen(line) + 1; + RegSetValueEx( hkFreelanceSymlinks, szIndex, 0, dwType, line, dwSize); + break; + } + } + } + RegCloseKey(hkFreelanceSymlinks); + } + #endif + lock_ReleaseMutex(&cm_Freelance_Lock); + + /* cm_reInitLocalMountPoints(); */ + if (fidp) { + fidp->unique = 1; + fidp->vnode = cm_noLocalMountPoints + 1; /* vnode value of last mt pt */ + } + cm_noteLocalMountPointChange(); + return 0; + } + + long cm_FreelanceRemoveSymlink(char *toremove) + { + int i, n; + char* cp; + char line[512]; + char shortname[200]; + char hfile[120], hfile2[120]; + FILE *fp1, *fp2; + int found=0; + #if !defined(DJGPP) + HKEY hkFreelanceSymlinks = 0; + DWORD dwType, dwSize; + DWORD dwSymlinks; + DWORD dwIndex; + #endif + + lock_ObtainMutex(&cm_Freelance_Lock); + + + #if !defined(DJGPP) + if (RegOpenKeyEx( HKEY_LOCAL_MACHINE, + "SOFTWARE\\OpenAFS\\Client\\Freelance\\Symlinks", + 0, + KEY_READ|KEY_WRITE|KEY_QUERY_VALUE, + &hkFreelanceSymlinks) == ERROR_SUCCESS) { + + RegQueryInfoKey( hkFreelanceSymlinks, + NULL, /* lpClass */ + NULL, /* lpcClass */ + NULL, /* lpReserved */ + NULL, /* lpcSubKeys */ + NULL, /* lpcMaxSubKeyLen */ + NULL, /* lpcMaxClassLen */ + &dwSymlinks, /* lpcValues */ + NULL, /* lpcMaxValueNameLen */ + NULL, /* lpcMaxValueLen */ + NULL, /* lpcbSecurityDescriptor */ + NULL /* lpftLastWriteTime */ + ); + + for ( dwIndex = 0; dwIndex < dwSymlinks; dwIndex++ ) { + TCHAR szValueName[16]; + DWORD dwValueSize = 16; + dwSize = sizeof(line); + RegEnumValue( hkFreelanceSymlinks, dwIndex, szValueName, &dwValueSize, NULL, + &dwType, line, &dwSize); + + cp=strchr(line, ':'); + memcpy(shortname, line, cp-line); + shortname[cp-line]=0; + + if (!strcmp(shortname, toremove)) { + RegDeleteValue( hkFreelanceSymlinks, szValueName ); + break; + } + } + RegCloseKey(hkFreelanceSymlinks); + } + #endif + + lock_ReleaseMutex(&cm_Freelance_Lock); + cm_noteLocalMountPointChange(); + return 0; + } #endif /* AFS_FREELANCE_CLIENT */ Index: openafs/src/WINNT/afsd/cm_freelance.h diff -c openafs/src/WINNT/afsd/cm_freelance.h:1.6.2.1 openafs/src/WINNT/afsd/cm_freelance.h:1.6.2.2 *** openafs/src/WINNT/afsd/cm_freelance.h:1.6.2.1 Mon Oct 18 00:09:26 2004 --- openafs/src/WINNT/afsd/cm_freelance.h Fri Nov 5 14:21:44 2004 *************** *** 3,21 **** typedef struct cm_localMountPoint { ! char* namep; ! char* mountPointStringp; ! struct cm_localMountPoint* next; } cm_localMountPoint_t; extern int cm_getNoLocalMountPoints(); extern long cm_InitLocalMountPoints(); extern int cm_getLocalMountPointChange(); extern int cm_reInitLocalMountPoints(); - extern cm_localMountPoint_t* cm_getLocalMountPoint(int vnode); extern void cm_InitFreelance(); extern long cm_FreelanceRemoveMount(char *toremove); extern long cm_FreelanceAddMount(char *filename, char *cellname, char *volume, int rw, cm_fid_t *fidp); extern int cm_clearLocalMountPointChange(); extern int cm_FakeRootFid(cm_fid_t *fidp); --- 3,23 ---- typedef struct cm_localMountPoint { ! char* namep; ! char* mountPointStringp; ! unsigned int fileType; ! struct cm_localMountPoint* next; } cm_localMountPoint_t; extern int cm_getNoLocalMountPoints(); extern long cm_InitLocalMountPoints(); extern int cm_getLocalMountPointChange(); extern int cm_reInitLocalMountPoints(); extern void cm_InitFreelance(); extern long cm_FreelanceRemoveMount(char *toremove); extern long cm_FreelanceAddMount(char *filename, char *cellname, char *volume, int rw, cm_fid_t *fidp); + extern long cm_FreelanceRemoveSymlink(char *toremove); + extern long cm_FreelanceAddSymlink(char *filename, char *destination, cm_fid_t *fidp); extern int cm_clearLocalMountPointChange(); extern int cm_FakeRootFid(cm_fid_t *fidp); Index: openafs/src/WINNT/afsd/cm_ioctl.c diff -c openafs/src/WINNT/afsd/cm_ioctl.c:1.33.2.4 openafs/src/WINNT/afsd/cm_ioctl.c:1.33.2.5 *** openafs/src/WINNT/afsd/cm_ioctl.c:1.33.2.4 Mon Oct 18 00:09:26 2004 --- openafs/src/WINNT/afsd/cm_ioctl.c Fri Nov 5 14:21:44 2004 *************** *** 458,470 **** code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp); if (code) return code; ! cellp = cm_FindCellByID(scp->fid.cell); ! if (cellp) { ! strcpy(ioctlp->outDatap, cellp->namep); ioctlp->outDatap += strlen(ioctlp->outDatap) + 1; code = 0; } - else code = CM_ERROR_NOSUCHCELL; cm_ReleaseSCache(scp); return code; --- 458,483 ---- code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp); if (code) return code; ! #ifdef AFS_FREELANCE_CLIENT ! if ( cm_freelanceEnabled && ! scp->fid.cell==AFS_FAKE_ROOT_CELL_ID && ! scp->fid.volume==AFS_FAKE_ROOT_VOL_ID && ! scp->fid.vnode==0x1 && scp->fid.unique==0x1 ) { ! strcpy(ioctlp->outDatap, "Freelance.Local.Root"); ioctlp->outDatap += strlen(ioctlp->outDatap) + 1; code = 0; + } else + #endif /* AFS_FREELANCE_CLIENT */ + { + cellp = cm_FindCellByID(scp->fid.cell); + if (cellp) { + strcpy(ioctlp->outDatap, cellp->namep); + ioctlp->outDatap += strlen(ioctlp->outDatap) + 1; + code = 0; + } + else + code = CM_ERROR_NOSUCHCELL; } cm_ReleaseSCache(scp); return code; *************** *** 983,988 **** --- 996,1002 ---- /* print trace */ if (inValue & 8) { afsd_ForceTrace(FALSE); + buf_ForceTrace(FALSE); } if (inValue & 2) { *************** *** 1213,1218 **** --- 1227,1233 ---- * do lookups of @sys entries and thinks it can trust them */ /* privs ok, store the entry, ... */ strcpy(cm_sysName, inname); + strcpy(cm_sysNameList[0], inname); if (setSysName > 1) { /* ... or list */ cp = ioctlp->inDatap; for (count = 1; count < setSysName; ++count) { *************** *** 1220,1226 **** osi_panic("cm_IoctlSysName: no cm_sysNameList entry to write\n", __FILE__, __LINE__); t = strlen(cp); ! memcpy(cm_sysNameList[count], cp, t + 1); /* include null */ cp += t + 1; } } --- 1235,1241 ---- osi_panic("cm_IoctlSysName: no cm_sysNameList entry to write\n", __FILE__, __LINE__); t = strlen(cp); ! strcpy(cm_sysNameList[count], cp); cp += t + 1; } } *************** *** 1509,1514 **** --- 1524,1549 ---- cp = ioctlp->inDatap; /* contents of link */ + #ifdef AFS_FREELANCE_CLIENT + if (cm_freelanceEnabled && dscp == cm_rootSCachep) { + /* we are adding the symlink to the root dir., so call + * the freelance code to do the add. */ + if (cp[0] == cp[1] && cp[1] == '\\' && + !_strnicmp(cm_NetbiosName,cp+2,strlen(cm_NetbiosName))) + { + /* skip \\AFS\ or \\AFS\all\ */ + char * p; + p = cp + 2 + strlen(cm_NetbiosName) + 1; + if ( !_strnicmp("all", p, 3) ) + p += 4; + cp = p; + } + osi_Log0(afsd_logp,"IoctlCreateSymlink within Freelance root dir"); + code = cm_FreelanceAddSymlink(leaf, cp, NULL); + return code; + } + #endif + /* Create symlink with mode 0755. */ tattr.mask = CM_ATTRMASK_UNIXMODEBITS; tattr.unixModeBits = 0755; *************** *** 1618,1623 **** --- 1653,1668 ---- cp = ioctlp->inDatap; + #ifdef AFS_FREELANCE_CLIENT + if (cm_freelanceEnabled && dscp == cm_rootSCachep) { + /* we are adding the mount point to the root dir., so call + * the freelance code to do the add. */ + osi_Log0(afsd_logp,"IoctlDeletelink from Freelance root dir"); + code = cm_FreelanceRemoveSymlink(cp); + return code; + } + #endif + code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp); /* if something went wrong, bail out now */ Index: openafs/src/WINNT/afsd/cm_scache.c diff -c openafs/src/WINNT/afsd/cm_scache.c:1.14.2.1 openafs/src/WINNT/afsd/cm_scache.c:1.14.2.2 *** openafs/src/WINNT/afsd/cm_scache.c:1.14.2.1 Tue Aug 17 00:28:39 2004 --- openafs/src/WINNT/afsd/cm_scache.c Fri Nov 5 14:21:44 2004 *************** *** 52,61 **** /* must be called with cm_scacheLock write-locked! */ void cm_AdjustLRU(cm_scache_t *scp) { ! if (scp == cm_scacheLRULastp) ! cm_scacheLRULastp = (cm_scache_t *) osi_QPrev(&scp->q); ! osi_QRemove((osi_queue_t **) &cm_scacheLRUFirstp, &scp->q); ! osi_QAdd((osi_queue_t **) &cm_scacheLRUFirstp, &scp->q); if (!cm_scacheLRULastp) cm_scacheLRULastp = scp; } --- 52,61 ---- /* must be called with cm_scacheLock write-locked! */ void cm_AdjustLRU(cm_scache_t *scp) { ! if (scp == cm_scacheLRULastp) ! cm_scacheLRULastp = (cm_scache_t *) osi_QPrev(&scp->q); ! osi_QRemove((osi_queue_t **) &cm_scacheLRUFirstp, &scp->q); ! osi_QAdd((osi_queue_t **) &cm_scacheLRUFirstp, &scp->q); if (!cm_scacheLRULastp) cm_scacheLRULastp = scp; } *************** *** 65,182 **** */ cm_scache_t *cm_GetNewSCache(void) { ! cm_scache_t *scp; ! int i; ! cm_scache_t **lscpp; ! cm_scache_t *tscp; ! ! if (cm_currentSCaches >= cm_maxSCaches) { ! for (scp = cm_scacheLRULastp; ! scp; ! scp = (cm_scache_t *) osi_QPrev(&scp->q)) { if (scp->refCount == 0) break; ! } ! if (scp) { ! /* we found an entry, so return it */ ! if (scp->flags & CM_SCACHEFLAG_INHASH) { ! /* hash it out first */ ! i = CM_SCACHE_HASH(&scp->fid); ! lscpp = &cm_hashTablep[i]; ! for (tscp = *lscpp; ! tscp; ! lscpp = &tscp->nextp, tscp = *lscpp) { if (tscp == scp) break; ! } ! osi_assertx(tscp, "afsd: scache hash screwup"); ! *lscpp = scp->nextp; ! scp->flags &= ~CM_SCACHEFLAG_INHASH; ! } ! ! /* look for things that shouldn't still be set */ ! osi_assert(scp->bufWritesp == NULL); ! osi_assert(scp->bufReadsp == NULL); ! ! /* invalidate so next merge works fine; ! * also initialize some flags */ ! scp->flags &= ~(CM_SCACHEFLAG_STATD ! | CM_SCACHEFLAG_RO ! | CM_SCACHEFLAG_PURERO ! | CM_SCACHEFLAG_OVERQUOTA ! | CM_SCACHEFLAG_OUTOFSPACE); ! scp->serverModTime = 0; ! scp->dataVersion = 0; ! scp->bulkStatProgress = hzero; ! /* discard callback */ if (scp->cbServerp) { cm_PutServer(scp->cbServerp); ! scp->cbServerp = NULL; } ! scp->cbExpires = 0; ! /* remove from dnlc */ ! cm_dnlcPurgedp(scp); ! cm_dnlcPurgevp(scp); ! ! /* discard cached status; if non-zero, Close ! * tried to store this to server but failed */ ! scp->mask = 0; ! ! /* drop held volume ref */ ! if (scp->volp) { ! cm_PutVolume(scp->volp); ! scp->volp = NULL; ! } ! ! /* discard symlink info */ ! if (scp->mountPointStringp) { ! free(scp->mountPointStringp); ! scp->mountPointStringp = NULL; ! } ! if (scp->mountRootFidp) { ! free(scp->mountRootFidp); ! scp->mountRootFidp = NULL; ! } ! if (scp->dotdotFidp) { ! free(scp->dotdotFidp); ! scp->dotdotFidp = NULL; ! } ! ! /* not locked, but there can be no references to this guy ! * while we hold the global refcount lock. ! */ ! cm_FreeAllACLEnts(scp); ! ! /* now remove from the LRU queue and put it back at the ! * head of the LRU queue. ! */ ! cm_AdjustLRU(scp); ! ! /* and we're done */ ! return scp; ! } ! } ! /* if we get here, we should allocate a new scache entry. We either are below ! * quota or we have a leak and need to allocate a new one to avoid panicing. ! */ ! scp = malloc(sizeof(*scp)); ! memset(scp, 0, sizeof(*scp)); ! lock_InitializeMutex(&scp->mx, "cm_scache_t mutex"); ! lock_InitializeRWLock(&scp->bufCreateLock, "cm_scache_t bufCreateLock"); ! ! /* and put it in the LRU queue */ ! osi_QAdd((osi_queue_t **) &cm_scacheLRUFirstp, &scp->q); if (!cm_scacheLRULastp) cm_scacheLRULastp = scp; ! cm_currentSCaches++; ! cm_dnlcPurgedp(scp); /* make doubly sure that this is not in dnlc */ ! cm_dnlcPurgevp(scp); ! return scp; ! } /* like strcmp, only for fids */ int cm_FidCmp(cm_fid_t *ap, cm_fid_t *bp) --- 65,182 ---- */ cm_scache_t *cm_GetNewSCache(void) { ! cm_scache_t *scp; ! int i; ! cm_scache_t **lscpp; ! cm_scache_t *tscp; ! ! if (cm_currentSCaches >= cm_maxSCaches) { ! for (scp = cm_scacheLRULastp; ! scp; ! scp = (cm_scache_t *) osi_QPrev(&scp->q)) { if (scp->refCount == 0) break; ! } ! if (scp) { ! /* we found an entry, so return it */ ! if (scp->flags & CM_SCACHEFLAG_INHASH) { ! /* hash it out first */ ! i = CM_SCACHE_HASH(&scp->fid); ! lscpp = &cm_hashTablep[i]; ! for (tscp = *lscpp; ! tscp; ! lscpp = &tscp->nextp, tscp = *lscpp) { if (tscp == scp) break; ! } ! osi_assertx(tscp, "afsd: scache hash screwup"); ! *lscpp = scp->nextp; ! scp->flags &= ~CM_SCACHEFLAG_INHASH; ! } ! ! /* look for things that shouldn't still be set */ ! osi_assert(scp->bufWritesp == NULL); ! osi_assert(scp->bufReadsp == NULL); ! ! /* invalidate so next merge works fine; ! * also initialize some flags */ ! scp->flags &= ~(CM_SCACHEFLAG_STATD ! | CM_SCACHEFLAG_RO ! | CM_SCACHEFLAG_PURERO ! | CM_SCACHEFLAG_OVERQUOTA ! | CM_SCACHEFLAG_OUTOFSPACE); ! scp->serverModTime = 0; ! scp->dataVersion = 0; ! scp->bulkStatProgress = hzero; ! /* discard callback */ if (scp->cbServerp) { cm_PutServer(scp->cbServerp); ! scp->cbServerp = NULL; } ! scp->cbExpires = 0; ! /* remove from dnlc */ ! cm_dnlcPurgedp(scp); ! cm_dnlcPurgevp(scp); ! ! /* discard cached status; if non-zero, Close ! * tried to store this to server but failed */ ! scp->mask = 0; ! ! /* drop held volume ref */ ! if (scp->volp) { ! cm_PutVolume(scp->volp); ! scp->volp = NULL; ! } ! ! /* discard symlink info */ ! if (scp->mountPointStringp) { ! free(scp->mountPointStringp); ! scp->mountPointStringp = NULL; ! } ! if (scp->mountRootFidp) { ! free(scp->mountRootFidp); ! scp->mountRootFidp = NULL; ! } ! if (scp->dotdotFidp) { ! free(scp->dotdotFidp); ! scp->dotdotFidp = NULL; ! } ! ! /* not locked, but there can be no references to this guy ! * while we hold the global refcount lock. ! */ ! cm_FreeAllACLEnts(scp); ! ! /* now remove from the LRU queue and put it back at the ! * head of the LRU queue. ! */ ! cm_AdjustLRU(scp); ! ! /* and we're done */ ! return scp; ! } ! } ! /* if we get here, we should allocate a new scache entry. We either are below ! * quota or we have a leak and need to allocate a new one to avoid panicing. ! */ ! scp = malloc(sizeof(*scp)); ! memset(scp, 0, sizeof(*scp)); ! lock_InitializeMutex(&scp->mx, "cm_scache_t mutex"); ! lock_InitializeRWLock(&scp->bufCreateLock, "cm_scache_t bufCreateLock"); ! ! /* and put it in the LRU queue */ ! osi_QAdd((osi_queue_t **) &cm_scacheLRUFirstp, &scp->q); if (!cm_scacheLRULastp) cm_scacheLRULastp = scp; ! cm_currentSCaches++; ! cm_dnlcPurgedp(scp); /* make doubly sure that this is not in dnlc */ ! cm_dnlcPurgevp(scp); ! return scp; ! } /* like strcmp, only for fids */ int cm_FidCmp(cm_fid_t *ap, cm_fid_t *bp) *************** *** 189,266 **** return 1; if (ap->cell != bp->cell) return 1; ! return 0; } void cm_fakeSCacheInit() { ! memset(&cm_fakeSCache, 0, sizeof(cm_fakeSCache)); ! lock_InitializeMutex(&cm_fakeSCache.mx, "cm_scache_t mutex"); ! cm_fakeSCache.cbServerp = (struct cm_server *)(-1); ! /* can leave clientModTime at 0 */ ! cm_fakeSCache.fileType = CM_SCACHETYPE_FILE; ! cm_fakeSCache.unixModeBits = 0777; ! cm_fakeSCache.length.LowPart = 1000; ! cm_fakeSCache.linkCount = 1; ! } void cm_InitSCache(long maxSCaches) { ! static osi_once_t once; ! if (osi_Once(&once)) { ! lock_InitializeRWLock(&cm_scacheLock, "cm_scacheLock"); ! cm_hashTableSize = maxSCaches / 2; ! cm_hashTablep = malloc(sizeof(cm_scache_t *) * cm_hashTableSize); ! memset(cm_hashTablep, 0, sizeof(cm_scache_t *) * cm_hashTableSize); ! cm_allFileLocks = NULL; ! cm_currentSCaches = 0; ! cm_maxSCaches = maxSCaches; ! cm_fakeSCacheInit(); ! cm_dnlcInit(); ! osi_EndOnce(&once); ! } } /* version that doesn't bother creating the entry if we don't find it */ cm_scache_t *cm_FindSCache(cm_fid_t *fidp) { ! long hash; ! cm_scache_t *scp; ! ! hash = CM_SCACHE_HASH(fidp); ! osi_assert(fidp->cell != 0); ! lock_ObtainWrite(&cm_scacheLock); ! for(scp=cm_hashTablep[hash]; scp; scp=scp->nextp) { ! if (cm_FidCmp(fidp, &scp->fid) == 0) { ! scp->refCount++; ! cm_AdjustLRU(scp); ! lock_ReleaseWrite(&cm_scacheLock); ! return scp; ! } } ! lock_ReleaseWrite(&cm_scacheLock); ! return NULL; } long cm_GetSCache(cm_fid_t *fidp, cm_scache_t **outScpp, cm_user_t *userp, ! cm_req_t *reqp) { ! long hash; cm_scache_t *scp; long code; cm_volume_t *volp = 0; cm_cell_t *cellp; char* mp = 0; ! int special; // yj: boolean variable to test if file is on root.afs ! int isRoot; extern cm_fid_t cm_rootFid; hash = CM_SCACHE_HASH(fidp); ! osi_assert(fidp->cell != 0); if (fidp->cell== cm_rootFid.cell && fidp->volume==cm_rootFid.volume && --- 189,266 ---- return 1; if (ap->cell != bp->cell) return 1; ! return 0; } void cm_fakeSCacheInit() { ! memset(&cm_fakeSCache, 0, sizeof(cm_fakeSCache)); ! lock_InitializeMutex(&cm_fakeSCache.mx, "cm_scache_t mutex"); ! cm_fakeSCache.cbServerp = (struct cm_server *)(-1); ! /* can leave clientModTime at 0 */ ! cm_fakeSCache.fileType = CM_SCACHETYPE_FILE; ! cm_fakeSCache.unixModeBits = 0777; ! cm_fakeSCache.length.LowPart = 1000; ! cm_fakeSCache.linkCount = 1; ! } void cm_InitSCache(long maxSCaches) { ! static osi_once_t once; ! if (osi_Once(&once)) { ! lock_InitializeRWLock(&cm_scacheLock, "cm_scacheLock"); ! cm_hashTableSize = maxSCaches / 2; ! cm_hashTablep = malloc(sizeof(cm_scache_t *) * cm_hashTableSize); ! memset(cm_hashTablep, 0, sizeof(cm_scache_t *) * cm_hashTableSize); ! cm_allFileLocks = NULL; ! cm_currentSCaches = 0; ! cm_maxSCaches = maxSCaches; ! cm_fakeSCacheInit(); ! cm_dnlcInit(); ! osi_EndOnce(&once); ! } } /* version that doesn't bother creating the entry if we don't find it */ cm_scache_t *cm_FindSCache(cm_fid_t *fidp) { ! long hash; ! cm_scache_t *scp; ! ! hash = CM_SCACHE_HASH(fidp); ! osi_assert(fidp->cell != 0); ! lock_ObtainWrite(&cm_scacheLock); ! for(scp=cm_hashTablep[hash]; scp; scp=scp->nextp) { ! if (cm_FidCmp(fidp, &scp->fid) == 0) { ! scp->refCount++; ! cm_AdjustLRU(scp); ! lock_ReleaseWrite(&cm_scacheLock); ! return scp; } ! } ! lock_ReleaseWrite(&cm_scacheLock); ! return NULL; } long cm_GetSCache(cm_fid_t *fidp, cm_scache_t **outScpp, cm_user_t *userp, ! cm_req_t *reqp) { ! long hash; cm_scache_t *scp; long code; cm_volume_t *volp = 0; cm_cell_t *cellp; char* mp = 0; ! int special; // yj: boolean variable to test if file is on root.afs ! int isRoot; extern cm_fid_t cm_rootFid; hash = CM_SCACHE_HASH(fidp); ! osi_assert(fidp->cell != 0); if (fidp->cell== cm_rootFid.cell && fidp->volume==cm_rootFid.volume && *************** *** 269,360 **** osi_Log0(afsd_logp,"cm_getSCache called with root cell/volume and vnode=0 and unique=0"); } ! // yj: check if we have the scp, if so, we don't need ! // to do anything else lock_ObtainWrite(&cm_scacheLock); ! for(scp=cm_hashTablep[hash]; scp; scp=scp->nextp) { ! if (cm_FidCmp(fidp, &scp->fid) == 0) { ! scp->refCount++; *outScpp = scp; cm_AdjustLRU(scp); lock_ReleaseWrite(&cm_scacheLock); ! return 0; } } ! // yj: when we get here, it means we don't have an scp ! // so we need to either load it or fake it, depending ! // on whether the file is "special", see below. ! ! // yj: if we're trying to get an scp for a file that's ! // on root.afs of homecell, we want to handle it specially ! // because we have to fill in the status stuff 'coz we ! // don't want trybulkstat to fill it in for us #ifdef AFS_FREELANCE_CLIENT ! special = (fidp->cell==AFS_FAKE_ROOT_CELL_ID && fidp->volume==AFS_FAKE_ROOT_VOL_ID && ! !(fidp->vnode==0x1 && fidp->unique==0x1)); ! isRoot = (fidp->cell==AFS_FAKE_ROOT_CELL_ID && fidp->volume==AFS_FAKE_ROOT_VOL_ID && ! fidp->vnode==0x1 && fidp->unique==0x1); ! if (cm_freelanceEnabled && isRoot) { ! osi_Log0(afsd_logp,"cm_getSCache Freelance and isRoot"); ! /* freelance: if we are trying to get the root scp for the first * time, we will just put in a place holder entry. */ ! volp = NULL; ! } ! if (cm_freelanceEnabled && special) { ! osi_Log0(afsd_logp,"cm_getSCache Freelance and special"); if (fidp->vnode > 1) { lock_ObtainMutex(&cm_Freelance_Lock); ! mp =(cm_localMountPoints+fidp->vnode-2)->mountPointStringp; ! lock_ReleaseMutex(&cm_Freelance_Lock); } else { mp = ""; } ! scp = cm_GetNewSCache(); ! scp->fid = *fidp; ! scp->volp = cm_rootSCachep->volp; ! if (scp->dotdotFidp == (cm_fid_t *) NULL) ! scp->dotdotFidp = (cm_fid_t *) malloc (sizeof(cm_fid_t)); ! scp->dotdotFidp->cell=AFS_FAKE_ROOT_CELL_ID; ! scp->dotdotFidp->volume=AFS_FAKE_ROOT_VOL_ID; ! scp->dotdotFidp->unique=1; ! scp->dotdotFidp->vnode=1; ! scp->flags |= (CM_SCACHEFLAG_PURERO | CM_SCACHEFLAG_RO); ! scp->nextp=cm_hashTablep[hash]; ! cm_hashTablep[hash]=scp; ! scp->flags |= CM_SCACHEFLAG_INHASH; ! scp->refCount = 1; ! scp->fileType = CM_SCACHETYPE_MOUNTPOINT; ! ! lock_ObtainMutex(&cm_Freelance_Lock); ! scp->length.LowPart = strlen(mp)+4; ! scp->mountPointStringp=malloc(strlen(mp)+1); ! strcpy(scp->mountPointStringp,mp); ! lock_ReleaseMutex(&cm_Freelance_Lock); ! ! scp->owner=0x0; ! scp->unixModeBits=0x1ff; ! scp->clientModTime=FakeFreelanceModTime; ! scp->serverModTime=FakeFreelanceModTime; ! scp->parentUnique = 0x1; ! scp->parentVnode=0x1; ! scp->group=0; ! scp->dataVersion=0x8; ! *outScpp = scp; ! lock_ReleaseWrite(&cm_scacheLock); ! /*afsi_log(" getscache done");*/ ! return 0; ! } ! // end of yj code #endif /* AFS_FREELANCE_CLIENT */ /* otherwise, we need to find the volume */ ! if (!cm_freelanceEnabled || !isRoot) { lock_ReleaseWrite(&cm_scacheLock); /* for perf. reasons */ cellp = cm_FindCellByID(fidp->cell); if (!cellp) --- 269,360 ---- osi_Log0(afsd_logp,"cm_getSCache called with root cell/volume and vnode=0 and unique=0"); } ! // yj: check if we have the scp, if so, we don't need ! // to do anything else lock_ObtainWrite(&cm_scacheLock); ! for(scp=cm_hashTablep[hash]; scp; scp=scp->nextp) { ! if (cm_FidCmp(fidp, &scp->fid) == 0) { ! scp->refCount++; *outScpp = scp; cm_AdjustLRU(scp); lock_ReleaseWrite(&cm_scacheLock); ! return 0; } } ! // yj: when we get here, it means we don't have an scp ! // so we need to either load it or fake it, depending ! // on whether the file is "special", see below. ! ! // yj: if we're trying to get an scp for a file that's ! // on root.afs of homecell, we want to handle it specially ! // because we have to fill in the status stuff 'coz we ! // don't want trybulkstat to fill it in for us #ifdef AFS_FREELANCE_CLIENT ! special = (fidp->cell==AFS_FAKE_ROOT_CELL_ID && fidp->volume==AFS_FAKE_ROOT_VOL_ID && ! !(fidp->vnode==0x1 && fidp->unique==0x1)); ! isRoot = (fidp->cell==AFS_FAKE_ROOT_CELL_ID && fidp->volume==AFS_FAKE_ROOT_VOL_ID && ! fidp->vnode==0x1 && fidp->unique==0x1); ! if (cm_freelanceEnabled && isRoot) { ! osi_Log0(afsd_logp,"cm_getSCache Freelance and isRoot"); ! /* freelance: if we are trying to get the root scp for the first * time, we will just put in a place holder entry. */ ! volp = NULL; ! } ! if (cm_freelanceEnabled && special) { ! osi_Log0(afsd_logp,"cm_getSCache Freelance and special"); if (fidp->vnode > 1) { lock_ObtainMutex(&cm_Freelance_Lock); ! mp =(cm_localMountPoints+fidp->vnode-2)->mountPointStringp; ! lock_ReleaseMutex(&cm_Freelance_Lock); } else { mp = ""; } ! scp = cm_GetNewSCache(); ! scp->fid = *fidp; ! scp->volp = cm_rootSCachep->volp; ! if (scp->dotdotFidp == (cm_fid_t *) NULL) ! scp->dotdotFidp = (cm_fid_t *) malloc (sizeof(cm_fid_t)); ! scp->dotdotFidp->cell=AFS_FAKE_ROOT_CELL_ID; ! scp->dotdotFidp->volume=AFS_FAKE_ROOT_VOL_ID; ! scp->dotdotFidp->unique=1; ! scp->dotdotFidp->vnode=1; ! scp->flags |= (CM_SCACHEFLAG_PURERO | CM_SCACHEFLAG_RO); ! scp->nextp=cm_hashTablep[hash]; ! cm_hashTablep[hash]=scp; ! scp->flags |= CM_SCACHEFLAG_INHASH; ! scp->refCount = 1; ! scp->fileType = (cm_localMountPoints+fidp->vnode-2)->fileType; ! ! lock_ObtainMutex(&cm_Freelance_Lock); ! scp->length.LowPart = strlen(mp)+4; ! scp->mountPointStringp=malloc(strlen(mp)+1); ! strcpy(scp->mountPointStringp,mp); ! lock_ReleaseMutex(&cm_Freelance_Lock); ! ! scp->owner=0x0; ! scp->unixModeBits=0x1ff; ! scp->clientModTime=FakeFreelanceModTime; ! scp->serverModTime=FakeFreelanceModTime; ! scp->parentUnique = 0x1; ! scp->parentVnode=0x1; ! scp->group=0; ! scp->dataVersion=0x8; ! *outScpp = scp; ! lock_ReleaseWrite(&cm_scacheLock); ! /*afsi_log(" getscache done");*/ ! return 0; ! } ! // end of yj code #endif /* AFS_FREELANCE_CLIENT */ /* otherwise, we need to find the volume */ ! if (!cm_freelanceEnabled || !isRoot) { lock_ReleaseWrite(&cm_scacheLock); /* for perf. reasons */ cellp = cm_FindCellByID(fidp->cell); if (!cellp) *************** *** 364,419 **** if (code) return code; lock_ObtainWrite(&cm_scacheLock); ! } ! /* otherwise, we have the volume, now reverify that the scp doesn't ! * exist, and proceed. ! */ ! for(scp=cm_hashTablep[hash]; scp; scp=scp->nextp) { ! if (cm_FidCmp(fidp, &scp->fid) == 0) { ! scp->refCount++; cm_AdjustLRU(scp); lock_ReleaseWrite(&cm_scacheLock); if (volp) ! cm_PutVolume(volp); *outScpp = scp; ! return 0; } } /* now, if we don't have the fid, recycle something */ ! scp = cm_GetNewSCache(); ! osi_assert(!(scp->flags & CM_SCACHEFLAG_INHASH)); ! scp->fid = *fidp; ! scp->volp = volp; /* a held reference */ ! ! if (!cm_freelanceEnabled || !isRoot) { ! /* if this scache entry represents a volume root then we need ! * to copy the dotdotFipd from the volume structure where the ! * "master" copy is stored (defect 11489) ! */ ! if(scp->fid.vnode == 1 && scp->fid.unique == 1 && volp->dotdotFidp) { if (scp->dotdotFidp == (cm_fid_t *) NULL) ! scp->dotdotFidp = (cm_fid_t *) malloc(sizeof(cm_fid_t)); *(scp->dotdotFidp) = *volp->dotdotFidp; ! } ! if (volp->roID == fidp->volume) scp->flags |= (CM_SCACHEFLAG_PURERO | CM_SCACHEFLAG_RO); ! else if (volp->bkID == fidp->volume) scp->flags |= CM_SCACHEFLAG_RO; ! } ! scp->nextp = cm_hashTablep[hash]; ! cm_hashTablep[hash] = scp; scp->flags |= CM_SCACHEFLAG_INHASH; ! scp->refCount = 1; ! /* XXX - The following fields in the cm_scache are ! * uninitialized: ! * fileType ! * parentVnode ! * parentUnique ! */ lock_ReleaseWrite(&cm_scacheLock); /* now we have a held scache entry; just return it */ --- 364,419 ---- if (code) return code; lock_ObtainWrite(&cm_scacheLock); ! } ! /* otherwise, we have the volume, now reverify that the scp doesn't ! * exist, and proceed. ! */ ! for(scp=cm_hashTablep[hash]; scp; scp=scp->nextp) { ! if (cm_FidCmp(fidp, &scp->fid) == 0) { ! scp->refCount++; cm_AdjustLRU(scp); lock_ReleaseWrite(&cm_scacheLock); if (volp) ! cm_PutVolume(volp); *outScpp = scp; ! return 0; } } /* now, if we don't have the fid, recycle something */ ! scp = cm_GetNewSCache(); ! osi_assert(!(scp->flags & CM_SCACHEFLAG_INHASH)); ! scp->fid = *fidp; ! scp->volp = volp; /* a held reference */ ! ! if (!cm_freelanceEnabled || !isRoot) { ! /* if this scache entry represents a volume root then we need ! * to copy the dotdotFipd from the volume structure where the ! * "master" copy is stored (defect 11489) ! */ ! if (scp->fid.vnode == 1 && scp->fid.unique == 1 && volp->dotdotFidp) { if (scp->dotdotFidp == (cm_fid_t *) NULL) ! scp->dotdotFidp = (cm_fid_t *) malloc(sizeof(cm_fid_t)); *(scp->dotdotFidp) = *volp->dotdotFidp; ! } ! if (volp->roID == fidp->volume) scp->flags |= (CM_SCACHEFLAG_PURERO | CM_SCACHEFLAG_RO); ! else if (volp->bkID == fidp->volume) scp->flags |= CM_SCACHEFLAG_RO; ! } ! scp->nextp = cm_hashTablep[hash]; ! cm_hashTablep[hash] = scp; scp->flags |= CM_SCACHEFLAG_INHASH; ! scp->refCount = 1; ! /* XXX - The following fields in the cm_scache are ! * uninitialized: ! * fileType ! * parentVnode ! * parentUnique ! */ lock_ReleaseWrite(&cm_scacheLock); /* now we have a held scache entry; just return it */ *************** *** 477,754 **** * CM_SCACHESYNC_STOREDATA_EXCL and CM_SCACHEFLAG_DATASTORING. */ long cm_SyncOp(cm_scache_t *scp, cm_buf_t *bufp, cm_user_t *up, cm_req_t *reqp, ! long rights, long flags) { ! osi_queueData_t *qdp; ! long code; ! cm_buf_t *tbufp; ! long outRights; ! int bufLocked; ! ! /* lookup this first */ ! bufLocked = flags & CM_SCACHESYNC_BUFLOCKED; ! ! /* some minor assertions */ ! if (flags & (CM_SCACHESYNC_STOREDATA | CM_SCACHESYNC_FETCHDATA ! | CM_SCACHESYNC_READ | CM_SCACHESYNC_WRITE ! | CM_SCACHESYNC_SETSIZE)) { ! if (bufp) { ! osi_assert(bufp->refCount > 0); ! /* ! osi_assert(cm_FidCmp(&bufp->fid, &scp->fid) == 0); ! */ ! } ! } ! else osi_assert(bufp == NULL); ! ! /* Do the access check. Now we don't really do the access check ! * atomically, since the caller doesn't expect the parent dir to be ! * returned locked, and that is what we'd have to do to prevent a ! * callback breaking message on the parent due to a setacl call from ! * being processed while we're running. So, instead, we check things ! * here, and if things look fine with the access, we proceed to finish ! * the rest of this check. Sort of a hack, but probably good enough. ! */ ! ! while (1) { ! if (flags & CM_SCACHESYNC_FETCHSTATUS) { ! /* if we're bringing in a new status block, ensure that ! * we aren't already doing so, and that no one is ! * changing the status concurrently, either. We need ! * to do this, even if the status is of a different ! * type, since we don't have the ability to figure out, ! * in the AFS 3 protocols, which status-changing ! * operation ran first, or even which order a read and ! * a write occurred in. ! */ ! if (scp->flags & (CM_SCACHEFLAG_FETCHING | CM_SCACHEFLAG_STORING ! | CM_SCACHEFLAG_SIZESTORING | CM_SCACHEFLAG_GETCALLBACK)) ! goto sleep; ! } ! if (flags & (CM_SCACHESYNC_STORESIZE | CM_SCACHESYNC_STORESTATUS ! | CM_SCACHESYNC_SETSIZE | CM_SCACHESYNC_GETCALLBACK)) { ! /* if we're going to make an RPC to change the status, make sure ! * that no one is bringing in or sending out the status. ! */ ! if (scp->flags & (CM_SCACHEFLAG_FETCHING | CM_SCACHEFLAG_STORING ! | CM_SCACHEFLAG_SIZESTORING | CM_SCACHEFLAG_GETCALLBACK)) ! goto sleep; ! if (scp->bufReadsp || scp->bufWritesp) goto sleep; ! } ! if (flags & CM_SCACHESYNC_FETCHDATA) { ! /* if we're bringing in a new chunk of data, make sure that ! * nothing is happening to that chunk, and that we aren't ! * changing the basic file status info, either. ! */ ! if (scp->flags & (CM_SCACHEFLAG_FETCHING | CM_SCACHEFLAG_STORING ! | CM_SCACHEFLAG_SIZESTORING | CM_SCACHEFLAG_GETCALLBACK)) ! goto sleep; ! if (bufp && (bufp->cmFlags & (CM_BUF_CMFETCHING | CM_BUF_CMSTORING))) ! goto sleep; ! } ! if (flags & CM_SCACHESYNC_STOREDATA) { ! /* same as fetch data */ ! if (scp->flags & (CM_SCACHEFLAG_FETCHING | CM_SCACHEFLAG_STORING ! | CM_SCACHEFLAG_SIZESTORING | CM_SCACHEFLAG_GETCALLBACK)) ! goto sleep; ! if (bufp && (bufp->cmFlags & (CM_BUF_CMFETCHING | CM_BUF_CMSTORING))) ! goto sleep; ! } ! if (flags & CM_SCACHESYNC_STOREDATA_EXCL) { ! /* Don't allow concurrent StoreData RPC's */ ! if (scp->flags & CM_SCACHEFLAG_DATASTORING) ! goto sleep; ! } ! ! if (flags & CM_SCACHESYNC_ASYNCSTORE) { ! /* Don't allow more than one BKG store request */ ! if (scp->flags & CM_SCACHEFLAG_ASYNCSTORING) ! goto sleep; ! } ! ! if (flags & CM_SCACHESYNC_LOCK) { ! /* Don't allow concurrent fiddling with lock lists */ ! if (scp->flags & CM_SCACHEFLAG_LOCKING) ! goto sleep; ! } ! ! /* now the operations that don't correspond to making RPCs */ ! if (flags & CM_SCACHESYNC_GETSTATUS) { ! /* we can use the status that's here, if we're not ! * bringing in new status. ! */ ! if (scp->flags & (CM_SCACHEFLAG_FETCHING)) ! goto sleep; ! } ! if (flags & CM_SCACHESYNC_SETSTATUS) { ! /* we can make a change to the local status, as long as ! * the status isn't changing now. ! * ! * If we're fetching or storing a chunk of data, we can ! * change the status locally, since the fetch/store ! * operations don't change any of the data that we're ! * changing here. ! */ ! if (scp->flags & (CM_SCACHEFLAG_FETCHING | CM_SCACHEFLAG_STORING ! | CM_SCACHEFLAG_SIZESTORING)) ! goto sleep; ! } ! if (flags & CM_SCACHESYNC_READ) { ! /* we're going to read the data, make sure that the ! * status is available, and that the data is here. It ! * is OK to read while storing the data back. ! */ ! if (scp->flags & CM_SCACHEFLAG_FETCHING) ! goto sleep; ! if (bufp && ((bufp->cmFlags ! & (CM_BUF_CMFETCHING ! | CM_BUF_CMFULLYFETCHED)) ! == CM_BUF_CMFETCHING)) ! goto sleep; ! } ! if (flags & CM_SCACHESYNC_WRITE) { ! /* don't write unless the status is stable and the chunk ! * is stable. ! */ ! if (scp->flags & (CM_SCACHEFLAG_FETCHING | CM_SCACHEFLAG_STORING ! | CM_SCACHEFLAG_SIZESTORING)) ! goto sleep; ! if (bufp && (bufp->cmFlags & (CM_BUF_CMFETCHING | CM_BUF_CMSTORING))) ! goto sleep; ! } ! // yj: modified this so that callback only checked if we're ! // not checking something on /afs /* fix the conditional to match the one in cm_HaveCallback */ ! if ( (flags & CM_SCACHESYNC_NEEDCALLBACK) #ifdef AFS_FREELANCE_CLIENT && (!cm_freelanceEnabled || !(scp->fid.vnode==0x1 && scp->fid.unique==0x1) || scp->fid.cell!=AFS_FAKE_ROOT_CELL_ID || scp->fid.volume!=AFS_FAKE_ROOT_VOL_ID || ! cm_fakeDirCallback < 2) #endif /* AFS_FREELANCE_CLIENT */ ! ) { ! if (!cm_HaveCallback(scp)) { ! osi_Log1(afsd_logp, "CM SyncOp getting callback on scp %x", ! (long) scp); ! if (bufLocked) lock_ReleaseMutex(&bufp->mx); ! code = cm_GetCallback(scp, up, reqp, 0); ! if (bufLocked) { ! lock_ReleaseMutex(&scp->mx); ! lock_ObtainMutex(&bufp->mx); ! lock_ObtainMutex(&scp->mx); ! } ! if (code) return code; ! continue; ! } } ! ! if (rights) { ! /* can't check access rights without a callback */ ! osi_assert(flags & CM_SCACHESYNC_NEEDCALLBACK); ! ! if ((rights & PRSFS_WRITE) && (scp->flags & CM_SCACHEFLAG_RO)) ! return CM_ERROR_READONLY; ! ! if (cm_HaveAccessRights(scp, up, rights, &outRights)) { ! if (~outRights & rights) return CM_ERROR_NOACCESS; ! } ! else { ! /* we don't know the required access rights */ ! if (bufLocked) lock_ReleaseMutex(&bufp->mx); ! code = cm_GetAccessRights(scp, up, reqp); ! if (code) return code; ! if (bufLocked) { ! lock_ReleaseMutex(&scp->mx); ! lock_ObtainMutex(&bufp->mx); ! lock_ObtainMutex(&scp->mx); ! } ! continue; ! } } ! /* if we get here, we're happy */ ! break; ! sleep: ! /* first check if we're not supposed to wait: fail ! * in this case, returning with everything still locked. ! */ ! if (flags & CM_SCACHESYNC_NOWAIT) return CM_ERROR_WOULDBLOCK; ! /* wait here, then try again */ ! osi_Log1(afsd_logp, "CM SyncOp sleeping scp %x", (long) scp); if ( scp->flags & CM_SCACHEFLAG_WAITING ) osi_Log1(afsd_logp, "CM SyncOp CM_SCACHEFLAG_WAITING already set for 0x%x", scp); else osi_Log1(afsd_logp, "CM SyncOp CM_SCACHEFLAG_WAITING set for 0x%x", scp); ! scp->flags |= CM_SCACHEFLAG_WAITING; ! if (bufLocked) lock_ReleaseMutex(&bufp->mx); osi_SleepM((long) &scp->flags, &scp->mx); osi_Log0(afsd_logp, "CM SyncOp woke!"); if (bufLocked) lock_ObtainMutex(&bufp->mx); lock_ObtainMutex(&scp->mx); ! } /* big while loop */ ! /* now, update the recorded state for RPC-type calls */ ! if (flags & CM_SCACHESYNC_FETCHSTATUS) ! scp->flags |= CM_SCACHEFLAG_FETCHING; ! if (flags & CM_SCACHESYNC_STORESTATUS) ! scp->flags |= CM_SCACHEFLAG_STORING; ! if (flags & CM_SCACHESYNC_STORESIZE) ! scp->flags |= CM_SCACHEFLAG_SIZESTORING; ! if (flags & CM_SCACHESYNC_GETCALLBACK) ! scp->flags |= CM_SCACHEFLAG_GETCALLBACK; ! if (flags & CM_SCACHESYNC_STOREDATA_EXCL) ! scp->flags |= CM_SCACHEFLAG_DATASTORING; ! if (flags & CM_SCACHESYNC_ASYNCSTORE) ! scp->flags |= CM_SCACHEFLAG_ASYNCSTORING; ! if (flags & CM_SCACHESYNC_LOCK) ! scp->flags |= CM_SCACHEFLAG_LOCKING; ! /* now update the buffer pointer */ ! if (flags & CM_SCACHESYNC_FETCHDATA) { ! /* ensure that the buffer isn't already in the I/O list */ ! if (bufp) { ! for(qdp = scp->bufReadsp; qdp; qdp = (osi_queueData_t *) osi_QNext(&qdp->q)) { ! tbufp = osi_GetQData(qdp); ! osi_assert(tbufp != bufp); ! } ! } ! ! /* queue a held reference to the buffer in the "reading" I/O list */ ! qdp = osi_QDAlloc(); ! osi_SetQData(qdp, bufp); ! if (bufp) { ! buf_Hold(bufp); ! bufp->cmFlags |= CM_BUF_CMFETCHING; ! } ! osi_QAdd((osi_queue_t **) &scp->bufReadsp, &qdp->q); } ! if (flags & CM_SCACHESYNC_STOREDATA) { ! /* ensure that the buffer isn't already in the I/O list */ ! if (bufp) { ! for(qdp = scp->bufWritesp; qdp; qdp = (osi_queueData_t *) osi_QNext(&qdp->q)) { ! tbufp = osi_GetQData(qdp); ! osi_assert(tbufp != bufp); ! } ! } ! ! /* queue a held reference to the buffer in the "writing" I/O list */ ! qdp = osi_QDAlloc(); ! osi_SetQData(qdp, bufp); ! if (bufp) { ! buf_Hold(bufp); ! bufp->cmFlags |= CM_BUF_CMSTORING; ! } ! osi_QAdd((osi_queue_t **) &scp->bufWritesp, &qdp->q); } ! ! return 0; } /* for those syncops that setup for RPCs. --- 477,754 ---- * CM_SCACHESYNC_STOREDATA_EXCL and CM_SCACHEFLAG_DATASTORING. */ long cm_SyncOp(cm_scache_t *scp, cm_buf_t *bufp, cm_user_t *up, cm_req_t *reqp, ! long rights, long flags) { ! osi_queueData_t *qdp; ! long code; ! cm_buf_t *tbufp; ! long outRights; ! int bufLocked; ! ! /* lookup this first */ ! bufLocked = flags & CM_SCACHESYNC_BUFLOCKED; ! ! /* some minor assertions */ ! if (flags & (CM_SCACHESYNC_STOREDATA | CM_SCACHESYNC_FETCHDATA ! | CM_SCACHESYNC_READ | CM_SCACHESYNC_WRITE ! | CM_SCACHESYNC_SETSIZE)) { ! if (bufp) { ! osi_assert(bufp->refCount > 0); ! /* ! osi_assert(cm_FidCmp(&bufp->fid, &scp->fid) == 0); ! */ ! } ! } ! else osi_assert(bufp == NULL); ! /* Do the access check. Now we don't really do the access check ! * atomically, since the caller doesn't expect the parent dir to be ! * returned locked, and that is what we'd have to do to prevent a ! * callback breaking message on the parent due to a setacl call from ! * being processed while we're running. So, instead, we check things ! * here, and if things look fine with the access, we proceed to finish ! * the rest of this check. Sort of a hack, but probably good enough. ! */ ! ! while (1) { ! if (flags & CM_SCACHESYNC_FETCHSTATUS) { ! /* if we're bringing in a new status block, ensure that ! * we aren't already doing so, and that no one is ! * changing the status concurrently, either. We need ! * to do this, even if the status is of a different ! * type, since we don't have the ability to figure out, ! * in the AFS 3 protocols, which status-changing ! * operation ran first, or even which order a read and ! * a write occurred in. ! */ ! if (scp->flags & (CM_SCACHEFLAG_FETCHING | CM_SCACHEFLAG_STORING ! | CM_SCACHEFLAG_SIZESTORING | CM_SCACHEFLAG_GETCALLBACK)) ! goto sleep; ! } ! if (flags & (CM_SCACHESYNC_STORESIZE | CM_SCACHESYNC_STORESTATUS ! | CM_SCACHESYNC_SETSIZE | CM_SCACHESYNC_GETCALLBACK)) { ! /* if we're going to make an RPC to change the status, make sure ! * that no one is bringing in or sending out the status. ! */ ! if (scp->flags & (CM_SCACHEFLAG_FETCHING | CM_SCACHEFLAG_STORING ! | CM_SCACHEFLAG_SIZESTORING | CM_SCACHEFLAG_GETCALLBACK)) ! goto sleep; ! if (scp->bufReadsp || scp->bufWritesp) goto sleep; ! } ! if (flags & CM_SCACHESYNC_FETCHDATA) { ! /* if we're bringing in a new chunk of data, make sure that ! * nothing is happening to that chunk, and that we aren't ! * changing the basic file status info, either. ! */ ! if (scp->flags & (CM_SCACHEFLAG_FETCHING | CM_SCACHEFLAG_STORING ! | CM_SCACHEFLAG_SIZESTORING | CM_SCACHEFLAG_GETCALLBACK)) ! goto sleep; ! if (bufp && (bufp->cmFlags & (CM_BUF_CMFETCHING | CM_BUF_CMSTORING))) ! goto sleep; ! } ! if (flags & CM_SCACHESYNC_STOREDATA) { ! /* same as fetch data */ ! if (scp->flags & (CM_SCACHEFLAG_FETCHING | CM_SCACHEFLAG_STORING ! | CM_SCACHEFLAG_SIZESTORING | CM_SCACHEFLAG_GETCALLBACK)) ! goto sleep; ! if (bufp && (bufp->cmFlags & (CM_BUF_CMFETCHING | CM_BUF_CMSTORING))) ! goto sleep; ! } ! ! if (flags & CM_SCACHESYNC_STOREDATA_EXCL) { ! /* Don't allow concurrent StoreData RPC's */ ! if (scp->flags & CM_SCACHEFLAG_DATASTORING) ! goto sleep; ! } ! ! if (flags & CM_SCACHESYNC_ASYNCSTORE) { ! /* Don't allow more than one BKG store request */ ! if (scp->flags & CM_SCACHEFLAG_ASYNCSTORING) ! goto sleep; ! } ! ! if (flags & CM_SCACHESYNC_LOCK) { ! /* Don't allow concurrent fiddling with lock lists */ ! if (scp->flags & CM_SCACHEFLAG_LOCKING) ! goto sleep; ! } ! ! /* now the operations that don't correspond to making RPCs */ ! if (flags & CM_SCACHESYNC_GETSTATUS) { ! /* we can use the status that's here, if we're not ! * bringing in new status. ! */ ! if (scp->flags & (CM_SCACHEFLAG_FETCHING)) ! goto sleep; ! } ! if (flags & CM_SCACHESYNC_SETSTATUS) { ! /* we can make a change to the local status, as long as ! * the status isn't changing now. ! * ! * If we're fetching or storing a chunk of data, we can ! * change the status locally, since the fetch/store ! * operations don't change any of the data that we're ! * changing here. ! */ ! if (scp->flags & (CM_SCACHEFLAG_FETCHING | CM_SCACHEFLAG_STORING ! | CM_SCACHEFLAG_SIZESTORING)) ! goto sleep; ! } ! if (flags & CM_SCACHESYNC_READ) { ! /* we're going to read the data, make sure that the ! * status is available, and that the data is here. It ! * is OK to read while storing the data back. ! */ ! if (scp->flags & CM_SCACHEFLAG_FETCHING) ! goto sleep; ! if (bufp && ((bufp->cmFlags ! & (CM_BUF_CMFETCHING ! | CM_BUF_CMFULLYFETCHED)) ! == CM_BUF_CMFETCHING)) ! goto sleep; ! } ! if (flags & CM_SCACHESYNC_WRITE) { ! /* don't write unless the status is stable and the chunk ! * is stable. ! */ ! if (scp->flags & (CM_SCACHEFLAG_FETCHING | CM_SCACHEFLAG_STORING ! | CM_SCACHEFLAG_SIZESTORING)) ! goto sleep; ! if (bufp && (bufp->cmFlags & (CM_BUF_CMFETCHING | CM_BUF_CMSTORING))) ! goto sleep; ! } ! // yj: modified this so that callback only checked if we're ! // not checking something on /afs /* fix the conditional to match the one in cm_HaveCallback */ ! if ( (flags & CM_SCACHESYNC_NEEDCALLBACK) #ifdef AFS_FREELANCE_CLIENT && (!cm_freelanceEnabled || !(scp->fid.vnode==0x1 && scp->fid.unique==0x1) || scp->fid.cell!=AFS_FAKE_ROOT_CELL_ID || scp->fid.volume!=AFS_FAKE_ROOT_VOL_ID || ! cm_fakeDirCallback < 2) #endif /* AFS_FREELANCE_CLIENT */ ! ) { ! if (!cm_HaveCallback(scp)) { ! osi_Log1(afsd_logp, "CM SyncOp getting callback on scp %x", ! (long) scp); ! if (bufLocked) lock_ReleaseMutex(&bufp->mx); ! code = cm_GetCallback(scp, up, reqp, 0); ! if (bufLocked) { ! lock_ReleaseMutex(&scp->mx); ! lock_ObtainMutex(&bufp->mx); ! lock_ObtainMutex(&scp->mx); } ! if (code) return code; ! continue; ! } ! } ! ! if (rights) { ! /* can't check access rights without a callback */ ! osi_assert(flags & CM_SCACHESYNC_NEEDCALLBACK); ! ! if ((rights & PRSFS_WRITE) && (scp->flags & CM_SCACHEFLAG_RO)) ! return CM_ERROR_READONLY; ! ! if (cm_HaveAccessRights(scp, up, rights, &outRights)) { ! if (~outRights & rights) return CM_ERROR_NOACCESS; ! } ! else { ! /* we don't know the required access rights */ ! if (bufLocked) lock_ReleaseMutex(&bufp->mx); ! code = cm_GetAccessRights(scp, up, reqp); ! if (code) return code; ! if (bufLocked) { ! lock_ReleaseMutex(&scp->mx); ! lock_ObtainMutex(&bufp->mx); ! lock_ObtainMutex(&scp->mx); } + continue; + } + } ! /* if we get here, we're happy */ ! break; ! sleep: ! /* first check if we're not supposed to wait: fail ! * in this case, returning with everything still locked. ! */ ! if (flags & CM_SCACHESYNC_NOWAIT) return CM_ERROR_WOULDBLOCK; ! /* wait here, then try again */ ! osi_Log1(afsd_logp, "CM SyncOp sleeping scp %x", (long) scp); if ( scp->flags & CM_SCACHEFLAG_WAITING ) osi_Log1(afsd_logp, "CM SyncOp CM_SCACHEFLAG_WAITING already set for 0x%x", scp); else osi_Log1(afsd_logp, "CM SyncOp CM_SCACHEFLAG_WAITING set for 0x%x", scp); ! scp->flags |= CM_SCACHEFLAG_WAITING; ! if (bufLocked) lock_ReleaseMutex(&bufp->mx); osi_SleepM((long) &scp->flags, &scp->mx); osi_Log0(afsd_logp, "CM SyncOp woke!"); if (bufLocked) lock_ObtainMutex(&bufp->mx); lock_ObtainMutex(&scp->mx); ! } /* big while loop */ ! /* now, update the recorded state for RPC-type calls */ ! if (flags & CM_SCACHESYNC_FETCHSTATUS) ! scp->flags |= CM_SCACHEFLAG_FETCHING; ! if (flags & CM_SCACHESYNC_STORESTATUS) ! scp->flags |= CM_SCACHEFLAG_STORING; ! if (flags & CM_SCACHESYNC_STORESIZE) ! scp->flags |= CM_SCACHEFLAG_SIZESTORING; ! if (flags & CM_SCACHESYNC_GETCALLBACK) ! scp->flags |= CM_SCACHEFLAG_GETCALLBACK; ! if (flags & CM_SCACHESYNC_STOREDATA_EXCL) ! scp->flags |= CM_SCACHEFLAG_DATASTORING; ! if (flags & CM_SCACHESYNC_ASYNCSTORE) ! scp->flags |= CM_SCACHEFLAG_ASYNCSTORING; ! if (flags & CM_SCACHESYNC_LOCK) ! scp->flags |= CM_SCACHEFLAG_LOCKING; ! ! /* now update the buffer pointer */ ! if (flags & CM_SCACHESYNC_FETCHDATA) { ! /* ensure that the buffer isn't already in the I/O list */ ! if (bufp) { ! for(qdp = scp->bufReadsp; qdp; qdp = (osi_queueData_t *) osi_QNext(&qdp->q)) { ! tbufp = osi_GetQData(qdp); ! osi_assert(tbufp != bufp); ! } ! } ! /* queue a held reference to the buffer in the "reading" I/O list */ ! qdp = osi_QDAlloc(); ! osi_SetQData(qdp, bufp); ! if (bufp) { ! buf_Hold(bufp); ! bufp->cmFlags |= CM_BUF_CMFETCHING; } + osi_QAdd((osi_queue_t **) &scp->bufReadsp, &qdp->q); + } ! if (flags & CM_SCACHESYNC_STOREDATA) { ! /* ensure that the buffer isn't already in the I/O list */ ! if (bufp) { ! for(qdp = scp->bufWritesp; qdp; qdp = (osi_queueData_t *) osi_QNext(&qdp->q)) { ! tbufp = osi_GetQData(qdp); ! osi_assert(tbufp != bufp); ! } } ! ! /* queue a held reference to the buffer in the "writing" I/O list */ ! qdp = osi_QDAlloc(); ! osi_SetQData(qdp, bufp); ! if (bufp) { ! buf_Hold(bufp); ! bufp->cmFlags |= CM_BUF_CMSTORING; ! } ! osi_QAdd((osi_queue_t **) &scp->bufWritesp, &qdp->q); ! } ! ! return 0; } /* for those syncops that setup for RPCs. *************** *** 756,822 **** */ void cm_SyncOpDone(cm_scache_t *scp, cm_buf_t *bufp, long flags) { ! osi_queueData_t *qdp; ! cm_buf_t *tbufp; ! ! /* now, update the recorded state for RPC-type calls */ ! if (flags & CM_SCACHESYNC_FETCHSTATUS) ! scp->flags &= ~CM_SCACHEFLAG_FETCHING; ! if (flags & CM_SCACHESYNC_STORESTATUS) ! scp->flags &= ~CM_SCACHEFLAG_STORING; ! if (flags & CM_SCACHESYNC_STORESIZE) ! scp->flags &= ~CM_SCACHEFLAG_SIZESTORING; ! if (flags & CM_SCACHESYNC_GETCALLBACK) ! scp->flags &= ~CM_SCACHEFLAG_GETCALLBACK; ! if (flags & CM_SCACHESYNC_STOREDATA_EXCL) ! scp->flags &= ~CM_SCACHEFLAG_DATASTORING; ! if (flags & CM_SCACHESYNC_ASYNCSTORE) ! scp->flags &= ~CM_SCACHEFLAG_ASYNCSTORING; ! if (flags & CM_SCACHESYNC_LOCK) ! scp->flags &= ~CM_SCACHEFLAG_LOCKING; ! /* now update the buffer pointer */ ! if (flags & CM_SCACHESYNC_FETCHDATA) { ! /* ensure that the buffer isn't already in the I/O list */ ! for(qdp = scp->bufReadsp; qdp; qdp = (osi_queueData_t *) osi_QNext(&qdp->q)) { ! tbufp = osi_GetQData(qdp); ! if (tbufp == bufp) break; ! } ! osi_assert(qdp != NULL); ! osi_assert(osi_GetQData(qdp) == bufp); ! osi_QRemove((osi_queue_t **) &scp->bufReadsp, &qdp->q); ! osi_QDFree(qdp); ! if (bufp) { ! bufp->cmFlags &= ! ~(CM_BUF_CMFETCHING | CM_BUF_CMFULLYFETCHED); ! buf_Release(bufp); ! } } ! /* now update the buffer pointer */ ! if (flags & CM_SCACHESYNC_STOREDATA) { ! /* ensure that the buffer isn't already in the I/O list */ ! for(qdp = scp->bufWritesp; qdp; qdp = (osi_queueData_t *) osi_QNext(&qdp->q)) { ! tbufp = osi_GetQData(qdp); ! if (tbufp == bufp) break; ! } ! osi_assert(qdp != NULL); ! osi_assert(osi_GetQData(qdp) == bufp); ! osi_QRemove((osi_queue_t **) &scp->bufWritesp, &qdp->q); ! osi_QDFree(qdp); ! if (bufp) { ! bufp->cmFlags &= ~CM_BUF_CMSTORING; ! buf_Release(bufp); ! } ! } ! ! /* and wakeup anyone who is waiting */ ! if (scp->flags & CM_SCACHEFLAG_WAITING) { ! osi_Log1(afsd_logp, "CM SyncOp CM_SCACHEFLAG_WAITING reset for 0x%x", scp); ! scp->flags &= ~CM_SCACHEFLAG_WAITING; ! osi_Wakeup((long) &scp->flags); } ! } /* merge in a response from an RPC. The scp must be locked, and the callback * is optional. --- 756,822 ---- */ void cm_SyncOpDone(cm_scache_t *scp, cm_buf_t *bufp, long flags) { ! osi_queueData_t *qdp; ! cm_buf_t *tbufp; ! /* now, update the recorded state for RPC-type calls */ ! if (flags & CM_SCACHESYNC_FETCHSTATUS) ! scp->flags &= ~CM_SCACHEFLAG_FETCHING; ! if (flags & CM_SCACHESYNC_STORESTATUS) ! scp->flags &= ~CM_SCACHEFLAG_STORING; ! if (flags & CM_SCACHESYNC_STORESIZE) ! scp->flags &= ~CM_SCACHEFLAG_SIZESTORING; ! if (flags & CM_SCACHESYNC_GETCALLBACK) ! scp->flags &= ~CM_SCACHEFLAG_GETCALLBACK; ! if (flags & CM_SCACHESYNC_STOREDATA_EXCL) ! scp->flags &= ~CM_SCACHEFLAG_DATASTORING; ! if (flags & CM_SCACHESYNC_ASYNCSTORE) ! scp->flags &= ~CM_SCACHEFLAG_ASYNCSTORING; ! if (flags & CM_SCACHESYNC_LOCK) ! scp->flags &= ~CM_SCACHEFLAG_LOCKING; ! ! /* now update the buffer pointer */ ! if (flags & CM_SCACHESYNC_FETCHDATA) { ! /* ensure that the buffer isn't already in the I/O list */ ! for(qdp = scp->bufReadsp; qdp; qdp = (osi_queueData_t *) osi_QNext(&qdp->q)) { ! tbufp = osi_GetQData(qdp); ! if (tbufp == bufp) break; ! } ! osi_assert(qdp != NULL); ! osi_assert(osi_GetQData(qdp) == bufp); ! osi_QRemove((osi_queue_t **) &scp->bufReadsp, &qdp->q); ! osi_QDFree(qdp); ! if (bufp) { ! bufp->cmFlags &= ! ~(CM_BUF_CMFETCHING | CM_BUF_CMFULLYFETCHED); ! buf_Release(bufp); } + } ! /* now update the buffer pointer */ ! if (flags & CM_SCACHESYNC_STOREDATA) { ! /* ensure that the buffer isn't already in the I/O list */ ! for(qdp = scp->bufWritesp; qdp; qdp = (osi_queueData_t *) osi_QNext(&qdp->q)) { ! tbufp = osi_GetQData(qdp); ! if (tbufp == bufp) break; ! } ! osi_assert(qdp != NULL); ! osi_assert(osi_GetQData(qdp) == bufp); ! osi_QRemove((osi_queue_t **) &scp->bufWritesp, &qdp->q); ! osi_QDFree(qdp); ! if (bufp) { ! bufp->cmFlags &= ~CM_BUF_CMSTORING; ! buf_Release(bufp); } ! } ! ! /* and wakeup anyone who is waiting */ ! if (scp->flags & CM_SCACHEFLAG_WAITING) { ! osi_Log1(afsd_logp, "CM SyncOp CM_SCACHEFLAG_WAITING reset for 0x%x", scp); ! scp->flags &= ~CM_SCACHEFLAG_WAITING; ! osi_Wakeup((long) &scp->flags); ! } ! } /* merge in a response from an RPC. The scp must be locked, and the callback * is optional. *************** *** 832,954 **** * started before that, can cause old info to be merged from the first call. */ void cm_MergeStatus(cm_scache_t *scp, AFSFetchStatus *statusp, AFSVolSync *volp, ! cm_user_t *userp, int flags) { ! // yj: i want to create some fake status for the /afs directory and the ! // entries under that directory #ifdef AFS_FREELANCE_CLIENT ! if (cm_freelanceEnabled && scp == cm_rootSCachep) { ! osi_Log0(afsd_logp,"cm_MergeStatus Freelance cm_rootSCachep"); ! statusp->InterfaceVersion = 0x1; statusp->FileType = CM_SCACHETYPE_DIRECTORY; ! statusp->LinkCount = scp->linkCount; ! statusp->Length = cm_fakeDirSize; ! statusp->DataVersion = cm_fakeDirVersion; ! statusp->Author = 0x1; ! statusp->Owner = 0x0; ! statusp->CallerAccess = 0x9; ! statusp->AnonymousAccess = 0x9; ! statusp->UnixModeBits = 0x1ff; ! statusp->ParentVnode = 0x1; ! statusp->ParentUnique = 0x1; ! statusp->ResidencyMask = 0; ! statusp->ClientModTime = FakeFreelanceModTime; ! statusp->ServerModTime = FakeFreelanceModTime; ! statusp->Group = 0; ! statusp->SyncCounter = 0; ! statusp->dataVersionHigh = 0; ! } #endif /* AFS_FREELANCE_CLIENT */ ! if (!(flags & CM_MERGEFLAG_FORCE) ! && statusp->DataVersion < (unsigned long) scp->dataVersion) { ! struct cm_cell *cellp; ! struct cm_volume *volp; ! ! cellp = cm_FindCellByID(scp->fid.cell); ! cm_GetVolumeByID(cellp, scp->fid.volume, userp, ! (cm_req_t *) NULL, &volp); ! if (scp->cbServerp) ! osi_Log2(afsd_logp, "old data from server %x volume %s", ! scp->cbServerp->addr.sin_addr.s_addr, ! volp->namep); ! osi_Log3(afsd_logp, "Bad merge, scp %x, scp dv %d, RPC dv %d", ! scp, scp->dataVersion, statusp->DataVersion); ! /* we have a number of data fetch/store operations running ! * concurrently, and we can tell which one executed last at the ! * server by its mtime. ! * Choose the one with the largest mtime, and ignore the rest. ! * ! * These concurrent calls are incompatible with setting the ! * mtime, so we won't have a locally changed mtime here. ! * ! * We could also have ACL info for a different user than usual, ! * in which case we have to do that part of the merge, anyway. ! * We won't have to worry about the info being old, since we ! * won't have concurrent calls ! * that change file status running from this machine. ! * ! * Added 3/17/98: if we see data version regression on an RO ! * file, it's probably due to a server holding an out-of-date ! * replica, rather than to concurrent RPC's. Failures to ! * release replicas are now flagged by the volserver, but only ! * since AFS 3.4 5.22, so there are plenty of clients getting ! * out-of-date replicas out there. ! * ! * If we discover an out-of-date replica, by this time it's too ! * late to go to another server and retry. Also, we can't ! * reject the merge, because then there is no way for ! * GetAccess to do its work, and the caller gets into an ! * infinite loop. So we just grin and bear it. ! */ ! if (!(scp->flags & CM_SCACHEFLAG_RO)) ! return; ! } ! scp->serverModTime = statusp->ServerModTime; ! ! if (!(scp->mask & CM_SCACHEMASK_CLIENTMODTIME)) { ! scp->clientModTime = statusp->ClientModTime; ! } ! if (!(scp->mask & CM_SCACHEMASK_LENGTH)) { ! scp->length.LowPart = statusp->Length; ! scp->length.HighPart = 0; ! } ! ! scp->serverLength.LowPart = statusp->Length; ! scp->serverLength.HighPart = 0; ! ! scp->linkCount = statusp->LinkCount; ! scp->dataVersion = statusp->DataVersion; ! scp->owner = statusp->Owner; ! scp->group = statusp->Group; ! scp->unixModeBits = statusp->UnixModeBits & 07777; ! ! if (statusp->FileType == File) ! scp->fileType = CM_SCACHETYPE_FILE; ! else if (statusp->FileType == Directory) ! scp->fileType = CM_SCACHETYPE_DIRECTORY; ! else if (statusp->FileType == SymbolicLink) { ! if ((scp->unixModeBits & 0111) == 0) ! scp->fileType = CM_SCACHETYPE_MOUNTPOINT; ! else ! scp->fileType = CM_SCACHETYPE_SYMLINK; ! } else { osi_Log1(afsd_logp, "Merge, Invalid File Type, scp %x", scp); scp->fileType = 0; /* invalid */ } ! /* and other stuff */ ! scp->parentVnode = statusp->ParentVnode; ! scp->parentUnique = statusp->ParentUnique; ! ! /* and merge in the private acl cache info, if this is more than the public ! * info; merge in the public stuff in any case. ! */ ! scp->anyAccess = statusp->AnonymousAccess; ! if (userp != NULL) { ! cm_AddACLCache(scp, userp, statusp->CallerAccess); ! } } /* note that our stat cache info is incorrect, so force us eventually --- 832,954 ---- * started before that, can cause old info to be merged from the first call. */ void cm_MergeStatus(cm_scache_t *scp, AFSFetchStatus *statusp, AFSVolSync *volp, ! cm_user_t *userp, int flags) { ! // yj: i want to create some fake status for the /afs directory and the ! // entries under that directory #ifdef AFS_FREELANCE_CLIENT ! if (cm_freelanceEnabled && scp == cm_rootSCachep) { ! osi_Log0(afsd_logp,"cm_MergeStatus Freelance cm_rootSCachep"); ! statusp->InterfaceVersion = 0x1; statusp->FileType = CM_SCACHETYPE_DIRECTORY; ! statusp->LinkCount = scp->linkCount; ! statusp->Length = cm_fakeDirSize; ! statusp->DataVersion = cm_fakeDirVersion; ! statusp->Author = 0x1; ! statusp->Owner = 0x0; ! statusp->CallerAccess = 0x9; ! statusp->AnonymousAccess = 0x9; ! statusp->UnixModeBits = 0x1ff; ! statusp->ParentVnode = 0x1; ! statusp->ParentUnique = 0x1; ! statusp->ResidencyMask = 0; ! statusp->ClientModTime = FakeFreelanceModTime; ! statusp->ServerModTime = FakeFreelanceModTime; ! statusp->Group = 0; ! statusp->SyncCounter = 0; ! statusp->dataVersionHigh = 0; ! } #endif /* AFS_FREELANCE_CLIENT */ ! if (!(flags & CM_MERGEFLAG_FORCE) ! && statusp->DataVersion < (unsigned long) scp->dataVersion) { ! struct cm_cell *cellp; ! struct cm_volume *volp; ! ! cellp = cm_FindCellByID(scp->fid.cell); ! cm_GetVolumeByID(cellp, scp->fid.volume, userp, ! (cm_req_t *) NULL, &volp); ! if (scp->cbServerp) ! osi_Log2(afsd_logp, "old data from server %x volume %s", ! scp->cbServerp->addr.sin_addr.s_addr, ! volp->namep); ! osi_Log3(afsd_logp, "Bad merge, scp %x, scp dv %d, RPC dv %d", ! scp, scp->dataVersion, statusp->DataVersion); ! /* we have a number of data fetch/store operations running ! * concurrently, and we can tell which one executed last at the ! * server by its mtime. ! * Choose the one with the largest mtime, and ignore the rest. ! * ! * These concurrent calls are incompatible with setting the ! * mtime, so we won't have a locally changed mtime here. ! * ! * We could also have ACL info for a different user than usual, ! * in which case we have to do that part of the merge, anyway. ! * We won't have to worry about the info being old, since we ! * won't have concurrent calls ! * that change file status running from this machine. ! * ! * Added 3/17/98: if we see data version regression on an RO ! * file, it's probably due to a server holding an out-of-date ! * replica, rather than to concurrent RPC's. Failures to ! * release replicas are now flagged by the volserver, but only ! * since AFS 3.4 5.22, so there are plenty of clients getting ! * out-of-date replicas out there. ! * ! * If we discover an out-of-date replica, by this time it's too ! * late to go to another server and retry. Also, we can't ! * reject the merge, because then there is no way for ! * GetAccess to do its work, and the caller gets into an ! * infinite loop. So we just grin and bear it. ! */ ! if (!(scp->flags & CM_SCACHEFLAG_RO)) ! return; ! } ! scp->serverModTime = statusp->ServerModTime; ! ! if (!(scp->mask & CM_SCACHEMASK_CLIENTMODTIME)) { ! scp->clientModTime = statusp->ClientModTime; ! } ! if (!(scp->mask & CM_SCACHEMASK_LENGTH)) { ! scp->length.LowPart = statusp->Length; ! scp->length.HighPart = 0; ! } ! ! scp->serverLength.LowPart = statusp->Length; ! scp->serverLength.HighPart = 0; ! ! scp->linkCount = statusp->LinkCount; ! scp->dataVersion = statusp->DataVersion; ! scp->owner = statusp->Owner; ! scp->group = statusp->Group; ! scp->unixModeBits = statusp->UnixModeBits & 07777; ! ! if (statusp->FileType == File) ! scp->fileType = CM_SCACHETYPE_FILE; ! else if (statusp->FileType == Directory) ! scp->fileType = CM_SCACHETYPE_DIRECTORY; ! else if (statusp->FileType == SymbolicLink) { ! if ((scp->unixModeBits & 0111) == 0) ! scp->fileType = CM_SCACHETYPE_MOUNTPOINT; ! else ! scp->fileType = CM_SCACHETYPE_SYMLINK; ! } else { osi_Log1(afsd_logp, "Merge, Invalid File Type, scp %x", scp); scp->fileType = 0; /* invalid */ } ! /* and other stuff */ ! scp->parentVnode = statusp->ParentVnode; ! scp->parentUnique = statusp->ParentUnique; ! ! /* and merge in the private acl cache info, if this is more than the public ! * info; merge in the public stuff in any case. ! */ ! scp->anyAccess = statusp->AnonymousAccess; ! if (userp != NULL) { ! cm_AddACLCache(scp, userp, statusp->CallerAccess); ! } } /* note that our stat cache info is incorrect, so force us eventually *************** *** 961,1020 **** */ void cm_DiscardSCache(cm_scache_t *scp) { ! lock_AssertMutex(&scp->mx); if (scp->cbServerp) { cm_PutServer(scp->cbServerp); scp->cbServerp = NULL; } ! scp->cbExpires = 0; ! cm_dnlcPurgedp(scp); ! cm_FreeAllACLEnts(scp); } void cm_AFSFidFromFid(AFSFid *afsFidp, cm_fid_t *fidp) { ! afsFidp->Volume = fidp->volume; ! afsFidp->Vnode = fidp->vnode; ! afsFidp->Unique = fidp->unique; ! } void cm_HoldSCache(cm_scache_t *scp) { ! lock_ObtainWrite(&cm_scacheLock); ! osi_assert(scp->refCount > 0); ! scp->refCount++; ! lock_ReleaseWrite(&cm_scacheLock); } void cm_ReleaseSCache(cm_scache_t *scp) { ! lock_ObtainWrite(&cm_scacheLock); ! osi_assert(scp->refCount-- > 0); ! lock_ReleaseWrite(&cm_scacheLock); } /* just look for the scp entry to get filetype */ /* doesn't need to be perfectly accurate, so locking doesn't matter too much */ int cm_FindFileType(cm_fid_t *fidp) { ! long hash; ! cm_scache_t *scp; ! hash = CM_SCACHE_HASH(fidp); ! osi_assert(fidp->cell != 0); ! lock_ObtainWrite(&cm_scacheLock); ! for(scp=cm_hashTablep[hash]; scp; scp=scp->nextp) { ! if (cm_FidCmp(fidp, &scp->fid) == 0) { ! /*scp->refCount++;*/ ! /*cm_AdjustLRU(scp);*/ ! lock_ReleaseWrite(&cm_scacheLock); ! return scp->fileType; ! } } ! lock_ReleaseWrite(&cm_scacheLock); ! return 0; } /* dump all scp's that have reference count > 0 to a file. --- 961,1018 ---- */ void cm_DiscardSCache(cm_scache_t *scp) { ! lock_AssertMutex(&scp->mx); if (scp->cbServerp) { cm_PutServer(scp->cbServerp); scp->cbServerp = NULL; } ! scp->cbExpires = 0; ! cm_dnlcPurgedp(scp); ! cm_FreeAllACLEnts(scp); } void cm_AFSFidFromFid(AFSFid *afsFidp, cm_fid_t *fidp) { ! afsFidp->Volume = fidp->volume; ! afsFidp->Vnode = fidp->vnode; ! afsFidp->Unique = fidp->unique; ! } void cm_HoldSCache(cm_scache_t *scp) { ! lock_ObtainWrite(&cm_scacheLock); ! osi_assert(scp->refCount > 0); ! scp->refCount++; ! lock_ReleaseWrite(&cm_scacheLock); } void cm_ReleaseSCache(cm_scache_t *scp) { ! lock_ObtainWrite(&cm_scacheLock); ! osi_assert(scp->refCount-- > 0); ! lock_ReleaseWrite(&cm_scacheLock); } /* just look for the scp entry to get filetype */ /* doesn't need to be perfectly accurate, so locking doesn't matter too much */ int cm_FindFileType(cm_fid_t *fidp) { ! long hash; ! cm_scache_t *scp; ! hash = CM_SCACHE_HASH(fidp); ! osi_assert(fidp->cell != 0); ! lock_ObtainWrite(&cm_scacheLock); ! for (scp=cm_hashTablep[hash]; scp; scp=scp->nextp) { ! if (cm_FidCmp(fidp, &scp->fid) == 0) { ! lock_ReleaseWrite(&cm_scacheLock); ! return scp->fileType; } ! } ! lock_ReleaseWrite(&cm_scacheLock); ! return 0; } /* dump all scp's that have reference count > 0 to a file. Index: openafs/src/WINNT/afsd/cm_scache.h diff -c openafs/src/WINNT/afsd/cm_scache.h:1.4.2.2 openafs/src/WINNT/afsd/cm_scache.h:1.4.2.3 *** openafs/src/WINNT/afsd/cm_scache.h:1.4.2.2 Mon Oct 18 00:09:26 2004 --- openafs/src/WINNT/afsd/cm_scache.h Fri Nov 5 14:21:44 2004 *************** *** 24,30 **** typedef struct cm_accessCache { osi_queue_t q; /* queue header */ struct cm_user *userp; /* user having access rights */ ! long rights; /* rights */ } cm_accessCache_t; typedef struct cm_file_lock { --- 24,30 ---- typedef struct cm_accessCache { osi_queue_t q; /* queue header */ struct cm_user *userp; /* user having access rights */ ! unsigned long rights; /* rights */ } cm_accessCache_t; typedef struct cm_file_lock { *************** *** 50,56 **** osi_queue_t q; /* lru queue; cm_scacheLock */ struct cm_scache *nextp; /* next in hash; cm_scacheLock */ cm_fid_t fid; ! long flags; /* flags; locked by mx */ /* synchronization stuff */ osi_mutex_t mx; /* mutex for this structure */ --- 50,56 ---- osi_queue_t q; /* lru queue; cm_scacheLock */ struct cm_scache *nextp; /* next in hash; cm_scacheLock */ cm_fid_t fid; ! unsigned long flags; /* flags; locked by mx */ /* synchronization stuff */ osi_mutex_t mx; /* mutex for this structure */ *************** *** 67,83 **** long parentUnique; /* for ACL callbacks */ /* local modification stat */ ! long mask; /* for clientModTime, length and * truncPos */ /* file status */ ! int fileType; /* file type */ time_t clientModTime; /* mtime */ time_t serverModTime; /* at server, for concurrent call * comparisons */ osi_hyper_t length; /* file length */ cm_prefetch_t prefetch; /* prefetch info structure */ ! int unixModeBits; /* unix protection mode bits */ int linkCount; /* link count */ long dataVersion; /* data version */ long owner; /* file owner */ --- 67,83 ---- long parentUnique; /* for ACL callbacks */ /* local modification stat */ ! unsigned long mask; /* for clientModTime, length and * truncPos */ /* file status */ ! unsigned int fileType; /* file type */ time_t clientModTime; /* mtime */ time_t serverModTime; /* at server, for concurrent call * comparisons */ osi_hyper_t length; /* file length */ cm_prefetch_t prefetch; /* prefetch info structure */ ! unsigned int unixModeBits; /* unix protection mode bits */ int linkCount; /* link count */ long dataVersion; /* data version */ long owner; /* file owner */ *************** *** 118,124 **** osi_hyper_t bulkStatProgress; /* track bulk stats of large dirs */ /* open state */ ! short openReads; /* opens for reading */ short openWrites; /* open for writing */ short openShares; /* open for read excl */ short openExcls; /* open for exclusives */ --- 118,124 ---- osi_hyper_t bulkStatProgress; /* track bulk stats of large dirs */ /* open state */ ! short openReads; /* open for reading */ short openWrites; /* open for writing */ short openShares; /* open for read excl */ short openExcls; /* open for exclusives */ Index: openafs/src/WINNT/afsd/cm_vnodeops.c diff -c openafs/src/WINNT/afsd/cm_vnodeops.c:1.19.2.4 openafs/src/WINNT/afsd/cm_vnodeops.c:1.19.2.5 *** openafs/src/WINNT/afsd/cm_vnodeops.c:1.19.2.4 Mon Oct 18 00:09:26 2004 --- openafs/src/WINNT/afsd/cm_vnodeops.c Fri Nov 5 14:21:44 2004 *************** *** 427,432 **** --- 427,435 ---- * Iterate through all entries in a directory. * When the function funcp is called, the buffer is locked but the * directory vnode is not. + * + * If the retscp parameter is not NULL, the parmp must be a + * cm_lookupSearch_t object. */ long cm_ApplyDir(cm_scache_t *scp, cm_DirFuncp_t funcp, void *parmp, osi_hyper_t *startOffsetp, cm_user_t *userp, cm_req_t *reqp, *************** *** 465,481 **** if (retscp) /* if this is a lookup call */ { cm_lookupSearch_t* sp = parmp; - int casefold = sp->caseFold; - - sp->caseFold = 0; /* we have a strong preference for exact matches */ - if ( *retscp = cm_dnlcLookup(scp, sp)) /* dnlc hit */ - { - sp->caseFold = casefold; - lock_ReleaseMutex(&scp->mx); - return 0; - } ! sp->caseFold = casefold; } /* --- 468,493 ---- if (retscp) /* if this is a lookup call */ { cm_lookupSearch_t* sp = parmp; ! #ifdef AFS_FREELANCE_CLIENT ! /* Freelance entries never end up in the DNLC because they ! * do not have an associated cm_server_t ! */ ! if ( !(cm_freelanceEnabled && ! sp->fid.cell==AFS_FAKE_ROOT_CELL_ID && ! sp->fid.volume==AFS_FAKE_ROOT_VOL_ID ) ) ! #endif /* AFS_FREELANCE_CLIENT */ ! { ! int casefold = sp->caseFold; ! sp->caseFold = 0; /* we have a strong preference for exact matches */ ! if ( *retscp = cm_dnlcLookup(scp, sp)) /* dnlc hit */ ! { ! sp->caseFold = casefold; ! lock_ReleaseMutex(&scp->mx); ! return 0; ! } ! sp->caseFold = casefold; ! } } /* *************** *** 787,793 **** } } /* locked, has callback, has valid data in buffer */ ! if ((tlen = scp->length.LowPart) > 1000) return CM_ERROR_TOOBIG; if (tlen <= 0) { code = CM_ERROR_INVAL; goto done; --- 799,806 ---- } } /* locked, has callback, has valid data in buffer */ ! if ((tlen = scp->length.LowPart) > 1000) ! return CM_ERROR_TOOBIG; if (tlen <= 0) { code = CM_ERROR_INVAL; goto done; *************** *** 1096,1101 **** --- 1109,1121 ---- int sysNameIndex = 0; cm_scache_t *scp = 0; + if ( stricmp(namep,SMB_IOCTL_FILENAME_NOSLASH) == 0 ) { + if (flags & CM_FLAG_CHECKPATH) + return CM_ERROR_NOSUCHPATH; + else + return CM_ERROR_NOSUCHFILE; + } + for ( sysNameIndex = 0; sysNameIndex < MAXNUMSYSNAMES; sysNameIndex++) { code = cm_ExpandSysName(namep, tname, sizeof(tname), sysNameIndex); if (code > 0) { *************** *** 1104,1113 **** *outpScpp = scp; return 0; } ! if (scp) { ! cm_ReleaseSCache(scp); ! scp = 0; ! } } else { return cm_LookupInternal(dscp, namep, flags, userp, reqp, outpScpp); } --- 1124,1133 ---- *outpScpp = scp; return 0; } ! if (scp) { ! cm_ReleaseSCache(scp); ! scp = 0; ! } } else { return cm_LookupInternal(dscp, namep, flags, userp, reqp, outpScpp); } *************** *** 1405,1416 **** if (tscp->fileType == CM_SCACHETYPE_SYMLINK) { /* this is a symlink; assemble a new buffer */ lock_ReleaseMutex(&tscp->mx); ! if (symlinkCount++ >= 16) { cm_ReleaseSCache(tscp); cm_ReleaseSCache(dirScp); if (psp) cm_FreeSpace(psp); ! return CM_ERROR_TOOBIG; } if (tc == 0) restp = ""; --- 1425,1436 ---- if (tscp->fileType == CM_SCACHETYPE_SYMLINK) { /* this is a symlink; assemble a new buffer */ lock_ReleaseMutex(&tscp->mx); ! if (symlinkCount++ >= MAX_SYMLINK_COUNT) { cm_ReleaseSCache(tscp); cm_ReleaseSCache(dirScp); if (psp) cm_FreeSpace(psp); ! return CM_ERROR_TOO_MANY_SYMLINKS; } if (tc == 0) restp = ""; *************** *** 1659,1667 **** bb.counter = 0; bb.bufOffset = *offsetp; /* first, assemble the file IDs we need to stat */ ! code = cm_ApplyDir(dscp, cm_TryBulkProc, (void *) &bb, offsetp, userp, ! reqp, NULL); /* if we failed, bail out early */ if (code && code != CM_ERROR_STOPNOW) return; --- 1679,1688 ---- bb.counter = 0; bb.bufOffset = *offsetp; + lock_ReleaseMutex(&dscp->mx); /* first, assemble the file IDs we need to stat */ ! code = cm_ApplyDir(dscp, cm_TryBulkProc, (void *) &bb, offsetp, userp, reqp, NULL); ! lock_ObtainMutex(&dscp->mx); /* if we failed, bail out early */ if (code && code != CM_ERROR_STOPNOW) return; *************** *** 1671,1677 **** * time. */ filex = 0; ! while(filex < bb.counter) { filesThisCall = bb.counter - filex; if (filesThisCall > AFSCBMAX) filesThisCall = AFSCBMAX; --- 1692,1698 ---- * time. */ filex = 0; ! while (filex < bb.counter) { filesThisCall = bb.counter - filex; if (filesThisCall > AFSCBMAX) filesThisCall = AFSCBMAX; Index: openafs/src/WINNT/afsd/cm_vnodeops.h diff -c openafs/src/WINNT/afsd/cm_vnodeops.h:1.5.2.3 openafs/src/WINNT/afsd/cm_vnodeops.h:1.5.2.4 *** openafs/src/WINNT/afsd/cm_vnodeops.h:1.5.2.3 Mon Oct 18 00:09:26 2004 --- openafs/src/WINNT/afsd/cm_vnodeops.h Fri Nov 5 14:21:45 2004 *************** *** 154,157 **** --- 154,158 ---- extern long cm_RetryLock(cm_file_lock_t *oldFileLock, int vcp_is_dead); + #define MAX_SYMLINK_COUNT 16 #endif /* __CM_VNODEOPS_H_ENV__ */ Index: openafs/src/WINNT/afsd/smb.c diff -c openafs/src/WINNT/afsd/smb.c:1.55.2.3 openafs/src/WINNT/afsd/smb.c:1.55.2.4 *** openafs/src/WINNT/afsd/smb.c:1.55.2.3 Mon Oct 18 00:09:27 2004 --- openafs/src/WINNT/afsd/smb.c Fri Nov 5 14:21:45 2004 *************** *** 387,396 **** { unsigned int attrs; ! if (scp->fileType == CM_SCACHETYPE_DIRECTORY ! || scp->fileType == CM_SCACHETYPE_MOUNTPOINT) attrs = SMB_ATTR_DIRECTORY; ! else attrs = 0; /* --- 387,407 ---- { unsigned int attrs; ! if ( scp->fileType == CM_SCACHETYPE_DIRECTORY || ! scp->fileType == CM_SCACHETYPE_MOUNTPOINT) ! { attrs = SMB_ATTR_DIRECTORY; ! #ifdef SPECIAL_FOLDERS ! #ifdef AFS_FREELANCE_CLIENT ! if ( cm_freelanceEnabled && ! scp->fid.cell==AFS_FAKE_ROOT_CELL_ID && ! scp->fid.volume==AFS_FAKE_ROOT_VOL_ID && ! scp->fid.vnode==0x1 && scp->fid.unique==0x1) { ! attrs |= SMB_ATTR_SYSTEM; /* FILE_ATTRIBUTE_SYSTEM */ ! } ! #endif /* AFS_FREELANCE_CLIENT */ ! #endif /* SPECIAL_FOLDERS */ ! } else attrs = 0; /* *************** *** 1300,1306 **** { int matchType = 0; smb_findShare_rock_t * vrock = (smb_findShare_rock_t *) rockp; ! if(!strnicmp(dep->name, vrock->shareName, 12)) { if(!stricmp(dep->name, vrock->shareName)) matchType = SMB_FINDSHARE_EXACT_MATCH; else --- 1311,1317 ---- { int matchType = 0; smb_findShare_rock_t * vrock = (smb_findShare_rock_t *) rockp; ! if (!strnicmp(dep->name, vrock->shareName, 12)) { if(!stricmp(dep->name, vrock->shareName)) matchType = SMB_FINDSHARE_EXACT_MATCH; else *************** *** 1464,1470 **** (uidp? (uidp->unp ? uidp->unp->userp : NULL) : NULL), &req, NULL); cm_ReleaseSCache(cm_rootSCachep); ! if(vrock.matchType) { sprintf(pathName,"/%s/",vrock.match); *pathNamep = strdup(strlwr(pathName)); free(vrock.match); --- 1475,1481 ---- (uidp? (uidp->unp ? uidp->unp->userp : NULL) : NULL), &req, NULL); cm_ReleaseSCache(cm_rootSCachep); ! if (vrock.matchType) { sprintf(pathName,"/%s/",vrock.match); *pathNamep = strdup(strlwr(pathName)); free(vrock.match); *************** *** 1546,1556 **** /* find a dir search structure by cookie value, and return it held. * Must be called with smb_globalLock held. */ ! smb_dirSearch_t *smb_FindDirSearchNL(long cookie) { smb_dirSearch_t *dsp; ! for(dsp = smb_firstDirSearchp; dsp; dsp = (smb_dirSearch_t *) osi_QNext(&dsp->q)) { if (dsp->cookie == cookie) { if (dsp != smb_firstDirSearchp) { /* move to head of LRU queue, too, if we're not already there */ --- 1557,1567 ---- /* find a dir search structure by cookie value, and return it held. * Must be called with smb_globalLock held. */ ! smb_dirSearch_t *smb_FindDirSearchNoLock(long cookie) { smb_dirSearch_t *dsp; ! for (dsp = smb_firstDirSearchp; dsp; dsp = (smb_dirSearch_t *) osi_QNext(&dsp->q)) { if (dsp->cookie == cookie) { if (dsp != smb_firstDirSearchp) { /* move to head of LRU queue, too, if we're not already there */ *************** *** 1562,1568 **** --- 1573,1581 ---- if (!smb_lastDirSearchp) smb_lastDirSearchp = (smb_dirSearch_t *) &dsp->q; } + lock_ObtainMutex(&dsp->mx); dsp->refCount++; + lock_ReleaseMutex(&dsp->mx); break; } } *************** *** 1572,1581 **** void smb_DeleteDirSearch(smb_dirSearch_t *dsp) { lock_ObtainWrite(&smb_globalLock); - dsp->flags |= SMB_DIRSEARCH_DELETE; - lock_ReleaseWrite(&smb_globalLock); lock_ObtainMutex(&dsp->mx); ! if(dsp->scp != NULL) { lock_ObtainMutex(&dsp->scp->mx); if (dsp->flags & SMB_DIRSEARCH_BULKST) { dsp->flags &= ~SMB_DIRSEARCH_BULKST; --- 1585,1593 ---- void smb_DeleteDirSearch(smb_dirSearch_t *dsp) { lock_ObtainWrite(&smb_globalLock); lock_ObtainMutex(&dsp->mx); ! dsp->flags |= SMB_DIRSEARCH_DELETE; ! if (dsp->scp != NULL) { lock_ObtainMutex(&dsp->scp->mx); if (dsp->flags & SMB_DIRSEARCH_BULKST) { dsp->flags &= ~SMB_DIRSEARCH_BULKST; *************** *** 1585,1621 **** lock_ReleaseMutex(&dsp->scp->mx); } lock_ReleaseMutex(&dsp->mx); } ! void smb_ReleaseDirSearch(smb_dirSearch_t *dsp) { cm_scache_t *scp; scp = NULL; ! lock_ObtainWrite(&smb_globalLock); osi_assert(dsp->refCount-- > 0); if (dsp->refCount == 0 && (dsp->flags & SMB_DIRSEARCH_DELETE)) { if (&dsp->q == (osi_queue_t *) smb_lastDirSearchp) smb_lastDirSearchp = (smb_dirSearch_t *) osi_QPrev(&smb_lastDirSearchp->q); osi_QRemove((osi_queue_t **) &smb_firstDirSearchp, &dsp->q); lock_FinalizeMutex(&dsp->mx); scp = dsp->scp; free(dsp); } - lock_ReleaseWrite(&smb_globalLock); - /* do this now to avoid spurious locking hierarchy creation */ if (scp) cm_ReleaseSCache(scp); } /* find a dir search structure by cookie value, and return it held */ smb_dirSearch_t *smb_FindDirSearch(long cookie) { smb_dirSearch_t *dsp; lock_ObtainWrite(&smb_globalLock); ! dsp = smb_FindDirSearchNL(cookie); lock_ReleaseWrite(&smb_globalLock); return dsp; } --- 1597,1643 ---- lock_ReleaseMutex(&dsp->scp->mx); } lock_ReleaseMutex(&dsp->mx); + lock_ReleaseWrite(&smb_globalLock); } ! /* Must be called with the smb_globalLock held */ ! void smb_ReleaseDirSearchNoLock(smb_dirSearch_t *dsp) { cm_scache_t *scp; scp = NULL; ! lock_ObtainMutex(&dsp->mx); osi_assert(dsp->refCount-- > 0); if (dsp->refCount == 0 && (dsp->flags & SMB_DIRSEARCH_DELETE)) { if (&dsp->q == (osi_queue_t *) smb_lastDirSearchp) smb_lastDirSearchp = (smb_dirSearch_t *) osi_QPrev(&smb_lastDirSearchp->q); osi_QRemove((osi_queue_t **) &smb_firstDirSearchp, &dsp->q); + lock_ReleaseMutex(&dsp->mx); lock_FinalizeMutex(&dsp->mx); scp = dsp->scp; free(dsp); + } else { + lock_ReleaseMutex(&dsp->mx); } /* do this now to avoid spurious locking hierarchy creation */ if (scp) cm_ReleaseSCache(scp); } + void smb_ReleaseDirSearch(smb_dirSearch_t *dsp) + { + lock_ObtainWrite(&smb_globalLock); + smb_ReleaseDirSearchNoLock(dsp); + lock_ReleaseWrite(&smb_globalLock); + } + /* find a dir search structure by cookie value, and return it held */ smb_dirSearch_t *smb_FindDirSearch(long cookie) { smb_dirSearch_t *dsp; lock_ObtainWrite(&smb_globalLock); ! dsp = smb_FindDirSearchNoLock(cookie); lock_ReleaseWrite(&smb_globalLock); return dsp; } *************** *** 1650,1664 **** } /* don't do more than this */ ! if (victimCount >= SMB_DIRSEARCH_GCMAX) break; } /* now release them */ ! lock_ReleaseWrite(&smb_globalLock); ! for(i = 0; i < victimCount; i++) { ! smb_ReleaseDirSearch(victimsp[i]); } - lock_ObtainWrite(&smb_globalLock); } /* function for allocating a dir search entry. We need these to remember enough context --- 1672,1685 ---- } /* don't do more than this */ ! if (victimCount >= SMB_DIRSEARCH_GCMAX) ! break; } /* now release them */ ! for (i = 0; i < victimCount; i++) { ! smb_ReleaseDirSearchNoLock(victimsp[i]); } } /* function for allocating a dir search entry. We need these to rem