diff --git a/WHATS_NEW b/WHATS_NEW index ba4ff4606..8fa2d9624 100644 --- a/WHATS_NEW +++ b/WHATS_NEW @@ -1,5 +1,6 @@ Version 2.02.20 - =================================== + Add devices/ignore_suspended_devices to ignore suspended dm devices. Add some missing close() and fclose() return code checks. Fix exit statuses of reporting tools (2.02.19). Add init script for dmeventd monitoring. diff --git a/doc/example.conf b/doc/example.conf index e7195afab..e8ded3925 100644 --- a/doc/example.conf +++ b/doc/example.conf @@ -79,6 +79,12 @@ devices { # software RAID (md) devices by looking for md superblocks. # 1 enables; 0 disables. md_component_detection = 1 + + # If, while scanning the system for PVs, LVM2 encounters a device-mapper + # device that has its I/O suspended, it waits for it to become accessible. + # Set this to 1 to skip such devices. This should only be needed + # in recovery situations. + ignore_suspended_devices = 0 } # This section that allows you to configure the nature of the diff --git a/lib/activate/activate.h b/lib/activate/activate.h index fc34ad5ee..803ac9002 100644 --- a/lib/activate/activate.h +++ b/lib/activate/activate.h @@ -95,4 +95,9 @@ int monitor_dev_for_events(struct cmd_context *cmd, int pv_uses_vg(struct physical_volume *pv, struct volume_group *vg); +/* + * Returns 1 if mapped device is not suspended. + */ +int device_is_usable(dev_t dev); + #endif diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c index 31f95961b..e3f3afae1 100644 --- a/lib/activate/dev_manager.c +++ b/lib/activate/dev_manager.c @@ -25,6 +25,7 @@ #include "targets.h" #include "config.h" #include "filter.h" +#include "activate.h" #include #include @@ -154,6 +155,42 @@ static int _info_run(const char *name, const char *dlid, struct dm_info *info, return r; } +int device_is_usable(dev_t dev) +{ + struct dm_task *dmt; + struct dm_info info; + int r = 0; + + if (!(dmt = dm_task_create(DM_DEVICE_INFO))) { + log_error("Failed to allocate dm_task struct to check dev status"); + return 0; + } + + if (!dm_task_set_major(dmt, MAJOR(dev)) || !dm_task_set_minor(dmt, MINOR(dev))) + goto_out; + + if (!dm_task_run(dmt)) { + log_error("Failed to get state of mapped device"); + goto out; + } + + if (!dm_task_get_info(dmt, &info)) + goto_out; + + if (!info.exists || info.suspended) + goto out; + + /* FIXME Also check for mirror block_on_error and mpath no paths */ + + /* FIXME Also check dependencies? */ + + r = 1; + + out: + dm_task_destroy(dmt); + return r; +} + static int _info(const char *name, const char *dlid, int mknodes, int with_open_count, struct dm_info *info, struct dm_pool *mem, char **uuid_out) diff --git a/lib/commands/toolcontext.c b/lib/commands/toolcontext.c index 53f022aa7..a81ed4265 100644 --- a/lib/commands/toolcontext.c +++ b/lib/commands/toolcontext.c @@ -592,6 +592,9 @@ static int _init_filters(struct cmd_context *cmd, unsigned load_persistent_cache return 0; } + init_ignore_suspended_devices(find_config_tree_int(cmd, + "devices/ignore_suspended_devices", DEFAULT_IGNORE_SUSPENDED_DEVICES)); + dev_cache = find_config_tree_str(cmd, "devices/cache", cache_file); if (!(f4 = persistent_filter_create(f3, dev_cache))) { diff --git a/lib/config/defaults.h b/lib/config/defaults.h index 45610464b..cad77e778 100644 --- a/lib/config/defaults.h +++ b/lib/config/defaults.h @@ -30,6 +30,7 @@ #define DEFAULT_PROC_DIR "/proc" #define DEFAULT_SYSFS_SCAN 1 #define DEFAULT_MD_COMPONENT_DETECTION 1 +#define DEFAULT_IGNORE_SUSPENDED_DEVICES 1 #define DEFAULT_LOCK_DIR "/var/lock/lvm" #define DEFAULT_LOCKING_LIB "liblvm2clusterlock.so" diff --git a/lib/filters/filter.c b/lib/filters/filter.c index 2723b7087..a121b0958 100644 --- a/lib/filters/filter.c +++ b/lib/filters/filter.c @@ -19,6 +19,7 @@ #include "lvm-string.h" #include "config.h" #include "metadata.h" +#include "activate.h" #include #include @@ -37,6 +38,7 @@ typedef struct { } device_info_t; static int _md_major = -1; +static int _device_mapper_major = -1; int md_major(void) { @@ -90,6 +92,13 @@ static int _passes_lvm_type_device_filter(struct dev_filter *f, return 0; } + /* Skip suspended devices */ + if (MAJOR(dev->dev) == _device_mapper_major && + ignore_suspended_devices() && device_is_usable(dev->dev)) { + log_debug("%s: Skipping: Suspended dm device", name); + return 0; + } + /* Check it's accessible */ if (!dev_open_flags(dev, O_RDONLY, 0, 1)) { log_debug("%s: Skipping: open failed", name); @@ -182,10 +191,14 @@ static int _scan_proc_dev(const char *proc, const struct config_node *cn) if (!strncmp("md", line + i, 2) && isspace(*(line + i + 2))) _md_major = line_maj; + /* Look for device-mapper device */ + /* FIXME Cope with multiple majors */ + if (!strncmp("device-mapper", line + i, 13) && isspace(*(line + i + 13))) + _device_mapper_major = line_maj; + /* 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++) { - dev_len = strlen(device_info[j].name); if (dev_len <= strlen(line + i) && !strncmp(device_info[j].name, line + i, dev_len) && diff --git a/lib/log/log.c b/lib/log/log.c index 7015337e5..2e657959e 100644 --- a/lib/log/log.c +++ b/lib/log/log.c @@ -49,6 +49,7 @@ static char _msg_prefix[30] = " "; static int _already_logging = 0; static int _mirror_in_sync = 0; static int _dmeventd_monitor = DEFAULT_DMEVENTD_MONITOR; +static int _ignore_suspended_devices = 0; static lvm2_log_fn_t _lvm2_log_fn = NULL; @@ -195,6 +196,11 @@ void init_dmeventd_monitor(int reg) _dmeventd_monitor = reg; } +void init_ignore_suspended_devices(int ignore) +{ + _ignore_suspended_devices = ignore; +} + void init_cmd_name(int status) { _log_cmd_name = status; @@ -274,6 +280,11 @@ int dmeventd_monitor_mode(void) return _dmeventd_monitor; } +int ignore_suspended_devices(void) +{ + return _ignore_suspended_devices; +} + void init_debug(int level) { _debug_level = level; diff --git a/lib/log/log.h b/lib/log/log.h index 4ff6ff544..1c75cbef4 100644 --- a/lib/log/log.h +++ b/lib/log/log.h @@ -76,6 +76,7 @@ void init_lockingfailed(int level); void init_security_level(int level); void init_mirror_in_sync(int in_sync); void init_dmeventd_monitor(int reg); +void init_ignore_suspended_devices(int ignore); void set_cmd_name(const char *cmd_name); @@ -90,6 +91,7 @@ int ignorelockingfailure(void); int lockingfailed(void); int security_level(void); int mirror_in_sync(void); +int ignore_suspended_devices(void); #define DMEVENTD_MONITOR_IGNORE -1 int dmeventd_monitor_mode(void);