1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-01-02 01:18:26 +03:00

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.
This commit is contained in:
Zdenek Kabelac 2019-03-13 13:02:09 +01:00
parent 1eeb2fa3f6
commit dc6dea4033
2 changed files with 67 additions and 12 deletions

View File

@ -1,5 +1,6 @@
Version 2.03.02 - 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. Use device INFO instead of STATUS when checking for mpath device uuid.
Change default io_memory_size from 4 to 8 MiB. Change default io_memory_size from 4 to 8 MiB.
Add config setting io_memory_size to set bcache size. Add config setting io_memory_size to set bcache size.

View File

@ -27,6 +27,14 @@
#define MPATH_PREFIX "mpath-" #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) static const char *_get_sysfs_name(struct device *dev)
{ {
const char *name; 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) 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; const char *part_name, *name;
struct stat info; struct stat info;
char path[PATH_MAX], parent_name[PATH_MAX]; 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 major = MAJOR(dev->dev);
int minor = MINOR(dev->dev); int minor = MINOR(dev->dev);
dev_t primary_dev; dev_t primary_dev;
long look;
/* Limit this filter only to SCSI devices */ /* Limit this filter only to SCSI devices */
if (!major_is_scsi_device(dt, MAJOR(dev->dev))) 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) if (major != dt->device_mapper_major)
return 0; 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) 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) static void _destroy(struct dev_filter *f)
{ {
struct mpath_priv *mp = (struct mpath_priv*) f->private;
if (f->use_count) if (f->use_count)
log_error(INTERNAL_ERROR "Destroying mpath filter while in use %u times.", 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) struct dev_filter *mpath_filter_create(struct dev_types *dt)
{ {
const char *sysfs_dir = dm_sysfs_dir(); 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) { if (!*sysfs_dir) {
log_verbose("No proc filesystem found: skipping multipath filter"); log_verbose("No proc filesystem found: skipping multipath filter");
return NULL; return NULL;
} }
if (!(f = zalloc(sizeof(*f)))) { if (!(hash = dm_hash_create(128))) {
log_error("mpath filter allocation failed"); log_error("mpath hash table creation failed.");
return NULL; return NULL;
} }
f->passes_filter = _ignore_mpath; if (!(mem = dm_pool_create("mpath", 256))) {
f->destroy = _destroy; log_error("mpath pool creation failed.");
f->use_count = 0; dm_hash_destroy(hash);
f->private = dt; return NULL;
f->name = "mpath"; }
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."); log_debug_devs("mpath filter initialised.");
return f; return &mp->f;
bad:
dm_pool_destroy(mem);
dm_hash_destroy(hash);
return NULL;
} }
#else #else