diff --git a/WHATS_NEW b/WHATS_NEW index f893dd0e5..0ee727160 100644 --- a/WHATS_NEW +++ b/WHATS_NEW @@ -1,5 +1,6 @@ Version 2.02.89 - ================================== + Add filter to avoid scan of device if it is part of active multipath. Add missing default $LVM_VG_NAME usage for snapshots. Fix extent_count overflow with lvextend. Add missing lvrename mirrored log recursion in for_each_sub_lv. diff --git a/doc/example.conf.in b/doc/example.conf.in index ed15db6c9..2dd18089c 100644 --- a/doc/example.conf.in +++ b/doc/example.conf.in @@ -103,6 +103,11 @@ devices { # 1 enables; 0 disables. sysfs_scan = 1 + # By default, LVM2 will ignore devices used as component paths + # of device-mapper multipath devices. + # 1 enables; 0 disables. + multipath_component_detection = 1 + # By default, LVM2 will ignore devices used as components of # software RAID (md) devices by looking for md superblocks. # 1 enables; 0 disables. diff --git a/include/.symlinks.in b/include/.symlinks.in index c16e107d9..00d7d55b4 100644 --- a/include/.symlinks.in +++ b/include/.symlinks.in @@ -16,6 +16,7 @@ @top_srcdir@/lib/display/display.h @top_srcdir@/lib/filters/filter-composite.h @top_srcdir@/lib/filters/filter-md.h +@top_srcdir@/lib/filters/filter-mpath.h @top_srcdir@/lib/filters/filter-persistent.h @top_srcdir@/lib/filters/filter-regex.h @top_srcdir@/lib/filters/filter-sysfs.h diff --git a/lib/Makefile.in b/lib/Makefile.in index a46e59603..4e9afd9d4 100644 --- a/lib/Makefile.in +++ b/lib/Makefile.in @@ -65,6 +65,7 @@ SOURCES =\ filters/filter-regex.c \ filters/filter-sysfs.c \ filters/filter-md.c \ + filters/filter-mpath.c \ filters/filter.c \ format_text/archive.c \ format_text/archiver.c \ diff --git a/lib/activate/activate.c b/lib/activate/activate.c index 2b44b1926..37c10f586 100644 --- a/lib/activate/activate.c +++ b/lib/activate/activate.c @@ -147,6 +147,10 @@ int target_present(struct cmd_context *cmd, const char *target_name, { return 0; } +int dm_prefix_check(const char *sysfs_dir, int major, int minor, const char *prefix) +{ + return 0; +} int lv_info(struct cmd_context *cmd, const struct logical_volume *lv, unsigned origin_only, struct lvinfo *info, int with_open_count, int with_read_ahead) { @@ -439,6 +443,29 @@ int target_version(const char *target_name, uint32_t *maj, return r; } +int dm_prefix_check(const char *sysfs_dir, int major, int minor, const char *prefix) +{ + struct dm_task *dmt; + const char *uuid; + int r; + + if (!(dmt = dm_task_create(DM_DEVICE_STATUS))) + return 0; + + if (!dm_task_set_minor(dmt, minor) || + !dm_task_set_major(dmt, major) || + !dm_task_run(dmt) || + !(uuid = dm_task_get_uuid(dmt))) { + dm_task_destroy(dmt); + return 0; + } + + r = strncasecmp(uuid, prefix, strlen(prefix)); + dm_task_destroy(dmt); + + return (r == 0) ? 1 : 0; +} + int module_present(struct cmd_context *cmd, const char *target_name) { int ret = 0; diff --git a/lib/activate/activate.h b/lib/activate/activate.h index 119211dfc..7de1703c0 100644 --- a/lib/activate/activate.h +++ b/lib/activate/activate.h @@ -53,6 +53,7 @@ int target_present(struct cmd_context *cmd, const char *target_name, int use_modprobe); int target_version(const char *target_name, uint32_t *maj, uint32_t *min, uint32_t *patchlevel); +int dm_prefix_check(const char *sysfs_dir, int major, int minor, const char *prefix); int list_segment_modules(struct dm_pool *mem, const struct lv_segment *seg, struct dm_list *modules); int list_lv_modules(struct dm_pool *mem, const struct logical_volume *lv, diff --git a/lib/commands/toolcontext.c b/lib/commands/toolcontext.c index 4dc4c2660..ec6e40011 100644 --- a/lib/commands/toolcontext.c +++ b/lib/commands/toolcontext.c @@ -22,6 +22,7 @@ #include "filter.h" #include "filter-composite.h" #include "filter-md.h" +#include "filter-mpath.h" #include "filter-persistent.h" #include "filter-regex.h" #include "filter-sysfs.h" @@ -714,7 +715,7 @@ static int _init_dev_cache(struct cmd_context *cmd) return 1; } -#define MAX_FILTERS 4 +#define MAX_FILTERS 5 static struct dev_filter *_init_filter_components(struct cmd_context *cmd) { @@ -766,6 +767,13 @@ static struct dev_filter *_init_filter_components(struct cmd_context *cmd) nr_filt++; } + /* mpath component filter. Optional, non-critical. */ + if (find_config_tree_bool(cmd, "devices/multipath_component_detection", + DEFAULT_MULTIPATH_COMPONENT_DETECTION)) { + if ((filters[nr_filt] = mpath_filter_create(cmd->sysfs_dir))) + nr_filt++; + } + /* Only build a composite filter if we really need it. */ return (nr_filt == 1) ? filters[0] : composite_filter_create(nr_filt, filters); diff --git a/lib/config/defaults.h b/lib/config/defaults.h index 6819a9a80..9b91aea51 100644 --- a/lib/config/defaults.h +++ b/lib/config/defaults.h @@ -33,6 +33,7 @@ #define DEFAULT_SYSFS_SCAN 1 #define DEFAULT_MD_COMPONENT_DETECTION 1 #define DEFAULT_MD_CHUNK_ALIGNMENT 1 +#define DEFAULT_MULTIPATH_COMPONENT_DETECTION 1 #define DEFAULT_IGNORE_SUSPENDED_DEVICES 1 #define DEFAULT_DISABLE_AFTER_ERROR_COUNT 0 #define DEFAULT_REQUIRE_RESTOREFILE_WITH_UUID 1 diff --git a/lib/filters/filter.c b/lib/filters/filter.c index f2398a1f2..68f65a034 100644 --- a/lib/filters/filter.c +++ b/lib/filters/filter.c @@ -29,8 +29,11 @@ #define NUMBER_OF_MAJORS 4096 -/* 0 means LVM won't use this major number. */ -static int _max_partitions_by_major[NUMBER_OF_MAJORS]; +#define PARTITION_SCSI_DEVICE (1 << 0) +static struct { + int max_partitions; /* 0 means LVM won't use this major number. */ + int flags; +} _partitions[NUMBER_OF_MAJORS]; typedef struct { const char *name; @@ -140,7 +143,7 @@ static int _passes_lvm_type_device_filter(struct dev_filter *f __attribute__((un uint64_t size; /* Is this a recognised device type? */ - if (!_max_partitions_by_major[MAJOR(dev->dev)]) { + if (!_partitions[MAJOR(dev->dev)].max_partitions) { log_debug("%s: Skipping: Unrecognised LVM device type %" PRIu64, name, (uint64_t) MAJOR(dev->dev)); return 0; @@ -194,12 +197,12 @@ static int _scan_proc_dev(const char *proc, const struct dm_config_node *cn) log_verbose("No proc filesystem found: using all block device " "types"); for (i = 0; i < NUMBER_OF_MAJORS; i++) - _max_partitions_by_major[i] = 1; + _partitions[i].max_partitions = 1; return 1; } /* All types unrecognised initially */ - memset(_max_partitions_by_major, 0, sizeof(int) * NUMBER_OF_MAJORS); + memset(_partitions, 0, sizeof(_partitions)); if (dm_snprintf(proc_devices, sizeof(proc_devices), "%s/devices", proc) < 0) { @@ -251,6 +254,10 @@ static int _scan_proc_dev(const char *proc, const struct dm_config_node *cn) if (!strncmp("device-mapper", line + i, 13) && isspace(*(line + i + 13))) _device_mapper_major = line_maj; + /* Major is SCSI device */ + if (!strncmp("sd", line + i, 2) && isspace(*(line + i + 2))) + _partitions[line_maj].flags |= PARTITION_SCSI_DEVICE; + /* Go through the valid device names and if there is a match store max number of partitions */ for (j = 0; device_info[j].name != NULL; j++) { @@ -258,7 +265,7 @@ static int _scan_proc_dev(const char *proc, const struct dm_config_node *cn) if (dev_len <= strlen(line + i) && !strncmp(device_info[j].name, line + i, dev_len) && (line_maj < NUMBER_OF_MAJORS)) { - _max_partitions_by_major[line_maj] = + _partitions[line_maj].max_partitions = device_info[j].max_partitions; break; } @@ -298,7 +305,7 @@ static int _scan_proc_dev(const char *proc, const struct dm_config_node *cn) if (dev_len <= strlen(line + i) && !strncmp(name, line + i, dev_len) && (line_maj < NUMBER_OF_MAJORS)) { - _max_partitions_by_major[line_maj] = cv->v.i; + _partitions[line_maj].max_partitions = cv->v.i; break; } } @@ -312,7 +319,18 @@ static int _scan_proc_dev(const char *proc, const struct dm_config_node *cn) int max_partitions(int major) { - return _max_partitions_by_major[major]; + if (major > NUMBER_OF_MAJORS) + return 0; + + return _partitions[major].max_partitions; +} + +int major_is_scsi_device(int major) +{ + if (major > NUMBER_OF_MAJORS) + return 0; + + return (_partitions[major].flags & PARTITION_SCSI_DEVICE) ? 1 : 0; } struct dev_filter *lvm_type_filter_create(const char *proc, diff --git a/lib/filters/filter.h b/lib/filters/filter.h index 5c6047a44..21cb89bde 100644 --- a/lib/filters/filter.h +++ b/lib/filters/filter.h @@ -39,6 +39,7 @@ int dm_major(void); int md_major(void); int blkext_major(void); int max_partitions(int major); +int major_is_scsi_device(int major); int dev_subsystem_part_major(const struct device *dev); const char *dev_subsystem_name(const struct device *dev);