Blame SOURCES/0019-libmultipath-fix-false-removes-in-dmevents-polling-c.patch

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, &params);
5c2e41
+	if (dm_get_next_target(dmt, NULL, &start, &length, &target_type,
5c2e41
+			       &params) != 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