[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[lvm-devel] [patch 1/1] Update vgsplit to only reject splits involving active LVs.



Prior to this change, a VG with any active LVs would cause vgsplit
to fail.  However there should be no reason we cannot split a VG,
provided the LVs involved in the split are inactive.

Fixes bz 252041.

Signed-off-by: Dave Wysochanski <dwysocha redhat com>
---
 lib/activate/activate.c     |    6 ++--
 lib/activate/activate.h     |    2 +
 test/t-vgsplit-operation.sh |   62 +++++++++++++++++++++++++++++++++++++++---
 tools/vgchange.c            |    8 +++---
 tools/vgsplit.c             |   54 ++++++++++++++++++++-----------------
 5 files changed, 95 insertions(+), 37 deletions(-)

diff --git a/lib/activate/activate.c b/lib/activate/activate.c
index 7b959cd..fe18a5e 100644
--- a/lib/activate/activate.c
+++ b/lib/activate/activate.c
@@ -542,8 +542,8 @@ int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv,
 	return r;
 }
 
-static int _lv_active(struct cmd_context *cmd, struct logical_volume *lv,
-		      unsigned by_uuid_only)
+int lv_active(struct cmd_context *cmd, struct logical_volume *lv,
+	      unsigned by_uuid_only)
 {
 	struct lvinfo info;
 
@@ -641,7 +641,7 @@ static int _lvs_in_vg_activated(struct volume_group *vg, unsigned by_uuid_only)
 
 	list_iterate_items(lvl, &vg->lvs) {
 		if (lvl->lv->status & VISIBLE_LV)
-			count += (_lv_active(vg->cmd, lvl->lv, by_uuid_only) == 1);
+			count += (lv_active(vg->cmd, lvl->lv, by_uuid_only) == 1);
 	}
 
 	return count;
diff --git a/lib/activate/activate.h b/lib/activate/activate.h
index ec68251..b86e1b0 100644
--- a/lib/activate/activate.h
+++ b/lib/activate/activate.h
@@ -91,6 +91,8 @@ int lvs_in_vg_activated(struct volume_group *vg);
 int lvs_in_vg_activated_by_uuid_only(struct volume_group *vg);
 int lvs_in_vg_opened(const struct volume_group *vg);
 
+int lv_active(struct cmd_context *cmd, struct logical_volume *lv,
+	      unsigned by_uuid_only);
 
 int monitor_dev_for_events(struct cmd_context *cmd,
 			    struct logical_volume *lv, int do_reg);
diff --git a/test/t-vgsplit-operation.sh b/test/t-vgsplit-operation.sh
index 58a054e..3a32141 100755
--- a/test/t-vgsplit-operation.sh
+++ b/test/t-vgsplit-operation.sh
@@ -222,7 +222,7 @@ test_expect_success \
    lvcreate -l 4 -n $lv3 -i 2 $vg1 $d3 $d4 &&
    vgchange -an $vg1 &&
    vgsplit -n $lv1 $vg1 $vg2;
-   status=$?; echo status=$?; test $status = 5 &&
+   status=$?; echo status=$status; test $status = 5 &&
    vgremove -ff $vg1'
 
 test_expect_success \
@@ -234,7 +234,7 @@ test_expect_success \
    vg_validate_pvlv_counts_ $vg1 4 1 2 &&
    vgchange -an $vg1 &&
    vgsplit -n $lv1 $vg1 $vg2;
-   status=$?; echo status=$?; test $status = 5 &&
+   status=$?; echo status=$status; test $status = 5 &&
    lvremove -f $vg1/$lv2 &&
    lvremove -f $vg1/$lv3 &&
    lvremove -f $vg1/$lv1 &&
@@ -249,7 +249,7 @@ test_expect_success \
    vg_validate_pvlv_counts_ $vg1 4 1 2 &&
    vgchange -an $vg1 &&
    vgsplit -n $lv2 $vg1 $vg2;
-   status=$?; echo status=$?; test $status = 5 &&
+   status=$?; echo status=$status; test $status = 5 &&
    lvremove -f $vg1/$lv2 &&
    lvremove -f $vg1/$lv3 &&
    lvremove -f $vg1/$lv1 &&
@@ -262,7 +262,7 @@ test_expect_success \
    vg_validate_pvlv_counts_ $vg1 4 4 0 &&
    vgchange -an $vg1 &&
    vgsplit $vg1 $vg2 $d2 &&
-   status=$?; echo status=$?; test $status = 5 &&
+   status=$?; echo status=$status; test $status = 5 &&
    vgremove -ff $vg1'
 
 test_expect_success \
@@ -273,8 +273,60 @@ test_expect_success \
    vg_validate_pvlv_counts_ $vg1 4 5 0 &&
    vgchange -an $vg1 &&
    vgsplit -n $lv2 $vg1 $vg2 2>err;
-   status=$?; echo status=$?; test $status = 5 &&
+   status=$?; echo status=$status; test $status = 5 &&
    vgremove -ff $vg1'
+#
+# Verify vgsplit rejects active LVs only when active LVs involved in split
+#
+test_expect_success \
+  "vgsplit fails, active mirror involved in split" \
+  'vgcreate $vg1 $d1 $d2 $d3 $d4 &&
+   lvcreate -l 16 -n $lv1 -m1 $vg1 $d1 $d2 $d3 &&
+   lvcreate -l 16 -n $lv2 $vg1 $d4 &&
+   lvchange -an $vg1/$lv2 &&
+   vg_validate_pvlv_counts_ $vg1 4 5 0 &&
+   vgsplit -n $lv1 $vg1 $vg2;
+   status=$?; echo status=$status; test $status = 5 &&
+   vgremove -ff $vg1'
+
+test_expect_success \
+  "vgsplit succeeds, active mirror not involved in split" \
+  'vgcreate $vg1 $d1 $d2 $d3 $d4 &&
+   lvcreate -l 16 -n $lv1 -m1 $vg1 $d1 $d2 $d3 &&
+   lvcreate -l 16 -n $lv2 $vg1 $d4 &&
+   lvchange -an $vg1/$lv2 &&
+   vg_validate_pvlv_counts_ $vg1 4 5 0 &&
+   vgsplit -n $lv2 $vg1 $vg2 &&
+   vgremove -ff $vg1 &&
+   vgremove -ff $vg2'
+
+test_expect_success \
+  "vgsplit fails, active snapshot involved in split" \
+  'vgcreate $vg1 $d1 $d2 $d3 $d4 &&
+   lvcreate -l 64 -i 2 -n $lv1 $vg1 $d1 $d2 &&
+   lvcreate -l 4 -i 2 -s -n $lv2 $vg1/$lv1 &&
+   lvcreate -l 64 -i 2 -n $lv3 $vg1 $d3 $d4 &&
+   lvchange -an $vg1/$lv3 &&
+   vg_validate_pvlv_counts_ $vg1 4 2 1 &&
+   vgsplit -n $lv2 $vg1 $vg2;
+   status=$?; echo status=$status; test $status = 5 &&
+   lvremove -f $vg1/$lv2 &&
+   vgremove -ff $vg1'
+
+test_expect_success \
+  "vgsplit succeeds, active snapshot not involved in split" \
+  'vgcreate $vg1 $d1 $d2 $d3 &&
+   lvcreate -l 64 -i 2 -n $lv1 $vg1 $d1 $d2 &&
+   lvcreate -l 4 -s -n $lv2 $vg1/$lv1 &&
+   vgextend $vg1 $d4 &&
+   lvcreate -l 64 -n $lv3 $vg1 $d4 &&
+   lvchange -an $vg1/$lv3 &&
+   vg_validate_pvlv_counts_ $vg1 4 2 1 &&
+   vgsplit -n $lv3 $vg1 $vg2 &&
+   vgchange -an $vg1 &&
+   lvremove -f $vg1/$lv2 &&
+   vgremove -ff $vg1 &&
+   vgremove -ff $vg2'
 
 
 test_done
diff --git a/tools/vgchange.c b/tools/vgchange.c
index 634f620..519d7a5 100644
--- a/tools/vgchange.c
+++ b/tools/vgchange.c
@@ -21,21 +21,21 @@ static int _monitor_lvs_in_vg(struct cmd_context *cmd,
 	struct lv_list *lvl;
 	struct logical_volume *lv;
 	struct lvinfo info;
-	int lv_active;
+	int lv_is_active;
 	int count = 0;
 
 	list_iterate_items(lvl, &vg->lvs) {
 		lv = lvl->lv;
 
 		if (!lv_info(cmd, lv, &info, 0, 0))
-			lv_active = 0;
+			lv_is_active = 0;
 		else
-			lv_active = info.exists;
+			lv_is_active = info.exists;
 
 		/*
 		 * FIXME: Need to consider all cases... PVMOVE, etc
 		 */
-		if ((lv->status & PVMOVE) || !lv_active)
+		if ((lv->status & PVMOVE) || !lv_is_active)
 			continue;
 
 		if (!monitor_dev_for_events(cmd, lv, reg)) {
diff --git a/tools/vgsplit.c b/tools/vgsplit.c
index c083889..12cf16f 100644
--- a/tools/vgsplit.c
+++ b/tools/vgsplit.c
@@ -94,6 +94,29 @@ static int _lv_is_in_vg(struct volume_group *vg, struct logical_volume *lv)
 }
 
 
+static int _move_one_lv(struct volume_group *vg_from,
+			struct volume_group *vg_to,
+			struct list *lvh)
+{
+	struct logical_volume *lv;
+	lv = list_item(lvh, struct lv_list)->lv;
+	if (lv_is_visible(lv) && lv_active(vg_from->cmd, lv, 0)) {
+		log_error("Logical volume \"%s\" must be inactive", lv->name);
+		return 0;
+	}
+	list_del(lvh);
+	list_add(&vg_to->lvs, lvh);
+	
+	if (lv->status & SNAPSHOT) {
+		vg_from->snapshot_count--;
+		vg_to->snapshot_count++;
+	} else {
+		vg_from->lv_count--;
+		vg_to->lv_count++;
+	}
+	return 1;
+}	
+
 static int _move_lvs(struct volume_group *vg_from, struct volume_group *vg_to)
 {
 	struct list *lvh, *lvht;
@@ -152,11 +175,8 @@ static int _move_lvs(struct volume_group *vg_from, struct volume_group *vg_to)
 			continue;
 
 		/* Move this LV */
-		list_del(lvh);
-		list_add(&vg_to->lvs, lvh);
-
-		vg_from->lv_count--;
-		vg_to->lv_count++;
+		if (!_move_one_lv(vg_from, vg_to, lvh))
+			return 0;
 	}
 
 	/* FIXME Ensure no LVs contain segs pointing at LVs in the other VG */
@@ -201,14 +221,10 @@ static int _move_snapshots(struct volume_group *vg_from,
 			 */
 			if (_lv_is_in_vg(vg_to, seg->cow) &&
 			    _lv_is_in_vg(vg_to, seg->origin)) {
-				list_del(lvh);
-				list_add(&vg_to->lvs, lvh);
-				
-				vg_from->snapshot_count--;
-				vg_to->snapshot_count++;
+				if (!_move_one_lv(vg_from, vg_to, lvh))
+					return 0;
 			}
 		}
-
 	}
 
 	return 1;
@@ -246,11 +262,8 @@ static int _move_mirrors(struct volume_group *vg_from,
 		}
 
 		if (seg_in == seg->area_count && log_in) {
-			list_del(lvh);
-			list_add(&vg_to->lvs, lvh);
-
-			vg_from->lv_count--;
-			vg_to->lv_count++;
+			if (!_move_one_lv(vg_from, vg_to, lvh))
+				return 0;
 		}
 	}
 
@@ -275,7 +288,6 @@ int vgsplit(struct cmd_context *cmd, int argc, char **argv)
 	char *vg_name_from, *vg_name_to;
 	struct volume_group *vg_to, *vg_from;
 	int opt;
-	int active;
 	int existing_vg;
 	int consistent;
 	const char *lv_name;
@@ -314,14 +326,6 @@ int vgsplit(struct cmd_context *cmd, int argc, char **argv)
 				       CORRECT_INCONSISTENT | FAIL_INCONSISTENT)))
 		 return ECMD_FAILED;
 
-	if ((active = lvs_in_vg_activated(vg_from))) {
-		/* FIXME Remove this restriction */
-		log_error("Logical volumes in \"%s\" must be inactive",
-			  vg_name_from);
-		unlock_vg(cmd, vg_name_from);
-		return ECMD_FAILED;
-	}
-
 	log_verbose("Checking for new volume group \"%s\"", vg_name_to);
 	if (!lock_vol(cmd, vg_name_to, LCK_VG_WRITE | LCK_NONBLOCK)) {
 		log_error("Can't get lock for %s", vg_name_to);
-- 
1.5.3.4

-- 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]