device-mapper-multipath-0.9.6-1

Update to the head of the upstream staging branch
Rename redhat patches
  * Previous patches 0001-0012 are now patches 0041-0052
Add 0053-RH-Add-mpathcleanup.patch
  * add mpathcleanup program
This commit is contained in:
Benjamin Marzinski 2023-09-22 15:29:43 -05:00
parent d88fe4b956
commit e5eddaae1a
56 changed files with 9256 additions and 89 deletions

1
.gitignore vendored
View File

@ -28,3 +28,4 @@ multipath-tools-091027.tar.gz
/multipath-tools-0.9.3.tgz
/multipath-tools-0.9.4.tgz
/multipath-tools-0.9.5.tgz
/multipath-tools-0.9.6.tgz

View File

@ -0,0 +1,51 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Tue, 22 Aug 2023 16:21:43 +0200
Subject: [PATCH] libmultipath: sysfs_set_scsi_tmo: do nothing for ACT_DRY_RUN
"multipath -d" might change sysfs timeouts of SCSI devices.
Make sure it doesn't.
Signed-off-by: Martin Wilck <mwilck@suse.com>
Cc: Jehan Singh <jehan.singh@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/configure.c | 4 ++--
libmultipath/discovery.c | 3 +++
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/libmultipath/configure.c b/libmultipath/configure.c
index 9513baae..029fbbd2 100644
--- a/libmultipath/configure.c
+++ b/libmultipath/configure.c
@@ -1193,13 +1193,13 @@ int coalesce_paths (struct vectors *vecs, vector mpvec, char *refwwid,
if (cmpp)
mpp->queue_mode = cmpp->queue_mode;
+ if (cmd == CMD_DRY_RUN && mpp->action == ACT_UNDEF)
+ mpp->action = ACT_DRY_RUN;
if (setup_map(mpp, &params, vecs)) {
remove_map(mpp, vecs->pathvec, NULL);
continue;
}
- if (cmd == CMD_DRY_RUN)
- mpp->action = ACT_DRY_RUN;
if (mpp->action == ACT_UNDEF)
select_action(mpp, curmp,
force_reload == FORCE_RELOAD_YES ? 1 : 0);
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
index e4de48e7..84ce5fe7 100644
--- a/libmultipath/discovery.c
+++ b/libmultipath/discovery.c
@@ -857,6 +857,9 @@ sysfs_set_scsi_tmo (struct config *conf, struct multipath *mpp)
bool warn_dev_loss = false;
bool warn_fast_io_fail = false;
+ if (mpp->action == ACT_DRY_RUN || mpp->action == ACT_REJECT)
+ return 0;
+
if (mpp->no_path_retry > 0) {
uint64_t no_path_retry_tmo =
(uint64_t)mpp->no_path_retry * conf->checkint;

View File

@ -0,0 +1,75 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Tue, 22 Aug 2023 21:36:11 +0200
Subject: [PATCH] libmultipath: add alias_already_taken()
Factor out a trivial helper function.
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/alias.c | 32 +++++++++++++++++++-------------
1 file changed, 19 insertions(+), 13 deletions(-)
diff --git a/libmultipath/alias.c b/libmultipath/alias.c
index c0139a2e..83ded886 100644
--- a/libmultipath/alias.c
+++ b/libmultipath/alias.c
@@ -8,6 +8,7 @@
#include <string.h>
#include <limits.h>
#include <stdio.h>
+#include <stdbool.h>
#include "debug.h"
#include "util.h"
@@ -109,30 +110,35 @@ scan_devname(const char *alias, const char *prefix)
return n;
}
-static int
-id_already_taken(int id, const char *prefix, const char *map_wwid)
+static bool alias_already_taken(const char *alias, const char *map_wwid)
{
- STRBUF_ON_STACK(buf);
- const char *alias;
-
- if (append_strbuf_str(&buf, prefix) < 0 ||
- format_devname(&buf, id) < 0)
- return 0;
- alias = get_strbuf_str(&buf);
if (dm_map_present(alias)) {
char wwid[WWID_SIZE];
/* If both the name and the wwid match, then it's fine.*/
if (dm_get_uuid(alias, wwid, sizeof(wwid)) == 0 &&
strncmp(map_wwid, wwid, sizeof(wwid)) == 0)
- return 0;
- condlog(3, "%s: alias '%s' already taken, but not in bindings file. reselecting alias", map_wwid, alias);
- return 1;
+ return false;
+ condlog(3, "%s: alias '%s' already taken, but not in bindings file. reselecting alias",
+ map_wwid, alias);
+ return true;
}
- return 0;
+ return false;
}
+static bool id_already_taken(int id, const char *prefix, const char *map_wwid)
+{
+ STRBUF_ON_STACK(buf);
+ const char *alias;
+
+ if (append_strbuf_str(&buf, prefix) < 0 ||
+ format_devname(&buf, id) < 0)
+ return false;
+
+ alias = get_strbuf_str(&buf);
+ return alias_already_taken(alias, map_wwid);
+}
/*
* Returns: 0 if matching entry in WWIDs file found

View File

@ -0,0 +1,207 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Tue, 22 Aug 2023 22:00:58 +0200
Subject: [PATCH] libmultipath: unify use_existing_alias() and
get_user_friendly_alias()
These functions are only called from select_alias(). The logic
is more obvious when unified in a single function.
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/alias.c | 82 ++++++++++++------------------------------
libmultipath/alias.h | 9 ++---
libmultipath/propsel.c | 19 +++++-----
3 files changed, 34 insertions(+), 76 deletions(-)
diff --git a/libmultipath/alias.c b/libmultipath/alias.c
index 83ded886..68f5d848 100644
--- a/libmultipath/alias.c
+++ b/libmultipath/alias.c
@@ -329,13 +329,13 @@ allocate_binding(int fd, const char *wwid, int id, const char *prefix)
return alias;
}
-char *
-use_existing_alias (const char *wwid, const char *file, const char *alias_old,
- const char *prefix, int bindings_read_only)
+char *get_user_friendly_alias(const char *wwid, const char *file, const char *alias_old,
+ const char *prefix, bool bindings_read_only)
{
char *alias = NULL;
int id = 0;
int fd, can_write;
+ bool new_binding = false;
char buff[WWID_SIZE];
FILE *f;
@@ -349,6 +349,10 @@ use_existing_alias (const char *wwid, const char *file, const char *alias_old,
close(fd);
return NULL;
}
+
+ if (!strlen(alias_old))
+ goto new_alias;
+
/* lookup the binding. if it exists, the wwid will be in buff
* either way, id contains the id for the alias
*/
@@ -358,14 +362,14 @@ use_existing_alias (const char *wwid, const char *file, const char *alias_old,
/* if buff is our wwid, it's already
* allocated correctly
*/
- if (strcmp(buff, wwid) == 0)
+ if (strcmp(buff, wwid) == 0) {
alias = strdup(alias_old);
- else {
- alias = NULL;
+ goto out;
+ } else {
condlog(0, "alias %s already bound to wwid %s, cannot reuse",
alias_old, buff);
+ goto new_alias;
}
- goto out;
}
id = lookup_binding(f, wwid, &alias, NULL, 0);
@@ -377,8 +381,15 @@ use_existing_alias (const char *wwid, const char *file, const char *alias_old,
/* allocate the existing alias in the bindings file */
id = scan_devname(alias_old, prefix);
- if (id <= 0)
- goto out;
+
+new_alias:
+ if (id <= 0) {
+ id = lookup_binding(f, wwid, &alias, prefix, 1);
+ if (id <= 0)
+ goto out;
+ else
+ new_binding = true;
+ }
if (fflush(f) != 0) {
condlog(0, "cannot fflush bindings file stream : %s",
@@ -388,8 +399,9 @@ use_existing_alias (const char *wwid, const char *file, const char *alias_old,
if (can_write && !bindings_read_only) {
alias = allocate_binding(fd, wwid, id, prefix);
- condlog(0, "Allocated existing binding [%s] for WWID [%s]",
- alias, wwid);
+ if (alias && !new_binding)
+ condlog(2, "Allocated existing binding [%s] for WWID [%s]",
+ alias, wwid);
}
out:
@@ -399,54 +411,6 @@ out:
return alias;
}
-char *
-get_user_friendly_alias(const char *wwid, const char *file, const char *prefix,
- int bindings_read_only)
-{
- char *alias;
- int fd, id;
- FILE *f;
- int can_write;
-
- if (!wwid || *wwid == '\0') {
- condlog(3, "Cannot find binding for empty WWID");
- return NULL;
- }
-
- fd = open_file(file, &can_write, bindings_file_header);
- if (fd < 0)
- return NULL;
-
- f = fdopen(fd, "r");
- if (!f) {
- condlog(0, "cannot fdopen on bindings file descriptor : %s",
- strerror(errno));
- close(fd);
- return NULL;
- }
-
- id = lookup_binding(f, wwid, &alias, prefix, 1);
- if (id < 0) {
- fclose(f);
- return NULL;
- }
-
- pthread_cleanup_push(free, alias);
-
- if (fflush(f) != 0) {
- condlog(0, "cannot fflush bindings file stream : %s",
- strerror(errno));
- free(alias);
- alias = NULL;
- } else if (can_write && !bindings_read_only && !alias)
- alias = allocate_binding(fd, wwid, id, prefix);
-
- fclose(f);
-
- pthread_cleanup_pop(0);
- return alias;
-}
-
int
get_user_friendly_wwid(const char *alias, char *buff, const char *file)
{
diff --git a/libmultipath/alias.h b/libmultipath/alias.h
index dbc950c4..fa332233 100644
--- a/libmultipath/alias.h
+++ b/libmultipath/alias.h
@@ -2,13 +2,10 @@
#define _ALIAS_H
int valid_alias(const char *alias);
-char *get_user_friendly_alias(const char *wwid, const char *file,
- const char *prefix,
- int bindings_readonly);
int get_user_friendly_wwid(const char *alias, char *buff, const char *file);
-char *use_existing_alias (const char *wwid, const char *file,
- const char *alias_old,
- const char *prefix, int bindings_read_only);
+char *get_user_friendly_alias(const char *wwid, const char *file,
+ const char *alias_old,
+ const char *prefix, bool bindings_read_only);
struct config;
int check_alias_settings(const struct config *);
diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c
index d6bce129..354e883f 100644
--- a/libmultipath/propsel.c
+++ b/libmultipath/propsel.c
@@ -401,19 +401,16 @@ int select_alias(struct config *conf, struct multipath * mp)
select_alias_prefix(conf, mp);
- if (strlen(mp->alias_old) > 0) {
- mp->alias = use_existing_alias(mp->wwid, conf->bindings_file,
- mp->alias_old, mp->alias_prefix,
- conf->bindings_read_only);
- memset (mp->alias_old, 0, WWID_SIZE);
- origin = "(setting: using existing alias)";
- }
+ mp->alias = get_user_friendly_alias(mp->wwid, conf->bindings_file,
+ mp->alias_old, mp->alias_prefix,
+ conf->bindings_read_only);
- if (mp->alias == NULL) {
- mp->alias = get_user_friendly_alias(mp->wwid,
- conf->bindings_file, mp->alias_prefix, conf->bindings_read_only);
+ if (mp->alias && !strncmp(mp->alias, mp->alias_old, WWID_SIZE))
+ origin = "(setting: using existing alias)";
+ else if (mp->alias)
origin = "(setting: user_friendly_name)";
- }
+ memset (mp->alias_old, 0, WWID_SIZE);
+
out:
if (mp->alias == NULL) {
mp->alias = strdup(mp->wwid);

View File

@ -0,0 +1,101 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Tue, 22 Aug 2023 22:23:29 +0200
Subject: [PATCH] libmultipath: never allocate an alias that's already taken
If the bindings file is changed in a way that multipathd can't handle
(e.g. by swapping the aliases of two maps), multipathd must not try
to re-use an alias that is already used by another map. Creating
or renaming a map with such an alias will fail. We already avoid
this for some cases, but not for all. Fix it.
Signed-off-by: Martin Wilck <mwilck@suse.com>
Cc: David Bond <dbond@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/alias.c | 31 +++++++++++++++++++++++--------
tests/alias.c | 2 +-
2 files changed, 24 insertions(+), 9 deletions(-)
diff --git a/libmultipath/alias.c b/libmultipath/alias.c
index 68f5d848..3e3dfe98 100644
--- a/libmultipath/alias.c
+++ b/libmultipath/alias.c
@@ -120,7 +120,7 @@ static bool alias_already_taken(const char *alias, const char *map_wwid)
if (dm_get_uuid(alias, wwid, sizeof(wwid)) == 0 &&
strncmp(map_wwid, wwid, sizeof(wwid)) == 0)
return false;
- condlog(3, "%s: alias '%s' already taken, but not in bindings file. reselecting alias",
+ condlog(3, "%s: alias '%s' already taken, reselecting alias",
map_wwid, alias);
return true;
}
@@ -359,12 +359,11 @@ char *get_user_friendly_alias(const char *wwid, const char *file, const char *al
rlookup_binding(f, buff, alias_old);
if (strlen(buff) > 0) {
- /* if buff is our wwid, it's already
- * allocated correctly
- */
+ /* If buff is our wwid, it's already allocated correctly. */
if (strcmp(buff, wwid) == 0) {
alias = strdup(alias_old);
goto out;
+
} else {
condlog(0, "alias %s already bound to wwid %s, cannot reuse",
alias_old, buff);
@@ -372,19 +371,35 @@ char *get_user_friendly_alias(const char *wwid, const char *file, const char *al
}
}
- id = lookup_binding(f, wwid, &alias, NULL, 0);
+ /*
+ * Look for an existing alias in the bindings file.
+ * Pass prefix = NULL, so lookup_binding() won't try to allocate a new id.
+ */
+ lookup_binding(f, wwid, &alias, NULL, 0);
if (alias) {
- condlog(3, "Use existing binding [%s] for WWID [%s]",
- alias, wwid);
+ if (alias_already_taken(alias, wwid)) {
+ free(alias);
+ alias = NULL;
+ } else
+ condlog(3, "Use existing binding [%s] for WWID [%s]",
+ alias, wwid);
goto out;
}
- /* allocate the existing alias in the bindings file */
+ /* alias_old is already taken by our WWID, update bindings file. */
id = scan_devname(alias_old, prefix);
new_alias:
if (id <= 0) {
+ /*
+ * no existing alias was provided, or allocating it
+ * failed. Try a new one.
+ */
id = lookup_binding(f, wwid, &alias, prefix, 1);
+ if (id == 0 && alias_already_taken(alias, wwid)) {
+ free(alias);
+ alias = NULL;
+ }
if (id <= 0)
goto out;
else
diff --git a/tests/alias.c b/tests/alias.c
index 3ca6c28b..11f209e0 100644
--- a/tests/alias.c
+++ b/tests/alias.c
@@ -398,7 +398,7 @@ static void mock_self_alias(const char *alias, const char *wwid)
will_return(__wrap_dm_get_uuid, wwid);
}
-#define USED_STR(alias_str, wwid_str) wwid_str ": alias '" alias_str "' already taken, but not in bindings file. reselecting alias\n"
+#define USED_STR(alias_str, wwid_str) wwid_str ": alias '" alias_str "' already taken, reselecting alias\n"
static void mock_failed_alias(const char *alias, char *msg)
{

View File

@ -0,0 +1,61 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Tue, 22 Aug 2023 22:30:16 +0200
Subject: [PATCH] libmultipath: lookup_binding: add comment about the algorithm
When I read this code, I always get confused. Adding comments to
explain the algorithm.
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/alias.c | 35 +++++++++++++++++++++++++++++++++++
1 file changed, 35 insertions(+)
diff --git a/libmultipath/alias.c b/libmultipath/alias.c
index 3e3dfe98..9e9ac563 100644
--- a/libmultipath/alias.c
+++ b/libmultipath/alias.c
@@ -172,6 +172,41 @@ lookup_binding(FILE *f, const char *map_wwid, char **map_alias,
alias = strtok_r(buf, " \t", &saveptr);
if (!alias) /* blank line */
continue;
+
+ /*
+ * Find an unused index - explanation of the algorithm
+ *
+ * ID: 1 = mpatha, 2 = mpathb, ...
+ *
+ * We assume the bindings are unsorted. The only constraint
+ * is that no ID occurs more than once. IDs that occur in the
+ * bindings are called "used".
+ *
+ * We call the list 1,2,3,..., exactly in this order, the list
+ * of "expected" IDs. The variable "id" always holds the next
+ * "expected" ID, IOW the last "expected" ID encountered plus 1.
+ * Thus all IDs below "id" are known to be used. However, at the
+ * end of the loop, the value of "id" isn't necessarily unused.
+ *
+ * "smallest_bigger_id" is the smallest used ID that was
+ * encountered while it was larger than the next "expected" ID
+ * at that iteration. Let X be some used ID. If all IDs below X
+ * are used and encountered in the right sequence before X, "id"
+ * will be > X when the loop ends. Otherwise, X was encountered
+ * "out of order", the condition (X > id) holds when X is
+ * encountered, and "smallest_bigger_id" will be set to X; i.e.
+ * it will be less or equal than X when the loop ends.
+ *
+ * At the end of the loop, (id < smallest_bigger_id) means that
+ * the value of "id" had been encountered neither in order nor
+ * out of order, and is thus unused. (id >= smallest_bigger_id)
+ * means that "id"'s value is in use. In this case, we play safe
+ * and use "biggest_id + 1" as the next value to try.
+ *
+ * biggest_id is always > smallest_bigger_id, except in the
+ * "perfectly ordered" case.
+ */
+
curr_id = scan_devname(alias, prefix);
if (curr_id == id) {
if (id < INT_MAX)

View File

@ -0,0 +1,35 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Wed, 23 Aug 2023 22:56:41 +0200
Subject: [PATCH] multipath-tools test: simplify debugging for condlog mismatch
If there's a mismatch between expected and actual log message,
print both messages.
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
tests/test-log.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/tests/test-log.c b/tests/test-log.c
index c1745872..63516999 100644
--- a/tests/test-log.c
+++ b/tests/test-log.c
@@ -16,12 +16,14 @@ void __wrap_dlog (int prio, const char * fmt, ...)
va_list ap;
char *expected;
- check_expected(prio);
va_start(ap, fmt);
vsnprintf(buff, MAX_MSG_SIZE, fmt, ap);
va_end(ap);
fprintf(stderr, "%s(%d): %s", __func__, prio, buff);
expected = mock_ptr_type(char *);
+ if (memcmp(expected, buff, strlen(expected)))
+ fprintf(stderr, "%s(expected): %s", __func__, expected);
+ check_expected(prio);
assert_memory_equal(buff, expected, strlen(expected));
}

View File

@ -0,0 +1,493 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Wed, 23 Aug 2023 22:57:29 +0200
Subject: [PATCH] multipath-tools tests: add tests for
get_user_friendly_alias()
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
tests/alias.c | 441 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 441 insertions(+)
diff --git a/tests/alias.c b/tests/alias.c
index 11f209e0..7e443b06 100644
--- a/tests/alias.c
+++ b/tests/alias.c
@@ -81,6 +81,35 @@ int __wrap_dm_get_uuid(const char *name, char *uuid, int uuid_len)
return ret;
}
+#define TEST_FDNO 1234
+#define TEST_FPTR ((FILE *) 0xaffe)
+
+int __wrap_open_file(const char *file, int *can_write, const char *header)
+{
+ int cw = mock_type(int);
+
+ *can_write = cw;
+ return TEST_FDNO;
+}
+
+FILE *__wrap_fdopen(int fd, const char *mode)
+{
+ assert_int_equal(fd, TEST_FDNO);
+ return TEST_FPTR;
+}
+
+int __wrap_fflush(FILE *f)
+{
+ assert_ptr_equal(f, TEST_FPTR);
+ return 0;
+}
+
+int __wrap_fclose(FILE *f)
+{
+ assert_ptr_equal(f, TEST_FPTR);
+ return 0;
+}
+
/* strbuf wrapper for the old format_devname() */
static int __format_devname(char *name, int id, size_t len, const char *prefix)
{
@@ -399,6 +428,22 @@ static void mock_self_alias(const char *alias, const char *wwid)
}
#define USED_STR(alias_str, wwid_str) wwid_str ": alias '" alias_str "' already taken, reselecting alias\n"
+#define NOMATCH_STR(alias_str) ("No matching alias [" alias_str "] in bindings file.\n")
+#define FOUND_STR(alias_str, wwid_str) \
+ "Found matching wwid [" wwid_str "] in bindings file." \
+ " Setting alias to " alias_str "\n"
+#define FOUND_ALIAS_STR(alias_str, wwid_str) \
+ "Found matching alias [" alias_str "] in bindings file." \
+ " Setting wwid to " wwid_str "\n"
+#define NOMATCH_WWID_STR(wwid_str) ("No matching wwid [" wwid_str "] in bindings file.\n")
+#define NEW_STR(alias_str, wwid_str) ("Created new binding [" alias_str "] for WWID [" wwid_str "]\n")
+#define EXISTING_STR(alias_str, wwid_str) ("Use existing binding [" alias_str "] for WWID [" wwid_str "]\n")
+#define ALLOC_STR(alias_str, wwid_str) ("Allocated existing binding [" alias_str "] for WWID [" wwid_str "]\n")
+#define BINDING_STR(alias_str, wwid_str) (alias_str " " wwid_str "\n")
+#define BOUND_STR(alias_str, wwid_str) ("alias "alias_str " already bound to wwid " wwid_str ", cannot reuse")
+#define ERR_STR(alias_str, wwid_str) ("ERROR: old alias [" alias_str "] for wwid [" wwid_str "] is used by other map\n")
+#define REUSE_STR(alias_str, wwid_str) ("alias " alias_str " already bound to wwid " wwid_str ", cannot reuse\n")
+#define NOMORE_STR "no more available user_friendly_names\n"
static void mock_failed_alias(const char *alias, char *msg)
{
@@ -421,6 +466,24 @@ static void mock_used_alias(const char *alias, char *msg)
expect_condlog(3, msg);
}
+static void mock_bindings_file(const char *content, int match_line)
+{
+ static char cnt[1024];
+ char *token;
+ int i;
+
+ assert_in_range(strlcpy(cnt, content, sizeof(cnt)), 0, sizeof(cnt) - 1);
+
+ for (token = strtok(cnt, "\n"), i = 0;
+ token && *token;
+ token = strtok(NULL, "\n"), i++) {
+ will_return(__wrap_fgets, token);
+ if (match_line == i)
+ return;
+ }
+ will_return(__wrap_fgets, NULL);
+}
+
static void lb_empty(void **state)
{
int rc;
@@ -1147,6 +1210,382 @@ static int test_allocate_binding(void)
return cmocka_run_group_tests(tests, NULL, NULL);
}
+#define mock_allocate_binding(alias, wwid) \
+ do { \
+ static const char ln[] = BINDING_STR(alias, wwid); \
+ \
+ will_return(__wrap_lseek, 0); \
+ expect_value(__wrap_write, count, strlen(ln)); \
+ expect_string(__wrap_write, buf, ln); \
+ will_return(__wrap_write, strlen(ln)); \
+ expect_condlog(3, NEW_STR(alias, wwid)); \
+ } while (0)
+
+static void gufa_empty_new_rw(void **state) {
+ char *alias;
+
+ will_return(__wrap_open_file, true);
+
+ will_return(__wrap_fgets, NULL);
+ mock_unused_alias("MPATHa");
+ expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
+
+ mock_allocate_binding("MPATHa", "WWID0");
+ alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", false);
+ assert_string_equal(alias, "MPATHa");
+ free(alias);
+}
+
+static void gufa_empty_new_ro_1(void **state) {
+ char *alias;
+ will_return(__wrap_open_file, false);
+ will_return(__wrap_fgets, NULL);
+ mock_unused_alias("MPATHa");
+ expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
+
+ alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", false);
+ assert_ptr_equal(alias, NULL);
+}
+
+static void gufa_empty_new_ro_2(void **state) {
+ char *alias;
+
+ will_return(__wrap_open_file, true);
+
+ will_return(__wrap_fgets, NULL);
+ mock_unused_alias("MPATHa");
+ expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
+
+ alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", true);
+ assert_ptr_equal(alias, NULL);
+}
+
+static void gufa_match_a_unused(void **state) {
+ char *alias;
+
+ will_return(__wrap_open_file, true);
+
+ will_return(__wrap_fgets, BINDING_STR("MPATHa", "WWID0"));
+ expect_condlog(3, FOUND_STR("MPATHa", "WWID0"));
+ mock_unused_alias("MPATHa");
+
+ alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", true);
+ assert_string_equal(alias, "MPATHa");
+ free(alias);
+}
+
+static void gufa_match_a_self(void **state) {
+ char *alias;
+
+ will_return(__wrap_open_file, true);
+
+ will_return(__wrap_fgets, BINDING_STR("MPATHa", "WWID0"));
+ expect_condlog(3, FOUND_STR("MPATHa", "WWID0"));
+ mock_self_alias("MPATHa", "WWID0");
+
+ alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", true);
+ assert_string_equal(alias, "MPATHa");
+ free(alias);
+}
+
+static void gufa_match_a_used(void **state) {
+ char *alias;
+
+ will_return(__wrap_open_file, true);
+
+ will_return(__wrap_fgets, BINDING_STR("MPATHa", "WWID0"));
+ expect_condlog(3, FOUND_STR("MPATHa", "WWID0"));
+ mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID0"));
+
+ alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", true);
+ assert_ptr_equal(alias, NULL);
+}
+
+static void gufa_nomatch_a_c(void **state) {
+ char *alias;
+ will_return(__wrap_open_file, true);
+
+ mock_bindings_file("MPATHa WWID0\n"
+ "MPATHc WWID2",
+ -1);
+ mock_unused_alias("MPATHb");
+ expect_condlog(3, NOMATCH_WWID_STR("WWID1"));
+
+ mock_allocate_binding("MPATHb", "WWID1");
+
+ alias = get_user_friendly_alias("WWID1", "x", "", "MPATH", false);
+ assert_string_equal(alias, "MPATHb");
+ free(alias);
+}
+
+static void gufa_nomatch_c_a(void **state) {
+ char *alias;
+ will_return(__wrap_open_file, true);
+
+ mock_bindings_file("MPATHc WWID2\n"
+ "MPATHa WWID0",
+ -1);
+ mock_unused_alias("MPATHb");
+ expect_condlog(3, NOMATCH_WWID_STR("WWID1"));
+
+ mock_allocate_binding("MPATHb", "WWID1");
+
+ alias = get_user_friendly_alias("WWID1", "x", "", "MPATH", false);
+ assert_string_equal(alias, "MPATHb");
+ free(alias);
+}
+
+static void gufa_nomatch_c_b(void **state) {
+ char *alias;
+ will_return(__wrap_open_file, true);
+
+ mock_bindings_file("MPATHc WWID2\n"
+ "MPATHb WWID1\n",
+ -1);
+ mock_unused_alias("MPATHa");
+ expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
+
+ mock_allocate_binding("MPATHa", "WWID0");
+
+ alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", false);
+ assert_string_equal(alias, "MPATHa");
+ free(alias);
+}
+
+static void gufa_nomatch_c_b_used(void **state) {
+ char *alias;
+ will_return(__wrap_open_file, true);
+
+ mock_bindings_file("MPATHc WWID2\n"
+ "MPATHb WWID1",
+ -1);
+ mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID4"));
+ expect_condlog(3, NOMATCH_WWID_STR("WWID4"));
+ mock_unused_alias("MPATHd");
+
+ mock_allocate_binding("MPATHd", "WWID4");
+
+ alias = get_user_friendly_alias("WWID4", "x", "", "MPATH", false);
+ assert_string_equal(alias, "MPATHd");
+ free(alias);
+}
+
+static void gufa_nomatch_b_f_a(void **state) {
+ char *alias;
+ will_return(__wrap_open_file, true);
+
+ mock_bindings_file("MPATHb WWID1\n"
+ "MPATHf WWID6\n"
+ "MPATHa WWID0\n",
+ -1);
+ expect_condlog(3, NOMATCH_WWID_STR("WWID7"));
+ mock_unused_alias("MPATHg");
+
+ mock_allocate_binding("MPATHg", "WWID7");
+
+ alias = get_user_friendly_alias("WWID7", "x", "", "MPATH", false);
+ assert_string_equal(alias, "MPATHg");
+ free(alias);
+}
+
+static void gufa_old_empty(void **state) {
+ char *alias;
+ will_return(__wrap_open_file, true);
+
+ /* rlookup_binding for ALIAS */
+ will_return(__wrap_fgets, NULL);
+ expect_condlog(3, NOMATCH_STR("MPATHz"));
+
+ /* lookup_binding */
+ will_return(__wrap_fgets, NULL);
+ expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
+
+ mock_allocate_binding("MPATHz", "WWID0");
+ expect_condlog(2, ALLOC_STR("MPATHz", "WWID0"));
+
+ alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false);
+ assert_string_equal(alias, "MPATHz");
+ free(alias);
+}
+
+static void gufa_old_match(void **state) {
+ char *alias;
+ will_return(__wrap_open_file, true);
+
+ mock_bindings_file("MPATHb WWID1\n"
+ "MPATHz WWID0",
+ 1);
+ expect_condlog(3, FOUND_ALIAS_STR("MPATHz", "WWID0"));
+
+ alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false);
+ assert_string_equal(alias, "MPATHz");
+ free(alias);
+}
+
+static void gufa_old_match_other(void **state) {
+ char *alias;
+ static const char bindings[] = "MPATHz WWID9";
+
+ will_return(__wrap_open_file, true);
+
+ mock_bindings_file(bindings, 0);
+ expect_condlog(3, FOUND_ALIAS_STR("MPATHz", "WWID9"));
+ expect_condlog(0, REUSE_STR("MPATHz", "WWID9"));
+
+ mock_bindings_file(bindings, -1);
+ expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
+ mock_unused_alias("MPATHa");
+
+ mock_allocate_binding("MPATHa", "WWID0");
+
+ alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false);
+ assert_string_equal(alias, "MPATHa");
+ free(alias);
+}
+
+static void gufa_old_match_other_used(void **state) {
+ char *alias;
+ static const char bindings[] = "MPATHz WWID9";
+
+ will_return(__wrap_open_file, true);
+
+ mock_bindings_file(bindings, 0);
+ expect_condlog(3, FOUND_ALIAS_STR("MPATHz", "WWID9"));
+ expect_condlog(0, REUSE_STR("MPATHz", "WWID9"));
+
+ mock_bindings_file(bindings, -1);
+ mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID0"));
+ expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
+ mock_unused_alias("MPATHb");
+
+ mock_allocate_binding("MPATHb", "WWID0");
+
+ alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false);
+ assert_string_equal(alias, "MPATHb");
+ free(alias);
+}
+
+static void gufa_old_match_other_wwidmatch(void **state) {
+ char *alias;
+ static const char bindings[] = ("MPATHz WWID9\n"
+ "MPATHc WWID2");
+ will_return(__wrap_open_file, true);
+
+ mock_bindings_file(bindings, 0);
+ expect_condlog(3, FOUND_ALIAS_STR("MPATHz", "WWID9"));
+ expect_condlog(0, REUSE_STR("MPATHz", "WWID9"));
+
+ mock_bindings_file(bindings, 1);
+ expect_condlog(3, FOUND_STR("MPATHc", "WWID2"));
+ mock_unused_alias("MPATHc");
+
+ alias = get_user_friendly_alias("WWID2", "x", "MPATHz", "MPATH", false);
+ assert_string_equal(alias, "MPATHc");
+ free(alias);
+}
+
+static void gufa_old_match_other_wwidmatch_used(void **state) {
+ char *alias;
+ static const char bindings[] = ("MPATHz WWID9\n"
+ "MPATHc WWID2");
+
+ will_return(__wrap_open_file, true);
+
+ mock_bindings_file(bindings, 0);
+ expect_condlog(3, FOUND_ALIAS_STR("MPATHz", "WWID9"));
+ expect_condlog(0, REUSE_STR("MPATHz", "WWID9"));
+
+ mock_bindings_file(bindings, 1);
+ expect_condlog(3, FOUND_STR("MPATHc", "WWID2"));
+ mock_used_alias("MPATHc", USED_STR("MPATHc", "WWID2"));
+
+ alias = get_user_friendly_alias("WWID2", "x", "MPATHz", "MPATH", false);
+ assert_ptr_equal(alias, NULL);
+}
+
+static void gufa_old_nomatch_wwidmatch(void **state) {
+ char *alias;
+ static const char bindings[] = "MPATHa WWID0";
+
+ will_return(__wrap_open_file, true);
+
+ mock_bindings_file(bindings, -1);
+ expect_condlog(3, NOMATCH_STR("MPATHz"));
+
+ mock_bindings_file(bindings, 0);
+ expect_condlog(3, FOUND_STR("MPATHa", "WWID0"));
+ mock_unused_alias("MPATHa");
+ expect_condlog(3, EXISTING_STR("MPATHa", "WWID0"));
+
+ alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false);
+ assert_string_equal(alias, "MPATHa");
+ free(alias);
+}
+
+static void gufa_old_nomatch_wwidmatch_used(void **state) {
+ char *alias;
+ static const char bindings[] = "MPATHa WWID0";
+ will_return(__wrap_open_file, true);
+
+ mock_bindings_file(bindings, -1);
+ expect_condlog(3, NOMATCH_STR("MPATHz"));
+
+ mock_bindings_file(bindings, 0);
+ expect_condlog(3, FOUND_STR("MPATHa", "WWID0"));
+ mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID0"));
+
+ alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false);
+ assert_ptr_equal(alias, NULL);
+}
+
+static void gufa_old_nomatch_nowwidmatch(void **state) {
+ char *alias;
+ static const char bindings[] = "MPATHb WWID1";
+
+ will_return(__wrap_open_file, true);
+
+ mock_bindings_file(bindings, -1);
+ expect_condlog(3, NOMATCH_STR("MPATHz"));
+
+ mock_bindings_file(bindings, -1);
+ expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
+
+ mock_allocate_binding("MPATHz", "WWID0");
+ expect_condlog(2, ALLOC_STR("MPATHz", "WWID0"));
+
+ alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false);
+ assert_string_equal(alias, "MPATHz");
+ free(alias);
+}
+
+static int test_get_user_friendly_alias()
+{
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test(gufa_empty_new_rw),
+ cmocka_unit_test(gufa_empty_new_ro_1),
+ cmocka_unit_test(gufa_empty_new_ro_2),
+ cmocka_unit_test(gufa_match_a_unused),
+ cmocka_unit_test(gufa_match_a_self),
+ cmocka_unit_test(gufa_match_a_used),
+ cmocka_unit_test(gufa_nomatch_a_c),
+ cmocka_unit_test(gufa_nomatch_c_a),
+ cmocka_unit_test(gufa_nomatch_c_b),
+ cmocka_unit_test(gufa_nomatch_c_b_used),
+ cmocka_unit_test(gufa_nomatch_b_f_a),
+ cmocka_unit_test(gufa_old_empty),
+ cmocka_unit_test(gufa_old_match),
+ cmocka_unit_test(gufa_old_match_other),
+ cmocka_unit_test(gufa_old_match_other_used),
+ cmocka_unit_test(gufa_old_match_other_wwidmatch),
+ cmocka_unit_test(gufa_old_match_other_wwidmatch_used),
+ cmocka_unit_test(gufa_old_nomatch_wwidmatch),
+ cmocka_unit_test(gufa_old_nomatch_wwidmatch_used),
+ cmocka_unit_test(gufa_old_nomatch_nowwidmatch),
+ };
+
+ return cmocka_run_group_tests(tests, NULL, NULL);
+}
+
int main(void)
{
int ret = 0;
@@ -1157,6 +1596,8 @@ int main(void)
ret += test_lookup_binding();
ret += test_rlookup_binding();
ret += test_allocate_binding();
+ ret += test_allocate_binding();
+ ret += test_get_user_friendly_alias();
return ret;
}

View File

@ -0,0 +1,365 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Thu, 24 Aug 2023 10:40:32 +0200
Subject: [PATCH] multipath-tools test: consistent use of macros in alias test
Use the macros introduced with the tests for get_user_friendly_alias()
also in the previously existing tests.
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
tests/alias.c | 80 ++++++++++++++++++++++++---------------------------
1 file changed, 38 insertions(+), 42 deletions(-)
diff --git a/tests/alias.c b/tests/alias.c
index 7e443b06..427b2814 100644
--- a/tests/alias.c
+++ b/tests/alias.c
@@ -490,7 +490,7 @@ static void lb_empty(void **state)
char *alias;
will_return(__wrap_fgets, NULL);
- expect_condlog(3, "No matching wwid [WWID0] in bindings file.\n");
+ expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
rc = lookup_binding(NULL, "WWID0", &alias, NULL, 0);
assert_int_equal(rc, 1);
assert_ptr_equal(alias, NULL);
@@ -503,7 +503,7 @@ static void lb_empty_unused(void **state)
will_return(__wrap_fgets, NULL);
mock_unused_alias("MPATHa");
- expect_condlog(3, "No matching wwid [WWID0] in bindings file.\n");
+ expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 1);
assert_int_equal(rc, 1);
assert_ptr_equal(alias, NULL);
@@ -518,7 +518,7 @@ static void lb_empty_failed(void **state)
will_return(__wrap_fgets, NULL);
mock_failed_alias("MPATHa", USED_STR("MPATHa", "WWID0"));
mock_unused_alias("MPATHb");
- expect_condlog(3, "No matching wwid [WWID0] in bindings file.\n");
+ expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 1);
assert_int_equal(rc, 2);
assert_ptr_equal(alias, NULL);
@@ -533,7 +533,7 @@ static void lb_empty_1_used(void **state)
will_return(__wrap_fgets, NULL);
mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID0"));
mock_unused_alias("MPATHb");
- expect_condlog(3, "No matching wwid [WWID0] in bindings file.\n");
+ expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 1);
assert_int_equal(rc, 2);
assert_ptr_equal(alias, NULL);
@@ -548,7 +548,7 @@ static void lb_empty_1_used_self(void **state)
will_return(__wrap_fgets, NULL);
mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID0"));
mock_self_alias("MPATHb", "WWID0");
- expect_condlog(3, "No matching wwid [WWID0] in bindings file.\n");
+ expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 1);
assert_int_equal(rc, 2);
assert_ptr_equal(alias, NULL);
@@ -561,8 +561,7 @@ static void lb_match_a(void **state)
char *alias;
will_return(__wrap_fgets, "MPATHa WWID0\n");
- expect_condlog(3, "Found matching wwid [WWID0] in bindings file."
- " Setting alias to MPATHa\n");
+ expect_condlog(3, FOUND_STR("MPATHa", "WWID0"));
rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 0);
assert_int_equal(rc, 0);
assert_ptr_not_equal(alias, NULL);
@@ -577,7 +576,7 @@ static void lb_nomatch_a(void **state)
will_return(__wrap_fgets, "MPATHa WWID0\n");
will_return(__wrap_fgets, NULL);
- expect_condlog(3, "No matching wwid [WWID1] in bindings file.\n");
+ expect_condlog(3, NOMATCH_WWID_STR("WWID1"));
rc = lookup_binding(NULL, "WWID1", &alias, "MPATH", 0);
assert_int_equal(rc, 2);
assert_ptr_equal(alias, NULL);
@@ -590,7 +589,7 @@ static void lb_nomatch_a_bad_check(void **state)
will_return(__wrap_fgets, "MPATHa WWID0\n");
will_return(__wrap_fgets, NULL);
- expect_condlog(0, "no more available user_friendly_names\n");
+ expect_condlog(0, NOMORE_STR);
rc = lookup_binding(NULL, "WWID1", &alias, NULL, 1);
assert_int_equal(rc, -1);
assert_ptr_equal(alias, NULL);
@@ -604,7 +603,7 @@ static void lb_nomatch_a_unused(void **state)
will_return(__wrap_fgets, "MPATHa WWID0\n");
will_return(__wrap_fgets, NULL);
mock_unused_alias("MPATHb");
- expect_condlog(3, "No matching wwid [WWID1] in bindings file.\n");
+ expect_condlog(3, NOMATCH_WWID_STR("WWID1"));
rc = lookup_binding(NULL, "WWID1", &alias, "MPATH", 1);
assert_int_equal(rc, 2);
assert_ptr_equal(alias, NULL);
@@ -622,7 +621,7 @@ static void lb_nomatch_a_3_used_failed_self(void **state)
mock_used_alias("MPATHd", USED_STR("MPATHd", "WWID1"));
mock_failed_alias("MPATHe", USED_STR("MPATHe", "WWID1"));
mock_self_alias("MPATHf", "WWID1");
- expect_condlog(3, "No matching wwid [WWID1] in bindings file.\n");
+ expect_condlog(3, NOMATCH_WWID_STR("WWID1"));
rc = lookup_binding(NULL, "WWID1", &alias, "MPATH", 1);
assert_int_equal(rc, 6);
assert_ptr_equal(alias, NULL);
@@ -635,8 +634,7 @@ static void do_lb_match_c(void **state, int check_if_taken)
will_return(__wrap_fgets, "MPATHa WWID0\n");
will_return(__wrap_fgets, "MPATHc WWID1\n");
- expect_condlog(3, "Found matching wwid [WWID1] in bindings file."
- " Setting alias to MPATHc\n");
+ expect_condlog(3, FOUND_STR("MPATHc", "WWID1"));
rc = lookup_binding(NULL, "WWID1", &alias, "MPATH", check_if_taken);
assert_int_equal(rc, 0);
assert_ptr_not_equal(alias, NULL);
@@ -662,7 +660,7 @@ static void lb_nomatch_a_c(void **state)
will_return(__wrap_fgets, "MPATHa WWID0\n");
will_return(__wrap_fgets, "MPATHc WWID1\n");
will_return(__wrap_fgets, NULL);
- expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n");
+ expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0);
assert_int_equal(rc, 2);
assert_ptr_equal(alias, NULL);
@@ -677,7 +675,7 @@ static void lb_nomatch_a_d_unused(void **state)
will_return(__wrap_fgets, "MPATHd WWID1\n");
will_return(__wrap_fgets, NULL);
mock_unused_alias("MPATHb");
- expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n");
+ expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1);
assert_int_equal(rc, 2);
assert_ptr_equal(alias, NULL);
@@ -693,7 +691,7 @@ static void lb_nomatch_a_d_1_used(void **state)
will_return(__wrap_fgets, NULL);
mock_used_alias("MPATHb", USED_STR("MPATHb", "WWID2"));
mock_unused_alias("MPATHc");
- expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n");
+ expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1);
assert_int_equal(rc, 3);
assert_ptr_equal(alias, NULL);
@@ -710,7 +708,7 @@ static void lb_nomatch_a_d_2_used(void **state)
mock_used_alias("MPATHb", USED_STR("MPATHb", "WWID2"));
mock_used_alias("MPATHc", USED_STR("MPATHc", "WWID2"));
mock_unused_alias("MPATHe");
- expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n");
+ expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1);
assert_int_equal(rc, 5);
assert_ptr_equal(alias, NULL);
@@ -728,7 +726,7 @@ static void lb_nomatch_a_d_3_used(void **state)
mock_used_alias("MPATHc", USED_STR("MPATHc", "WWID2"));
mock_used_alias("MPATHe", USED_STR("MPATHe", "WWID2"));
mock_unused_alias("MPATHf");
- expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n");
+ expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1);
assert_int_equal(rc, 6);
assert_ptr_equal(alias, NULL);
@@ -742,7 +740,7 @@ static void lb_nomatch_c_a(void **state)
will_return(__wrap_fgets, "MPATHc WWID1\n");
will_return(__wrap_fgets, "MPATHa WWID0\n");
will_return(__wrap_fgets, NULL);
- expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n");
+ expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0);
assert_int_equal(rc, 2);
assert_ptr_equal(alias, NULL);
@@ -758,7 +756,7 @@ static void lb_nomatch_d_a_unused(void **state)
will_return(__wrap_fgets, "MPATHd WWID0\n");
will_return(__wrap_fgets, NULL);
mock_unused_alias("MPATHb");
- expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n");
+ expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1);
assert_int_equal(rc, 2);
assert_ptr_equal(alias, NULL);
@@ -775,7 +773,7 @@ static void lb_nomatch_d_a_1_used(void **state)
will_return(__wrap_fgets, NULL);
mock_used_alias("MPATHb", USED_STR("MPATHb", "WWID2"));
mock_unused_alias("MPATHe");
- expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n");
+ expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1);
assert_int_equal(rc, 5);
assert_ptr_equal(alias, NULL);
@@ -790,7 +788,7 @@ static void lb_nomatch_a_b(void **state)
will_return(__wrap_fgets, "MPATHz WWID26\n");
will_return(__wrap_fgets, "MPATHb WWID1\n");
will_return(__wrap_fgets, NULL);
- expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n");
+ expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0);
assert_int_equal(rc, 3);
assert_ptr_equal(alias, NULL);
@@ -806,7 +804,7 @@ static void lb_nomatch_a_b_bad(void **state)
will_return(__wrap_fgets, "MPATHb\n");
will_return(__wrap_fgets, NULL);
expect_condlog(3, "Ignoring malformed line 3 in bindings file\n");
- expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n");
+ expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0);
assert_int_equal(rc, 3);
assert_ptr_equal(alias, NULL);
@@ -823,7 +821,7 @@ static void lb_nomatch_a_b_bad_self(void **state)
will_return(__wrap_fgets, NULL);
expect_condlog(3, "Ignoring malformed line 3 in bindings file\n");
mock_self_alias("MPATHc", "WWID2");
- expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n");
+ expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1);
assert_int_equal(rc, 3);
assert_ptr_equal(alias, NULL);
@@ -838,7 +836,7 @@ static void lb_nomatch_b_a(void **state)
will_return(__wrap_fgets, "MPATHz WWID26\n");
will_return(__wrap_fgets, "MPATHa WWID0\n");
will_return(__wrap_fgets, NULL);
- expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n");
+ expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0);
assert_int_equal(rc, 27);
assert_ptr_equal(alias, NULL);
@@ -857,7 +855,7 @@ static void lb_nomatch_b_a_3_used(void **state)
mock_used_alias("MPATHab", USED_STR("MPATHab", "WWID2"));
mock_used_alias("MPATHac", USED_STR("MPATHac", "WWID2"));
mock_unused_alias("MPATHad");
- expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n");
+ expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1);
assert_int_equal(rc, 30);
assert_ptr_equal(alias, NULL);
@@ -873,7 +871,7 @@ static void do_lb_nomatch_int_max(void **state, int check_if_taken)
will_return(__wrap_fgets, "MPATH" MPATH_ID_INT_MAX " WWIDMAX\n");
will_return(__wrap_fgets, "MPATHa WWID0\n");
will_return(__wrap_fgets, NULL);
- expect_condlog(0, "no more available user_friendly_names\n");
+ expect_condlog(0, NOMORE_STR);
rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", check_if_taken);
assert_int_equal(rc, -1);
assert_ptr_equal(alias, NULL);
@@ -898,7 +896,7 @@ static void lb_nomatch_int_max_used(void **state)
will_return(__wrap_fgets, "MPATH" MPATH_ID_INT_MAX " WWIDMAX\n");
will_return(__wrap_fgets, NULL);
mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID2"));
- expect_condlog(0, "no more available user_friendly_names\n");
+ expect_condlog(0, NOMORE_STR);
rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1);
assert_int_equal(rc, -1);
assert_ptr_equal(alias, NULL);
@@ -913,7 +911,7 @@ static void lb_nomatch_int_max_m1(void **state)
will_return(__wrap_fgets, "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n");
will_return(__wrap_fgets, "MPATHa WWID0\n");
will_return(__wrap_fgets, NULL);
- expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n");
+ expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0);
assert_int_equal(rc, INT_MAX);
assert_ptr_equal(alias, NULL);
@@ -929,7 +927,7 @@ static void lb_nomatch_int_max_m1_used(void **state)
will_return(__wrap_fgets, "MPATHa WWID0\n");
will_return(__wrap_fgets, NULL);
mock_used_alias("MPATH" MPATH_ID_INT_MAX, USED_STR("MPATH" MPATH_ID_INT_MAX, "WWID2"));
- expect_condlog(0, "no more available user_friendly_names\n");
+ expect_condlog(0, NOMORE_STR);
rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1);
assert_int_equal(rc, -1);
assert_ptr_equal(alias, NULL);
@@ -945,7 +943,7 @@ static void lb_nomatch_int_max_m1_1_used(void **state)
will_return(__wrap_fgets, NULL);
mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID2"));
mock_unused_alias("MPATH" MPATH_ID_INT_MAX);
- expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n");
+ expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1);
assert_int_equal(rc, INT_MAX);
assert_ptr_equal(alias, NULL);
@@ -961,7 +959,7 @@ static void lb_nomatch_int_max_m1_2_used(void **state)
will_return(__wrap_fgets, NULL);
mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID2"));
mock_used_alias("MPATH" MPATH_ID_INT_MAX, USED_STR("MPATH" MPATH_ID_INT_MAX, "WWID2"));
- expect_condlog(0, "no more available user_friendly_names\n");
+ expect_condlog(0, NOMORE_STR);
rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1);
assert_int_equal(rc, -1);
assert_ptr_equal(alias, NULL);
@@ -1017,7 +1015,7 @@ static void rl_empty(void **state)
buf[0] = '\0';
will_return(__wrap_fgets, NULL);
- expect_condlog(3, "No matching alias [MPATHa] in bindings file.\n");
+ expect_condlog(3, NOMATCH_STR("MPATHa"));
rc = rlookup_binding(NULL, buf, "MPATHa");
assert_int_equal(rc, -1);
assert_string_equal(buf, "");
@@ -1030,8 +1028,7 @@ static void rl_match_a(void **state)
buf[0] = '\0';
will_return(__wrap_fgets, "MPATHa WWID0\n");
- expect_condlog(3, "Found matching alias [MPATHa] in bindings file. "
- "Setting wwid to WWID0\n");
+ expect_condlog(3, FOUND_ALIAS_STR("MPATHa", "WWID0"));
rc = rlookup_binding(NULL, buf, "MPATHa");
assert_int_equal(rc, 0);
assert_string_equal(buf, "WWID0");
@@ -1045,7 +1042,7 @@ static void rl_nomatch_a(void **state)
buf[0] = '\0';
will_return(__wrap_fgets, "MPATHa WWID0\n");
will_return(__wrap_fgets, NULL);
- expect_condlog(3, "No matching alias [MPATHb] in bindings file.\n");
+ expect_condlog(3, NOMATCH_STR("MPATHb"));
rc = rlookup_binding(NULL, buf, "MPATHb");
assert_int_equal(rc, -1);
assert_string_equal(buf, "");
@@ -1060,7 +1057,7 @@ static void rl_malformed_a(void **state)
will_return(__wrap_fgets, "MPATHa \n");
will_return(__wrap_fgets, NULL);
expect_condlog(3, "Ignoring malformed line 1 in bindings file\n");
- expect_condlog(3, "No matching alias [MPATHa] in bindings file.\n");
+ expect_condlog(3, NOMATCH_STR("MPATHa"));
rc = rlookup_binding(NULL, buf, "MPATHa");
assert_int_equal(rc, -1);
assert_string_equal(buf, "");
@@ -1080,7 +1077,7 @@ static void rl_overlong_a(void **state)
will_return(__wrap_fgets, line);
will_return(__wrap_fgets, NULL);
expect_condlog(3, "Ignoring too large wwid at 1 in bindings file\n");
- expect_condlog(3, "No matching alias [MPATHa] in bindings file.\n");
+ expect_condlog(3, NOMATCH_STR("MPATHa"));
rc = rlookup_binding(NULL, buf, "MPATHa");
assert_int_equal(rc, -1);
assert_string_equal(buf, "");
@@ -1095,8 +1092,7 @@ static void rl_match_b(void **state)
will_return(__wrap_fgets, "MPATHa WWID0\n");
will_return(__wrap_fgets, "MPATHz WWID26\n");
will_return(__wrap_fgets, "MPATHb WWID2\n");
- expect_condlog(3, "Found matching alias [MPATHb] in bindings file. "
- "Setting wwid to WWID2\n");
+ expect_condlog(3, FOUND_ALIAS_STR("MPATHb", "WWID2"));
rc = rlookup_binding(NULL, buf, "MPATHb");
assert_int_equal(rc, 0);
assert_string_equal(buf, "WWID2");
@@ -1125,7 +1121,7 @@ static void al_a(void **state)
expect_value(__wrap_write, count, strlen(ln));
expect_string(__wrap_write, buf, ln);
will_return(__wrap_write, strlen(ln));
- expect_condlog(3, "Created new binding [MPATHa] for WWID [WWIDa]\n");
+ expect_condlog(3, NEW_STR("MPATHa", "WWIDa"));
alias = allocate_binding(0, "WWIDa", 1, "MPATH");
assert_ptr_not_equal(alias, NULL);
@@ -1142,7 +1138,7 @@ static void al_zz(void **state)
expect_value(__wrap_write, count, strlen(ln));
expect_string(__wrap_write, buf, ln);
will_return(__wrap_write, strlen(ln));
- expect_condlog(3, "Created new binding [MPATHzz] for WWID [WWIDzz]\n");
+ expect_condlog(3, NEW_STR("MPATHzz", "WWIDzz"));
alias = allocate_binding(0, "WWIDzz", 26*26 + 26, "MPATH");
assert_ptr_not_equal(alias, NULL);

View File

@ -0,0 +1,246 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Thu, 24 Aug 2023 10:49:32 +0200
Subject: [PATCH] multipath-tools tests: convert mock_{failed,used}_alias to
macros
This way we can further improve readability of the individual test
cases.
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
tests/alias.c | 92 +++++++++++++++++++++++++--------------------------
1 file changed, 46 insertions(+), 46 deletions(-)
diff --git a/tests/alias.c b/tests/alias.c
index 427b2814..a32b43e8 100644
--- a/tests/alias.c
+++ b/tests/alias.c
@@ -445,26 +445,26 @@ static void mock_self_alias(const char *alias, const char *wwid)
#define REUSE_STR(alias_str, wwid_str) ("alias " alias_str " already bound to wwid " wwid_str ", cannot reuse\n")
#define NOMORE_STR "no more available user_friendly_names\n"
-static void mock_failed_alias(const char *alias, char *msg)
-{
- expect_string(__wrap_dm_map_present, str, alias);
- will_return(__wrap_dm_map_present, 1);
- expect_string(__wrap_dm_get_uuid, name, alias);
- expect_value(__wrap_dm_get_uuid, uuid_len, WWID_SIZE);
- will_return(__wrap_dm_get_uuid, 1);
- expect_condlog(3, msg);
-}
+#define mock_failed_alias(alias, wwid) \
+ do { \
+ expect_string(__wrap_dm_map_present, str, alias); \
+ will_return(__wrap_dm_map_present, 1); \
+ expect_string(__wrap_dm_get_uuid, name, alias); \
+ expect_value(__wrap_dm_get_uuid, uuid_len, WWID_SIZE); \
+ will_return(__wrap_dm_get_uuid, 1); \
+ expect_condlog(3, USED_STR(alias, wwid)); \
+ } while (0)
-static void mock_used_alias(const char *alias, char *msg)
-{
- expect_string(__wrap_dm_map_present, str, alias);
- will_return(__wrap_dm_map_present, 1);
- expect_string(__wrap_dm_get_uuid, name, alias);
- expect_value(__wrap_dm_get_uuid, uuid_len, WWID_SIZE);
- will_return(__wrap_dm_get_uuid, 0);
- will_return(__wrap_dm_get_uuid, "WWID_USED");
- expect_condlog(3, msg);
-}
+#define mock_used_alias(alias, wwid) \
+ do { \
+ expect_string(__wrap_dm_map_present, str, alias); \
+ will_return(__wrap_dm_map_present, 1); \
+ expect_string(__wrap_dm_get_uuid, name, alias); \
+ expect_value(__wrap_dm_get_uuid, uuid_len, WWID_SIZE); \
+ will_return(__wrap_dm_get_uuid, 0); \
+ will_return(__wrap_dm_get_uuid, "WWID_USED"); \
+ expect_condlog(3, USED_STR(alias, wwid)); \
+ } while(0)
static void mock_bindings_file(const char *content, int match_line)
{
@@ -516,7 +516,7 @@ static void lb_empty_failed(void **state)
char *alias;
will_return(__wrap_fgets, NULL);
- mock_failed_alias("MPATHa", USED_STR("MPATHa", "WWID0"));
+ mock_failed_alias("MPATHa", "WWID0");
mock_unused_alias("MPATHb");
expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 1);
@@ -531,7 +531,7 @@ static void lb_empty_1_used(void **state)
char *alias;
will_return(__wrap_fgets, NULL);
- mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID0"));
+ mock_used_alias("MPATHa", "WWID0");
mock_unused_alias("MPATHb");
expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 1);
@@ -546,7 +546,7 @@ static void lb_empty_1_used_self(void **state)
char *alias;
will_return(__wrap_fgets, NULL);
- mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID0"));
+ mock_used_alias("MPATHa", "WWID0");
mock_self_alias("MPATHb", "WWID0");
expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 1);
@@ -616,10 +616,10 @@ static void lb_nomatch_a_3_used_failed_self(void **state)
will_return(__wrap_fgets, "MPATHa WWID0\n");
will_return(__wrap_fgets, NULL);
- mock_used_alias("MPATHb", USED_STR("MPATHb", "WWID1"));
- mock_used_alias("MPATHc", USED_STR("MPATHc", "WWID1"));
- mock_used_alias("MPATHd", USED_STR("MPATHd", "WWID1"));
- mock_failed_alias("MPATHe", USED_STR("MPATHe", "WWID1"));
+ mock_used_alias("MPATHb", "WWID1");
+ mock_used_alias("MPATHc", "WWID1");
+ mock_used_alias("MPATHd", "WWID1");
+ mock_failed_alias("MPATHe", "WWID1");
mock_self_alias("MPATHf", "WWID1");
expect_condlog(3, NOMATCH_WWID_STR("WWID1"));
rc = lookup_binding(NULL, "WWID1", &alias, "MPATH", 1);
@@ -689,7 +689,7 @@ static void lb_nomatch_a_d_1_used(void **state)
will_return(__wrap_fgets, "MPATHa WWID0\n");
will_return(__wrap_fgets, "MPATHd WWID1\n");
will_return(__wrap_fgets, NULL);
- mock_used_alias("MPATHb", USED_STR("MPATHb", "WWID2"));
+ mock_used_alias("MPATHb", "WWID2");
mock_unused_alias("MPATHc");
expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1);
@@ -705,8 +705,8 @@ static void lb_nomatch_a_d_2_used(void **state)
will_return(__wrap_fgets, "MPATHa WWID0\n");
will_return(__wrap_fgets, "MPATHd WWID1\n");
will_return(__wrap_fgets, NULL);
- mock_used_alias("MPATHb", USED_STR("MPATHb", "WWID2"));
- mock_used_alias("MPATHc", USED_STR("MPATHc", "WWID2"));
+ mock_used_alias("MPATHb", "WWID2");
+ mock_used_alias("MPATHc", "WWID2");
mock_unused_alias("MPATHe");
expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1);
@@ -722,9 +722,9 @@ static void lb_nomatch_a_d_3_used(void **state)
will_return(__wrap_fgets, "MPATHa WWID0\n");
will_return(__wrap_fgets, "MPATHd WWID1\n");
will_return(__wrap_fgets, NULL);
- mock_used_alias("MPATHb", USED_STR("MPATHb", "WWID2"));
- mock_used_alias("MPATHc", USED_STR("MPATHc", "WWID2"));
- mock_used_alias("MPATHe", USED_STR("MPATHe", "WWID2"));
+ mock_used_alias("MPATHb", "WWID2");
+ mock_used_alias("MPATHc", "WWID2");
+ mock_used_alias("MPATHe", "WWID2");
mock_unused_alias("MPATHf");
expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1);
@@ -771,7 +771,7 @@ static void lb_nomatch_d_a_1_used(void **state)
will_return(__wrap_fgets, "MPATHa WWID0\n");
will_return(__wrap_fgets, "MPATHd WWID0\n");
will_return(__wrap_fgets, NULL);
- mock_used_alias("MPATHb", USED_STR("MPATHb", "WWID2"));
+ mock_used_alias("MPATHb", "WWID2");
mock_unused_alias("MPATHe");
expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1);
@@ -851,9 +851,9 @@ static void lb_nomatch_b_a_3_used(void **state)
will_return(__wrap_fgets, "MPATHz WWID26\n");
will_return(__wrap_fgets, "MPATHa WWID0\n");
will_return(__wrap_fgets, NULL);
- mock_used_alias("MPATHaa", USED_STR("MPATHaa", "WWID2"));
- mock_used_alias("MPATHab", USED_STR("MPATHab", "WWID2"));
- mock_used_alias("MPATHac", USED_STR("MPATHac", "WWID2"));
+ mock_used_alias("MPATHaa", "WWID2");
+ mock_used_alias("MPATHab", "WWID2");
+ mock_used_alias("MPATHac", "WWID2");
mock_unused_alias("MPATHad");
expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1);
@@ -895,7 +895,7 @@ static void lb_nomatch_int_max_used(void **state)
will_return(__wrap_fgets, "MPATHb WWID1\n");
will_return(__wrap_fgets, "MPATH" MPATH_ID_INT_MAX " WWIDMAX\n");
will_return(__wrap_fgets, NULL);
- mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID2"));
+ mock_used_alias("MPATHa", "WWID2");
expect_condlog(0, NOMORE_STR);
rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1);
assert_int_equal(rc, -1);
@@ -926,7 +926,7 @@ static void lb_nomatch_int_max_m1_used(void **state)
will_return(__wrap_fgets, "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n");
will_return(__wrap_fgets, "MPATHa WWID0\n");
will_return(__wrap_fgets, NULL);
- mock_used_alias("MPATH" MPATH_ID_INT_MAX, USED_STR("MPATH" MPATH_ID_INT_MAX, "WWID2"));
+ mock_used_alias("MPATH" MPATH_ID_INT_MAX, "WWID2");
expect_condlog(0, NOMORE_STR);
rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1);
assert_int_equal(rc, -1);
@@ -941,7 +941,7 @@ static void lb_nomatch_int_max_m1_1_used(void **state)
will_return(__wrap_fgets, "MPATHb WWID1\n");
will_return(__wrap_fgets, "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n");
will_return(__wrap_fgets, NULL);
- mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID2"));
+ mock_used_alias("MPATHa", "WWID2");
mock_unused_alias("MPATH" MPATH_ID_INT_MAX);
expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1);
@@ -957,8 +957,8 @@ static void lb_nomatch_int_max_m1_2_used(void **state)
will_return(__wrap_fgets, "MPATHb WWID1\n");
will_return(__wrap_fgets, "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n");
will_return(__wrap_fgets, NULL);
- mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID2"));
- mock_used_alias("MPATH" MPATH_ID_INT_MAX, USED_STR("MPATH" MPATH_ID_INT_MAX, "WWID2"));
+ mock_used_alias("MPATHa", "WWID2");
+ mock_used_alias("MPATH" MPATH_ID_INT_MAX, "WWID2");
expect_condlog(0, NOMORE_STR);
rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1);
assert_int_equal(rc, -1);
@@ -1291,7 +1291,7 @@ static void gufa_match_a_used(void **state) {
will_return(__wrap_fgets, BINDING_STR("MPATHa", "WWID0"));
expect_condlog(3, FOUND_STR("MPATHa", "WWID0"));
- mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID0"));
+ mock_used_alias("MPATHa", "WWID0");
alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", true);
assert_ptr_equal(alias, NULL);
@@ -1355,7 +1355,7 @@ static void gufa_nomatch_c_b_used(void **state) {
mock_bindings_file("MPATHc WWID2\n"
"MPATHb WWID1",
-1);
- mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID4"));
+ mock_used_alias("MPATHa", "WWID4");
expect_condlog(3, NOMATCH_WWID_STR("WWID4"));
mock_unused_alias("MPATHd");
@@ -1450,7 +1450,7 @@ static void gufa_old_match_other_used(void **state) {
expect_condlog(0, REUSE_STR("MPATHz", "WWID9"));
mock_bindings_file(bindings, -1);
- mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID0"));
+ mock_used_alias("MPATHa", "WWID0");
expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
mock_unused_alias("MPATHb");
@@ -1493,7 +1493,7 @@ static void gufa_old_match_other_wwidmatch_used(void **state) {
mock_bindings_file(bindings, 1);
expect_condlog(3, FOUND_STR("MPATHc", "WWID2"));
- mock_used_alias("MPATHc", USED_STR("MPATHc", "WWID2"));
+ mock_used_alias("MPATHc", "WWID2");
alias = get_user_friendly_alias("WWID2", "x", "MPATHz", "MPATH", false);
assert_ptr_equal(alias, NULL);
@@ -1528,7 +1528,7 @@ static void gufa_old_nomatch_wwidmatch_used(void **state) {
mock_bindings_file(bindings, 0);
expect_condlog(3, FOUND_STR("MPATHa", "WWID0"));
- mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID0"));
+ mock_used_alias("MPATHa", "WWID0");
alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false);
assert_ptr_equal(alias, NULL);

View File

@ -0,0 +1,500 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Thu, 24 Aug 2023 11:13:44 +0200
Subject: [PATCH] multipath-tools test: use mock_bindings_file() consistently
Further improve test readablity.
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
tests/alias.c | 178 +++++++++++++++++++++-----------------------------
1 file changed, 76 insertions(+), 102 deletions(-)
diff --git a/tests/alias.c b/tests/alias.c
index a32b43e8..f334f928 100644
--- a/tests/alias.c
+++ b/tests/alias.c
@@ -489,7 +489,7 @@ static void lb_empty(void **state)
int rc;
char *alias;
- will_return(__wrap_fgets, NULL);
+ mock_bindings_file("", -1);
expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
rc = lookup_binding(NULL, "WWID0", &alias, NULL, 0);
assert_int_equal(rc, 1);
@@ -501,7 +501,7 @@ static void lb_empty_unused(void **state)
int rc;
char *alias;
- will_return(__wrap_fgets, NULL);
+ mock_bindings_file("", -1);
mock_unused_alias("MPATHa");
expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 1);
@@ -515,7 +515,7 @@ static void lb_empty_failed(void **state)
int rc;
char *alias;
- will_return(__wrap_fgets, NULL);
+ mock_bindings_file("", -1);
mock_failed_alias("MPATHa", "WWID0");
mock_unused_alias("MPATHb");
expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
@@ -530,7 +530,7 @@ static void lb_empty_1_used(void **state)
int rc;
char *alias;
- will_return(__wrap_fgets, NULL);
+ mock_bindings_file("", -1);
mock_used_alias("MPATHa", "WWID0");
mock_unused_alias("MPATHb");
expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
@@ -545,7 +545,7 @@ static void lb_empty_1_used_self(void **state)
int rc;
char *alias;
- will_return(__wrap_fgets, NULL);
+ mock_bindings_file("", -1);
mock_used_alias("MPATHa", "WWID0");
mock_self_alias("MPATHb", "WWID0");
expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
@@ -560,7 +560,7 @@ static void lb_match_a(void **state)
int rc;
char *alias;
- will_return(__wrap_fgets, "MPATHa WWID0\n");
+ mock_bindings_file("MPATHa WWID0\n", 0);
expect_condlog(3, FOUND_STR("MPATHa", "WWID0"));
rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 0);
assert_int_equal(rc, 0);
@@ -574,8 +574,7 @@ static void lb_nomatch_a(void **state)
int rc;
char *alias;
- will_return(__wrap_fgets, "MPATHa WWID0\n");
- will_return(__wrap_fgets, NULL);
+ mock_bindings_file("MPATHa WWID0\n", -1);
expect_condlog(3, NOMATCH_WWID_STR("WWID1"));
rc = lookup_binding(NULL, "WWID1", &alias, "MPATH", 0);
assert_int_equal(rc, 2);
@@ -587,8 +586,7 @@ static void lb_nomatch_a_bad_check(void **state)
int rc;
char *alias;
- will_return(__wrap_fgets, "MPATHa WWID0\n");
- will_return(__wrap_fgets, NULL);
+ mock_bindings_file("MPATHa WWID0\n", -1);
expect_condlog(0, NOMORE_STR);
rc = lookup_binding(NULL, "WWID1", &alias, NULL, 1);
assert_int_equal(rc, -1);
@@ -600,8 +598,7 @@ static void lb_nomatch_a_unused(void **state)
int rc;
char *alias;
- will_return(__wrap_fgets, "MPATHa WWID0\n");
- will_return(__wrap_fgets, NULL);
+ mock_bindings_file("MPATHa WWID0\n", -1);
mock_unused_alias("MPATHb");
expect_condlog(3, NOMATCH_WWID_STR("WWID1"));
rc = lookup_binding(NULL, "WWID1", &alias, "MPATH", 1);
@@ -614,8 +611,7 @@ static void lb_nomatch_a_3_used_failed_self(void **state)
int rc;
char *alias;
- will_return(__wrap_fgets, "MPATHa WWID0\n");
- will_return(__wrap_fgets, NULL);
+ mock_bindings_file("MPATHa WWID0\n", -1);
mock_used_alias("MPATHb", "WWID1");
mock_used_alias("MPATHc", "WWID1");
mock_used_alias("MPATHd", "WWID1");
@@ -632,8 +628,8 @@ static void do_lb_match_c(void **state, int check_if_taken)
int rc;
char *alias;
- will_return(__wrap_fgets, "MPATHa WWID0\n");
- will_return(__wrap_fgets, "MPATHc WWID1\n");
+ mock_bindings_file("MPATHa WWID0\n"
+ "MPATHc WWID1", 1);
expect_condlog(3, FOUND_STR("MPATHc", "WWID1"));
rc = lookup_binding(NULL, "WWID1", &alias, "MPATH", check_if_taken);
assert_int_equal(rc, 0);
@@ -657,9 +653,8 @@ static void lb_nomatch_a_c(void **state)
int rc;
char *alias;
- will_return(__wrap_fgets, "MPATHa WWID0\n");
- will_return(__wrap_fgets, "MPATHc WWID1\n");
- will_return(__wrap_fgets, NULL);
+ mock_bindings_file("MPATHa WWID0\n"
+ "MPATHc WWID1", -1);
expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0);
assert_int_equal(rc, 2);
@@ -671,9 +666,8 @@ static void lb_nomatch_a_d_unused(void **state)
int rc;
char *alias;
- will_return(__wrap_fgets, "MPATHa WWID0\n");
- will_return(__wrap_fgets, "MPATHd WWID1\n");
- will_return(__wrap_fgets, NULL);
+ mock_bindings_file("MPATHa WWID0\n"
+ "MPATHd WWID1", -1);
mock_unused_alias("MPATHb");
expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1);
@@ -686,9 +680,8 @@ static void lb_nomatch_a_d_1_used(void **state)
int rc;
char *alias;
- will_return(__wrap_fgets, "MPATHa WWID0\n");
- will_return(__wrap_fgets, "MPATHd WWID1\n");
- will_return(__wrap_fgets, NULL);
+ mock_bindings_file("MPATHa WWID0\n"
+ "MPATHd WWID1", -1);
mock_used_alias("MPATHb", "WWID2");
mock_unused_alias("MPATHc");
expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
@@ -702,9 +695,8 @@ static void lb_nomatch_a_d_2_used(void **state)
int rc;
char *alias;
- will_return(__wrap_fgets, "MPATHa WWID0\n");
- will_return(__wrap_fgets, "MPATHd WWID1\n");
- will_return(__wrap_fgets, NULL);
+ mock_bindings_file("MPATHa WWID0\n"
+ "MPATHd WWID1", -1);
mock_used_alias("MPATHb", "WWID2");
mock_used_alias("MPATHc", "WWID2");
mock_unused_alias("MPATHe");
@@ -719,9 +711,8 @@ static void lb_nomatch_a_d_3_used(void **state)
int rc;
char *alias;
- will_return(__wrap_fgets, "MPATHa WWID0\n");
- will_return(__wrap_fgets, "MPATHd WWID1\n");
- will_return(__wrap_fgets, NULL);
+ mock_bindings_file("MPATHa WWID0\n"
+ "MPATHd WWID1", -1);
mock_used_alias("MPATHb", "WWID2");
mock_used_alias("MPATHc", "WWID2");
mock_used_alias("MPATHe", "WWID2");
@@ -737,9 +728,8 @@ static void lb_nomatch_c_a(void **state)
int rc;
char *alias;
- will_return(__wrap_fgets, "MPATHc WWID1\n");
- will_return(__wrap_fgets, "MPATHa WWID0\n");
- will_return(__wrap_fgets, NULL);
+ mock_bindings_file("MPATHc WWID1\n"
+ "MPATHa WWID0\n", -1);
expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0);
assert_int_equal(rc, 2);
@@ -751,10 +741,9 @@ static void lb_nomatch_d_a_unused(void **state)
int rc;
char *alias;
- will_return(__wrap_fgets, "MPATHc WWID1\n");
- will_return(__wrap_fgets, "MPATHa WWID0\n");
- will_return(__wrap_fgets, "MPATHd WWID0\n");
- will_return(__wrap_fgets, NULL);
+ mock_bindings_file("MPATHc WWID1\n"
+ "MPATHa WWID0\n"
+ "MPATHd WWID0\n", -1);
mock_unused_alias("MPATHb");
expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1);
@@ -767,10 +756,9 @@ static void lb_nomatch_d_a_1_used(void **state)
int rc;
char *alias;
- will_return(__wrap_fgets, "MPATHc WWID1\n");
- will_return(__wrap_fgets, "MPATHa WWID0\n");
- will_return(__wrap_fgets, "MPATHd WWID0\n");
- will_return(__wrap_fgets, NULL);
+ mock_bindings_file("MPATHc WWID1\n"
+ "MPATHa WWID0\n"
+ "MPATHd WWID0\n", -1);
mock_used_alias("MPATHb", "WWID2");
mock_unused_alias("MPATHe");
expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
@@ -784,10 +772,9 @@ static void lb_nomatch_a_b(void **state)
int rc;
char *alias;
- will_return(__wrap_fgets, "MPATHa WWID0\n");
- will_return(__wrap_fgets, "MPATHz WWID26\n");
- will_return(__wrap_fgets, "MPATHb WWID1\n");
- will_return(__wrap_fgets, NULL);
+ mock_bindings_file("MPATHa WWID0\n"
+ "MPATHz WWID26\n"
+ "MPATHb WWID1\n", -1);
expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0);
assert_int_equal(rc, 3);
@@ -799,10 +786,9 @@ static void lb_nomatch_a_b_bad(void **state)
int rc;
char *alias;
- will_return(__wrap_fgets, "MPATHa WWID0\n");
- will_return(__wrap_fgets, "MPATHz WWID26\n");
- will_return(__wrap_fgets, "MPATHb\n");
- will_return(__wrap_fgets, NULL);
+ mock_bindings_file("MPATHa WWID0\n"
+ "MPATHz WWID26\n"
+ "MPATHb\n", -1);
expect_condlog(3, "Ignoring malformed line 3 in bindings file\n");
expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0);
@@ -815,10 +801,9 @@ static void lb_nomatch_a_b_bad_self(void **state)
int rc;
char *alias;
- will_return(__wrap_fgets, "MPATHa WWID0\n");
- will_return(__wrap_fgets, "MPATHz WWID26\n");
- will_return(__wrap_fgets, "MPATHb\n");
- will_return(__wrap_fgets, NULL);
+ mock_bindings_file("MPATHa WWID0\n"
+ "MPATHz WWID26\n"
+ "MPATHb\n", -1);
expect_condlog(3, "Ignoring malformed line 3 in bindings file\n");
mock_self_alias("MPATHc", "WWID2");
expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
@@ -832,10 +817,9 @@ static void lb_nomatch_b_a(void **state)
int rc;
char *alias;
- will_return(__wrap_fgets, "MPATHb WWID1\n");
- will_return(__wrap_fgets, "MPATHz WWID26\n");
- will_return(__wrap_fgets, "MPATHa WWID0\n");
- will_return(__wrap_fgets, NULL);
+ mock_bindings_file("MPATHb WWID1\n"
+ "MPATHz WWID26\n"
+ "MPATHa WWID0\n", -1);
expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0);
assert_int_equal(rc, 27);
@@ -847,10 +831,9 @@ static void lb_nomatch_b_a_3_used(void **state)
int rc;
char *alias;
- will_return(__wrap_fgets, "MPATHb WWID1\n");
- will_return(__wrap_fgets, "MPATHz WWID26\n");
- will_return(__wrap_fgets, "MPATHa WWID0\n");
- will_return(__wrap_fgets, NULL);
+ mock_bindings_file("MPATHb WWID1\n"
+ "MPATHz WWID26\n"
+ "MPATHa WWID0\n", -1);
mock_used_alias("MPATHaa", "WWID2");
mock_used_alias("MPATHab", "WWID2");
mock_used_alias("MPATHac", "WWID2");
@@ -867,10 +850,9 @@ static void do_lb_nomatch_int_max(void **state, int check_if_taken)
int rc;
char *alias;
- will_return(__wrap_fgets, "MPATHb WWID1\n");
- will_return(__wrap_fgets, "MPATH" MPATH_ID_INT_MAX " WWIDMAX\n");
- will_return(__wrap_fgets, "MPATHa WWID0\n");
- will_return(__wrap_fgets, NULL);
+ mock_bindings_file("MPATHb WWID1\n"
+ "MPATH" MPATH_ID_INT_MAX " WWIDMAX\n"
+ "MPATHa WWID0\n", -1);
expect_condlog(0, NOMORE_STR);
rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", check_if_taken);
assert_int_equal(rc, -1);
@@ -892,9 +874,8 @@ static void lb_nomatch_int_max_used(void **state)
int rc;
char *alias;
- will_return(__wrap_fgets, "MPATHb WWID1\n");
- will_return(__wrap_fgets, "MPATH" MPATH_ID_INT_MAX " WWIDMAX\n");
- will_return(__wrap_fgets, NULL);
+ mock_bindings_file("MPATHb WWID1\n"
+ "MPATH" MPATH_ID_INT_MAX " WWIDMAX\n", -1);
mock_used_alias("MPATHa", "WWID2");
expect_condlog(0, NOMORE_STR);
rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1);
@@ -907,10 +888,9 @@ static void lb_nomatch_int_max_m1(void **state)
int rc;
char *alias;
- will_return(__wrap_fgets, "MPATHb WWID1\n");
- will_return(__wrap_fgets, "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n");
- will_return(__wrap_fgets, "MPATHa WWID0\n");
- will_return(__wrap_fgets, NULL);
+ mock_bindings_file("MPATHb WWID1\n"
+ "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n"
+ "MPATHa WWID0\n", -1);
expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0);
assert_int_equal(rc, INT_MAX);
@@ -922,10 +902,9 @@ static void lb_nomatch_int_max_m1_used(void **state)
int rc;
char *alias;
- will_return(__wrap_fgets, "MPATHb WWID1\n");
- will_return(__wrap_fgets, "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n");
- will_return(__wrap_fgets, "MPATHa WWID0\n");
- will_return(__wrap_fgets, NULL);
+ mock_bindings_file("MPATHb WWID1\n"
+ "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n"
+ "MPATHa WWID0\n", -1);
mock_used_alias("MPATH" MPATH_ID_INT_MAX, "WWID2");
expect_condlog(0, NOMORE_STR);
rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1);
@@ -938,9 +917,8 @@ static void lb_nomatch_int_max_m1_1_used(void **state)
int rc;
char *alias;
- will_return(__wrap_fgets, "MPATHb WWID1\n");
- will_return(__wrap_fgets, "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n");
- will_return(__wrap_fgets, NULL);
+ mock_bindings_file("MPATHb WWID1\n"
+ "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n", -1);
mock_used_alias("MPATHa", "WWID2");
mock_unused_alias("MPATH" MPATH_ID_INT_MAX);
expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
@@ -954,9 +932,8 @@ static void lb_nomatch_int_max_m1_2_used(void **state)
int rc;
char *alias;
- will_return(__wrap_fgets, "MPATHb WWID1\n");
- will_return(__wrap_fgets, "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n");
- will_return(__wrap_fgets, NULL);
+ mock_bindings_file("MPATHb WWID1\n"
+ "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n", -1);
mock_used_alias("MPATHa", "WWID2");
mock_used_alias("MPATH" MPATH_ID_INT_MAX, "WWID2");
expect_condlog(0, NOMORE_STR);
@@ -1014,7 +991,7 @@ static void rl_empty(void **state)
char buf[WWID_SIZE];
buf[0] = '\0';
- will_return(__wrap_fgets, NULL);
+ mock_bindings_file("", -1);
expect_condlog(3, NOMATCH_STR("MPATHa"));
rc = rlookup_binding(NULL, buf, "MPATHa");
assert_int_equal(rc, -1);
@@ -1027,7 +1004,7 @@ static void rl_match_a(void **state)
char buf[WWID_SIZE];
buf[0] = '\0';
- will_return(__wrap_fgets, "MPATHa WWID0\n");
+ mock_bindings_file("MPATHa WWID0\n", 0);
expect_condlog(3, FOUND_ALIAS_STR("MPATHa", "WWID0"));
rc = rlookup_binding(NULL, buf, "MPATHa");
assert_int_equal(rc, 0);
@@ -1040,8 +1017,7 @@ static void rl_nomatch_a(void **state)
char buf[WWID_SIZE];
buf[0] = '\0';
- will_return(__wrap_fgets, "MPATHa WWID0\n");
- will_return(__wrap_fgets, NULL);
+ mock_bindings_file("MPATHa WWID0\n", -1);
expect_condlog(3, NOMATCH_STR("MPATHb"));
rc = rlookup_binding(NULL, buf, "MPATHb");
assert_int_equal(rc, -1);
@@ -1054,8 +1030,7 @@ static void rl_malformed_a(void **state)
char buf[WWID_SIZE];
buf[0] = '\0';
- will_return(__wrap_fgets, "MPATHa \n");
- will_return(__wrap_fgets, NULL);
+ mock_bindings_file("MPATHa \n", -1);
expect_condlog(3, "Ignoring malformed line 1 in bindings file\n");
expect_condlog(3, NOMATCH_STR("MPATHa"));
rc = rlookup_binding(NULL, buf, "MPATHa");
@@ -1074,8 +1049,7 @@ static void rl_overlong_a(void **state)
snprintf(line + sizeof(line) - 2, 2, "\n");
buf[0] = '\0';
- will_return(__wrap_fgets, line);
- will_return(__wrap_fgets, NULL);
+ mock_bindings_file(line, -1);
expect_condlog(3, "Ignoring too large wwid at 1 in bindings file\n");
expect_condlog(3, NOMATCH_STR("MPATHa"));
rc = rlookup_binding(NULL, buf, "MPATHa");
@@ -1089,9 +1063,9 @@ static void rl_match_b(void **state)
char buf[WWID_SIZE];
buf[0] = '\0';
- will_return(__wrap_fgets, "MPATHa WWID0\n");
- will_return(__wrap_fgets, "MPATHz WWID26\n");
- will_return(__wrap_fgets, "MPATHb WWID2\n");
+ mock_bindings_file("MPATHa WWID0\n"
+ "MPATHz WWID26\n"
+ "MPATHb WWID2\n", 2);
expect_condlog(3, FOUND_ALIAS_STR("MPATHb", "WWID2"));
rc = rlookup_binding(NULL, buf, "MPATHb");
assert_int_equal(rc, 0);
@@ -1222,7 +1196,7 @@ static void gufa_empty_new_rw(void **state) {
will_return(__wrap_open_file, true);
- will_return(__wrap_fgets, NULL);
+ mock_bindings_file("", -1);
mock_unused_alias("MPATHa");
expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
@@ -1235,7 +1209,7 @@ static void gufa_empty_new_rw(void **state) {
static void gufa_empty_new_ro_1(void **state) {
char *alias;
will_return(__wrap_open_file, false);
- will_return(__wrap_fgets, NULL);
+ mock_bindings_file("", -1);
mock_unused_alias("MPATHa");
expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
@@ -1248,7 +1222,7 @@ static void gufa_empty_new_ro_2(void **state) {
will_return(__wrap_open_file, true);
- will_return(__wrap_fgets, NULL);
+ mock_bindings_file("", -1);
mock_unused_alias("MPATHa");
expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
@@ -1261,7 +1235,7 @@ static void gufa_match_a_unused(void **state) {
will_return(__wrap_open_file, true);
- will_return(__wrap_fgets, BINDING_STR("MPATHa", "WWID0"));
+ mock_bindings_file("MPATHa WWID0", 0);
expect_condlog(3, FOUND_STR("MPATHa", "WWID0"));
mock_unused_alias("MPATHa");
@@ -1275,7 +1249,7 @@ static void gufa_match_a_self(void **state) {
will_return(__wrap_open_file, true);
- will_return(__wrap_fgets, BINDING_STR("MPATHa", "WWID0"));
+ mock_bindings_file("MPATHa WWID0", 0);
expect_condlog(3, FOUND_STR("MPATHa", "WWID0"));
mock_self_alias("MPATHa", "WWID0");
@@ -1289,7 +1263,7 @@ static void gufa_match_a_used(void **state) {
will_return(__wrap_open_file, true);
- will_return(__wrap_fgets, BINDING_STR("MPATHa", "WWID0"));
+ mock_bindings_file("MPATHa WWID0", 0);
expect_condlog(3, FOUND_STR("MPATHa", "WWID0"));
mock_used_alias("MPATHa", "WWID0");
@@ -1389,11 +1363,11 @@ static void gufa_old_empty(void **state) {
will_return(__wrap_open_file, true);
/* rlookup_binding for ALIAS */
- will_return(__wrap_fgets, NULL);
+ mock_bindings_file("", -1);
expect_condlog(3, NOMATCH_STR("MPATHz"));
/* lookup_binding */
- will_return(__wrap_fgets, NULL);
+ mock_bindings_file("", -1);
expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
mock_allocate_binding("MPATHz", "WWID0");

View File

@ -0,0 +1,109 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Tue, 22 Aug 2023 15:32:17 +0200
Subject: [PATCH] libmultipath: add global variable for current bindings
Add a variable global_bindings that holds the currently active vector of
bindings. This variable is freed at program exit.
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/alias.c | 11 +++++++++--
libmultipath/alias.h | 1 +
libmultipath/libmultipath.version | 1 +
multipath/main.c | 2 ++
multipathd/main.c | 1 +
5 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/libmultipath/alias.c b/libmultipath/alias.c
index 9e9ac563..dd363fd8 100644
--- a/libmultipath/alias.c
+++ b/libmultipath/alias.c
@@ -511,6 +511,7 @@ static void _free_binding(struct binding *bdg)
* an abstract type.
*/
typedef struct _vector Bindings;
+static Bindings global_bindings = { .allocated = 0 };
static void free_bindings(Bindings *bindings)
{
@@ -522,6 +523,11 @@ static void free_bindings(Bindings *bindings)
vector_reset(bindings);
}
+void cleanup_bindings(void)
+{
+ free_bindings(&global_bindings);
+}
+
enum {
BINDING_EXISTS,
BINDING_CONFLICT,
@@ -751,7 +757,6 @@ int check_alias_settings(const struct config *conf)
pthread_cleanup_pop(1);
pthread_cleanup_pop(1);
- pthread_cleanup_push_cast(free_bindings, &bindings);
fd = open_file(conf->bindings_file, &can_write, BINDINGS_FILE_HEADER);
if (fd != -1) {
FILE *file = fdopen(fd, "r");
@@ -771,6 +776,8 @@ int check_alias_settings(const struct config *conf)
close(fd);
}
}
- pthread_cleanup_pop(1);
+
+ cleanup_bindings();
+ global_bindings = bindings;
return rc;
}
diff --git a/libmultipath/alias.h b/libmultipath/alias.h
index fa332233..37b49d9c 100644
--- a/libmultipath/alias.h
+++ b/libmultipath/alias.h
@@ -9,5 +9,6 @@ char *get_user_friendly_alias(const char *wwid, const char *file,
struct config;
int check_alias_settings(const struct config *);
+void cleanup_bindings(void);
#endif /* _ALIAS_H */
diff --git a/libmultipath/libmultipath.version b/libmultipath/libmultipath.version
index a7b8c337..ddd302f5 100644
--- a/libmultipath/libmultipath.version
+++ b/libmultipath/libmultipath.version
@@ -64,6 +64,7 @@ global:
checker_name;
checker_state_name;
check_foreign;
+ cleanup_bindings;
cleanup_lock;
coalesce_paths;
count_active_paths;
diff --git a/multipath/main.c b/multipath/main.c
index b78f3162..45e9745f 100644
--- a/multipath/main.c
+++ b/multipath/main.c
@@ -843,6 +843,8 @@ main (int argc, char *argv[])
conf->force_sync = 1;
if (atexit(cleanup_vecs))
condlog(1, "failed to register cleanup handler for vecs: %m");
+ if (atexit(cleanup_bindings))
+ condlog(1, "failed to register cleanup handler for bindings: %m");
while ((arg = getopt(argc, argv, ":adDcChl::eFfM:v:p:b:BrR:itTquUwW")) != EOF ) {
switch(arg) {
case 'v':
diff --git a/multipathd/main.c b/multipathd/main.c
index 2e02a548..214ed4ae 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -3325,6 +3325,7 @@ static void cleanup_child(void)
{
cleanup_threads();
cleanup_vecs();
+ cleanup_bindings();
if (poll_dmevents)
cleanup_dmevent_waiter();

View File

@ -0,0 +1,40 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Tue, 22 Aug 2023 15:37:15 +0200
Subject: [PATCH] libmultipath: rename fix_bindings_file() to
update_bindings_file()
We will use this function in a more generic way, give it a more
generic name.
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/alias.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/libmultipath/alias.c b/libmultipath/alias.c
index dd363fd8..0aac2393 100644
--- a/libmultipath/alias.c
+++ b/libmultipath/alias.c
@@ -595,8 +595,8 @@ static int write_bindings_file(const Bindings *bindings, int fd)
return 0;
}
-static int fix_bindings_file(const struct config *conf,
- const Bindings *bindings)
+static int update_bindings_file(const struct config *conf,
+ const Bindings *bindings)
{
int rc;
int fd = -1;
@@ -766,7 +766,7 @@ int check_alias_settings(const struct config *conf)
rc = _check_bindings_file(conf, file, &bindings);
pthread_cleanup_pop(1);
if (rc == -1 && can_write && !conf->bindings_read_only)
- rc = fix_bindings_file(conf, &bindings);
+ rc = update_bindings_file(conf, &bindings);
else if (rc == -1)
condlog(0, "ERROR: bad settings in read-only bindings file %s",
conf->bindings_file);

View File

@ -0,0 +1,285 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Tue, 22 Aug 2023 16:54:54 +0200
Subject: [PATCH] libmultipath: alias.c: move bindings related code up
No code changes, just moving code.
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/alias.c | 239 ++++++++++++++++++++++---------------------
1 file changed, 120 insertions(+), 119 deletions(-)
diff --git a/libmultipath/alias.c b/libmultipath/alias.c
index 0aac2393..7af403da 100644
--- a/libmultipath/alias.c
+++ b/libmultipath/alias.c
@@ -9,6 +9,7 @@
#include <limits.h>
#include <stdio.h>
#include <stdbool.h>
+#include <assert.h>
#include "debug.h"
#include "util.h"
@@ -51,6 +52,125 @@
static const char bindings_file_header[] = BINDINGS_FILE_HEADER;
+struct binding {
+ char *alias;
+ char *wwid;
+};
+
+/*
+ * Perhaps one day we'll implement this more efficiently, thus use
+ * an abstract type.
+ */
+typedef struct _vector Bindings;
+static Bindings global_bindings = { .allocated = 0 };
+
+enum {
+ BINDING_EXISTS,
+ BINDING_CONFLICT,
+ BINDING_ADDED,
+ BINDING_DELETED,
+ BINDING_NOTFOUND,
+ BINDING_ERROR,
+};
+
+static void _free_binding(struct binding *bdg)
+{
+ free(bdg->wwid);
+ free(bdg->alias);
+ free(bdg);
+}
+
+static int add_binding(Bindings *bindings, const char *alias, const char *wwid)
+{
+ struct binding *bdg;
+ int i, cmp = 0;
+
+ /*
+ * Keep the bindings array sorted by alias.
+ * Optimization: Search backwards, assuming that the bindings file is
+ * sorted already.
+ */
+ vector_foreach_slot_backwards(bindings, bdg, i) {
+ if ((cmp = strcmp(bdg->alias, alias)) <= 0)
+ break;
+ }
+
+ /* Check for exact match */
+ if (i >= 0 && cmp == 0)
+ return strcmp(bdg->wwid, wwid) ?
+ BINDING_CONFLICT : BINDING_EXISTS;
+
+ i++;
+ bdg = calloc(1, sizeof(*bdg));
+ if (bdg) {
+ bdg->wwid = strdup(wwid);
+ bdg->alias = strdup(alias);
+ if (bdg->wwid && bdg->alias &&
+ vector_insert_slot(bindings, i, bdg))
+ return BINDING_ADDED;
+ else
+ _free_binding(bdg);
+ }
+
+ return BINDING_ERROR;
+}
+
+static int write_bindings_file(const Bindings *bindings, int fd)
+{
+ struct binding *bnd;
+ STRBUF_ON_STACK(line);
+ int i;
+
+ if (write(fd, BINDINGS_FILE_HEADER, sizeof(BINDINGS_FILE_HEADER) - 1)
+ != sizeof(BINDINGS_FILE_HEADER) - 1)
+ return -1;
+
+ vector_foreach_slot(bindings, bnd, i) {
+ int len;
+
+ if ((len = print_strbuf(&line, "%s %s\n",
+ bnd->alias, bnd->wwid)) < 0)
+ return -1;
+ if (write(fd, get_strbuf_str(&line), len) != len)
+ return -1;
+ truncate_strbuf(&line, 0);
+ }
+ return 0;
+}
+
+static int update_bindings_file(const struct config *conf,
+ const Bindings *bindings)
+{
+ int rc;
+ int fd = -1;
+ char tempname[PATH_MAX];
+ mode_t old_umask;
+
+ if (safe_sprintf(tempname, "%s.XXXXXX", conf->bindings_file))
+ return -1;
+ /* coverity: SECURE_TEMP */
+ old_umask = umask(0077);
+ if ((fd = mkstemp(tempname)) == -1) {
+ condlog(1, "%s: mkstemp: %m", __func__);
+ return -1;
+ }
+ umask(old_umask);
+ pthread_cleanup_push(cleanup_fd_ptr, &fd);
+ rc = write_bindings_file(bindings, fd);
+ pthread_cleanup_pop(1);
+ if (rc == -1) {
+ condlog(1, "failed to write new bindings file %s",
+ tempname);
+ unlink(tempname);
+ return rc;
+ }
+ if ((rc = rename(tempname, conf->bindings_file)) == -1)
+ condlog(0, "%s: rename: %m", __func__);
+ else
+ condlog(1, "updated bindings file %s", conf->bindings_file);
+ return rc;
+}
+
int
valid_alias(const char *alias)
{
@@ -494,25 +614,6 @@ get_user_friendly_wwid(const char *alias, char *buff, const char *file)
return 0;
}
-struct binding {
- char *alias;
- char *wwid;
-};
-
-static void _free_binding(struct binding *bdg)
-{
- free(bdg->wwid);
- free(bdg->alias);
- free(bdg);
-}
-
-/*
- * Perhaps one day we'll implement this more efficiently, thus use
- * an abstract type.
- */
-typedef struct _vector Bindings;
-static Bindings global_bindings = { .allocated = 0 };
-
static void free_bindings(Bindings *bindings)
{
struct binding *bdg;
@@ -528,106 +629,6 @@ void cleanup_bindings(void)
free_bindings(&global_bindings);
}
-enum {
- BINDING_EXISTS,
- BINDING_CONFLICT,
- BINDING_ADDED,
- BINDING_DELETED,
- BINDING_NOTFOUND,
- BINDING_ERROR,
-};
-
-static int add_binding(Bindings *bindings, const char *alias, const char *wwid)
-{
- struct binding *bdg;
- int i, cmp = 0;
-
- /*
- * Keep the bindings array sorted by alias.
- * Optimization: Search backwards, assuming that the bindings file is
- * sorted already.
- */
- vector_foreach_slot_backwards(bindings, bdg, i) {
- if ((cmp = strcmp(bdg->alias, alias)) <= 0)
- break;
- }
-
- /* Check for exact match */
- if (i >= 0 && cmp == 0)
- return strcmp(bdg->wwid, wwid) ?
- BINDING_CONFLICT : BINDING_EXISTS;
-
- i++;
- bdg = calloc(1, sizeof(*bdg));
- if (bdg) {
- bdg->wwid = strdup(wwid);
- bdg->alias = strdup(alias);
- if (bdg->wwid && bdg->alias &&
- vector_insert_slot(bindings, i, bdg))
- return BINDING_ADDED;
- else
- _free_binding(bdg);
- }
-
- return BINDING_ERROR;
-}
-
-static int write_bindings_file(const Bindings *bindings, int fd)
-{
- struct binding *bnd;
- STRBUF_ON_STACK(line);
- int i;
-
- if (write(fd, BINDINGS_FILE_HEADER, sizeof(BINDINGS_FILE_HEADER) - 1)
- != sizeof(BINDINGS_FILE_HEADER) - 1)
- return -1;
-
- vector_foreach_slot(bindings, bnd, i) {
- int len;
-
- if ((len = print_strbuf(&line, "%s %s\n",
- bnd->alias, bnd->wwid)) < 0)
- return -1;
- if (write(fd, get_strbuf_str(&line), len) != len)
- return -1;
- truncate_strbuf(&line, 0);
- }
- return 0;
-}
-
-static int update_bindings_file(const struct config *conf,
- const Bindings *bindings)
-{
- int rc;
- int fd = -1;
- char tempname[PATH_MAX];
- mode_t old_umask;
-
- if (safe_sprintf(tempname, "%s.XXXXXX", conf->bindings_file))
- return -1;
- /* coverity: SECURE_TEMP */
- old_umask = umask(0077);
- if ((fd = mkstemp(tempname)) == -1) {
- condlog(1, "%s: mkstemp: %m", __func__);
- return -1;
- }
- umask(old_umask);
- pthread_cleanup_push(cleanup_fd_ptr, &fd);
- rc = write_bindings_file(bindings, fd);
- pthread_cleanup_pop(1);
- if (rc == -1) {
- condlog(1, "failed to write new bindings file %s",
- tempname);
- unlink(tempname);
- return rc;
- }
- if ((rc = rename(tempname, conf->bindings_file)) == -1)
- condlog(0, "%s: rename: %m", __func__);
- else
- condlog(1, "updated bindings file %s", conf->bindings_file);
- return rc;
-}
-
static int _check_bindings_file(const struct config *conf, FILE *file,
Bindings *bindings)
{

View File

@ -0,0 +1,61 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Thu, 24 Aug 2023 15:53:49 +0200
Subject: [PATCH] libmultipath: update_bindings_file: take filename argument
This function just uses the file name, no other configuration
parameters. Also, pass the Bindings argument first to use the
same convention as the other functions in this file.
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/alias.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/libmultipath/alias.c b/libmultipath/alias.c
index 7af403da..9bd3875e 100644
--- a/libmultipath/alias.c
+++ b/libmultipath/alias.c
@@ -138,15 +138,15 @@ static int write_bindings_file(const Bindings *bindings, int fd)
return 0;
}
-static int update_bindings_file(const struct config *conf,
- const Bindings *bindings)
+static int update_bindings_file(const Bindings *bindings,
+ const char *bindings_file)
{
int rc;
int fd = -1;
char tempname[PATH_MAX];
mode_t old_umask;
- if (safe_sprintf(tempname, "%s.XXXXXX", conf->bindings_file))
+ if (safe_sprintf(tempname, "%s.XXXXXX", bindings_file))
return -1;
/* coverity: SECURE_TEMP */
old_umask = umask(0077);
@@ -164,10 +164,10 @@ static int update_bindings_file(const struct config *conf,
unlink(tempname);
return rc;
}
- if ((rc = rename(tempname, conf->bindings_file)) == -1)
+ if ((rc = rename(tempname, bindings_file)) == -1)
condlog(0, "%s: rename: %m", __func__);
else
- condlog(1, "updated bindings file %s", conf->bindings_file);
+ condlog(1, "updated bindings file %s", bindings_file);
return rc;
}
@@ -767,7 +767,7 @@ int check_alias_settings(const struct config *conf)
rc = _check_bindings_file(conf, file, &bindings);
pthread_cleanup_pop(1);
if (rc == -1 && can_write && !conf->bindings_read_only)
- rc = update_bindings_file(conf, &bindings);
+ rc = update_bindings_file(&bindings, conf->bindings_file);
else if (rc == -1)
condlog(0, "ERROR: bad settings in read-only bindings file %s",
conf->bindings_file);

View File

@ -0,0 +1,59 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Thu, 24 Aug 2023 15:54:45 +0200
Subject: [PATCH] libmultipath: update_bindings_file: use a single write()
Save code and syscalls by assembling the content in memory first.
write() may return less bytes written than expected. Deal with it.
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/alias.c | 26 +++++++++++++++++---------
1 file changed, 17 insertions(+), 9 deletions(-)
diff --git a/libmultipath/alias.c b/libmultipath/alias.c
index 9bd3875e..92f90f05 100644
--- a/libmultipath/alias.c
+++ b/libmultipath/alias.c
@@ -118,22 +118,30 @@ static int add_binding(Bindings *bindings, const char *alias, const char *wwid)
static int write_bindings_file(const Bindings *bindings, int fd)
{
struct binding *bnd;
- STRBUF_ON_STACK(line);
+ STRBUF_ON_STACK(content);
int i;
+ size_t len;
- if (write(fd, BINDINGS_FILE_HEADER, sizeof(BINDINGS_FILE_HEADER) - 1)
- != sizeof(BINDINGS_FILE_HEADER) - 1)
+ if (__append_strbuf_str(&content, BINDINGS_FILE_HEADER,
+ sizeof(BINDINGS_FILE_HEADER) - 1) == -1)
return -1;
vector_foreach_slot(bindings, bnd, i) {
- int len;
-
- if ((len = print_strbuf(&line, "%s %s\n",
- bnd->alias, bnd->wwid)) < 0)
+ if (print_strbuf(&content, "%s %s\n",
+ bnd->alias, bnd->wwid) < 0)
return -1;
- if (write(fd, get_strbuf_str(&line), len) != len)
+ }
+ len = get_strbuf_len(&content);
+ while (len > 0) {
+ ssize_t n = write(fd, get_strbuf_str(&content), len);
+
+ if (n < 0)
+ return n;
+ else if (n == 0) {
+ condlog(2, "%s: short write", __func__);
return -1;
- truncate_strbuf(&line, 0);
+ }
+ len -= n;
}
return 0;
}

View File

@ -0,0 +1,29 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Thu, 24 Aug 2023 22:33:39 +0200
Subject: [PATCH] libmultipath: update_bindings_file: don't log temp file name
The name of the temp file is unlikely to be helpful for users,
and hard to predict in the unit test. Omit it.
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/alias.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/libmultipath/alias.c b/libmultipath/alias.c
index 92f90f05..afa5879e 100644
--- a/libmultipath/alias.c
+++ b/libmultipath/alias.c
@@ -167,8 +167,7 @@ static int update_bindings_file(const Bindings *bindings,
rc = write_bindings_file(bindings, fd);
pthread_cleanup_pop(1);
if (rc == -1) {
- condlog(1, "failed to write new bindings file %s",
- tempname);
+ condlog(1, "failed to write new bindings file");
unlink(tempname);
return rc;
}

View File

@ -0,0 +1,94 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Thu, 24 Aug 2023 21:17:25 +0200
Subject: [PATCH] libmultipath: alias.c: factor out read_binding()
This way we can test the parsing of input lines from the bindings
file more easily.
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/alias.c | 58 ++++++++++++++++++++++++++++++--------------
1 file changed, 40 insertions(+), 18 deletions(-)
diff --git a/libmultipath/alias.c b/libmultipath/alias.c
index afa5879e..ecf4a2ac 100644
--- a/libmultipath/alias.c
+++ b/libmultipath/alias.c
@@ -636,6 +636,43 @@ void cleanup_bindings(void)
free_bindings(&global_bindings);
}
+enum {
+ READ_BINDING_OK,
+ READ_BINDING_SKIP,
+};
+
+static int read_binding(char *line, unsigned int linenr, char **alias,
+ char **wwid) {
+ char *c, *saveptr;
+
+ c = strpbrk(line, "#\n\r");
+ if (c)
+ *c = '\0';
+
+ *alias = strtok_r(line, " \t", &saveptr);
+ if (!*alias) /* blank line */
+ return READ_BINDING_SKIP;
+
+ *wwid = strtok_r(NULL, " \t", &saveptr);
+ if (!*wwid) {
+ condlog(1, "invalid line %u in bindings file, missing WWID",
+ linenr);
+ return READ_BINDING_SKIP;
+ }
+ if (strlen(*wwid) > WWID_SIZE - 1) {
+ condlog(3,
+ "Ignoring too large wwid at %u in bindings file",
+ linenr);
+ return READ_BINDING_SKIP;
+ }
+ c = strtok_r(NULL, " \t", &saveptr);
+ if (c)
+ /* This is non-fatal */
+ condlog(1, "invalid line %d in bindings file, extra args \"%s\"",
+ linenr, c);
+ return READ_BINDING_OK;
+}
+
static int _check_bindings_file(const struct config *conf, FILE *file,
Bindings *bindings)
{
@@ -647,27 +684,12 @@ static int _check_bindings_file(const struct config *conf, FILE *file,
pthread_cleanup_push(cleanup_free_ptr, &line);
while ((n = getline(&line, &line_len, file)) >= 0) {
- char *c, *alias, *wwid, *saveptr;
+ char *alias, *wwid;
const char *mpe_wwid;
- linenr++;
- c = strpbrk(line, "#\n\r");
- if (c)
- *c = '\0';
- alias = strtok_r(line, " \t", &saveptr);
- if (!alias) /* blank line */
- continue;
- wwid = strtok_r(NULL, " \t", &saveptr);
- if (!wwid) {
- condlog(1, "invalid line %d in bindings file, missing WWID",
- linenr);
+ if (read_binding(line, ++linenr, &alias, &wwid)
+ == READ_BINDING_SKIP)
continue;
- }
- c = strtok_r(NULL, " \t", &saveptr);
- if (c)
- /* This is non-fatal */
- condlog(1, "invalid line %d in bindings file, extra args \"%s\"",
- linenr, c);
mpe_wwid = get_mpe_wwid(conf->mptable, alias);
if (mpe_wwid && strcmp(mpe_wwid, wwid)) {

View File

@ -0,0 +1,545 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Tue, 22 Aug 2023 21:14:51 +0200
Subject: [PATCH] libmultipath: keep bindings in memory
Rather than opening the bindings file every time we must retrieve
a binding, keep the contents in memory and write the file only
if additions have been made. This simplifies the code, and should speed up
alias lookups significantly. As a side effect, the aliases will be stored
sorted by alias, which changes the way aliases are allocated if there are
unused "holes" in the sequence of aliases. For example, if the bindings file
contains mpathb, mpathy, and mpatha, in this order, the next new alias used to
be mpathz and is now mpathc.
Another side effect is that multipathd will not automatically pick up changes
to the bindings file at runtime without a reconfigure operation. It is
questionable whether these on-the-fly changes were a good idea in the first
place, as inconsistent configurations may easily come to pass. It desired,
it would be feasible to implement automatic update of the bindings using the
existing inotify approach.
The new implementation of get_user_friendly_alias() is slightly different
than before. The logic is summarized in a comment in the code. Unit tests
will be provided that illustrate the changes.
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/alias.c | 351 ++++++++++++++++-----------------------
libmultipath/alias.h | 2 +-
libmultipath/configure.c | 3 +-
3 files changed, 144 insertions(+), 212 deletions(-)
diff --git a/libmultipath/alias.c b/libmultipath/alias.c
index ecf4a2ac..d6563749 100644
--- a/libmultipath/alias.c
+++ b/libmultipath/alias.c
@@ -50,8 +50,6 @@
"# alias wwid\n" \
"#\n"
-static const char bindings_file_header[] = BINDINGS_FILE_HEADER;
-
struct binding {
char *alias;
char *wwid;
@@ -80,6 +78,45 @@ static void _free_binding(struct binding *bdg)
free(bdg);
}
+static const struct binding *get_binding_for_alias(const Bindings *bindings,
+ const char *alias)
+{
+ const struct binding *bdg;
+ int i;
+
+ if (!alias)
+ return NULL;
+ vector_foreach_slot(bindings, bdg, i) {
+ if (!strncmp(bdg->alias, alias, WWID_SIZE)) {
+ condlog(3, "Found matching alias [%s] in bindings file."
+ " Setting wwid to %s", alias, bdg->wwid);
+ return bdg;
+ }
+ }
+
+ condlog(3, "No matching alias [%s] in bindings file.", alias);
+ return NULL;
+}
+
+static const struct binding *get_binding_for_wwid(const Bindings *bindings,
+ const char *wwid)
+{
+ const struct binding *bdg;
+ int i;
+
+ if (!wwid)
+ return NULL;
+ vector_foreach_slot(bindings, bdg, i) {
+ if (!strncmp(bdg->wwid, wwid, WWID_SIZE)) {
+ condlog(3, "Found matching wwid [%s] in bindings file."
+ " Setting alias to %s", wwid, bdg->alias);
+ return bdg;
+ }
+ }
+ condlog(3, "No matching wwid [%s] in bindings file.", wwid);
+ return NULL;
+}
+
static int add_binding(Bindings *bindings, const char *alias, const char *wwid)
{
struct binding *bdg;
@@ -115,6 +152,24 @@ static int add_binding(Bindings *bindings, const char *alias, const char *wwid)
return BINDING_ERROR;
}
+static int delete_binding(Bindings *bindings, const char *wwid)
+{
+ struct binding *bdg;
+ int i;
+
+ vector_foreach_slot(bindings, bdg, i) {
+ if (!strncmp(bdg->wwid, wwid, WWID_SIZE)) {
+ _free_binding(bdg);
+ break;
+ }
+ }
+ if (i >= VECTOR_SIZE(bindings))
+ return BINDING_NOTFOUND;
+
+ vector_del_slot(bindings, i);
+ return BINDING_DELETED;
+}
+
static int write_bindings_file(const Bindings *bindings, int fd)
{
struct binding *bnd;
@@ -267,38 +322,15 @@ static bool id_already_taken(int id, const char *prefix, const char *map_wwid)
return alias_already_taken(alias, map_wwid);
}
-/*
- * Returns: 0 if matching entry in WWIDs file found
- * -1 if an error occurs
- * >0 a free ID that could be used for the WWID at hand
- * *map_alias is set to a freshly allocated string with the matching alias if
- * the function returns 0, or to NULL otherwise.
- */
-static int
-lookup_binding(FILE *f, const char *map_wwid, char **map_alias,
- const char *prefix, int check_if_taken)
+int get_free_id(const Bindings *bindings, const char *prefix, const char *map_wwid)
{
- char buf[LINE_MAX];
- unsigned int line_nr = 0;
- int id = 1;
+ const struct binding *bdg;
+ int i, id = 1;
int biggest_id = 1;
int smallest_bigger_id = INT_MAX;
- *map_alias = NULL;
-
- rewind(f);
- while (fgets(buf, LINE_MAX, f)) {
- const char *alias, *wwid;
- char *c, *saveptr;
- int curr_id;
-
- line_nr++;
- c = strpbrk(buf, "#\n\r");
- if (c)
- *c = '\0';
- alias = strtok_r(buf, " \t", &saveptr);
- if (!alias) /* blank line */
- continue;
+ vector_foreach_slot(bindings, bdg, i) {
+ int curr_id = scan_devname(bdg->alias, prefix);
/*
* Find an unused index - explanation of the algorithm
@@ -333,8 +365,6 @@ lookup_binding(FILE *f, const char *map_wwid, char **map_alias,
* biggest_id is always > smallest_bigger_id, except in the
* "perfectly ordered" case.
*/
-
- curr_id = scan_devname(alias, prefix);
if (curr_id == id) {
if (id < INT_MAX)
id++;
@@ -345,36 +375,15 @@ lookup_binding(FILE *f, const char *map_wwid, char **map_alias,
}
if (curr_id > biggest_id)
biggest_id = curr_id;
+
if (curr_id > id && curr_id < smallest_bigger_id)
smallest_bigger_id = curr_id;
- wwid = strtok_r(NULL, " \t", &saveptr);
- if (!wwid){
- condlog(3,
- "Ignoring malformed line %u in bindings file",
- line_nr);
- continue;
- }
- if (strcmp(wwid, map_wwid) == 0){
- condlog(3, "Found matching wwid [%s] in bindings file."
- " Setting alias to %s", wwid, alias);
- *map_alias = strdup(alias);
- if (*map_alias == NULL) {
- condlog(0, "Cannot copy alias from bindings "
- "file: out of memory");
- return -1;
- }
- return 0;
- }
- }
- if (!prefix && check_if_taken)
- id = -1;
- if (id >= smallest_bigger_id) {
- if (biggest_id < INT_MAX)
- id = biggest_id + 1;
- else
- id = -1;
}
- if (id > 0 && check_if_taken) {
+
+ if (id >= smallest_bigger_id)
+ id = biggest_id < INT_MAX ? biggest_id + 1 : -1;
+
+ if (id > 0) {
while(id_already_taken(id, prefix, map_wwid)) {
if (id == INT_MAX) {
id = -1;
@@ -391,64 +400,17 @@ lookup_binding(FILE *f, const char *map_wwid, char **map_alias,
}
}
}
- if (id < 0) {
+
+ if (id < 0)
condlog(0, "no more available user_friendly_names");
- return -1;
- } else
- condlog(3, "No matching wwid [%s] in bindings file.", map_wwid);
return id;
}
-static int
-rlookup_binding(FILE *f, char *buff, const char *map_alias)
-{
- char line[LINE_MAX];
- unsigned int line_nr = 0;
-
- buff[0] = '\0';
-
- while (fgets(line, LINE_MAX, f)) {
- char *c, *saveptr;
- const char *alias, *wwid;
-
- line_nr++;
- c = strpbrk(line, "#\n\r");
- if (c)
- *c = '\0';
- alias = strtok_r(line, " \t", &saveptr);
- if (!alias) /* blank line */
- continue;
- wwid = strtok_r(NULL, " \t", &saveptr);
- if (!wwid){
- condlog(3,
- "Ignoring malformed line %u in bindings file",
- line_nr);
- continue;
- }
- if (strlen(wwid) > WWID_SIZE - 1) {
- condlog(3,
- "Ignoring too large wwid at %u in bindings file", line_nr);
- continue;
- }
- if (strcmp(alias, map_alias) == 0){
- condlog(3, "Found matching alias [%s] in bindings file."
- " Setting wwid to %s", alias, wwid);
- strlcpy(buff, wwid, WWID_SIZE);
- return 0;
- }
- }
- condlog(3, "No matching alias [%s] in bindings file.", map_alias);
-
- return -1;
-}
-
static char *
-allocate_binding(int fd, const char *wwid, int id, const char *prefix)
+allocate_binding(const char *filename, const char *wwid, int id, const char *prefix)
{
STRBUF_ON_STACK(buf);
- off_t offset;
- ssize_t len;
- char *alias, *c;
+ char *alias;
if (id <= 0) {
condlog(0, "%s: cannot allocate new binding for id %d",
@@ -460,164 +422,135 @@ allocate_binding(int fd, const char *wwid, int id, const char *prefix)
format_devname(&buf, id) == -1)
return NULL;
- if (print_strbuf(&buf, " %s\n", wwid) < 0)
- return NULL;
+ alias = steal_strbuf_str(&buf);
- offset = lseek(fd, 0, SEEK_END);
- if (offset < 0){
- condlog(0, "Cannot seek to end of bindings file : %s",
- strerror(errno));
+ if (add_binding(&global_bindings, alias, wwid) != BINDING_ADDED) {
+ condlog(0, "%s: cannot allocate new binding %s for %s",
+ __func__, alias, wwid);
+ free(alias);
return NULL;
}
- len = get_strbuf_len(&buf);
- alias = steal_strbuf_str(&buf);
-
- if (write(fd, alias, len) != len) {
- condlog(0, "Cannot write binding to bindings file : %s",
- strerror(errno));
- /* clear partial write */
- if (ftruncate(fd, offset))
- condlog(0, "Cannot truncate the header : %s",
- strerror(errno));
+ if (update_bindings_file(&global_bindings, filename) == -1) {
+ condlog(1, "%s: deleting binding %s for %s", __func__, alias, wwid);
+ delete_binding(&global_bindings, wwid);
free(alias);
return NULL;
}
- c = strchr(alias, ' ');
- if (c)
- *c = '\0';
condlog(3, "Created new binding [%s] for WWID [%s]", alias, wwid);
return alias;
}
+/*
+ * get_user_friendly_alias() action table
+ *
+ * The table shows the various cases, the actions taken, and the CI
+ * functions from tests/alias.c that represent them.
+ *
+ * - O: old alias given
+ * - A: old alias in table (y: yes, correct WWID; X: yes, wrong WWID)
+ * - W: wwid in table
+ *
+ * | No | O | A | W | action | function gufa_X |
+ * |----+---+---+---+--------------------------------------------+------------------------------|
+ * | 1 | n | - | n | get new alias | nomatch_Y |
+ * | 2 | n | - | y | use alias from bindings | match_a_Y |
+ * | 3 | y | n | n | add binding for old alias | old_nomatch_nowwidmatch |
+ * | 4 | y | n | y | use alias from bindings (avoid duplicates) | old_nomatch_wwidmatch |
+ * | 5 | y | y | n | [ impossible ] | - |
+ * | 6 | y | y | y | use old alias == alias from bindings | old_match |
+ * | 7 | y | X | n | get new alias | old_match_other |
+ * | 8 | y | X | y | use alias from bindings | old_match_other_wwidmatch |
+ *
+ * Notes:
+ * - "use alias from bindings" means that the alias from the bindings file will
+ * be tried; if it is in use, the alias selection will fail. No other
+ * bindings will be attempted.
+ * - "get new alias" fails if all aliases are used up, or if writing the
+ * bindings file fails.
+ * - if "alias_old" is set, it can't be bound to a different map. alias_old is
+ * initialized in find_existing_alias() by scanning the mpvec. We trust
+ * that the mpvec corrcectly represents kernel state.
+ */
+
char *get_user_friendly_alias(const char *wwid, const char *file, const char *alias_old,
const char *prefix, bool bindings_read_only)
{
char *alias = NULL;
int id = 0;
- int fd, can_write;
bool new_binding = false;
- char buff[WWID_SIZE];
- FILE *f;
-
- fd = open_file(file, &can_write, bindings_file_header);
- if (fd < 0)
- return NULL;
-
- f = fdopen(fd, "r");
- if (!f) {
- condlog(0, "cannot fdopen on bindings file descriptor");
- close(fd);
- return NULL;
- }
+ const struct binding *bdg;
- if (!strlen(alias_old))
+ if (!*alias_old)
goto new_alias;
- /* lookup the binding. if it exists, the wwid will be in buff
- * either way, id contains the id for the alias
- */
- rlookup_binding(f, buff, alias_old);
-
- if (strlen(buff) > 0) {
- /* If buff is our wwid, it's already allocated correctly. */
- if (strcmp(buff, wwid) == 0) {
+ /* See if there's a binding matching both alias_old and wwid */
+ bdg = get_binding_for_alias(&global_bindings, alias_old);
+ if (bdg) {
+ if (!strcmp(bdg->wwid, wwid)) {
alias = strdup(alias_old);
goto out;
-
} else {
condlog(0, "alias %s already bound to wwid %s, cannot reuse",
- alias_old, buff);
+ alias_old, bdg->wwid);
goto new_alias;
}
}
- /*
- * Look for an existing alias in the bindings file.
- * Pass prefix = NULL, so lookup_binding() won't try to allocate a new id.
- */
- lookup_binding(f, wwid, &alias, NULL, 0);
- if (alias) {
- if (alias_already_taken(alias, wwid)) {
- free(alias);
- alias = NULL;
- } else
+ /* allocate the existing alias in the bindings file */
+ id = scan_devname(alias_old, prefix);
+
+new_alias:
+ /* Check for existing binding of WWID */
+ bdg = get_binding_for_wwid(&global_bindings, wwid);
+ if (bdg) {
+ if (!alias_already_taken(bdg->alias, wwid)) {
condlog(3, "Use existing binding [%s] for WWID [%s]",
- alias, wwid);
+ bdg->alias, wwid);
+ alias = strdup(bdg->alias);
+ }
goto out;
}
- /* alias_old is already taken by our WWID, update bindings file. */
- id = scan_devname(alias_old, prefix);
-
-new_alias:
if (id <= 0) {
/*
* no existing alias was provided, or allocating it
* failed. Try a new one.
*/
- id = lookup_binding(f, wwid, &alias, prefix, 1);
- if (id == 0 && alias_already_taken(alias, wwid)) {
- free(alias);
- alias = NULL;
- }
+ id = get_free_id(&global_bindings, prefix, wwid);
if (id <= 0)
goto out;
else
new_binding = true;
}
- if (fflush(f) != 0) {
- condlog(0, "cannot fflush bindings file stream : %s",
- strerror(errno));
- goto out;
- }
+ if (!bindings_read_only && id > 0)
+ alias = allocate_binding(file, wwid, id, prefix);
- if (can_write && !bindings_read_only) {
- alias = allocate_binding(fd, wwid, id, prefix);
- if (alias && !new_binding)
- condlog(2, "Allocated existing binding [%s] for WWID [%s]",
- alias, wwid);
- }
+ if (alias && !new_binding)
+ condlog(2, "Allocated existing binding [%s] for WWID [%s]",
+ alias, wwid);
out:
- pthread_cleanup_push(free, alias);
- fclose(f);
- pthread_cleanup_pop(0);
return alias;
}
-int
-get_user_friendly_wwid(const char *alias, char *buff, const char *file)
+int get_user_friendly_wwid(const char *alias, char *buff)
{
- int fd, unused;
- FILE *f;
+ const struct binding *bdg;
if (!alias || *alias == '\0') {
condlog(3, "Cannot find binding for empty alias");
return -1;
}
- fd = open_file(file, &unused, bindings_file_header);
- if (fd < 0)
- return -1;
-
- f = fdopen(fd, "r");
- if (!f) {
- condlog(0, "cannot fdopen on bindings file descriptor : %s",
- strerror(errno));
- close(fd);
+ bdg = get_binding_for_alias(&global_bindings, alias);
+ if (!bdg) {
+ *buff = '\0';
return -1;
}
-
- rlookup_binding(f, buff, alias);
- if (!strlen(buff)) {
- fclose(f);
- return -1;
- }
-
- fclose(f);
+ strlcpy(buff, bdg->wwid, WWID_SIZE);
return 0;
}
diff --git a/libmultipath/alias.h b/libmultipath/alias.h
index 37b49d9c..5ef6720b 100644
--- a/libmultipath/alias.h
+++ b/libmultipath/alias.h
@@ -2,7 +2,7 @@
#define _ALIAS_H
int valid_alias(const char *alias);
-int get_user_friendly_wwid(const char *alias, char *buff, const char *file);
+int get_user_friendly_wwid(const char *alias, char *buff);
char *get_user_friendly_alias(const char *wwid, const char *file,
const char *alias_old,
const char *prefix, bool bindings_read_only);
diff --git a/libmultipath/configure.c b/libmultipath/configure.c
index 029fbbd2..d8094903 100644
--- a/libmultipath/configure.c
+++ b/libmultipath/configure.c
@@ -1378,8 +1378,7 @@ static int _get_refwwid(enum mpath_cmds cmd, const char *dev,
refwwid = tmpwwid;
/* or may be a binding */
- else if (get_user_friendly_wwid(dev, tmpwwid,
- conf->bindings_file) == 0)
+ else if (get_user_friendly_wwid(dev, tmpwwid) == 0)
refwwid = tmpwwid;
/* or may be an alias */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,53 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Fri, 25 Aug 2023 20:35:19 +0200
Subject: [PATCH] libmultipath: dm_get_uuid(): return emtpy UUID for
non-existing maps
libdevmapper will most probably not return a UUID for non-existing
maps anyway. But it's cheap to double-check here.
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/devmapper.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
index 248c3734..9be82f4e 100644
--- a/libmultipath/devmapper.c
+++ b/libmultipath/devmapper.c
@@ -706,12 +706,16 @@ dm_get_prefixed_uuid(const char *name, char *uuid, int uuid_len)
{
struct dm_task *dmt;
const char *uuidtmp;
+ struct dm_info info;
int r = 1;
dmt = libmp_dm_task_create(DM_DEVICE_INFO);
if (!dmt)
return 1;
+ if (uuid_len > 0)
+ uuid[0] = '\0';
+
if (!dm_task_set_name (dmt, name))
goto uuidout;
@@ -720,11 +724,13 @@ dm_get_prefixed_uuid(const char *name, char *uuid, int uuid_len)
goto uuidout;
}
+ if (!dm_task_get_info(dmt, &info) ||
+ !info.exists)
+ goto uuidout;
+
uuidtmp = dm_task_get_uuid(dmt);
if (uuidtmp)
strlcpy(uuid, uuidtmp, uuid_len);
- else
- uuid[0] = '\0';
r = 0;
uuidout:

View File

@ -0,0 +1,158 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Mon, 28 Aug 2023 12:26:37 +0200
Subject: [PATCH] libmultipath: adapt to new semantics of dm_get_uuid()
dm_get_uuid() will return 1 for non-existing maps. Thus we don't need
to call dm_map_present() any more in alias_already_taken(). This changes
our semantics: previously we'd avoid using an alias for which dm_get_uuid()
had failed. Now we treat failure in dm_get_uuid() as indication that the
map doesn't exist. This is not dangerous because dm_task_get_uuid() cannot
fail, and thus the modified dm_get_uuid() will fail if and only if
dm_map_present() would return false.
This makes the "failed alias" test mostly obsolete, as "failed" is now
treated as "unused".
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/alias.c | 25 +++++++++++++------------
tests/alias.c | 32 +++++++-------------------------
2 files changed, 20 insertions(+), 37 deletions(-)
diff --git a/libmultipath/alias.c b/libmultipath/alias.c
index d6563749..58436ec0 100644
--- a/libmultipath/alias.c
+++ b/libmultipath/alias.c
@@ -295,18 +295,19 @@ scan_devname(const char *alias, const char *prefix)
static bool alias_already_taken(const char *alias, const char *map_wwid)
{
- if (dm_map_present(alias)) {
- char wwid[WWID_SIZE];
-
- /* If both the name and the wwid match, then it's fine.*/
- if (dm_get_uuid(alias, wwid, sizeof(wwid)) == 0 &&
- strncmp(map_wwid, wwid, sizeof(wwid)) == 0)
- return false;
- condlog(3, "%s: alias '%s' already taken, reselecting alias",
- map_wwid, alias);
- return true;
- }
- return false;
+ char wwid[WWID_SIZE];
+
+ /* If the map doesn't exist, it's fine */
+ if (dm_get_uuid(alias, wwid, sizeof(wwid)) != 0)
+ return false;
+
+ /* If both the name and the wwid match, it's fine.*/
+ if (strncmp(map_wwid, wwid, sizeof(wwid)) == 0)
+ return false;
+
+ condlog(3, "%s: alias '%s' already taken, reselecting alias",
+ map_wwid, alias);
+ return true;
}
static bool id_already_taken(int id, const char *prefix, const char *map_wwid)
diff --git a/tests/alias.c b/tests/alias.c
index 50a21ecf..d1cc487b 100644
--- a/tests/alias.c
+++ b/tests/alias.c
@@ -73,12 +73,6 @@ int __wrap_mkstemp(char *template)
return 10;
}
-int __wrap_dm_map_present(const char * str)
-{
- check_expected(str);
- return mock_type(int);
-}
-
int __wrap_dm_get_uuid(const char *name, char *uuid, int uuid_len)
{
int ret;
@@ -398,14 +392,13 @@ static int test_scan_devname(void)
static void mock_unused_alias(const char *alias)
{
- expect_string(__wrap_dm_map_present, str, alias);
- will_return(__wrap_dm_map_present, 0);
+ expect_string(__wrap_dm_get_uuid, name, alias);
+ expect_value(__wrap_dm_get_uuid, uuid_len, WWID_SIZE);
+ will_return(__wrap_dm_get_uuid, 1);
}
static void mock_self_alias(const char *alias, const char *wwid)
{
- expect_string(__wrap_dm_map_present, str, alias);
- will_return(__wrap_dm_map_present, 1);
expect_string(__wrap_dm_get_uuid, name, alias);
expect_value(__wrap_dm_get_uuid, uuid_len, WWID_SIZE);
will_return(__wrap_dm_get_uuid, 0);
@@ -432,18 +425,13 @@ static void mock_self_alias(const char *alias, const char *wwid)
#define mock_failed_alias(alias, wwid) \
do { \
- expect_string(__wrap_dm_map_present, str, alias); \
- will_return(__wrap_dm_map_present, 1); \
expect_string(__wrap_dm_get_uuid, name, alias); \
expect_value(__wrap_dm_get_uuid, uuid_len, WWID_SIZE); \
will_return(__wrap_dm_get_uuid, 1); \
- expect_condlog(3, USED_STR(alias, wwid)); \
} while (0)
#define mock_used_alias(alias, wwid) \
do { \
- expect_string(__wrap_dm_map_present, str, alias); \
- will_return(__wrap_dm_map_present, 1); \
expect_string(__wrap_dm_get_uuid, name, alias); \
expect_value(__wrap_dm_get_uuid, uuid_len, WWID_SIZE); \
will_return(__wrap_dm_get_uuid, 0); \
@@ -566,9 +554,8 @@ static void lb_empty_failed(void **state)
mock_bindings_file("");
expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
mock_failed_alias("MPATHa", "WWID0");
- mock_unused_alias("MPATHb");
rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 1);
- assert_int_equal(rc, 2);
+ assert_int_equal(rc, 1);
assert_ptr_equal(alias, NULL);
free(alias);
}
@@ -666,9 +653,8 @@ static void lb_nomatch_a_3_used_failed_self(void **state)
mock_used_alias("MPATHc", "WWID1");
mock_used_alias("MPATHd", "WWID1");
mock_failed_alias("MPATHe", "WWID1");
- mock_self_alias("MPATHf", "WWID1");
rc = lookup_binding(NULL, "WWID1", &alias, "MPATH", 1);
- assert_int_equal(rc, 6);
+ assert_int_equal(rc, 5);
assert_ptr_equal(alias, NULL);
}
@@ -940,7 +926,7 @@ static void lb_nomatch_b_a_aa(void **state)
static void lb_nomatch_b_a_aa_zz(void **state)
{
- int rc, i;
+ int rc;
char *alias;
STRBUF_ON_STACK(buf);
@@ -949,11 +935,7 @@ static void lb_nomatch_b_a_aa_zz(void **state)
* lookup_binding finds MPATHaaa as next free entry, because MPATHaa is
* found before MPATHb, and MPATHzz was in the bindings, too.
*/
- for (i = 0; i <= 26; i++) {
- print_strbuf(&buf, "MPATH");
- format_devname(&buf, i + 1);
- print_strbuf(&buf, " WWID%d\n", i);
- }
+ fill_bindings(&buf, 0, 26);
print_strbuf(&buf, "MPATHzz WWID676\n");
mock_bindings_file(get_strbuf_str(&buf));
expect_condlog(3, NOMATCH_WWID_STR("WWID703"));

View File

@ -0,0 +1,98 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Fri, 8 Sep 2023 15:19:54 +0200
Subject: [PATCH] libmultipath: sort aliases by length and strcmp
The current sort order of aliases is alphabetical, which is does not match
the actual order of aliases, where "mpathaa" > "mpathz". Change the ordering as
follows: first sort by string length, then alphabetically. This will make
sure that for aliases with the same prefix, alias order is correct ("mpathaaa"
will be sorted after "mpathzz", etc). Even for mixed prefixes, the alias
order will be correct for every individual prefix, even though aliases with
different prefixes may alternate in the file.
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/alias.c | 45 +++++++++++++++++++++++++++++++++-----------
1 file changed, 34 insertions(+), 11 deletions(-)
diff --git a/libmultipath/alias.c b/libmultipath/alias.c
index 58436ec0..af6565b1 100644
--- a/libmultipath/alias.c
+++ b/libmultipath/alias.c
@@ -117,6 +117,35 @@ static const struct binding *get_binding_for_wwid(const Bindings *bindings,
return NULL;
}
+/*
+ * Sort order for aliases.
+ *
+ * The "numeric" ordering of aliases for a given prefix P is
+ * Pa, ..., Pz, Paa, ..., Paz, Pba, ... , Pzz, Paaa, ..., Pzzz, Paaaa, ...
+ * We use the fact that for equal prefix, longer strings are always
+ * higher than shorter ones. Strings of equal length are sorted alphabetically.
+ * This is achieved by sorting be length first, then using strcmp().
+ * If multiple prefixes are in use, the aliases with a given prefix will
+ * not necessarily be in a contiguous range of the vector, but they will
+ * be ordered such that for a given prefix, numercally higher aliases will
+ * always be sorted after lower ones.
+ */
+static int alias_compar(const void *p1, const void *p2)
+{
+ const char *alias1 = *((char * const *)p1);
+ const char *alias2 = *((char * const *)p2);
+
+ if (alias1 && alias2) {
+ ssize_t ldif = strlen(alias1) - strlen(alias2);
+
+ if (ldif)
+ return ldif;
+ return strcmp(alias1, alias2);
+ } else
+ /* Move NULL alias to the end */
+ return alias1 ? -1 : alias2 ? 1 : 0;
+}
+
static int add_binding(Bindings *bindings, const char *alias, const char *wwid)
{
struct binding *bdg;
@@ -128,7 +157,7 @@ static int add_binding(Bindings *bindings, const char *alias, const char *wwid)
* sorted already.
*/
vector_foreach_slot_backwards(bindings, bdg, i) {
- if ((cmp = strcmp(bdg->alias, alias)) <= 0)
+ if ((cmp = alias_compar(&bdg->alias, &alias)) <= 0)
break;
}
@@ -657,16 +686,10 @@ static int _check_bindings_file(const struct config *conf, FILE *file,
return rc;
}
-static int alias_compar(const void *p1, const void *p2)
+static int mp_alias_compar(const void *p1, const void *p2)
{
- const char *alias1 = (*(struct mpentry * const *)p1)->alias;
- const char *alias2 = (*(struct mpentry * const *)p2)->alias;
-
- if (alias1 && alias2)
- return strcmp(alias1, alias2);
- else
- /* Move NULL alias to the end */
- return alias1 ? -1 : alias2 ? 1 : 0;
+ return alias_compar(&((*(struct mpentry * const *)p1)->alias),
+ &((*(struct mpentry * const *)p2)->alias));
}
/*
@@ -700,7 +723,7 @@ int check_alias_settings(const struct config *conf)
pthread_cleanup_push_cast(free_bindings, &bindings);
pthread_cleanup_push(cleanup_vector_free, mptable);
- vector_sort(mptable, alias_compar);
+ vector_sort(mptable, mp_alias_compar);
vector_foreach_slot(mptable, mpe, i) {
if (!mpe->alias)
/*

View File

@ -0,0 +1,90 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Fri, 8 Sep 2023 15:46:02 +0200
Subject: [PATCH] multipath-tools tests: fix alias test after sort order change
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
tests/alias.c | 30 ++++++++++++------------------
1 file changed, 12 insertions(+), 18 deletions(-)
diff --git a/tests/alias.c b/tests/alias.c
index d1cc487b..8ed95d7a 100644
--- a/tests/alias.c
+++ b/tests/alias.c
@@ -932,16 +932,15 @@ static void lb_nomatch_b_a_aa_zz(void **state)
/*
* add_bindings() sorts alphabetically. ("a", "aa", "ab", "b", "c", ...)
- * lookup_binding finds MPATHaaa as next free entry, because MPATHaa is
- * found before MPATHb, and MPATHzz was in the bindings, too.
+ * lookup_binding finds MPATHab as next free entry.
*/
fill_bindings(&buf, 0, 26);
print_strbuf(&buf, "MPATHzz WWID676\n");
mock_bindings_file(get_strbuf_str(&buf));
expect_condlog(3, NOMATCH_WWID_STR("WWID703"));
- mock_unused_alias("MPATHaaa");
+ mock_unused_alias("MPATHab");
rc = lookup_binding(NULL, "WWID703", &alias, "MPATH", 1);
- assert_int_equal(rc, 703);
+ assert_int_equal(rc, 28);
assert_ptr_equal(alias, NULL);
}
@@ -998,13 +997,8 @@ static void lb_nomatch_b_a_3_used(void **state)
#ifdef MPATH_ID_INT_MAX
/*
- * The bindings will be sorted by alias, alphabetically, which is not
- * the same as the "numeric" sort order for user-friendly aliases.
- * get_free_id() selects the highest used ID + 1 if an unsorted entry
- * is encountered in the bindings table and it's id is equal to the
- * next "expected" id. This happens if all IDs from "a" to "aa" are
- * in the table. If the INT_MAX entry is in the table, too, it will
- * overflow.
+ * The bindings will be sorted by alias. Therefore we have no chance to
+ * simulate a "full" table.
*/
static void lb_nomatch_int_max(void **state)
{
@@ -1016,9 +1010,9 @@ static void lb_nomatch_int_max(void **state)
print_strbuf(&buf, "MPATH%s WWIDMAX\n", MPATH_ID_INT_MAX);
mock_bindings_file(get_strbuf_str(&buf));
expect_condlog(3, NOMATCH_WWID_STR("WWIDNOMORE"));
- expect_condlog(0, NOMORE_STR);
+ mock_unused_alias("MPATHab");
rc = lookup_binding(NULL, "WWIDNOMORE", &alias, "MPATH", 1);
- assert_int_equal(rc, -1);
+ assert_int_equal(rc, 28);
assert_ptr_equal(alias, NULL);
}
@@ -1049,9 +1043,9 @@ static void lb_nomatch_int_max_m1(void **state)
print_strbuf(&buf, "MPATH%s WWIDMAXM1\n", MPATH_ID_INT_MAX_m1);
mock_bindings_file(get_strbuf_str(&buf));
expect_condlog(3, NOMATCH_WWID_STR("WWIDMAX"));
- mock_unused_alias("MPATH" MPATH_ID_INT_MAX);
+ mock_unused_alias("MPATHab");
rc = lookup_binding(NULL, "WWIDMAX", &alias, "MPATH", 1);
- assert_int_equal(rc, INT_MAX);
+ assert_int_equal(rc, 28);
assert_ptr_equal(alias, NULL);
}
@@ -1065,10 +1059,10 @@ static void lb_nomatch_int_max_m1_used(void **state)
print_strbuf(&buf, "MPATH%s WWIDMAXM1\n", MPATH_ID_INT_MAX_m1);
mock_bindings_file(get_strbuf_str(&buf));
expect_condlog(3, NOMATCH_WWID_STR("WWIDMAX"));
- mock_used_alias("MPATH" MPATH_ID_INT_MAX, "WWIDMAX");
- expect_condlog(0, NOMORE_STR);
+ mock_used_alias("MPATHab", "WWIDMAX");
+ mock_unused_alias("MPATHac");
rc = lookup_binding(NULL, "WWIDMAX", &alias, "MPATH", 1);
- assert_int_equal(rc, -1);
+ assert_int_equal(rc, 29);
assert_ptr_equal(alias, NULL);
}

View File

@ -0,0 +1,122 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Fri, 8 Sep 2023 19:50:51 +0200
Subject: [PATCH] libmultipath: simplify get_free_id() assuming total ordering
If we can assume that the bindings array is totally ordered for every
prefix, which the previous patch guarantees, the search for a free ID can be
simplified.
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/alias.c | 85 ++++++++++----------------------------------
1 file changed, 18 insertions(+), 67 deletions(-)
diff --git a/libmultipath/alias.c b/libmultipath/alias.c
index af6565b1..66e34e31 100644
--- a/libmultipath/alias.c
+++ b/libmultipath/alias.c
@@ -356,83 +356,34 @@ int get_free_id(const Bindings *bindings, const char *prefix, const char *map_ww
{
const struct binding *bdg;
int i, id = 1;
- int biggest_id = 1;
- int smallest_bigger_id = INT_MAX;
vector_foreach_slot(bindings, bdg, i) {
int curr_id = scan_devname(bdg->alias, prefix);
- /*
- * Find an unused index - explanation of the algorithm
- *
- * ID: 1 = mpatha, 2 = mpathb, ...
- *
- * We assume the bindings are unsorted. The only constraint
- * is that no ID occurs more than once. IDs that occur in the
- * bindings are called "used".
- *
- * We call the list 1,2,3,..., exactly in this order, the list
- * of "expected" IDs. The variable "id" always holds the next
- * "expected" ID, IOW the last "expected" ID encountered plus 1.
- * Thus all IDs below "id" are known to be used. However, at the
- * end of the loop, the value of "id" isn't necessarily unused.
- *
- * "smallest_bigger_id" is the smallest used ID that was
- * encountered while it was larger than the next "expected" ID
- * at that iteration. Let X be some used ID. If all IDs below X
- * are used and encountered in the right sequence before X, "id"
- * will be > X when the loop ends. Otherwise, X was encountered
- * "out of order", the condition (X > id) holds when X is
- * encountered, and "smallest_bigger_id" will be set to X; i.e.
- * it will be less or equal than X when the loop ends.
- *
- * At the end of the loop, (id < smallest_bigger_id) means that
- * the value of "id" had been encountered neither in order nor
- * out of order, and is thus unused. (id >= smallest_bigger_id)
- * means that "id"'s value is in use. In this case, we play safe
- * and use "biggest_id + 1" as the next value to try.
- *
- * biggest_id is always > smallest_bigger_id, except in the
- * "perfectly ordered" case.
- */
- if (curr_id == id) {
- if (id < INT_MAX)
- id++;
- else {
- id = -1;
- break;
- }
+ if (curr_id == -1)
+ continue;
+ if (id > curr_id) {
+ condlog(0, "%s: ERROR: bindings are not sorted", __func__);
+ return -1;
}
- if (curr_id > biggest_id)
- biggest_id = curr_id;
-
- if (curr_id > id && curr_id < smallest_bigger_id)
- smallest_bigger_id = curr_id;
+ while (id < curr_id && id_already_taken(id, prefix, map_wwid))
+ id++;
+ if (id < curr_id)
+ return id;
+ id++;
+ if (id <= 0)
+ break;
}
- if (id >= smallest_bigger_id)
- id = biggest_id < INT_MAX ? biggest_id + 1 : -1;
-
- if (id > 0) {
- while(id_already_taken(id, prefix, map_wwid)) {
- if (id == INT_MAX) {
- id = -1;
- break;
- }
- id++;
- if (id == smallest_bigger_id) {
- if (biggest_id == INT_MAX) {
- id = -1;
- break;
- }
- if (biggest_id >= smallest_bigger_id)
- id = biggest_id + 1;
- }
- }
+ for (; id > 0; id++) {
+ if (!id_already_taken(id, prefix, map_wwid))
+ break;
}
- if (id < 0)
+ if (id <= 0) {
+ id = -1;
condlog(0, "no more available user_friendly_names");
+ }
return id;
}

View File

@ -0,0 +1,203 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Fri, 8 Sep 2023 19:58:03 +0200
Subject: [PATCH] multipath-tools tests: adapt alias tests for total ordering
The "unsorted" test fail now, and are removed. The algorithm is now
better at finding "gaps".
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
tests/alias.c | 88 ++++++++-------------------------------------------
1 file changed, 14 insertions(+), 74 deletions(-)
diff --git a/tests/alias.c b/tests/alias.c
index 8ed95d7a..dff5f93b 100644
--- a/tests/alias.c
+++ b/tests/alias.c
@@ -439,27 +439,7 @@ static void mock_self_alias(const char *alias, const char *wwid)
expect_condlog(3, USED_STR(alias, wwid)); \
} while(0)
-static int add_binding_unsorted(Bindings *bindings,
- const char *alias, const char *wwid)
-{
- struct binding *bdg = calloc(1, sizeof(*bdg));
-
- if (!bdg)
- return -1;
- bdg->wwid = strdup(wwid);
- bdg->alias = strdup(alias);
- if (!bdg->wwid || !bdg->alias || !vector_alloc_slot(bindings)) {
- free(bdg->alias);
- free(bdg->wwid);
- free(bdg);
- return BINDING_ERROR;
- }
- vector_set_slot(bindings, bdg);
- return BINDING_ADDED;
-}
-
-static void __mock_bindings_file(const char *content,
- int (*add)(Bindings *, const char *, const char *))
+static void __mock_bindings_file(const char *content)
{
char *cnt __attribute__((cleanup(cleanup_charp))) = NULL;
char *token, *savep = NULL;
@@ -478,17 +458,13 @@ static void __mock_bindings_file(const char *content,
== READ_BINDING_SKIP)
continue;
- rc = add(&global_bindings, alias, wwid);
+ rc = add_binding(&global_bindings, alias, wwid);
assert_int_equal(rc, BINDING_ADDED);
}
}
static void mock_bindings_file(const char *content) {
- return __mock_bindings_file(content, add_binding);
-}
-
-static void mock_bindings_file_unsorted(const char *content) {
- return __mock_bindings_file(content, add_binding_unsorted);
+ return __mock_bindings_file(content);
}
static int teardown_bindings(void **state)
@@ -861,10 +837,6 @@ static void lb_nomatch_b_z_a(void **state)
int rc;
char *alias;
- /*
- * add_bindings() sorts alphabetically. Therefore get_free_id()
- * finds MPATHc as a free entry.
- */
mock_bindings_file("MPATHb WWID1\n"
"MPATHz WWID26\n"
"MPATHa WWID0\n");
@@ -880,10 +852,6 @@ static void lb_nomatch_b_aa_a(void **state)
int rc;
char *alias;
- /*
- * add_bindings() sorts alphabetically. ("a", "aa", b").
- * The get_free_id() algorithm finds the "hole" after "b".
- */
mock_bindings_file("MPATHb WWID1\n"
"MPATHz WWID26\n"
"MPATHa WWID0\n");
@@ -911,10 +879,6 @@ static void lb_nomatch_b_a_aa(void **state)
char *alias;
STRBUF_ON_STACK(buf);
- /*
- * add_bindings() sorts alphabetically. ("a", "aa", "ab", "b", "c", ...)
- * lookup_binding finds MPATHac as next free entry.
- */
fill_bindings(&buf, 0, 26);
mock_bindings_file(get_strbuf_str(&buf));
expect_condlog(3, NOMATCH_WWID_STR("WWID28"));
@@ -930,10 +894,6 @@ static void lb_nomatch_b_a_aa_zz(void **state)
char *alias;
STRBUF_ON_STACK(buf);
- /*
- * add_bindings() sorts alphabetically. ("a", "aa", "ab", "b", "c", ...)
- * lookup_binding finds MPATHab as next free entry.
- */
fill_bindings(&buf, 0, 26);
print_strbuf(&buf, "MPATHzz WWID676\n");
mock_bindings_file(get_strbuf_str(&buf));
@@ -944,25 +904,6 @@ static void lb_nomatch_b_a_aa_zz(void **state)
assert_ptr_equal(alias, NULL);
}
-static void lb_nomatch_b_z_a_unsorted(void **state)
-{
- int rc;
- char *alias;
-
- /*
- * With unsorted bindings (shouldn't happen normally), get_free_id()
- * plays safe and returns MPATHaa as first free entry.
- */
- mock_bindings_file_unsorted("MPATHb WWID1\n"
- "MPATHz WWID26\n"
- "MPATHa WWID0\n");
- expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
- mock_unused_alias("MPATHaa");
- rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1);
- assert_int_equal(rc, 27);
- assert_ptr_equal(alias, NULL);
-}
-
static void lb_nomatch_b_a(void **state)
{
int rc;
@@ -1027,9 +968,9 @@ static void lb_nomatch_int_max_used(void **state)
mock_bindings_file(get_strbuf_str(&buf));
expect_condlog(3, NOMATCH_WWID_STR("WWIDNOMORE"));
mock_used_alias("MPATHa", "WWIDNOMORE");
- expect_condlog(0, NOMORE_STR);
+ mock_unused_alias("MPATHab");
rc = lookup_binding(NULL, "WWIDNOMORE", &alias, "MPATH", 1);
- assert_int_equal(rc, -1);
+ assert_int_equal(rc, 28);
assert_ptr_equal(alias, NULL);
}
@@ -1077,9 +1018,9 @@ static void lb_nomatch_int_max_m1_1_used(void **state)
mock_bindings_file(get_strbuf_str(&buf));
expect_condlog(3, NOMATCH_WWID_STR("WWIDMAX"));
mock_used_alias("MPATHa", "WWIDMAX");
- mock_unused_alias("MPATH" MPATH_ID_INT_MAX);
+ mock_unused_alias("MPATHab");
rc = lookup_binding(NULL, "WWIDMAX", &alias, "MPATH", 1);
- assert_int_equal(rc, INT_MAX);
+ assert_int_equal(rc, 28);
assert_ptr_equal(alias, NULL);
}
@@ -1095,10 +1036,10 @@ static void lb_nomatch_int_max_m1_2_used(void **state)
expect_condlog(3, NOMATCH_WWID_STR("WWIDMAX"));
mock_used_alias("MPATHa", "WWIDMAX");
- mock_used_alias("MPATH" MPATH_ID_INT_MAX, "WWIDMAX");
- expect_condlog(0, NOMORE_STR);
+ mock_used_alias("MPATHab", "WWIDMAX");
+ mock_unused_alias("MPATHac");
rc = lookup_binding(NULL, "WWIDMAX", &alias, "MPATH", 1);
- assert_int_equal(rc, -1);
+ assert_int_equal(rc, 29);
assert_ptr_equal(alias, NULL);
}
#endif
@@ -1133,7 +1074,6 @@ static int test_lookup_binding(void)
cmocka_unit_test_teardown(lb_nomatch_b_aa_a, teardown_bindings),
cmocka_unit_test_teardown(lb_nomatch_b_a_aa, teardown_bindings),
cmocka_unit_test_teardown(lb_nomatch_b_a_aa_zz, teardown_bindings),
- cmocka_unit_test_teardown(lb_nomatch_b_z_a_unsorted, teardown_bindings),
cmocka_unit_test_teardown(lb_nomatch_b_a, teardown_bindings),
cmocka_unit_test_teardown(lb_nomatch_b_a_3_used, teardown_bindings),
#ifdef MPATH_ID_INT_MAX
@@ -1593,14 +1533,14 @@ static void gufa_nomatch_b_f_a(void **state) {
"MPATHf WWID6\n"
"MPATHa WWID0\n");
- mock_bindings_file_unsorted(bindings);
+ mock_bindings_file(bindings);
expect_condlog(3, NOMATCH_WWID_STR("WWID7"));
- mock_unused_alias("MPATHg");
+ mock_unused_alias("MPATHc");
- mock_allocate_binding_len("MPATHg", "WWID7", sizeof(bindings) - 1);
+ mock_allocate_binding_len("MPATHc", "WWID7", sizeof(bindings) - 1);
alias = get_user_friendly_alias("WWID7", "x", "", "MPATH", false);
- assert_string_equal(alias, "MPATHg");
+ assert_string_equal(alias, "MPATHc");
free(alias);
}

View File

@ -0,0 +1,275 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Fri, 8 Sep 2023 21:39:44 +0200
Subject: [PATCH] multipath-tools tests: add test for ordering of bindings
As the assignment of free aliases now relies on the bindings being
properly sorted, add some unit tests to make sure the sorting algorithm
works.
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
tests/alias.c | 212 +++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 209 insertions(+), 3 deletions(-)
diff --git a/tests/alias.c b/tests/alias.c
index dff5f93b..7f3ff38a 100644
--- a/tests/alias.c
+++ b/tests/alias.c
@@ -13,6 +13,9 @@
#include "globals.c"
#include "../libmultipath/alias.c"
+/* For verbose printing of all aliases in the ordering tests */
+#define ALIAS_DEBUG 0
+
#if INT_MAX == 0x7fffffff
/* user_friendly_name for map #INT_MAX */
#define MPATH_ID_INT_MAX "fxshrxw"
@@ -439,11 +442,12 @@ static void mock_self_alias(const char *alias, const char *wwid)
expect_condlog(3, USED_STR(alias, wwid)); \
} while(0)
-static void __mock_bindings_file(const char *content)
+static void __mock_bindings_file(const char *content, bool conflict_ok)
{
char *cnt __attribute__((cleanup(cleanup_charp))) = NULL;
char *token, *savep = NULL;
int i;
+ uintmax_t values[] = { BINDING_ADDED, BINDING_CONFLICT };
cnt = strdup(content);
assert_ptr_not_equal(cnt, NULL);
@@ -459,12 +463,12 @@ static void __mock_bindings_file(const char *content)
continue;
rc = add_binding(&global_bindings, alias, wwid);
- assert_int_equal(rc, BINDING_ADDED);
+ assert_in_set(rc, values, conflict_ok ? 2 : 1);
}
}
static void mock_bindings_file(const char *content) {
- return __mock_bindings_file(content);
+ return __mock_bindings_file(content, false);
}
static int teardown_bindings(void **state)
@@ -1744,6 +1748,207 @@ static int test_get_user_friendly_alias()
return cmocka_run_group_tests(tests, NULL, NULL);
}
+/* Numbers 1-1000, randomly shuffled */
+static const int random_numbers[1000] = {
+ 694, 977, 224, 178, 841, 818, 914, 549, 831, 942, 263, 834, 919, 800,
+ 111, 517, 719, 297, 988, 98, 332, 516, 754, 772, 495, 488, 331, 529,
+ 142, 747, 848, 618, 375, 624, 74, 753, 782, 944, 623, 468, 862, 997,
+ 417, 258, 298, 774, 673, 904, 883, 766, 867, 400, 11, 950, 14, 784,
+ 655, 155, 396, 9, 743, 93, 651, 245, 968, 306, 785, 581, 880, 486,
+ 168, 631, 203, 4, 663, 294, 702, 762, 619, 684, 48, 181, 21, 443, 643,
+ 863, 1000, 327, 26, 126, 382, 765, 586, 76, 49, 925, 319, 865, 797,
+ 876, 693, 334, 433, 243, 419, 901, 854, 326, 985, 347, 874, 527, 282,
+ 290, 380, 167, 95, 3, 257, 936, 60, 426, 227, 345, 577, 492, 467, 580,
+ 967, 422, 823, 718, 610, 64, 700, 412, 163, 288, 506, 828, 432, 51,
+ 356, 348, 539, 478, 17, 945, 602, 123, 450, 660, 429, 113, 310, 358,
+ 512, 758, 508, 19, 542, 304, 286, 446, 918, 723, 333, 603, 731, 978,
+ 230, 697, 109, 872, 175, 853, 947, 965, 121, 222, 101, 811, 117, 601,
+ 191, 752, 384, 415, 938, 278, 915, 715, 240, 552, 912, 838, 150, 840,
+ 627, 29, 636, 464, 861, 481, 992, 249, 934, 82, 368, 724, 807, 593,
+ 157, 147, 199, 637, 41, 62, 902, 505, 621, 342, 174, 260, 729, 961,
+ 219, 311, 629, 789, 81, 739, 860, 712, 223, 165, 741, 981, 485, 363,
+ 346, 709, 125, 369, 279, 634, 399, 162, 193, 769, 149, 314, 868, 612,
+ 524, 675, 341, 343, 476, 606, 388, 613, 850, 264, 903, 451, 908, 779,
+ 453, 148, 497, 46, 132, 43, 885, 955, 269, 395, 72, 128, 767, 989,
+ 929, 423, 742, 55, 13, 79, 924, 182, 295, 563, 668, 169, 974, 154,
+ 970, 54, 674, 52, 437, 570, 550, 531, 554, 793, 678, 218, 367, 105,
+ 197, 315, 958, 892, 86, 47, 284, 37, 561, 522, 198, 689, 817, 573,
+ 877, 201, 803, 501, 881, 546, 530, 523, 780, 579, 953, 135, 23, 620,
+ 84, 698, 303, 656, 357, 323, 494, 58, 131, 913, 995, 120, 70, 1, 195,
+ 365, 210, 25, 898, 173, 307, 239, 77, 418, 952, 963, 92, 455, 425, 12,
+ 536, 161, 328, 933, 401, 251, 735, 725, 362, 322, 557, 681, 302, 53,
+ 786, 801, 391, 946, 748, 133, 717, 851, 7, 372, 993, 387, 906, 373,
+ 667, 33, 670, 389, 209, 611, 896, 652, 69, 999, 344, 845, 633, 36,
+ 487, 192, 180, 45, 640, 427, 707, 805, 188, 152, 905, 217, 30, 252,
+ 386, 665, 299, 541, 410, 787, 5, 857, 751, 392, 44, 595, 146, 745,
+ 641, 957, 866, 773, 806, 815, 659, 102, 704, 430, 106, 296, 129, 847,
+ 130, 990, 669, 236, 225, 680, 159, 213, 438, 189, 447, 600, 232, 594,
+ 32, 56, 390, 647, 855, 428, 330, 714, 738, 706, 666, 461, 469, 482,
+ 558, 814, 559, 177, 575, 538, 309, 383, 261, 156, 420, 761, 630, 893,
+ 10, 116, 940, 844, 71, 377, 662, 312, 520, 244, 143, 759, 119, 186,
+ 592, 909, 864, 376, 768, 254, 265, 394, 511, 760, 574, 6, 436, 514,
+ 59, 226, 644, 956, 578, 825, 548, 145, 736, 597, 378, 821, 987, 897,
+ 354, 144, 722, 895, 589, 503, 826, 498, 543, 617, 763, 231, 808, 528,
+ 89, 479, 607, 737, 170, 404, 371, 65, 103, 340, 283, 141, 313, 858,
+ 289, 124, 971, 687, 954, 732, 39, 926, 176, 100, 267, 519, 890, 535,
+ 276, 448, 27, 457, 899, 385, 184, 275, 770, 544, 614, 449, 160, 658,
+ 259, 973, 108, 604, 24, 207, 562, 757, 744, 324, 444, 962, 591, 480,
+ 398, 409, 998, 253, 325, 445, 979, 8, 35, 118, 73, 683, 208, 85, 190,
+ 791, 408, 871, 657, 179, 18, 556, 496, 475, 20, 894, 484, 775, 889,
+ 463, 241, 730, 57, 907, 551, 859, 943, 185, 416, 870, 590, 435, 471,
+ 932, 268, 381, 626, 502, 565, 273, 534, 672, 778, 292, 473, 566, 104,
+ 172, 285, 832, 411, 329, 628, 397, 472, 271, 910, 711, 690, 969, 585,
+ 809, 941, 923, 555, 228, 685, 242, 94, 96, 211, 140, 61, 922, 795,
+ 869, 34, 255, 38, 984, 676, 15, 560, 632, 434, 921, 355, 582, 351,
+ 212, 200, 819, 960, 649, 852, 75, 771, 361, 996, 238, 316, 720, 671,
+ 462, 112, 569, 171, 664, 625, 588, 405, 553, 270, 533, 353, 842, 114,
+ 972, 83, 937, 63, 194, 237, 537, 980, 802, 916, 959, 688, 839, 350,
+ 917, 650, 545, 615, 151, 352, 686, 726, 266, 509, 439, 491, 935, 608,
+ 518, 653, 339, 609, 277, 635, 836, 88, 407, 440, 642, 927, 229, 727,
+ 360, 477, 846, 413, 454, 616, 28, 598, 567, 540, 790, 424, 247, 317,
+ 746, 911, 798, 321, 547, 248, 734, 829, 220, 138, 756, 500, 691, 196,
+ 740, 930, 843, 733, 221, 827, 50, 813, 949, 525, 349, 474, 134, 875,
+ 695, 513, 414, 515, 638, 99, 366, 490, 975, 246, 465, 206, 281, 583,
+ 256, 587, 749, 2, 951, 679, 215, 364, 458, 402, 646, 991, 335, 982,
+ 835, 300, 900, 703, 994, 983, 234, 888, 532, 804, 584, 305, 792, 442,
+ 291, 964, 158, 370, 452, 250, 521, 166, 948, 812, 794, 272, 699, 205,
+ 183, 507, 301, 920, 781, 233, 824, 137, 489, 833, 887, 966, 856, 78,
+ 830, 153, 359, 696, 526, 216, 66, 701, 403, 891, 849, 571, 308, 483,
+ 164, 293, 928, 677, 320, 837, 441, 639, 564, 510, 648, 274, 336, 661,
+ 878, 777, 816, 976, 493, 810, 67, 87, 91, 187, 882, 986, 80, 22, 499,
+ 90, 705, 139, 136, 122, 708, 716, 886, 572, 127, 40, 721, 764, 16,
+ 379, 692, 645, 456, 710, 460, 783, 97, 776, 713, 884, 115, 466, 596,
+ 374, 406, 110, 568, 68, 214, 622, 470, 107, 504, 682, 31, 421, 576,
+ 654, 605, 788, 799, 280, 338, 931, 873, 204, 287, 459, 755, 939, 599,
+ 431, 796, 235, 42, 750, 262, 318, 393, 202, 822, 879, 820, 728, 337,
+};
+
+static void fill_bindings_random(struct strbuf *buf, int start, int end,
+ const char *prefix)
+{
+ int i;
+
+ for (i = start; i < end; i++) {
+ print_strbuf(buf, "%s", prefix);
+ format_devname(buf, random_numbers[i]);
+ print_strbuf(buf, " WWID%d\n", random_numbers[i]);
+ }
+}
+
+struct random_aliases {
+ int start;
+ int end;
+ const char *prefix;
+};
+
+static void order_test(int n, const struct random_aliases ra[], bool conflict_ok)
+{
+ STRBUF_ON_STACK(buf);
+ int i, j, prev, curr, tmp;
+ struct binding *bdg;
+ Bindings *bindings = &global_bindings;
+
+ for (j = 0; j < n; j++)
+ fill_bindings_random(&buf, ra[j].start, ra[j].end, ra[j].prefix);
+ __mock_bindings_file(get_strbuf_str(&buf), conflict_ok);
+
+ for (j = 0; j < n; j++) {
+ bdg = VECTOR_SLOT(bindings, 0);
+ if (ALIAS_DEBUG && j == 0)
+ printf("%d: %s\n", 0, bdg->alias);
+ prev = scan_devname(bdg->alias, ra[j].prefix);
+ i = 1;
+ vector_foreach_slot_after(bindings, bdg, i) {
+ if (ALIAS_DEBUG && j == 0)
+ printf("%d: %s\n", i, bdg->alias);
+ tmp = scan_devname(bdg->alias, ra[j].prefix);
+ if (tmp == -1)
+ continue;
+ curr = tmp;
+ if (prev > 0) {
+ if (curr <= prev)
+ printf("ERROR: %d (%s) %d >= %d\n",
+ i, bdg->alias, prev, curr);
+ assert_true(curr > prev);
+ }
+ prev = curr;
+ }
+ }
+}
+
+static void order_01(void **state)
+{
+ const struct random_aliases ra[] = {
+ { 0, 1000, "MPATH" },
+ };
+
+ order_test(ARRAY_SIZE(ra), ra, false);
+}
+
+static void order_02(void **state)
+{
+ const struct random_aliases ra[] = {
+ { 0, 500, "MPATH" },
+ { 200, 700, "mpath" },
+ };
+ order_test(ARRAY_SIZE(ra), ra, false);
+}
+
+static void order_03(void **state)
+{
+ const struct random_aliases ra[] = {
+ { 500, 1000, "MPTH" },
+ { 0, 500, "MPATH" },
+ };
+ order_test(ARRAY_SIZE(ra), ra, false);
+}
+
+static void order_04(void **state)
+{
+ const struct random_aliases ra[] = {
+ { 0, 500, "mpa" },
+ { 250, 750, "mp" },
+ };
+ order_test(ARRAY_SIZE(ra), ra, true);
+}
+
+static void order_05(void **state)
+{
+ const struct random_aliases ra[] = {
+ { 0, 100, "A" },
+ { 0, 100, "B" },
+ { 0, 100, "C" },
+ { 0, 100, "D" },
+ };
+ order_test(ARRAY_SIZE(ra), ra, false);
+}
+
+static void order_06(void **state)
+{
+ const struct random_aliases ra[] = {
+ { 0, 100, "" },
+ { 0, 100, "a" },
+ { 0, 100, "aa" },
+ { 0, 100, "ab" },
+ { 0, 100, "aaa" },
+ };
+ order_test(ARRAY_SIZE(ra), ra, true);
+}
+
+static int test_bindings_order()
+{
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test_teardown(order_01, teardown_bindings),
+ cmocka_unit_test_teardown(order_02, teardown_bindings),
+ cmocka_unit_test_teardown(order_03, teardown_bindings),
+ cmocka_unit_test_teardown(order_04, teardown_bindings),
+ cmocka_unit_test_teardown(order_05, teardown_bindings),
+ cmocka_unit_test_teardown(order_06, teardown_bindings),
+ };
+
+ return cmocka_run_group_tests(tests, NULL, NULL);
+}
+
int main(void)
{
int ret = 0;
@@ -1755,6 +1960,7 @@ int main(void)
ret += test_rlookup_binding();
ret += test_allocate_binding();
ret += test_get_user_friendly_alias();
+ ret += test_bindings_order();
return ret;
}

View File

@ -0,0 +1,597 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Thu, 7 Sep 2023 22:22:43 +0200
Subject: [PATCH] multipathd: watch bindings file with inotify + timestamp
Since "libmultipath: keep bindings in memory", we don't re-read the
bindings file after every modification. Add a notification mechanism
that makes multipathd aware of changes to the bindings file. Because
multipathd itself will change the bindings file, it must compare
timestamps in order to avoid reading the file repeatedly.
Because select_alias() can be called from multiple thread contexts (uxlsnr,
uevent handler), we need to add locking for the bindings file. The
timestamp must also be protected by a lock, because it can't be read
or written atomically.
Note: The notification mechanism expects the bindings file to be
atomically replaced by rename(2). Changes must be made in a temporary file and
applied using rename(2), as in update_bindings_file(). The inotify
mechanism deliberately does not listen to close-after-write events
that would be generated by editing the bindings file directly. This
Note also: new bindings will only be read from add_map_with_path(),
i.e. either during reconfigure(), or when a new map is created during
runtime. Existing maps will not be renamed if the binding file changes,
unless the user runs "multipathd reconfigure". This is not a change
wrt the previous code, but it should be mentioned anyway.
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/alias.c | 256 +++++++++++++++++++++++++-----
libmultipath/alias.h | 3 +-
libmultipath/libmultipath.version | 5 +
multipathd/uxlsnr.c | 36 ++++-
tests/alias.c | 3 +
5 files changed, 256 insertions(+), 47 deletions(-)
diff --git a/libmultipath/alias.c b/libmultipath/alias.c
index 66e34e31..964b8a7b 100644
--- a/libmultipath/alias.c
+++ b/libmultipath/alias.c
@@ -10,6 +10,7 @@
#include <stdio.h>
#include <stdbool.h>
#include <assert.h>
+#include <sys/inotify.h>
#include "debug.h"
#include "util.h"
@@ -22,6 +23,7 @@
#include "config.h"
#include "devmapper.h"
#include "strbuf.h"
+#include "time-util.h"
/*
* significant parts of this file were taken from iscsi-bindings.c of the
@@ -50,6 +52,12 @@
"# alias wwid\n" \
"#\n"
+/* uatomic access only */
+static int bindings_file_changed = 1;
+
+static pthread_mutex_t timestamp_mutex = PTHREAD_MUTEX_INITIALIZER;
+static struct timespec bindings_last_updated;
+
struct binding {
char *alias;
char *wwid;
@@ -60,6 +68,9 @@ struct binding {
* an abstract type.
*/
typedef struct _vector Bindings;
+
+/* Protect global_bindings */
+static pthread_mutex_t bindings_mutex = PTHREAD_MUTEX_INITIALIZER;
static Bindings global_bindings = { .allocated = 0 };
enum {
@@ -78,6 +89,27 @@ static void _free_binding(struct binding *bdg)
free(bdg);
}
+static void free_bindings(Bindings *bindings)
+{
+ struct binding *bdg;
+ int i;
+
+ vector_foreach_slot(bindings, bdg, i)
+ _free_binding(bdg);
+ vector_reset(bindings);
+}
+
+static void set_global_bindings(Bindings *bindings)
+{
+ Bindings old_bindings;
+
+ pthread_mutex_lock(&bindings_mutex);
+ old_bindings = global_bindings;
+ global_bindings = *bindings;
+ pthread_mutex_unlock(&bindings_mutex);
+ free_bindings(&old_bindings);
+}
+
static const struct binding *get_binding_for_alias(const Bindings *bindings,
const char *alias)
{
@@ -199,7 +231,8 @@ static int delete_binding(Bindings *bindings, const char *wwid)
return BINDING_DELETED;
}
-static int write_bindings_file(const Bindings *bindings, int fd)
+static int write_bindings_file(const Bindings *bindings, int fd,
+ struct timespec *ts)
{
struct binding *bnd;
STRBUF_ON_STACK(content);
@@ -227,9 +260,56 @@ static int write_bindings_file(const Bindings *bindings, int fd)
}
len -= n;
}
+ fsync(fd);
+ if (ts) {
+ struct stat st;
+
+ if (fstat(fd, &st) == 0)
+ *ts = st.st_mtim;
+ else
+ clock_gettime(CLOCK_REALTIME_COARSE, ts);
+ }
return 0;
}
+void handle_bindings_file_inotify(const struct inotify_event *event)
+{
+ struct config *conf;
+ const char *base;
+ bool changed = false;
+ struct stat st;
+ struct timespec ts = { 0, 0 };
+ int ret;
+
+ if (!(event->mask & IN_MOVED_TO))
+ return;
+
+ conf = get_multipath_config();
+ base = strrchr(conf->bindings_file, '/');
+ changed = base && base > conf->bindings_file &&
+ !strcmp(base + 1, event->name);
+ ret = stat(conf->bindings_file, &st);
+ put_multipath_config(conf);
+
+ if (!changed)
+ return;
+
+ pthread_mutex_lock(&timestamp_mutex);
+ if (ret == 0) {
+ ts = st.st_mtim;
+ changed = timespeccmp(&ts, &bindings_last_updated) > 0;
+ }
+ pthread_mutex_unlock(&timestamp_mutex);
+
+ if (changed) {
+ uatomic_xchg(&bindings_file_changed, 1);
+ condlog(3, "%s: bindings file must be re-read, new timestamp: %ld.%06ld",
+ __func__, (long)ts.tv_sec, (long)ts.tv_nsec / 1000);
+ } else
+ condlog(3, "%s: bindings file is up-to-date, timestamp: %ld.%06ld",
+ __func__, (long)ts.tv_sec, (long)ts.tv_nsec / 1000);
+}
+
static int update_bindings_file(const Bindings *bindings,
const char *bindings_file)
{
@@ -237,6 +317,7 @@ static int update_bindings_file(const Bindings *bindings,
int fd = -1;
char tempname[PATH_MAX];
mode_t old_umask;
+ struct timespec ts;
if (safe_sprintf(tempname, "%s.XXXXXX", bindings_file))
return -1;
@@ -248,7 +329,7 @@ static int update_bindings_file(const Bindings *bindings,
}
umask(old_umask);
pthread_cleanup_push(cleanup_fd_ptr, &fd);
- rc = write_bindings_file(bindings, fd);
+ rc = write_bindings_file(bindings, fd, &ts);
pthread_cleanup_pop(1);
if (rc == -1) {
condlog(1, "failed to write new bindings file");
@@ -257,8 +338,12 @@ static int update_bindings_file(const Bindings *bindings,
}
if ((rc = rename(tempname, bindings_file)) == -1)
condlog(0, "%s: rename: %m", __func__);
- else
+ else {
+ pthread_mutex_lock(&timestamp_mutex);
+ bindings_last_updated = ts;
+ pthread_mutex_unlock(&timestamp_mutex);
condlog(1, "updated bindings file %s", bindings_file);
+ }
return rc;
}
@@ -387,6 +472,7 @@ int get_free_id(const Bindings *bindings, const char *prefix, const char *map_ww
return id;
}
+/* Called with binding_mutex held */
static char *
allocate_binding(const char *filename, const char *wwid, int id, const char *prefix)
{
@@ -423,6 +509,30 @@ allocate_binding(const char *filename, const char *wwid, int id, const char *pre
return alias;
}
+enum {
+ BINDINGS_FILE_UP2DATE,
+ BINDINGS_FILE_READ,
+ BINDINGS_FILE_ERROR,
+ BINDINGS_FILE_BAD,
+};
+
+static int _read_bindings_file(const struct config *conf, Bindings *bindings,
+ bool force);
+
+static void read_bindings_file(void)
+{
+ struct config *conf;
+ Bindings bindings = {.allocated = 0, };
+ int rc;
+
+ conf = get_multipath_config();
+ pthread_cleanup_push(put_multipath_config, conf);
+ rc = _read_bindings_file(conf, &bindings, false);
+ pthread_cleanup_pop(1);
+ if (rc == BINDINGS_FILE_READ)
+ set_global_bindings(&bindings);
+}
+
/*
* get_user_friendly_alias() action table
*
@@ -463,6 +573,11 @@ char *get_user_friendly_alias(const char *wwid, const char *file, const char *al
bool new_binding = false;
const struct binding *bdg;
+ read_bindings_file();
+
+ pthread_mutex_lock(&bindings_mutex);
+ pthread_cleanup_push(cleanup_mutex, &bindings_mutex);
+
if (!*alias_old)
goto new_alias;
@@ -514,40 +629,40 @@ new_alias:
alias, wwid);
out:
+ /* unlock bindings_mutex */
+ pthread_cleanup_pop(1);
return alias;
}
int get_user_friendly_wwid(const char *alias, char *buff)
{
const struct binding *bdg;
+ int rc = -1;
if (!alias || *alias == '\0') {
condlog(3, "Cannot find binding for empty alias");
return -1;
}
+ read_bindings_file();
+
+ pthread_mutex_lock(&bindings_mutex);
+ pthread_cleanup_push(cleanup_mutex, &bindings_mutex);
bdg = get_binding_for_alias(&global_bindings, alias);
- if (!bdg) {
+ if (bdg) {
+ strlcpy(buff, bdg->wwid, WWID_SIZE);
+ rc = 0;
+ } else
*buff = '\0';
- return -1;
- }
- strlcpy(buff, bdg->wwid, WWID_SIZE);
- return 0;
-}
-
-static void free_bindings(Bindings *bindings)
-{
- struct binding *bdg;
- int i;
-
- vector_foreach_slot(bindings, bdg, i)
- _free_binding(bdg);
- vector_reset(bindings);
+ pthread_cleanup_pop(1);
+ return rc;
}
void cleanup_bindings(void)
{
+ pthread_mutex_lock(&bindings_mutex);
free_bindings(&global_bindings);
+ pthread_mutex_unlock(&bindings_mutex);
}
enum {
@@ -595,7 +710,20 @@ static int _check_bindings_file(const struct config *conf, FILE *file,
char *line = NULL;
size_t line_len = 0;
ssize_t n;
-
+ char header[sizeof(BINDINGS_FILE_HEADER)];
+
+ header[sizeof(BINDINGS_FILE_HEADER) - 1] = '\0';
+ if (fread(header, sizeof(BINDINGS_FILE_HEADER) - 1, 1, file) < 1) {
+ condlog(2, "%s: failed to read header from %s", __func__,
+ conf->bindings_file);
+ fseek(file, 0, SEEK_SET);
+ rc = -1;
+ } else if (strcmp(header, BINDINGS_FILE_HEADER)) {
+ condlog(2, "%s: invalid header in %s", __func__,
+ conf->bindings_file);
+ fseek(file, 0, SEEK_SET);
+ rc = -1;
+ }
pthread_cleanup_push(cleanup_free_ptr, &line);
while ((n = getline(&line, &line_len, file)) >= 0) {
char *alias, *wwid;
@@ -643,6 +771,68 @@ static int mp_alias_compar(const void *p1, const void *p2)
&((*(struct mpentry * const *)p2)->alias));
}
+static int _read_bindings_file(const struct config *conf, Bindings *bindings,
+ bool force)
+{
+ int can_write;
+ int rc = 0, ret, fd;
+ FILE *file;
+ struct stat st;
+ int has_changed = uatomic_xchg(&bindings_file_changed, 0);
+
+ if (!force) {
+ if (!has_changed) {
+ condlog(4, "%s: bindings are unchanged", __func__);
+ return BINDINGS_FILE_UP2DATE;
+ }
+ }
+
+ fd = open_file(conf->bindings_file, &can_write, BINDINGS_FILE_HEADER);
+ if (fd == -1)
+ return BINDINGS_FILE_ERROR;
+
+ file = fdopen(fd, "r");
+ if (file != NULL) {
+ condlog(3, "%s: reading %s", __func__, conf->bindings_file);
+
+ pthread_cleanup_push(cleanup_fclose, file);
+ ret = _check_bindings_file(conf, file, bindings);
+ if (ret == 0) {
+ struct timespec ts;
+
+ rc = BINDINGS_FILE_READ;
+ ret = fstat(fd, &st);
+ if (ret == 0)
+ ts = st.st_mtim;
+ else {
+ condlog(1, "%s: fstat failed (%m), using current time", __func__);
+ clock_gettime(CLOCK_REALTIME_COARSE, &ts);
+ }
+ pthread_mutex_lock(&timestamp_mutex);
+ bindings_last_updated = ts;
+ pthread_mutex_unlock(&timestamp_mutex);
+ } else if (ret == -1 && can_write && !conf->bindings_read_only) {
+ ret = update_bindings_file(bindings, conf->bindings_file);
+ if (ret == 0)
+ rc = BINDINGS_FILE_READ;
+ else
+ rc = BINDINGS_FILE_BAD;
+ } else {
+ condlog(0, "ERROR: bad settings in read-only bindings file %s",
+ conf->bindings_file);
+ rc = BINDINGS_FILE_BAD;
+ }
+ pthread_cleanup_pop(1);
+ } else {
+ condlog(1, "failed to fdopen %s: %m",
+ conf->bindings_file);
+ close(fd);
+ rc = BINDINGS_FILE_ERROR;
+ }
+
+ return rc;
+}
+
/*
* check_alias_settings(): test for inconsistent alias configuration
*
@@ -661,8 +851,7 @@ static int mp_alias_compar(const void *p1, const void *p2)
*/
int check_alias_settings(const struct config *conf)
{
- int can_write;
- int rc = 0, i, fd;
+ int i, rc;
Bindings bindings = {.allocated = 0, };
vector mptable = NULL;
struct mpentry *mpe;
@@ -695,27 +884,12 @@ int check_alias_settings(const struct config *conf)
pthread_cleanup_pop(1);
pthread_cleanup_pop(1);
- fd = open_file(conf->bindings_file, &can_write, BINDINGS_FILE_HEADER);
- if (fd != -1) {
- FILE *file = fdopen(fd, "r");
-
- if (file != NULL) {
- pthread_cleanup_push(cleanup_fclose, file);
- rc = _check_bindings_file(conf, file, &bindings);
- pthread_cleanup_pop(1);
- if (rc == -1 && can_write && !conf->bindings_read_only)
- rc = update_bindings_file(&bindings, conf->bindings_file);
- else if (rc == -1)
- condlog(0, "ERROR: bad settings in read-only bindings file %s",
- conf->bindings_file);
- } else {
- condlog(1, "failed to fdopen %s: %m",
- conf->bindings_file);
- close(fd);
- }
+ rc = _read_bindings_file(conf, &bindings, true);
+
+ if (rc == BINDINGS_FILE_READ) {
+ set_global_bindings(&bindings);
+ rc = 0;
}
- cleanup_bindings();
- global_bindings = bindings;
return rc;
}
diff --git a/libmultipath/alias.h b/libmultipath/alias.h
index 5ef6720b..ca8911f4 100644
--- a/libmultipath/alias.h
+++ b/libmultipath/alias.h
@@ -10,5 +10,6 @@ char *get_user_friendly_alias(const char *wwid, const char *file,
struct config;
int check_alias_settings(const struct config *);
void cleanup_bindings(void);
-
+struct inotify_event;
+void handle_bindings_file_inotify(const struct inotify_event *event);
#endif /* _ALIAS_H */
diff --git a/libmultipath/libmultipath.version b/libmultipath/libmultipath.version
index ddd302f5..57e50c12 100644
--- a/libmultipath/libmultipath.version
+++ b/libmultipath/libmultipath.version
@@ -238,3 +238,8 @@ global:
local:
*;
};
+
+LIBMULTIPATH_20.1.0 {
+global:
+ handle_bindings_file_inotify;
+};
diff --git a/multipathd/uxlsnr.c b/multipathd/uxlsnr.c
index 02e89fb4..d1f8f234 100644
--- a/multipathd/uxlsnr.c
+++ b/multipathd/uxlsnr.c
@@ -41,6 +41,7 @@
#include "cli.h"
#include "uxlsnr.h"
#include "strbuf.h"
+#include "alias.h"
/* state of client connection */
enum {
@@ -190,6 +191,7 @@ void wakeup_cleanup(void *arg)
struct watch_descriptors {
int conf_wd;
int dir_wd;
+ int mp_wd; /* /etc/multipath; for bindings file */
};
/* failing to set the watch descriptor is o.k. we just miss a warning
@@ -200,6 +202,8 @@ static void reset_watch(int notify_fd, struct watch_descriptors *wds,
struct config *conf;
int dir_reset = 0;
int conf_reset = 0;
+ int mp_reset = 0;
+ char *bindings_file __attribute__((cleanup(cleanup_charp))) = NULL;
if (notify_fd == -1)
return;
@@ -214,7 +218,10 @@ static void reset_watch(int notify_fd, struct watch_descriptors *wds,
conf_reset = 1;
if (wds->dir_wd == -1)
dir_reset = 1;
+ if (wds->mp_wd == -1)
+ mp_reset = 1;
}
+ bindings_file = strdup(conf->bindings_file);
put_multipath_config(conf);
if (dir_reset) {
@@ -235,7 +242,18 @@ static void reset_watch(int notify_fd, struct watch_descriptors *wds,
if (wds->conf_wd == -1)
condlog(3, "didn't set up notifications on /etc/multipath.conf: %m");
}
- return;
+ if (mp_reset && bindings_file) {
+ char *slash = strrchr(bindings_file, '/');
+
+ if (slash && slash > bindings_file) {
+ *slash = '\0';
+ wds->mp_wd = inotify_add_watch(notify_fd, bindings_file,
+ IN_MOVED_TO|IN_ONLYDIR);
+ if (wds->mp_wd == -1)
+ condlog(3, "didn't set up notifications on %s: %m",
+ bindings_file);
+ }
+ }
}
static void handle_inotify(int fd, struct watch_descriptors *wds)
@@ -256,12 +274,13 @@ static void handle_inotify(int fd, struct watch_descriptors *wds)
inotify_rm_watch(fd, wds->conf_wd);
if (wds->dir_wd != -1)
inotify_rm_watch(fd, wds->dir_wd);
- wds->conf_wd = wds->dir_wd = -1;
+ if (wds->mp_wd != -1)
+ inotify_rm_watch(fd, wds->mp_wd);
+ wds->conf_wd = wds->dir_wd = wds->mp_wd = -1;
}
break;
}
- got_notify = 1;
for (ptr = buff; ptr < buff + len;
ptr += sizeof(struct inotify_event) + event->len) {
event = (const struct inotify_event *) ptr;
@@ -273,7 +292,13 @@ static void handle_inotify(int fd, struct watch_descriptors *wds)
wds->conf_wd = inotify_add_watch(notify_fd, DEFAULT_CONFIGFILE, IN_CLOSE_WRITE);
else if (wds->dir_wd == event->wd)
wds->dir_wd = -1;
+ else if (wds->mp_wd == event->wd)
+ wds->mp_wd = -1;
}
+ if (wds->mp_wd != -1 && wds->mp_wd == event->wd)
+ handle_bindings_file_inotify(event);
+ else
+ got_notify = 1;
}
}
if (got_notify)
@@ -599,7 +624,7 @@ void *uxsock_listen(long ux_sock, void *trigger_data)
int max_pfds = MIN_POLLS + POLLFDS_BASE;
/* conf->sequence_nr will be 1 when uxsock_listen is first called */
unsigned int sequence_nr = 0;
- struct watch_descriptors wds = { .conf_wd = -1, .dir_wd = -1 };
+ struct watch_descriptors wds = { .conf_wd = -1, .dir_wd = -1, .mp_wd = -1, };
struct vectors *vecs = trigger_data;
condlog(3, "uxsock: startup listener");
@@ -666,7 +691,8 @@ void *uxsock_listen(long ux_sock, void *trigger_data)
reset_watch(notify_fd, &wds, &sequence_nr);
polls[POLLFD_NOTIFY].fd = notify_fd;
- if (notify_fd == -1 || (wds.conf_wd == -1 && wds.dir_wd == -1))
+ if (notify_fd == -1 || (wds.conf_wd == -1 && wds.dir_wd == -1
+ && wds.mp_wd == -1))
polls[POLLFD_NOTIFY].events = 0;
else
polls[POLLFD_NOTIFY].events = POLLIN;
diff --git a/tests/alias.c b/tests/alias.c
index 7f3ff38a..9ae27567 100644
--- a/tests/alias.c
+++ b/tests/alias.c
@@ -1954,6 +1954,9 @@ int main(void)
int ret = 0;
init_test_verbosity(3);
+ /* avoid open_file() call in _read_bindings_file */
+ bindings_file_changed = 0;
+
ret += test_format_devname();
ret += test_scan_devname();
ret += test_lookup_binding();

View File

@ -0,0 +1,102 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Fri, 8 Sep 2023 19:54:07 +0200
Subject: [PATCH] multipath-tools tests: mock pthread_mutex_{lock,unlock}
If some test fails with a lock held, cmocka doesn't deal well with
pthread_cleanup_pop(). Such tests can cause deadlock with the locking
primitives in the alias code, because locks don't get properly unlocked. Just
mock the lock/unlock functions and generate an error if they weren't paired at
the end of the test.
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
tests/Makefile | 1 +
tests/alias.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 47 insertions(+)
diff --git a/tests/Makefile b/tests/Makefile
index c777d07a..7dac8a8f 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -52,6 +52,7 @@ blacklist-test_LIBDEPS := -ludev
vpd-test_OBJDEPS := $(multipathdir)/discovery.o
vpd-test_LIBDEPS := -ludev -lpthread -ldl
alias-test_TESTDEPS := test-log.o
+alias-test_OBJDEPS := $(mpathutildir)/util.o
alias-test_LIBDEPS := -lpthread -ldl
valid-test_OBJDEPS := $(multipathdir)/valid.o $(multipathdir)/discovery.o
valid-test_LIBDEPS := -lmount -ludev -lpthread -ldl
diff --git a/tests/alias.c b/tests/alias.c
index 9ae27567..94df36d8 100644
--- a/tests/alias.c
+++ b/tests/alias.c
@@ -89,6 +89,47 @@ int __wrap_dm_get_uuid(const char *name, char *uuid, int uuid_len)
return ret;
}
+static int lock_errors;
+static int bindings_locked;
+static int timestamp_locked;
+int __wrap_pthread_mutex_lock(pthread_mutex_t *mutex)
+{
+ if (mutex == &bindings_mutex) {
+ if (bindings_locked) {
+ fprintf(stderr, "%s: bindings_mutex LOCKED\n", __func__);
+ lock_errors++;
+ }
+ bindings_locked = 1;
+ } else if (mutex == &timestamp_mutex) {
+ if (timestamp_locked) {
+ fprintf(stderr, "%s: timestamp_mutex LOCKED\n", __func__);
+ lock_errors++;
+ }
+ timestamp_locked = 1;
+ } else
+ fprintf(stderr, "%s called for unknown mutex %p\n", __func__, mutex);
+ return 0;
+}
+
+int __wrap_pthread_mutex_unlock(pthread_mutex_t *mutex)
+{
+ if (mutex == &bindings_mutex) {
+ if (!bindings_locked) {
+ fprintf(stderr, "%s: bindings_mutex UNLOCKED\n", __func__);
+ lock_errors++;
+ }
+ bindings_locked = 0;
+ } else if (mutex == &timestamp_mutex) {
+ if (!timestamp_locked) {
+ fprintf(stderr, "%s: timestamp_mutex UNLOCKED\n", __func__);
+ lock_errors++;
+ }
+ timestamp_locked = 0;
+ } else
+ fprintf(stderr, "%s called for unknown mutex %p\n", __func__, mutex);
+ return 0;
+}
+
#define TEST_FDNO 1234
#define TEST_FPTR ((FILE *) 0xaffe)
@@ -1718,6 +1759,10 @@ static void gufa_old_nomatch_nowwidmatch(void **state) {
free(alias);
}
+static void gufa_check_locking(void **state) {
+ assert_int_equal(lock_errors, 0);
+}
+
static int test_get_user_friendly_alias()
{
const struct CMUnitTest tests[] = {
@@ -1743,6 +1788,7 @@ static int test_get_user_friendly_alias()
cmocka_unit_test_teardown(gufa_old_nomatch_wwidmatch, teardown_bindings),
cmocka_unit_test_teardown(gufa_old_nomatch_wwidmatch_used, teardown_bindings),
cmocka_unit_test_teardown(gufa_old_nomatch_nowwidmatch, teardown_bindings),
+ cmocka_unit_test(gufa_check_locking),
};
return cmocka_run_group_tests(tests, NULL, NULL);

View File

@ -0,0 +1,73 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Fri, 8 Sep 2023 22:13:51 +0200
Subject: [PATCH] multipath-tools Makefile: sanitize paths for configuration
files
Make the path to multipath.conf configurable, and use the same prefix
by default for multipath.conf and multipath/conf.d. For "usr-merged"
distributions with immutable /usr, we'll want to have the configuration
under a different prefix. This can be achieved by using e.g.
make prefix=/usr etc_prefix=""
Note that with prefix=/usr, before this patch the code would use
/usr/etc/multipath/conf.d, but /etc/multipath.conf. If this (rather
inconsistent) behavior is desired, use the following command line:
make prefix=/usr configfile=/etc/multipath.conf
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
Makefile.inc | 9 ++++++---
libmultipath/defaults.h | 1 -
2 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/Makefile.inc b/Makefile.inc
index 502cd0f1..39972d93 100644
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -37,6 +37,8 @@ prefix :=
exec_prefix := $(prefix)
# Prefix for non-essential libraries (libdmmp)
usr_prefix := $(prefix)
+# Prefix for configfuration files (multipath.conf)
+etc_prefix := $(prefix)
# Where to install systemd-related files. systemd is usually installed under /usr
# Note: some systemd installations use separate "prefix" and "rootprefix".
# In this case, override only unitdir to use systemd's "rootprefix" instead of $(systemd_prefix)
@@ -54,7 +56,8 @@ usrlibdir := $(usr_prefix)/$(LIB)
includedir := $(usr_prefix)/include
pkgconfdir := $(usrlibdir)/pkgconfig
plugindir := $(prefix)/$(LIB)/multipath
-configdir := $(prefix)/etc/multipath/conf.d
+configdir := $(etc_prefix)/etc/multipath/conf.d
+configfile := $(etc_prefix)/etc/multipath.conf
runtimedir := $(if $(shell test -L /var/run -o ! -d /var/run && echo 1),/run,/var/run)
devmapper_incdir := $(or $(shell $(PKG_CONFIG) --variable=includedir devmapper),/usr/include)
libudev_incdir := $(or $(shell $(PKG_CONFIG) --variable=includedir libudev),/usr/include)
@@ -84,8 +87,8 @@ WARNFLAGS := -Werror -Wall -Wextra -Wformat=2 $(WFORMATOVERFLOW) -Werror=implici
$(WNOCLOBBERED) -Werror=cast-qual $(ERROR_DISCARDED_QUALIFIERS) $(W_URCU_TYPE_LIMITS)
CPPFLAGS := $(FORTIFY_OPT) $(CPPFLAGS) \
-DBIN_DIR=\"$(bindir)\" -DMULTIPATH_DIR=\"$(plugindir)\" \
- -DRUNTIME_DIR=\"$(runtimedir)\" \
- -DCONFIG_DIR=\"$(configdir)\" -DEXTRAVERSION=\"$(EXTRAVERSION)\" -MMD -MP
+ -DRUNTIME_DIR=\"$(runtimedir)\" -DCONFIG_DIR=\"$(configdir)\" \
+ -DDEFAULT_CONFIGFILE=\"$(configfile)\" -DEXTRAVERSION=\"$(EXTRAVERSION)\" -MMD -MP
CFLAGS := --std=gnu99 $(CFLAGS) $(OPTFLAGS) $(WARNFLAGS) -pipe
BIN_CFLAGS := -fPIE -DPIE
LIB_CFLAGS := -fPIC
diff --git a/libmultipath/defaults.h b/libmultipath/defaults.h
index b3f11d4c..bc2d6388 100644
--- a/libmultipath/defaults.h
+++ b/libmultipath/defaults.h
@@ -66,7 +66,6 @@
#define MAX_DEV_LOSS_TMO UINT_MAX
#define DEFAULT_PIDFILE RUNTIME_DIR "/multipathd.pid"
#define DEFAULT_SOCKET "/org/kernel/linux/storage/multipathd"
-#define DEFAULT_CONFIGFILE "/etc/multipath.conf"
#define DEFAULT_BINDINGS_FILE "/etc/multipath/bindings"
#define DEFAULT_WWIDS_FILE "/etc/multipath/wwids"
#define DEFAULT_PRKEYS_FILE "/etc/multipath/prkeys"

View File

@ -0,0 +1,58 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Fri, 8 Sep 2023 22:26:22 +0200
Subject: [PATCH] multipath-tools: add compile time configuration for
"/etc/multipath"
Instead of hard-conding "/etc/multipath" as the path for the state
files "bindings", "prkeys", and "wwids", make this path configurable
via the "statedir" compile-time option. The default is currently still
/etc, it might change to /var/lib or similar in the future.
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
Makefile.inc | 4 +++-
libmultipath/defaults.h | 6 +++---
2 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/Makefile.inc b/Makefile.inc
index 39972d93..96206b2f 100644
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -58,6 +58,7 @@ pkgconfdir := $(usrlibdir)/pkgconfig
plugindir := $(prefix)/$(LIB)/multipath
configdir := $(etc_prefix)/etc/multipath/conf.d
configfile := $(etc_prefix)/etc/multipath.conf
+statedir := $(etc_prefix)/etc/multipath
runtimedir := $(if $(shell test -L /var/run -o ! -d /var/run && echo 1),/run,/var/run)
devmapper_incdir := $(or $(shell $(PKG_CONFIG) --variable=includedir devmapper),/usr/include)
libudev_incdir := $(or $(shell $(PKG_CONFIG) --variable=includedir libudev),/usr/include)
@@ -88,7 +89,8 @@ WARNFLAGS := -Werror -Wall -Wextra -Wformat=2 $(WFORMATOVERFLOW) -Werror=implici
CPPFLAGS := $(FORTIFY_OPT) $(CPPFLAGS) \
-DBIN_DIR=\"$(bindir)\" -DMULTIPATH_DIR=\"$(plugindir)\" \
-DRUNTIME_DIR=\"$(runtimedir)\" -DCONFIG_DIR=\"$(configdir)\" \
- -DDEFAULT_CONFIGFILE=\"$(configfile)\" -DEXTRAVERSION=\"$(EXTRAVERSION)\" -MMD -MP
+ -DDEFAULT_CONFIGFILE=\"$(configfile)\" -DSTATE_DIR=\"$(statedir)\" \
+ -DEXTRAVERSION=\"$(EXTRAVERSION)\" -MMD -MP
CFLAGS := --std=gnu99 $(CFLAGS) $(OPTFLAGS) $(WARNFLAGS) -pipe
BIN_CFLAGS := -fPIE -DPIE
LIB_CFLAGS := -fPIC
diff --git a/libmultipath/defaults.h b/libmultipath/defaults.h
index bc2d6388..d01f9712 100644
--- a/libmultipath/defaults.h
+++ b/libmultipath/defaults.h
@@ -66,9 +66,9 @@
#define MAX_DEV_LOSS_TMO UINT_MAX
#define DEFAULT_PIDFILE RUNTIME_DIR "/multipathd.pid"
#define DEFAULT_SOCKET "/org/kernel/linux/storage/multipathd"
-#define DEFAULT_BINDINGS_FILE "/etc/multipath/bindings"
-#define DEFAULT_WWIDS_FILE "/etc/multipath/wwids"
-#define DEFAULT_PRKEYS_FILE "/etc/multipath/prkeys"
+#define DEFAULT_BINDINGS_FILE STATE_DIR "/bindings"
+#define DEFAULT_WWIDS_FILE STATE_DIR "/wwids"
+#define DEFAULT_PRKEYS_FILE STATE_DIR "/prkeys"
#define MULTIPATH_SHM_BASE RUNTIME_DIR "/multipath/"

View File

@ -0,0 +1,366 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Fri, 8 Sep 2023 22:48:16 +0200
Subject: [PATCH] multipath-tools man pages: generate with correct paths
Generate the man pages using the compile-time settings for paths
to multipath.conf etc.
Add a paragraph about the CONFIGDIR (/etc/multipath/conf.d)
and the drop-in configuration files in the multipath.conf man page.
Also, make sure all generated man pages and other files are correctly
removed by "make clean".
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
.gitignore | 4 +++
Makefile.inc | 3 +++
mpathpersist/Makefile | 5 ++--
.../{mpathpersist.8 => mpathpersist.8.in} | 2 +-
multipath/Makefile | 13 +++++----
multipath/{multipath.8 => multipath.8.in} | 10 +++----
.../{multipath.conf.5 => multipath.conf.5.in} | 27 ++++++++++++-------
multipathd/Makefile | 9 ++++---
multipathd/{multipathd.8 => multipathd.8.in} | 8 +++---
9 files changed, 49 insertions(+), 32 deletions(-)
rename mpathpersist/{mpathpersist.8 => mpathpersist.8.in} (99%)
rename multipath/{multipath.8 => multipath.8.in} (97%)
rename multipath/{multipath.conf.5 => multipath.conf.5.in} (98%)
rename multipathd/{multipathd.8 => multipathd.8.in} (97%)
diff --git a/.gitignore b/.gitignore
index 535353e5..2986578f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,11 +13,15 @@ cscope.files
cscope.out
kpartx/kpartx
multipath/multipath
+multipath/multipath.8
+multipath/multipath.conf.5
multipath/multipath.rules
multipath/tmpfiles.conf
multipathd/multipathd
+multipathd/multipathd.8
multipathd/multipathc
mpathpersist/mpathpersist
+mpathpersist/mpathpersist.8
abi.tar.gz
abi
abi-test
diff --git a/Makefile.inc b/Makefile.inc
index 96206b2f..79e521e1 100644
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -133,3 +133,6 @@ NV_VERSION_SCRIPT = $(DEVLIB:%.so=%-nv.version)
@grep -P '^[ \t]+[a-zA-Z_][a-zA-Z0-9_]*;' $< >>$@
@printf 'local:\n\t*;\n};\n' >>$@
+%: %.in
+ @echo creating $@
+ $(Q)sed 's:@CONFIGFILE@:'$(configfile)':g;s:@CONFIGDIR@:'$(configdir)':g;s:@STATE_DIR@:'$(statedir)':g;s:@RUNTIME_DIR@:'$(runtimedir)':g' $< >$@
diff --git a/mpathpersist/Makefile b/mpathpersist/Makefile
index f57c105c..f3749467 100644
--- a/mpathpersist/Makefile
+++ b/mpathpersist/Makefile
@@ -8,10 +8,11 @@ LIBDEPS += -L$(mpathpersistdir) -lmpathpersist -L$(multipathdir) -lmultipath \
-L$(mpathutildir) -lmpathutil -L$(mpathcmddir) -lmpathcmd -lpthread -ldevmapper -ludev
EXEC = mpathpersist
+MANPAGES := mpathpersist.8
OBJS = main.o
-all: $(EXEC)
+all: $(EXEC) $(MANPAGES)
$(EXEC): $(OBJS)
$(Q)$(CC) $(OBJS) -o $(EXEC) $(LDFLAGS) $(CFLAGS) $(LIBDEPS)
@@ -23,7 +24,7 @@ install:
$(Q)$(INSTALL_PROGRAM) -m 644 $(EXEC).8 $(DESTDIR)$(mandir)/man8
clean: dep_clean
- $(Q)$(RM) core *.o $(EXEC)
+ $(Q)$(RM) core *.o $(EXEC) $(MANPAGES)
include $(wildcard $(OBJS:.o=.d))
diff --git a/mpathpersist/mpathpersist.8 b/mpathpersist/mpathpersist.8.in
similarity index 99%
rename from mpathpersist/mpathpersist.8
rename to mpathpersist/mpathpersist.8.in
index 8d26b37c..fecef0d6 100644
--- a/mpathpersist/mpathpersist.8
+++ b/mpathpersist/mpathpersist.8.in
@@ -31,7 +31,7 @@ mpathpersist \- Manages SCSI persistent reservations on dm multipath devices.
.
This utility is used to manage SCSI persistent reservations on Device Mapper
Multipath devices. To be able to use this functionality, the \fIreservation_key\fR
-attribute must be defined in the \fI/etc/multipath.conf\fR file. Otherwise the
+attribute must be defined in the \fI@CONFIGFILE@\fR file. Otherwise the
\fBmultipathd\fR daemon will not check for persistent reservation for newly
discovered paths or reinstated paths.
.
diff --git a/multipath/Makefile b/multipath/Makefile
index 73db991a..68cb5ce7 100644
--- a/multipath/Makefile
+++ b/multipath/Makefile
@@ -3,7 +3,9 @@
#
include ../Makefile.inc
-EXEC := multipath
+EXEC := multipath
+MANPAGES := multipath.8 multipath.conf.5
+GENERATED := $(MANPAGES) multipath.rules tmpfiles.conf
CPPFLAGS += -I$(multipathdir) -I$(mpathutildir) -I$(mpathcmddir)
CFLAGS += $(BIN_CFLAGS)
@@ -13,7 +15,7 @@ LIBDEPS += -L$(multipathdir) -lmultipath -L$(mpathutildir) -lmpathutil \
OBJS := main.o
-all: $(EXEC) multipath.rules tmpfiles.conf
+all: $(EXEC) $(GENERATED)
$(EXEC): $(OBJS) $(multipathdir)/libmultipath.so $(mpathcmddir)/libmpathcmd.so
@echo building $@ because of $?
@@ -47,15 +49,12 @@ uninstall:
$(Q)$(RM) $(DESTDIR)$(libudevdir)/rules.d/56-multipath.rules
$(Q)$(RM) $(DESTDIR)$(mandir)/man8/$(EXEC).8
$(Q)$(RM) $(DESTDIR)$(mandir)/man5/$(EXEC).conf.5
+ $(Q)$(RM) $(DESTDIR)$(tmpfilesdir)/multipath.conf
clean: dep_clean
- $(Q)$(RM) core *.o $(EXEC) multipath.rules tmpfiles.conf
+ $(Q)$(RM) core *.o $(EXEC) $(GENERATED)
include $(wildcard $(OBJS:.o=.d))
dep_clean:
$(Q)$(RM) $(OBJS:.o=.d)
-
-%: %.in
- @echo creating $@
- $(Q)sed 's,@RUNTIME_DIR@,$(runtimedir),' $< >$@
diff --git a/multipath/multipath.8 b/multipath/multipath.8.in
similarity index 97%
rename from multipath/multipath.8
rename to multipath/multipath.8.in
index 5fed6df7..348eb220 100644
--- a/multipath/multipath.8
+++ b/multipath/multipath.8.in
@@ -185,7 +185,7 @@ Display the currently used multipathd configuration.
.B \-T
Display the currently used multipathd configuration, limiting the output to
those devices actually present in the system. This can be used a template for
-creating \fImultipath.conf\fR.
+creating \fI@CONFIGFILE@\fR.
.
.\" ----------------------------------------------------------------------------
.SH OPTIONS
@@ -233,11 +233,11 @@ option from \fBmultipath.conf(5)\fR.
.B \-i
Ignore WWIDs file when processing devices. If
\fIfind_multipaths strict\fR or \fIfind_multipaths no\fR is set in
-\fImultipath.conf\fR, multipath only considers devices that are
+\fI@CONFIGFILE@\fR, multipath only considers devices that are
listed in the WWIDs file. This option overrides that behavior. For other values
of \fIfind_multipaths\fR, this option has no effect. See the description of
\fIfind_multipaths\fR in
-.BR multipath.conf (5).
+.BR @CONFIGFILE@ (5).
This option should only be used in rare circumstances.
.
.TP
@@ -246,8 +246,8 @@ Treat the bindings file as read only.
.
.TP
.BI \-b " file"
-Set \fIuser_friendly_names\fR bindings file location. The default is
-\fI/etc/multipath/bindings\fR.
+(\fBdeprecated, do not use\fR) Set \fIuser_friendly_names\fR bindings file location. The default is
+\fI@STATE_DIR@/bindings\fR.
.
.TP
.B \-q
diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5.in
similarity index 98%
rename from multipath/multipath.conf.5
rename to multipath/multipath.conf.5.in
index 93af17db..20df2232 100644
--- a/multipath/multipath.conf.5
+++ b/multipath/multipath.conf.5.in
@@ -13,14 +13,14 @@
.SH NAME
.\" ----------------------------------------------------------------------------
.
-multipath.conf \- multipath daemon configuration file.
+@CONFIGFILE@, @CONFIGDIR@/*.conf \- multipath daemon configuration file.
.
.
.\" ----------------------------------------------------------------------------
.SH DESCRIPTION
.\" ----------------------------------------------------------------------------
.
-.B "/etc/multipath.conf"
+.B "@CONFIGFILE@"
is the configuration file for the multipath daemon. It is used to
overwrite the built-in configuration table of \fBmultipathd\fP.
Any line whose first non-white-space character is a '#' is considered
@@ -29,6 +29,15 @@ a comment line. Empty lines are ignored.
Currently used multipathd configuration can be displayed with the \fBmultipath -t\fR
or \fBmultipathd show config\fR command.
.
+.PP
+Additional configuration can be made in drop-in files under
+.B @CONFIGDIR@.
+Files ending in \fI.conf\fR in this directory are read
+in alphabetical order, after reading \fI@CONFIGFILE@\fR.
+They use the same syntax as \fI@CONFIGFILE@\fR itself,
+and support all sections and keywords. If a keyword occurs in the same section
+in multiple files, the last occurence will take precedence over all others.
+.
.
.\" ----------------------------------------------------------------------------
.SH SYNTAX
@@ -85,7 +94,7 @@ not mandatory.
.
.LP
.B Note on regular expressions:
-The \fImultipath.conf\fR syntax allows many attribute values to be specified as POSIX
+The \fI@CONFIGFILE@\fR syntax allows many attribute values to be specified as POSIX
Extended Regular Expressions (see \fBregex\fR(7)). These regular expressions
are \fBcase sensitive\fR and \fBnot anchored\fR, thus the expression "bar" matches "barbie",
"rhabarber", and "wunderbar", but not "Barbie". To avoid unwanted substring
@@ -711,7 +720,7 @@ The default is: \fBno\fR
.B user_friendly_names
If set to
.I yes
-, using the bindings file \fI/etc/multipath/bindings\fR to assign a persistent
+, using the bindings file \fI@STATE_DIR@/bindings\fR to assign a persistent
and unique alias to the multipath, in the form of mpath<n>. If set to
.I no
use the WWID as the alias. In either case this be will
@@ -790,7 +799,7 @@ The full pathname of the binding file to be used when the user_friendly_names
option is set.
.RS
.TP
-The default is: \fB/etc/multipath/bindings\fR
+The default is: \fB@STATE_DIR@/bindings\fR
.RE
.
.
@@ -801,7 +810,7 @@ The full pathname of the WWIDs file, which is used by multipath to keep track
of the WWIDs for LUNs it has created multipath devices on in the past.
.RS
.TP
-The default is: \fB/etc/multipath/wwids\fR
+The default is: \fB@STATE_DIR@/wwids\fR
.RE
.
.
@@ -813,7 +822,7 @@ track of the persistent reservation key used for a specific WWID, when
\fIreservation_key\fR is set to \fBfile\fR.
.RS
.TP
-The default is: \fB/etc/multipath/prkeys\fR
+The default is: \fB@STATE_DIR@/prkeys\fR
.RE
.
.
@@ -872,7 +881,7 @@ The default is: \fBno\fR
.I yes
and the SCSI layer has already attached a hardware_handler to the device,
multipath will not force the device to use the hardware_handler specified by
-multipath.conf. If the SCSI layer has not attached a hardware handler,
+@CONFIGFILE@. If the SCSI layer has not attached a hardware handler,
multipath will continue to use its configured hardware handler.
.RS
.PP
@@ -1559,7 +1568,7 @@ given device, the attributes of all matching entries are applied to it.
If an attribute is specified in several matching device subsections,
later entries take precedence. Thus, entries in files under \fIconfig_dir\fR (in
reverse alphabetical order) have the highest precedence, followed by entries
-in \fImultipath.conf\fR; the built-in hardware table has the lowest
+in \fI@CONFIGFILE@\fR; the built-in hardware table has the lowest
precedence. Inside a configuration file, later entries have higher precedence
than earlier ones.
.LP
diff --git a/multipathd/Makefile b/multipathd/Makefile
index 0d0146c5..cdba3db1 100644
--- a/multipathd/Makefile
+++ b/multipathd/Makefile
@@ -1,7 +1,8 @@
include ../Makefile.inc
-EXEC := multipathd
-CLI := multipathc
+EXEC := multipathd
+CLI := multipathc
+MANPAGES := multipathd.8
CPPFLAGS += -I$(multipathdir) -I$(mpathutildir) -I$(mpathpersistdir) -I$(mpathcmddir) -I$(thirdpartydir) \
$(shell $(PKG_CONFIG) --modversion liburcu 2>/dev/null | \
@@ -42,7 +43,7 @@ ifeq ($(FPIN_SUPPORT),1)
OBJS += fpin_handlers.o
endif
-all : $(EXEC) $(CLI)
+all : $(EXEC) $(CLI) $(MANPAGES)
$(EXEC): $(OBJS) $(multipathdir)/libmultipath.so $(mpathcmddir)/libmpathcmd.so
@echo building $@ because of $?
@@ -79,7 +80,7 @@ uninstall:
$(Q)$(RM) $(DESTDIR)$(unitdir)/$(EXEC).socket
clean: dep_clean
- $(Q)$(RM) core *.o $(EXEC) $(CLI)
+ $(Q)$(RM) core *.o $(EXEC) $(CLI) $(MANPAGES)
include $(wildcard $(OBJS:.o=.d) $(CLI_OBJS:.o=.d))
diff --git a/multipathd/multipathd.8 b/multipathd/multipathd.8.in
similarity index 97%
rename from multipathd/multipathd.8
rename to multipathd/multipathd.8.in
index cc72b775..e98c27fd 100644
--- a/multipathd/multipathd.8
+++ b/multipathd/multipathd.8.in
@@ -155,7 +155,7 @@ Show the format wildcards used in interactive commands taking $format.
.TP
.B list|show config
Show the currently used configuration, derived from default values and values
-specified within the configuration file \fI/etc/multipath.conf\fR.
+specified within the configuration file \fI@CONFIGFILE@\fR.
.
.TP
.B list|show config local
@@ -165,7 +165,7 @@ the devices section to those devices that are actually present in the system.
.TP
.B list|show blacklist
Show the currently used blacklist rules, derived from default values and values
-specified within the configuration file \fI/etc/multipath.conf\fR.
+specified within the configuration file \fI@CONFIGFILE@\fR.
.
.TP
.B list|show devices
@@ -290,13 +290,13 @@ Get the current persistent reservation key associated with $map.
.B map|multipath $map setprkey key $key
Set the persistent reservation key associated with $map to $key in the
\fIprkeys_file\fR. This key will only be used by multipathd if
-\fIreservation_key\fR is set to \fBfile\fR in \fI/etc/multipath.conf\fR.
+\fIreservation_key\fR is set to \fBfile\fR in \fI@CONFIGFILE@\fR.
.
.TP
.B map|multipath $map unsetprkey
Remove the persistent reservation key associated with $map from the
\fIprkeys_file\fR. This will only unset the key used by multipathd if
-\fIreservation_key\fR is set to \fBfile\fR in \fI/etc/multipath.conf\fR.
+\fIreservation_key\fR is set to \fBfile\fR in \fI@CONFIGFILE@\fR.
.
.TP
.B path $path setmarginal

View File

@ -0,0 +1,25 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Mon, 11 Sep 2023 09:30:13 +0200
Subject: [PATCH] libdmmp/Makefile: fix bug in install section
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libdmmp/Makefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libdmmp/Makefile b/libdmmp/Makefile
index 078eca8f..172ba045 100644
--- a/libdmmp/Makefile
+++ b/libdmmp/Makefile
@@ -44,7 +44,7 @@ install:
$(DESTDIR)$(pkgconfdir)/$(PKGFILE)
$(Q)sed -i 's|__INCLUDEDIR__|$(includedir)|g' \
$(DESTDIR)$(pkgconfdir)/$(PKGFILE)
- $(Q)$(INSTALL_PROGRAM) -d 755 $(DESTDIR)$(mandir)/man3
+ $(Q)$(INSTALL_PROGRAM) -m 755 -d $(DESTDIR)$(mandir)/man3
$(Q)$(INSTALL_PROGRAM) -m 644 -t $(DESTDIR)$(mandir)/man3 docs/man/*.3
uninstall:

View File

@ -0,0 +1,75 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Mon, 11 Sep 2023 10:22:13 +0200
Subject: [PATCH] multipath-tools: README.md: improve documentation for
compile-time options
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
README.md | 38 ++++++++++++++++++++++++++------------
1 file changed, 26 insertions(+), 12 deletions(-)
diff --git a/README.md b/README.md
index a7f994ae..679e55bf 100644
--- a/README.md
+++ b/README.md
@@ -89,9 +89,17 @@ The following variables can be passed to the `make` command line:
* `plugindir="/some/path"`: directory where libmultipath plugins (path
checkers, prioritizers, and foreign multipath support) will be looked up.
This used to be the run-time option `multipath_dir` in earlier versions.
- * `configdir="/some/path"` : directory to search for configuration files.
+ The default is `$(prefix)/$(LIB)/multipath`, where `$(LIB)` is `lib64` on
+ systems that have `/lib64`, and `lib` otherwise.
+ * `configfile="/some/path`": The path to the main configuration file.
+ The defalt is `$(etc_prefix)/etc/multipath.conf`.
+ * `configdir="/some/path"` : directory to search for additional configuration files.
This used to be the run-time option `config_dir` in earlier versions.
- The default is `/etc/multipath/conf.d`.
+ The default is `$(etc_prefix)/etc/multipath/conf.d`.
+ * `statedir="/some/path"`: The path of the directory where multipath-tools
+ stores run-time settings that need persist between reboots, such as known
+ WWIDs, user-friendly names, and persistent reservation keys.
+ The default is `$(etc_prefix)/etc/multipath`.
* `READLINE=libedit` or `READLINE=libreadline`: enable command line history
and TAB completion in the interactive mode *(which is entered with `multipathd -k` or `multipathc`)*.
The respective development package will be required for building.
@@ -119,21 +127,27 @@ The following variables can be passed to the `make` command line:
### Installation Paths
* `prefix`: The directory prefix for (almost) all files to be installed.
- Distributions may want to set this to `/usr`.
- **Note**: for multipath-tools, unlike many other packages, `prefix`
- defaults to the empty string, which resolves to the root directory (`/`).
+ "Usr-merged" distributions[^systemd] may want to set this to `/usr`. The
+ default is empty (`""`).
* `usr_prefix`: where to install those parts of the code that aren't necessary
- for booting. You may want to set this to `/usr` if `prefix` is empty.
- * `systemd_prefix`: Prefix for systemd-related files. It defaults to `/usr`.
- Some systemd installations use separate `prefix` and `rootprefix`. On such
- a distribution, set `prefix`, and override `unitdir` to use systemd's
- `rootprefix`.
+ for booting. Non-usr-merged distributions[^systemd] may want to set this to
+ `/usr`. The default is `$(prefix)`.
+ * `systemd_prefix`: Prefix for systemd-related files[^systemd]. The default is `/usr`.
+ * `etc_prefix`: The prefix for configuration files. "Usr-merged"
+ distributions with immutable `/usr`[^systemd] may want to set this to
+ `/etc`. The default is `$(prefix)`.
* `LIB`: the subdirectory under `prefix` where shared libraries will be
installed. By default, the makefile uses `/lib64` if this directory is
found on the build system, and `/lib` otherwise.
-See also `configdir` and `plugindir` above. See `Makefile.inc` for more
-fine-grained control.
+The options `configdir`, `plugindir`, `configfile`, and `statedir` above can
+be used for setting indvidual paths where the `prefix` variables don't provide
+sufficient control. See `Makefile.inc` for even more fine-grained control.
+
+[^systemd]: Some systemd installations use separate `prefix` and `rootprefix`.
+ On such a distribution, set `prefix`, and override `unitdir` to use systemd's
+ `rootprefix`. Recent systemd releases generally require everything to be
+ installed under `/usr` (so-called "usr-merged" distribution). On "usr-
### Compiler Options

View File

@ -0,0 +1,55 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Mon, 11 Sep 2023 11:36:25 +0200
Subject: [PATCH] libmultipath: print built-in values for deprecated options
In the error messages we print when a deprecated option is encountered,
print the compile-time value of the option.
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/dict.c | 16 +++++++++-------
1 file changed, 9 insertions(+), 7 deletions(-)
diff --git a/libmultipath/dict.c b/libmultipath/dict.c
index f81c84aa..dace343d 100644
--- a/libmultipath/dict.c
+++ b/libmultipath/dict.c
@@ -314,14 +314,16 @@ def_ ## option ## _handler (struct config *conf, vector strvec, \
static int deprecated_handler(struct config *conf, vector strvec, const char *file,
int line_nr);
-#define declare_deprecated_handler(option) \
+#define declare_deprecated_handler(option, default) \
static int \
deprecated_ ## option ## _handler (struct config *conf, vector strvec, \
const char *file, int line_nr) \
{ \
static bool warned; \
if (!warned) { \
- condlog(1, "%s line %d: ignoring deprecated option \"" #option "\"", file, line_nr); \
+ condlog(1, "%s line %d: ignoring deprecated option \"" \
+ #option "\", using built-in value: \"%s\"", \
+ file, line_nr, default); \
warned = true; \
} \
return deprecated_handler(conf, strvec, file, line_nr); \
@@ -2057,11 +2059,11 @@ snprint_deprecated (struct config *conf, struct strbuf *buff, const void * data)
}
// Deprecated keywords
-declare_deprecated_handler(config_dir)
-declare_deprecated_handler(disable_changed_wwids)
-declare_deprecated_handler(getuid_callout)
-declare_deprecated_handler(multipath_dir)
-declare_deprecated_handler(pg_timeout)
+declare_deprecated_handler(config_dir, CONFIG_DIR)
+declare_deprecated_handler(disable_changed_wwids, "yes")
+declare_deprecated_handler(getuid_callout, "(not set)")
+declare_deprecated_handler(multipath_dir, MULTIPATH_DIR)
+declare_deprecated_handler(pg_timeout, "(not set)")
/*
* If you add or remove a keyword also update multipath/multipath.conf.5

View File

@ -0,0 +1,25 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Mon, 11 Sep 2023 11:37:37 +0200
Subject: [PATCH] multipath: add a missing newline
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipath/main.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/multipath/main.c b/multipath/main.c
index 45e9745f..b91289e8 100644
--- a/multipath/main.c
+++ b/multipath/main.c
@@ -1025,7 +1025,7 @@ main (int argc, char *argv[])
}
if (check_alias_settings(conf)) {
- fprintf(stderr, "fatal configuration error, aborting");
+ fprintf(stderr, "fatal configuration error, aborting\n");
exit(RTVL_FAIL);
}

View File

@ -0,0 +1,66 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Mon, 11 Sep 2023 16:03:34 +0200
Subject: [PATCH] multipath-tools: allow prefixes with and w/o trailing slash
Add some logic to Makefile.inc that leads to the same result
for "prefix=" and "prefix=/", or "prefix=/usr" and "prefix=/usr/".
The logic does not work for multiple trailing slashes. It applies
to all XYZ_prefix variables in Makefile.inc.
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
Makefile.inc | 35 ++++++++++++++++++++++-------------
1 file changed, 22 insertions(+), 13 deletions(-)
diff --git a/Makefile.inc b/Makefile.inc
index 79e521e1..6e384e68 100644
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -43,22 +43,31 @@ etc_prefix := $(prefix)
# Note: some systemd installations use separate "prefix" and "rootprefix".
# In this case, override only unitdir to use systemd's "rootprefix" instead of $(systemd_prefix)
systemd_prefix := /usr
-unitdir := $(systemd_prefix)/lib/systemd/system
-tmpfilesdir := $(systemd_prefix)/lib/tmpfiles.d
-modulesloaddir := $(systemd_prefix)/lib/modules-load.d
-libudevdir := $(systemd_prefix)/lib/udev
+
+# Make sure all prefix variables end in "/"
+append-slash = $(1)$(if $(filter %/,$(1)),,/)
+override prefix := $(call append-slash,$(prefix))
+override exec_prefix := $(call append-slash,$(exec_prefix))
+override usr_prefix := $(call append-slash,$(usr_prefix))
+override etc_prefix := $(call append-slash,$(etc_prefix))
+override systemd_prefix := $(call append-slash,$(systemd_prefix))
+
+unitdir := $(systemd_prefix)lib/systemd/system
+tmpfilesdir := $(systemd_prefix)lib/tmpfiles.d
+modulesloaddir := $(systemd_prefix)lib/modules-load.d
+libudevdir := $(systemd_prefix)lib/udev
udevrulesdir := $(libudevdir)/rules.d
-bindir := $(exec_prefix)/sbin
-mandir := $(usr_prefix)/share/man
+bindir := $(exec_prefix)sbin
+mandir := $(usr_prefix)share/man
LIB := $(if $(shell test -d /lib64 && echo 1),lib64,lib)
-syslibdir := $(prefix)/$(LIB)
-usrlibdir := $(usr_prefix)/$(LIB)
-includedir := $(usr_prefix)/include
+syslibdir := $(prefix)$(LIB)
+usrlibdir := $(usr_prefix)$(LIB)
+includedir := $(usr_prefix)include
pkgconfdir := $(usrlibdir)/pkgconfig
-plugindir := $(prefix)/$(LIB)/multipath
-configdir := $(etc_prefix)/etc/multipath/conf.d
-configfile := $(etc_prefix)/etc/multipath.conf
-statedir := $(etc_prefix)/etc/multipath
+plugindir := $(prefix)$(LIB)/multipath
+configdir := $(etc_prefix)etc/multipath/conf.d
+configfile := $(etc_prefix)etc/multipath.conf
+statedir := $(etc_prefix)etc/multipath
runtimedir := $(if $(shell test -L /var/run -o ! -d /var/run && echo 1),/run,/var/run)
devmapper_incdir := $(or $(shell $(PKG_CONFIG) --variable=includedir devmapper),/usr/include)
libudev_incdir := $(or $(shell $(PKG_CONFIG) --variable=includedir libudev),/usr/include)

View File

@ -0,0 +1,897 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Mon, 11 Sep 2023 17:58:13 +0200
Subject: [PATCH] libmultipath: deprecate bindings_file, wwids_file,
prkeys_file
The options bindings_file, wwids_file, and prkeys_file have been
deprecated since cb4d6db ("libmultipath: deprecate file and directory config
options") (multipath-tools 0.8.8). Deprecate and ignore them now.
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/alias.c | 43 +++++++++----------
libmultipath/alias.h | 3 +-
libmultipath/config.c | 18 --------
libmultipath/config.h | 3 --
libmultipath/dict.c | 39 +++---------------
libmultipath/libmultipath.version | 8 +---
libmultipath/prkey.c | 7 ++--
libmultipath/prkey.h | 7 ++--
libmultipath/propsel.c | 5 +--
libmultipath/wwids.c | 18 ++------
multipath/main.c | 2 +-
multipath/multipath.conf.5.in | 23 +++++------
multipathd/uxlsnr.c | 17 +++-----
tests/alias.c | 68 +++++++++++++++----------------
14 files changed, 90 insertions(+), 171 deletions(-)
diff --git a/libmultipath/alias.c b/libmultipath/alias.c
index 964b8a7b..e5d3f151 100644
--- a/libmultipath/alias.c
+++ b/libmultipath/alias.c
@@ -55,6 +55,8 @@
/* uatomic access only */
static int bindings_file_changed = 1;
+static const char bindings_file_path[] = DEFAULT_BINDINGS_FILE;
+
static pthread_mutex_t timestamp_mutex = PTHREAD_MUTEX_INITIALIZER;
static struct timespec bindings_last_updated;
@@ -274,7 +276,6 @@ static int write_bindings_file(const Bindings *bindings, int fd,
void handle_bindings_file_inotify(const struct inotify_event *event)
{
- struct config *conf;
const char *base;
bool changed = false;
struct stat st;
@@ -284,12 +285,9 @@ void handle_bindings_file_inotify(const struct inotify_event *event)
if (!(event->mask & IN_MOVED_TO))
return;
- conf = get_multipath_config();
- base = strrchr(conf->bindings_file, '/');
- changed = base && base > conf->bindings_file &&
- !strcmp(base + 1, event->name);
- ret = stat(conf->bindings_file, &st);
- put_multipath_config(conf);
+ base = strrchr(bindings_file_path, '/');
+ changed = base && !strcmp(base + 1, event->name);
+ ret = stat(bindings_file_path, &st);
if (!changed)
return;
@@ -310,8 +308,7 @@ void handle_bindings_file_inotify(const struct inotify_event *event)
__func__, (long)ts.tv_sec, (long)ts.tv_nsec / 1000);
}
-static int update_bindings_file(const Bindings *bindings,
- const char *bindings_file)
+static int update_bindings_file(const Bindings *bindings)
{
int rc;
int fd = -1;
@@ -319,7 +316,7 @@ static int update_bindings_file(const Bindings *bindings,
mode_t old_umask;
struct timespec ts;
- if (safe_sprintf(tempname, "%s.XXXXXX", bindings_file))
+ if (safe_sprintf(tempname, "%s.XXXXXX", bindings_file_path))
return -1;
/* coverity: SECURE_TEMP */
old_umask = umask(0077);
@@ -336,13 +333,13 @@ static int update_bindings_file(const Bindings *bindings,
unlink(tempname);
return rc;
}
- if ((rc = rename(tempname, bindings_file)) == -1)
+ if ((rc = rename(tempname, bindings_file_path)) == -1)
condlog(0, "%s: rename: %m", __func__);
else {
pthread_mutex_lock(&timestamp_mutex);
bindings_last_updated = ts;
pthread_mutex_unlock(&timestamp_mutex);
- condlog(1, "updated bindings file %s", bindings_file);
+ condlog(1, "updated bindings file %s", bindings_file_path);
}
return rc;
}
@@ -474,7 +471,7 @@ int get_free_id(const Bindings *bindings, const char *prefix, const char *map_ww
/* Called with binding_mutex held */
static char *
-allocate_binding(const char *filename, const char *wwid, int id, const char *prefix)
+allocate_binding(const char *wwid, int id, const char *prefix)
{
STRBUF_ON_STACK(buf);
char *alias;
@@ -498,7 +495,7 @@ allocate_binding(const char *filename, const char *wwid, int id, const char *pre
return NULL;
}
- if (update_bindings_file(&global_bindings, filename) == -1) {
+ if (update_bindings_file(&global_bindings) == -1) {
condlog(1, "%s: deleting binding %s for %s", __func__, alias, wwid);
delete_binding(&global_bindings, wwid);
free(alias);
@@ -565,7 +562,7 @@ static void read_bindings_file(void)
* that the mpvec corrcectly represents kernel state.
*/
-char *get_user_friendly_alias(const char *wwid, const char *file, const char *alias_old,
+char *get_user_friendly_alias(const char *wwid, const char *alias_old,
const char *prefix, bool bindings_read_only)
{
char *alias = NULL;
@@ -622,7 +619,7 @@ new_alias:
}
if (!bindings_read_only && id > 0)
- alias = allocate_binding(file, wwid, id, prefix);
+ alias = allocate_binding(wwid, id, prefix);
if (alias && !new_binding)
condlog(2, "Allocated existing binding [%s] for WWID [%s]",
@@ -715,12 +712,12 @@ static int _check_bindings_file(const struct config *conf, FILE *file,
header[sizeof(BINDINGS_FILE_HEADER) - 1] = '\0';
if (fread(header, sizeof(BINDINGS_FILE_HEADER) - 1, 1, file) < 1) {
condlog(2, "%s: failed to read header from %s", __func__,
- conf->bindings_file);
+ bindings_file_path);
fseek(file, 0, SEEK_SET);
rc = -1;
} else if (strcmp(header, BINDINGS_FILE_HEADER)) {
condlog(2, "%s: invalid header in %s", __func__,
- conf->bindings_file);
+ bindings_file_path);
fseek(file, 0, SEEK_SET);
rc = -1;
}
@@ -787,13 +784,13 @@ static int _read_bindings_file(const struct config *conf, Bindings *bindings,
}
}
- fd = open_file(conf->bindings_file, &can_write, BINDINGS_FILE_HEADER);
+ fd = open_file(bindings_file_path, &can_write, BINDINGS_FILE_HEADER);
if (fd == -1)
return BINDINGS_FILE_ERROR;
file = fdopen(fd, "r");
if (file != NULL) {
- condlog(3, "%s: reading %s", __func__, conf->bindings_file);
+ condlog(3, "%s: reading %s", __func__, bindings_file_path);
pthread_cleanup_push(cleanup_fclose, file);
ret = _check_bindings_file(conf, file, bindings);
@@ -812,20 +809,20 @@ static int _read_bindings_file(const struct config *conf, Bindings *bindings,
bindings_last_updated = ts;
pthread_mutex_unlock(&timestamp_mutex);
} else if (ret == -1 && can_write && !conf->bindings_read_only) {
- ret = update_bindings_file(bindings, conf->bindings_file);
+ ret = update_bindings_file(bindings);
if (ret == 0)
rc = BINDINGS_FILE_READ;
else
rc = BINDINGS_FILE_BAD;
} else {
condlog(0, "ERROR: bad settings in read-only bindings file %s",
- conf->bindings_file);
+ bindings_file_path);
rc = BINDINGS_FILE_BAD;
}
pthread_cleanup_pop(1);
} else {
condlog(1, "failed to fdopen %s: %m",
- conf->bindings_file);
+ bindings_file_path);
close(fd);
rc = BINDINGS_FILE_ERROR;
}
diff --git a/libmultipath/alias.h b/libmultipath/alias.h
index ca8911f4..629e8d56 100644
--- a/libmultipath/alias.h
+++ b/libmultipath/alias.h
@@ -3,8 +3,7 @@
int valid_alias(const char *alias);
int get_user_friendly_wwid(const char *alias, char *buff);
-char *get_user_friendly_alias(const char *wwid, const char *file,
- const char *alias_old,
+char *get_user_friendly_alias(const char *wwid, const char *alias_old,
const char *prefix, bool bindings_read_only);
struct config;
diff --git a/libmultipath/config.c b/libmultipath/config.c
index 7b207590..b7dbc6f5 100644
--- a/libmultipath/config.c
+++ b/libmultipath/config.c
@@ -752,15 +752,6 @@ static void _uninit_config(struct config *conf)
if (conf->hwhandler)
free(conf->hwhandler);
- if (conf->bindings_file)
- free(conf->bindings_file);
-
- if (conf->wwids_file)
- free(conf->wwids_file);
-
- if (conf->prkeys_file)
- free(conf->prkeys_file);
-
if (conf->prio_name)
free(conf->prio_name);
@@ -922,9 +913,6 @@ int _init_config (const char *file, struct config *conf)
* internal defaults
*/
get_sys_max_fds(&conf->max_fds);
- conf->bindings_file = set_default(DEFAULT_BINDINGS_FILE);
- conf->wwids_file = set_default(DEFAULT_WWIDS_FILE);
- conf->prkeys_file = set_default(DEFAULT_PRKEYS_FILE);
conf->attribute_flags = 0;
conf->reassign_maps = DEFAULT_REASSIGN_MAPS;
conf->checkint = CHECKINT_UNDEF;
@@ -1078,12 +1066,6 @@ int _init_config (const char *file, struct config *conf)
merge_blacklist(conf->elist_wwid);
merge_blacklist_device(conf->elist_device);
- if (conf->bindings_file == NULL)
- conf->bindings_file = set_default(DEFAULT_BINDINGS_FILE);
-
- if (!conf->bindings_file || !conf->wwids_file || !conf->prkeys_file)
- goto out;
-
libmp_verbosity = conf->verbosity;
return 0;
out:
diff --git a/libmultipath/config.h b/libmultipath/config.h
index 0a2c297b..8c22ce75 100644
--- a/libmultipath/config.h
+++ b/libmultipath/config.h
@@ -207,9 +207,6 @@ struct config {
char * uid_attribute;
char * features;
char * hwhandler;
- char * bindings_file;
- char * wwids_file;
- char * prkeys_file;
char * prio_name;
char * prio_args;
char * checker_name;
diff --git a/libmultipath/dict.c b/libmultipath/dict.c
index dace343d..044067af 100644
--- a/libmultipath/dict.c
+++ b/libmultipath/dict.c
@@ -168,27 +168,6 @@ fail:
return 0;
}
-static int
-set_path(vector strvec, void *ptr, const char *file, int line_nr)
-{
- char **str_ptr = (char **)ptr;
- char *old_str = *str_ptr;
-
- *str_ptr = set_value(strvec);
- if (!*str_ptr) {
- free(old_str);
- return 1;
- }
- if ((*str_ptr)[0] != '/'){
- condlog(1, "%s line %d, %s is not an absolute path. Ignoring",
- file, line_nr, *str_ptr);
- free(*str_ptr);
- *str_ptr = old_str;
- } else
- free(old_str);
- return 0;
-}
-
static int
set_str_noslash(vector strvec, void *ptr, const char *file, int line_nr)
{
@@ -831,15 +810,6 @@ declare_hw_snprint(user_friendly_names, print_yes_no_undef)
declare_mp_handler(user_friendly_names, set_yes_no_undef)
declare_mp_snprint(user_friendly_names, print_yes_no_undef)
-declare_def_warn_handler(bindings_file, set_path)
-declare_def_snprint(bindings_file, print_str)
-
-declare_def_warn_handler(wwids_file, set_path)
-declare_def_snprint(wwids_file, print_str)
-
-declare_def_warn_handler(prkeys_file, set_path)
-declare_def_snprint(prkeys_file, print_str)
-
declare_def_handler(retain_hwhandler, set_yes_no_undef)
declare_def_snprint_defint(retain_hwhandler, print_yes_no_undef,
DEFAULT_RETAIN_HWHANDLER)
@@ -2064,6 +2034,9 @@ declare_deprecated_handler(disable_changed_wwids, "yes")
declare_deprecated_handler(getuid_callout, "(not set)")
declare_deprecated_handler(multipath_dir, MULTIPATH_DIR)
declare_deprecated_handler(pg_timeout, "(not set)")
+declare_deprecated_handler(bindings_file, DEFAULT_BINDINGS_FILE)
+declare_deprecated_handler(wwids_file, DEFAULT_WWIDS_FILE)
+declare_deprecated_handler(prkeys_file, DEFAULT_PRKEYS_FILE)
/*
* If you add or remove a keyword also update multipath/multipath.conf.5
@@ -2106,9 +2079,9 @@ init_keywords(vector keywords)
install_keyword("fast_io_fail_tmo", &def_fast_io_fail_handler, &snprint_def_fast_io_fail);
install_keyword("dev_loss_tmo", &def_dev_loss_handler, &snprint_def_dev_loss);
install_keyword("eh_deadline", &def_eh_deadline_handler, &snprint_def_eh_deadline);
- install_keyword("bindings_file", &def_bindings_file_handler, &snprint_def_bindings_file);
- install_keyword("wwids_file", &def_wwids_file_handler, &snprint_def_wwids_file);
- install_keyword("prkeys_file", &def_prkeys_file_handler, &snprint_def_prkeys_file);
+ install_keyword("bindings_file", &deprecated_bindings_file_handler, &snprint_deprecated);
+ install_keyword("wwids_file", &deprecated_wwids_file_handler, &snprint_deprecated);
+ install_keyword("prkeys_file", &deprecated_prkeys_file_handler, &snprint_deprecated);
install_keyword("log_checker_err", &def_log_checker_err_handler, &snprint_def_log_checker_err);
install_keyword("reservation_key", &def_reservation_key_handler, &snprint_def_reservation_key);
install_keyword("all_tg_pt", &def_all_tg_pt_handler, &snprint_def_all_tg_pt);
diff --git a/libmultipath/libmultipath.version b/libmultipath/libmultipath.version
index 57e50c12..8368ef7a 100644
--- a/libmultipath/libmultipath.version
+++ b/libmultipath/libmultipath.version
@@ -43,7 +43,7 @@ LIBMPATHCOMMON_1.0.0 {
put_multipath_config;
};
-LIBMULTIPATH_20.0.0 {
+LIBMULTIPATH_21.0.0 {
global:
/* symbols referenced by multipath and multipathd */
add_foreign;
@@ -121,6 +121,7 @@ global:
get_used_hwes;
get_vpd_sgio;
group_by_prio;
+ handle_bindings_file_inotify;
has_dm_info;
init_checkers;
init_config;
@@ -238,8 +239,3 @@ global:
local:
*;
};
-
-LIBMULTIPATH_20.1.0 {
-global:
- handle_bindings_file_inotify;
-};
diff --git a/libmultipath/prkey.c b/libmultipath/prkey.c
index a215499d..c66d293b 100644
--- a/libmultipath/prkey.c
+++ b/libmultipath/prkey.c
@@ -157,8 +157,7 @@ static int do_prkey(int fd, char *wwid, char *keystr, int cmd)
return 0;
}
-int get_prkey(struct config *conf, struct multipath *mpp, uint64_t *prkey,
- uint8_t *sa_flags)
+int get_prkey(struct multipath *mpp, uint64_t *prkey, uint8_t *sa_flags)
{
int fd;
int unused;
@@ -168,7 +167,7 @@ int get_prkey(struct config *conf, struct multipath *mpp, uint64_t *prkey,
if (!strlen(mpp->wwid))
goto out;
- fd = open_file(conf->prkeys_file, &unused, PRKEYS_FILE_HEADER);
+ fd = open_file(DEFAULT_PRKEYS_FILE, &unused, PRKEYS_FILE_HEADER);
if (fd < 0)
goto out;
ret = do_prkey(fd, mpp->wwid, keystr, PRKEY_READ);
@@ -201,7 +200,7 @@ int set_prkey(struct config *conf, struct multipath *mpp, uint64_t prkey,
sa_flags &= MPATH_F_APTPL_MASK;
}
- fd = open_file(conf->prkeys_file, &can_write, PRKEYS_FILE_HEADER);
+ fd = open_file(DEFAULT_PRKEYS_FILE, &can_write, PRKEYS_FILE_HEADER);
if (fd < 0)
goto out;
if (!can_write) {
diff --git a/libmultipath/prkey.h b/libmultipath/prkey.h
index a16de106..43afd5e4 100644
--- a/libmultipath/prkey.h
+++ b/libmultipath/prkey.h
@@ -16,9 +16,8 @@
int print_reservation_key(struct strbuf *buff,
struct be64 key, uint8_t flags, int source);
int parse_prkey_flags(const char *ptr, uint64_t *prkey, uint8_t *flags);
-int set_prkey(struct config *conf, struct multipath *mpp, uint64_t prkey,
- uint8_t sa_flags);
-int get_prkey(struct config *conf, struct multipath *mpp, uint64_t *prkey,
- uint8_t *sa_flags);
+int set_prkey(struct config *conf, struct multipath *mpp,
+ uint64_t prkey, uint8_t sa_flags);
+int get_prkey(struct multipath *mpp, uint64_t *prkey, uint8_t *sa_flags);
#endif /* _PRKEY_H */
diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c
index 354e883f..44241e2a 100644
--- a/libmultipath/propsel.c
+++ b/libmultipath/propsel.c
@@ -401,8 +401,7 @@ int select_alias(struct config *conf, struct multipath * mp)
select_alias_prefix(conf, mp);
- mp->alias = get_user_friendly_alias(mp->wwid, conf->bindings_file,
- mp->alias_old, mp->alias_prefix,
+ mp->alias = get_user_friendly_alias(mp->wwid, mp->alias_old, mp->alias_prefix,
conf->bindings_read_only);
if (mp->alias && !strncmp(mp->alias, mp->alias_old, WWID_SIZE))
@@ -992,7 +991,7 @@ int select_reservation_key(struct config *conf, struct multipath *mp)
out:
if (mp->prkey_source == PRKEY_SOURCE_FILE) {
from_file = " (from prkeys file)";
- if (get_prkey(conf, mp, &prkey, &mp->sa_flags) != 0)
+ if (get_prkey(mp, &prkey, &mp->sa_flags) != 0)
put_be64(mp->reservation_key, 0);
else
put_be64(mp->reservation_key, prkey);
diff --git a/libmultipath/wwids.c b/libmultipath/wwids.c
index 89bb60ca..591cd09b 100644
--- a/libmultipath/wwids.c
+++ b/libmultipath/wwids.c
@@ -94,12 +94,8 @@ replace_wwids(vector mp)
struct multipath * mpp;
size_t len;
int ret = -1;
- struct config *conf;
- conf = get_multipath_config();
- pthread_cleanup_push(put_multipath_config, conf);
- fd = open_file(conf->wwids_file, &can_write, WWIDS_FILE_HEADER);
- pthread_cleanup_pop(1);
+ fd = open_file(DEFAULT_WWIDS_FILE, &can_write, WWIDS_FILE_HEADER);
if (fd < 0)
goto out;
@@ -200,7 +196,6 @@ remove_wwid(char *wwid) {
int len, can_write;
char *str;
int ret = -1;
- struct config *conf;
len = strlen(wwid) + 4; /* two slashes the newline and a zero byte */
str = malloc(len);
@@ -216,10 +211,7 @@ remove_wwid(char *wwid) {
goto out;
}
condlog(3, "removing line '%s' from wwids file", str);
- conf = get_multipath_config();
- pthread_cleanup_push(put_multipath_config, conf);
- fd = open_file(conf->wwids_file, &can_write, WWIDS_FILE_HEADER);
- pthread_cleanup_pop(1);
+ fd = open_file(DEFAULT_WWIDS_FILE, &can_write, WWIDS_FILE_HEADER);
if (fd < 0) {
ret = -1;
@@ -244,12 +236,8 @@ check_wwids_file(char *wwid, int write_wwid)
{
int fd, can_write, found, ret;
FILE *f;
- struct config *conf;
- conf = get_multipath_config();
- pthread_cleanup_push(put_multipath_config, conf);
- fd = open_file(conf->wwids_file, &can_write, WWIDS_FILE_HEADER);
- pthread_cleanup_pop(1);
+ fd = open_file(DEFAULT_WWIDS_FILE, &can_write, WWIDS_FILE_HEADER);
if (fd < 0)
return -1;
diff --git a/multipath/main.c b/multipath/main.c
index b91289e8..9e1c5052 100644
--- a/multipath/main.c
+++ b/multipath/main.c
@@ -856,7 +856,7 @@ main (int argc, char *argv[])
libmp_verbosity = atoi(optarg);
break;
case 'b':
- conf->bindings_file = strdup(optarg);
+ condlog(1, "option -b ignored");
break;
case 'B':
conf->bindings_read_only = 1;
diff --git a/multipath/multipath.conf.5.in b/multipath/multipath.conf.5.in
index 20df2232..d320a88f 100644
--- a/multipath/multipath.conf.5.in
+++ b/multipath/multipath.conf.5.in
@@ -794,35 +794,28 @@ The default is: \fB<unset>\fR
.
.TP
.B bindings_file
-(Deprecated) This option is deprecated, and will be removed in a future release.
-The full pathname of the binding file to be used when the user_friendly_names
-option is set.
+(Deprecated) This option is not supported any more, and will be ignored.
.RS
.TP
-The default is: \fB@STATE_DIR@/bindings\fR
+The compiled-in value is: \fB@STATE_DIR@/bindings\fR
.RE
.
.
.TP
.B wwids_file
-(Deprecated) This option is deprecated, and will be removed in a future release.
-The full pathname of the WWIDs file, which is used by multipath to keep track
-of the WWIDs for LUNs it has created multipath devices on in the past.
+(Deprecated) This option is not supported any more, and will be ignored.
.RS
.TP
-The default is: \fB@STATE_DIR@/wwids\fR
+The compiled-in value is: \fB@STATE_DIR@/wwids\fR
.RE
.
.
.TP
.B prkeys_file
-(Deprecated) This option is deprecated, and will be removed in a future release.
-The full pathname of the prkeys file, which is used by multipathd to keep
-track of the persistent reservation key used for a specific WWID, when
-\fIreservation_key\fR is set to \fBfile\fR.
+(Deprecated) This option is not supported any more, and will be ignored.
.RS
.TP
-The default is: \fB@STATE_DIR@/prkeys\fR
+The compiled-in value is: \fB@STATE_DIR@/prkeys\fR
.RE
.
.
@@ -989,6 +982,10 @@ The default is: \fB<unset>\fR
.TP
.B config_dir
(Deprecated) This option is not supported any more, and the value is ignored.
+.RS
+.TP
+The compiled-in value is: \fB@CONFIGDIR@\fR
+.RE
.
.
.TP
diff --git a/multipathd/uxlsnr.c b/multipathd/uxlsnr.c
index d1f8f234..4d6f258c 100644
--- a/multipathd/uxlsnr.c
+++ b/multipathd/uxlsnr.c
@@ -203,7 +203,6 @@ static void reset_watch(int notify_fd, struct watch_descriptors *wds,
int dir_reset = 0;
int conf_reset = 0;
int mp_reset = 0;
- char *bindings_file __attribute__((cleanup(cleanup_charp))) = NULL;
if (notify_fd == -1)
return;
@@ -221,7 +220,6 @@ static void reset_watch(int notify_fd, struct watch_descriptors *wds,
if (wds->mp_wd == -1)
mp_reset = 1;
}
- bindings_file = strdup(conf->bindings_file);
put_multipath_config(conf);
if (dir_reset) {
@@ -242,17 +240,12 @@ static void reset_watch(int notify_fd, struct watch_descriptors *wds,
if (wds->conf_wd == -1)
condlog(3, "didn't set up notifications on /etc/multipath.conf: %m");
}
- if (mp_reset && bindings_file) {
- char *slash = strrchr(bindings_file, '/');
-
- if (slash && slash > bindings_file) {
- *slash = '\0';
- wds->mp_wd = inotify_add_watch(notify_fd, bindings_file,
- IN_MOVED_TO|IN_ONLYDIR);
- if (wds->mp_wd == -1)
+ if (mp_reset) {
+ wds->mp_wd = inotify_add_watch(notify_fd, STATE_DIR,
+ IN_MOVED_TO|IN_ONLYDIR);
+ if (wds->mp_wd == -1)
condlog(3, "didn't set up notifications on %s: %m",
- bindings_file);
- }
+ STATE_DIR);
}
}
diff --git a/tests/alias.c b/tests/alias.c
index 94df36d8..f893d174 100644
--- a/tests/alias.c
+++ b/tests/alias.c
@@ -1264,10 +1264,10 @@ static void al_a(void **state)
will_return(__wrap_write, ln);
will_return(__wrap_write, strlen(BINDINGS_FILE_HEADER) + strlen(ln));
will_return(__wrap_rename, 0);
- expect_condlog(1, "updated bindings file foo");
+ expect_condlog(1, "updated bindings file " DEFAULT_BINDINGS_FILE);
expect_condlog(3, NEW_STR("MPATHa", "WWIDa"));
- alias = allocate_binding("foo", "WWIDa", 1, "MPATH");
+ alias = allocate_binding("WWIDa", 1, "MPATH");
assert_ptr_not_equal(alias, NULL);
assert_string_equal(alias, "MPATHa");
check_bindings_size(1);
@@ -1283,10 +1283,10 @@ static void al_zz(void **state)
will_return(__wrap_write, ln);
will_return(__wrap_write, strlen(BINDINGS_FILE_HEADER) + strlen(ln));
will_return(__wrap_rename, 0);
- expect_condlog(1, "updated bindings file foo");
+ expect_condlog(1, "updated bindings file " DEFAULT_BINDINGS_FILE);
expect_condlog(3, NEW_STR("MPATHzz", "WWIDzz"));
- alias = allocate_binding("foo", "WWIDzz", 26*26 + 26, "MPATH");
+ alias = allocate_binding("WWIDzz", 26*26 + 26, "MPATH");
assert_ptr_not_equal(alias, NULL);
assert_string_equal(alias, "MPATHzz");
check_bindings_size(1);
@@ -1298,7 +1298,7 @@ static void al_0(void **state)
char *alias;
expect_condlog(0, "allocate_binding: cannot allocate new binding for id 0\n");
- alias = allocate_binding(0, "WWIDa", 0, "MPATH");
+ alias = allocate_binding("WWIDa", 0, "MPATH");
assert_ptr_equal(alias, NULL);
check_bindings_size(0);
}
@@ -1308,7 +1308,7 @@ static void al_m2(void **state)
char *alias;
expect_condlog(0, "allocate_binding: cannot allocate new binding for id -2\n");
- alias = allocate_binding(0, "WWIDa", -2, "MPATH");
+ alias = allocate_binding("WWIDa", -2, "MPATH");
assert_ptr_equal(alias, NULL);
check_bindings_size(0);
}
@@ -1325,10 +1325,10 @@ static void al_write_partial(void **state)
will_return(__wrap_write, ln + sizeof(ln) - 2);
will_return(__wrap_write, 1);
will_return(__wrap_rename, 0);
- expect_condlog(1, "updated bindings file foo");
+ expect_condlog(1, "updated bindings file " DEFAULT_BINDINGS_FILE);
expect_condlog(3, "Created new binding [MPATHa] for WWID [WWIDa]\n");
- alias = allocate_binding("foo", "WWIDa", 1, "MPATH");
+ alias = allocate_binding("WWIDa", 1, "MPATH");
assert_ptr_not_equal(alias, NULL);
assert_string_equal(alias, "MPATHa");
check_bindings_size(1);
@@ -1350,7 +1350,7 @@ static void al_write_short(void **state)
expect_condlog(1, "failed to write new bindings file");
expect_condlog(1, "allocate_binding: deleting binding MPATHa for WWIDa");
- alias = allocate_binding("foo", "WWIDa", 1, "MPATH");
+ alias = allocate_binding("WWIDa", 1, "MPATH");
assert_ptr_equal(alias, NULL);
check_bindings_size(0);
}
@@ -1366,7 +1366,7 @@ static void al_write_err(void **state)
expect_condlog(1, "failed to write new bindings file");
expect_condlog(1, "allocate_binding: deleting binding MPATHa for WWIDa");
- alias = allocate_binding("foo", "WWIDa", 1, "MPATH");
+ alias = allocate_binding("WWIDa", 1, "MPATH");
assert_ptr_equal(alias, NULL);
check_bindings_size(0);
}
@@ -1383,7 +1383,7 @@ static void al_rename_err(void **state)
expect_condlog(0, "update_bindings_file: rename: Read-only file system");
expect_condlog(1, "allocate_binding: deleting binding MPATHa for WWIDa");
- alias = allocate_binding("foo", "WWIDa", 1, "MPATH");
+ alias = allocate_binding("WWIDa", 1, "MPATH");
assert_ptr_equal(alias, NULL);
check_bindings_size(0);
}
@@ -1415,7 +1415,7 @@ static int test_allocate_binding(void)
strlen(BINDINGS_FILE_HEADER) + (len) + strlen(ln)); \
will_return(__wrap_rename, err); \
if (err == 0) { \
- expect_condlog(1, "updated bindings file x\n"); \
+ expect_condlog(1, "updated bindings file " DEFAULT_BINDINGS_FILE); \
expect_condlog(3, NEW_STR(alias, wwid)); \
} else { \
expect_condlog(0, "update_bindings_file: rename: " msg "\n"); \
@@ -1441,7 +1441,7 @@ static void gufa_empty_new_rw(void **state) {
expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
mock_allocate_binding("MPATHa", "WWID0");
- alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", false);
+ alias = get_user_friendly_alias("WWID0", "", "MPATH", false);
assert_string_equal(alias, "MPATHa");
free(alias);
}
@@ -1454,7 +1454,7 @@ static void gufa_empty_new_ro_1(void **state) {
expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
mock_allocate_binding_err("MPATHa", "WWID0", -EROFS, "Read-only file system");
- alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", false);
+ alias = get_user_friendly_alias("WWID0", "", "MPATH", false);
assert_ptr_equal(alias, NULL);
}
@@ -1465,7 +1465,7 @@ static void gufa_empty_new_ro_2(void **state) {
expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
mock_unused_alias("MPATHa");
- alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", true);
+ alias = get_user_friendly_alias("WWID0", "", "MPATH", true);
assert_ptr_equal(alias, NULL);
}
@@ -1477,7 +1477,7 @@ static void gufa_match_a_unused(void **state) {
mock_unused_alias("MPATHa");
expect_condlog(3, EXISTING_STR("MPATHa", "WWID0"));
- alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", true);
+ alias = get_user_friendly_alias("WWID0", "", "MPATH", true);
assert_string_equal(alias, "MPATHa");
free(alias);
}
@@ -1490,7 +1490,7 @@ static void gufa_match_a_self(void **state) {
mock_self_alias("MPATHa", "WWID0");
expect_condlog(3, EXISTING_STR("MPATHa", "WWID0"));
- alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", true);
+ alias = get_user_friendly_alias("WWID0", "", "MPATH", true);
assert_string_equal(alias, "MPATHa");
free(alias);
}
@@ -1503,7 +1503,7 @@ static void gufa_match_a_used(void **state) {
expect_condlog(3, FOUND_STR("MPATHa", "WWID0"));
mock_used_alias("MPATHa", "WWID0");
- alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", true);
+ alias = get_user_friendly_alias("WWID0", "", "MPATH", true);
assert_ptr_equal(alias, NULL);
}
@@ -1518,7 +1518,7 @@ static void gufa_nomatch_a_c(void **state) {
mock_allocate_binding_len("MPATHb", "WWID1", strlen(bindings));
- alias = get_user_friendly_alias("WWID1", "x", "", "MPATH", false);
+ alias = get_user_friendly_alias("WWID1", "", "MPATH", false);
assert_string_equal(alias, "MPATHb");
free(alias);
}
@@ -1534,7 +1534,7 @@ static void gufa_nomatch_c_a(void **state) {
mock_allocate_binding_len("MPATHb", "WWID1", sizeof(bindings) - 1);
- alias = get_user_friendly_alias("WWID1", "x", "", "MPATH", false);
+ alias = get_user_friendly_alias("WWID1", "", "MPATH", false);
assert_string_equal(alias, "MPATHb");
free(alias);
}
@@ -1550,7 +1550,7 @@ static void gufa_nomatch_c_b(void **state) {
mock_allocate_binding_len("MPATHa", "WWID0", sizeof(bindings) - 1);
- alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", false);
+ alias = get_user_friendly_alias("WWID0", "", "MPATH", false);
assert_string_equal(alias, "MPATHa");
free(alias);
}
@@ -1567,7 +1567,7 @@ static void gufa_nomatch_c_b_used(void **state) {
mock_allocate_binding_len("MPATHd", "WWID4", sizeof(bindings) - 1);
- alias = get_user_friendly_alias("WWID4", "x", "", "MPATH", false);
+ alias = get_user_friendly_alias("WWID4", "", "MPATH", false);
assert_string_equal(alias, "MPATHd");
free(alias);
}
@@ -1584,7 +1584,7 @@ static void gufa_nomatch_b_f_a(void **state) {
mock_allocate_binding_len("MPATHc", "WWID7", sizeof(bindings) - 1);
- alias = get_user_friendly_alias("WWID7", "x", "", "MPATH", false);
+ alias = get_user_friendly_alias("WWID7", "", "MPATH", false);
assert_string_equal(alias, "MPATHc");
free(alias);
}
@@ -1599,7 +1599,7 @@ static void gufa_nomatch_b_aa_a(void **state) {
mock_unused_alias("MPATHab");
mock_allocate_binding_len("MPATHab", "WWID28", get_strbuf_len(&buf));
- alias = get_user_friendly_alias("WWID28", "x", "", "MPATH", false);
+ alias = get_user_friendly_alias("WWID28", "", "MPATH", false);
assert_string_equal(alias, "MPATHab");
free(alias);
}
@@ -1616,7 +1616,7 @@ static void gufa_nomatch_b_f_a_sorted(void **state) {
mock_allocate_binding_len("MPATHc", "WWID7", sizeof(bindings) - 1);
- alias = get_user_friendly_alias("WWID7", "x", "", "MPATH", false);
+ alias = get_user_friendly_alias("WWID7", "", "MPATH", false);
assert_string_equal(alias, "MPATHc");
free(alias);
}
@@ -1632,7 +1632,7 @@ static void gufa_old_empty(void **state) {
mock_allocate_binding("MPATHz", "WWID0");
expect_condlog(2, ALLOC_STR("MPATHz", "WWID0"));
- alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false);
+ alias = get_user_friendly_alias("WWID0", "MPATHz", "MPATH", false);
assert_string_equal(alias, "MPATHz");
free(alias);
}
@@ -1644,7 +1644,7 @@ static void gufa_old_match(void **state) {
"MPATHz WWID0");
expect_condlog(3, FOUND_ALIAS_STR("MPATHz", "WWID0"));
- alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false);
+ alias = get_user_friendly_alias("WWID0", "MPATHz", "MPATH", false);
assert_string_equal(alias, "MPATHz");
free(alias);
}
@@ -1661,7 +1661,7 @@ static void gufa_old_match_other(void **state) {
mock_allocate_binding_len("MPATHa", "WWID0", sizeof(bindings) - 1);
- alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false);
+ alias = get_user_friendly_alias("WWID0", "MPATHz", "MPATH", false);
assert_string_equal(alias, "MPATHa");
free(alias);
}
@@ -1678,7 +1678,7 @@ static void gufa_old_match_other_used(void **state) {
mock_unused_alias("MPATHb");
mock_allocate_binding_len("MPATHb", "WWID0", sizeof(bindings) - 1);
- alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false);
+ alias = get_user_friendly_alias("WWID0", "MPATHz", "MPATH", false);
assert_string_equal(alias, "MPATHb");
free(alias);
}
@@ -1695,7 +1695,7 @@ static void gufa_old_match_other_wwidmatch(void **state) {
mock_unused_alias("MPATHc");
expect_condlog(3, EXISTING_STR("MPATHc", "WWID2"));
- alias = get_user_friendly_alias("WWID2", "x", "MPATHz", "MPATH", false);
+ alias = get_user_friendly_alias("WWID2", "MPATHz", "MPATH", false);
assert_string_equal(alias, "MPATHc");
free(alias);
}
@@ -1711,7 +1711,7 @@ static void gufa_old_match_other_wwidmatch_used(void **state) {
expect_condlog(3, FOUND_STR("MPATHc", "WWID2"));
mock_used_alias("MPATHc", "WWID2");
- alias = get_user_friendly_alias("WWID2", "x", "MPATHz", "MPATH", false);
+ alias = get_user_friendly_alias("WWID2", "MPATHz", "MPATH", false);
assert_ptr_equal(alias, NULL);
}
@@ -1725,7 +1725,7 @@ static void gufa_old_nomatch_wwidmatch(void **state) {
mock_unused_alias("MPATHa");
expect_condlog(3, EXISTING_STR("MPATHa", "WWID0"));
- alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false);
+ alias = get_user_friendly_alias("WWID0", "MPATHz", "MPATH", false);
assert_string_equal(alias, "MPATHa");
free(alias);
}
@@ -1739,7 +1739,7 @@ static void gufa_old_nomatch_wwidmatch_used(void **state) {
expect_condlog(3, FOUND_STR("MPATHa", "WWID0"));
mock_used_alias("MPATHa", "WWID0");
- alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false);
+ alias = get_user_friendly_alias("WWID0", "MPATHz", "MPATH", false);
assert_ptr_equal(alias, NULL);
}
@@ -1754,7 +1754,7 @@ static void gufa_old_nomatch_nowwidmatch(void **state) {
mock_allocate_binding_len("MPATHz", "WWID0", sizeof(bindings) - 1);
expect_condlog(2, ALLOC_STR("MPATHz", "WWID0"));
- alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false);
+ alias = get_user_friendly_alias("WWID0", "MPATHz", "MPATH", false);
assert_string_equal(alias, "MPATHz");
free(alias);
}

View File

@ -0,0 +1,158 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Tue, 12 Sep 2023 11:54:47 +0200
Subject: [PATCH] libmultipath: avoid -Warray-bounds error in uatomic
operations
The use of uatomic_xchg() in alias.c causes a -Warray-bounds error
on distributions using gcc 12, such as Fedora 37. This is a similar
error to 2534c4f ("libmultipath: avoid -Warray-bounds error with gcc
12 and musl libc"). This happens only with liburcu 0.13 and earlier,
and only with certain gcc versions. See liburcu commit 835b9ab
("Fix: x86 and s390 uatomic: __hp() macro warning with gcc 11").
Enhance the fix for 2534c4f by a adding a workaround for uatomic_xchg(),
and introduce the macro URCU_VERSION (originally only used for multipathd)
globally.
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
Makefile.inc | 2 +-
create-config.mk | 5 +++++
libmultipath/alias.c | 5 +++--
libmultipath/lock.h | 21 +++++++++++++--------
multipathd/Makefile | 2 --
5 files changed, 22 insertions(+), 13 deletions(-)
diff --git a/Makefile.inc b/Makefile.inc
index 6e384e68..04bfa56e 100644
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -95,7 +95,7 @@ OPTFLAGS := -O2 -g $(STACKPROT) --param=ssp-buffer-size=4
WARNFLAGS := -Werror -Wall -Wextra -Wformat=2 $(WFORMATOVERFLOW) -Werror=implicit-int \
-Werror=implicit-function-declaration -Werror=format-security \
$(WNOCLOBBERED) -Werror=cast-qual $(ERROR_DISCARDED_QUALIFIERS) $(W_URCU_TYPE_LIMITS)
-CPPFLAGS := $(FORTIFY_OPT) $(CPPFLAGS) \
+CPPFLAGS := $(FORTIFY_OPT) $(CPPFLAGS) $(D_URCU_VERSION) \
-DBIN_DIR=\"$(bindir)\" -DMULTIPATH_DIR=\"$(plugindir)\" \
-DRUNTIME_DIR=\"$(runtimedir)\" -DCONFIG_DIR=\"$(configdir)\" \
-DDEFAULT_CONFIGFILE=\"$(configfile)\" -DSTATE_DIR=\"$(statedir)\" \
diff --git a/create-config.mk b/create-config.mk
index d1255971..4d318b96 100644
--- a/create-config.mk
+++ b/create-config.mk
@@ -73,6 +73,10 @@ TEST_URCU_TYPE_LIMITS = $(shell \
$(CC) -c -Werror=type-limits -o /dev/null -xc - 2>/dev/null \
|| echo -Wno-type-limits )
+URCU_VERSION = $(shell \
+ $(PKG_CONFIG) --modversion liburcu 2>/dev/null | \
+ awk -F. '{ printf("-DURCU_VERSION=0x%06x", 256 * ( 256 * $$1 + $$2) + $$3); }')
+
DEFINES :=
ifneq ($(call check_func,dm_task_no_flush,$(devmapper_incdir)/libdevmapper.h),0)
@@ -168,6 +172,7 @@ $(TOPDIR)/config.mk: $(multipathdir)/autoconfig.h
@echo creating $@
@echo "FPIN_SUPPORT := $(FPIN_SUPPORT)" >$@
@echo "FORTIFY_OPT := $(FORTIFY_OPT)" >>$@
+ @echo "D_URCU_VERSION := $(call URCU_VERSION)" >>$@
@echo "SYSTEMD := $(SYSTEMD)" >>$@
@echo "ANA_SUPPORT := $(ANA_SUPPORT)" >>$@
@echo "STACKPROT := $(call TEST_CC_OPTION,-fstack-protector-strong,-fstack-protector)" >>$@
diff --git a/libmultipath/alias.c b/libmultipath/alias.c
index e5d3f151..74431f3f 100644
--- a/libmultipath/alias.c
+++ b/libmultipath/alias.c
@@ -24,6 +24,7 @@
#include "devmapper.h"
#include "strbuf.h"
#include "time-util.h"
+#include "lock.h"
/*
* significant parts of this file were taken from iscsi-bindings.c of the
@@ -300,7 +301,7 @@ void handle_bindings_file_inotify(const struct inotify_event *event)
pthread_mutex_unlock(&timestamp_mutex);
if (changed) {
- uatomic_xchg(&bindings_file_changed, 1);
+ uatomic_xchg_int(&bindings_file_changed, 1);
condlog(3, "%s: bindings file must be re-read, new timestamp: %ld.%06ld",
__func__, (long)ts.tv_sec, (long)ts.tv_nsec / 1000);
} else
@@ -775,7 +776,7 @@ static int _read_bindings_file(const struct config *conf, Bindings *bindings,
int rc = 0, ret, fd;
FILE *file;
struct stat st;
- int has_changed = uatomic_xchg(&bindings_file_changed, 0);
+ int has_changed = uatomic_xchg_int(&bindings_file_changed, 0);
if (!force) {
if (!has_changed) {
diff --git a/libmultipath/lock.h b/libmultipath/lock.h
index 9814be76..ac80d1d8 100644
--- a/libmultipath/lock.h
+++ b/libmultipath/lock.h
@@ -13,15 +13,20 @@ struct mutex_lock {
int waiters; /* uatomic access only */
};
-#if !defined(__GLIBC__) && defined(__GNUC__) && __GNUC__ == 12
+static inline void init_lock(struct mutex_lock *a)
+{
+ pthread_mutex_init(&a->mutex, NULL);
+ uatomic_set(&a->waiters, 0);
+}
+
+#if defined(__GNUC__) && __GNUC__ == 12 && URCU_VERSION < 0xe00
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Warray-bounds"
#endif
-static inline void init_lock(struct mutex_lock *a)
+static inline int uatomic_xchg_int(int *ptr, int val)
{
- pthread_mutex_init(&a->mutex, NULL);
- uatomic_set(&a->waiters, 0);
+ return uatomic_xchg(ptr, val);
}
static inline void lock(struct mutex_lock *a)
@@ -31,6 +36,10 @@ static inline void lock(struct mutex_lock *a)
uatomic_dec(&a->waiters);
}
+#if defined(__GNUC__) && __GNUC__ == 12 && URCU_VERSION < 0xe00
+#pragma GCC diagnostic pop
+#endif
+
static inline int trylock(struct mutex_lock *a)
{
return pthread_mutex_trylock(&a->mutex);
@@ -51,10 +60,6 @@ static inline bool lock_has_waiters(struct mutex_lock *a)
return (uatomic_read(&a->waiters) > 0);
}
-#if !defined(__GLIBC__) && defined(__GNUC__) && __GNUC__ == 12
-#pragma GCC diagnostic pop
-#endif
-
#define lock_cleanup_pop(a) pthread_cleanup_pop(1)
void cleanup_lock (void * data);
diff --git a/multipathd/Makefile b/multipathd/Makefile
index cdba3db1..0ba6ecb7 100644
--- a/multipathd/Makefile
+++ b/multipathd/Makefile
@@ -5,8 +5,6 @@ CLI := multipathc
MANPAGES := multipathd.8
CPPFLAGS += -I$(multipathdir) -I$(mpathutildir) -I$(mpathpersistdir) -I$(mpathcmddir) -I$(thirdpartydir) \
- $(shell $(PKG_CONFIG) --modversion liburcu 2>/dev/null | \
- awk -F. '{ printf("-DURCU_VERSION=0x%06x", 256 * ( 256 * $$1 + $$2) + $$3); }') \
-DBINDIR='"$(bindir)"' $(SYSTEMD_CPPFLAGS)
#

View File

@ -0,0 +1,52 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Xose Vazquez Perez <xose.vazquez@gmail.com>
Date: Fri, 15 Sep 2023 22:22:06 +0200
Subject: [PATCH] multipath-tools: fix spelling
Cc: Martin Wilck <mwilck@suse.com>
Cc: Benjamin Marzinski <bmarzins@redhat.com>
Cc: Christophe Varoqui <christophe.varoqui@opensvc.com>
Cc: DM-DEVEL ML <dm-devel@redhat.com>
Signed-off-by: Xose Vazquez Perez <xose.vazquez@gmail.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
README.md | 4 ++--
multipath/multipath.conf.5.in | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/README.md b/README.md
index 679e55bf..524c9fb1 100644
--- a/README.md
+++ b/README.md
@@ -92,7 +92,7 @@ The following variables can be passed to the `make` command line:
The default is `$(prefix)/$(LIB)/multipath`, where `$(LIB)` is `lib64` on
systems that have `/lib64`, and `lib` otherwise.
* `configfile="/some/path`": The path to the main configuration file.
- The defalt is `$(etc_prefix)/etc/multipath.conf`.
+ The default is `$(etc_prefix)/etc/multipath.conf`.
* `configdir="/some/path"` : directory to search for additional configuration files.
This used to be the run-time option `config_dir` in earlier versions.
The default is `$(etc_prefix)/etc/multipath/conf.d`.
@@ -141,7 +141,7 @@ The following variables can be passed to the `make` command line:
found on the build system, and `/lib` otherwise.
The options `configdir`, `plugindir`, `configfile`, and `statedir` above can
-be used for setting indvidual paths where the `prefix` variables don't provide
+be used for setting individual paths where the `prefix` variables don't provide
sufficient control. See `Makefile.inc` for even more fine-grained control.
[^systemd]: Some systemd installations use separate `prefix` and `rootprefix`.
diff --git a/multipath/multipath.conf.5.in b/multipath/multipath.conf.5.in
index d320a88f..226d0019 100644
--- a/multipath/multipath.conf.5.in
+++ b/multipath/multipath.conf.5.in
@@ -36,7 +36,7 @@ Files ending in \fI.conf\fR in this directory are read
in alphabetical order, after reading \fI@CONFIGFILE@\fR.
They use the same syntax as \fI@CONFIGFILE@\fR itself,
and support all sections and keywords. If a keyword occurs in the same section
-in multiple files, the last occurence will take precedence over all others.
+in multiple files, the last occurrence will take precedence over all others.
.
.
.\" ----------------------------------------------------------------------------

View File

@ -0,0 +1,300 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Muneendra <muneendra.kumar@broadcom.com>
Date: Wed, 20 Sep 2023 20:41:15 -0700
Subject: [PATCH] multipathd: Added support to handle FPIN-Li events for
FC-NVMe
This patch adds the support to handle FPIN-Li for FC-NVMe.
On receiving the FPIN-Li events this patch moves the devices paths
which are affected due to link integrity to marginal path groups.
The paths which are set to marginal path group will be unset
on receiving the RSCN events
(mwilck: minor compile fix for 32-bit architectures)
Signed-off-by: Muneendra <muneendra.kumar@broadcom.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
---
multipathd/fpin_handlers.c | 206 +++++++++++++++++++++++++++----------
1 file changed, 151 insertions(+), 55 deletions(-)
diff --git a/multipathd/fpin_handlers.c b/multipathd/fpin_handlers.c
index aa0f63c9..be087ca0 100644
--- a/multipathd/fpin_handlers.c
+++ b/multipathd/fpin_handlers.c
@@ -60,18 +60,15 @@ static void _udev_device_unref(void *p)
/*set/unset the path state to marginal*/
-static int fpin_set_pathstate(struct path *pp, bool set)
+static void fpin_set_pathstate(struct path *pp, bool set)
{
const char *action = set ? "set" : "unset";
- if (!pp || !pp->mpp || !pp->mpp->alias)
- return -1;
-
- condlog(3, "\n%s: %s marginal path %s (fpin)",
- action, pp->mpp->alias, pp->dev_t);
+ condlog(3, "%s: %s marginal path %s (fpin)",
+ pp->mpp ? pp->mpp->alias : "orphan", action, pp->dev_t);
pp->marginal = set;
- pp->mpp->fpin_must_reload = true;
- return 0;
+ if (pp->mpp)
+ pp->mpp->fpin_must_reload = true;
}
/* This will unset marginal state of a device*/
@@ -82,14 +79,14 @@ static void fpin_path_unsetmarginal(char *devname, struct vectors *vecs)
pp = find_path_by_dev(vecs->pathvec, devname);
if (!pp)
pp = find_path_by_devt(vecs->pathvec, devname);
-
- fpin_set_pathstate(pp, false);
+ if (pp)
+ fpin_set_pathstate(pp, false);
}
/*This will set the marginal state of a device*/
-static int fpin_path_setmarginal(struct path *pp)
+static void fpin_path_setmarginal(struct path *pp)
{
- return fpin_set_pathstate(pp, true);
+ fpin_set_pathstate(pp, true);
}
/* Unsets all the devices in the list from marginal state */
@@ -183,8 +180,8 @@ static void fpin_set_rport_marginal(struct udev_device *rport_dev)
udev_device_get_syspath(rport_dev));
}
-/*Add the marginal devices info into the list*/
-static void
+/*Add the marginal devices info into the list and return 0 on success*/
+static int
fpin_add_marginal_dev_info(uint32_t host_num, char *devname)
{
struct marginal_dev_list *newdev = NULL;
@@ -199,65 +196,160 @@ fpin_add_marginal_dev_info(uint32_t host_num, char *devname)
list_add_tail(&(newdev->node),
&fpin_li_marginal_dev_list_head);
pthread_mutex_unlock(&fpin_li_marginal_dev_mutex);
- }
+ } else
+ return -ENOMEM;
+ return 0;
}
/*
- * This function goes through the vecs->pathvec, and for
- * each path, check that the host number,
- * the target WWPN associated with the path matches
- * with the els wwpn and sets the path and port state to
+ * This function compares Transport Address Controller Port pn,
+ * Host Transport Address Controller Port pn with the els wwpn ,attached_wwpn
+ * and return 1 (match) or 0 (no match) or a negative error code
+ */
+static int extract_nvme_addresses_chk_path_pwwn(const char *address,
+ uint64_t els_wwpn, uint64_t els_attached_wwpn)
+
+{
+ uint64_t traddr;
+ uint64_t host_traddr;
+
+ /*
+ * Find the position of "traddr=" and "host_traddr="
+ * and the address will be in the below format
+ * "traddr=nn-0x200400110dff9400:pn-0x200400110dff9400,
+ * host_traddr=nn-0x200400110dff9400:pn-0x200400110dff9400"
+ */
+ const char *traddr_start = strstr(address, "traddr=");
+ const char *host_traddr_start = strstr(address, "host_traddr=");
+
+ if (!traddr_start || !host_traddr_start)
+ return -EINVAL;
+
+ /* Extract traddr pn */
+ if (sscanf(traddr_start, "traddr=nn-%*[^:]:pn-%" SCNx64, &traddr) != 1)
+ return -EINVAL;
+
+ /* Extract host_traddr pn*/
+ if (sscanf(host_traddr_start, "host_traddr=nn-%*[^:]:pn-%" SCNx64,
+ &host_traddr) != 1)
+ return -EINVAL;
+ condlog(4, "traddr 0x%" PRIx64 " hosttraddr 0x%" PRIx64 " els_wwpn 0x%"
+ PRIx64" els_host_traddr 0x%" PRIx64,
+ traddr, host_traddr,
+ els_wwpn, els_attached_wwpn);
+ if ((host_traddr == els_attached_wwpn) && (traddr == els_wwpn))
+ return 1;
+ return 0;
+}
+
+/*
+ * This function check that the Transport Address Controller Port pn,
+ * Host Transport Address Controller Port pn associated with the path matches
+ * with the els wwpn ,attached_wwpn and sets the path state to
* Marginal
*/
-static int fpin_chk_wwn_setpath_marginal(uint16_t host_num, struct vectors *vecs,
+static void fpin_check_set_nvme_path_marginal(uint16_t host_num, struct path *pp,
+ uint64_t els_wwpn, uint64_t attached_wwpn)
+{
+ struct udev_device *ctl = NULL;
+ const char *address = NULL;
+ int ret = 0;
+
+ ctl = udev_device_get_parent_with_subsystem_devtype(pp->udev, "nvme", NULL);
+ if (ctl == NULL) {
+ condlog(2, "%s: No parent device for ", pp->dev);
+ return;
+ }
+ address = udev_device_get_sysattr_value(ctl, "address");
+ if (!address) {
+ condlog(2, "%s: unable to get the address ", pp->dev);
+ return;
+ }
+ condlog(4, "\n address %s: dev :%s\n", address, pp->dev);
+ ret = extract_nvme_addresses_chk_path_pwwn(address, els_wwpn, attached_wwpn);
+ if (ret <= 0)
+ return;
+ ret = fpin_add_marginal_dev_info(host_num, pp->dev);
+ if (ret < 0)
+ return;
+ fpin_path_setmarginal(pp);
+}
+
+/*
+ * This function check the host number, the target WWPN
+ * associated with the path matches with the els wwpn and
+ * sets the path and port state to Marginal
+ */
+static void fpin_check_set_scsi_path_marginal(uint16_t host_num, struct path *pp,
uint64_t els_wwpn)
{
- struct path *pp;
- struct multipath *mpp;
- int i, k;
char rport_id[42];
const char *value = NULL;
struct udev_device *rport_dev = NULL;
uint64_t wwpn;
int ret = 0;
+ sprintf(rport_id, "rport-%d:%d-%d",
+ pp->sg_id.host_no, pp->sg_id.channel, pp->sg_id.transport_id);
+ rport_dev = udev_device_new_from_subsystem_sysname(udev,
+ "fc_remote_ports", rport_id);
+ if (!rport_dev) {
+ condlog(2, "%s: No fc_remote_port device for '%s'", pp->dev,
+ rport_id);
+ return;
+ }
+ pthread_cleanup_push(_udev_device_unref, rport_dev);
+ value = udev_device_get_sysattr_value(rport_dev, "port_name");
+ if (!value)
+ goto unref;
+
+ wwpn = strtol(value, NULL, 16);
+ /*
+ * If the port wwpn matches sets the path and port state
+ * to marginal
+ */
+ if (wwpn == els_wwpn) {
+ ret = fpin_add_marginal_dev_info(host_num, pp->dev);
+ if (ret < 0)
+ goto unref;
+ fpin_path_setmarginal(pp);
+ fpin_set_rport_marginal(rport_dev);
+ }
+unref:
+ pthread_cleanup_pop(1);
+ return;
+
+}
+
+/*
+ * This function goes through the vecs->pathvec, and for
+ * each path, it checks and sets the path state to marginal
+ * if the path's associated port wwpn ,hostnum matches with
+ * els wwnpn ,attached_wwpn
+ */
+static int fpin_chk_wwn_setpath_marginal(uint16_t host_num, struct vectors *vecs,
+ uint64_t els_wwpn, uint64_t attached_wwpn)
+{
+ struct path *pp;
+ struct multipath *mpp;
+ int i, k;
+ int ret = 0;
pthread_cleanup_push(cleanup_lock, &vecs->lock);
lock(&vecs->lock);
pthread_testcancel();
vector_foreach_slot(vecs->pathvec, pp, k) {
- /* Checks the host number and also for the SCSI FCP */
- if (pp->bus != SYSFS_BUS_SCSI || pp->sg_id.proto_id != SCSI_PROTOCOL_FCP || host_num != pp->sg_id.host_no)
+ if (!pp->mpp)
continue;
- sprintf(rport_id, "rport-%d:%d-%d",
- pp->sg_id.host_no, pp->sg_id.channel, pp->sg_id.transport_id);
- rport_dev = udev_device_new_from_subsystem_sysname(udev,
- "fc_remote_ports", rport_id);
- if (!rport_dev) {
- condlog(2, "%s: No fc_remote_port device for '%s'", pp->dev,
- rport_id);
- continue;
- }
- pthread_cleanup_push(_udev_device_unref, rport_dev);
- value = udev_device_get_sysattr_value(rport_dev, "port_name");
- if (!value)
- goto unref;
-
- if (value)
- wwpn = strtol(value, NULL, 16);
- /*
- * If the port wwpn matches sets the path and port state
- * to marginal
- */
- if (wwpn == els_wwpn) {
- ret = fpin_path_setmarginal(pp);
- if (ret < 0)
- goto unref;
- fpin_set_rport_marginal(rport_dev);
- fpin_add_marginal_dev_info(host_num, pp->dev);
+ /*checks if the bus type is nvme and the protocol is FC-NVMe*/
+ if ((pp->bus == SYSFS_BUS_NVME) && (pp->sg_id.proto_id == NVME_PROTOCOL_FC)) {
+ fpin_check_set_nvme_path_marginal(host_num, pp, els_wwpn, attached_wwpn);
+ } else if ((pp->bus == SYSFS_BUS_SCSI) &&
+ (pp->sg_id.proto_id == SCSI_PROTOCOL_FCP) &&
+ (host_num == pp->sg_id.host_no)) {
+ /* Checks the host number and also for the SCSI FCP */
+ fpin_check_set_scsi_path_marginal(host_num, pp, els_wwpn);
}
-unref:
- pthread_cleanup_pop(1);
}
/* walk backwards because reload_and_sync_map() can remove mpp */
vector_foreach_slot_backwards(vecs->mpvec, mpp, i) {
@@ -286,14 +378,18 @@ fpin_parse_li_els_setpath_marginal(uint16_t host_num, struct fc_tlv_desc *tlv,
struct fc_fn_li_desc *li_desc = (struct fc_fn_li_desc *)tlv;
int count = 0;
int ret = 0;
+ uint64_t attached_wwpn;
/* Update the wwn to list */
wwn_count = be32_to_cpu(li_desc->pname_count);
- condlog(4, "Got wwn count as %d\n", wwn_count);
+ attached_wwpn = be64_to_cpu(li_desc->attached_wwpn);
+ condlog(4, "Got wwn count as %d detecting wwn 0x%" PRIx64
+ " attached_wwpn 0x%" PRIx64 "\n",
+ wwn_count, be64_to_cpu(li_desc->detecting_wwpn), attached_wwpn);
for (iter = 0; iter < wwn_count; iter++) {
wwpn = be64_to_cpu(li_desc->pname_list[iter]);
- ret = fpin_chk_wwn_setpath_marginal(host_num, vecs, wwpn);
+ ret = fpin_chk_wwn_setpath_marginal(host_num, vecs, wwpn, attached_wwpn);
if (ret < 0)
condlog(2, "failed to set the path marginal associated with wwpn: 0x%" PRIx64 "\n", wwpn);

View File

@ -15,7 +15,7 @@ Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/Makefile.inc b/Makefile.inc
index 2e25d2ea..540e1dfc 100644
index 04bfa56e..62d3d5cc 100644
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -34,9 +34,9 @@ endif
@ -27,9 +27,9 @@ index 2e25d2ea..540e1dfc 100644
# Prefix for non-essential libraries (libdmmp)
-usr_prefix := $(prefix)
+usr_prefix := $(prefix)/usr
# Prefix for configfuration files (multipath.conf)
etc_prefix := $(prefix)
# Where to install systemd-related files. systemd is usually installed under /usr
# Note: some systemd installations use separate "prefix" and "rootprefix".
# In this case, override only unitdir to use systemd's "rootprefix" instead of $(systemd_prefix)
diff --git a/kpartx/kpartx.rules b/kpartx/kpartx.rules
index 1969dee0..d2b28233 100644
--- a/kpartx/kpartx.rules
@ -43,10 +43,10 @@ index 1969dee0..d2b28233 100644
LABEL="kpartx_end"
diff --git a/multipath/Makefile b/multipath/Makefile
index 73db991a..b3c2cc81 100644
index 68cb5ce7..f70e64ec 100644
--- a/multipath/Makefile
+++ b/multipath/Makefile
@@ -24,7 +24,7 @@ install:
@@ -26,7 +26,7 @@ install:
$(Q)$(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)/
$(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(udevrulesdir)
$(Q)$(INSTALL_PROGRAM) -m 644 11-dm-mpath.rules $(DESTDIR)$(udevrulesdir)
@ -55,7 +55,7 @@ index 73db991a..b3c2cc81 100644
$(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(modulesloaddir)
$(Q)$(INSTALL_PROGRAM) -m 644 modules-load.conf $(DESTDIR)$(modulesloaddir)/multipath.conf
$(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(tmpfilesdir)
@@ -44,7 +44,7 @@ uninstall:
@@ -46,7 +46,7 @@ uninstall:
$(Q)$(RM) $(DESTDIR)$(udevrulesdir)/11-dm-mpath.rules
$(Q)$(RM) $(DESTDIR)$(modulesloaddir)/multipath.conf
$(Q)$(RM) $(DESTDIR)$(modulesloaddir)/scsi_dh.conf
@ -63,4 +63,4 @@ index 73db991a..b3c2cc81 100644
+ $(Q)$(RM) $(DESTDIR)$(libudevdir)/rules.d/62-multipath.rules
$(Q)$(RM) $(DESTDIR)$(mandir)/man8/$(EXEC).8
$(Q)$(RM) $(DESTDIR)$(mandir)/man5/$(EXEC).conf.5
$(Q)$(RM) $(DESTDIR)$(tmpfilesdir)/multipath.conf

View File

@ -13,26 +13,25 @@ it.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/blacklist.c | 6 ++----
multipath/multipath.conf.5 | 11 ++++++-----
libmultipath/blacklist.c | 5 ++---
multipath/multipath.conf.5.in | 11 ++++++-----
tests/blacklist.c | 7 ++-----
3 files changed, 10 insertions(+), 14 deletions(-)
3 files changed, 10 insertions(+), 13 deletions(-)
diff --git a/libmultipath/blacklist.c b/libmultipath/blacklist.c
index 8d15d2ea..eff690fd 100644
index 75100b20..0b212078 100644
--- a/libmultipath/blacklist.c
+++ b/libmultipath/blacklist.c
@@ -201,9 +201,6 @@ setup_default_blist (struct config * conf)
if (store_ble(conf->blist_devnode, "!^(sd[a-z]|dasd[a-z]|nvme[0-9])", ORIGIN_DEFAULT))
@@ -230,8 +230,6 @@ setup_default_blist (struct config * conf)
ORIGIN_DEFAULT))
return 1;
}
- if (store_ble(conf->elist_property, "(SCSI_IDENT_|ID_WWN)", ORIGIN_DEFAULT))
- return 1;
-
vector_foreach_slot (conf->hwtable, hwe, i) {
if (hwe->bl_product) {
if (find_blacklist_device(conf->blist_device,
@@ -409,7 +406,8 @@ filter_property(const struct config *conf, struct udev_device *udev,
@@ -438,7 +436,8 @@ filter_property(const struct config *conf, struct udev_device *udev,
*uid_attribute != '\0';
bool uid_attr_seen = false;
@ -42,11 +41,11 @@ index 8d15d2ea..eff690fd 100644
udev_list_entry_foreach(list_entry,
udev_device_get_properties_list_entry(udev)) {
diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
index b4dccd1b..284282c6 100644
--- a/multipath/multipath.conf.5
+++ b/multipath/multipath.conf.5
@@ -1367,9 +1367,14 @@ keywords. Both are regular expressions. For a full description of these keywords
diff --git a/multipath/multipath.conf.5.in b/multipath/multipath.conf.5.in
index 226d0019..bae4168f 100644
--- a/multipath/multipath.conf.5.in
+++ b/multipath/multipath.conf.5.in
@@ -1402,9 +1402,14 @@ keywords. Both are regular expressions. For a full description of these keywords
Regular expression for an udev property. All
devices that have matching udev properties will be excluded/included.
The handling of the \fIproperty\fR keyword is special,
@ -62,7 +61,7 @@ index b4dccd1b..284282c6 100644
.
.RS
.PP
@@ -1380,10 +1385,6 @@ Blacklisting by missing properties is only applied to devices which do have the
@@ -1415,10 +1420,6 @@ Blacklisting by missing properties is only applied to devices which do have the
property specified by \fIuid_attribute\fR (e.g. \fIID_SERIAL\fR)
set. Previously, it was applied to every device, possibly causing devices to be
blacklisted because of temporary I/O error conditions.
@ -74,10 +73,10 @@ index b4dccd1b..284282c6 100644
.TP
.B protocol
diff --git a/tests/blacklist.c b/tests/blacklist.c
index 882aa3a1..6a22b660 100644
index ba8dfd07..693db3fa 100644
--- a/tests/blacklist.c
+++ b/tests/blacklist.c
@@ -375,9 +375,8 @@ static void test_property_missing(void **state)
@@ -384,9 +384,8 @@ static void test_property_missing(void **state)
{
static struct udev_device udev = { "sdb", { "ID_FOO", "ID_BAZ", "ID_BAR", "ID_SERIAL", NULL } };
conf.blist_property = blist_property_wwn;
@ -88,7 +87,7 @@ index 882aa3a1..6a22b660 100644
assert_int_equal(filter_property(&conf, &udev, 3, "ID_BLAH"),
MATCH_NOTHING);
assert_int_equal(filter_property(&conf, &udev, 3, ""),
@@ -469,9 +468,7 @@ static void test_filter_path_missing1(void **state)
@@ -478,9 +477,7 @@ static void test_filter_path_missing1(void **state)
conf.blist_device = blist_device_foo_bar;
conf.blist_protocol = blist_protocol_fcp;
conf.blist_wwid = blist_wwid_xyzzy;

View File

@ -14,17 +14,18 @@ Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/config.c | 13 +++++++++++++
libmultipath/config.h | 1 +
multipath/main.c | 6 ++++++
multipath/multipath.rules.in | 1 +
multipathd/multipathd.8 | 2 ++
multipathd/multipathd.8.in | 2 ++
multipathd/multipathd.service | 1 +
multipathd/multipathd.socket | 1 +
6 files changed, 19 insertions(+)
7 files changed, 25 insertions(+)
diff --git a/libmultipath/config.c b/libmultipath/config.c
index 5c5c0726..183b319d 100644
index b7dbc6f5..3a374b3d 100644
--- a/libmultipath/config.c
+++ b/libmultipath/config.c
@@ -966,6 +966,19 @@ int _init_config (const char *file, struct config *conf)
@@ -958,6 +958,19 @@ int _init_config (const char *file, struct config *conf)
}
factorize_hwtable(conf->hwtable, builtin_hwtable_size, file);
validate_pctable(conf->overrides, 0, file);
@ -45,7 +46,7 @@ index 5c5c0726..183b319d 100644
conf->processed_main_config = 1;
diff --git a/libmultipath/config.h b/libmultipath/config.h
index 87947469..0dc89c16 100644
index 8c22ce75..92f3a0df 100644
--- a/libmultipath/config.h
+++ b/libmultipath/config.h
@@ -10,6 +10,7 @@
@ -56,6 +57,35 @@ index 87947469..0dc89c16 100644
enum devtypes {
DEV_NONE,
diff --git a/multipath/main.c b/multipath/main.c
index 9e1c5052..46944589 100644
--- a/multipath/main.c
+++ b/multipath/main.c
@@ -829,11 +829,14 @@ main (int argc, char *argv[])
struct config *conf;
int retries = -1;
bool enable_foreign = false;
+ bool have_config;
+ struct stat buf;
libmultipath_init();
if (atexit(dm_lib_exit) || atexit(libmultipath_exit))
condlog(1, "failed to register cleanup handler for libmultipath: %m");
logsink = LOGSINK_STDERR_WITH_TIME;
+ have_config = (stat(DEFAULT_CONFIGFILE, &buf) == 0);
if (init_config(DEFAULT_CONFIGFILE))
exit(RTVL_FAIL);
if (atexit(uninit_config))
@@ -1081,6 +1084,9 @@ main (int argc, char *argv[])
while ((r = configure(conf, cmd, dev_type, dev)) == RTVL_RETRY)
condlog(3, "restart multipath configuration process");
+ if (!have_config && r == RTVL_OK &&
+ (cmd == CMD_LIST_SHORT || cmd == CMD_LIST_LONG))
+ r = RTVL_FAIL;
out:
put_multipath_config(conf);
if (dev)
diff --git a/multipath/multipath.rules.in b/multipath/multipath.rules.in
index 6f123760..70b69a06 100644
--- a/multipath/multipath.rules.in
@ -68,11 +98,11 @@ index 6f123760..70b69a06 100644
ENV{DEVTYPE}!="partition", GOTO="test_dev"
IMPORT{parent}="DM_MULTIPATH_DEVICE_PATH"
diff --git a/multipathd/multipathd.8 b/multipathd/multipathd.8
index bdf102eb..a16a0bd5 100644
--- a/multipathd/multipathd.8
+++ b/multipathd/multipathd.8
@@ -48,6 +48,8 @@ map regains its maximum performance and redundancy.
diff --git a/multipathd/multipathd.8.in b/multipathd/multipathd.8.in
index e98c27fd..fd2061e5 100644
--- a/multipathd/multipathd.8.in
+++ b/multipathd/multipathd.8.in
@@ -49,6 +49,8 @@ map regains its maximum performance and redundancy.
With the \fB-k\fR option, \fBmultipathd\fR acts as a client utility that
sends commands to a running instance of the multipathd daemon (see
\fBCOMMANDS\fR below).

View File

@ -13,10 +13,10 @@ Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
1 file changed, 17 insertions(+), 5 deletions(-)
diff --git a/Makefile.inc b/Makefile.inc
index 540e1dfc..748911e2 100644
index 62d3d5cc..72fd8d57 100644
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -78,11 +78,23 @@ ORIG_LDFLAGS := $(LDFLAGS)
@@ -91,11 +91,23 @@ ORIG_LDFLAGS := $(LDFLAGS)
SYSTEMD_CPPFLAGS := $(if $(SYSTEMD),-DUSE_SYSTEMD=$(SYSTEMD))
SYSTEMD_LIBDEPS := $(if $(SYSTEMD),$(if $(shell test $(SYSTEMD) -gt 209 && echo 1),-lsystemd,-lsystemd-daemon))
@ -38,13 +38,13 @@ index 540e1dfc..748911e2 100644
+WARNFLAGS := -Werror -Wextra -Wformat=2 $(WFORMATOVERFLOW) -Werror=implicit-int \
-Werror=implicit-function-declaration -Werror=format-security \
- $(WNOCLOBBERED) -Werror=cast-qual $(ERROR_DISCARDED_QUALIFIERS) $(W_URCU_TYPE_LIMITS)
-CPPFLAGS := $(FORTIFY_OPT) $(CPPFLAGS) \
-CPPFLAGS := $(FORTIFY_OPT) $(CPPFLAGS) $(D_URCU_VERSION) \
+ $(WNOCLOBBERED) -Werror=cast-qual $(ERROR_DISCARDED_QUALIFIERS) $(W_URCU_TYPE_LIMITS) -Wstrict-prototypes
+CPPFLAGS := $(CPPFLAGS) \
+CPPFLAGS := $(CPPFLAGS) $(D_URCU_VERSION) \
-DBIN_DIR=\"$(bindir)\" -DMULTIPATH_DIR=\"$(plugindir)\" \
-DRUNTIME_DIR=\"$(runtimedir)\" \
-DCONFIG_DIR=\"$(configdir)\" -DEXTRAVERSION=\"$(EXTRAVERSION)\" -MMD -MP
@@ -90,7 +102,7 @@ CFLAGS := --std=gnu99 $(CFLAGS) $(OPTFLAGS) $(WARNFLAGS) -pipe
-DRUNTIME_DIR=\"$(runtimedir)\" -DCONFIG_DIR=\"$(configdir)\" \
-DDEFAULT_CONFIGFILE=\"$(configfile)\" -DSTATE_DIR=\"$(statedir)\" \
@@ -104,7 +116,7 @@ CFLAGS := --std=gnu99 $(CFLAGS) $(OPTFLAGS) $(WARNFLAGS) -pipe
BIN_CFLAGS := -fPIE -DPIE
LIB_CFLAGS := -fPIC
SHARED_FLAGS := -shared

View File

@ -21,10 +21,10 @@ Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
create mode 100644 multipath/mpathconf.8
diff --git a/libmultipath/config.c b/libmultipath/config.c
index 183b319d..01f36a4f 100644
index 3a374b3d..4544f484 100644
--- a/libmultipath/config.c
+++ b/libmultipath/config.c
@@ -968,6 +968,8 @@ int _init_config (const char *file, struct config *conf)
@@ -960,6 +960,8 @@ int _init_config (const char *file, struct config *conf)
validate_pctable(conf->overrides, 0, file);
} else {
condlog(0, "/etc/multipath.conf does not exist, blacklisting all devices.");
@ -34,10 +34,10 @@ index 183b319d..01f36a4f 100644
conf->blist_devnode = vector_alloc();
if (!conf->blist_devnode) {
diff --git a/multipath/Makefile b/multipath/Makefile
index b3c2cc81..413294ef 100644
index f70e64ec..9942d1a9 100644
--- a/multipath/Makefile
+++ b/multipath/Makefile
@@ -22,6 +22,7 @@ $(EXEC): $(OBJS) $(multipathdir)/libmultipath.so $(mpathcmddir)/libmpathcmd.so
@@ -24,6 +24,7 @@ $(EXEC): $(OBJS) $(multipathdir)/libmultipath.so $(mpathcmddir)/libmpathcmd.so
install:
$(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(bindir)
$(Q)$(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)/
@ -45,7 +45,7 @@ index b3c2cc81..413294ef 100644
$(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(udevrulesdir)
$(Q)$(INSTALL_PROGRAM) -m 644 11-dm-mpath.rules $(DESTDIR)$(udevrulesdir)
$(Q)$(INSTALL_PROGRAM) -m 644 multipath.rules $(DESTDIR)$(udevrulesdir)/62-multipath.rules
@@ -31,6 +32,7 @@ install:
@@ -33,6 +34,7 @@ install:
$(Q)$(INSTALL_PROGRAM) -m 644 tmpfiles.conf $(DESTDIR)$(tmpfilesdir)/multipath.conf
$(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(mandir)/man8
$(Q)$(INSTALL_PROGRAM) -m 644 $(EXEC).8 $(DESTDIR)$(mandir)/man8
@ -53,7 +53,7 @@ index b3c2cc81..413294ef 100644
$(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(mandir)/man5
$(Q)$(INSTALL_PROGRAM) -m 644 $(EXEC).conf.5 $(DESTDIR)$(mandir)/man5
ifneq ($(SCSI_DH_MODULES_PRELOAD),)
@@ -41,11 +43,13 @@ endif
@@ -43,11 +45,13 @@ endif
uninstall:
$(Q)$(RM) $(DESTDIR)$(bindir)/$(EXEC)
@ -65,8 +65,8 @@ index b3c2cc81..413294ef 100644
$(Q)$(RM) $(DESTDIR)$(mandir)/man8/$(EXEC).8
+ $(Q)$(RM) $(DESTDIR)$(mandir)/man8/mpathconf.8
$(Q)$(RM) $(DESTDIR)$(mandir)/man5/$(EXEC).conf.5
$(Q)$(RM) $(DESTDIR)$(tmpfilesdir)/multipath.conf
clean: dep_clean
diff --git a/multipath/mpathconf b/multipath/mpathconf
new file mode 100644
index 00000000..319664b1

View File

@ -15,12 +15,12 @@ multipathd.service
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipath/main.c | 54 +++++++++++++++++++++++++++++++++--
multipath/multipath.8 | 7 ++++-
multipath/multipath.8.in | 7 ++++-
multipathd/multipathd.service | 1 +
3 files changed, 59 insertions(+), 3 deletions(-)
diff --git a/multipath/main.c b/multipath/main.c
index 90f940f1..3549740a 100644
index 46944589..47f89a0a 100644
--- a/multipath/main.c
+++ b/multipath/main.c
@@ -120,7 +120,7 @@ usage (char * progname)
@ -41,7 +41,7 @@ index 90f940f1..3549740a 100644
" -c check if a device should be a path in a multipath device\n"
" -C check if a multipath device has usable paths\n"
" -q allow queue_if_no_path when multipathd is not running\n"
@@ -447,6 +449,50 @@ static void cleanup_vecs(void)
@@ -448,6 +450,50 @@ static void cleanup_vecs(void)
free_pathvec(vecs.pathvec, FREE_PATHS);
}
@ -92,16 +92,16 @@ index 90f940f1..3549740a 100644
static int
configure (struct config *conf, enum mpath_cmds cmd,
enum devtypes dev_type, char *devpath)
@@ -842,7 +888,7 @@ main (int argc, char *argv[])
conf->force_sync = 1;
if (atexit(cleanup_vecs))
@@ -848,7 +894,7 @@ main (int argc, char *argv[])
condlog(1, "failed to register cleanup handler for vecs: %m");
if (atexit(cleanup_bindings))
condlog(1, "failed to register cleanup handler for bindings: %m");
- while ((arg = getopt(argc, argv, ":adDcChl::eFfM:v:p:b:BrR:itTquUwW")) != EOF ) {
+ while ((arg = getopt(argc, argv, ":aAdDcChl::eFfM:v:p:b:BrR:itTquUwW")) != EOF ) {
switch(arg) {
case 'v':
if (!isdigit(optarg[0])) {
@@ -913,6 +959,10 @@ main (int argc, char *argv[])
@@ -919,6 +965,10 @@ main (int argc, char *argv[])
case 'T':
cmd = CMD_DUMP_CONFIG;
break;
@ -112,11 +112,11 @@ index 90f940f1..3549740a 100644
case 'h':
usage(argv[0]);
exit(RTVL_OK);
diff --git a/multipath/multipath.8 b/multipath/multipath.8
index 88149d53..072a03ee 100644
--- a/multipath/multipath.8
+++ b/multipath/multipath.8
@@ -63,7 +63,7 @@ multipath \- Device mapper target autoconfig.
diff --git a/multipath/multipath.8.in b/multipath/multipath.8.in
index 348eb220..82a7e68e 100644
--- a/multipath/multipath.8.in
+++ b/multipath/multipath.8.in
@@ -64,7 +64,7 @@ multipath \- Device mapper target autoconfig.
.B multipath
.RB [\| \-v\ \c
.IR level \|]
@ -125,7 +125,7 @@ index 88149d53..072a03ee 100644
.
.LP
.B multipath
@@ -145,6 +145,11 @@ device mapper, path checkers ...).
@@ -146,6 +146,11 @@ device mapper, path checkers ...).
Add the WWID for the specified device to the WWIDs file.
.
.TP

View File

@ -12,7 +12,7 @@ Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libmultipath/defaults.h b/libmultipath/defaults.h
index a5e9ea0c..514fd880 100644
index d01f9712..ee2e13a9 100644
--- a/libmultipath/defaults.h
+++ b/libmultipath/defaults.h
@@ -23,7 +23,7 @@

View File

@ -13,7 +13,7 @@ Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
1 file changed, 29 insertions(+), 2 deletions(-)
diff --git a/libmultipath/prioritizers/ana.c b/libmultipath/prioritizers/ana.c
index b5c7873d..e139360c 100644
index e9827dca..80a32aa3 100644
--- a/libmultipath/prioritizers/ana.c
+++ b/libmultipath/prioritizers/ana.c
@@ -24,6 +24,7 @@
@ -68,7 +68,7 @@ index b5c7873d..e139360c 100644
static int get_ana_info(struct path * pp)
{
int rc;
@@ -210,8 +234,11 @@ int getprio(struct path *pp, __attribute__((unused)) char *args,
@@ -209,8 +233,11 @@ int getprio(struct path *pp, __attribute__((unused)) char *args)
if (pp->fd < 0)
rc = -ANA_ERR_NO_INFORMATION;

View File

@ -14,7 +14,7 @@ Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
2 files changed, 8 insertions(+), 10 deletions(-)
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
index 6865cd92..72825829 100644
index 84ce5fe7..104fdd5a 100644
--- a/libmultipath/discovery.c
+++ b/libmultipath/discovery.c
@@ -1177,13 +1177,9 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len,

View File

@ -11,7 +11,7 @@ Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Makefile.inc b/Makefile.inc
index 748911e2..c07bcb0c 100644
index 72fd8d57..a49e9f5a 100644
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -16,7 +16,7 @@ READLINE :=

View File

@ -12,7 +12,7 @@ Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Makefile.inc b/Makefile.inc
index c07bcb0c..e59313c6 100644
index a49e9f5a..51b55196 100644
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -12,7 +12,7 @@

View File

@ -0,0 +1,186 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Fri, 7 Jul 2023 15:25:59 -0500
Subject: [PATCH] RH: Add mpathcleanup
mpathcleanup is a program that will remove a multipath device as well as
all of the scsi path devices that make it up.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipath/Makefile | 2 +
multipath/mpathcleanup | 145 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 147 insertions(+)
create mode 100755 multipath/mpathcleanup
diff --git a/multipath/Makefile b/multipath/Makefile
index 9942d1a9..d281b501 100644
--- a/multipath/Makefile
+++ b/multipath/Makefile
@@ -25,6 +25,7 @@ install:
$(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(bindir)
$(Q)$(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)/
$(Q)$(INSTALL_PROGRAM) -m 755 mpathconf $(DESTDIR)$(bindir)/
+ $(Q)$(INSTALL_PROGRAM) -m 755 mpathcleanup $(DESTDIR)$(bindir)/
$(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(udevrulesdir)
$(Q)$(INSTALL_PROGRAM) -m 644 11-dm-mpath.rules $(DESTDIR)$(udevrulesdir)
$(Q)$(INSTALL_PROGRAM) -m 644 multipath.rules $(DESTDIR)$(udevrulesdir)/62-multipath.rules
@@ -46,6 +47,7 @@ endif
uninstall:
$(Q)$(RM) $(DESTDIR)$(bindir)/$(EXEC)
$(Q)$(RM) $(DESTDIR)$(bindir)/mpathconf
+ $(Q)$(RM) $(DESTDIR)$(bindir)/mpathcleanup
$(Q)$(RM) $(DESTDIR)$(udevrulesdir)/11-dm-mpath.rules
$(Q)$(RM) $(DESTDIR)$(modulesloaddir)/multipath.conf
$(Q)$(RM) $(DESTDIR)$(modulesloaddir)/scsi_dh.conf
diff --git a/multipath/mpathcleanup b/multipath/mpathcleanup
new file mode 100755
index 00000000..6fd921e4
--- /dev/null
+++ b/multipath/mpathcleanup
@@ -0,0 +1,145 @@
+#!/bin/bash
+#
+# Copyright (C) 2023 Red Hat, Inc. All rights reserved.
+#
+# This file is part of the device-mapper-multipath package.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+unset PROGRAM FLUSH DEVICE DEVNAME MAJOR MINOR PATHDEVS PATHDEV HAVE_MULTIPATHD QUEUEING
+
+function usage
+{
+ echo "usage: $PROGRAM [-h] [--flush] <device>"
+ echo ""
+ echo "remove a multipath device and its scsi path devices"
+ echo ""
+ echo "options:"
+ echo " -h, --help show this help message and exit"
+ echo " --flush disable queuing on the multipath device and"
+ echo " flush the path devices before removing"
+}
+
+function parse_args
+{
+ while [ -n "$1" ]; do
+ case $1 in
+ --flush)
+ FLUSH=1
+ shift
+ ;;
+ --help | -h)
+ usage
+ exit 1
+ ;;
+ *)
+ if [ -n "$DEVICE" ]; then
+ usage
+ exit 1
+ fi
+ DEVICE=$1
+ shift
+ ;;
+ esac
+ done
+}
+
+function validate_device
+{
+ if [ -z "$DEVICE" ]; then
+ usage
+ exit 1
+ fi
+ if [[ "$DEVICE" =~ ^[[:digit:]]+:[[:digit:]]+$ ]]; then
+ MAJOR=${DEVICE%%:*}
+ MINOR=${DEVICE##*:}
+ DEVNAME=`dmsetup ls --target multipath | grep "($MAJOR, $MINOR)$" | awk '{print $1}'`
+ else
+ DEVNAME=`dmsetup ls --target multipath | awk '{print $1}' | grep "^$DEVICE$"`
+ fi
+ if [ -z "$DEVNAME" ]; then
+ DEVNAME=`multipath -v 1 -l $DEVICE 2>/dev/null`
+ if [ -z "$DEVNAME" ]; then
+ echo "$DEVICE is not a multipath device"
+ exit 1
+ fi
+ # verify that this is not a native nvme multipath device
+ dmsetup ls --target multipath | awk '{print $1}' | grep -q "^$DEVNAME$"
+ if test $? -eq 1; then
+ echo "$DEVICE is not a device-mapper multipath device"
+ exit 1
+ fi
+ fi
+ if [ -z "$MINOR" ]; then
+ MINOR=`dmsetup info -c --noheadings -o minor $DEVNAME`
+ fi
+}
+
+function get_paths
+{
+ PATHDEVS=`ls /sys/block/dm-$MINOR/slaves`
+ for PATHDEV in $PATHDEVS; do
+ if [[ ! "$PATHDEV" =~ ^sd[a-z]+$ ]]; then
+ echo "$PATHDEV is not a scsi device. $PROGRAM only works with scsi devices"
+ exit 1
+ fi
+ done
+}
+
+function remove_devs
+{
+ pidof multipathd > /dev/null
+ HAVE_MULTIPATHD=$?
+ multipath -v2 -l "$DEVNAME" | grep features | grep -q queue_if_no_path
+ QUEUEING=$?
+ if [ -n "$FLUSH" ] && [ "$QUEUEING" -eq 0 ]; then
+ if test $HAVE_MULTIPATHD -eq 0; then
+ multipathd disablequeueing map "$DEVNAME" > /dev/null
+ else
+ dmsetup message "$DEVNAME" 0 fail_if_no_path
+ fi
+ sleep 1
+ fi
+ if test $HAVE_MULTIPATHD -eq 0; then
+ multipath -f "$DEVNAME"
+ else
+ multipathd -Df "$DEVNAME"
+ fi
+ if test $? -eq 1; then
+ echo "$DEVICE cannot be removed"
+ exit 1
+ fi
+ for PATHDEV in $PATHDEVS; do
+ if [ -n "$FLUSH" ]; then
+ blockdev --flushbufs /dev/"$PATHDEV"
+ fi
+ echo 1 > /sys/block/"$PATHDEV"/device/delete
+ done
+}
+
+function verify_removal
+{
+ multipath -v 1 -d $DEVNAME | grep -q "^$DEVNAME$"
+ if test $? -eq 0; then
+ echo "$DEVICE removed but path devices still exist"
+ exit 1
+ fi
+ multipath -v 1 -l $DEVNAME | grep -q "^$DEVNAME$"
+ if test $? -eq 0; then
+ echo "$DEVICE removal succeeded, but device still exists"
+ exit 1
+ fi
+}
+
+PROGRAM="$0"
+parse_args "$@"
+validate_device
+get_paths
+remove_devs
+verify_removal

View File

@ -1,27 +1,68 @@
Name: device-mapper-multipath
Version: 0.9.5
Release: 2%{?dist}
Version: 0.9.6
Release: 1%{?dist}
Summary: Tools to manage multipath devices using device-mapper
License: GPLv2
URL: http://christophe.varoqui.free.fr/
# The source for this package was pulled from upstream's git repo. Use the
# following command to generate the tarball
# curl -L https://github.com/opensvc/multipath-tools/archive/0.9.5.tar.gz -o multipath-tools-0.9.5.tgz
Source0: multipath-tools-0.9.5.tgz
# curl -L https://github.com/opensvc/multipath-tools/archive/0.9.6.tar.gz -o multipath-tools-0.9.6.tgz
Source0: multipath-tools-0.9.6.tgz
Source1: multipath.conf
Patch0001: 0001-RH-fixup-udev-rules-for-redhat.patch
Patch0002: 0002-RH-Remove-the-property-blacklist-exception-builtin.patch
Patch0003: 0003-RH-don-t-start-without-a-config-file.patch
Patch0004: 0004-RH-Fix-nvme-function-missing-argument.patch
Patch0005: 0005-RH-use-rpm-optflags-if-present.patch
Patch0006: 0006-RH-add-mpathconf.patch
Patch0007: 0007-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch
Patch0008: 0008-RH-reset-default-find_mutipaths-value-to-off.patch
Patch0009: 0009-RH-attempt-to-get-ANA-info-via-sysfs-first.patch
Patch0010: 0010-RH-make-parse_vpd_pg83-match-scsi_id-output.patch
Patch0011: 0011-RH-add-scsi-device-handlers-to-modules-load.d.patch
Patch0012: 0012-RH-compile-with-libreadline-support.patch
Patch0001: 0001-libmultipath-sysfs_set_scsi_tmo-do-nothing-for-ACT_D.patch
Patch0002: 0002-libmultipath-add-alias_already_taken.patch
Patch0003: 0003-libmultipath-unify-use_existing_alias-and-get_user_f.patch
Patch0004: 0004-libmultipath-never-allocate-an-alias-that-s-already-.patch
Patch0005: 0005-libmultipath-lookup_binding-add-comment-about-the-al.patch
Patch0006: 0006-multipath-tools-test-simplify-debugging-for-condlog-.patch
Patch0007: 0007-multipath-tools-tests-add-tests-for-get_user_friendl.patch
Patch0008: 0008-multipath-tools-test-consistent-use-of-macros-in-ali.patch
Patch0009: 0009-multipath-tools-tests-convert-mock_-failed-used-_ali.patch
Patch0010: 0010-multipath-tools-test-use-mock_bindings_file-consiste.patch
Patch0011: 0011-libmultipath-add-global-variable-for-current-binding.patch
Patch0012: 0012-libmultipath-rename-fix_bindings_file-to-update_bind.patch
Patch0013: 0013-libmultipath-alias.c-move-bindings-related-code-up.patch
Patch0014: 0014-libmultipath-update_bindings_file-take-filename-argu.patch
Patch0015: 0015-libmultipath-update_bindings_file-use-a-single-write.patch
Patch0016: 0016-libmultipath-update_bindings_file-don-t-log-temp-fil.patch
Patch0017: 0017-libmultipath-alias.c-factor-out-read_binding.patch
Patch0018: 0018-libmultipath-keep-bindings-in-memory.patch
Patch0019: 0019-multipath-tools-tests-fix-alias-tests.patch
Patch0020: 0020-libmultipath-dm_get_uuid-return-emtpy-UUID-for-non-e.patch
Patch0021: 0021-libmultipath-adapt-to-new-semantics-of-dm_get_uuid.patch
Patch0022: 0022-libmultipath-sort-aliases-by-length-and-strcmp.patch
Patch0023: 0023-multipath-tools-tests-fix-alias-test-after-sort-orde.patch
Patch0024: 0024-libmultipath-simplify-get_free_id-assuming-total-ord.patch
Patch0025: 0025-multipath-tools-tests-adapt-alias-tests-for-total-or.patch
Patch0026: 0026-multipath-tools-tests-add-test-for-ordering-of-bindi.patch
Patch0027: 0027-multipathd-watch-bindings-file-with-inotify-timestam.patch
Patch0028: 0028-multipath-tools-tests-mock-pthread_mutex_-lock-unloc.patch
Patch0029: 0029-multipath-tools-Makefile-sanitize-paths-for-configur.patch
Patch0030: 0030-multipath-tools-add-compile-time-configuration-for-e.patch
Patch0031: 0031-multipath-tools-man-pages-generate-with-correct-path.patch
Patch0032: 0032-libdmmp-Makefile-fix-bug-in-install-section.patch
Patch0033: 0033-multipath-tools-README.md-improve-documentation-for-.patch
Patch0034: 0034-libmultipath-print-built-in-values-for-deprecated-op.patch
Patch0035: 0035-multipath-add-a-missing-newline.patch
Patch0036: 0036-multipath-tools-allow-prefixes-with-and-w-o-trailing.patch
Patch0037: 0037-libmultipath-deprecate-bindings_file-wwids_file-prke.patch
Patch0038: 0038-libmultipath-avoid-Warray-bounds-error-in-uatomic-op.patch
Patch0039: 0039-multipath-tools-fix-spelling.patch
Patch0040: 0040-multipathd-Added-support-to-handle-FPIN-Li-events-fo.patch
Patch0041: 0041-RH-fixup-udev-rules-for-redhat.patch
Patch0042: 0042-RH-Remove-the-property-blacklist-exception-builtin.patch
Patch0043: 0043-RH-don-t-start-without-a-config-file.patch
Patch0044: 0044-RH-Fix-nvme-function-missing-argument.patch
Patch0045: 0045-RH-use-rpm-optflags-if-present.patch
Patch0046: 0046-RH-add-mpathconf.patch
Patch0047: 0047-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch
Patch0048: 0048-RH-reset-default-find_mutipaths-value-to-off.patch
Patch0049: 0049-RH-attempt-to-get-ANA-info-via-sysfs-first.patch
Patch0050: 0050-RH-make-parse_vpd_pg83-match-scsi_id-output.patch
Patch0051: 0051-RH-add-scsi-device-handlers-to-modules-load.d.patch
Patch0052: 0052-RH-compile-with-libreadline-support.patch
Patch0053: 0053-RH-Add-mpathcleanup.patch
# runtime
Requires: %{name}-libs = %{version}-%{release}
@ -108,7 +149,7 @@ This package contains the files needed to develop applications that use
device-mapper-multipath's libdmmp C API library
%prep
%autosetup -n multipath-tools-0.9.5 -p1
%autosetup -n multipath-tools-0.9.6 -p1
cp %{SOURCE1} .
%build
@ -158,6 +199,7 @@ fi
%{_sbindir}/multipathd
%{_sbindir}/multipathc
%{_sbindir}/mpathconf
%{_sbindir}/mpathcleanup
%{_sbindir}/mpathpersist
%{_unitdir}/multipathd.service
%{_unitdir}/multipathd.socket
@ -230,6 +272,13 @@ fi
%{_pkgconfdir}/libdmmp.pc
%changelog
* Fri Sep 22 2023 Benjamin Marzinski <bmarzins@redhat.com> - 0.9.6-1
- Update to the head of the upstream staging branch
- Rename redhat patches
* Previous patches 0001-0012 are now patches 0041-0052
- Add 0053-RH-Add-mpathcleanup.patch
* add mpathcleanup program
* Wed Jul 19 2023 Fedora Release Engineering <releng@fedoraproject.org> - 0.9.5-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild

View File

@ -1,2 +1,2 @@
SHA512 (multipath-tools-0.9.5.tgz) = 39c2e5d45542c6076eb3b17b9994629b4c1f74347aa43e0119001fa2d07d3a606fd5e617962906a11b313afb37a115bd8eec2ef24447e980e61b5900625f9146
SHA512 (multipath-tools-0.9.6.tgz) = 17d2b46ead9df6826b3266035bc077a2f4d4bea01e2cd59e32d3917cda40c320f11bc8572da7ba66251e312b46d9be317737069193d481d202d49f9aa5fd71b9
SHA512 (multipath.conf) = 71953dce5a68adcf60a942305f5a66023e6f4c4baf53b1bfdb4edf65ed5b8e03db804363c36d1dcfd85591f4766f52b515269904c53b84d7b076da0b80b09942