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
281 lines
8.7 KiB
7 years ago
|
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 */
|