summaryrefslogtreecommitdiffstats
path: root/lib/metadata/raid_manip.c
diff options
context:
space:
mode:
authorJonathan Earl Brassow <jbrassow@redhat.com>2012-04-11 01:23:29 +0000
committerJonathan Earl Brassow <jbrassow@redhat.com>2012-04-11 01:23:29 +0000
commitc0b5886f18ffe21e1f32acf3ac7b1ba05b0abede (patch)
tree024ca49da32f6993552a3bd11ab268255b56a413 /lib/metadata/raid_manip.c
parentbad8b5848fe8e83095983fc0f035ab5190b9426a (diff)
downloadlvm2-c0b5886f18ffe21e1f32acf3ac7b1ba05b0abede.tar.gz
lvm2-c0b5886f18ffe21e1f32acf3ac7b1ba05b0abede.tar.xz
lvm2-c0b5886f18ffe21e1f32acf3ac7b1ba05b0abede.zip
RAID LVs could not handle a down-convert if a device other than the last one
in the array was specified for removal. This change addresses that (bz806111).
Diffstat (limited to 'lib/metadata/raid_manip.c')
-rw-r--r--lib/metadata/raid_manip.c18
1 files changed, 16 insertions, 2 deletions
diff --git a/lib/metadata/raid_manip.c b/lib/metadata/raid_manip.c
index ffaab277..96e2bc0b 100644
--- a/lib/metadata/raid_manip.c
+++ b/lib/metadata/raid_manip.c
@@ -975,6 +975,8 @@ static int _raid_extract_images(struct logical_volume *lv, uint32_t new_count,
static int _raid_remove_images(struct logical_volume *lv,
uint32_t new_count, struct dm_list *pvs)
{
+ uint32_t s;
+ struct lv_segment *seg;
struct dm_list removal_list;
struct lv_list *lvl;
@@ -1024,9 +1026,21 @@ static int _raid_remove_images(struct logical_volume *lv,
}
/*
- * Resume original LV
- * This also resumes all other sub-LVs
+ * Resume the remaining LVs
+ * We must start by resuming the sub-LVs first (which would
+ * otherwise be handled automatically) because the shifting
+ * of positions could otherwise cause name collisions. For
+ * example, if position 0 of a 3-way array is removed, position
+ * 1 and 2 must be shifted and renamed 0 and 1. If position 2
+ * tries to rename first, it will collide with the existing
+ * position 1.
*/
+ seg = first_seg(lv);
+ for (s = 0; (new_count > 1) && (s < seg->area_count); s++) {
+ if (!resume_lv(lv->vg->cmd, seg_lv(seg, s)) ||
+ !resume_lv(lv->vg->cmd, seg_metalv(seg, s)))
+ return_0;
+ }
if (!resume_lv(lv->vg->cmd, lv)) {
log_error("Failed to resume %s/%s after committing changes",
lv->vg->name, lv->name);