summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Teigland <teigland@redhat.com>2017-09-01 15:13:09 -0500
committerDavid Teigland <teigland@redhat.com>2017-10-18 14:10:15 -0500
commit657d6de15f01c787b75abc4f739514f6114bb521 (patch)
treeb3fa810d3d1fe1ec0b1920666c96de7cf474a1dd
parent5b8ba61d8d67f59dfcd86ecf0e5a193c5b21f4e7 (diff)
downloadlvm2-657d6de15f01c787b75abc4f739514f6114bb521.tar.gz
lvmcache: add list of defective devices
Add a new class of PV. A "defective device" belongs to lvm, but has labels/headers/metadata that are corrupt, invalid, unparsable, or not understood by lvm in some way. LVM can't use the device in this condition, so it puts in into the new class of defective devices, which are displayed by 'pvs' but are otherwise not usable.
-rw-r--r--lib/cache/lvmcache.c71
-rw-r--r--lib/cache/lvmcache.h6
-rw-r--r--tools/command.c1
-rw-r--r--tools/commands.h13
-rw-r--r--tools/toollib.c63
-rw-r--r--tools/tools.h2
6 files changed, 149 insertions, 7 deletions
diff --git a/lib/cache/lvmcache.c b/lib/cache/lvmcache.c
index e753dd0ff..4f8706bf1 100644
--- a/lib/cache/lvmcache.c
+++ b/lib/cache/lvmcache.c
@@ -105,6 +105,7 @@ static struct dm_hash_table *_vgid_hash = NULL;
static struct dm_hash_table *_vgname_hash = NULL;
static struct dm_hash_table *_lock_hash = NULL;
static DM_LIST_INIT(_vginfos);
+static DM_LIST_INIT(_found_defective_devs);
static DM_LIST_INIT(_found_duplicate_devs);
static DM_LIST_INIT(_unused_duplicate_devs);
static int _scanning_in_progress = 0;
@@ -123,6 +124,7 @@ int lvmcache_init(void)
_vgs_locked = 0;
dm_list_init(&_vginfos);
+ dm_list_init(&_found_defective_devs);
dm_list_init(&_found_duplicate_devs);
dm_list_init(&_unused_duplicate_devs);
@@ -524,7 +526,7 @@ void lvmcache_remove_unchosen_duplicate(struct device *dev)
}
}
-static void _destroy_duplicate_device_list(struct dm_list *head)
+static void _destroy_device_list(struct dm_list *head)
{
struct device_list *devl, *devl2;
@@ -956,7 +958,7 @@ next:
}
if (!alt) {
- _destroy_duplicate_device_list(&_unused_duplicate_devs);
+ _destroy_device_list(&_unused_duplicate_devs);
dm_list_splice(&_unused_duplicate_devs, &new_unused);
return;
}
@@ -1266,7 +1268,12 @@ int lvmcache_label_scan(struct cmd_context *cmd)
/*
* Duplicates found during this label scan are added to _found_duplicate_devs().
*/
- _destroy_duplicate_device_list(&_found_duplicate_devs);
+ _destroy_device_list(&_found_duplicate_devs);
+
+ /*
+ * Devs found during this label scan that have problems so they can't be used.
+ */
+ _destroy_device_list(&_found_defective_devs);
/*
* Do the actual scanning. This populates lvmcache
@@ -2320,10 +2327,12 @@ void lvmcache_destroy(struct cmd_context *cmd, int retain_orphans, int reset)
*/
dm_list_init(&cmd->unused_duplicate_devs);
lvmcache_get_unused_duplicate_devs(cmd, &cmd->unused_duplicate_devs);
- _destroy_duplicate_device_list(&_unused_duplicate_devs);
- _destroy_duplicate_device_list(&_found_duplicate_devs); /* should be empty anyway */
+ _destroy_device_list(&_unused_duplicate_devs);
+ _destroy_device_list(&_found_duplicate_devs); /* should be empty anyway */
_found_duplicate_pvs = 0;
+ _destroy_device_list(&_found_defective_devs);
+
if (retain_orphans)
if (!init_lvmcache_orphans(cmd))
stack;
@@ -2664,6 +2673,58 @@ int lvmcache_uncertain_ownership(struct lvmcache_info *info) {
return mdas_empty_or_ignored(&info->mdas);
}
+void lvmcache_remove_defective_dev(struct device *dev)
+{
+ struct device_list *devl;
+
+ dm_list_iterate_items(devl, &_found_defective_devs) {
+ if (devl->dev == dev) {
+ dm_list_del(&devl->list);
+ return;
+ }
+ }
+}
+
+/*
+ * FIXME: We might need to use a new struct for this list that can hold more
+ * info about the defective dev.
+ */
+
+int lvmcache_add_defective_dev(struct device *dev)
+{
+ struct device_list *devl;
+
+ if (_dev_in_device_list(dev, &_found_defective_devs))
+ return 1;
+
+ if (!(devl = dm_zalloc(sizeof(*devl))))
+ return_0;
+ devl->dev = dev;
+
+ dm_list_add(&_found_defective_devs, &devl->list);
+ return 1;
+}
+
+int lvmcache_dev_is_defective(struct device *dev)
+{
+ return _dev_in_device_list(dev, &_found_defective_devs);
+}
+
+int lvmcache_get_defective_devs(struct cmd_context *cmd, struct dm_list *head)
+{
+ struct device_list *devl, *devl2;
+
+ dm_list_iterate_items(devl, &_found_defective_devs) {
+ if (!(devl2 = dm_pool_alloc(cmd->mem, sizeof(*devl2)))) {
+ log_error("device_list element allocation failed");
+ return 0;
+ }
+ devl2->dev = devl->dev;
+ dm_list_add(head, &devl2->list);
+ }
+ return 1;
+}
+
uint64_t lvmcache_smallest_mda_size(struct lvmcache_info *info)
{
if (!info)
diff --git a/lib/cache/lvmcache.h b/lib/cache/lvmcache.h
index e36284c24..902df845b 100644
--- a/lib/cache/lvmcache.h
+++ b/lib/cache/lvmcache.h
@@ -220,4 +220,10 @@ int lvmcache_get_vg_devs(struct cmd_context *cmd,
struct dm_list *devs);
void lvmcache_set_independent_location(const char *vgname);
+
+void lvmcache_remove_defective_dev(struct device *dev);
+int lvmcache_add_defective_dev(struct device *dev);
+int lvmcache_dev_is_defective(struct device *dev);
+int lvmcache_get_defective_devs(struct cmd_context *cmd, struct dm_list *head);
+
#endif
diff --git a/tools/command.c b/tools/command.c
index 17b5eb40e..3a4253b3f 100644
--- a/tools/command.c
+++ b/tools/command.c
@@ -140,6 +140,7 @@ static inline int configtype_arg(struct cmd_context *cmd __attribute__((unused))
#define ENABLE_DUPLICATE_DEVS 0x00000400
#define DISALLOW_TAG_ARGS 0x00000800
#define GET_VGNAME_FROM_OPTIONS 0x00001000
+#define ENABLE_DEFECTIVE_DEVS 0x00002000
/* create foo_CMD enums for command def ID's in command-lines.in */
diff --git a/tools/commands.h b/tools/commands.h
index 17a8ca524..28589ffbd 100644
--- a/tools/commands.h
+++ b/tools/commands.h
@@ -127,7 +127,11 @@ xx(pvdata,
xx(pvdisplay,
"Display various attributes of physical volume(s)",
- PERMITTED_READ_ONLY | ENABLE_ALL_DEVS | ENABLE_DUPLICATE_DEVS | LOCKD_VG_SH)
+ PERMITTED_READ_ONLY |
+ ENABLE_ALL_DEVS |
+ ENABLE_DUPLICATE_DEVS |
+ ENABLE_DEFECTIVE_DEVS |
+ LOCKD_VG_SH)
/* ALL_VGS_IS_DEFAULT is for polldaemon to find pvmoves in-progress using process_each_vg. */
@@ -145,7 +149,12 @@ xx(pvremove,
xx(pvs,
"Display information about physical volumes",
- PERMITTED_READ_ONLY | ALL_VGS_IS_DEFAULT | ENABLE_ALL_DEVS | ENABLE_DUPLICATE_DEVS | LOCKD_VG_SH)
+ PERMITTED_READ_ONLY |
+ ALL_VGS_IS_DEFAULT |
+ ENABLE_ALL_DEVS |
+ ENABLE_DUPLICATE_DEVS |
+ ENABLE_DEFECTIVE_DEVS |
+ LOCKD_VG_SH)
xx(pvscan,
"List all physical volumes",
diff --git a/tools/toollib.c b/tools/toollib.c
index 5bc362846..cd72fb130 100644
--- a/tools/toollib.c
+++ b/tools/toollib.c
@@ -4144,6 +4144,62 @@ static int _process_duplicate_pvs(struct cmd_context *cmd,
return ECMD_PROCESSED;
}
+/*
+ * FIXME: add a new letter for defective devs to show in pv_attr and
+ * a new reporting field pvs -o defective.
+ */
+
+static int _process_defective_pvs(struct cmd_context *cmd,
+ struct dm_list *all_devices,
+ struct dm_list *arg_devices,
+ int process_all_devices,
+ struct processing_handle *handle,
+ process_single_pv_fn_t process_single_pv)
+{
+ struct physical_volume pv_dummy;
+ struct physical_volume *pv;
+ struct device_id_list *dil;
+ struct device_list *devl;
+ struct dm_list defective_devs;
+ int ret_max = ECMD_PROCESSED;
+ int ret = 0;
+
+ dm_list_init(&defective_devs);
+
+ if (!lvmcache_get_defective_devs(cmd, &defective_devs))
+ return_ECMD_FAILED;
+
+ dm_list_iterate_items(devl, &defective_devs) {
+
+ _device_list_remove(all_devices, devl->dev);
+
+ if ((dil = _device_list_find_dev(arg_devices, devl->dev)))
+ _device_list_remove(arg_devices, devl->dev);
+
+ if (!(cmd->cname->flags & ENABLE_DEFECTIVE_DEVS))
+ continue;
+
+ log_very_verbose("Processing defective device %s.", dev_name(devl->dev));
+
+ memset(&pv_dummy, 0, sizeof(pv_dummy));
+ dm_list_init(&pv_dummy.tags);
+ dm_list_init(&pv_dummy.segments);
+ pv_dummy.dev = devl->dev;
+ pv_dummy.fmt = cmd->fmt;
+ pv = &pv_dummy;
+
+ ret = process_single_pv(cmd, NULL, pv, handle);
+
+ if (ret > ret_max)
+ ret_max = ret;
+
+ if (sigint_caught())
+ return_ECMD_FAILED;
+ }
+
+ return ECMD_PROCESSED;
+}
+
static int _process_pvs_in_vg(struct cmd_context *cmd,
struct volume_group *vg,
struct dm_list *all_devices,
@@ -4545,6 +4601,13 @@ int process_each_pv(struct cmd_context *cmd,
if (ret > ret_max)
ret_max = ret;
+ ret = _process_defective_pvs(cmd, &all_devices, &arg_devices, process_all_devices,
+ handle, process_single_pv);
+ if (ret != ECMD_PROCESSED)
+ stack;
+ if (ret > ret_max)
+ ret_max = ret;
+
/*
* If the orphans lock was held, there shouldn't be missed devices. If
* there were, we cannot clear the cache while holding the orphans lock
diff --git a/tools/tools.h b/tools/tools.h
index 0ba42f5ae..a65a9ea6b 100644
--- a/tools/tools.h
+++ b/tools/tools.h
@@ -136,6 +136,8 @@ struct arg_value_group_list {
#define DISALLOW_TAG_ARGS 0x00000800
/* Command may need to find VG name in an option value. */
#define GET_VGNAME_FROM_OPTIONS 0x00001000
+/* Command should process defective devices. */
+#define ENABLE_DEFECTIVE_DEVS 0x00002000
void usage(const char *name);