You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

281 lines
8.7 KiB

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