Blame SOURCES/lvm2-2_02_178-pvmove-reinstantiate-clustered-pvmove.patch

f0aa83
 WHATS_NEW               |   1 +
f0aa83
 lib/activate/activate.c |   1 -
f0aa83
 lib/locking/locking.c   |  12 ++++--
f0aa83
 lib/locking/locking.h   |   2 +-
f0aa83
 tools/pvmove.c          | 109 ++++++++++++++++++++++++++++++++++++------------
f0aa83
 5 files changed, 93 insertions(+), 32 deletions(-)
f0aa83
f0aa83
diff --git a/WHATS_NEW b/WHATS_NEW
f0aa83
index c3117de..da10eed 100644
f0aa83
--- a/WHATS_NEW
f0aa83
+++ b/WHATS_NEW
f0aa83
@@ -1,5 +1,6 @@
f0aa83
 Version 2.02.178 - 
f0aa83
 =====================================
f0aa83
+  Restore pvmove support for wide-clustered active volumes (2.02.177).
f0aa83
   Avoid non-exclusive activation of exclusive segment types.
f0aa83
   Fix trimming sibling PVs when doing a pvmove of raid subLVs.
f0aa83
   Preserve exclusive activation during thin snaphost merge.
f0aa83
diff --git a/lib/activate/activate.c b/lib/activate/activate.c
f0aa83
index 18cc7cf..7a37130 100644
f0aa83
--- a/lib/activate/activate.c
f0aa83
+++ b/lib/activate/activate.c
f0aa83
@@ -2576,7 +2576,6 @@ static int _lv_activate(struct cmd_context *cmd, const char *lvid_s,
f0aa83
 
f0aa83
 	if (!laopts->exclusive &&
f0aa83
 	    (lv_is_origin(lv) ||
f0aa83
-	     lv_is_pvmove(lv) ||
f0aa83
 	     seg_only_exclusive(first_seg(lv))))  {
f0aa83
 		log_error(INTERNAL_ERROR "Trying non-exlusive activation of %s with "
f0aa83
 			  "a volume type %s requiring exclusive activation.",
f0aa83
diff --git a/lib/locking/locking.c b/lib/locking/locking.c
f0aa83
index 8daa61e..1a3ce9d 100644
f0aa83
--- a/lib/locking/locking.c
f0aa83
+++ b/lib/locking/locking.c
f0aa83
@@ -399,15 +399,19 @@ int activate_lv_excl(struct cmd_context *cmd, const struct logical_volume *lv)
f0aa83
 }
f0aa83
 
f0aa83
 /* Lock a list of LVs */
f0aa83
-int activate_lvs(struct cmd_context *cmd, struct dm_list *lvs)
f0aa83
+int activate_lvs(struct cmd_context *cmd, struct dm_list *lvs, unsigned exclusive)
f0aa83
 {
f0aa83
 	struct dm_list *lvh;
f0aa83
 	struct lv_list *lvl;
f0aa83
 
f0aa83
 	dm_list_iterate_items(lvl, lvs) {
f0aa83
-		if (!activate_lv_excl_local(cmd, lvl->lv)) {
f0aa83
-			log_error("Failed to locally exclusively activate %s.",
f0aa83
-				  display_lvname(lvl->lv));
f0aa83
+		if (!exclusive && !lv_is_active_exclusive(lvl->lv)) {
f0aa83
+			if (!activate_lv(cmd, lvl->lv)) {
f0aa83
+				log_error("Failed to activate %s", display_lvname(lvl->lv));
f0aa83
+				return 0;
f0aa83
+			}
f0aa83
+		} else if (!activate_lv_excl(cmd, lvl->lv)) {
f0aa83
+			log_error("Failed to activate %s", display_lvname(lvl->lv));
f0aa83
 			dm_list_uniterate(lvh, lvs, &lvl->list) {
f0aa83
 				lvl = dm_list_item(lvh, struct lv_list);
f0aa83
 				if (!deactivate_lv(cmd, lvl->lv))
f0aa83
diff --git a/lib/locking/locking.h b/lib/locking/locking.h
f0aa83
index 47841ed..f2fbb00 100644
f0aa83
--- a/lib/locking/locking.h
f0aa83
+++ b/lib/locking/locking.h
f0aa83
@@ -262,6 +262,6 @@ int sync_dev_names(struct cmd_context* cmd);
f0aa83
 
f0aa83
 /* Process list of LVs */
f0aa83
 struct volume_group;
f0aa83
-int activate_lvs(struct cmd_context *cmd, struct dm_list *lvs);
f0aa83
+int activate_lvs(struct cmd_context *cmd, struct dm_list *lvs, unsigned exclusive);
f0aa83
 
f0aa83
 #endif
f0aa83
diff --git a/tools/pvmove.c b/tools/pvmove.c
f0aa83
index b3d1d89..cbd5cb8 100644
f0aa83
--- a/tools/pvmove.c
f0aa83
+++ b/tools/pvmove.c
f0aa83
@@ -64,6 +64,16 @@ static int _pvmove_target_present(struct cmd_context *cmd, int clustered)
f0aa83
 	return found;
f0aa83
 }
f0aa83
 
f0aa83
+static unsigned _pvmove_is_exclusive(struct cmd_context *cmd,
f0aa83
+				     struct volume_group *vg)
f0aa83
+{
f0aa83
+	if (vg_is_clustered(vg))
f0aa83
+		if (!_pvmove_target_present(cmd, 1))
f0aa83
+			return 1;
f0aa83
+
f0aa83
+	return 0;
f0aa83
+}
f0aa83
+
f0aa83
 /* Allow /dev/vgname/lvname, vgname/lvname or lvname */
f0aa83
 static const char *_extract_lvname(struct cmd_context *cmd, const char *vgname,
f0aa83
 				   const char *arg)
f0aa83
@@ -320,7 +330,8 @@ static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd,
f0aa83
 						const char *lv_name,
f0aa83
 						struct dm_list *allocatable_pvs,
f0aa83
 						alloc_policy_t alloc,
f0aa83
-						struct dm_list **lvs_changed)
f0aa83
+						struct dm_list **lvs_changed,
f0aa83
+						unsigned *exclusive)
f0aa83
 {
f0aa83
 	struct logical_volume *lv_mirr, *lv;
f0aa83
 	struct lv_segment *seg;
f0aa83
@@ -329,6 +340,8 @@ static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd,
f0aa83
 	uint32_t log_count = 0;
f0aa83
 	int lv_found = 0;
f0aa83
 	int lv_skipped = 0;
f0aa83
+	int lv_active_count = 0;
f0aa83
+	int lv_exclusive_count = 0;
f0aa83
 
f0aa83
 	/* FIXME Cope with non-contiguous => splitting existing segments */
f0aa83
 	if (!(lv_mirr = lv_create_empty("pvmove%d", NULL,
f0aa83
@@ -422,33 +435,54 @@ static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd,
f0aa83
 		if (!lv_is_on_pvs(lv, source_pvl))
f0aa83
 			continue;
f0aa83
 
f0aa83
-		seg = first_seg(lv);
f0aa83
-		if (seg_is_raid(seg) || seg_is_mirrored(seg) ||
f0aa83
-		    lv_is_thin_volume(lv) || lv_is_thin_pool(lv)) {
f0aa83
-			/*
f0aa83
-			 * Pass over top-level LVs - they were handled.
f0aa83
-			 * Allow sub-LVs to proceed.
f0aa83
-			 */
f0aa83
-			continue;
f0aa83
-		}
f0aa83
-
f0aa83
 		if (lv_is_locked(lv)) {
f0aa83
 			lv_skipped = 1;
f0aa83
 			log_print_unless_silent("Skipping locked LV %s.", display_lvname(lv));
f0aa83
 			continue;
f0aa83
 		}
f0aa83
 
f0aa83
-		if (vg_is_clustered(vg) &&
f0aa83
-		    lv_is_visible(lv) &&
f0aa83
-		    lv_is_active(lv) &&
f0aa83
-		    !lv_is_active_exclusive_locally(lv)) {
f0aa83
-			lv_skipped = 1;
f0aa83
-			log_print_unless_silent("Skipping LV %s which is active, "
f0aa83
-						"but not locally exclusively.",
f0aa83
-						display_lvname(lv));
f0aa83
-			continue;
f0aa83
+		if (vg_is_clustered(vg) && lv_is_visible(lv)) {
f0aa83
+			if (lv_is_active_exclusive_locally(lv)) {
f0aa83
+				if (lv_active_count) {
f0aa83
+					log_error("Cannot move in clustered VG %s "
f0aa83
+						  "if some LVs are activated "
f0aa83
+						  "exclusively while others don't.",
f0aa83
+						  vg->name);
f0aa83
+					return NULL;
f0aa83
+				}
f0aa83
+
f0aa83
+				lv_exclusive_count++;
f0aa83
+			} else if (lv_is_active(lv)) {
f0aa83
+				if (seg_only_exclusive(first_seg(lv))) {
f0aa83
+					lv_skipped = 1;
f0aa83
+					log_print_unless_silent("Skipping LV %s which is active, "
f0aa83
+								"but not locally exclusively.",
f0aa83
+							display_lvname(lv));
f0aa83
+					continue;
f0aa83
+				}
f0aa83
+
f0aa83
+				if (*exclusive) {
f0aa83
+					log_error("Cannot move in clustered VG %s, "
f0aa83
+						  "clustered mirror (cmirror) not detected "
f0aa83
+						  "and LVs are activated non-exclusively.",
f0aa83
+						  vg->name);
f0aa83
+					return NULL;
f0aa83
+				}
f0aa83
+
f0aa83
+				lv_active_count++;
f0aa83
+			}
f0aa83
 		}
f0aa83
 
f0aa83
+		seg = first_seg(lv);
f0aa83
+		if (seg_is_raid(seg) || seg_is_mirrored(seg) ||
f0aa83
+		    seg_is_cache(seg) || seg_is_cache_pool(seg) ||
f0aa83
+		    seg_is_thin(seg) || seg_is_thin_pool(seg))
f0aa83
+			/*
f0aa83
+			 * Pass over top-level LVs - they were handled.
f0aa83
+			 * Allow sub-LVs to proceed.
f0aa83
+			 */
f0aa83
+			continue;
f0aa83
+
f0aa83
 		if (!_insert_pvmove_mirrors(cmd, lv_mirr, source_pvl, lv,
f0aa83
 					    *lvs_changed))
f0aa83
 			return_NULL;
f0aa83
@@ -483,15 +517,35 @@ static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd,
f0aa83
 		return NULL;
f0aa83
 	}
f0aa83
 
f0aa83
+	if (lv_exclusive_count)
f0aa83
+		*exclusive = 1;
f0aa83
+
f0aa83
 	return lv_mirr;
f0aa83
 }
f0aa83
 
f0aa83
+static int _activate_lv(struct cmd_context *cmd, struct logical_volume *lv_mirr,
f0aa83
+			unsigned exclusive)
f0aa83
+{
f0aa83
+	int r = 0;
f0aa83
+
f0aa83
+	if (exclusive || lv_is_active_exclusive(lv_mirr))
f0aa83
+		r = activate_lv_excl(cmd, lv_mirr);
f0aa83
+	else
f0aa83
+		r = activate_lv(cmd, lv_mirr);
f0aa83
+
f0aa83
+	if (!r)
f0aa83
+		stack;
f0aa83
+
f0aa83
+	return r;
f0aa83
+}
f0aa83
+
f0aa83
 /*
f0aa83
  * Called to set up initial pvmove LV only.
f0aa83
  * (Not called after first or any other section completes.)
f0aa83
  */
f0aa83
 static int _update_metadata(struct logical_volume *lv_mirr,
f0aa83
-			    struct dm_list *lvs_changed)
f0aa83
+			    struct dm_list *lvs_changed,
f0aa83
+			    unsigned exclusive)
f0aa83
 {
f0aa83
 	struct lv_list *lvl;
f0aa83
 	struct logical_volume *lv = lv_mirr;
f0aa83
@@ -505,7 +559,7 @@ static int _update_metadata(struct logical_volume *lv_mirr,
f0aa83
                 return_0;
f0aa83
 
f0aa83
 	/* Ensure mirror LV is active */
f0aa83
-	if (!activate_lv_excl_local(lv_mirr->vg->cmd, lv_mirr)) {
f0aa83
+	if (!_activate_lv(lv_mirr->vg->cmd, lv_mirr, exclusive)) {
f0aa83
 		if (test_mode())
f0aa83
 			return 1;
f0aa83
 
f0aa83
@@ -548,6 +602,7 @@ static int _pvmove_setup_single(struct cmd_context *cmd,
f0aa83
 	struct logical_volume *lv = NULL;
f0aa83
 	const char *pv_name = pv_dev_name(pv);
f0aa83
 	unsigned flags = PVMOVE_FIRST_TIME;
f0aa83
+	unsigned exclusive;
f0aa83
 	int r = ECMD_FAILED;
f0aa83
 
f0aa83
 	pp->found_pv = 1;
f0aa83
@@ -594,6 +649,8 @@ static int _pvmove_setup_single(struct cmd_context *cmd,
f0aa83
 		}
f0aa83
 	}
f0aa83
 
f0aa83
+	exclusive = _pvmove_is_exclusive(cmd, vg);
f0aa83
+
f0aa83
 	if ((lv_mirr = find_pvmove_lv(vg, pv_dev(pv), PVMOVE))) {
f0aa83
 		log_print_unless_silent("Detected pvmove in progress for %s.", pv_name);
f0aa83
 		if (pp->pv_count || lv_name)
f0aa83
@@ -605,7 +662,7 @@ static int _pvmove_setup_single(struct cmd_context *cmd,
f0aa83
 		}
f0aa83
 
f0aa83
 		/* Ensure mirror LV is active */
f0aa83
-		if (!activate_lv_excl_local(cmd, lv_mirr)) {
f0aa83
+		if (!_activate_lv(cmd, lv_mirr, exclusive)) {
f0aa83
 			log_error("ABORTING: Temporary mirror activation failed.");
f0aa83
 			goto out;
f0aa83
 		}
f0aa83
@@ -630,12 +687,12 @@ static int _pvmove_setup_single(struct cmd_context *cmd,
f0aa83
 
f0aa83
 		if (!(lv_mirr = _set_up_pvmove_lv(cmd, vg, source_pvl, lv_name,
f0aa83
 						  allocatable_pvs, pp->alloc,
f0aa83
-						  &lvs_changed)))
f0aa83
+						  &lvs_changed, &exclusive)))
f0aa83
 			goto_out;
f0aa83
 	}
f0aa83
 
f0aa83
 	/* Lock lvs_changed and activate (with old metadata) */
f0aa83
-	if (!activate_lvs(cmd, lvs_changed))
f0aa83
+	if (!activate_lvs(cmd, lvs_changed, exclusive))
f0aa83
 		goto_out;
f0aa83
 
f0aa83
 	/* FIXME Presence of a mirror once set PVMOVE - now remove associated logic */
f0aa83
@@ -646,7 +703,7 @@ static int _pvmove_setup_single(struct cmd_context *cmd,
f0aa83
 		goto out;
f0aa83
 
f0aa83
 	if (flags & PVMOVE_FIRST_TIME)
f0aa83
-		if (!_update_metadata(lv_mirr, lvs_changed))
f0aa83
+		if (!_update_metadata(lv_mirr, lvs_changed, exclusive))
f0aa83
 			goto_out;
f0aa83
 
f0aa83
 	/* LVs are all in status LOCKED */