diff options
author | David Teigland <teigland@redhat.com> | 2015-11-04 14:26:46 -0600 |
---|---|---|
committer | David Teigland <teigland@redhat.com> | 2015-11-04 14:26:46 -0600 |
commit | 73ee03bfaa7c222ed7e0b35f74fb01a9bf327a44 (patch) | |
tree | 9d3f58ab09d1de4fdc6d6d05659ca379d7c5b517 | |
parent | 59df6b6b171696ca4e1d390032580f1afaf43e54 (diff) | |
download | lvm2-dev-dct-lvmetad-13.tar.gz |
Warn about duplicate PVs when using lvmetaddev-dct-lvmetad-13
A flag is set in lvmetad when duplicate PVs have
been found. Commands check this flag and print
a warning about duplicate PVs if it's set.
When devices are scanned, the flag is set or
cleared in lvmetad.
-rw-r--r-- | daemons/lvmetad/lvmetad-core.c | 14 | ||||
-rw-r--r-- | lib/cache/lvmcache.c | 19 | ||||
-rw-r--r-- | lib/cache/lvmcache.h | 2 | ||||
-rw-r--r-- | lib/cache/lvmetad.c | 91 | ||||
-rw-r--r-- | lib/cache/lvmetad.h | 6 | ||||
-rw-r--r-- | tools/lvmcmdline.c | 16 |
6 files changed, 147 insertions, 1 deletions
diff --git a/daemons/lvmetad/lvmetad-core.c b/daemons/lvmetad/lvmetad-core.c index f2a7b338b..829c94be8 100644 --- a/daemons/lvmetad/lvmetad-core.c +++ b/daemons/lvmetad/lvmetad-core.c @@ -258,7 +258,9 @@ struct vg_info { uint32_t flags; /* VGFL_ */ }; -#define GLFL_INVALID 0x00000001 +#define GLFL_INVALID 0x00000001 +#define GLFL_DUPLICATES 0x00000002 + #define VGFL_INVALID 0x00000001 typedef struct { @@ -2281,6 +2283,7 @@ static response pv_found(lvmetad_state *s, request r) arg_device, arg_pvid); unlock_pvid_to_pvmeta(s); dm_config_destroy(new_pvmeta); + s->flags |= GLFL_DUPLICATES; return reply_fail("Ignore duplicate PV"); } } @@ -2304,6 +2307,7 @@ static response pv_found(lvmetad_state *s, request r) new_device, old_device, arg_pvid); unlock_pvid_to_pvmeta(s); dm_config_destroy(new_pvmeta); + s->flags |= GLFL_DUPLICATES; return reply_fail("Ignore duplicate PV"); } @@ -2513,6 +2517,7 @@ static response vg_remove(lvmetad_state *s, request r) static response set_global_info(lvmetad_state *s, request r) { const int global_invalid = daemon_request_int(r, "global_invalid", -1); + const int duplicates = daemon_request_int(r, "duplicates", -1); if (global_invalid == 1) s->flags |= GLFL_INVALID; @@ -2520,6 +2525,12 @@ static response set_global_info(lvmetad_state *s, request r) else if (global_invalid == 0) s->flags &= ~GLFL_INVALID; + if (duplicates == 1) + s->flags |= GLFL_DUPLICATES; + + else if (duplicates == 0) + s->flags &= ~GLFL_DUPLICATES; + return daemon_reply_simple("OK", NULL); } @@ -2527,6 +2538,7 @@ static response get_global_info(lvmetad_state *s, request r) { return daemon_reply_simple("OK", "global_invalid = %d", (s->flags & GLFL_INVALID) ? 1 : 0, + "duplicates = %d", (s->flags & GLFL_DUPLICATES) ? 1 : 0, "token = %s", s->token[0] ? s->token : "none", NULL); } diff --git a/lib/cache/lvmcache.c b/lib/cache/lvmcache.c index acb6ae927..8a89601df 100644 --- a/lib/cache/lvmcache.c +++ b/lib/cache/lvmcache.c @@ -79,6 +79,7 @@ static int _scanning_in_progress = 0; static int _has_scanned = 0; static int _vgs_locked = 0; static int _vg_global_lock_held = 0; /* Global lock held when cache wiped? */ +static int _found_duplicates = 0; int lvmcache_init(void) { @@ -1544,6 +1545,23 @@ int lvmcache_update_vg(struct volume_group *vg, unsigned precommitted) return 1; } +/* + * When scanning all devices, lvmcache detects duplicate PVs exist if it sees + * two different devices with the same pvid. When it sees this, it ignores the + * duplicate device, and sets _found_duplicates. After the scan is done, we + * set or clear a flag in lvmetad indicating duplicate PVs, so that subsequent + * commands can print warnings about thatm. + */ +int lvmcache_found_duplicates(void) +{ + return _found_duplicates; +} + +void lvmcache_clear_found_duplicates(void) +{ + _found_duplicates = 0; +} + struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid, struct device *dev, const char *vgname, const char *vgid, @@ -1592,6 +1610,7 @@ struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid, log_warn("Ignore duplicate PV on device %s. Already using PV from device %s. (%s)", dev_name(dev), dev_name(existing->dev), pvid_s); log_warn("Use the global_filter to select a different device."); + _found_duplicates = 1; return NULL; } else { /* diff --git a/lib/cache/lvmcache.h b/lib/cache/lvmcache.h index b2abfa549..c232e4446 100644 --- a/lib/cache/lvmcache.h +++ b/lib/cache/lvmcache.h @@ -186,5 +186,7 @@ int lvmcache_contains_lock_type_sanlock(struct cmd_context *cmd); void lvmcache_get_max_name_lengths(struct cmd_context *cmd, unsigned *pv_max_name_len, unsigned *vg_max_name_len); +int lvmcache_found_duplicates(void); +void lvmcache_clear_found_duplicates(void); #endif diff --git a/lib/cache/lvmetad.c b/lib/cache/lvmetad.c index 581784b04..8f9f509da 100644 --- a/lib/cache/lvmetad.c +++ b/lib/cache/lvmetad.c @@ -314,6 +314,80 @@ out: return ret; } +static void _send_duplicates(struct cmd_context *cmd, int set) +{ + daemon_reply reply; + + log_debug_lvmetad("lvmetad send duplicates %d", set); + + reply = daemon_send_simple(_lvmetad, "set_global_info", + "token = %s", "skip", + "duplicates = %d", set, + NULL); + if (reply.error) + log_error("_send_duplicates error %d", reply.error); + + if (strcmp(daemon_reply_str(reply, "response", ""), "OK")) + log_error("_send_duplicates not ok"); + + daemon_reply_destroy(reply); +} + +/* + * The current command scanned devices and found a duplicate + * PV, so it sets the duplicates flag in lvmetad, + * which causes subsequent commands that use lvmetad to + * print a warning about duplicate PVs. + */ +void lvmetad_set_duplicates(struct cmd_context *cmd) +{ + _send_duplicates(cmd, 1); +} + +/* + * The current command scanned devices and did not find any + * duplicate PVs, so it can clear the duplicates + * flag in lvmetad, and subsequent commands will not + * warn about duplicate PVs. + */ +void lvmetad_clear_duplicates(struct cmd_context *cmd) +{ + _send_duplicates(cmd, 0); +} + +/* + * The duplicates flag can be set in lvmetad because + * the previous command that scanned devices found a duplicate + * and set the flag using lvmetad_set_duplicates(), + * or because a new PV was added to lvmetad by + * 'pvscan --cache dev', and lvmetad found that dev was a + * duplicate and set its duplicates flag. + */ +int lvmetad_check_duplicates(struct cmd_context *cmd) +{ + daemon_reply reply; + int duplicates; + + reply = daemon_send_simple(_lvmetad, "get_global_info", + "token = %s", "skip", + NULL); + + if (reply.error) { + log_error("lvmetad_check_duplicates get_global_info error %d", reply.error); + return 0; + } + + if (strcmp(daemon_reply_str(reply, "response", ""), "OK")) { + log_error("lvmetad_check_duplicates get_global_info not ok"); + return 0; + } + + duplicates = daemon_reply_int(reply, "duplicates", 0); + daemon_reply_destroy(reply); + + return duplicates; +} + static int _lvmetad_pvscan_all_devs(struct cmd_context *cmd, activation_handler handler, int ignore_obsolete); @@ -1485,6 +1559,8 @@ static int _lvmetad_pvscan_all_devs(struct cmd_context *cmd, activation_handler return 0; } + lvmcache_clear_found_duplicates(); + log_debug_lvmetad("Scanning all devices to update lvmetad."); if (!(iter = dev_iter_create(cmd->lvmetad_filter, 1))) { @@ -1527,6 +1603,21 @@ static int _lvmetad_pvscan_all_devs(struct cmd_context *cmd, activation_handler if (!_token_update()) return 0; + /* + * We are done scanning all devices, and lvmcache set a flag if + * duplicate PVs were seen. If using lvmetad, and duplicates were seen + * during the scan, then set an "duplicates" flag in lvmetad to + * indicate duplicate PVs exist. Subsequent commands will check for + * this duplicates flag, and if it's set they will warn about duplicate + * PVs. When the next rescan happens, this flag will be set or cleared + * again dependin on whether the duplicates still exist or have been + * resolved. + */ + if (lvmcache_found_duplicates()) + lvmetad_set_duplicates(cmd); + else + lvmetad_clear_duplicates(cmd); + return r; } diff --git a/lib/cache/lvmetad.h b/lib/cache/lvmetad.h index 4c4549ee9..f9b83a053 100644 --- a/lib/cache/lvmetad.h +++ b/lib/cache/lvmetad.h @@ -175,6 +175,9 @@ int lvmetad_pvscan_foreign_vgs(struct cmd_context *cmd, activation_handler handl int lvmetad_vg_clear_outdated_pvs(struct volume_group *vg); void lvmetad_validate_global_cache(struct cmd_context *cmd, int force); int lvmetad_token_matches(struct cmd_context *cmd); +void lvmetad_set_duplicates(struct cmd_context *cmd); +void lvmetad_clear_duplicates(struct cmd_context *cmd); +int lvmetad_check_duplicates(struct cmd_context *cmd); # else /* LVMETAD_SUPPORT */ @@ -206,6 +209,9 @@ int lvmetad_token_matches(struct cmd_context *cmd); # define lvmetad_validate_global_cache(cmd, force) do { } while (0) # define lvmetad_token_matches(cmd) (1) # define lvmetad_is_connected() (0) +# define lvmetad_set_duplicates() do { } while (0) +# define lvmetad_clear_duplicates() do { } while (0) +# define lvmetad_check_duplicates() (0) # endif /* LVMETAD_SUPPORT */ diff --git a/tools/lvmcmdline.c b/tools/lvmcmdline.c index f2e60b4d5..3cf7f1bae 100644 --- a/tools/lvmcmdline.c +++ b/tools/lvmcmdline.c @@ -1658,6 +1658,22 @@ int lvm_run_command(struct cmd_context *cmd, int argc, char **argv) log_error("Failed to scan devices"); return ECMD_FAILED; } + } else if (lvmetad_check_duplicates(cmd)) { + /* + * Warn if duplicate PVs exist. Because we're using lvmetad, + * we won't be scanning devices, so we rely on lvmetad to tell + * us if duplicate devices were seen by the last device scan. + * + * FIXME: maybe enhance this by listing the actual duplicate devices? + * The device scan that set the duplicates flag in lvmetad could + * also send lvmetad the names of the duplicate devices it ignored. + * That list could then be returned here and included in this + * warning. However, that list would not always be accurate, + * because a "full picture" scan is needed to construct a truely + * accurate picture of duplicate PVs. + */ + log_warn("WARNING: duplicate PVs have been found."); + log_warn("WARNING: duplicate PVs can be resolved with filters or vgimportclone."); } } |