<div dir="ltr">Merged,<div>Thanks.</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Jun 6, 2017 at 9:33 PM, Martin Wilck <span dir="ltr"><<a href="mailto:mwilck@suse.com" target="_blank">mwilck@suse.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">The multipath command fails early if libdevmapper and/or the<br>
dm_multipath driver are not found. But some multipath operations<br>
don't require device mapper, notably the path checking operations<br>
called from udev rules during early boot.<br>
<br>
This patch delays dm initialization until the first device-mapper<br>
call, allowing such operations to succeed even if the dm_multipath<br>
driver is not loaded yet.<br>
<br>
This fixes the following problem: during system boot, the dm_multipath<br>
driver is usually loaded via "ExecStartPre" from the multipathd service<br>
file. But with commit d7188fcd, this service is started only after<br>
udev settle and thus the modules are loaded too late for udev<br>
rule processing, causing "multipath" invocations from udev rules to fail<br>
and paths to be wrongly classified as non-multipath.<br>
<br>
Fixes: d7188fcd "multipathd: start daemon after udev trigger"<br>
Signed-off-by: Martin Wilck <<a href="mailto:mwilck@suse.com">mwilck@suse.com</a>><br>
---<br>
libmultipath/devmapper.c | 79 ++++++++++++++++++++++++++++++<wbr>++++--------------<br>
libmultipath/devmapper.h | 4 ++-<br>
libmultipath/waiter.c | 2 +-<br>
multipath/main.c | 8 ++---<br>
multipathd/main.c | 4 +--<br>
5 files changed, 63 insertions(+), 34 deletions(-)<br>
<br>
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c<br>
index 69b634bf..4319b381 100644<br>
--- a/libmultipath/devmapper.c<br>
+++ b/libmultipath/devmapper.c<br>
@@ -21,6 +21,7 @@<br>
#include "memory.h"<br>
#include "devmapper.h"<br>
#include "sysfs.h"<br>
+#include "config.h"<br>
<br>
#include "log_pthread.h"<br>
#include <sys/types.h><br>
@@ -178,7 +179,7 @@ out:<br>
}<br>
<br>
static int<br>
-dm_drv_prereq (void)<br>
+dm_drv_prereq (unsigned int *ver)<br>
{<br>
unsigned int minv[3] = {1, 0, 3};<br>
unsigned int version[3] = {0, 0, 0};<br>
@@ -193,19 +194,51 @@ dm_drv_prereq (void)<br>
condlog(3, "DM multipath kernel driver v%u.%u.%u",<br>
v[0], v[1], v[2]);<br>
<br>
- if VERSION_GE(v, minv)<br>
+ if (VERSION_GE(v, minv)) {<br>
+ ver[0] = v[0];<br>
+ ver[1] = v[1];<br>
+ ver[2] = v[2];<br>
return 0;<br>
+ }<br>
<br>
condlog(0, "DM multipath kernel driver must be >= v%u.%u.%u",<br>
minv[0], minv[1], minv[2]);<br>
return 1;<br>
}<br>
<br>
-int dm_prereq(void)<br>
+static int dm_prereq(unsigned int *v)<br>
{<br>
if (dm_lib_prereq())<br>
return 1;<br>
- return dm_drv_prereq();<br>
+ return dm_drv_prereq(v);<br>
+}<br>
+<br>
+static int libmp_dm_udev_sync = 0;<br>
+<br>
+void libmp_udev_set_sync_support(<wbr>int on)<br>
+{<br>
+ libmp_dm_udev_sync = !!on;<br>
+}<br>
+<br>
+void libmp_dm_init(void)<br>
+{<br>
+ struct config *conf;<br>
+<br>
+ conf = get_multipath_config();<br>
+ dm_init(conf->verbosity);<br>
+ if (dm_prereq(conf->version))<br>
+ exit(1);<br>
+ put_multipath_config(conf);<br>
+ dm_udev_set_sync_support(<wbr>libmp_dm_udev_sync);<br>
+}<br>
+<br>
+struct dm_task*<br>
+libmp_dm_task_create(int task)<br>
+{<br>
+ static pthread_once_t dm_initialized = PTHREAD_ONCE_INIT;<br>
+<br>
+ pthread_once(&dm_initialized, libmp_dm_init);<br>
+ return dm_task_create(task);<br>
}<br>
<br>
#define do_deferred(x) ((x) == DEFERRED_REMOVE_ON || (x) == DEFERRED_REMOVE_IN_PROGRESS)<br>
@@ -219,7 +252,7 @@ dm_simplecmd (int task, const char *name, int no_flush, int need_sync, uint16_t<br>
uint32_t cookie = 0;<br>
struct dm_task *dmt;<br>
<br>
- if (!(dmt = dm_task_create (task)))<br>
+ if (!(dmt = libmp_dm_task_create (task)))<br>
return 0;<br>
<br>
if (!dm_task_set_name (dmt, name))<br>
@@ -274,7 +307,7 @@ dm_addmap (int task, const char *target, struct multipath *mpp,<br>
uint32_t cookie = 0;<br>
uint16_t udev_flags = DM_UDEV_DISABLE_LIBRARY_<wbr>FALLBACK | ((skip_kpartx == SKIP_KPARTX_ON)? MPATH_UDEV_NO_KPARTX_FLAG : 0);<br>
<br>
- if (!(dmt = dm_task_create (task)))<br>
+ if (!(dmt = libmp_dm_task_create (task)))<br>
return 0;<br>
<br>
if (!dm_task_set_name (dmt, mpp->alias))<br>
@@ -411,7 +444,7 @@ do_get_info(const char *name, struct dm_info *info)<br>
int r = -1;<br>
struct dm_task *dmt;<br>
<br>
- if (!(dmt = dm_task_create(DM_DEVICE_INFO)<wbr>))<br>
+ if (!(dmt = libmp_dm_task_create(DM_<wbr>DEVICE_INFO)))<br>
return r;<br>
<br>
if (!dm_task_set_name(dmt, name))<br>
@@ -449,7 +482,7 @@ int dm_get_map(const char *name, unsigned long long *size, char *outparams)<br>
char *target_type = NULL;<br>
char *params = NULL;<br>
<br>
- if (!(dmt = dm_task_create(DM_DEVICE_<wbr>TABLE)))<br>
+ if (!(dmt = libmp_dm_task_create(DM_<wbr>DEVICE_TABLE)))<br>
return 1;<br>
<br>
if (!dm_task_set_name(dmt, name))<br>
@@ -485,7 +518,7 @@ dm_get_prefixed_uuid(const char *name, char *uuid)<br>
const char *uuidtmp;<br>
int r = 1;<br>
<br>
- dmt = dm_task_create(DM_DEVICE_INFO)<wbr>;<br>
+ dmt = libmp_dm_task_create(DM_<wbr>DEVICE_INFO);<br>
if (!dmt)<br>
return 1;<br>
<br>
@@ -548,7 +581,7 @@ int dm_get_status(char *name, char *outstatus)<br>
char *target_type = NULL;<br>
char *status = NULL;<br>
<br>
- if (!(dmt = dm_task_create(DM_DEVICE_<wbr>STATUS)))<br>
+ if (!(dmt = libmp_dm_task_create(DM_<wbr>DEVICE_STATUS)))<br>
return 1;<br>
<br>
if (!dm_task_set_name(dmt, name))<br>
@@ -591,7 +624,7 @@ int dm_type(const char *name, char *type)<br>
char *target_type = NULL;<br>
char *params;<br>
<br>
- if (!(dmt = dm_task_create(DM_DEVICE_<wbr>TABLE)))<br>
+ if (!(dmt = libmp_dm_task_create(DM_<wbr>DEVICE_TABLE)))<br>
return 0;<br>
<br>
if (!dm_task_set_name(dmt, name))<br>
@@ -627,7 +660,7 @@ int dm_is_mpath(const char *name)<br>
char *params;<br>
const char *uuid;<br>
<br>
- if (!(dmt = dm_task_create(DM_DEVICE_<wbr>TABLE)))<br>
+ if (!(dmt = libmp_dm_task_create(DM_<wbr>DEVICE_TABLE)))<br>
return 0;<br>
<br>
if (!dm_task_set_name(dmt, name))<br>
@@ -679,7 +712,7 @@ dm_get_opencount (const char * mapname)<br>
struct dm_task *dmt;<br>
struct dm_info info;<br>
<br>
- if (!(dmt = dm_task_create(DM_DEVICE_INFO)<wbr>))<br>
+ if (!(dmt = libmp_dm_task_create(DM_<wbr>DEVICE_INFO)))<br>
return 0;<br>
<br>
if (!dm_task_set_name(dmt, mapname))<br>
@@ -837,7 +870,7 @@ int dm_flush_maps (int retries)<br>
struct dm_names *names;<br>
unsigned next = 0;<br>
<br>
- if (!(dmt = dm_task_create (DM_DEVICE_LIST)))<br>
+ if (!(dmt = libmp_dm_task_create (DM_DEVICE_LIST)))<br>
return 0;<br>
<br>
dm_task_no_open_count(dmt);<br>
@@ -868,7 +901,7 @@ dm_message(const char * mapname, char * message)<br>
int r = 1;<br>
struct dm_task *dmt;<br>
<br>
- if (!(dmt = dm_task_create(DM_DEVICE_<wbr>TARGET_MSG)))<br>
+ if (!(dmt = libmp_dm_task_create(DM_<wbr>DEVICE_TARGET_MSG)))<br>
return 1;<br>
<br>
if (!dm_task_set_name(dmt, mapname))<br>
@@ -970,7 +1003,7 @@ dm_get_maps (vector mp)<br>
if (!mp)<br>
return 1;<br>
<br>
- if (!(dmt = dm_task_create(DM_DEVICE_LIST)<wbr>))<br>
+ if (!(dmt = libmp_dm_task_create(DM_<wbr>DEVICE_LIST)))<br>
return 1;<br>
<br>
dm_task_no_open_count(dmt);<br>
@@ -1056,7 +1089,7 @@ dm_mapname(int major, int minor)<br>
int r;<br>
int loop = MAX_WAIT * LOOPS_PER_SEC;<br>
<br>
- if (!(dmt = dm_task_create(DM_DEVICE_<wbr>STATUS)))<br>
+ if (!(dmt = libmp_dm_task_create(DM_<wbr>DEVICE_STATUS)))<br>
return NULL;<br>
<br>
if (!dm_task_set_major(dmt, major) ||<br>
@@ -1109,7 +1142,7 @@ do_foreach_partmaps (const char * mapname,<br>
int r = 1;<br>
char *p;<br>
<br>
- if (!(dmt = dm_task_create(DM_DEVICE_LIST)<wbr>))<br>
+ if (!(dmt = libmp_dm_task_create(DM_<wbr>DEVICE_LIST)))<br>
return 1;<br>
<br>
dm_task_no_open_count(dmt);<br>
@@ -1333,7 +1366,7 @@ dm_rename (const char * old, char * new, char *delim, int skip_kpartx)<br>
if (dm_rename_partmaps(old, new, delim))<br>
return r;<br>
<br>
- if (!(dmt = dm_task_create(DM_DEVICE_<wbr>RENAME)))<br>
+ if (!(dmt = libmp_dm_task_create(DM_<wbr>DEVICE_RENAME)))<br>
return r;<br>
<br>
if (!dm_task_set_name(dmt, old))<br>
@@ -1382,7 +1415,7 @@ int dm_reassign_table(const char *name, char *old, char *new)<br>
char *buff;<br>
void *next = NULL;<br>
<br>
- if (!(dmt = dm_task_create(DM_DEVICE_<wbr>TABLE)))<br>
+ if (!(dmt = libmp_dm_task_create(DM_<wbr>DEVICE_TABLE)))<br>
return 0;<br>
<br>
if (!dm_task_set_name(dmt, name))<br>
@@ -1392,7 +1425,7 @@ int dm_reassign_table(const char *name, char *old, char *new)<br>
<br>
if (!dm_task_run(dmt))<br>
goto out;<br>
- if (!(reload_dmt = dm_task_create(DM_DEVICE_<wbr>RELOAD)))<br>
+ if (!(reload_dmt = libmp_dm_task_create(DM_<wbr>DEVICE_RELOAD)))<br>
goto out;<br>
if (!dm_task_set_name(reload_dmt, name))<br>
goto out_reload;<br>
@@ -1456,7 +1489,7 @@ int dm_reassign(const char *mapname)<br>
return 1;<br>
}<br>
<br>
- if (!(dmt = dm_task_create(DM_DEVICE_DEPS)<wbr>)) {<br>
+ if (!(dmt = libmp_dm_task_create(DM_<wbr>DEVICE_DEPS))) {<br>
condlog(3, "%s: couldn't make dm task", mapname);<br>
return 0;<br>
}<br>
@@ -1514,7 +1547,7 @@ int dm_setgeometry(struct multipath *mpp)<br>
return 1;<br>
}<br>
<br>
- if (!(dmt = dm_task_create(DM_DEVICE_SET_<wbr>GEOMETRY)))<br>
+ if (!(dmt = libmp_dm_task_create(DM_<wbr>DEVICE_SET_GEOMETRY)))<br>
return 0;<br>
<br>
if (!dm_task_set_name(dmt, mpp->alias))<br>
diff --git a/libmultipath/devmapper.h b/libmultipath/devmapper.h<br>
index fa739bcc..99a554b5 100644<br>
--- a/libmultipath/devmapper.h<br>
+++ b/libmultipath/devmapper.h<br>
@@ -25,7 +25,9 @@<br>
#endif<br>
<br>
void dm_init(int verbosity);<br>
-int dm_prereq (void);<br>
+void libmp_dm_init(void);<br>
+void libmp_udev_set_sync_support(<wbr>int on);<br>
+struct dm_task *libmp_dm_task_create(int task);<br>
int dm_drv_version (unsigned int * version, char * str);<br>
int dm_simplecmd_flush (int, const char *, uint16_t);<br>
int dm_simplecmd_noflush (int, const char *, uint16_t);<br>
diff --git a/libmultipath/waiter.c b/libmultipath/waiter.c<br>
index 995ea1ad..cb9708b2 100644<br>
--- a/libmultipath/waiter.c<br>
+++ b/libmultipath/waiter.c<br>
@@ -76,7 +76,7 @@ static int waiteventloop (struct event_thread *waiter)<br>
if (!waiter->event_nr)<br>
waiter->event_nr = dm_geteventnr(waiter->mapname)<wbr>;<br>
<br>
- if (!(waiter->dmt = dm_task_create(DM_DEVICE_<wbr>WAITEVENT))) {<br>
+ if (!(waiter->dmt = libmp_dm_task_create(DM_<wbr>DEVICE_WAITEVENT))) {<br>
condlog(0, "%s: devmap event #%i dm_task_create error",<br>
waiter->mapname, waiter->event_nr);<br>
return 1;<br>
diff --git a/multipath/main.c b/multipath/main.c<br>
index 4174d43d..dede017e 100644<br>
--- a/multipath/main.c<br>
+++ b/multipath/main.c<br>
@@ -634,12 +634,6 @@ main (int argc, char *argv[])<br>
exit(1);<br>
}<br>
<br>
- dm_init(conf->verbosity);<br>
- if (dm_prereq())<br>
- exit(1);<br>
- dm_drv_version(conf->version, TGT_MPATH);<br>
- dm_udev_set_sync_support(1);<br>
-<br>
if (optind < argc) {<br>
dev = MALLOC(FILE_NAME_SIZE);<br>
<br>
@@ -670,6 +664,8 @@ main (int argc, char *argv[])<br>
conf->max_fds, strerror(errno));<br>
}<br>
<br>
+ libmp_udev_set_sync_support(1)<wbr>;<br>
+<br>
if (init_checkers(conf-><wbr>multipath_dir)) {<br>
condlog(0, "failed to initialize checkers");<br>
goto out;<br>
diff --git a/multipathd/main.c b/multipathd/main.c<br>
index 81c76cab..4be2c579 100644<br>
--- a/multipathd/main.c<br>
+++ b/multipathd/main.c<br>
@@ -2408,8 +2408,6 @@ child (void * param)<br>
conf->ignore_new_devs = ignore_new_devs;<br>
uxsock_timeout = conf->uxsock_timeout;<br>
rcu_assign_pointer(multipath_<wbr>conf, conf);<br>
- dm_init(conf->verbosity);<br>
- dm_drv_version(conf->version, TGT_MPATH);<br>
if (init_checkers(conf-><wbr>multipath_dir)) {<br>
condlog(0, "failed to initialize checkers");<br>
goto failed;<br>
@@ -2458,7 +2456,6 @@ child (void * param)<br>
setscheduler();<br>
set_oom_adj();<br>
<br>
- dm_udev_set_sync_support(0);<br>
#ifdef USE_SYSTEMD<br>
envp = getenv("WATCHDOG_USEC");<br>
if (envp && sscanf(envp, "%lu", &checkint) == 1) {<br>
@@ -2700,6 +2697,7 @@ main (int argc, char *argv[])<br>
pthread_cond_init_mono(&<wbr>config_cond);<br>
<br>
udev = udev_new();<br>
+ libmp_udev_set_sync_support(0)<wbr>;<br>
<br>
while ((arg = getopt(argc, argv, ":dsv:k::Bn")) != EOF ) {<br>
switch(arg) {<br>
<span class="HOEnZb"><font color="#888888">--<br>
2.13.0<br>
<br>
</font></span></blockquote></div><br></div>