summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Teigland <teigland@redhat.com>2019-08-22 17:02:27 -0500
committerDavid Teigland <teigland@redhat.com>2019-08-22 17:03:35 -0500
commitf15564d18efa2e8bd2d7092535134d4ea60439d4 (patch)
tree6f3f0d8afae8aab3d15b0930eb913f97d1dd33e2
parent4a3e1ac7407dff9e53c5efea179a5620ad13f8f3 (diff)
downloadlvm2-dev-dct-stable-filter-wwid.tar.gz
filter: use wwid for mpath filterdev-dct-stable-filter-wwid
-rw-r--r--lib/device/dev-cache.c46
-rw-r--r--lib/device/dev-type.c40
-rw-r--r--lib/device/dev-type.h3
-rw-r--r--lib/device/device.h1
-rw-r--r--lib/filters/filter-mpath.c98
5 files changed, 181 insertions, 7 deletions
diff --git a/lib/device/dev-cache.c b/lib/device/dev-cache.c
index a429b100a..53b42d09c 100644
--- a/lib/device/dev-cache.c
+++ b/lib/device/dev-cache.c
@@ -163,6 +163,50 @@ void dev_set_preferred_name(struct dm_str_list *sl, struct device *dev)
dm_list_add_h(&dev->aliases, &sl->list);
}
+static void _dev_cache_set_wwids(void)
+{
+ struct btree_iter *iter;
+ struct device *dev;
+ char buf[WWID_BUF_SIZE];
+ int already = 0;
+ int found = 0;
+ int notfound = 0;
+
+ if (!_cache.devices)
+ return;
+
+ log_debug("Reading wwid for all devices.");
+
+ iter = btree_first(_cache.devices);
+
+ while (iter) {
+ dev = btree_get_data(iter);
+
+ if (dev->wwid) {
+ already++;
+ goto next;
+ }
+
+ memset(buf, 0, sizeof(buf));
+
+ if (dev_read_wwid(dev, buf, sizeof(buf))) {
+ if (buf[0]) {
+ dev->wwid = dm_pool_strdup(_cache.mem, buf);
+ found++;
+ } else
+ notfound++;
+ } else {
+ notfound++;
+ }
+
+ next:
+ iter = btree_next(iter);
+ }
+
+ log_debug("Found wwid for %d devs not found for %d already set for %d.",
+ found, notfound, already);
+}
+
/*
* Check whether path0 or path1 contains the subpath. The path that
* *does not* contain the subpath wins (return 0 or 1). If both paths
@@ -1218,6 +1262,8 @@ void dev_cache_scan(void)
dm_list_iterate_items(dl, &_cache.files)
_insert_file(dl->dir);
+
+ _dev_cache_set_wwids();
}
int dev_cache_has_scanned(void)
diff --git a/lib/device/dev-type.c b/lib/device/dev-type.c
index 14a28dc37..343af9997 100644
--- a/lib/device/dev-type.c
+++ b/lib/device/dev-type.c
@@ -269,6 +269,46 @@ const char *dev_subsystem_name(struct dev_types *dt, struct device *dev)
return "";
}
+#define WWID_BUF_SIZE 512
+
+int dev_read_wwid(struct device *dev, char *outbuf, int outsize)
+{
+ FILE *fp;
+ char path[PATH_MAX];
+ char buf[WWID_BUF_SIZE];
+ int len;
+
+ if (dm_snprintf(path, sizeof(path), "%sdev/block/%d:%d/device/wwid",
+ dm_sysfs_dir(),
+ (int) MAJOR(dev->dev),
+ (int) MINOR(dev->dev)) < 0) {
+ log_warn("Sysfs path for wwid is too long.");
+ return 0;
+ }
+
+ if (!(fp = fopen(path, "r")))
+ return 0;
+
+ if (!fgets(buf, sizeof(buf), fp))
+ log_debug("Empty wwid for %s", dev_name(dev));
+ else {
+ len = strlen(buf);
+
+ if (len > outsize - 1) {
+ log_debug("sysfs wwid len %d too large for buffer %d for %s",
+ len, outsize, dev_name(dev));
+ len = outsize - 1;
+ }
+
+ strncpy(outbuf, buf, outsize);
+ }
+
+ if (fclose(fp))
+ log_sys_debug("fclose", path);
+
+ return 1;
+}
+
int major_max_partitions(struct dev_types *dt, int major)
{
if (major >= NUMBER_OF_MAJORS)
diff --git a/lib/device/dev-type.h b/lib/device/dev-type.h
index bd989f8c8..4d2431d25 100644
--- a/lib/device/dev-type.h
+++ b/lib/device/dev-type.h
@@ -93,4 +93,7 @@ unsigned long dev_discard_granularity(struct dev_types *dt, struct device *dev);
int dev_is_rotational(struct dev_types *dt, struct device *dev);
+#define WWID_BUF_SIZE 512
+int dev_read_wwid(struct device *dev, char *outbuf, int outsize);
+
#endif
diff --git a/lib/device/device.h b/lib/device/device.h
index aafc40114..8d5f04816 100644
--- a/lib/device/device.h
+++ b/lib/device/device.h
@@ -82,6 +82,7 @@ struct device {
const char *vgid; /* if device is an LV */
const char *lvid; /* if device is an LV */
+ const char *wwid;
char pvid[ID_LEN + 1]; /* if device is a PV */
char _padding[7];
diff --git a/lib/filters/filter-mpath.c b/lib/filters/filter-mpath.c
index 6763be33c..888007db4 100644
--- a/lib/filters/filter-mpath.c
+++ b/lib/filters/filter-mpath.c
@@ -15,6 +15,7 @@
#include "lib.h"
#include "filter.h"
#include "activate.h"
+#include "str_list.h"
#ifdef UDEV_SYNC_SUPPORT
#include <libudev.h>
#include "dev-ext-udev-constants.h"
@@ -24,6 +25,11 @@
#include <dirent.h>
+/* FIXME: use config setting to change or disable this wwids file. */
+static const char *_wwids_file = "/etc/multipath/wwids";
+static struct dm_list *_wwids_list; /* struct dm_str_list */
+static struct dm_pool *_wwids_mem;
+
#define MPATH_PREFIX "mpath-"
static const char *_get_sysfs_name(struct device *dev)
@@ -146,7 +152,7 @@ static int _get_parent_mpath(const char *dir, char *name, int max_size)
}
#ifdef UDEV_SYNC_SUPPORT
-static int _udev_dev_is_mpath(struct device *dev)
+static int _udev_dev_is_mpath_component(struct device *dev)
{
const char *value;
struct dev_ext *ext;
@@ -165,13 +171,80 @@ static int _udev_dev_is_mpath(struct device *dev)
return 0;
}
#else
-static int _udev_dev_is_mpath(struct device *dev)
+static int _udev_dev_is_mpath_component(struct device *dev)
{
return 0;
}
#endif
-static int _native_dev_is_mpath(struct dev_filter *f, struct device *dev)
+#define MAX_WWID_LINE 512
+
+/*
+ * N.B. this doesn't account for the multipath.conf blacklist.
+ */
+
+static int _read_wwids_file(void)
+{
+ FILE *fp;
+ char line[MAX_WWID_LINE];
+ char *wwid, *p;
+
+ if (!(fp = fopen(_wwids_file, "r"))) {
+ return_0;
+ }
+
+ if (!(_wwids_mem = dm_pool_create("filter mpath", 1024))) {
+ fclose(fp);
+ fp = NULL;
+ return_0;
+ }
+
+ if (!(_wwids_list = str_list_create(_wwids_mem))) {
+ fclose(fp);
+ fp = NULL;
+ dm_pool_destroy(_wwids_mem);
+ _wwids_mem = NULL;
+ return_0;
+ }
+
+ while (fgets(line, sizeof(line), fp)) {
+ if (line[0] == '#')
+ continue;
+
+ wwid = line;
+
+ if (line[0] == '/')
+ wwid++;
+
+ if ((p = strchr(wwid, '/')))
+ *p = '\0';
+
+ if (!str_list_add_no_dup_check(_wwids_mem, _wwids_list,
+ dm_pool_strdup(_wwids_mem, wwid)))
+ stack;
+ }
+
+ if (fclose(fp))
+ stack;
+
+ return 1;
+}
+
+static int _wwid_dev_is_mpath_component(struct device *dev)
+{
+ if (!_wwids_list)
+ return 0;
+
+ if (!dev->wwid)
+ return 0;
+
+ if (str_list_match_item(_wwids_list, dev->wwid))
+ return 1;
+
+ return 0;
+}
+
+static int _native_dev_is_mpath_component(struct dev_filter *f, struct device *dev)
{
struct dev_types *dt = (struct dev_types *) f->private;
const char *part_name, *name;
@@ -186,6 +259,11 @@ static int _native_dev_is_mpath(struct dev_filter *f, struct device *dev)
if (!major_is_scsi_device(dt, MAJOR(dev->dev)))
return 0;
+ if (_wwid_dev_is_mpath_component(dev)) {
+ log_debug_devs("%s: wwid is mpath component %s", dev_name(dev), dev->wwid);
+ return 1;
+ }
+
switch (dev_get_primary_dev(dt, dev, &primary_dev)) {
case 2: /* The dev is partition. */
part_name = dev_name(dev); /* name of original dev for log_debug msg */
@@ -230,13 +308,13 @@ static int _native_dev_is_mpath(struct dev_filter *f, struct device *dev)
return lvm_dm_prefix_check(major, minor, MPATH_PREFIX);
}
-static int _dev_is_mpath(struct dev_filter *f, struct device *dev)
+static int _dev_is_mpath_component(struct dev_filter *f, struct device *dev)
{
if (dev->ext.src == DEV_EXT_NONE)
- return _native_dev_is_mpath(f, dev);
+ return _native_dev_is_mpath_component(f, dev);
if (dev->ext.src == DEV_EXT_UDEV)
- return _udev_dev_is_mpath(dev);
+ return _udev_dev_is_mpath_component(dev);
log_error(INTERNAL_ERROR "Missing hook for mpath recognition "
"using external device info source %s", dev_ext_name(dev));
@@ -248,7 +326,7 @@ static int _dev_is_mpath(struct dev_filter *f, struct device *dev)
static int _ignore_mpath(struct dev_filter *f, struct device *dev)
{
- if (_dev_is_mpath(f, dev) == 1) {
+ if (_dev_is_mpath_component(f, dev) == 1) {
if (dev->ext.src == DEV_EXT_NONE)
log_debug_devs(MSG_SKIPPING, dev_name(dev));
else
@@ -265,6 +343,10 @@ static void _destroy(struct dev_filter *f)
if (f->use_count)
log_error(INTERNAL_ERROR "Destroying mpath filter while in use %u times.", f->use_count);
+ dm_pool_destroy(_wwids_mem);
+ _wwids_mem = NULL;
+ _wwids_list = NULL;
+
dm_free(f);
}
@@ -283,6 +365,8 @@ struct dev_filter *mpath_filter_create(struct dev_types *dt)
return NULL;
}
+ _read_wwids_file();
+
f->passes_filter = _ignore_mpath;
f->destroy = _destroy;
f->use_count = 0;