From: Martin Wilck <mwilck@xxxxxxxx> 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@xxxxxxxx> --- libmultipath/alias.c | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/libmultipath/alias.c b/libmultipath/alias.c index 548a118..af3e24f 100644 --- a/libmultipath/alias.c +++ b/libmultipath/alias.c @@ -672,6 +672,24 @@ 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; + + if (alias1 && alias2) + return strcmp(alias1, alias2); + else + /* Move NULL alias to the end */ + return alias1 ? -1 : alias2 ? 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 +711,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 +740,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 -- dm-devel mailing list dm-devel@xxxxxxxxxx https://listman.redhat.com/mailman/listinfo/dm-devel