mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +03:00
RAID: Make RAID single-machine-exclusive capable in a cluster
Creation, deletion, [de]activation, repair, conversion, scrubbing and changing operations are all now available for RAID LVs in a cluster - provided that they are activated exclusively. The code has been changed to ensure that no LV or sub-LV activation is attempted cluster-wide. This includes the often overlooked operations of activating metadata areas for the brief time it takes to clear them. Additionally, some 'resume_lv' operations were replaced with 'activate_lv_excl_local' when sub-LVs were promoted to top-level LVs for removal, clearing or extraction. This was necessary because it forces the appropriate renaming actions the occur via resume in the single-machine case, but won't happen in a cluster due to the necessity of acquiring a lock first. The *raid* tests have been updated to allow testing in a cluster. For the most part, this meant creating devices with '-aey' if they were to be converted to RAID. (RAID requires the converting LV to be EX because it is a condition of activation for the RAID LV in a cluster.)
This commit is contained in:
parent
8d1d83504d
commit
2691f1d764
@ -1,5 +1,6 @@
|
|||||||
Version 2.02.101 -
|
Version 2.02.101 -
|
||||||
===================================
|
===================================
|
||||||
|
Make RAID capable of single-machine exclusive operations in a cluster.
|
||||||
Drop calculation of read ahead for deactivated volume.
|
Drop calculation of read ahead for deactivated volume.
|
||||||
Check for exactly one lv segment in validation of thin pools and volumes.
|
Check for exactly one lv segment in validation of thin pools and volumes.
|
||||||
Fix dmeventd unmonitoring of thin pools.
|
Fix dmeventd unmonitoring of thin pools.
|
||||||
|
@ -737,24 +737,28 @@ int lv_active_change(struct cmd_context *cmd, struct logical_volume *lv,
|
|||||||
if (!deactivate_lv(cmd, lv))
|
if (!deactivate_lv(cmd, lv))
|
||||||
return_0;
|
return_0;
|
||||||
} else if ((activate == CHANGE_AE) ||
|
} else if ((activate == CHANGE_AE) ||
|
||||||
|
seg_is_raid(first_seg(lv)) ||
|
||||||
lv_is_origin(lv) ||
|
lv_is_origin(lv) ||
|
||||||
lv_is_thin_type(lv)) {
|
lv_is_thin_type(lv)) {
|
||||||
if (activate == CHANGE_ALN) {
|
if (activate == CHANGE_ALN) {
|
||||||
/* origin or thin, all others have _AE */
|
/* origin, thin or RAID - all others have _AE */
|
||||||
/* other types of activation are implicitly exclusive */
|
/* other types of activation are implicitly exclusive */
|
||||||
/* Note: the order of tests is mandatory */
|
/* Note: the order of tests is mandatory */
|
||||||
log_error("Cannot deactivate \"%s\" locally.", lv->name);
|
log_error("Cannot deactivate \"%s\" locally.", lv->name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
log_verbose("Activating logical volume \"%s\" exclusively.", lv->name);
|
log_verbose("Activating logical volume \"%s\" exclusively.",
|
||||||
|
lv->name);
|
||||||
if (!activate_lv_excl(cmd, lv))
|
if (!activate_lv_excl(cmd, lv))
|
||||||
return_0;
|
return_0;
|
||||||
} else if (activate == CHANGE_ALN) {
|
} else if (activate == CHANGE_ALN) {
|
||||||
log_verbose("Deactivating logical volume \"%s\" locally.", lv->name);
|
log_verbose("Deactivating logical volume \"%s\" locally.",
|
||||||
|
lv->name);
|
||||||
if (!deactivate_lv_local(cmd, lv))
|
if (!deactivate_lv_local(cmd, lv))
|
||||||
return_0;
|
return_0;
|
||||||
} else if ((activate == CHANGE_ALY) || (activate == CHANGE_AAY)) {
|
} else if ((activate == CHANGE_ALY) || (activate == CHANGE_AAY)) {
|
||||||
log_verbose("Activating logical volume \"%s\" locally.", lv->name);
|
log_verbose("Activating logical volume \"%s\" locally.",
|
||||||
|
lv->name);
|
||||||
if (!activate_lv_local(cmd, lv))
|
if (!activate_lv_local(cmd, lv))
|
||||||
return_0;
|
return_0;
|
||||||
} else { /* CHANGE_AY */
|
} else { /* CHANGE_AY */
|
||||||
|
@ -2881,7 +2881,8 @@ static int _lv_extend_layered_lv(struct alloc_handle *ah,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!activate_lv(meta_lv->vg->cmd, meta_lv)) {
|
/* For clearing, simply activate exclusive locally */
|
||||||
|
if (!activate_lv_excl_local(meta_lv->vg->cmd, meta_lv)) {
|
||||||
log_error("Failed to activate %s/%s for clearing",
|
log_error("Failed to activate %s/%s for clearing",
|
||||||
meta_lv->vg->name, meta_lv->name);
|
meta_lv->vg->name, meta_lv->name);
|
||||||
return 0;
|
return 0;
|
||||||
@ -5504,7 +5505,8 @@ int lv_activation_skip(struct logical_volume *lv, activation_change_t activate,
|
|||||||
* If lp->activate is AY*, activate it.
|
* If lp->activate is AY*, activate it.
|
||||||
* If lp->activate was AN* and the pool was originally inactive, deactivate it.
|
* If lp->activate was AN* and the pool was originally inactive, deactivate it.
|
||||||
*/
|
*/
|
||||||
static struct logical_volume *_lv_create_an_lv(struct volume_group *vg, struct lvcreate_params *lp,
|
static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
|
||||||
|
struct lvcreate_params *lp,
|
||||||
const char *new_lv_name)
|
const char *new_lv_name)
|
||||||
{
|
{
|
||||||
struct cmd_context *cmd = vg->cmd;
|
struct cmd_context *cmd = vg->cmd;
|
||||||
@ -5527,21 +5529,6 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg, struct l
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vg_is_clustered(vg) && segtype_is_raid(lp->segtype)) {
|
|
||||||
/*
|
|
||||||
* FIXME:
|
|
||||||
* We could allow a RAID LV to be created as long as it
|
|
||||||
* is activated exclusively. Any subsequent activations
|
|
||||||
* would have to be enforced as exclusive also.
|
|
||||||
*
|
|
||||||
* For now, we disallow the existence of RAID LVs in a
|
|
||||||
* cluster VG
|
|
||||||
*/
|
|
||||||
log_error("Unable to create a %s logical volume in a cluster.",
|
|
||||||
lp->segtype->name);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((segtype_is_mirrored(lp->segtype) ||
|
if ((segtype_is_mirrored(lp->segtype) ||
|
||||||
segtype_is_raid(lp->segtype) || segtype_is_thin(lp->segtype)) &&
|
segtype_is_raid(lp->segtype) || segtype_is_thin(lp->segtype)) &&
|
||||||
!(vg->fid->fmt->features & FMT_SEGMENTS)) {
|
!(vg->fid->fmt->features & FMT_SEGMENTS)) {
|
||||||
@ -5843,6 +5830,14 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg, struct l
|
|||||||
} else if (seg_is_raid(lp)) {
|
} else if (seg_is_raid(lp)) {
|
||||||
first_seg(lv)->min_recovery_rate = lp->min_recovery_rate;
|
first_seg(lv)->min_recovery_rate = lp->min_recovery_rate;
|
||||||
first_seg(lv)->max_recovery_rate = lp->max_recovery_rate;
|
first_seg(lv)->max_recovery_rate = lp->max_recovery_rate;
|
||||||
|
if (vg_is_clustered(lv->vg) &&
|
||||||
|
is_change_activating(lp->activate) &&
|
||||||
|
(lp->activate != CHANGE_AE)) {
|
||||||
|
log_debug_activation("Creating RAID logical volume in a"
|
||||||
|
" cluster: setting activation"
|
||||||
|
" mode to EX");
|
||||||
|
lp->activate = CHANGE_AE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME Log allocation and attachment should have happened inside lv_extend. */
|
/* FIXME Log allocation and attachment should have happened inside lv_extend. */
|
||||||
|
@ -174,7 +174,7 @@ static int _clear_lv(struct logical_volume *lv)
|
|||||||
if (test_mode())
|
if (test_mode())
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (!was_active && !activate_lv(lv->vg->cmd, lv)) {
|
if (!was_active && !activate_lv_excl_local(lv->vg->cmd, lv)) {
|
||||||
log_error("Failed to activate %s for clearing",
|
log_error("Failed to activate %s for clearing",
|
||||||
lv->name);
|
lv->name);
|
||||||
return 0;
|
return 0;
|
||||||
@ -962,12 +962,12 @@ static int _raid_remove_images(struct logical_volume *lv,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We resume the extracted sub-LVs first so they are renamed
|
* We activate the extracted sub-LVs first so they are renamed
|
||||||
* and won't conflict with the remaining (possibly shifted)
|
* and won't conflict with the remaining (possibly shifted)
|
||||||
* sub-LVs.
|
* sub-LVs.
|
||||||
*/
|
*/
|
||||||
dm_list_iterate_items(lvl, &removal_list) {
|
dm_list_iterate_items(lvl, &removal_list) {
|
||||||
if (!resume_lv(lv->vg->cmd, lvl->lv)) {
|
if (!activate_lv_excl_local(lv->vg->cmd, lvl->lv)) {
|
||||||
log_error("Failed to resume extracted LVs");
|
log_error("Failed to resume extracted LVs");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1023,6 +1023,16 @@ int lv_raid_change_image_count(struct logical_volume *lv,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* LV must be either in-active or exclusively active
|
||||||
|
*/
|
||||||
|
if (lv_is_active(lv) && vg_is_clustered(lv->vg) &&
|
||||||
|
!lv_is_active_exclusive_locally(lv)) {
|
||||||
|
log_error("%s/%s must be active exclusive locally to"
|
||||||
|
" perform this operation.", lv->vg->name, lv->name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (old_count > new_count)
|
if (old_count > new_count)
|
||||||
return _raid_remove_images(lv, new_count, pvs);
|
return _raid_remove_images(lv, new_count, pvs);
|
||||||
|
|
||||||
@ -1125,15 +1135,15 @@ int lv_raid_split(struct logical_volume *lv, const char *split_name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* First resume the newly split LV and LVs on the removal list.
|
* First activate the newly split LV and LVs on the removal list.
|
||||||
* This is necessary so that there are no name collisions due to
|
* This is necessary so that there are no name collisions due to
|
||||||
* the original RAID LV having possibly had sub-LVs that have been
|
* the original RAID LV having possibly had sub-LVs that have been
|
||||||
* shifted and renamed.
|
* shifted and renamed.
|
||||||
*/
|
*/
|
||||||
if (!resume_lv(cmd, lvl->lv))
|
if (!activate_lv_excl_local(cmd, lvl->lv))
|
||||||
return_0;
|
return_0;
|
||||||
dm_list_iterate_items(lvl, &removal_list)
|
dm_list_iterate_items(lvl, &removal_list)
|
||||||
if (!resume_lv(cmd, lvl->lv))
|
if (!activate_lv_excl_local(cmd, lvl->lv))
|
||||||
return_0;
|
return_0;
|
||||||
|
|
||||||
if (!resume_lv(lv->vg->cmd, lv)) {
|
if (!resume_lv(lv->vg->cmd, lv)) {
|
||||||
@ -1470,6 +1480,12 @@ int lv_raid_reshape(struct logical_volume *lv,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (vg_is_clustered(lv->vg) && !lv_is_active_exclusive_locally(lv)) {
|
||||||
|
log_error("%s/%s must be active exclusive locally to"
|
||||||
|
" perform this operation.", lv->vg->name, lv->name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (!strcmp(seg->segtype->name, "mirror") &&
|
if (!strcmp(seg->segtype->name, "mirror") &&
|
||||||
(!strcmp(new_segtype->name, "raid1")))
|
(!strcmp(new_segtype->name, "raid1")))
|
||||||
return _convert_mirror_to_raid1(lv, new_segtype);
|
return _convert_mirror_to_raid1(lv, new_segtype);
|
||||||
@ -1493,21 +1509,23 @@ int lv_raid_replace(struct logical_volume *lv,
|
|||||||
struct dm_list *allocate_pvs)
|
struct dm_list *allocate_pvs)
|
||||||
{
|
{
|
||||||
uint32_t s, sd, match_count = 0;
|
uint32_t s, sd, match_count = 0;
|
||||||
struct dm_list old_meta_lvs, old_data_lvs;
|
struct dm_list old_lvs;
|
||||||
struct dm_list new_meta_lvs, new_data_lvs;
|
struct dm_list new_meta_lvs, new_data_lvs;
|
||||||
struct lv_segment *raid_seg = first_seg(lv);
|
struct lv_segment *raid_seg = first_seg(lv);
|
||||||
struct lv_list *lvl;
|
struct lv_list *lvl;
|
||||||
char *tmp_names[raid_seg->area_count * 2];
|
char *tmp_names[raid_seg->area_count * 2];
|
||||||
|
|
||||||
dm_list_init(&old_meta_lvs);
|
dm_list_init(&old_lvs);
|
||||||
dm_list_init(&old_data_lvs);
|
|
||||||
dm_list_init(&new_meta_lvs);
|
dm_list_init(&new_meta_lvs);
|
||||||
dm_list_init(&new_data_lvs);
|
dm_list_init(&new_data_lvs);
|
||||||
|
|
||||||
if (!lv_is_active_locally(lv)) {
|
if (lv->status & PARTIAL_LV)
|
||||||
|
lv->vg->cmd->partial_activation = 1;
|
||||||
|
|
||||||
|
if (!lv_is_active_exclusive_locally(lv)) {
|
||||||
log_error("%s/%s must be active %sto perform this operation.",
|
log_error("%s/%s must be active %sto perform this operation.",
|
||||||
lv->vg->name, lv->name,
|
lv->vg->name, lv->name,
|
||||||
vg_is_clustered(lv->vg) ? "locally " : "");
|
vg_is_clustered(lv->vg) ? "exclusive locally " : "");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1612,12 +1630,20 @@ try_again:
|
|||||||
*/
|
*/
|
||||||
if (!_raid_extract_images(lv, raid_seg->area_count - match_count,
|
if (!_raid_extract_images(lv, raid_seg->area_count - match_count,
|
||||||
remove_pvs, 0,
|
remove_pvs, 0,
|
||||||
&old_meta_lvs, &old_data_lvs)) {
|
&old_lvs, &old_lvs)) {
|
||||||
log_error("Failed to remove the specified images from %s/%s",
|
log_error("Failed to remove the specified images from %s/%s",
|
||||||
lv->vg->name, lv->name);
|
lv->vg->name, lv->name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now that they are extracted and visible, make the system aware
|
||||||
|
* of their new names.
|
||||||
|
*/
|
||||||
|
dm_list_iterate_items(lvl, &old_lvs)
|
||||||
|
if (!activate_lv_excl_local(lv->vg->cmd, lvl->lv))
|
||||||
|
return_0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Skip metadata operation normally done to clear the metadata sub-LVs.
|
* Skip metadata operation normally done to clear the metadata sub-LVs.
|
||||||
*
|
*
|
||||||
@ -1696,13 +1722,7 @@ try_again:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
dm_list_iterate_items(lvl, &old_meta_lvs) {
|
dm_list_iterate_items(lvl, &old_lvs) {
|
||||||
if (!deactivate_lv(lv->vg->cmd, lvl->lv))
|
|
||||||
return_0;
|
|
||||||
if (!lv_remove(lvl->lv))
|
|
||||||
return_0;
|
|
||||||
}
|
|
||||||
dm_list_iterate_items(lvl, &old_data_lvs) {
|
|
||||||
if (!deactivate_lv(lv->vg->cmd, lvl->lv))
|
if (!deactivate_lv(lv->vg->cmd, lvl->lv))
|
||||||
return_0;
|
return_0;
|
||||||
if (!lv_remove(lvl->lv))
|
if (!lv_remove(lvl->lv))
|
||||||
|
@ -524,17 +524,6 @@ int vg_set_clustered(struct volume_group *vg, int clustered)
|
|||||||
* on active mirrors, snapshots or RAID logical volumes.
|
* on active mirrors, snapshots or RAID logical volumes.
|
||||||
*/
|
*/
|
||||||
dm_list_iterate_items(lvl, &vg->lvs) {
|
dm_list_iterate_items(lvl, &vg->lvs) {
|
||||||
/*
|
|
||||||
* FIXME:
|
|
||||||
* We could allow exclusive activation of RAID LVs, but
|
|
||||||
* for now we disallow them in a cluster VG at all.
|
|
||||||
*/
|
|
||||||
if (lv_is_raid_type(lvl->lv)) {
|
|
||||||
log_error("RAID logical volumes are not allowed "
|
|
||||||
"in a cluster volume group.");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lv_is_active(lvl->lv) &&
|
if (lv_is_active(lvl->lv) &&
|
||||||
(lv_is_mirrored(lvl->lv) || lv_is_raid_type(lvl->lv))) {
|
(lv_is_mirrored(lvl->lv) || lv_is_raid_type(lvl->lv))) {
|
||||||
log_error("%s logical volumes must be inactive "
|
log_error("%s logical volumes must be inactive "
|
||||||
|
@ -640,9 +640,6 @@ wait_for_sync() {
|
|||||||
# i.e. dm_target_at_least dm-thin-pool 1 0
|
# i.e. dm_target_at_least dm-thin-pool 1 0
|
||||||
target_at_least()
|
target_at_least()
|
||||||
{
|
{
|
||||||
# Raid target does not work in cluster
|
|
||||||
test -e LOCAL_CLVMD -a "$1" = "dm-raid" && return 1
|
|
||||||
|
|
||||||
case "$1" in
|
case "$1" in
|
||||||
dm-*) modprobe "$1" || true ;;
|
dm-*) modprobe "$1" || true ;;
|
||||||
esac
|
esac
|
||||||
|
@ -289,7 +289,7 @@ run_checks() {
|
|||||||
|
|
||||||
# Hey, specifying devices for thin allocation doesn't work
|
# Hey, specifying devices for thin allocation doesn't work
|
||||||
# lvconvert --thinpool $1/$2 "$dev6"
|
# lvconvert --thinpool $1/$2 "$dev6"
|
||||||
lvcreate -L 2M -n ${2}_meta $1 "$dev6"
|
lvcreate -aey -L 2M -n ${2}_meta $1 "$dev6"
|
||||||
lvconvert --thinpool $1/$2 --poolmetadata ${2}_meta
|
lvconvert --thinpool $1/$2 --poolmetadata ${2}_meta
|
||||||
lvcreate -T $1/$2 -V 1 -n thinlv
|
lvcreate -T $1/$2 -V 1 -n thinlv
|
||||||
THIN_POSTFIX="_tdata"
|
THIN_POSTFIX="_tdata"
|
||||||
@ -303,7 +303,7 @@ run_checks() {
|
|||||||
printf "#\n#\n# run_checks: RAID as thinpool metadata\n#\n#\n"
|
printf "#\n#\n# run_checks: RAID as thinpool metadata\n#\n#\n"
|
||||||
|
|
||||||
lvrename $1/$2 ${2}_meta
|
lvrename $1/$2 ${2}_meta
|
||||||
lvcreate -L 2M -n $2 $1 "$dev6"
|
lvcreate -aey -L 2M -n $2 $1 "$dev6"
|
||||||
lvconvert --thinpool $1/$2 --poolmetadata ${2}_meta
|
lvconvert --thinpool $1/$2 --poolmetadata ${2}_meta
|
||||||
lvcreate -T $1/$2 -V 1 -n thinlv
|
lvcreate -T $1/$2 -V 1 -n thinlv
|
||||||
THIN_POSTFIX="_tmeta"
|
THIN_POSTFIX="_tmeta"
|
||||||
@ -314,7 +314,7 @@ run_checks() {
|
|||||||
run_recovery_rate_check $1 $2
|
run_recovery_rate_check $1 $2
|
||||||
elif [ 'snapshot' == $3 ]; then
|
elif [ 'snapshot' == $3 ]; then
|
||||||
printf "#\n#\n# run_checks: RAID under snapshot\n#\n#\n"
|
printf "#\n#\n# run_checks: RAID under snapshot\n#\n#\n"
|
||||||
lvcreate -s $1/$2 -l 4 -n snap "$dev6"
|
lvcreate -aey -s $1/$2 -l 4 -n snap "$dev6"
|
||||||
|
|
||||||
run_writemostly_check $1 $2
|
run_writemostly_check $1 $2
|
||||||
run_syncaction_check $1 $2
|
run_syncaction_check $1 $2
|
||||||
|
@ -11,8 +11,6 @@
|
|||||||
|
|
||||||
. lib/test
|
. lib/test
|
||||||
|
|
||||||
test -e LOCAL_CLVMD && skip
|
|
||||||
|
|
||||||
get_image_pvs() {
|
get_image_pvs() {
|
||||||
local d
|
local d
|
||||||
local images
|
local images
|
||||||
@ -24,7 +22,10 @@ get_image_pvs() {
|
|||||||
########################################################
|
########################################################
|
||||||
# MAIN
|
# MAIN
|
||||||
########################################################
|
########################################################
|
||||||
aux target_at_least dm-raid 1 2 0 || skip
|
if ! aux target_at_least dm-raid 1 2 0; then
|
||||||
|
dmsetup targets | grep raid
|
||||||
|
skip
|
||||||
|
fi
|
||||||
|
|
||||||
# 9 PVs needed for RAID10 testing (3-stripes/2-mirror - replacing 3 devs)
|
# 9 PVs needed for RAID10 testing (3-stripes/2-mirror - replacing 3 devs)
|
||||||
aux prepare_pvs 9 80
|
aux prepare_pvs 9 80
|
||||||
@ -57,17 +58,17 @@ for i in 1 2 3; do
|
|||||||
# Shouldn't be able to create with just 1 image
|
# Shouldn't be able to create with just 1 image
|
||||||
not lvcreate --type raid1 -m 0 -l 2 -n $lv1 $vg
|
not lvcreate --type raid1 -m 0 -l 2 -n $lv1 $vg
|
||||||
|
|
||||||
lvcreate -l 2 -n $lv1 $vg
|
lvcreate -aey -l 2 -n $lv1 $vg
|
||||||
else
|
else
|
||||||
lvcreate --type raid1 -m $(($i - 1)) -l 2 -n $lv1 $vg
|
lvcreate --type raid1 -m $(($i - 1)) -l 2 -n $lv1 $vg
|
||||||
aux wait_for_sync $vg $lv1
|
aux wait_for_sync $vg $lv1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if $under_snap; then
|
if $under_snap; then
|
||||||
lvcreate -s $vg/$lv1 -n snap -l 2
|
lvcreate -aey -s $vg/$lv1 -n snap -l 2
|
||||||
fi
|
fi
|
||||||
|
|
||||||
lvconvert -m $((j - 1)) $vg/$lv1
|
lvconvert -m $((j - 1)) $vg/$lv1
|
||||||
|
|
||||||
# FIXME: ensure no residual devices
|
# FIXME: ensure no residual devices
|
||||||
|
|
||||||
@ -138,7 +139,7 @@ lvremove -ff $vg
|
|||||||
###########################################
|
###########################################
|
||||||
# Linear to RAID1 conversion ("raid1" default segtype)
|
# Linear to RAID1 conversion ("raid1" default segtype)
|
||||||
###########################################
|
###########################################
|
||||||
lvcreate -l 2 -n $lv1 $vg
|
lvcreate -aey -l 2 -n $lv1 $vg
|
||||||
lvconvert -m 1 $vg/$lv1 \
|
lvconvert -m 1 $vg/$lv1 \
|
||||||
--config 'global { mirror_segtype_default = "raid1" }'
|
--config 'global { mirror_segtype_default = "raid1" }'
|
||||||
lvs --noheadings -o attr $vg/$lv1 | grep '^r*'
|
lvs --noheadings -o attr $vg/$lv1 | grep '^r*'
|
||||||
@ -147,17 +148,27 @@ lvremove -ff $vg
|
|||||||
###########################################
|
###########################################
|
||||||
# Linear to RAID1 conversion (override "mirror" default segtype)
|
# Linear to RAID1 conversion (override "mirror" default segtype)
|
||||||
###########################################
|
###########################################
|
||||||
lvcreate -l 2 -n $lv1 $vg
|
lvcreate -aey -l 2 -n $lv1 $vg
|
||||||
lvconvert --type raid1 -m 1 $vg/$lv1 \
|
lvconvert --type raid1 -m 1 $vg/$lv1 \
|
||||||
--config 'global { mirror_segtype_default = "mirror" }'
|
--config 'global { mirror_segtype_default = "mirror" }'
|
||||||
lvs --noheadings -o attr $vg/$lv1 | grep '^r*'
|
lvs --noheadings -o attr $vg/$lv1 | grep '^r*'
|
||||||
lvremove -ff $vg
|
lvremove -ff $vg
|
||||||
|
|
||||||
|
###########################################
|
||||||
|
# Must not be able to convert non-EX LVs in a cluster
|
||||||
|
###########################################
|
||||||
|
if [ -e LOCAL_CLVMD ]; then
|
||||||
|
lvcreate -l 2 -n $lv1 $vg
|
||||||
|
not lvconvert --type raid1 -m 1 $vg/$lv1 \
|
||||||
|
--config 'global { mirror_segtype_default = "mirror" }'
|
||||||
|
lvremove -ff $vg
|
||||||
|
fi
|
||||||
|
|
||||||
###########################################
|
###########################################
|
||||||
# Mirror to RAID1 conversion
|
# Mirror to RAID1 conversion
|
||||||
###########################################
|
###########################################
|
||||||
for i in 1 2 3 ; do
|
for i in 1 2 3 ; do
|
||||||
lvcreate --type mirror -m $i -l 2 -n $lv1 $vg
|
lvcreate -aey --type mirror -m $i -l 2 -n $lv1 $vg
|
||||||
aux wait_for_sync $vg $lv1
|
aux wait_for_sync $vg $lv1
|
||||||
lvconvert --type raid1 $vg/$lv1
|
lvconvert --type raid1 $vg/$lv1
|
||||||
lvremove -ff $vg
|
lvremove -ff $vg
|
||||||
|
@ -11,8 +11,6 @@
|
|||||||
|
|
||||||
. lib/test
|
. lib/test
|
||||||
|
|
||||||
test -e LOCAL_CLVMD && skip
|
|
||||||
|
|
||||||
get_image_pvs() {
|
get_image_pvs() {
|
||||||
local d
|
local d
|
||||||
local images
|
local images
|
||||||
@ -56,3 +54,5 @@ for i in 0 1; do
|
|||||||
$vg/$lv1
|
$vg/$lv1
|
||||||
aux wait_for_sync $vg $lv1
|
aux wait_for_sync $vg $lv1
|
||||||
done
|
done
|
||||||
|
|
||||||
|
lvremove -ff $vg
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
|
|
||||||
. lib/test
|
. lib/test
|
||||||
|
|
||||||
test -e LOCAL_CLVMD && skip
|
|
||||||
aux target_at_least dm-raid 1 1 0 || skip
|
aux target_at_least dm-raid 1 1 0 || skip
|
||||||
|
|
||||||
aux prepare_vg 5
|
aux prepare_vg 5
|
||||||
@ -51,7 +50,7 @@ done
|
|||||||
#
|
#
|
||||||
# Convert large linear to RAID1 (belong in different test script?)
|
# Convert large linear to RAID1 (belong in different test script?)
|
||||||
#
|
#
|
||||||
lvcreate -L 200T -n $lv1 $vg1
|
lvcreate -aey -L 200T -n $lv1 $vg1
|
||||||
# Need to deactivate or the up-convert will start sync'ing
|
# Need to deactivate or the up-convert will start sync'ing
|
||||||
lvchange -an $vg1/$lv1
|
lvchange -an $vg1/$lv1
|
||||||
lvconvert --type raid1 -m 1 $vg1/$lv1
|
lvconvert --type raid1 -m 1 $vg1/$lv1
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
|
|
||||||
. lib/test
|
. lib/test
|
||||||
|
|
||||||
test -e LOCAL_CLVMD && skip
|
|
||||||
aux target_at_least dm-raid 1 3 0 || skip
|
aux target_at_least dm-raid 1 3 0 || skip
|
||||||
|
|
||||||
aux prepare_vg 5
|
aux prepare_vg 5
|
||||||
|
@ -301,6 +301,20 @@ static int lvchange_refresh(struct cmd_context *cmd, struct logical_volume *lv)
|
|||||||
return lv_refresh(cmd, lv);
|
return lv_refresh(cmd, lv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int _reactivate_lv(struct logical_volume *lv,
|
||||||
|
int active, int exclusive)
|
||||||
|
{
|
||||||
|
struct cmd_context *cmd = lv->vg->cmd;
|
||||||
|
|
||||||
|
if (!active)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (exclusive)
|
||||||
|
return activate_lv_excl_local(cmd, lv);
|
||||||
|
|
||||||
|
return activate_lv(cmd, lv);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* lvchange_resync
|
* lvchange_resync
|
||||||
* @cmd
|
* @cmd
|
||||||
@ -311,6 +325,7 @@ static int lvchange_refresh(struct cmd_context *cmd, struct logical_volume *lv)
|
|||||||
static int lvchange_resync(struct cmd_context *cmd, struct logical_volume *lv)
|
static int lvchange_resync(struct cmd_context *cmd, struct logical_volume *lv)
|
||||||
{
|
{
|
||||||
int active = 0;
|
int active = 0;
|
||||||
|
int exclusive = 0;
|
||||||
int monitored;
|
int monitored;
|
||||||
struct lvinfo info;
|
struct lvinfo info;
|
||||||
struct lv_segment *seg = first_seg(lv);
|
struct lv_segment *seg = first_seg(lv);
|
||||||
@ -356,9 +371,17 @@ static int lvchange_resync(struct cmd_context *cmd, struct logical_volume *lv)
|
|||||||
return_0;
|
return_0;
|
||||||
|
|
||||||
active = 1;
|
active = 1;
|
||||||
|
if (lv_is_active_exclusive_locally(lv))
|
||||||
|
exclusive = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (seg_is_raid(seg) && active && !exclusive) {
|
||||||
|
log_error("RAID logical volume %s/%s cannot be active remotely.",
|
||||||
|
lv->vg->name, lv->name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Activate exclusively to ensure no nodes still have LV active */
|
/* Activate exclusively to ensure no nodes still have LV active */
|
||||||
monitored = dmeventd_monitor_mode();
|
monitored = dmeventd_monitor_mode();
|
||||||
if (monitored != DMEVENTD_MONITOR_IGNORE)
|
if (monitored != DMEVENTD_MONITOR_IGNORE)
|
||||||
@ -403,7 +426,7 @@ static int lvchange_resync(struct cmd_context *cmd, struct logical_volume *lv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (active && !activate_lv(cmd, lv)) {
|
if (!_reactivate_lv(lv, active, exclusive)) {
|
||||||
log_error("Failed to reactivate %s to resynchronize "
|
log_error("Failed to reactivate %s to resynchronize "
|
||||||
"mirror", lv->name);
|
"mirror", lv->name);
|
||||||
return 0;
|
return 0;
|
||||||
@ -429,7 +452,7 @@ static int lvchange_resync(struct cmd_context *cmd, struct logical_volume *lv)
|
|||||||
log_error("Failed to write intermediate VG metadata.");
|
log_error("Failed to write intermediate VG metadata.");
|
||||||
if (!attach_metadata_devices(seg, &device_list))
|
if (!attach_metadata_devices(seg, &device_list))
|
||||||
stack;
|
stack;
|
||||||
if (active && !activate_lv(cmd, lv))
|
if (!_reactivate_lv(lv, active, exclusive))
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -438,7 +461,7 @@ static int lvchange_resync(struct cmd_context *cmd, struct logical_volume *lv)
|
|||||||
log_error("Failed to commit intermediate VG metadata.");
|
log_error("Failed to commit intermediate VG metadata.");
|
||||||
if (!attach_metadata_devices(seg, &device_list))
|
if (!attach_metadata_devices(seg, &device_list))
|
||||||
stack;
|
stack;
|
||||||
if (active && !activate_lv(cmd, lv))
|
if (!_reactivate_lv(lv, active, exclusive))
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -446,9 +469,10 @@ static int lvchange_resync(struct cmd_context *cmd, struct logical_volume *lv)
|
|||||||
backup(lv->vg);
|
backup(lv->vg);
|
||||||
|
|
||||||
dm_list_iterate_items(lvl, &device_list) {
|
dm_list_iterate_items(lvl, &device_list) {
|
||||||
if (!activate_lv(cmd, lvl->lv)) {
|
if (!activate_lv_excl_local(cmd, lvl->lv)) {
|
||||||
log_error("Unable to activate %s for mirror log resync",
|
log_error("Unable to activate %s for %s clearing",
|
||||||
lvl->lv->name);
|
lvl->lv->name, (seg_is_raid(seg)) ?
|
||||||
|
"metadata area" : "mirror log");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -486,8 +510,9 @@ static int lvchange_resync(struct cmd_context *cmd, struct logical_volume *lv)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (active && !activate_lv(cmd, lv)) {
|
if (!_reactivate_lv(lv, active, exclusive)) {
|
||||||
log_error("Failed to reactivate %s after resync", lv->name);
|
log_error("Failed to reactivate %s after resync",
|
||||||
|
lv->name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1754,10 +1754,11 @@ static int lvconvert_raid(struct logical_volume *lv, struct lvconvert_params *lp
|
|||||||
return lv_raid_replace(lv, lp->replace_pvh, lp->pvh);
|
return lv_raid_replace(lv, lp->replace_pvh, lp->pvh);
|
||||||
|
|
||||||
if (arg_count(cmd, repair_ARG)) {
|
if (arg_count(cmd, repair_ARG)) {
|
||||||
if (!lv_is_active_locally(lv)) {
|
if (!lv_is_active_exclusive_locally(lv)) {
|
||||||
log_error("%s/%s must be active %sto perform"
|
log_error("%s/%s must be active %sto perform this"
|
||||||
"this operation.", lv->vg->name, lv->name,
|
" operation.", lv->vg->name, lv->name,
|
||||||
vg_is_clustered(lv->vg) ? "locally " : "");
|
vg_is_clustered(lv->vg) ?
|
||||||
|
"exclusive locally " : "");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user