summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Teigland <teigland@redhat.com>2015-10-15 17:13:28 -0500
committerDavid Teigland <teigland@redhat.com>2015-10-19 16:51:50 -0500
commit26b7001d9ed51fdaa1246368a27ff99a53b9476d (patch)
treef2afebf79aa4ebee52af5b28157ed6decad1a171
parent2e655b5610eb0ccde2b1e099a78f9f6122bda4f2 (diff)
downloadlvm2-dev-dct-lvmetad4.tar.gz
lvmetad: refresh content at command startdev-dct-lvmetad4
At the start of the command, check if the lvmetad content needs updating (token not matching), and if so do the scan and update it. This gets the updating done right at the beginning, before command processing is started. The early scan already exists for the foreign VGs case, so this is added to it. Previously, the command would be part way through its own processing before discovering via lvmetad_send that lvmetad needed updating. It's not good to interrupt a command, insert a 'pvscan --cache', then continue on with the original command. The pvscan is likely to interfere with the original command.
-rw-r--r--daemons/lvmetad/lvmetad-core.c7
-rw-r--r--lib/cache/lvmetad.c62
-rw-r--r--lib/cache/lvmetad.h2
-rw-r--r--tools/commands.h2
-rw-r--r--tools/lvmcmdline.c24
-rw-r--r--tools/pvscan.c15
-rw-r--r--tools/tools.h2
7 files changed, 103 insertions, 11 deletions
diff --git a/daemons/lvmetad/lvmetad-core.c b/daemons/lvmetad/lvmetad-core.c
index e14795699..848b10d35 100644
--- a/daemons/lvmetad/lvmetad-core.c
+++ b/daemons/lvmetad/lvmetad-core.c
@@ -2479,9 +2479,10 @@ static response set_global_info(lvmetad_state *s, request r)
static response get_global_info(lvmetad_state *s, request r)
{
- return daemon_reply_simple("OK", "global_invalid = %d",
- (s->flags & GLFL_INVALID) ? 1 : 0,
- NULL);
+ return daemon_reply_simple("OK",
+ "global_invalid = %d", (s->flags & GLFL_INVALID) ? 1 : 0,
+ "token = %s", s->token[0] ? s->token : "none",
+ NULL);
}
static response set_vg_info(lvmetad_state *s, request r)
diff --git a/lib/cache/lvmetad.c b/lib/cache/lvmetad.c
index 090f0d722..090bd7544 100644
--- a/lib/cache/lvmetad.c
+++ b/lib/cache/lvmetad.c
@@ -206,6 +206,54 @@ void lvmetad_set_socket(const char *sock)
_lvmetad_socket = sock;
}
+int lvmetad_token_matches(struct cmd_context *cmd)
+{
+ daemon_reply reply;
+ const char *daemon_token;
+ int ret = 1;
+
+ reply = daemon_send_simple(_lvmetad, "get_global_info",
+ "token = %s", "skip",
+ NULL);
+ if (reply.error) {
+ log_error("lvmetad_token_matches get_global_info error %d", reply.error);
+ ret = 0;
+ goto out;
+ }
+
+ if (strcmp(daemon_reply_str(reply, "response", ""), "OK")) {
+ log_error("lvmetad_token_matches get_global_info not ok");
+ ret = 0;
+ goto out;
+ }
+
+ daemon_token = daemon_reply_str(reply, "token", NULL);
+
+ if (!daemon_token) {
+ log_error("lvmetad_token_matches no token returned");
+ ret = 0;
+ goto out;
+ }
+
+ if (!strcmp(daemon_token, "none")) {
+ /* lvmetad is not yet populated */
+ ret = 0;
+ goto out;
+ }
+
+ if (strcmp(daemon_token, _lvmetad_token)) {
+ /*
+ * lvmetad has an unmatching token; it was last populated
+ * using a different global filter.
+ */
+ ret = 0;
+ goto out;
+ }
+out:
+ daemon_reply_destroy(reply);
+ return ret;
+}
+
static int _lvmetad_pvscan_all_devs(struct cmd_context *cmd, activation_handler handler,
int ignore_obsolete);
@@ -246,6 +294,13 @@ retry:
* we re-scan immediately, but if we lose the potential race for
* the update, we back off for a short while (0.05-0.5 seconds) and
* try again.
+ *
+ * FIXME: remove the retry/pvscan and just fail the command.
+ * Running pvscan here is likely to mess up the state of
+ * the original command. This should be very unlikely
+ * since the token is verified to match at the start
+ * of the command now. Also there's no recursion check to
+ * prevent _lvmetad_pvscan_all_devs->lvmetad_send->_lvmetad_pvscan_all_devs...
*/
if (!repl.error && !strcmp(daemon_reply_str(repl, "response", ""), "token_mismatch") &&
num_rescans < MAX_RESCANS && total_usecs_waited < (SCAN_TIMEOUT_SECONDS * 1000000) && !test_mode()) {
@@ -1744,7 +1799,12 @@ void lvmetad_validate_global_cache(struct cmd_context *cmd, int force)
/*
* Update the local lvmetad cache so it correctly reflects any
- * changes made on remote hosts.
+ * changes made on remote hosts. (It's possible that this command
+ * already refreshed the local lvmetad because of a token change,
+ * but we need to do it again here since we now hold the global
+ * lock. Another host may have changed things between the time
+ * we rescanned for the token, and the time we acquired the global
+ * lock.)
*/
lvmetad_pvscan_all_devs(cmd, NULL);
diff --git a/lib/cache/lvmetad.h b/lib/cache/lvmetad.h
index af0d562fe..1c94308df 100644
--- a/lib/cache/lvmetad.h
+++ b/lib/cache/lvmetad.h
@@ -168,6 +168,7 @@ 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);
# else /* LVMETAD_SUPPORT */
@@ -197,6 +198,7 @@ void lvmetad_validate_global_cache(struct cmd_context *cmd, int force);
# define lvmetad_pvscan_foreign_vgs(cmd, handler) (0)
# define lvmetad_vg_clear_outdated_pvs(vg) (1)
# define lvmetad_validate_global_cache(cmd, force) do { } while (0)
+# define lvmetad_token_matches(cmd) (1)
# endif /* LVMETAD_SUPPORT */
diff --git a/tools/commands.h b/tools/commands.h
index 92d13fdf0..fb41d9e4c 100644
--- a/tools/commands.h
+++ b/tools/commands.h
@@ -962,7 +962,7 @@ xx(pvs,
xx(pvscan,
"List all physical volumes",
- PERMITTED_READ_ONLY | LOCKD_VG_SH,
+ PERMITTED_READ_ONLY | LOCKD_VG_SH | SKIP_AUTO_PVSCAN,
"pvscan\n"
"\t[-b|--background]\n"
"\t[--cache [-a|--activate ay] [ DevicePath | -j|--major major --minor minor]...]\n"
diff --git a/tools/lvmcmdline.c b/tools/lvmcmdline.c
index 657797765..858b0360f 100644
--- a/tools/lvmcmdline.c
+++ b/tools/lvmcmdline.c
@@ -1640,13 +1640,25 @@ int lvm_run_command(struct cmd_context *cmd, int argc, char **argv)
}
/*
- * Other hosts might have changed foreign VGs so enforce a rescan
- * before processing any command using them.
+ * The lvmetad cache may need to be repopulated before we use it because:
+ * - We are reading foreign VGs which others hosts may have changed
+ * which our lvmetad would not have seen.
+ * - lvmetad may have just been started and no command has been run
+ * to populate it yet (e.g. no pvscan --cache was run).
+ * - Another local command may have run with a different global filter
+ * which changed the content of lvmetad from what we want (recognized
+ * by differnet token values.)
+ *
+ * The pvscan command does rescanning and lvmetad upates itself,
+ * so it doesn't want this automatic rescanning.
*/
- if (cmd->include_foreign_vgs && lvmetad_used() &&
- !lvmetad_pvscan_foreign_vgs(cmd, NULL)) {
- log_error("Failed to scan devices.");
- return ECMD_FAILED;
+ if (lvmetad_active() && !(cmd->command->flags & SKIP_AUTO_PVSCAN)) {
+ if (!lvmetad_token_matches(cmd) || cmd->include_foreign_vgs) {
+ if (!lvmetad_pvscan_all_devs(cmd, NULL)) {
+ log_error("Failed to scan devices");
+ return ECMD_FAILED;
+ }
+ }
}
/*
diff --git a/tools/pvscan.c b/tools/pvscan.c
index 10bf28e52..7ea83f225 100644
--- a/tools/pvscan.c
+++ b/tools/pvscan.c
@@ -387,6 +387,21 @@ int pvscan(struct cmd_context *cmd, int argc, char **argv)
arg_count(cmd, exported_ARG) ?
"of exported volume group(s)" : "in no volume group");
+ /*
+ * All pvscan commands skip the automatic repopulating of
+ * lvmetad when the token doesn't match, because pvscan_lvmetad
+ * above (for pvscan --cache) needs to do that repopulating
+ * itself. So for other pvscan commands (without --cache), we
+ * need to check the lvmetad token and repopulate the cache
+ * if it doesn't match.
+ */
+ if (lvmetad_active() && !lvmetad_token_matches(cmd)) {
+ if (!lvmetad_pvscan_all_devs(cmd, NULL)) {
+ log_error("Failed to scan devices");
+ return ECMD_FAILED;
+ }
+ }
+
if (!lock_vol(cmd, VG_GLOBAL, LCK_VG_WRITE, NULL)) {
log_error("Unable to obtain global lock.");
return ECMD_FAILED;
diff --git a/tools/tools.h b/tools/tools.h
index 4ed893fc4..793a871ac 100644
--- a/tools/tools.h
+++ b/tools/tools.h
@@ -105,6 +105,8 @@ struct arg_value_group_list {
#define LOCKD_VG_SH 0x00000020
/* Command does not process any metadata. */
#define NO_METADATA_PROCESSING 0x00000040
+/* Don't refresh lvmetad cache automatically, let command do it. */
+#define SKIP_AUTO_PVSCAN 0x00000080
/* a register of the lvm commands */
struct command {