[dm-devel] [PATCH v3 18/20] multipath -u: quick check if path is multipathed
Martin Wilck
mwilck at suse.com
Mon Apr 2 19:50:49 UTC 2018
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.
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 392d5f0..c21ee28 100644
--- a/multipath/main.c
+++ b/multipath/main.c
@@ -594,6 +594,15 @@ configure (struct config *conf, enum mpath_cmds cmd,
!find_multipaths_on(conf) || !ignore_wwids(conf)) {
goto print_valid;
}
+ /*
+ * Shortcut for find_multipaths smart:
+ * Quick check if path is already multipathed.
+ */
+ if (ignore_wwids(conf) &&
+ sysfs_is_multipathed(VECTOR_SLOT(pathvec, 0))) {
+ r = 0;
+ goto print_valid;
+ }
}
}
@@ -666,7 +675,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