summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlasdair G Kergon <agk@redhat.com>2016-08-23 02:24:30 +0100
committerAlasdair G Kergon <agk@redhat.com>2016-08-23 02:26:14 +0100
commit952e4133283ac4a593d0fa8daccdc55c907379de (patch)
tree3176d81099276864b0301c3e7999921e0ed2ff87
parent7646741ec67845f47b77eb647ef0fedc78d6b92c (diff)
downloadlvm2-952e4133283ac4a593d0fa8daccdc55c907379de.tar.gz
dmeventd: Fix unmonitoring when segtype changes.
When the segment type is being changed, unmonitoring an LV requires the existing dso to be specified as a parameter, not the new one.
-rw-r--r--WHATS_NEW1
-rw-r--r--lib/activate/activate.c90
2 files changed, 89 insertions, 2 deletions
diff --git a/WHATS_NEW b/WHATS_NEW
index 0b2301867..fdf63e423 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.02.165 -
===================================
+ Fix dmeventd unmonitoring when segment type (and dso) changes.
Don't allow lvconvert --repair on raid0 devices or attempt to monitor them.
No longer adjust incorrect number of raid stripes supplied to lvcreate.
Move lcm and gcd to lib/misc.
diff --git a/lib/activate/activate.c b/lib/activate/activate.c
index d4c297ea3..908c41103 100644
--- a/lib/activate/activate.c
+++ b/lib/activate/activate.c
@@ -1548,7 +1548,7 @@ static struct dm_event_handler *_create_dm_event_handler(struct cmd_context *cmd
if (dm_event_handler_set_dmeventd_path(dmevh, find_config_tree_str(cmd, dmeventd_executable_CFG, NULL)))
goto_bad;
- if (dm_event_handler_set_dso(dmevh, dso))
+ if (dso && dm_event_handler_set_dso(dmevh, dso))
goto_bad;
if (dm_event_handler_set_uuid(dmevh, dmuuid))
@@ -1592,6 +1592,39 @@ static char *_build_target_uuid(struct cmd_context *cmd, const struct logical_vo
return build_dm_uuid(cmd->mem, lv, layer);
}
+static int _device_registered_with_dmeventd(struct cmd_context *cmd, const struct logical_volume *lv, int *pending, const char **dso)
+{
+ char *uuid;
+ enum dm_event_mask evmask = 0;
+ struct dm_event_handler *dmevh;
+
+ *pending = 0;
+
+ if (!(uuid = _build_target_uuid(cmd, lv)))
+ return_0;
+
+ if (!(dmevh = _create_dm_event_handler(cmd, uuid, NULL, 0, DM_EVENT_ALL_ERRORS)))
+ return_0;
+
+ if (dm_event_get_registered_device(dmevh, 0)) {
+ dm_event_handler_destroy(dmevh);
+ return 0;
+ }
+
+ evmask = dm_event_handler_get_event_mask(dmevh);
+ if (evmask & DM_EVENT_REGISTRATION_PENDING) {
+ *pending = 1;
+ evmask &= ~DM_EVENT_REGISTRATION_PENDING;
+ }
+
+ if (dso && (*dso = dm_event_handler_get_dso(dmevh)) && !(*dso = dm_pool_strdup(cmd->mem, *dso)))
+ log_error("Failed to duplicate dso name.");
+
+ dm_event_handler_destroy(dmevh);
+
+ return evmask;
+}
+
int target_registered_with_dmeventd(struct cmd_context *cmd, const char *dso,
const struct logical_volume *lv, int *pending)
{
@@ -1657,6 +1690,48 @@ int target_register_events(struct cmd_context *cmd, const char *dso, const struc
#endif
+#ifdef DMEVENTD
+/* FIXME Restructure all this code so that unmonitoring works cleanly regardless of current target type. */
+static int _segment_independent_unmonitor(struct cmd_context *cmd, const struct logical_volume *lv, const char *dso)
+{
+ int i, pending = 0, monitored;
+ int r;
+
+ log_verbose("Not monitoring %s with %s%s", display_lvname(lv), dso, test_mode() ? " [Test mode: skipping this]" : "");
+
+ /* FIXME Test mode should really continue a bit further. */
+ if (test_mode())
+ return 1;
+
+ if (!target_register_events(cmd, dso, lv, 0, 0, 0)) {
+ log_error("%s: segment unmonitoring function failed.",
+ display_lvname(lv));
+
+ return 0;
+ }
+
+ /* Check [un]monitor results */
+ /* Try a couple times if pending, but not forever... */
+ for (i = 0; i < 40; i++) {
+ pending = 0;
+ monitored = _device_registered_with_dmeventd(cmd, lv, &pending, NULL);
+ if (pending || monitored)
+ log_very_verbose("%s unmonitoring still pending: waiting...",
+ display_lvname(lv));
+ else
+ break;
+ usleep(10000 * i);
+ }
+
+ r = !monitored;
+
+ if (!r && !error_message_produced())
+ log_error("Not monitoring %s failed.", display_lvname(lv));
+
+ return r;
+}
+#endif
+
/*
* Returns 0 if an attempt to (un)monitor the device failed.
* Returns 1 otherwise.
@@ -1674,6 +1749,7 @@ int monitor_dev_for_events(struct cmd_context *cmd, const struct logical_volume
uint32_t s;
static const struct lv_activate_opts zlaopts = { 0 };
struct lvinfo info;
+ const char *dso;
if (!laopts)
laopts = &zlaopts;
@@ -1781,7 +1857,11 @@ int monitor_dev_for_events(struct cmd_context *cmd, const struct logical_volume
!seg->segtype->ops->target_monitored) /* doesn't support registration */
continue;
- monitored = seg->segtype->ops->target_monitored(seg, &pending);
+ if (!monitor)
+ /* When unmonitoring, obtain existing dso being used. */
+ monitored = _device_registered_with_dmeventd(cmd, seg->lv, &pending, &dso);
+ else
+ monitored = seg->segtype->ops->target_monitored(seg, &pending);
/* FIXME: We should really try again if pending */
monitored = (pending) ? 0 : monitored;
@@ -1796,6 +1876,12 @@ int monitor_dev_for_events(struct cmd_context *cmd, const struct logical_volume
} else {
if (!monitored)
log_verbose("%s already not monitored.", display_lvname(lv));
+ else if (*dso)
+ /*
+ * Divert unmonitor away from code that depends on the new segment
+ * type instead of the existing one if it's changing.
+ */
+ return _segment_independent_unmonitor(cmd, lv, dso);
else if (seg->segtype->ops->target_unmonitor_events)
monitor_fn = seg->segtype->ops->target_unmonitor_events;
}