summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlasdair Kergon <agk@redhat.com>2012-04-24 00:51:26 +0000
committerAlasdair Kergon <agk@redhat.com>2012-04-24 00:51:26 +0000
commit067184f32d634e73ee58c61ba5892994f7f5fe9f (patch)
treee5b56f061f897f4152ffcbf0ee9ff73162d5dfda
parentc62f9f0b2fd4f288349a535e9a99a1e5b883ebbf (diff)
downloadlvm2-067184f32d634e73ee58c61ba5892994f7f5fe9f.tar.gz
lvm2-067184f32d634e73ee58c61ba5892994f7f5fe9f.tar.xz
lvm2-067184f32d634e73ee58c61ba5892994f7f5fe9f.zip
Handle replacement of an active device that goes missing with an error device.
(E.g. lvchange --refresh --partial on striped LV if a PV disappeared.)
-rw-r--r--WHATS_NEW3
-rw-r--r--lib/activate/dev_manager.c32
2 files changed, 27 insertions, 8 deletions
diff --git a/WHATS_NEW b/WHATS_NEW
index 487786b5..daec7117 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,6 +1,7 @@
Version 2.02.96 -
================================
- Unlike 'mirror' segtype, 'raid1' should perform flush on suspend.
+ Handle replacement of an active device that goes missing with an error device.
+ Change change raid1 segtype always to request a flush when suspending.
Add udev info and context to lvmdump.
Fix RAID device replacement code so that it works under snapshot.
Fix inability to split RAID1 image while specifying a particular PV.
diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c
index 84a5e57c..be99e8cf 100644
--- a/lib/activate/dev_manager.c
+++ b/lib/activate/dev_manager.c
@@ -1423,10 +1423,11 @@ bad:
static char *_add_error_device(struct dev_manager *dm, struct dm_tree *dtree,
struct lv_segment *seg, int s)
{
- char *id, *name;
+ char *dlid, *name;
char errid[32];
struct dm_tree_node *node;
struct lv_segment *seg_i;
+ struct dm_info info;
int segno = -1, i = 0;
uint64_t size = (uint64_t) seg->len * seg->lv->vg->extent_size;
@@ -1443,18 +1444,35 @@ static char *_add_error_device(struct dev_manager *dm, struct dm_tree *dtree,
sprintf(errid, "missing_%d_%d", segno, s);
- if (!(id = build_dm_uuid(dm->mem, seg->lv->lvid.s, errid)))
+ if (!(dlid = build_dm_uuid(dm->mem, seg->lv->lvid.s, errid)))
return_NULL;
if (!(name = dm_build_dm_name(dm->mem, seg->lv->vg->name,
seg->lv->name, errid)))
return_NULL;
- if (!(node = dm_tree_add_new_dev(dtree, name, id, 0, 0, 0, 0, 0)))
- return_NULL;
- if (!dm_tree_node_add_error_target(node, size))
- return_NULL;
- return id;
+ log_debug("Getting device info for %s [%s]", name, dlid);
+ if (!_info(dlid, 1, 0, &info, NULL)) {
+ log_error("Failed to get info for %s [%s].", name, dlid);
+ return 0;
+ }
+
+ if (!info.exists) {
+ /* Create new node */
+ if (!(node = dm_tree_add_new_dev(dtree, name, dlid, 0, 0, 0, 0, 0)))
+ return_NULL;
+ if (!dm_tree_node_add_error_target(node, size))
+ return_NULL;
+ } else {
+ /* Already exists */
+ if (!dm_tree_add_dev(dtree, info.major, info.minor)) {
+ log_error("Failed to add device (%" PRIu32 ":%" PRIu32") to dtree",
+ info.major, info.minor);
+ return_NULL;
+ }
+ }
+
+ return dlid;
}
static int _add_error_area(struct dev_manager *dm, struct dm_tree_node *node,