From 5979a37e4e361bd9d2c52b6f6ef4bcce20a3124c Mon Sep 17 00:00:00 2001 From: Jeffrey Altman Date: Tue, 8 Jan 2008 07:04:51 +0000 Subject: [PATCH] windows-smb-started-synchronization-20080108 LICENSE MIT Add a new mutex "smb_StartedMutex" which is used to protect the transitions between the various smb_ListenerState values. --- src/WINNT/afsd/afsd_service.c | 10 +-- src/WINNT/afsd/cm_daemon.c | 6 +- src/WINNT/afsd/lanahelper.h | 2 - src/WINNT/afsd/smb.c | 167 +++++++++++++++++++++++++++++++++--------- src/WINNT/afsd/smb.h | 8 +- 5 files changed, 144 insertions(+), 49 deletions(-) diff --git a/src/WINNT/afsd/afsd_service.c b/src/WINNT/afsd/afsd_service.c index ed0fc1f..ac58d2a 100644 --- a/src/WINNT/afsd/afsd_service.c +++ b/src/WINNT/afsd/afsd_service.c @@ -344,7 +344,7 @@ afsd_ServiceControlHandlerEx( powerStateSuspended = 1; if (osVersion.dwMajorVersion >= 6) { cm_SuspendSCache(); - smb_StopListeners(); + smb_StopListeners(0); } dwRet = NO_ERROR; break; @@ -353,14 +353,14 @@ afsd_ServiceControlHandlerEx( powerStateSuspended = 1; if (osVersion.dwMajorVersion >= 6) { cm_SuspendSCache(); - smb_StopListeners(); + smb_StopListeners(0); } dwRet = NO_ERROR; break; case PBT_APMRESUMECRITICAL: afsi_log("SERVICE_CONTROL_APMRESUMECRITICAL"); if (osVersion.dwMajorVersion >= 6) - smb_RestartListeners(); + smb_RestartListeners(0); dwRet = NO_ERROR; break; case PBT_APMRESUMESUSPEND: @@ -394,7 +394,7 @@ afsd_ServiceControlHandlerEx( afsi_log("SERVICE_CONTROL_APMRESUMEAUTOMATIC"); powerStateSuspended = 0; if (osVersion.dwMajorVersion >= 6) - smb_RestartListeners(); + smb_RestartListeners(0); dwRet = NO_ERROR; break; default: @@ -441,7 +441,7 @@ static DWORD __stdcall MountGlobalDrivesThread(void * notUsed) dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_QUERY_VALUE, &hKey); if (dwResult != ERROR_SUCCESS) - return; + return 0; while (dwIndex < MAX_DRIVES) { dwDriveSize = sizeof(szDriveToMapTo); diff --git a/src/WINNT/afsd/cm_daemon.c b/src/WINNT/afsd/cm_daemon.c index 86b23fa..8eb97b7 100644 --- a/src/WINNT/afsd/cm_daemon.c +++ b/src/WINNT/afsd/cm_daemon.c @@ -69,7 +69,7 @@ void cm_IpAddrDaemon(long parm) thrd_SetEvent(cm_IPAddrDaemon_ShutdownEvent); Result = NotifyAddrChange(NULL,NULL); if (Result == NO_ERROR && daemon_ShutdownFlag == 0) { - smb_LanAdapterChange(); + smb_SetLanAdapterChangeDetected(); thrd_ResetEvent(cm_IPAddrDaemon_ShutdownEvent); Sleep(2500); if (daemon_ShutdownFlag == 0) { @@ -395,7 +395,7 @@ void cm_Daemon(long parm) /* check to see if the listener threads halted due to network * disconnect or other issues. If so, attempt to restart them. */ - smb_RestartListeners(); + smb_RestartListeners(0); if (daemon_ShutdownFlag == 1) break; @@ -523,7 +523,7 @@ void cm_Daemon(long parm) if (daemon_ShutdownFlag == 1) { break; } - thrd_Sleep(30 * 1000); /* sleep 30 seconds */ + thrd_Sleep(1000); /* sleep 30 seconds */ } thrd_SetEvent(cm_Daemon_ShutdownEvent); } diff --git a/src/WINNT/afsd/lanahelper.h b/src/WINNT/afsd/lanahelper.h index 1979b3e..608fe16 100644 --- a/src/WINNT/afsd/lanahelper.h +++ b/src/WINNT/afsd/lanahelper.h @@ -35,8 +35,6 @@ extern "C" { typedef BYTE lana_number_t; -#define LANA_INVALID 0xff - struct LANAINFO { lana_number_t lana_number; diff --git a/src/WINNT/afsd/smb.c b/src/WINNT/afsd/smb.c index 9eadd67..688b812 100644 --- a/src/WINNT/afsd/smb.c +++ b/src/WINNT/afsd/smb.c @@ -59,9 +59,11 @@ osi_log_t * smb_logp; osi_rwlock_t smb_globalLock; osi_rwlock_t smb_rctLock; osi_mutex_t smb_ListenerLock; +osi_mutex_t smb_StartedLock; -char smb_LANadapter = -1; +unsigned char smb_LANadapter = LANA_INVALID; unsigned char smb_sharename[NCBNAMSZ+1] = {0}; +int smb_LanAdapterChangeDetected = 0; BOOL isGateway = FALSE; @@ -163,7 +165,7 @@ DWORD smb_TlsRequestSlot = -1; /* forward decl */ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp, NCB *ncbp, raw_write_cont_t *rwcp); -int smb_NetbiosInit(void); +int smb_NetbiosInit(int); #ifdef LOG_PACKET void smb_LogPacket(smb_packet_t *packet); @@ -8087,7 +8089,9 @@ void smb_Listener(void *parmp) if (code == NRC_BRIDGE) { int lanaRemaining = 0; + lock_ObtainMutex(&smb_StartedLock); if (smb_ListenerState == SMB_LISTENER_STOPPED || smbShutdownFlag == 1) { + lock_ReleaseMutex(&smb_StartedLock); ExitThread(1); } @@ -8111,10 +8115,11 @@ void smb_Listener(void *parmp) #endif ); smb_ListenerState = SMB_LISTENER_STOPPED; - smb_LANadapter = -1; + smb_LANadapter = LANA_INVALID; lana_list.length = 0; } FreeNCB(ncbp); + lock_ReleaseMutex(&smb_StartedLock); return; } else if (code != 0) { char tbuffer[AFSPATHMAX]; @@ -8124,16 +8129,16 @@ void smb_Listener(void *parmp) ExitThread(1); } - osi_Log2(smb_logp, - "NCBLISTEN lana=%d failed with code %d", - ncbp->ncb_lana_num, code); + osi_Log3(smb_logp, + "NCBLISTEN lana=%d failed with code %d [%s]", + ncbp->ncb_lana_num, code, ncb_error_string(code)); osi_Log0(smb_logp, "Client exiting due to network failure. Please restart client.\n"); sprintf(tbuffer, "Client exiting due to network failure. Please restart client.\n" - "NCBLISTEN lana=%d failed with code %d", - ncbp->ncb_lana_num, code); + "NCBLISTEN lana=%d failed with code %d [%s]", + ncbp->ncb_lana_num, code, ncb_error_string(code)); if (showErrors) code = (*smb_MBfunc)(NULL, tbuffer, "AFS Client Service: Fatal Error", MB_OK|MB_SERVICE_NOTIFICATION); @@ -8321,31 +8326,71 @@ void smb_Listener(void *parmp) FreeNCB(ncbp); } +void smb_SetLanAdapterChangeDetected(void) +{ + lock_ObtainMutex(&smb_StartedLock); + smb_LanAdapterChangeDetected = 1; + lock_ReleaseMutex(&smb_StartedLock); +} -void smb_LanAdapterChange(void) { +void smb_LanAdapterChange(int locked) { lana_number_t lanaNum; BOOL bGateway; char NetbiosName[MAX_NB_NAME_LENGTH] = ""; int change = 0; + LANA_ENUM temp_list; + long code; + int i; + + + afsi_log("smb_LanAdapterChange"); + + if (!locked) + lock_ObtainMutex(&smb_StartedLock); + + smb_LanAdapterChangeDetected = 0; if (!powerStateSuspended && SUCCEEDED(lana_GetUncServerNameEx(NetbiosName, &lanaNum, &bGateway, LANA_NETBIOS_NAME_FULL))) { - if (smb_LANadapter != lanaNum || - isGateway != bGateway || - strcmp(cm_NetbiosName, NetbiosName)) + + if ( lanaNum != LANA_INVALID && smb_LANadapter != lanaNum || + isGateway != bGateway || + strcmp(cm_NetbiosName, NetbiosName) ) { change = 1; + } else { + NCB *ncbp = GetNCB(); + ncbp->ncb_command = NCBENUM; + ncbp->ncb_buffer = (PUCHAR)&temp_list; + ncbp->ncb_length = sizeof(temp_list); + code = Netbios(ncbp); + if (code == 0) { + if (temp_list.length != lana_list.length) + change = 1; + else { + for (i=0; i%s<", smb_localNamep); - if (smb_LANadapter == -1) { + if (smb_LANadapter == LANA_INVALID) { ncbp->ncb_command = NCBENUM; ncbp->ncb_buffer = (PUCHAR)&lana_list; ncbp->ncb_length = sizeof(lana_list); @@ -8487,6 +8542,7 @@ int smb_NetbiosInit(void) } } if (code == 0) { + smb_LANadapter = lana; lana_found = 1; /* at least one worked */ } } @@ -8495,7 +8551,7 @@ int smb_NetbiosInit(void) if (!lana_found) { afsi_log("No valid LANA numbers found!"); lana_list.length = 0; - smb_LANadapter = -1; + smb_LANadapter = LANA_INVALID; smb_ListenerState = SMB_LISTENER_STOPPED; cm_VolStatus_Network_Stopped(cm_NetbiosName #ifdef _WIN64 @@ -8507,18 +8563,32 @@ int smb_NetbiosInit(void) /* we're done with the NCB now */ FreeNCB(ncbp); - return ((lana_list.length > 0 && smb_LANadapter != -1) ? 1 : 0); + afsi_log("smb_NetbiosInit smb_LANadapter=%d",smb_LANadapter); + if (lana_list.length > 0) + osi_assert(smb_LANadapter != LANA_INVALID); + + if (!locked) + lock_ReleaseMutex(&smb_StartedLock); + + return (lana_list.length > 0 ? 1 : 0); } -void smb_StartListeners() +void smb_StartListeners(int locked) { int i; int lpid; thread_t phandle; - if (smb_ListenerState == SMB_LISTENER_STARTED) + if (!locked) + lock_ObtainMutex(&smb_StartedLock); + + if (smb_ListenerState == SMB_LISTENER_STARTED) { + if (!locked) + lock_ReleaseMutex(&smb_StartedLock); return; - + } + + afsi_log("smb_StartListeners"); smb_ListenerState = SMB_LISTENER_STARTED; cm_VolStatus_Network_Started(cm_NetbiosName #ifdef _WIN64 @@ -8534,18 +8604,26 @@ void smb_StartListeners() osi_assertx(phandle != NULL, "smb_Listener thread creation failure"); thrd_CloseHandle(phandle); } + if (!locked) + lock_ReleaseMutex(&smb_StartedLock); } -void smb_RestartListeners() +void smb_RestartListeners(int locked) { - if (!powerStateSuspended) { + if (!locked) + lock_ObtainMutex(&smb_StartedLock); + + afsi_log("smb_RestartListeners"); + if (!powerStateSuspended && smb_ListenerState != SMB_LISTENER_UNINITIALIZED) { if (smb_ListenerState == SMB_LISTENER_STOPPED) { - if (smb_NetbiosInit()) - smb_StartListeners(); - } - if (smb_LANadapter == -1) - smb_LanAdapterChange(); + if (smb_NetbiosInit(1)) + smb_StartListeners(1); + } else if (smb_LanAdapterChangeDetected) { + smb_LanAdapterChange(1); + } } + if (!locked) + lock_ReleaseMutex(&smb_StartedLock); } void smb_StopListener(NCB *ncbp, int lana) @@ -8576,14 +8654,21 @@ void smb_StopListener(NCB *ncbp, int lana) } } -void smb_StopListeners(void) +void smb_StopListeners(int locked) { NCB *ncbp; int lana, l; - if (smb_ListenerState == SMB_LISTENER_STOPPED) + if (!locked) + lock_ObtainMutex(&smb_StartedLock); + + if (smb_ListenerState == SMB_LISTENER_STOPPED) { + if (!locked) + lock_ReleaseMutex(&smb_StartedLock); return; + } + afsi_log("smb_StopListeners"); smb_ListenerState = SMB_LISTENER_STOPPED; cm_VolStatus_Network_Stopped(cm_NetbiosName #ifdef _WIN64 @@ -8607,8 +8692,10 @@ void smb_StopListeners(void) /* force a re-evaluation of the network adapters */ lana_list.length = 0; - smb_LANadapter = -1; + smb_LANadapter = LANA_INVALID; FreeNCB(ncbp); + if (!locked) + lock_ReleaseMutex(&smb_StartedLock); Sleep(1000); /* give the listener threads a chance to exit */ } @@ -8624,6 +8711,7 @@ void smb_Init(osi_log_t *logp, int useV3, struct tm myTime; EVENT_HANDLE retHandle; char eventName[MAX_PATH]; + int startListeners = 0; smb_TlsRequestSlot = TlsAlloc(); @@ -8661,6 +8749,7 @@ void smb_Init(osi_log_t *logp, int useV3, lock_InitializeMutex(&smb_RawBufLock, "smb raw buffer lock"); lock_InitializeMutex(&smb_ListenerLock, "smb listener lock"); + lock_InitializeMutex(&smb_StartedLock, "smb started lock"); /* 4 Raw I/O buffers */ smb_RawBufs = calloc(65536,1); @@ -8675,7 +8764,8 @@ void smb_Init(osi_log_t *logp, int useV3, smb_ncbFreeListp = NULL; smb_packetFreeListp = NULL; - smb_NetbiosInit(); + lock_ObtainMutex(&smb_StartedLock); + startListeners = smb_NetbiosInit(1); /* Initialize listener and server structures */ numVCs = 0; @@ -8942,8 +9032,8 @@ void smb_Init(osi_log_t *logp, int useV3, } /* Start listeners, waiters, servers, and daemons */ - - smb_StartListeners(); + if (startListeners) + smb_StartListeners(1); phandle = thrd_Create(NULL, 65536, (ThreadFunc) smb_ClientWaiter, NULL, 0, &lpid, "smb_ClientWaiter"); @@ -8972,6 +9062,7 @@ void smb_Init(osi_log_t *logp, int useV3, osi_assertx(phandle != NULL, "smb_WaitingLocksDaemon thread creation failure"); thrd_CloseHandle(phandle); + lock_ReleaseMutex(&smb_StartedLock); return; } @@ -9250,5 +9341,9 @@ int smb_DumpVCP(FILE *outputFile, char *cookie, int lock) long smb_IsNetworkStarted(void) { - return (smb_ListenerState == SMB_LISTENER_STARTED && smbShutdownFlag == 0); + long rc; + lock_ObtainWrite(&smb_globalLock); + rc = (smb_ListenerState == SMB_LISTENER_STARTED && smbShutdownFlag == 0); + lock_ReleaseWrite(&smb_globalLock); + return rc; } diff --git a/src/WINNT/afsd/smb.h b/src/WINNT/afsd/smb.h index 3a884be..f8f8980 100644 --- a/src/WINNT/afsd/smb.h +++ b/src/WINNT/afsd/smb.h @@ -730,11 +730,13 @@ extern DWORD smb_ServerExceptionFilter(void); extern void smb_UpdateServerPriority(void); extern void smb_SetRequestStartTime(void); extern void smb_ResetServerPriority(void); -extern void smb_RestartListeners(void); -extern void smb_StopListeners(void); +extern void smb_RestartListeners(int); +extern void smb_StopListeners(int); extern void smb_StopListener(NCB *ncbp, int lana); extern long smb_IsNetworkStarted(void); -extern void smb_LanAdapterChange(void); +extern void smb_LanAdapterChange(int); +extern void smb_SetLanAdapterChangeDetected(void); + #define SMB_LISTENER_UNINITIALIZED -1 #define SMB_LISTENER_STOPPED 0 -- 1.9.4