]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
Rework the "disksFrozen" hack to be more generic.
authorVMware, Inc <>
Mon, 22 Mar 2010 22:17:37 +0000 (15:17 -0700)
committerMarcelo Vanzin <mvanzin@vmware.com>
Mon, 22 Mar 2010 22:17:37 +0000 (15:17 -0700)
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 <mvanzin@vmware.com>
open-vm-tools/lib/include/vmware/tools/plugin.h
open-vm-tools/lib/include/vmware/tools/vmbackup.h [new file with mode: 0644]
open-vm-tools/services/plugins/guestInfo/guestInfoServer.c
open-vm-tools/services/plugins/vmbackup/Makefile.am
open-vm-tools/services/plugins/vmbackup/stateMachine.c
open-vm-tools/services/plugins/vmbackup/vmBackupSignals.gm [new file with mode: 0644]
open-vm-tools/services/vmtoolsd/mainLoop.c
open-vm-tools/services/vmtoolsd/toolsCoreInt.h

index 11f3c04e74e149cbeb28d5e0c282236a931cc056..cf8e319aa37239e86c262e90a0dbbf3ced654f67 100644 (file)
@@ -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 (file)
index 0000000..8fec44c
--- /dev/null
@@ -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_ */
+
index 92ad1ef5c126f58aa82b22f39e59ac39b5048de8..01af2c4297244c4537628d0d25f9152518cb45d9 100644 (file)
@@ -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 &regData;
    }
index 0795b60cbf2cff7f7ac95304b72032856d3fa609..6afc1c452425c5ec5c09fdb7f192b9e15849015d 100644 (file)
@@ -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)
 
index 6560c61664e86809204ed9427ac4c3de66b6e9df..3909d5a7c99d8540ce05a7a700f899c049266495 100644 (file)
 
 #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"
@@ -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 &regData;
    }
 
diff --git a/open-vm-tools/services/plugins/vmbackup/vmBackupSignals.gm b/open-vm-tools/services/plugins/vmbackup/vmBackupSignals.gm
new file mode 100644 (file)
index 0000000..d456de3
--- /dev/null
@@ -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
+
index 1f08aec7229d76198cdf4f6b5d17eef410b1c9c8..c83fa827db9fa5e17eff3810ab8b4791c1a11661 100644 (file)
@@ -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);
index d59d3f40d853edfe9265fe6a3ed755d2c99a2fa7..aba4fa5a606584345ada1e77ad0c55f9686370a6 100644 (file)
@@ -76,6 +76,7 @@ typedef struct ToolsServiceState {
    gchar         *name;
    gchar         *configFile;
    time_t         configMtime;
+   guint          configCheckTask;
    gboolean       log;
    gboolean       mainService;
    gchar         *commonPath;