From: VMware, Inc <> Date: Mon, 22 Mar 2010 22:17:37 +0000 (-0700) Subject: Rework the "disksFrozen" hack to be more generic. X-Git-Tag: 2010.03.20-243334~7 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=cb225a952a4c461581ae83c2c03211abbef3c649;p=thirdparty%2Fopen-vm-tools.git Rework the "disksFrozen" hack to be more generic. CS 1010838 added a hack to work around an issue with the Win32 sync driver. The hack is simpler than the more generic solution, which is fine for the release branch it was targeted at, but changing the public plugin API for such things is in general a bad idea. This change implements it so that the current (i.e. before that patch) public API is maintained but the same functionality can be achieved. It requires a little bit more code, though, since it requires creating a new gobject signal to notify of the state change. Signed-off-by: Marcelo Vanzin --- diff --git a/open-vm-tools/lib/include/vmware/tools/plugin.h b/open-vm-tools/lib/include/vmware/tools/plugin.h index 11f3c04e7..cf8e319aa 100644 --- a/open-vm-tools/lib/include/vmware/tools/plugin.h +++ b/open-vm-tools/lib/include/vmware/tools/plugin.h @@ -216,11 +216,6 @@ typedef struct ToolsAppCtx { * register and emit their own signals using this object. */ gpointer serviceObj; - /** - * If this flag is TRUE, it's not safe to access the disk. Code that tries - * to access the disk should avoid running in that case. - */ - gboolean disksFrozen; } ToolsAppCtx; #if defined(G_PLATFORM_WIN32) diff --git a/open-vm-tools/lib/include/vmware/tools/vmbackup.h b/open-vm-tools/lib/include/vmware/tools/vmbackup.h new file mode 100644 index 000000000..8fec44c8a --- /dev/null +++ b/open-vm-tools/lib/include/vmware/tools/vmbackup.h @@ -0,0 +1,43 @@ +/********************************************************* + * Copyright (C) 2010 VMware, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation version 2.1 and no later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + *********************************************************/ + +#ifndef _VMBACKUP_H_ +#define _VMBACKUP_H_ + +/** + * @file vmbackup.h + * + * Public interface of the "vmbackup" plugin. Defines events generated by the + * plugin that other code can monitor. + */ + +/** + * Signal sent when access to disk resources has been affected in some manner + * (e.g., disks have been frozen in preparation for a snapshot). Plugins that + * access the disk should listen for this signal and avoid performing disk + * operations while I/O is frozen. + * + * @param[in] src The source object. + * @param[in] ctx ToolsAppCtx *: The application context. + * @param[in] freeze TRUE if I/O is being frozen, FALSE otherwise. + * @param[in] data Client data. + */ +#define TOOLS_CORE_SIG_IO_FREEZE "tcs_io_freeze" + +#endif /* _VMBACKUP_H_ */ + diff --git a/open-vm-tools/services/plugins/guestInfo/guestInfoServer.c b/open-vm-tools/services/plugins/guestInfo/guestInfoServer.c index 92ad1ef5c..01af2c429 100644 --- a/open-vm-tools/services/plugins/guestInfo/guestInfoServer.c +++ b/open-vm-tools/services/plugins/guestInfo/guestInfoServer.c @@ -57,6 +57,7 @@ #include "vmware/guestrpc/tclodefs.h" #include "vmware/tools/plugin.h" #include "vmware/tools/utils.h" +#include "vmware/tools/vmbackup.h" #if !defined(__APPLE__) #include "embed_version.h" @@ -114,7 +115,7 @@ static Bool SetGuestInfo(ToolsAppCtx *ctx, GuestInfoType key, static Bool DiskInfoChanged(PGuestDiskInfo diskInfo); static void GuestInfoClearCache(void); static GuestNicList *NicInfoV3ToV2(const NicInfoV3 *infoV3); -static void TweakGatherLoop(ToolsAppCtx *ctx); +static void TweakGatherLoop(ToolsAppCtx *ctx, gboolean enable); /** @@ -216,7 +217,32 @@ GuestInfoServerConfReload(gpointer src, ToolsAppCtx *ctx, gpointer data) { - TweakGatherLoop(ctx); + TweakGatherLoop(ctx, TRUE); +} + + +/* + ****************************************************************************** + * GuestInfoServerIOFreeze -- */ /** + * + * IO freeze signal handler. Disables info gathering while I/O is frozen. + * See bug 529653. + * + * @param[in] src The source object. + * @param[in] ctx The application context. + * @param[in] freeze Whether I/O is being frozen. + * @param[in] data Unused. + * + ****************************************************************************** + */ + +static void +GuestInfoServerIOFreeze(gpointer src, + ToolsAppCtx *ctx, + gboolean freeze, + gpointer data) +{ + TweakGatherLoop(ctx, !freeze); } @@ -360,12 +386,6 @@ GuestInfoGather(gpointer data) g_debug("Entered guest info gather.\n"); - /* See bug 529653. */ - if (ctx->disksFrozen) { - g_debug("Skipping guest info gathering while disks are frozen."); - return TRUE; - } - /* Send tools version. */ if (!GuestInfoUpdateVmdb(ctx, INFO_BUILD_NUMBER, BUILD_NUMBER)) { /* @@ -1092,7 +1112,8 @@ NicInfoV3ToV2(const NicInfoV3 *infoV3) * This function is responsible for creating, manipulating, and resetting the * GuestInfoGather loop timeout source. * - * @param[in] ctx The app context. + * @param[in] ctx The app context. + * @param[in] enable Whether to enable the gather loop. * * @sa CONFNAME_GUESTINFO_POLLINTERVAL * @@ -1100,25 +1121,30 @@ NicInfoV3ToV2(const NicInfoV3 *infoV3) */ static void -TweakGatherLoop(ToolsAppCtx *ctx) +TweakGatherLoop(ToolsAppCtx *ctx, + gboolean enable) { GError *gError = NULL; - gint pollInterval = GUESTINFO_TIME_INTERVAL_MSEC; + gint pollInterval = 0; - /* - * Check the config registry for a custom poll interval, converting from - * seconds to milliseconds. - */ - if (g_key_file_has_key(ctx->config, CONFGROUPNAME_GUESTINFO, - CONFNAME_GUESTINFO_POLLINTERVAL, NULL)) { - pollInterval = g_key_file_get_integer(ctx->config, CONFGROUPNAME_GUESTINFO, - CONFNAME_GUESTINFO_POLLINTERVAL, &gError); - pollInterval *= 1000; - - if (pollInterval < 0 || gError) { - g_warning("Invalid %s.%s value. Using default.\n", - CONFGROUPNAME_GUESTINFO, CONFNAME_GUESTINFO_POLLINTERVAL); - pollInterval = GUESTINFO_TIME_INTERVAL_MSEC; + if (enable) { + pollInterval = GUESTINFO_TIME_INTERVAL_MSEC; + + /* + * Check the config registry for a custom poll interval, converting from + * seconds to milliseconds. + */ + if (g_key_file_has_key(ctx->config, CONFGROUPNAME_GUESTINFO, + CONFNAME_GUESTINFO_POLLINTERVAL, NULL)) { + pollInterval = g_key_file_get_integer(ctx->config, CONFGROUPNAME_GUESTINFO, + CONFNAME_GUESTINFO_POLLINTERVAL, &gError); + pollInterval *= 1000; + + if (pollInterval < 0 || gError) { + g_warning("Invalid %s.%s value. Using default.\n", + CONFGROUPNAME_GUESTINFO, CONFNAME_GUESTINFO_POLLINTERVAL); + pollInterval = GUESTINFO_TIME_INTERVAL_MSEC; + } } } @@ -1127,6 +1153,7 @@ TweakGatherLoop(ToolsAppCtx *ctx) * timeout source. */ if (guestInfoPollInterval == pollInterval) { + ASSERT(pollInterval || gatherTimeoutSource == NULL); return; } @@ -1193,6 +1220,7 @@ ToolsOnLoad(ToolsAppCtx *ctx) ToolsPluginSignalCb sigs[] = { { TOOLS_CORE_SIG_CAPABILITIES, GuestInfoServerSendUptime, NULL }, { TOOLS_CORE_SIG_CONF_RELOAD, GuestInfoServerConfReload, NULL }, + { TOOLS_CORE_SIG_IO_FREEZE, GuestInfoServerIOFreeze, NULL }, { TOOLS_CORE_SIG_RESET, GuestInfoServerReset, NULL }, { TOOLS_CORE_SIG_SET_OPTION, GuestInfoServerSetOption, NULL }, { TOOLS_CORE_SIG_SHUTDOWN, GuestInfoServerShutdown, NULL } @@ -1211,7 +1239,7 @@ ToolsOnLoad(ToolsAppCtx *ctx) /* * Set up the GuestInfoGather loop. */ - TweakGatherLoop(ctx); + TweakGatherLoop(ctx, TRUE); return ®Data; } diff --git a/open-vm-tools/services/plugins/vmbackup/Makefile.am b/open-vm-tools/services/plugins/vmbackup/Makefile.am index 0795b60cb..6afc1c452 100644 --- a/open-vm-tools/services/plugins/vmbackup/Makefile.am +++ b/open-vm-tools/services/plugins/vmbackup/Makefile.am @@ -25,10 +25,31 @@ libvmbackup_la_LDFLAGS = libvmbackup_la_LDFLAGS += @PLUGIN_LDFLAGS@ libvmbackup_la_LIBADD = +libvmbackup_la_LIBADD += @GOBJECT_LIBS@ libvmbackup_la_LIBADD += @VMTOOLS_LIBS@ libvmbackup_la_SOURCES = libvmbackup_la_SOURCES += scriptOps.c libvmbackup_la_SOURCES += stateMachine.c libvmbackup_la_SOURCES += syncDriverOps.c +libvmbackup_la_SOURCES += vmBackupSignals.c + +BUILT_SOURCES = +BUILT_SOURCES += vmBackupSignals.c +BUILT_SOURCES += vmBackupSignals.h + +CLEANFILES = +CLEANFILES += vmBackupSignals.c +CLEANFILES += vmBackupSignals.h + +EXTRA_DIST = +EXTRA_DIST += vmBackupSignals.gm + +vmBackupSignals.c: $(top_srcdir)/services/plugins/vmbackup/vmBackupSignals.gm + glib-genmarshal --body $(top_srcdir)/services/plugins/vmbackup/vmBackupSignals.gm > \ + $@ || (rm -f $@ && exit 1) + +vmBackupSignals.h: $(top_srcdir)/services/plugins/vmbackup/vmBackupSignals.gm + glib-genmarshal --header $(top_srcdir)/services/plugins/vmbackup/vmBackupSignals.gm > \ + $@ || (rm -f $@ && exit 1) diff --git a/open-vm-tools/services/plugins/vmbackup/stateMachine.c b/open-vm-tools/services/plugins/vmbackup/stateMachine.c index 6560c6166..3909d5a7c 100644 --- a/open-vm-tools/services/plugins/vmbackup/stateMachine.c +++ b/open-vm-tools/services/plugins/vmbackup/stateMachine.c @@ -35,12 +35,15 @@ #include "vmBackupInt.h" +#include #include #include "guestApp.h" #include "str.h" #include "strutil.h" #include "util.h" +#include "vmBackupSignals.h" #include "vmware/tools/utils.h" +#include "vmware/tools/vmbackup.h" #if !defined(__APPLE__) #include "embed_version.h" @@ -281,7 +284,10 @@ VmBackupOnError(void) /* Next state is "sync error". */ gBackupState->pollPeriod = 1000; gBackupState->machineState = VMBACKUP_MSTATE_SYNC_ERROR; - gBackupState->ctx->disksFrozen = FALSE; + g_signal_emit_by_name(gBackupState->ctx->serviceObj, + TOOLS_CORE_SIG_IO_FREEZE, + gBackupState->ctx, + FALSE); break; case VMBACKUP_MSTATE_SCRIPT_THAW: @@ -446,7 +452,10 @@ VmBackupAsyncCallback(void *clientData) case VMBACKUP_MSTATE_SYNC_THAW: /* Next state is "script thaw". */ - gBackupState->ctx->disksFrozen = FALSE; + g_signal_emit_by_name(gBackupState->ctx->serviceObj, + TOOLS_CORE_SIG_IO_FREEZE, + gBackupState->ctx, + FALSE); if (!VmBackupStartScripts(VMBACKUP_SCRIPT_THAW)) { VmBackupOnError(); } @@ -494,9 +503,15 @@ static Bool VmBackupEnableSync(void) { g_debug("*** %s\n", __FUNCTION__); - gBackupState->ctx->disksFrozen = TRUE; + g_signal_emit_by_name(gBackupState->ctx->serviceObj, + TOOLS_CORE_SIG_IO_FREEZE, + gBackupState->ctx, + TRUE); if (!gSyncProvider->start(gBackupState, gSyncProvider->clientData)) { - gBackupState->ctx->disksFrozen = FALSE; + g_signal_emit_by_name(gBackupState->ctx->serviceObj, + TOOLS_CORE_SIG_IO_FREEZE, + gBackupState->ctx, + FALSE); VmBackup_SendEvent(VMBACKUP_EVENT_REQUESTOR_ERROR, VMBACKUP_SYNC_ERROR, "Error when enabling the sync provider."); @@ -779,6 +794,19 @@ ToolsOnLoad(ToolsAppCtx *ctx) gSyncProvider = provider; regData.regs = VMTools_WrapArray(regs, sizeof *regs, ARRAYSIZE(regs)); + + g_signal_new(TOOLS_CORE_SIG_IO_FREEZE, + G_OBJECT_TYPE(ctx->serviceObj), + 0, + 0, + NULL, + NULL, + g_cclosure_user_marshal_VOID__POINTER_BOOLEAN, + G_TYPE_NONE, + 2, + G_TYPE_POINTER, + G_TYPE_BOOLEAN); + return ®Data; } diff --git a/open-vm-tools/services/plugins/vmbackup/vmBackupSignals.gm b/open-vm-tools/services/plugins/vmbackup/vmBackupSignals.gm new file mode 100644 index 000000000..d456de3c2 --- /dev/null +++ b/open-vm-tools/services/plugins/vmbackup/vmBackupSignals.gm @@ -0,0 +1,29 @@ +########################################################## +# Copyright (C) 2010 VMware, Inc. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation version 2.1 and no later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public +# License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +########################################################## + +## +# @file vmBackupSignals.gm +# +# Defines the custom GClosure marshal functions for the vmbackup signals. +# +# @see plugin.h +# + +# The "io freeze" signal. +VOID:POINTER,BOOLEAN + diff --git a/open-vm-tools/services/vmtoolsd/mainLoop.c b/open-vm-tools/services/vmtoolsd/mainLoop.c index 1f08aec72..c83fa827d 100644 --- a/open-vm-tools/services/vmtoolsd/mainLoop.c +++ b/open-vm-tools/services/vmtoolsd/mainLoop.c @@ -38,7 +38,7 @@ #include "vmcheck.h" #include "vmware/guestrpc/tclodefs.h" #include "vmware/tools/utils.h" - +#include "vmware/tools/vmbackup.h" /* ****************************************************************************** @@ -127,14 +127,38 @@ ToolsCoreInitializeDebug(ToolsServiceState *state) static gboolean ToolsCoreConfFileCb(gpointer clientData) { - ToolsServiceState *state = clientData; - if (!state->ctx.disksFrozen) { - ToolsCore_ReloadConfig(state, FALSE); - } + ToolsCore_ReloadConfig(clientData, FALSE); return TRUE; } +/** + * IO freeze signal handler. Disables the conf file check task if I/O is + * frozen, re-enable it otherwise. See bug 529653. + * + * @param[in] src The source object. + * @param[in] ctx Unused. + * @param[in] freeze Whether I/O is being frozen. + * @param[in] state Service state. + */ + +static void +ToolsCoreIOFreezeCb(gpointer src, + ToolsAppCtx *ctx, + gboolean freeze, + ToolsServiceState *state) +{ + if (state->configCheckTask > 0 && freeze) { + g_source_remove(state->configCheckTask); + state->configCheckTask = 0; + } else if (state->configCheckTask == 0 && !freeze) { + state->configCheckTask = g_timeout_add(CONF_POLL_TIME * 10, + ToolsCoreConfFileCb, + state); + } +} + + /* ****************************************************************************** * ToolsCoreRunLoop -- */ /** @@ -178,7 +202,23 @@ ToolsCoreRunLoop(ToolsServiceState *state) } ToolsCore_RegisterPlugins(state); - g_timeout_add(CONF_POLL_TIME * 10, ToolsCoreConfFileCb, state); + + /* + * Listen for the I/O freeze signal. We have to disable the config file + * check when I/O is frozen or the (Win32) sync driver may cause the service + * to hang (and make the VM unusable until it times out). + */ + if (g_signal_lookup(TOOLS_CORE_SIG_IO_FREEZE, + G_OBJECT_TYPE(state->ctx.serviceObj)) != 0) { + g_signal_connect(state->ctx.serviceObj, + TOOLS_CORE_SIG_IO_FREEZE, + G_CALLBACK(ToolsCoreIOFreezeCb), + state); + } + + state->configCheckTask = g_timeout_add(CONF_POLL_TIME * 10, + ToolsCoreConfFileCb, + state); #if defined(__APPLE__) ToolsCore_CFRunLoop(state); diff --git a/open-vm-tools/services/vmtoolsd/toolsCoreInt.h b/open-vm-tools/services/vmtoolsd/toolsCoreInt.h index d59d3f40d..aba4fa5a6 100644 --- a/open-vm-tools/services/vmtoolsd/toolsCoreInt.h +++ b/open-vm-tools/services/vmtoolsd/toolsCoreInt.h @@ -76,6 +76,7 @@ typedef struct ToolsServiceState { gchar *name; gchar *configFile; time_t configMtime; + guint configCheckTask; gboolean log; gboolean mainService; gchar *commonPath;