]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
Skip specified file systems when doing a quiesced snapshot on Linux
authorOliver Kurth <okurth@vmware.com>
Mon, 26 Feb 2018 20:35:36 +0000 (12:35 -0800)
committerOliver Kurth <okurth@vmware.com>
Mon, 26 Feb 2018 20:35:36 +0000 (12:35 -0800)
Add a tools.conf setting "excludedFileSystems" that specifies one or
more file system mount points to be skipped over when performing a
quiesced snapshot on Linux guests.  The value of excludedFileSystems
is a comma-separated list of glob-style patterns as recognized by the
glib routines described here:

https://developer.gnome.org/glib/stable/glib-Glob-style-pattern-matching.html

With this change, when performing a quiesced snapshot, the sync driver
freeze routine removes from the list of mount points it is to process
any path that matches a pattern in the excludedFileSystems list.

In the course of testing the change, a bug was found in SyncDriverFreeze
in which it returned SD_ERROR rather than FALSE when the path list is
empty.

This change also includes some whitespace cleanup in syncDriverWin32.c.

open-vm-tools/lib/include/syncDriver.h
open-vm-tools/lib/syncDriver/syncDriverPosix.c
open-vm-tools/services/plugins/vix/foundryToolsDaemon.c
open-vm-tools/services/plugins/vmbackup/stateMachine.c
open-vm-tools/services/plugins/vmbackup/syncDriverOps.c
open-vm-tools/services/plugins/vmbackup/vmBackupInt.h

index 4cb71b491ae1ceda46fc4a854dc0a2a3b6322bf3..20712f66a0bdd120545afe21a1f0d720926dc18c 100644 (file)
@@ -1,5 +1,5 @@
 /*********************************************************
- * Copyright (C) 2005-2017 VMware, Inc. All rights reserved.
+ * Copyright (C) 2005-2018 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
@@ -50,7 +50,8 @@ typedef enum {
 
 Bool SyncDriver_Init(void);
 Bool SyncDriver_Freeze(const char *drives, Bool enableNullDriver,
-                       SyncDriverHandle *handle);
+                       SyncDriverHandle *handle,
+                       const char *excludedFileSystems);
 Bool SyncDriver_Thaw(const SyncDriverHandle handle);
 SyncDriverStatus SyncDriver_QueryStatus(const SyncDriverHandle handle,
                                         int32 timeout);
index f66ca8026c88e23c56693f60e87946d1450bd984..839cb6dd986ae4b8d5e683c1a16582c484842f86 100644 (file)
@@ -64,16 +64,22 @@ static RemoteDevPrefix gRemoteDevPrefixes[] = {
 
 #undef DEF_DEV_PREFIX
 
+/* Cached value of excludedFileSystems */
+static char *gExcludedFileSystems = NULL;
+
+/* Array of path patterns parsed and compiled from gExcludedFileSystems */
+static GPtrArray *gExcludedPathPatterns = NULL;
+
 
 /*
  *-----------------------------------------------------------------------------
  *
  * SyncDriverIsRemoteFS  --
  *
- *    Checks whether a filesystem is remote or not
+ *    Checks whether a file system is remote or not
  *
  * Results:
- *    Returns TRUE for remote filesystem types or device names,
+ *    Returns TRUE for remote file system types or device names,
  *    otherwise FALSE.
  *
  * Side effects:
@@ -149,7 +155,7 @@ SyncDriverLocalMounts(void)
        * could lead to hangs. See PR 1196785.
        */
       if (SyncDriverIsRemoteFS(mntinfo)) {
-         Debug(LGPFX "Skipping remote filesystem, name=%s, mntpt=%s.\n",
+         Debug(LGPFX "Skipping remote file system, name=%s, mntpt=%s.\n",
                MNTINFO_NAME(mntinfo), MNTINFO_MNTPT(mntinfo));
          continue;
       }
@@ -221,6 +227,178 @@ SyncDriverFreePath(gpointer data, gpointer userData)
 }
 
 
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * SyncDriverUpdateExcludedFS --
+ *
+ *    Update the excluded file system list and compile the path patterns.
+ *
+ * Results:
+ *    None
+ *
+ * Side effects:
+ *    None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static void
+SyncDriverUpdateExcludedFS(const char *excludedFS)    // IN
+{
+   gchar **patterns = NULL;
+   int i;
+
+   ASSERT((gExcludedFileSystems == NULL && gExcludedPathPatterns == NULL) ||
+          (gExcludedFileSystems != NULL && gExcludedPathPatterns != NULL));
+
+   /*
+    * Passing a NULL pointer to g_ptr_array_free appears to result in
+    * a glib assert array, hence this test.  As per the above assert,
+    * either both of gExcludedFileSystems and gExcludedPathPatterns
+    * are NULL or both aren't.
+    */
+   if (gExcludedPathPatterns != NULL) {
+      /*
+       * Free the data but don't set the pointers to anything here because
+       * they're about to get new assignments below.
+       */
+      g_free(gExcludedFileSystems);
+      g_ptr_array_free(gExcludedPathPatterns, TRUE);
+   }
+
+   if (excludedFS == NULL) {
+      Debug(LGPFX "Set the excluded file system list to (null).\n");
+      gExcludedFileSystems = NULL;
+      gExcludedPathPatterns = NULL;
+      return;
+   }
+
+   Debug(LGPFX "Set the excluded file system list to \"%s\".\n", excludedFS);
+
+   gExcludedFileSystems = g_strdup(excludedFS);
+   gExcludedPathPatterns =
+         g_ptr_array_new_with_free_func((GDestroyNotify) &g_pattern_spec_free);
+
+   patterns = g_strsplit(gExcludedFileSystems, ",", 0);
+
+   for (i = 0; patterns[i] != NULL; ++i) {
+      if (patterns[i][0] != '\0') {
+         g_ptr_array_add(gExcludedPathPatterns,
+                         g_pattern_spec_new(patterns[i]));
+      }
+   }
+
+   g_strfreev(patterns);
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * SyncDriverIsExcludedFS --
+ *
+ *    See whether a given path (mount point) matches any of the
+ *    file systems to be excluded.
+ *
+ *    Assumes that the caller has verified that the excluded file
+ *    system list is non-empty.
+ *
+ * Results:
+ *    TRUE if the path matches at least one of the excluded path patterns
+ *    FALSE no matches found
+ *
+ * Side effects:
+ *    None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static Bool
+SyncDriverIsExcludedFS(const char *path)                 // IN
+{
+   int i;
+
+   ASSERT(gExcludedFileSystems != NULL && gExcludedPathPatterns != NULL);
+   ASSERT(path != NULL);
+
+   for (i = 0; i < gExcludedPathPatterns->len; ++i) {
+      if (g_pattern_match_string(g_ptr_array_index(gExcludedPathPatterns, i),
+                                 path)) {
+         return TRUE;
+      }
+   }
+   return FALSE;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * SyncDriverFilterFS
+ *
+ *    Remove a specified list of file systems from a list of paths.  The
+ *    parameter excludedFS is a string containing a comma-separated
+ *    list of patterns describing file systems that are to be excluded
+ *    from the the quiescing operation.  The patterns specify the paths
+ *    of file system mount points.  This routine removes from pathlist
+ *    any paths that match one or more patterns specified in excludedFS.
+ *
+ * Results:
+ *    Modified path list with all paths matching excludedFS removed.
+ *
+ * Side effects:
+ *    Calls other routines that modify the global variables
+ *    gExcludedFileSystems and gExcludedPathPatterns, which cache the
+ *    information in excludedFS.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+GSList *
+SyncDriverFilterFS(GSList *pathlist,             // IN / OUT
+                   const char *excludedFS)       // IN
+{
+   GSList *current;
+
+   /*
+    * Update the excluded file system list if excludedFS has changed.
+    */
+   if (g_strcmp0(excludedFS, gExcludedFileSystems) != 0) {
+      SyncDriverUpdateExcludedFS(excludedFS);
+   } else {
+      Debug(LGPFX "Leave the excluded file system list as \"%s\".\n",
+         (excludedFS != NULL) ? excludedFS : "(null)");
+   }
+
+   /*
+    * If the excluded file system list is empty, return the path list as is.
+    */
+   if (gExcludedFileSystems == NULL) {
+      return pathlist;
+   }
+
+   /*
+    * Traverse the path list, removing all file systems that should be
+    * excluded.
+    */
+   current = pathlist;
+   while (current != NULL) {
+      GSList *next = g_slist_next(current);
+      char *path = (char *) current->data;
+
+      if (SyncDriverIsExcludedFS(path)) {
+         Debug(LGPFX "Excluding file system, name=%s\n", path);
+         pathlist = g_slist_delete_link(pathlist, current);
+         free(path);
+      }
+      current = next;
+   }
+
+   return pathlist;
+}
+
+
 /*
  *-----------------------------------------------------------------------------
  *
@@ -232,6 +410,10 @@ SyncDriverFreePath(gpointer data, gpointer userData)
  *    clients should still call SyncDriver_QueryStatus to maintain future
  *    compatibility in case that changes.
  *
+ *    excludedFileSystems is the value of the tools.conf setting of the same
+ *    name.  If non-NULL, It's expected to be a list of patterns specifying
+ *    file system mount points to be excluded from the freeze operation.
+ *
  *    This function will try different available sync implementations. It will
  *    follow the order in the "gBackends" array, and keep on trying different
  *    backends while SD_UNAVAILABLE is returned. If all backends are
@@ -249,9 +431,10 @@ SyncDriverFreePath(gpointer data, gpointer userData)
  */
 
 Bool
-SyncDriver_Freeze(const char *userPaths,     // IN
-                  Bool enableNullDriver,     // IN
-                  SyncDriverHandle *handle)  // OUT
+SyncDriver_Freeze(const char *userPaths,              // IN
+                  Bool enableNullDriver,              // IN
+                  SyncDriverHandle *handle,           // OUT
+                  const char *excludedFileSystems)    // IN
 {
    GSList *paths = NULL;
    SyncDriverErr err = SD_UNAVAILABLE;
@@ -296,9 +479,10 @@ SyncDriver_Freeze(const char *userPaths,     // IN
       }
    }
 
+   paths = SyncDriverFilterFS(paths, excludedFileSystems);
    if (paths == NULL) {
-      Warning(LGPFX "No paths to freeze.\n");
-      return SD_ERROR;
+      Warning(LGPFX "No file systems to freeze.\n");
+      return FALSE;
    }
 
    while (err == SD_UNAVAILABLE && i < ARRAYSIZE(gBackends)) {
index 493127fa811394fafa42e1e82e6e2e7b576e272e..2ca5b281dd228d3dcdd63960a03b158449eab73f 100644 (file)
@@ -1,5 +1,5 @@
 /*********************************************************
- * Copyright (C) 2003-2017 VMware, Inc. All rights reserved.
+ * Copyright (C) 2003-2018 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
@@ -593,7 +593,8 @@ ToolsDaemonTcloSyncDriverFreeze(RpcInData *data)
                                                 FALSE);
 
    /* Perform the actual freeze. */
-   if (!SyncDriver_Freeze(driveList, enableNullDriver, &gSyncDriverHandle) ||
+   if (!SyncDriver_Freeze(driveList, enableNullDriver, &gSyncDriverHandle,
+                          NULL) ||
        SyncDriver_QueryStatus(gSyncDriverHandle, INFINITE) != SYNCDRIVER_IDLE) {
       g_warning("%s: Failed to Freeze drives '%s'\n",
                 __FUNCTION__, driveList);
index 2c03ef9fb75ebe5910e0193f4cd580e0a473edc6..af226eb71dac754507d63da206df4f705c63b026 100644 (file)
@@ -1,5 +1,5 @@
 /*********************************************************
- * Copyright (C) 2007-2017 VMware, Inc. All rights reserved.
+ * Copyright (C) 2007-2018 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
@@ -327,6 +327,7 @@ VmBackupFinalize(void)
    g_free(gBackupState->scriptArg);
    g_free(gBackupState->volumes);
    g_free(gBackupState->snapshots);
+   g_free(gBackupState->excludedFileSystems);
    g_free(gBackupState->errorMsg);
    g_free(gBackupState);
    gBackupState = NULL;
@@ -965,6 +966,13 @@ VmBackupStartCommon(RpcInData *data,
            gBackupState->allowHWProvider, gBackupState->execScripts,
            (gBackupState->scriptArg != NULL) ? gBackupState->scriptArg : "",
            gBackupState->timeout, gBackupState->enableNullDriver, forceQuiesce);
+#if defined(__linux__)
+   gBackupState->excludedFileSystems =
+         VMBACKUP_CONFIG_GET_STR(ctx->config, "excludedFileSystems", NULL);
+   g_debug("Using excludedFileSystems = \"%s\"\n",
+           (gBackupState->excludedFileSystems != NULL) ?
+            gBackupState->excludedFileSystems : "(null)");
+#endif
    g_debug("Quiescing volumes: %s",
            (gBackupState->volumes) ? gBackupState->volumes : "(null)");
 
index 682686df08137f206e50df9c890802f0db0cc175..65994e7a718bcd696c780d2d75d378796f3bb197 100644 (file)
@@ -1,5 +1,5 @@
 /*********************************************************
- * Copyright (C) 2007-2017 VMware, Inc. All rights reserved.
+ * Copyright (C) 2007-2018 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
@@ -236,7 +236,8 @@ VmBackupNewDriverOp(VmBackupState *state,       // IN
       success = SyncDriver_Freeze(op->volumes,
                                   useNullDriverPrefs ?
                                   state->enableNullDriver : FALSE,
-                                  op->syncHandle);
+                                  op->syncHandle,
+                                  state->excludedFileSystems);
    } else {
       op->manifest = SyncNewManifest(state, *op->syncHandle);
       success = VmBackupDriverThaw(op->syncHandle);
index a315ad3b8185fbf670180297092a99cfcad8c3a3..6a5bbcddc091926e82bd3095789084710b76467f 100644 (file)
@@ -1,5 +1,5 @@
 /*********************************************************
- * Copyright (C) 2008-2017 VMware, Inc. All rights reserved.
+ * Copyright (C) 2008-2018 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
@@ -117,6 +117,7 @@ typedef struct VmBackupState {
    Bool           generateManifests;
    Bool           quiesceApps;
    Bool           quiesceFS;
+   char          *excludedFileSystems;
    Bool           allowHWProvider;
    Bool           execScripts;
    Bool           enableNullDriver;