Blame SOURCES/lvm2-2_02_178-pvmove-enhance-accepted-states-of-active-LVs.patch

f0aa83
 tools/pvmove.c | 97 ++++++++++++++++++++++++++++++++--------------------------
f0aa83
 1 file changed, 54 insertions(+), 43 deletions(-)
f0aa83
f0aa83
diff --git a/tools/pvmove.c b/tools/pvmove.c
f0aa83
index cbd5cb8..2a26a10 100644
f0aa83
--- a/tools/pvmove.c
f0aa83
+++ b/tools/pvmove.c
f0aa83
@@ -340,8 +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
+	int needs_exclusive = *exclusive;
f0aa83
+	const struct logical_volume *holder;
f0aa83
 
f0aa83
 	/* FIXME Cope with non-contiguous => splitting existing segments */
f0aa83
 	if (!(lv_mirr = lv_create_empty("pvmove%d", NULL,
f0aa83
@@ -392,8 +392,13 @@ static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd,
f0aa83
 			return NULL;
f0aa83
 		}
f0aa83
 
f0aa83
-		if (seg_is_raid(first_seg(lv)) ||
f0aa83
-		    seg_is_mirrored(first_seg(lv))) {
f0aa83
+		seg = first_seg(lv);
f0aa83
+
f0aa83
+		/* Presence of exclusive LV decides whether pvmove must be also exclusive */
f0aa83
+		if ((seg_only_exclusive(seg) || lv_is_origin(lv) || lv_is_cow(lv)))
f0aa83
+			needs_exclusive = 1;
f0aa83
+
f0aa83
+		if (seg_is_raid(seg) || seg_is_mirrored(seg)) {
f0aa83
 			dm_list_init(&trim_list);
f0aa83
 
f0aa83
 			if (!get_pv_list_for_lv(vg->cmd->mem, lv, &trim_list))
f0aa83
@@ -432,6 +437,14 @@ static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd,
f0aa83
 			lv_found = 1;
f0aa83
 		}
f0aa83
 
f0aa83
+		seg = first_seg(lv);
f0aa83
+
f0aa83
+		if (seg_is_cache(seg) || seg_is_cache_pool(seg) ||
f0aa83
+		    seg_is_mirrored(seg) || seg_is_raid(seg) ||
f0aa83
+		    seg_is_snapshot(seg) ||
f0aa83
+		    seg_is_thin(seg) || seg_is_thin_pool(seg))
f0aa83
+			continue; /* bottom-level LVs only... */
f0aa83
+
f0aa83
 		if (!lv_is_on_pvs(lv, source_pvl))
f0aa83
 			continue;
f0aa83
 
f0aa83
@@ -441,47 +454,36 @@ static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd,
f0aa83
 			continue;
f0aa83
 		}
f0aa83
 
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
+		holder = lv_lock_holder(lv);
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
+		if (needs_exclusive) {
f0aa83
+			/* With exclusive pvmove skip LV when:
f0aa83
+			 *  - is active remotely
f0aa83
+			 *  - is not active locally and cannot be activated exclusively locally
f0aa83
+                         *
f0aa83
+			 * Note: lvm2 can proceed with exclusive pvmove for 'just' locally active LVs
f0aa83
+			 * in the case it's NOT active anywhere else, since LOCKED LVs cannot be
f0aa83
+			 * later activated by user.
f0aa83
 			 */
f0aa83
+			if (lv_is_active_remotely(holder) ||
f0aa83
+			    (!lv_is_active_locally(holder) && !activate_lv_excl_local(cmd, holder))) {
f0aa83
+				lv_skipped = 1;
f0aa83
+				log_print_unless_silent("Skipping LV %s which is not locally exclusive%s.",
f0aa83
+							display_lvname(lv),
f0aa83
+							/* Report missing cmirrord cases that matterd.
f0aa83
+							 * With exclusive LV types cmirrord would not help. */
f0aa83
+							(*exclusive &&
f0aa83
+							 !lv_is_origin(holder) &&
f0aa83
+							 !seg_only_exclusive(first_seg(holder))) ?
f0aa83
+							" and clustered mirror (cmirror) not detected" : "");
f0aa83
+				continue;
f0aa83
+			}
f0aa83
+		} else if (!activate_lv(cmd, holder)) {
f0aa83
+			lv_skipped = 1;
f0aa83
+			log_print_unless_silent("Skipping LV %s which cannot be activated.",
f0aa83
+						display_lvname(lv));
f0aa83
 			continue;
f0aa83
+		}
f0aa83
 
f0aa83
 		if (!_insert_pvmove_mirrors(cmd, lv_mirr, source_pvl, lv,
f0aa83
 					    *lvs_changed))
f0aa83
@@ -517,7 +519,7 @@ static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd,
f0aa83
 		return NULL;
f0aa83
 	}
f0aa83
 
f0aa83
-	if (lv_exclusive_count)
f0aa83
+	if (needs_exclusive)
f0aa83
 		*exclusive = 1;
f0aa83
 
f0aa83
 	return lv_mirr;
f0aa83
@@ -600,6 +602,8 @@ static int _pvmove_setup_single(struct cmd_context *cmd,
f0aa83
 	struct dm_list *lvs_changed;
f0aa83
 	struct logical_volume *lv_mirr;
f0aa83
 	struct logical_volume *lv = NULL;
f0aa83
+	struct lv_list *lvl;
f0aa83
+	const struct logical_volume *lvh;
f0aa83
 	const char *pv_name = pv_dev_name(pv);
f0aa83
 	unsigned flags = PVMOVE_FIRST_TIME;
f0aa83
 	unsigned exclusive;
f0aa83
@@ -661,6 +665,13 @@ static int _pvmove_setup_single(struct cmd_context *cmd,
f0aa83
 			goto out;
f0aa83
 		}
f0aa83
 
f0aa83
+		dm_list_iterate_items(lvl, lvs_changed) {
f0aa83
+			lvh = lv_lock_holder(lvl->lv);
f0aa83
+			/* Exclusive LV decides whether pvmove must be also exclusive */
f0aa83
+			if (lv_is_origin(lvh) || seg_only_exclusive(first_seg(lvh)))
f0aa83
+				exclusive = 1;
f0aa83
+		}
f0aa83
+
f0aa83
 		/* Ensure mirror LV is active */
f0aa83
 		if (!_activate_lv(cmd, lv_mirr, exclusive)) {
f0aa83
 			log_error("ABORTING: Temporary mirror activation failed.");