|
|
5c2e41 |
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
|
5c2e41 |
From: Benjamin Marzinski <bmarzins@redhat.com>
|
|
|
5c2e41 |
Date: Tue, 27 Nov 2018 22:50:57 -0600
|
|
|
5c2e41 |
Subject: [PATCH] libmultipath: fix false removes in dmevents polling code
|
|
|
5c2e41 |
|
|
|
5c2e41 |
dm_is_mpath() would return 0 if either a device was not a multipath
|
|
|
5c2e41 |
device or if the libdevmapper command failed. Because dm_is_mpath()
|
|
|
5c2e41 |
didn't distinguish between these situations, dm_get_events() could
|
|
|
5c2e41 |
assume that a device was not really a multipath device, when in fact it
|
|
|
5c2e41 |
was, and the libdevmapper command simply failed. This would cause the
|
|
|
5c2e41 |
dmevents polling waiter to stop monitoring the device.
|
|
|
5c2e41 |
|
|
|
5c2e41 |
In reality, the call to dm_is_mpath() isn't necessary, because
|
|
|
5c2e41 |
dm_get_events() will already verify that the device name is on the list
|
|
|
5c2e41 |
of devices to wait for. However, if there are a large number of
|
|
|
5c2e41 |
non-multipath devices on the system, ignoring them can be useful. Thus,
|
|
|
5c2e41 |
if dm_is_mpath() successfully runs the libdevmapper command and verifies
|
|
|
5c2e41 |
that the device is not a multipath device, dm_get_events() should skip
|
|
|
5c2e41 |
it. But if the libdevmapper command fails, dm_get_events() should still
|
|
|
5c2e41 |
check the device list, to see if the device should be monitored.
|
|
|
5c2e41 |
|
|
|
5c2e41 |
This commit makes dm_is_mpath() return -1 for situations where
|
|
|
5c2e41 |
the libdevmapper command failed, and makes dm_get_events() only ignore
|
|
|
5c2e41 |
the device on a return of 0.
|
|
|
5c2e41 |
|
|
|
5c2e41 |
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
|
|
5c2e41 |
---
|
|
|
5c2e41 |
libmpathpersist/mpath_persist.c | 4 ++--
|
|
|
5c2e41 |
libmultipath/devmapper.c | 41 +++++++++++++++++++++++----------
|
|
|
5c2e41 |
multipath/main.c | 2 +-
|
|
|
5c2e41 |
multipathd/dmevents.c | 8 +++++--
|
|
|
5c2e41 |
multipathd/main.c | 2 +-
|
|
|
5c2e41 |
5 files changed, 39 insertions(+), 18 deletions(-)
|
|
|
5c2e41 |
|
|
|
5c2e41 |
diff --git a/libmpathpersist/mpath_persist.c b/libmpathpersist/mpath_persist.c
|
|
|
5c2e41 |
index 2ffe56e..7e8a676 100644
|
|
|
5c2e41 |
--- a/libmpathpersist/mpath_persist.c
|
|
|
5c2e41 |
+++ b/libmpathpersist/mpath_persist.c
|
|
|
5c2e41 |
@@ -188,7 +188,7 @@ int mpath_persistent_reserve_in (int fd, int rq_servact,
|
|
|
5c2e41 |
|
|
|
5c2e41 |
condlog(3, "alias = %s", alias);
|
|
|
5c2e41 |
map_present = dm_map_present(alias);
|
|
|
5c2e41 |
- if (map_present && !dm_is_mpath(alias)){
|
|
|
5c2e41 |
+ if (map_present && dm_is_mpath(alias) != 1){
|
|
|
5c2e41 |
condlog( 0, "%s: not a multipath device.", alias);
|
|
|
5c2e41 |
ret = MPATH_PR_DMMP_ERROR;
|
|
|
5c2e41 |
goto out;
|
|
|
5c2e41 |
@@ -283,7 +283,7 @@ int mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope,
|
|
|
5c2e41 |
condlog(3, "alias = %s", alias);
|
|
|
5c2e41 |
map_present = dm_map_present(alias);
|
|
|
5c2e41 |
|
|
|
5c2e41 |
- if (map_present && !dm_is_mpath(alias)){
|
|
|
5c2e41 |
+ if (map_present && dm_is_mpath(alias) != 1){
|
|
|
5c2e41 |
condlog(3, "%s: not a multipath device.", alias);
|
|
|
5c2e41 |
ret = MPATH_PR_DMMP_ERROR;
|
|
|
5c2e41 |
goto out;
|
|
|
5c2e41 |
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
|
|
|
5c2e41 |
index 0433b49..3294bd4 100644
|
|
|
5c2e41 |
--- a/libmultipath/devmapper.c
|
|
|
5c2e41 |
+++ b/libmultipath/devmapper.c
|
|
|
5c2e41 |
@@ -692,9 +692,15 @@ out:
|
|
|
5c2e41 |
return r;
|
|
|
5c2e41 |
}
|
|
|
5c2e41 |
|
|
|
5c2e41 |
+/*
|
|
|
5c2e41 |
+ * returns:
|
|
|
5c2e41 |
+ * 1 : is multipath device
|
|
|
5c2e41 |
+ * 0 : is not multipath device
|
|
|
5c2e41 |
+ * -1 : error
|
|
|
5c2e41 |
+ */
|
|
|
5c2e41 |
int dm_is_mpath(const char *name)
|
|
|
5c2e41 |
{
|
|
|
5c2e41 |
- int r = 0;
|
|
|
5c2e41 |
+ int r = -1;
|
|
|
5c2e41 |
struct dm_task *dmt;
|
|
|
5c2e41 |
struct dm_info info;
|
|
|
5c2e41 |
uint64_t start, length;
|
|
|
5c2e41 |
@@ -703,33 +709,44 @@ int dm_is_mpath(const char *name)
|
|
|
5c2e41 |
const char *uuid;
|
|
|
5c2e41 |
|
|
|
5c2e41 |
if (!(dmt = libmp_dm_task_create(DM_DEVICE_TABLE)))
|
|
|
5c2e41 |
- return 0;
|
|
|
5c2e41 |
+ goto out;
|
|
|
5c2e41 |
|
|
|
5c2e41 |
if (!dm_task_set_name(dmt, name))
|
|
|
5c2e41 |
- goto out;
|
|
|
5c2e41 |
+ goto out_task;
|
|
|
5c2e41 |
|
|
|
5c2e41 |
dm_task_no_open_count(dmt);
|
|
|
5c2e41 |
|
|
|
5c2e41 |
if (!dm_task_run(dmt))
|
|
|
5c2e41 |
- goto out;
|
|
|
5c2e41 |
+ goto out_task;
|
|
|
5c2e41 |
|
|
|
5c2e41 |
- if (!dm_task_get_info(dmt, &info) || !info.exists)
|
|
|
5c2e41 |
- goto out;
|
|
|
5c2e41 |
+ if (!dm_task_get_info(dmt, &info))
|
|
|
5c2e41 |
+ goto out_task;
|
|
|
5c2e41 |
+
|
|
|
5c2e41 |
+ r = 0;
|
|
|
5c2e41 |
+
|
|
|
5c2e41 |
+ if (!info.exists)
|
|
|
5c2e41 |
+ goto out_task;
|
|
|
5c2e41 |
|
|
|
5c2e41 |
uuid = dm_task_get_uuid(dmt);
|
|
|
5c2e41 |
|
|
|
5c2e41 |
if (!uuid || strncmp(uuid, UUID_PREFIX, UUID_PREFIX_LEN) != 0)
|
|
|
5c2e41 |
- goto out;
|
|
|
5c2e41 |
+ goto out_task;
|
|
|
5c2e41 |
|
|
|
5c2e41 |
/* Fetch 1st target */
|
|
|
5c2e41 |
- dm_get_next_target(dmt, NULL, &start, &length, &target_type, ¶ms);
|
|
|
5c2e41 |
+ if (dm_get_next_target(dmt, NULL, &start, &length, &target_type,
|
|
|
5c2e41 |
+ ¶ms) != NULL)
|
|
|
5c2e41 |
+ /* multiple targets */
|
|
|
5c2e41 |
+ goto out_task;
|
|
|
5c2e41 |
|
|
|
5c2e41 |
if (!target_type || strcmp(target_type, TGT_MPATH) != 0)
|
|
|
5c2e41 |
- goto out;
|
|
|
5c2e41 |
+ goto out_task;
|
|
|
5c2e41 |
|
|
|
5c2e41 |
r = 1;
|
|
|
5c2e41 |
-out:
|
|
|
5c2e41 |
+out_task:
|
|
|
5c2e41 |
dm_task_destroy(dmt);
|
|
|
5c2e41 |
+out:
|
|
|
5c2e41 |
+ if (r < 0)
|
|
|
5c2e41 |
+ condlog(2, "%s: dm command failed in %s", name, __FUNCTION__);
|
|
|
5c2e41 |
return r;
|
|
|
5c2e41 |
}
|
|
|
5c2e41 |
|
|
|
5c2e41 |
@@ -823,7 +840,7 @@ int _dm_flush_map (const char * mapname, int need_sync, int deferred_remove,
|
|
|
5c2e41 |
unsigned long long mapsize;
|
|
|
5c2e41 |
char params[PARAMS_SIZE] = {0};
|
|
|
5c2e41 |
|
|
|
5c2e41 |
- if (!dm_is_mpath(mapname))
|
|
|
5c2e41 |
+ if (dm_is_mpath(mapname) != 1)
|
|
|
5c2e41 |
return 0; /* nothing to do */
|
|
|
5c2e41 |
|
|
|
5c2e41 |
/* if the device currently has no partitions, do not
|
|
|
5c2e41 |
@@ -1087,7 +1104,7 @@ dm_get_maps (vector mp)
|
|
|
5c2e41 |
}
|
|
|
5c2e41 |
|
|
|
5c2e41 |
do {
|
|
|
5c2e41 |
- if (!dm_is_mpath(names->name))
|
|
|
5c2e41 |
+ if (dm_is_mpath(names->name) != 1)
|
|
|
5c2e41 |
goto next;
|
|
|
5c2e41 |
|
|
|
5c2e41 |
mpp = dm_get_multipath(names->name);
|
|
|
5c2e41 |
diff --git a/multipath/main.c b/multipath/main.c
|
|
|
5c2e41 |
index ccb6091..2c4054d 100644
|
|
|
5c2e41 |
--- a/multipath/main.c
|
|
|
5c2e41 |
+++ b/multipath/main.c
|
|
|
5c2e41 |
@@ -321,7 +321,7 @@ static int check_usable_paths(struct config *conf,
|
|
|
5c2e41 |
goto out;
|
|
|
5c2e41 |
}
|
|
|
5c2e41 |
|
|
|
5c2e41 |
- if (!dm_is_mpath(mapname)) {
|
|
|
5c2e41 |
+ if (dm_is_mpath(mapname) != 1) {
|
|
|
5c2e41 |
condlog(1, "%s is not a multipath map", devpath);
|
|
|
5c2e41 |
goto free;
|
|
|
5c2e41 |
}
|
|
|
5c2e41 |
diff --git a/multipathd/dmevents.c b/multipathd/dmevents.c
|
|
|
5c2e41 |
index 31e64a7..0034892 100644
|
|
|
5c2e41 |
--- a/multipathd/dmevents.c
|
|
|
5c2e41 |
+++ b/multipathd/dmevents.c
|
|
|
5c2e41 |
@@ -168,7 +168,9 @@ static int dm_get_events(void)
|
|
|
5c2e41 |
while (names->dev) {
|
|
|
5c2e41 |
uint32_t event_nr;
|
|
|
5c2e41 |
|
|
|
5c2e41 |
- if (!dm_is_mpath(names->name))
|
|
|
5c2e41 |
+ /* Don't delete device if dm_is_mpath() fails without
|
|
|
5c2e41 |
+ * checking the device type */
|
|
|
5c2e41 |
+ if (dm_is_mpath(names->name) == 0)
|
|
|
5c2e41 |
goto next;
|
|
|
5c2e41 |
|
|
|
5c2e41 |
event_nr = dm_event_nr(names);
|
|
|
5c2e41 |
@@ -204,7 +206,9 @@ int watch_dmevents(char *name)
|
|
|
5c2e41 |
struct dev_event *dev_evt, *old_dev_evt;
|
|
|
5c2e41 |
int i;
|
|
|
5c2e41 |
|
|
|
5c2e41 |
- if (!dm_is_mpath(name)) {
|
|
|
5c2e41 |
+ /* We know that this is a multipath device, so only fail if
|
|
|
5c2e41 |
+ * device-mapper tells us that we're wrong */
|
|
|
5c2e41 |
+ if (dm_is_mpath(name) == 0) {
|
|
|
5c2e41 |
condlog(0, "%s: not a multipath device. can't watch events",
|
|
|
5c2e41 |
name);
|
|
|
5c2e41 |
return -1;
|
|
|
5c2e41 |
diff --git a/multipathd/main.c b/multipathd/main.c
|
|
|
5c2e41 |
index 4e2835d..82a298b 100644
|
|
|
5c2e41 |
--- a/multipathd/main.c
|
|
|
5c2e41 |
+++ b/multipathd/main.c
|
|
|
5c2e41 |
@@ -678,7 +678,7 @@ ev_add_map (char * dev, const char * alias, struct vectors * vecs)
|
|
|
5c2e41 |
int delayed_reconfig, reassign_maps;
|
|
|
5c2e41 |
struct config *conf;
|
|
|
5c2e41 |
|
|
|
5c2e41 |
- if (!dm_is_mpath(alias)) {
|
|
|
5c2e41 |
+ if (dm_is_mpath(alias) != 1) {
|
|
|
5c2e41 |
condlog(4, "%s: not a multipath map", alias);
|
|
|
5c2e41 |
return 0;
|
|
|
5c2e41 |
}
|
|
|
5c2e41 |
--
|
|
|
5c2e41 |
2.17.2
|
|
|
5c2e41 |
|