[dm-devel] [PATCH] libmultipath: lazy device-mapper initialization

Christophe Varoqui christophe.varoqui at opensvc.com
Wed Jun 21 10:24:41 UTC 2017


Merged,
Thanks.

On Tue, Jun 6, 2017 at 9:33 PM, Martin Wilck <mwilck at suse.com> 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.
>
> Fixes: d7188fcd "multipathd: start daemon after udev trigger"
> Signed-off-by: Martin Wilck <mwilck at suse.com>
> ---
>  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
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://listman.redhat.com/archives/dm-devel/attachments/20170621/aa04c558/attachment.htm>


More information about the dm-devel mailing list