diff options
author | David Teigland <teigland@redhat.com> | 2019-08-22 17:02:27 -0500 |
---|---|---|
committer | David Teigland <teigland@redhat.com> | 2019-08-22 17:03:35 -0500 |
commit | f15564d18efa2e8bd2d7092535134d4ea60439d4 (patch) | |
tree | 6f3f0d8afae8aab3d15b0930eb913f97d1dd33e2 | |
parent | 4a3e1ac7407dff9e53c5efea179a5620ad13f8f3 (diff) | |
download | lvm2-dev-dct-stable-filter-wwid.tar.gz |
filter: use wwid for mpath filterdev-dct-stable-filter-wwid
-rw-r--r-- | lib/device/dev-cache.c | 46 | ||||
-rw-r--r-- | lib/device/dev-type.c | 40 | ||||
-rw-r--r-- | lib/device/dev-type.h | 3 | ||||
-rw-r--r-- | lib/device/device.h | 1 | ||||
-rw-r--r-- | lib/filters/filter-mpath.c | 98 |
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; |