Windows: Suspend/Resume for afsd_service
authorJeffrey Altman <jaltman@your-file-system.com>
Fri, 9 Dec 2011 23:40:42 +0000 (18:40 -0500)
committerJeffrey Altman <jaltman@secure-endpoints.com>
Sat, 10 Dec 2011 14:44:32 +0000 (06:44 -0800)
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 <buildbot@rampaginggeek.com>
Reviewed-by: Jeffrey Altman <jaltman@secure-endpoints.com>
Tested-by: Jeffrey Altman <jaltman@secure-endpoints.com>

src/WINNT/afsd/afsd_service.c
src/WINNT/afsrdr/common/AFSUserPrototypes.h
src/WINNT/afsrdr/user/RDRInit.cpp

index 7118a90..817b031 100644 (file)
@@ -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 <afsconfig.h>
 #include <afs/param.h>
@@ -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;
                 }
             }
index d3a2668..9e29eaa 100644 (file)
@@ -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);
index 91e178e..37a30d8 100644 (file)
@@ -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);
+}