From: Oliver Kurth Date: Mon, 26 Feb 2018 20:35:36 +0000 (-0800) Subject: Skip specified file systems when doing a quiesced snapshot on Linux X-Git-Tag: 10.2.5~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=477ed7490a0c8376b050b49af84a07e82490fbe6;p=thirdparty%2Fopen-vm-tools.git Skip specified file systems when doing a quiesced snapshot on Linux 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. --- diff --git a/open-vm-tools/lib/include/syncDriver.h b/open-vm-tools/lib/include/syncDriver.h index 4cb71b491..20712f66a 100644 --- a/open-vm-tools/lib/include/syncDriver.h +++ b/open-vm-tools/lib/include/syncDriver.h @@ -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); diff --git a/open-vm-tools/lib/syncDriver/syncDriverPosix.c b/open-vm-tools/lib/syncDriver/syncDriverPosix.c index f66ca8026..839cb6dd9 100644 --- a/open-vm-tools/lib/syncDriver/syncDriverPosix.c +++ b/open-vm-tools/lib/syncDriver/syncDriverPosix.c @@ -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)) { diff --git a/open-vm-tools/services/plugins/vix/foundryToolsDaemon.c b/open-vm-tools/services/plugins/vix/foundryToolsDaemon.c index 493127fa8..2ca5b281d 100644 --- a/open-vm-tools/services/plugins/vix/foundryToolsDaemon.c +++ b/open-vm-tools/services/plugins/vix/foundryToolsDaemon.c @@ -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); diff --git a/open-vm-tools/services/plugins/vmbackup/stateMachine.c b/open-vm-tools/services/plugins/vmbackup/stateMachine.c index 2c03ef9fb..af226eb71 100644 --- a/open-vm-tools/services/plugins/vmbackup/stateMachine.c +++ b/open-vm-tools/services/plugins/vmbackup/stateMachine.c @@ -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)"); diff --git a/open-vm-tools/services/plugins/vmbackup/syncDriverOps.c b/open-vm-tools/services/plugins/vmbackup/syncDriverOps.c index 682686df0..65994e7a7 100644 --- a/open-vm-tools/services/plugins/vmbackup/syncDriverOps.c +++ b/open-vm-tools/services/plugins/vmbackup/syncDriverOps.c @@ -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); diff --git a/open-vm-tools/services/plugins/vmbackup/vmBackupInt.h b/open-vm-tools/services/plugins/vmbackup/vmBackupInt.h index a315ad3b8..6a5bbcddc 100644 --- a/open-vm-tools/services/plugins/vmbackup/vmBackupInt.h +++ b/open-vm-tools/services/plugins/vmbackup/vmBackupInt.h @@ -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;