[dm-devel] [PATCH v2 2/3] libmultipath: check_alias_settings(): pre-sort mptable by alias
mwilck at suse.com
mwilck at suse.com
Wed Aug 24 08:11:46 UTC 2022
From: Martin Wilck <mwilck at suse.com>
add_binding() contains an optimization; it assumes that the list of
bindings is alphabetically sorted by alias, and tries to maintain
this order.
But conf->mptable is sorted by wwid. Therefore check_alias_settings() may take
a long time if the mptable is large.
Create a copy of the mptable, sorted by alias, and use it for add_bindings().
This speeds up check_alias_settings by roughly a factor of 10 (0.1s vs. 1s)
for my test setup with 10000 entries in the mptable.
Signed-off-by: Martin Wilck <mwilck at suse.com>
---
libmultipath/alias.c | 44 +++++++++++++++++++++++++++++++++++++++++---
1 file changed, 41 insertions(+), 3 deletions(-)
diff --git a/libmultipath/alias.c b/libmultipath/alias.c
index 548a118..284092b 100644
--- a/libmultipath/alias.c
+++ b/libmultipath/alias.c
@@ -672,6 +672,31 @@ static void cleanup_fclose(void *p)
fclose(p);
}
+static int alias_compar(const void *p1, const void *p2)
+{
+ const char *alias1 = (*(struct mpentry * const *)p1)->alias;
+ const char *alias2 = (*(struct mpentry * const *)p2)->alias;
+ int cmp;
+
+ if (alias1 && alias2)
+ cmp = strcmp(alias1, alias2);
+ else
+ /* Move NULL alias to the end */
+ cmp = alias1 ? -1 : alias2 ? 1 : 0;
+
+ if (cmp)
+ return cmp;
+
+ /* Ensure stable sort, see wwid_compar() in config.c */
+ return p1 < p2 ? -1 : p1 > p2 ? 1 : 0;
+}
+
+static void cleanup_vector_free(void *arg)
+{
+ if (arg)
+ vector_free((vector)arg);
+}
+
/*
* check_alias_settings(): test for inconsistent alias configuration
*
@@ -693,12 +718,24 @@ int check_alias_settings(const struct config *conf)
int can_write;
int rc = 0, i, fd;
Bindings bindings = {.allocated = 0, };
+ vector mptable = NULL;
struct mpentry *mpe;
+ mptable = vector_convert(NULL, conf->mptable, struct mpentry *, identity);
+ if (!mptable)
+ return -1;
+
pthread_cleanup_push_cast(free_bindings, &bindings);
- vector_foreach_slot(conf->mptable, mpe, i) {
- if (!mpe->wwid || !mpe->alias)
- continue;
+ pthread_cleanup_push(cleanup_vector_free, mptable);
+
+ vector_sort(mptable, alias_compar);
+ vector_foreach_slot(mptable, mpe, i) {
+ if (!mpe->alias)
+ /*
+ * alias_compar() sorts NULL alias at the end,
+ * so we can stop if we encounter this.
+ */
+ break;
if (add_binding(&bindings, mpe->alias, mpe->wwid) ==
BINDING_CONFLICT) {
condlog(0, "ERROR: alias \"%s\" bound to multiple wwids in multipath.conf, "
@@ -710,6 +747,7 @@ int check_alias_settings(const struct config *conf)
}
/* This clears the bindings */
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);
--
2.37.1
More information about the dm-devel
mailing list