From 41d145b303d61aa6f8f336e4d66748dea860d08f Mon Sep 17 00:00:00 2001 From: Jeffrey Altman Date: Fri, 9 Dec 2011 18:40:42 -0500 Subject: [PATCH] Windows: Suspend/Resume for afsd_service The power mgmt events are received in the service. The service can block all requests from the redirector from being processed until it knows that it is safe to process them. The service will receive a SERVICE_CONTROL_APMSUSPEND just before the system goes to sleep. The service has two seconds to respond and it uses that time to attempt to send RXAFS_GiveUpAllCallBacks to all file servers as an rx_multi with no wait. It also marks all servers down and updates the callback expirations to be just after the servers were marked down so that they will be forced to be refreshed when the server is marked up. Upon resume the service receives two events. First, SERVICE_CONTROL_APMRESUMEAUTOMATIC which is used to perform an SMB lan adapter change detection and perform a probe of all down servers. The second, SERVICE_CONTROL_APMRESUMESUSPEND is used to resume SMB listeners, perform a 2nd lan adapter change check (just in case), check the status of all down servers in additional networks have come up, and finally resume processing of redirector requests. With these changes no special logic in the redirector is required. Change-Id: I5405ecab754dca04f34afb024c4dacc3fe089088 Reviewed-on: http://gerrit.openafs.org/6243 Tested-by: BuildBot Reviewed-by: Jeffrey Altman Tested-by: Jeffrey Altman --- src/WINNT/afsd/afsd_service.c | 83 +++++++++++++++++---- src/WINNT/afsrdr/common/AFSUserPrototypes.h | 4 + src/WINNT/afsrdr/user/RDRInit.cpp | 22 ++++++ 3 files changed, 96 insertions(+), 13 deletions(-) diff --git a/src/WINNT/afsd/afsd_service.c b/src/WINNT/afsd/afsd_service.c index 7118a905c..817b03187 100644 --- a/src/WINNT/afsd/afsd_service.c +++ b/src/WINNT/afsd/afsd_service.c @@ -1,3 +1,11 @@ +/* + * Copyright 2000, International Business Machines Corporation and others. + * All Rights Reserved. + * + * This software has been released under the terms of the IBM Public + * License. For details, see the LICENSE file in the top-level source + * directory or online at http://www.openafs.org/dl/license10.html + */ #include #include @@ -309,6 +317,7 @@ afsd_ServiceControlHandlerEx( ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT; SetServiceStatus(StatusHandle, &ServiceStatus); afsi_log("SERVICE_CONTROL_INTERROGATE"); + osi_Log0(afsd_logp, "SERVICE_CONTROL_INTERROGATE"); dwRet = NO_ERROR; break; @@ -319,6 +328,7 @@ afsd_ServiceControlHandlerEx( #ifdef DEBUG afsi_log("SERVICE_CONTROL_POWEREVENT"); #endif + osi_Log0(afsd_logp, "SERVICE_CONTROL_POWEREVENT"); /* ** dwEventType of this notification == WPARAM of WM_POWERBROADCAST ** Return NO_ERROR == return TRUE for that message, i.e. accept request @@ -330,87 +340,134 @@ afsd_ServiceControlHandlerEx( { case PBT_APMQUERYSUSPEND: afsi_log("SERVICE_CONTROL_APMQUERYSUSPEND"); + osi_Log0(afsd_logp,"SERVICE_CONTROL_APMQUERYSUSPEND"); /* Write all dirty buffers back to server */ - if ( !lana_OnlyLoopback() ) { + if ( !lana_OnlyLoopback() ) buf_CleanAndReset(); - cm_SuspendSCache(); - } afsi_log("SERVICE_CONTROL_APMQUERYSUSPEND buf_CleanAndReset complete"); + osi_Log0(afsd_logp,"SERVICE_CONTROL_APMQUERYSUSPEND buf_CleanAndReset complete"); dwRet = NO_ERROR; break; case PBT_APMQUERYSTANDBY: afsi_log("SERVICE_CONTROL_APMQUERYSTANDBY"); + osi_Log0(afsd_logp,"SERVICE_CONTROL_APMQUERYSTANDBY"); /* Write all dirty buffers back to server */ - if ( !lana_OnlyLoopback() ) { + if ( !lana_OnlyLoopback() ) buf_CleanAndReset(); - cm_SuspendSCache(); - } afsi_log("SERVICE_CONTROL_APMQUERYSTANDBY buf_CleanAndReset complete"); + osi_Log0(afsd_logp,"SERVICE_CONTROL_APMQUERYSTANDBY buf_CleanAndReset complete"); dwRet = NO_ERROR; break; /* allow remaining case PBT_WhatEver */ case PBT_APMSUSPEND: afsi_log("SERVICE_CONTROL_APMSUSPEND"); + osi_Log0(afsd_logp,"SERVICE_CONTROL_APMSUSPEND"); powerStateSuspended = 1; - if (osVersion.dwMajorVersion >= 6) { - cm_SuspendSCache(); + if (osVersion.dwMajorVersion >= 6) smb_StopListeners(0); - } + + if (RDR_Initialized) + RDR_Suspend(); + cm_SuspendSCache(); + dwRet = NO_ERROR; + afsi_log("SERVICE_CONTROL_APMSUSPEND complete"); + osi_Log0(afsd_logp,"SERVICE_CONTROL_APMSUSPEND complete"); break; case PBT_APMSTANDBY: afsi_log("SERVICE_CONTROL_APMSTANDBY"); + osi_Log0(afsd_logp,"SERVICE_CONTROL_APMSTANDBY"); powerStateSuspended = 1; - if (osVersion.dwMajorVersion >= 6) { - cm_SuspendSCache(); + if (osVersion.dwMajorVersion >= 6) smb_StopListeners(0); - } + if (RDR_Initialized) + RDR_Suspend(); + cm_SuspendSCache(); dwRet = NO_ERROR; + afsi_log("SERVICE_CONTROL_APMSTANDBY complete"); + osi_Log0(afsd_logp,"SERVICE_CONTROL_APMSTANDBY complete"); break; case PBT_APMRESUMECRITICAL: afsi_log("SERVICE_CONTROL_APMRESUMECRITICAL"); + osi_Log0(afsd_logp,"SERVICE_CONTROL_APMRESUMECRITICAL"); if (osVersion.dwMajorVersion >= 6) smb_RestartListeners(0); + cm_CheckServers(CM_FLAG_CHECKDOWNSERVERS, NULL); + if (RDR_Initialized) + RDR_Resume(); dwRet = NO_ERROR; + afsi_log("SERVICE_CONTROL_APMRESUMECRITICAL complete"); + osi_Log0(afsd_logp,"SERVICE_CONTROL_APMRESUMECRITICAL complete"); break; case PBT_APMRESUMESUSPEND: /* User logged in after suspend */ afsi_log("SERVICE_CONTROL_APMRESUMESUSPEND"); + osi_Log0(afsd_logp,"SERVICE_CONTROL_APMRESUMESUSPEND"); + powerStateSuspended = 0; + cm_CheckServers(CM_FLAG_CHECKDOWNSERVERS, NULL); + if (osVersion.dwMajorVersion >= 6) + smb_RestartListeners(0); + if (smb_Enabled && osVersion.dwMajorVersion >= 6) { + smb_SetLanAdapterChangeDetected(); + } + if (RDR_Initialized) + RDR_Resume(); dwRet = NO_ERROR; + afsi_log("SERVICE_CONTROL_APMRESUMESUSPEND complete"); + osi_Log0(afsd_logp,"SERVICE_CONTROL_APMRESUMESUSPEND complete"); break; case PBT_APMRESUMESTANDBY: /* User logged in after standby */ afsi_log("SERVICE_CONTROL_APMRESUMESTANDBY"); + osi_Log0(afsd_logp,"SERVICE_CONTROL_APMRESUMESTANDBY"); + powerStateSuspended = 0; + cm_CheckServers(CM_FLAG_CHECKDOWNSERVERS, NULL); + if (osVersion.dwMajorVersion >= 6) + smb_RestartListeners(0); + if (smb_Enabled && osVersion.dwMajorVersion >= 6) { + smb_SetLanAdapterChangeDetected(); + } + if (RDR_Initialized) + RDR_Resume(); dwRet = NO_ERROR; + afsi_log("SERVICE_CONTROL_APMRESUMESTANDBY complete"); + osi_Log0(afsd_logp,"SERVICE_CONTROL_APMRESUMESTANDBY complete"); break; case PBT_APMBATTERYLOW: afsi_log("SERVICE_CONTROL_APMBATTERYLOW"); + osi_Log0(afsd_logp,"SERVICE_CONTROL_APMBATTERYLOW"); dwRet = NO_ERROR; break; case PBT_APMPOWERSTATUSCHANGE: #ifdef DEBUG afsi_log("SERVICE_CONTROL_APMPOWERSTATUSCHANGE"); #endif + osi_Log0(afsd_logp,"SERVICE_CONTROL_APMPOWERSTATUSCHANGE"); dwRet = NO_ERROR; break; case PBT_APMOEMEVENT: #ifdef DEBUG afsi_log("SERVICE_CONTROL_APMOEMEVENT"); #endif + osi_Log0(afsd_logp,"SERVICE_CONTROL_APMOEMEVENT"); dwRet = NO_ERROR; break; case PBT_APMRESUMEAUTOMATIC: /* This is the message delivered once all devices are up */ afsi_log("SERVICE_CONTROL_APMRESUMEAUTOMATIC"); - powerStateSuspended = 0; + osi_Log0(afsd_logp,"SERVICE_CONTROL_APMRESUMEAUTOMATIC"); if (smb_Enabled && osVersion.dwMajorVersion >= 6) { smb_SetLanAdapterChangeDetected(); } + cm_CheckServers(CM_FLAG_CHECKDOWNSERVERS, NULL); dwRet = NO_ERROR; + afsi_log("SERVICE_CONTROL_APMRESUMEAUTOMATIC complete"); + osi_Log0(afsd_logp,"SERVICE_CONTROL_APMRESUMEAUTOMATIC complete"); break; default: afsi_log("SERVICE_CONTROL_unknown"); + osi_Log1(afsd_logp, "SERVICE_CONTROL_unknown: 0x%x", dwEventType); dwRet = NO_ERROR; } } diff --git a/src/WINNT/afsrdr/common/AFSUserPrototypes.h b/src/WINNT/afsrdr/common/AFSUserPrototypes.h index d3a26685a..9e29eaae6 100644 --- a/src/WINNT/afsrdr/common/AFSUserPrototypes.h +++ b/src/WINNT/afsrdr/common/AFSUserPrototypes.h @@ -62,3 +62,7 @@ RDR_SysName(ULONG Architecture, ULONG Count, WCHAR **NameList); extern afs_int32 RDR_BkgFetch(cm_scache_t *scp, afs_uint32 p1, afs_uint32 p2, afs_uint32 p3, afs_uint32 p4, cm_user_t *userp, cm_req_t *reqp); + +extern VOID RDR_Suspend( void); + +extern VOID RDR_Resume( void); diff --git a/src/WINNT/afsrdr/user/RDRInit.cpp b/src/WINNT/afsrdr/user/RDRInit.cpp index 91e178e2d..37a30d810 100644 --- a/src/WINNT/afsrdr/user/RDRInit.cpp +++ b/src/WINNT/afsrdr/user/RDRInit.cpp @@ -115,6 +115,8 @@ DWORD dwOvEvIdx = 0; extern "C" wchar_t RDR_UNCName[64]=L"AFS"; +HANDLE RDR_SuspendEvent = INVALID_HANDLE_VALUE; + /* returns 0 on success */ extern "C" DWORD RDR_Initialize(void) @@ -125,6 +127,12 @@ RDR_Initialize(void) DWORD dummyLen; DWORD numSvThreads = CM_CONFIGDEFAULT_SVTHREADS; + // Initialize the Suspend Event + RDR_SuspendEvent = CreateEvent( NULL, + TRUE, // manual reset event + TRUE, // signaled + NULL); + dwRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY, 0, KEY_QUERY_VALUE, &parmKey); if (dwRet == ERROR_SUCCESS) { @@ -469,6 +477,8 @@ RDR_RequestWorkerThread( LPVOID lpParameter) break; } + WaitForSingleObject( RDR_SuspendEvent, INFINITE); + // // Go process the request // @@ -2054,3 +2064,15 @@ RDR_SysName(ULONG Architecture, ULONG Count, WCHAR **NameList) return rc; } + +extern "C" VOID +RDR_Suspend( VOID) +{ + ResetEvent( RDR_SuspendEvent); +} + +extern "C" VOID +RDR_Resume( VOID) +{ + SetEvent( RDR_SuspendEvent); +} -- 2.39.5