summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Teigland <teigland@redhat.com>2015-11-04 14:26:46 -0600
committerDavid Teigland <teigland@redhat.com>2015-11-04 14:26:46 -0600
commit73ee03bfaa7c222ed7e0b35f74fb01a9bf327a44 (patch)
tree9d3f58ab09d1de4fdc6d6d05659ca379d7c5b517
parent59df6b6b171696ca4e1d390032580f1afaf43e54 (diff)
downloadlvm2-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.c14
-rw-r--r--lib/cache/lvmcache.c19
-rw-r--r--lib/cache/lvmcache.h2
-rw-r--r--lib/cache/lvmetad.c91
-rw-r--r--lib/cache/lvmetad.h6
-rw-r--r--tools/lvmcmdline.c16
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.");
}
}