[dm-devel] [PATCH 78/78] multipathd: trigger all devices on startup

Benjamin Marzinski bmarzins at redhat.com
Fri Mar 27 05:59:47 UTC 2015


On Mon, Mar 16, 2015 at 01:37:05PM +0100, Hannes Reinecke wrote:
> During startup multipathd might race with udev and device discovery.
> During that time any information from libudev might not be fully
> available, leading to spurious multipathd failures during startup.
> So instead of scanning all devices on our own we should just
> re-trigger the existing devices; with that we'll read _all_
> devices via uevents during startup and avoid the race condition.

Should we also be sending change uevents for the dm devices?

-Ben

> 
> Signed-off-by: Hannes Reinecke <hare at suse.de>
> ---
>  libmultipath/discovery.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++
>  libmultipath/discovery.h |  1 +
>  multipathd/main.c        | 36 +++++++++++++++++++++++++++++----
>  3 files changed, 85 insertions(+), 4 deletions(-)
> 
> diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
> index 4582a20..8762819 100644
> --- a/libmultipath/discovery.c
> +++ b/libmultipath/discovery.c
> @@ -134,6 +134,58 @@ path_discover (vector pathvec, struct config * conf,
>  }
>  
>  int
> +path_trigger (struct config * conf, int flag)
> +{
> +	struct udev_enumerate *udev_iter;
> +	struct udev_list_entry *entry;
> +	int num_paths = 0;
> +
> +	udev_iter = udev_enumerate_new(conf->udev);
> +	if (!udev_iter)
> +		return -ENOMEM;
> +
> +	udev_enumerate_add_match_subsystem(udev_iter, "block");
> +	udev_enumerate_scan_devices(udev_iter);
> +
> +	udev_list_entry_foreach(entry,
> +				udev_enumerate_get_list_entry(udev_iter)) {
> +		const char *devpath;
> +		char *devname;
> +		char filename[PATH_MAX];
> +		int fd;
> +
> +		devpath = udev_list_entry_get_name(entry);
> +		condlog(3, "Trigger device %s", devpath);
> +		devname = strrchr(devpath, '/');
> +		if (!devname) {
> +			condlog(3, "%s: invalid devpath", devpath);
> +			continue;
> +		}
> +		devname++;
> +		if (filter_devnode(conf->blist_devnode,
> +				   conf->elist_devnode, devname) > 0) {
> +			condlog(3, "%s: blacklisted", devname);
> +			continue;
> +		}
> +		strncpy(filename, devpath, strlen(devpath) + 1);
> +		strncat(filename, "/uevent", 8);
> +		fd = open(filename, O_WRONLY | O_CLOEXEC);
> +		if (fd < 0)
> +			continue;
> +		if (write(fd, "add", 3) < 0) {
> +			condlog(3, "%s: Failed to trigger 'add' uevent: %m",
> +				devpath);
> +		} else {
> +			num_paths++;
> +		}
> +		close(fd);
> +	}
> +	udev_enumerate_unref(udev_iter);
> +	condlog(4, "Triggered %d paths", num_paths);
> +	return num_paths;
> +}
> +
> +int
>  path_discovery (vector pathvec, struct config * conf, int flag)
>  {
>  	struct udev_enumerate *udev_iter;
> diff --git a/libmultipath/discovery.h b/libmultipath/discovery.h
> index da7652c..9ae3d23 100644
> --- a/libmultipath/discovery.h
> +++ b/libmultipath/discovery.h
> @@ -31,6 +31,7 @@
>  struct config;
>  
>  int path_discovery (vector pathvec, struct config * conf, int flag);
> +int path_trigger (struct config * conf, int flag);
>  
>  int do_tur (char *);
>  int path_offline (struct path *);
> diff --git a/multipathd/main.c b/multipathd/main.c
> index d9f2435..480b10d 100644
> --- a/multipathd/main.c
> +++ b/multipathd/main.c
> @@ -1581,6 +1581,24 @@ configure (struct vectors * vecs, int start_waiters)
>  }
>  
>  int
> +trigger_devices (struct vectors * vecs)
> +{
> +
> +	if (!vecs->pathvec && !(vecs->pathvec = vector_alloc()))
> +		return 1;
> +
> +	if (!vecs->mpvec && !(vecs->mpvec = vector_alloc()))
> +		return 1;
> +
> +	/*
> +	 * Trigger all non-blacklisted block devices
> +	 */
> +	path_trigger(conf, DI_ALL);
> +
> +	return 0;
> +}
> +
> +int
>  reconfigure (struct vectors * vecs)
>  {
>  	struct config * old = conf;
> @@ -1902,15 +1920,21 @@ child (void * param)
>  		condlog(0, "failed to create cli listener: %d", rc);
>  		goto failed;
>  	}
> -	/*
> -	 * fetch and configure both paths and multipaths
> -	 */
>  #ifdef USE_SYSTEMD
>  	sd_notify(0, "STATUS=configure");
>  #endif
>  	post_config_state(DAEMON_CONFIGURE);
>  
>  	/*
> +	 * Trigger all paths to force reconfiguration
> +	 */
> +	pthread_cleanup_push(cleanup_lock, &vecs->lock);
> +	lock(vecs->lock);
> +	pthread_testcancel();
> +	trigger_devices(vecs);
> +	lock_cleanup_pop(vecs->lock);
> +
> +	/*
>  	 * start threads
>  	 */
>  	if ((rc = pthread_create(&check_thr, &misc_attr, checkerloop, vecs))) {
> @@ -1927,6 +1951,8 @@ child (void * param)
>  	pid_rc = pidfile_create(DEFAULT_PIDFILE, daemon_pid);
>  	/* Ignore errors, we can live without */
>  
> +	post_config_state(DAEMON_RUNNING);
> +
>  #ifdef USE_SYSTEMD
>  	sd_notify(0, "READY=1\nSTATUS=running");
>  #endif
> @@ -2129,7 +2155,9 @@ main (int argc, char *argv[])
>  			conf->bindings_read_only = 1;
>  			break;
>  		default:
> -			;
> +			fprintf(stderr, "Invalid argument '-%c'\n",
> +				optopt);
> +			exit(1);
>  		}
>  	}
>  	if (optind < argc) {
> -- 
> 1.8.4.5




More information about the dm-devel mailing list