* 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)
--- /dev/null
+/*********************************************************
+ * 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_ */
+
#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"
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);
/**
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);
}
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)) {
/*
* 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
*
*/
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;
+ }
}
}
* timeout source.
*/
if (guestInfoPollInterval == pollInterval) {
+ ASSERT(pollInterval || gatherTimeoutSource == NULL);
return;
}
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 }
/*
* Set up the GuestInfoGather loop.
*/
- TweakGatherLoop(ctx);
+ TweakGatherLoop(ctx, TRUE);
return ®Data;
}
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)
#include "vmBackupInt.h"
+#include <glib-object.h>
#include <gmodule.h>
#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"
/* 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:
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();
}
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.");
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;
}
--- /dev/null
+##########################################################
+# 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
+
#include "vmcheck.h"
#include "vmware/guestrpc/tclodefs.h"
#include "vmware/tools/utils.h"
-
+#include "vmware/tools/vmbackup.h"
/*
******************************************************************************
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 -- */ /**
}
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);
gchar *name;
gchar *configFile;
time_t configMtime;
+ guint configCheckTask;
gboolean log;
gboolean mainService;
gchar *commonPath;