|
|
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.");
|