1
0
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:
Jonathan Brassow 2013-09-10 16:33:22 -05:00
parent 8d1d83504d
commit 2691f1d764
13 changed files with 124 additions and 83 deletions

View File

@ -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.

View File

@ -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 */

View File

@ -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. */

View File

@ -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))

View File

@ -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 "

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;
} }

View File

@ -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;
} }