#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:
* 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;
}
}
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * 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;
+}
+
+
/*
*-----------------------------------------------------------------------------
*
* 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
*/
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;
}
}
+ 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)) {