summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZdenek Kabelac <zkabelac@redhat.com>2019-03-13 13:02:09 +0100
committerZdenek Kabelac <zkabelac@redhat.com>2019-03-20 14:37:42 +0100
commitdc6dea40331687b8740cc48833f4c7c42a2db1a1 (patch)
tree430a6ba08435388179e7c5981f592ec97c22a914
parent1eeb2fa3f687e71a541299383fe15bdb9e5a8088 (diff)
downloadlvm2-dc6dea40331687b8740cc48833f4c7c42a2db1a1.tar.gz
filter: enhance mpath detection
Internal detection of SCSI device being in-use by DM mpath has been performed several times for each component device - this could be eventually racy - so instead when we do remember 1st. checked result for device being mpath and use it consistenly over the filter runtime.
-rw-r--r--WHATS_NEW1
-rw-r--r--lib/filters/filter-mpath.c78
2 files changed, 67 insertions, 12 deletions
diff --git a/WHATS_NEW b/WHATS_NEW
index 168b26739..ad9282759 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.03.02 -
===================================
+ Query mpath device only once per command for its state.
Use device INFO instead of STATUS when checking for mpath device uuid.
Change default io_memory_size from 4 to 8 MiB.
Add config setting io_memory_size to set bcache size.
diff --git a/lib/filters/filter-mpath.c b/lib/filters/filter-mpath.c
index f0374b4d0..25a507c55 100644
--- a/lib/filters/filter-mpath.c
+++ b/lib/filters/filter-mpath.c
@@ -27,6 +27,14 @@
#define MPATH_PREFIX "mpath-"
+
+struct mpath_priv {
+ struct dm_pool *mem;
+ struct dev_filter f;
+ struct dev_types *dt;
+ struct dm_hash_table *hash;
+};
+
static const char *_get_sysfs_name(struct device *dev)
{
const char *name;
@@ -174,7 +182,8 @@ static int _udev_dev_is_mpath(struct device *dev)
static int _native_dev_is_mpath(struct dev_filter *f, struct device *dev)
{
- struct dev_types *dt = (struct dev_types *) f->private;
+ struct mpath_priv *mp = (struct mpath_priv *) f->private;
+ struct dev_types *dt = mp->dt;
const char *part_name, *name;
struct stat info;
char path[PATH_MAX], parent_name[PATH_MAX];
@@ -182,6 +191,7 @@ static int _native_dev_is_mpath(struct dev_filter *f, struct device *dev)
int major = MAJOR(dev->dev);
int minor = MINOR(dev->dev);
dev_t primary_dev;
+ long look;
/* Limit this filter only to SCSI devices */
if (!major_is_scsi_device(dt, MAJOR(dev->dev)))
@@ -228,7 +238,22 @@ static int _native_dev_is_mpath(struct dev_filter *f, struct device *dev)
if (major != dt->device_mapper_major)
return 0;
- return lvm_dm_prefix_check(major, minor, MPATH_PREFIX);
+ /* Avoid repeated detection of multipath device and use first checked result */
+ look = (long) dm_hash_lookup_binary(mp->hash, &minor, sizeof(minor));
+ if (look > 0) {
+ log_debug_devs("%s(%u:%u): already checked as %sbeing mpath.",
+ parent_name, major, minor, (look > 1) ? "" : "not ");
+ return (look > 1) ? 0 : 1;
+ }
+
+ if (lvm_dm_prefix_check(major, minor, MPATH_PREFIX)) {
+ (void) dm_hash_insert_binary(mp->hash, &minor, sizeof(minor), (void*)2);
+ return 1;
+ }
+
+ (void) dm_hash_insert_binary(mp->hash, &minor, sizeof(minor), (void*)1);
+
+ return 0;
}
static int _dev_is_mpath(struct dev_filter *f, struct device *dev)
@@ -263,36 +288,65 @@ static int _ignore_mpath(struct cmd_context *cmd, struct dev_filter *f, struct d
static void _destroy(struct dev_filter *f)
{
+ struct mpath_priv *mp = (struct mpath_priv*) f->private;
+
if (f->use_count)
log_error(INTERNAL_ERROR "Destroying mpath filter while in use %u times.", f->use_count);
- free(f);
+ dm_hash_destroy(mp->hash);
+ dm_pool_destroy(mp->mem);
}
struct dev_filter *mpath_filter_create(struct dev_types *dt)
{
const char *sysfs_dir = dm_sysfs_dir();
- struct dev_filter *f;
+ struct dm_pool *mem;
+ struct mpath_priv *mp;
+ struct dm_hash_table *hash;
if (!*sysfs_dir) {
log_verbose("No proc filesystem found: skipping multipath filter");
return NULL;
}
- if (!(f = zalloc(sizeof(*f)))) {
- log_error("mpath filter allocation failed");
+ if (!(hash = dm_hash_create(128))) {
+ log_error("mpath hash table creation failed.");
return NULL;
}
- f->passes_filter = _ignore_mpath;
- f->destroy = _destroy;
- f->use_count = 0;
- f->private = dt;
- f->name = "mpath";
+ if (!(mem = dm_pool_create("mpath", 256))) {
+ log_error("mpath pool creation failed.");
+ dm_hash_destroy(hash);
+ return NULL;
+ }
+
+ if (!(mp = dm_pool_zalloc(mem, sizeof(*mp)))) {
+ log_error("mpath filter allocation failed.");
+ goto bad;
+ }
+
+ if (!(mp = dm_pool_zalloc(mem, sizeof(*mp)))) {
+ log_error("mpath filter allocation failed.");
+ goto bad;
+ }
+
+ mp->f.passes_filter = _ignore_mpath;
+ mp->f.destroy = _destroy;
+ mp->f.use_count = 0;
+ mp->f.private = mp;
+ mp->f.name = "mpath";
+
+ mp->mem = mem;
+ mp->dt = dt;
+ mp->hash = hash;
log_debug_devs("mpath filter initialised.");
- return f;
+ return &mp->f;
+bad:
+ dm_pool_destroy(mem);
+ dm_hash_destroy(hash);
+ return NULL;
}
#else