[dm-devel] [PATCH v4 18/20] multipath -u: quick check if path is multipathed
Benjamin Marzinski
bmarzins at redhat.com
Thu Apr 12 18:46:18 UTC 2018
On Wed, Apr 04, 2018 at 06:16:25PM +0200, Martin Wilck wrote:
> With "find_multipaths smart", we accept paths as valid if they are
> already part of a multipath map. This patch avoids doing a full path
> and device-mapper map scan for this case, speeding up "multipath -u"
> considerably.
I feel like this supports my idea from 17/20. I really think that in
smart mode, the only time we should be claiming a device as multipath is
on an add event, if it has always been claimed (or pretend claimed) as a
multipath path, or if it is currently a multipath path. Once we have let
a uevent go by for a path without setting SYSTEMD_READY=0, anything else
is free to use it, and we simply can't safely set SYSTEMD_READY=0,
unless we know that multipathd has already grabbed the device. I feel
like checking the wwids file should give you confidence that a device
either currently is a multipath path, or has always been claimed as one.
However, this patch can fix any loop holes where a device isn't in the
wwids file, but it multipathed (I don't know of any offhand).
-Ben
>
> Signed-off-by: Martin Wilck <mwilck at suse.com>
> ---
> libmultipath/sysfs.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++
> libmultipath/sysfs.h | 2 ++
> multipath/main.c | 14 ++++++++++-
> 3 files changed, 81 insertions(+), 1 deletion(-)
>
> diff --git a/libmultipath/sysfs.c b/libmultipath/sysfs.c
> index 97e0997..589eeaf 100644
> --- a/libmultipath/sysfs.c
> +++ b/libmultipath/sysfs.c
> @@ -27,6 +27,7 @@
> #include <string.h>
> #include <dirent.h>
> #include <libudev.h>
> +#include <fnmatch.h>
>
> #include "checkers.h"
> #include "vector.h"
> @@ -287,3 +288,68 @@ int sysfs_check_holders(char * check_devt, char * new_devt)
>
> return 0;
> }
> +
> +static int select_dm_devs(const struct dirent *di)
> +{
> + return fnmatch("dm-*", di->d_name, FNM_FILE_NAME) == 0;
> +}
> +
> +static void close_fd(void *arg)
> +{
> + close((long)arg);
> +}
> +
> +bool sysfs_is_multipathed(const struct path *pp)
> +{
> + char pathbuf[PATH_MAX];
> + struct dirent **di;
> + int n, r, i;
> + bool found = false;
> +
> + n = snprintf(pathbuf, sizeof(pathbuf), "/sys/block/%s/holders",
> + pp->dev);
> +
> + if (n >= sizeof(pathbuf)) {
> + condlog(1, "%s: pathname overflow", __func__);
> + return false;
> + }
> +
> + r = scandir(pathbuf, &di, select_dm_devs, alphasort);
> + if (r == 0)
> + return false;
> + else if (r < 0) {
> + condlog(1, "%s: error scanning %s", __func__, pathbuf);
> + return false;
> + }
> +
> + pthread_cleanup_push(free, di);
> + for (i = 0; i < r && !found; i++) {
> + long fd;
> + int nr;
> + char uuid[6];
> +
> + if (snprintf(pathbuf + n, sizeof(pathbuf) - n,
> + "/%s/dm/uuid", di[i]->d_name)
> + >= sizeof(pathbuf) - n)
> + continue;
> +
> + fd = open(pathbuf, O_RDONLY);
> + if (fd == -1) {
> + condlog(1, "%s: error opening %s", __func__, pathbuf);
> + continue;
> + }
> +
> + pthread_cleanup_push(close_fd, (void*)fd);
> + nr = read(fd, uuid, sizeof(uuid));
> + if (nr == sizeof(uuid) && !memcmp(uuid, "mpath-", sizeof(uuid)))
> + found = true;
> + else if (nr < 0) {
> + condlog(1, "%s: error reading from %s: %s",
> + __func__, pathbuf, strerror(errno));
> + }
> + pthread_cleanup_pop(1);
> + }
> + pthread_cleanup_pop(1);
> +
> + return found;
> +}
> diff --git a/libmultipath/sysfs.h b/libmultipath/sysfs.h
> index 75c0f9c..9ae30b3 100644
> --- a/libmultipath/sysfs.h
> +++ b/libmultipath/sysfs.h
> @@ -4,6 +4,7 @@
>
> #ifndef _LIBMULTIPATH_SYSFS_H
> #define _LIBMULTIPATH_SYSFS_H
> +#include <stdbool.h>
>
> ssize_t sysfs_attr_set_value(struct udev_device *dev, const char *attr_name,
> const char * value, size_t value_len);
> @@ -13,4 +14,5 @@ ssize_t sysfs_bin_attr_get_value(struct udev_device *dev, const char *attr_name,
> unsigned char * value, size_t value_len);
> int sysfs_get_size (struct path *pp, unsigned long long * size);
> int sysfs_check_holders(char * check_devt, char * new_devt);
> +bool sysfs_is_multipathed(const struct path *pp);
> #endif
> diff --git a/multipath/main.c b/multipath/main.c
> index a60a5f3..ae46e5a 100644
> --- a/multipath/main.c
> +++ b/multipath/main.c
> @@ -595,6 +595,15 @@ configure (struct config *conf, enum mpath_cmds cmd,
> !ignore_wwids_on(conf)) {
> goto print_valid;
> }
> + /*
> + * Shortcut for find_multipaths smart:
> + * Quick check if path is already multipathed.
> + */
> + if (ignore_wwids_on(conf) &&
> + sysfs_is_multipathed(VECTOR_SLOT(pathvec, 0))) {
> + r = 0;
> + goto print_valid;
> + }
> }
> }
>
> @@ -667,7 +676,10 @@ configure (struct config *conf, enum mpath_cmds cmd,
> condlog(3, "%s: path %s is in use: %s",
> __func__, pp->dev,
> strerror(errno));
> - r = 1;
> + /*
> + * Check if we raced with multipathd
> + */
> + r = !sysfs_is_multipathed(VECTOR_SLOT(pathvec, 0));
> }
> goto print_valid;
> }
> --
> 2.16.1
More information about the dm-devel
mailing list