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