device-mapper-multipath/0022-libmultipath-sort-aliases-by-length-and-strcmp.patch
Benjamin Marzinski e5eddaae1a 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
2023-09-22 15:29:43 -05:00

99 lines
3.6 KiB
Diff

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)
/*