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