mirror of
https://git.openafs.org/openafs.git
synced 2025-01-21 00:10:15 +00:00
win-power-mgmt-flush-test-20041003
The windows power management code responds to a request to suspend or hibernate by performing a "fs flushvol" as the logged in user on each of the SMB/CIFS mounted shares. This can be very time consuming if the cell servers cannot be reached. This patch adds a test to ensure that there is at least one network adapter in the machine which is not a loopback adapter. While developing this patch other areas of concern have been raised. The power management code waits a fixed period of time based upon the hard dead timeout before allowing the suspend/hibernate to continue. This allows the machine to shutdown even if there are active flush operations being performed. This defeats the benefit of performing the flush at all. A better mechanism could be developed if the functions called via cm_IoctlFlushVolume returned and checked error codes. Then it might be possible to abandon the flush operation if a Server Not Reachable state was obtained. The power management flush operations will also not work on Terminal Server. This would be important in the case where a terminal server is shutting down due to a switch over to a UPS. The reason it does not work on Terminal Server is that there is that it is not possible for afsd_service.exe to enumerate the SMB/CIFS shares and impersonate the individual logged in users. It would be preferred for there to be a new cm_FlushAll() function implemented which was not dependent on the use of the ioctl mechanism for the purpose of identifying a volume ID or a user ID.
This commit is contained in:
parent
3f2e943d43
commit
2469663d0d
@ -27,6 +27,9 @@
|
|||||||
|
|
||||||
#include "afsd_flushvol.h"
|
#include "afsd_flushvol.h"
|
||||||
#include "afsd_eventlog.h"
|
#include "afsd_eventlog.h"
|
||||||
|
#include "lanahelper.h"
|
||||||
|
|
||||||
|
extern void afsi_log(char *pattern, ...);
|
||||||
|
|
||||||
static FLUSHVOLTHREADINFO gThreadInfo = {0};
|
static FLUSHVOLTHREADINFO gThreadInfo = {0};
|
||||||
static HANDLE gThreadHandle = NULL;
|
static HANDLE gThreadHandle = NULL;
|
||||||
@ -48,6 +51,7 @@ afsd_ServicePerformFlushVolumeCmd(char *data)
|
|||||||
register afs_int32 code;
|
register afs_int32 code;
|
||||||
struct ViceIoctl blob;
|
struct ViceIoctl blob;
|
||||||
|
|
||||||
|
afsi_log("Flushing Volume \"%s\"",data);
|
||||||
memset(&blob, '\0', sizeof(blob));
|
memset(&blob, '\0', sizeof(blob));
|
||||||
code = pioctl(data, VIOC_FLUSHVOLUME, &blob, 0);
|
code = pioctl(data, VIOC_FLUSHVOLUME, &blob, 0);
|
||||||
|
|
||||||
@ -74,6 +78,11 @@ afsd_ServicePerformFlushVolumes()
|
|||||||
PCHAR pszShareName, pc;
|
PCHAR pszShareName, pc;
|
||||||
afs_int32 afsRet = 0;
|
afs_int32 afsRet = 0;
|
||||||
|
|
||||||
|
if ( lana_OnlyLoopback() ) {
|
||||||
|
// Nothing to do if we only have a loopback interface
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
// Determine the root share name (\\AFS\ALL or \\<machine>-AFS\ALL),
|
// Determine the root share name (\\AFS\ALL or \\<machine>-AFS\ALL),
|
||||||
// and the length of the server name prefix.
|
// and the length of the server name prefix.
|
||||||
pszShareName = smb_GetSharename();
|
pszShareName = smb_GetSharename();
|
||||||
@ -143,8 +152,7 @@ afsd_ServicePerformFlushVolumes()
|
|||||||
{
|
{
|
||||||
// got one!
|
// got one!
|
||||||
// but we don't want to flush '\\[...]afs\all'
|
// but we don't want to flush '\\[...]afs\all'
|
||||||
if (_stricmp(lpnr->lpRemoteName,
|
if (_stricmp(lpnr->lpRemoteName, pszShareName) == 0)
|
||||||
pszShareName) == 0)
|
|
||||||
continue;
|
continue;
|
||||||
++dwTotalVols;
|
++dwTotalVols;
|
||||||
|
|
||||||
|
@ -32,7 +32,8 @@
|
|||||||
// The following is defined if you want to receive Power notifications,
|
// The following is defined if you want to receive Power notifications,
|
||||||
// including Hibernation, and also subsequent flushing of AFS volumes
|
// including Hibernation, and also subsequent flushing of AFS volumes
|
||||||
//
|
//
|
||||||
#define REGISTER_POWER_NOTIFICATIONS
|
#define REGISTER_POWER_NOTIFICATIONS 1
|
||||||
|
#define FLUSH_VOLUME 1
|
||||||
//
|
//
|
||||||
// Check
|
// Check
|
||||||
*/
|
*/
|
||||||
@ -130,7 +131,6 @@ afsd_ServiceFlushVolume(DWORD dwlpEventData)
|
|||||||
{
|
{
|
||||||
dwRet = NO_ERROR;
|
dwRet = NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* flush was unsuccessful, or timeout - deny shutdown */
|
/* flush was unsuccessful, or timeout - deny shutdown */
|
||||||
@ -177,7 +177,7 @@ afsd_ServiceControlHandler(DWORD ctrlCode)
|
|||||||
if (doTrace)
|
if (doTrace)
|
||||||
afsd_ForceTrace(FALSE);
|
afsd_ForceTrace(FALSE);
|
||||||
|
|
||||||
doneTrace:
|
doneTrace:
|
||||||
ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
|
ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
|
||||||
ServiceStatus.dwWin32ExitCode = NO_ERROR;
|
ServiceStatus.dwWin32ExitCode = NO_ERROR;
|
||||||
ServiceStatus.dwCheckPoint = 1;
|
ServiceStatus.dwCheckPoint = 1;
|
||||||
@ -276,7 +276,7 @@ afsd_ServiceControlHandlerEx(
|
|||||||
case PBT_APMQUERYSUSPEND:
|
case PBT_APMQUERYSUSPEND:
|
||||||
case PBT_APMQUERYSTANDBY:
|
case PBT_APMQUERYSTANDBY:
|
||||||
|
|
||||||
#ifdef REGISTER_POWER_NOTIFICATIONS
|
#ifdef FLUSH_VOLUME
|
||||||
/* handle event */
|
/* handle event */
|
||||||
dwRet = afsd_ServiceFlushVolume((DWORD) lpEventData);
|
dwRet = afsd_ServiceFlushVolume((DWORD) lpEventData);
|
||||||
#else
|
#else
|
||||||
|
@ -394,6 +394,35 @@ extern "C" lana_number_t lana_FindLoopback(void)
|
|||||||
return LANA_INVALID;
|
return LANA_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Returns TRUE if all adapters are loopback adapters */
|
||||||
|
extern "C" BOOL lana_OnlyLoopback(void)
|
||||||
|
{
|
||||||
|
NCB ncb;
|
||||||
|
LANA_ENUM lana_list;
|
||||||
|
int status;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
memset(&ncb, 0, sizeof(ncb));
|
||||||
|
ncb.ncb_command = NCBENUM;
|
||||||
|
ncb.ncb_buffer = (UCHAR *) &lana_list;
|
||||||
|
ncb.ncb_length = sizeof(lana_list);
|
||||||
|
status = Netbios(&ncb);
|
||||||
|
if (status != 0) {
|
||||||
|
#ifndef NOLOGGING
|
||||||
|
afsi_log("Netbios NCBENUM failed: status %ld", status);
|
||||||
|
#endif
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
for (i = 0; i < lana_list.length; i++) {
|
||||||
|
if (!lana_IsLoopback(lana_list.lana[i])) {
|
||||||
|
// Found one non-Loopback adapter
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// All adapters are loopback
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
// Is the given lana a Windows Loopback Adapter?
|
// Is the given lana a Windows Loopback Adapter?
|
||||||
// TODO: implement a better check for loopback
|
// TODO: implement a better check for loopback
|
||||||
// TODO: also check for proper bindings (IPv4)
|
// TODO: also check for proper bindings (IPv4)
|
||||||
|
@ -59,6 +59,8 @@ extern "C" {
|
|||||||
|
|
||||||
lana_number_t lana_FindLoopback(void);
|
lana_number_t lana_FindLoopback(void);
|
||||||
|
|
||||||
|
BOOL lana_OnlyLoopback(void);
|
||||||
|
|
||||||
BOOL lana_IsLoopback(lana_number_t lana);
|
BOOL lana_IsLoopback(lana_number_t lana);
|
||||||
|
|
||||||
long lana_GetUncServerNameEx(char *buffer, lana_number_t * pLana, int * pIsGateway, int flags);
|
long lana_GetUncServerNameEx(char *buffer, lana_number_t * pLana, int * pIsGateway, int flags);
|
||||||
|
Loading…
Reference in New Issue
Block a user