Blame SOURCES/lvm2-2_02_187-pvscan-fix-activation-of-incomplete-VGs.patch

f507f1
From 8aac4049c270ae8beb741a2cd80084810945a718 Mon Sep 17 00:00:00 2001
f507f1
From: David Teigland <teigland@redhat.com>
f507f1
Date: Tue, 3 Sep 2019 15:14:08 -0500
f507f1
Subject: [PATCH 1/4] pvscan: fix activation of incomplete VGs
f507f1
f507f1
For a long time there has been a bug in the activation
f507f1
done by the initial pvscan (which scans all devs to
f507f1
initialize the lvmetad cache.)  It was attempting to
f507f1
activate all VGs, even those that were not complete.
f507f1
f507f1
lvmetad tells pvscan when a VG is complete, and pvscan
f507f1
needs to use this information to decide which VGs to
f507f1
activate.
f507f1
f507f1
When there are problems that prevent lvmetad from being
f507f1
used (e.g. lvmetad is disabled or not running), pvscan
f507f1
activation cannot use lvmetad to determine when a VG
f507f1
is complete, so it now checks if devices are present
f507f1
for all PVs in the VG before activating.
f507f1
f507f1
(The recent commit "pvscan: avoid redundant activation"
f507f1
could make this bug more apparent because redundant
f507f1
activations can cover up the effect of activating an
f507f1
incomplete VG and missing some LV activations.)
f507f1
f507f1
(cherry picked from commit 6b12930860a993624d6325aec2e9c561f4412aa9)
f507f1
---
f507f1
 lib/cache/lvmetad.c   | 15 ++++++++----
f507f1
 lib/cache/lvmetad.h   |  2 +-
f507f1
 tools/lvmcmdline.c    |  2 +-
f507f1
 tools/lvscan.c        |  2 +-
f507f1
 tools/pvscan.c        | 65 ++++++++++++++++++++++++++++++++++++++++++++++-----
f507f1
 tools/vgcfgrestore.c  |  2 +-
f507f1
 tools/vgimport.c      |  2 +-
f507f1
 tools/vgimportclone.c |  2 +-
f507f1
 tools/vgscan.c        |  2 +-
f507f1
 9 files changed, 77 insertions(+), 17 deletions(-)
f507f1
f507f1
diff --git a/lib/cache/lvmetad.c b/lib/cache/lvmetad.c
f507f1
index 1eda567..e659711 100644
f507f1
--- a/lib/cache/lvmetad.c
f507f1
+++ b/lib/cache/lvmetad.c
f507f1
@@ -1704,6 +1704,13 @@ int lvmetad_pv_found(struct cmd_context *cmd, const struct id *pvid, struct devi
f507f1
 		changed = daemon_reply_int(reply, "changed", 0);
f507f1
 	}
f507f1
 
f507f1
+	if (vg && vg->system_id && vg->system_id[0] &&
f507f1
+	    cmd->system_id && cmd->system_id[0] &&
f507f1
+	    strcmp(vg->system_id, cmd->system_id)) {
f507f1
+		log_debug_lvmetad("Ignore foreign VG %s on %s", vg->name , dev_name(dev));
f507f1
+		goto out;
f507f1
+	}
f507f1
+
f507f1
 	/*
f507f1
 	 * If lvmetad now sees all PVs in the VG, it returned the
f507f1
 	 * "complete" status string.  Add this VG name to the list
f507f1
@@ -1734,7 +1741,7 @@ int lvmetad_pv_found(struct cmd_context *cmd, const struct id *pvid, struct devi
f507f1
 				log_error("str_list_add failed");
f507f1
 		}
f507f1
 	}
f507f1
-
f507f1
+out:
f507f1
 	daemon_reply_destroy(reply);
f507f1
 
f507f1
 	return result;
f507f1
@@ -2347,7 +2354,7 @@ bad:
f507f1
  * generally revert disk scanning and not use lvmetad.
f507f1
  */
f507f1
 
f507f1
-int lvmetad_pvscan_all_devs(struct cmd_context *cmd, int do_wait)
f507f1
+int lvmetad_pvscan_all_devs(struct cmd_context *cmd, int do_wait, struct dm_list *found_vgnames)
f507f1
 {
f507f1
 	struct device_list *devl, *devl2;
f507f1
 	struct dm_list scan_devs;
f507f1
@@ -2429,7 +2436,7 @@ int lvmetad_pvscan_all_devs(struct cmd_context *cmd, int do_wait)
f507f1
 
f507f1
 		dm_list_del(&devl->list);
f507f1
 
f507f1
-		ret = lvmetad_pvscan_single(cmd, devl->dev, NULL, NULL);
f507f1
+		ret = lvmetad_pvscan_single(cmd, devl->dev, found_vgnames, NULL);
f507f1
 
f507f1
 		label_scan_invalidate(devl->dev);
f507f1
 
f507f1
@@ -2774,7 +2781,7 @@ void lvmetad_validate_global_cache(struct cmd_context *cmd, int force)
f507f1
 	 * we rescanned for the token, and the time we acquired the global
f507f1
 	 * lock.)
f507f1
 	 */
f507f1
-	if (!lvmetad_pvscan_all_devs(cmd, 1)) {
f507f1
+	if (!lvmetad_pvscan_all_devs(cmd, 1, NULL)) {
f507f1
 		log_warn("WARNING: Not using lvmetad because cache update failed.");
f507f1
 		lvmetad_make_unused(cmd);
f507f1
 		return;
f507f1
diff --git a/lib/cache/lvmetad.h b/lib/cache/lvmetad.h
f507f1
index 73c2645..55ce16a 100644
f507f1
--- a/lib/cache/lvmetad.h
f507f1
+++ b/lib/cache/lvmetad.h
f507f1
@@ -151,7 +151,7 @@ int lvmetad_pvscan_single(struct cmd_context *cmd, struct device *dev,
f507f1
 			  struct dm_list *found_vgnames,
f507f1
 			  struct dm_list *changed_vgnames);
f507f1
 
f507f1
-int lvmetad_pvscan_all_devs(struct cmd_context *cmd, int do_wait);
f507f1
+int lvmetad_pvscan_all_devs(struct cmd_context *cmd, int do_wait, struct dm_list *found_vgnames);
f507f1
 
f507f1
 int lvmetad_vg_clear_outdated_pvs(struct volume_group *vg);
f507f1
 void lvmetad_validate_global_cache(struct cmd_context *cmd, int force);
f507f1
diff --git a/tools/lvmcmdline.c b/tools/lvmcmdline.c
f507f1
index f82827d..75a0401 100644
f507f1
--- a/tools/lvmcmdline.c
f507f1
+++ b/tools/lvmcmdline.c
f507f1
@@ -2991,7 +2991,7 @@ int lvm_run_command(struct cmd_context *cmd, int argc, char **argv)
f507f1
 	 */
f507f1
 	if (lvmetad_used() && !_cmd_no_lvmetad_autoscan(cmd)) {
f507f1
 		if (cmd->include_foreign_vgs || !lvmetad_token_matches(cmd)) {
f507f1
-			if (lvmetad_used() && !lvmetad_pvscan_all_devs(cmd, cmd->include_foreign_vgs ? 1 : 0)) {
f507f1
+			if (lvmetad_used() && !lvmetad_pvscan_all_devs(cmd, cmd->include_foreign_vgs ? 1 : 0, NULL)) {
f507f1
 				log_warn("WARNING: Not using lvmetad because cache update failed.");
f507f1
 				lvmetad_make_unused(cmd);
f507f1
 			}
f507f1
diff --git a/tools/lvscan.c b/tools/lvscan.c
f507f1
index c38208a..34e9f31 100644
f507f1
--- a/tools/lvscan.c
f507f1
+++ b/tools/lvscan.c
f507f1
@@ -103,7 +103,7 @@ int lvscan(struct cmd_context *cmd, int argc, char **argv)
f507f1
 
f507f1
 	/* Needed because this command has NO_LVMETAD_AUTOSCAN. */
f507f1
 	if (lvmetad_used() && (!lvmetad_token_matches(cmd) || lvmetad_is_disabled(cmd, &reason))) {
f507f1
-		if (lvmetad_used() && !lvmetad_pvscan_all_devs(cmd, 0)) {
f507f1
+		if (lvmetad_used() && !lvmetad_pvscan_all_devs(cmd, 0, NULL)) {
f507f1
 			log_warn("WARNING: Not using lvmetad because cache update failed.");
f507f1
 			lvmetad_make_unused(cmd);
f507f1
 		}
f507f1
diff --git a/tools/pvscan.c b/tools/pvscan.c
f507f1
index e5afe0c..9e76f52 100644
f507f1
--- a/tools/pvscan.c
f507f1
+++ b/tools/pvscan.c
f507f1
@@ -38,6 +38,7 @@ struct pvscan_params {
f507f1
 
f507f1
 struct pvscan_aa_params {
f507f1
 	int refresh_all;
f507f1
+	int all_vgs;
f507f1
 	unsigned int activate_errors;
f507f1
 	struct dm_list changed_vgnames;
f507f1
 };
f507f1
@@ -223,6 +224,28 @@ void online_vg_file_remove(const char *vgname)
f507f1
 	unlink(path);
f507f1
 }
f507f1
 
f507f1
+static void _online_files_remove(const char *dirpath)
f507f1
+{
f507f1
+	char path[PATH_MAX];
f507f1
+	DIR *dir;
f507f1
+	struct dirent *de;
f507f1
+
f507f1
+	if (!(dir = opendir(dirpath)))
f507f1
+		return;
f507f1
+
f507f1
+	while ((de = readdir(dir))) {
f507f1
+		if (de->d_name[0] == '.')
f507f1
+			continue;
f507f1
+
f507f1
+		memset(path, 0, sizeof(path));
f507f1
+		snprintf(path, sizeof(path), "%s/%s", dirpath, de->d_name);
f507f1
+		if (unlink(path))
f507f1
+			log_sys_debug("unlink", path);
f507f1
+	}
f507f1
+	if (closedir(dir))
f507f1
+		log_sys_debug("closedir", dirpath);
f507f1
+}
f507f1
+
f507f1
 /*
f507f1
  * pvscan --cache does not perform any lvmlockd locking, and
f507f1
  * pvscan --cache -aay skips autoactivation in lockd VGs.
f507f1
@@ -271,6 +294,8 @@ static int _pvscan_autoactivate_single(struct cmd_context *cmd, const char *vg_n
f507f1
 				       struct volume_group *vg, struct processing_handle *handle)
f507f1
 {
f507f1
 	struct pvscan_aa_params *pp = (struct pvscan_aa_params *)handle->custom_handle;
f507f1
+	struct pv_list *pvl;
f507f1
+	int incomplete = 0;
f507f1
 
f507f1
 	if (vg_is_clustered(vg))
f507f1
 		return ECMD_PROCESSED;
f507f1
@@ -281,6 +306,24 @@ static int _pvscan_autoactivate_single(struct cmd_context *cmd, const char *vg_n
f507f1
 	if (is_lockd_type(vg->lock_type))
f507f1
 		return ECMD_PROCESSED;
f507f1
 
f507f1
+	/*
f507f1
+	 * This all_vgs case only happens in fallback cases when there's some
f507f1
+	 * problem preventing the use of lvmetad.  When lvmetad can be properly
f507f1
+	 * used, the found_vgnames list should have the names of complete VGs
f507f1
+	 * that should be activated.
f507f1
+	 */
f507f1
+	if (pp->all_vgs) {
f507f1
+		dm_list_iterate_items(pvl, &vg->pvs) {
f507f1
+			if (!pvl->pv->dev)
f507f1
+				incomplete++;
f507f1
+		}
f507f1
+
f507f1
+		if (incomplete) {
f507f1
+			log_print("pvscan[%d] VG %s incomplete (need %d).", getpid(), vg->name, incomplete);
f507f1
+			return ECMD_PROCESSED;
f507f1
+		}
f507f1
+	}
f507f1
+
f507f1
 	log_debug("pvscan autoactivating VG %s.", vg_name);
f507f1
 
f507f1
 #if 0
f507f1
@@ -377,6 +420,7 @@ static int _pvscan_autoactivate(struct cmd_context *cmd, struct pvscan_aa_params
f507f1
 	if (all_vgs) {
f507f1
 		cmd->cname->flags |= ALL_VGS_IS_DEFAULT;
f507f1
 		pp->refresh_all = 1;
f507f1
+		pp->all_vgs = 1;
f507f1
 	}
f507f1
 
f507f1
 	ret = process_each_vg(cmd, 0, NULL, NULL, vgnames, 0, 0, handle, _pvscan_autoactivate_single);
f507f1
@@ -463,17 +507,23 @@ static int _pvscan_cache(struct cmd_context *cmd, int argc, char **argv)
f507f1
 	 * Scan all devices when no args are given.
f507f1
 	 */
f507f1
 	if (!argc && !devno_args) {
f507f1
+		_online_files_remove(_vgs_online_dir);
f507f1
+
f507f1
 		log_verbose("Scanning all devices.");
f507f1
 
f507f1
-		if (!lvmetad_pvscan_all_devs(cmd, 1)) {
f507f1
+		if (!lvmetad_pvscan_all_devs(cmd, 1, &found_vgnames)) {
f507f1
 			log_warn("WARNING: Not using lvmetad because cache update failed.");
f507f1
 			lvmetad_make_unused(cmd);
f507f1
+			all_vgs = 1;
f507f1
 		}
f507f1
 		if (lvmetad_used() && lvmetad_is_disabled(cmd, &reason)) {
f507f1
 			log_warn("WARNING: Not using lvmetad because %s.", reason);
f507f1
 			lvmetad_make_unused(cmd);
f507f1
+			all_vgs = 1;
f507f1
 		}
f507f1
-		all_vgs = 1;
f507f1
+
f507f1
+		if (!all_vgs && do_activate)
f507f1
+			log_print("pvscan[%d] activating all complete VGs (no args)", getpid());
f507f1
 		goto activate;
f507f1
 	}
f507f1
 
f507f1
@@ -485,7 +535,7 @@ static int _pvscan_cache(struct cmd_context *cmd, int argc, char **argv)
f507f1
 	 * never scan any devices other than those specified.
f507f1
 	 */
f507f1
 	if (!lvmetad_token_matches(cmd)) {
f507f1
-		if (lvmetad_used() && !lvmetad_pvscan_all_devs(cmd, 0)) {
f507f1
+		if (lvmetad_used() && !lvmetad_pvscan_all_devs(cmd, 0, &found_vgnames)) {
f507f1
 			log_warn("WARNING: Not updating lvmetad because cache update failed.");
f507f1
 			ret = ECMD_FAILED;
f507f1
 			goto out;
f507f1
@@ -493,9 +543,12 @@ static int _pvscan_cache(struct cmd_context *cmd, int argc, char **argv)
f507f1
 		if (lvmetad_used() && lvmetad_is_disabled(cmd, &reason)) {
f507f1
 			log_warn("WARNING: Not using lvmetad because %s.", reason);
f507f1
 			lvmetad_make_unused(cmd);
f507f1
+			all_vgs = 1;
f507f1
+			log_print("pvscan[%d] activating all directly (lvmetad disabled from scan) %s", getpid(), dev_arg ?: "");
f507f1
 		}
f507f1
-		log_print("pvscan[%d] activating all directly (lvmetad token) %s", getpid(), dev_arg ?: "");
f507f1
-		all_vgs = 1;
f507f1
+
f507f1
+		if (!all_vgs)
f507f1
+			log_print("pvscan[%d] activating all complete VGs for init", getpid());
f507f1
 		goto activate;
f507f1
 	}
f507f1
 
f507f1
@@ -808,7 +861,7 @@ int pvscan(struct cmd_context *cmd, int argc, char **argv)
f507f1
 
f507f1
 	/* Needed because this command has NO_LVMETAD_AUTOSCAN. */
f507f1
 	if (lvmetad_used() && (!lvmetad_token_matches(cmd) || lvmetad_is_disabled(cmd, &reason))) {
f507f1
-		if (lvmetad_used() && !lvmetad_pvscan_all_devs(cmd, 0)) {
f507f1
+		if (lvmetad_used() && !lvmetad_pvscan_all_devs(cmd, 0, NULL)) {
f507f1
 			log_warn("WARNING: Not using lvmetad because cache update failed.");
f507f1
 			lvmetad_make_unused(cmd);
f507f1
 		}
f507f1
diff --git a/tools/vgcfgrestore.c b/tools/vgcfgrestore.c
f507f1
index 48a2fa4..e7f9848 100644
f507f1
--- a/tools/vgcfgrestore.c
f507f1
+++ b/tools/vgcfgrestore.c
f507f1
@@ -177,7 +177,7 @@ rescan:
f507f1
 		}
f507f1
 		if (!refresh_filters(cmd))
f507f1
 			stack;
f507f1
-		if (!lvmetad_pvscan_all_devs(cmd, 1)) {
f507f1
+		if (!lvmetad_pvscan_all_devs(cmd, 1, NULL)) {
f507f1
 			log_warn("WARNING: Failed to scan devices.");
f507f1
 			log_warn("WARNING: Update lvmetad with pvscan --cache.");
f507f1
 			goto out;
f507f1
diff --git a/tools/vgimport.c b/tools/vgimport.c
f507f1
index ea50198..d4455ec 100644
f507f1
--- a/tools/vgimport.c
f507f1
+++ b/tools/vgimport.c
f507f1
@@ -96,7 +96,7 @@ int vgimport(struct cmd_context *cmd, int argc, char **argv)
f507f1
 	 * import it.
f507f1
 	 */
f507f1
 	if (lvmetad_used()) {
f507f1
-		if (!lvmetad_pvscan_all_devs(cmd, 1)) {
f507f1
+		if (!lvmetad_pvscan_all_devs(cmd, 1, NULL)) {
f507f1
 			log_warn("WARNING: Not using lvmetad because cache update failed.");
f507f1
 			lvmetad_make_unused(cmd);
f507f1
 		}
f507f1
diff --git a/tools/vgimportclone.c b/tools/vgimportclone.c
f507f1
index c4c5d4c..ac3766b 100644
f507f1
--- a/tools/vgimportclone.c
f507f1
+++ b/tools/vgimportclone.c
f507f1
@@ -377,7 +377,7 @@ out:
f507f1
 		if (!refresh_filters(cmd))
f507f1
 			stack;
f507f1
 
f507f1
-		if (!lvmetad_pvscan_all_devs(cmd, 1)) {
f507f1
+		if (!lvmetad_pvscan_all_devs(cmd, 1, NULL)) {
f507f1
 			log_warn("WARNING: Failed to scan devices.");
f507f1
 			log_warn("WARNING: Update lvmetad with pvscan --cache.");
f507f1
 		}
f507f1
diff --git a/tools/vgscan.c b/tools/vgscan.c
f507f1
index 1ec9083..7a63996 100644
f507f1
--- a/tools/vgscan.c
f507f1
+++ b/tools/vgscan.c
f507f1
@@ -101,7 +101,7 @@ int vgscan(struct cmd_context *cmd, int argc, char **argv)
f507f1
 		log_verbose("Ignoring vgscan --cache command because lvmetad is not in use.");
f507f1
 
f507f1
 	if (lvmetad_used() && (arg_is_set(cmd, cache_long_ARG) || !lvmetad_token_matches(cmd) || lvmetad_is_disabled(cmd, &reason))) {
f507f1
-		if (lvmetad_used() && !lvmetad_pvscan_all_devs(cmd, arg_is_set(cmd, cache_long_ARG))) {
f507f1
+		if (lvmetad_used() && !lvmetad_pvscan_all_devs(cmd, arg_is_set(cmd, cache_long_ARG), NULL)) {
f507f1
 			log_warn("WARNING: Not using lvmetad because cache update failed.");
f507f1
 			lvmetad_make_unused(cmd);
f507f1
 		}
f507f1
-- 
f507f1
1.8.3.1
f507f1