summaryrefslogtreecommitdiff
path: root/tools/lvchange.c
diff options
context:
space:
mode:
authorHeinz Mauelshagen <heinzm@redhat.com>2018-10-31 23:05:08 +0100
committerHeinz Mauelshagen <heinzm@redhat.com>2018-12-11 16:35:34 +0100
commitdd5716ddf258c4a44819fa90d3356833ccf767b4 (patch)
treee30f68547a530edf37523866b2ba7a9588abf7fa /tools/lvchange.c
parentb2d1facd960e192b38ae4a9866f3bea9646e6cd5 (diff)
downloadlvm2-dd5716ddf258c4a44819fa90d3356833ccf767b4.tar.gz
raid: fix (de)activation of RaidLVs with visible SubLVs
There's a small window during creation of a new RaidLV when rmeta SubLVs are made visible to wipe them in order to prevent erroneous discovery of stale RAID metadata. In case a crash prevents the SubLVs from being committed hidden after such wiping, the RaidLV can still be activated with the SubLVs visible. During deactivation though, a deadlock occurs because the visible SubLVs are deactivated before the RaidLV. The patch adds _check_raid_sublvs to the raid validation in merge.c, an activation check to activate.c (paranoid, because the merge.c check will prevent activation in case of visible SubLVs) and shares the existing wiping function _clear_lvs in raid_manip.c moved to lv_manip.c and renamed to activate_and_wipe_lvlist to remove code duplication. Whilst on it, introduce activate_and_wipe_lv to share with (lvconvert|lvchange).c. Resolves: rhbz1633167
Diffstat (limited to 'tools/lvchange.c')
-rw-r--r--tools/lvchange.c32
1 files changed, 5 insertions, 27 deletions
diff --git a/tools/lvchange.c b/tools/lvchange.c
index 537e582aa..975e24fc3 100644
--- a/tools/lvchange.c
+++ b/tools/lvchange.c
@@ -311,7 +311,6 @@ static int _lvchange_resync(struct cmd_context *cmd, struct logical_volume *lv)
int monitored;
struct lv_segment *seg = first_seg(lv);
struct dm_list device_list;
- struct lv_list *lvl;
dm_list_init(&device_list);
@@ -389,6 +388,7 @@ static int _lvchange_resync(struct cmd_context *cmd, struct logical_volume *lv)
* Now we handle mirrors with log devices
*/
lv->status &= ~LV_NOTSYNCED;
+ lv->status |= LV_ACTIVATION_SKIP;
/* Separate mirror log or metadata devices so we can clear them */
if (!_detach_metadata_devices(seg, &device_list)) {
@@ -407,32 +407,8 @@ static int _lvchange_resync(struct cmd_context *cmd, struct logical_volume *lv)
/* No backup for intermediate metadata, so just unlock memory */
memlock_unlock(lv->vg->cmd);
- dm_list_iterate_items(lvl, &device_list) {
- if (!activate_lv(cmd, lvl->lv)) {
- log_error("Unable to activate %s for %s clearing.",
- display_lvname(lvl->lv), (seg_is_raid(seg)) ?
- "metadata area" : "mirror log");
- return 0;
- }
-
- if (!wipe_lv(lvl->lv, (struct wipe_params)
- { .do_zero = 1, .zero_sectors = lvl->lv->size })) {
- log_error("Unable to reset sync status for %s.",
- display_lvname(lv));
- if (!deactivate_lv(cmd, lvl->lv))
- log_error("Failed to deactivate log LV after "
- "wiping failed");
- return 0;
- }
-
- if (!deactivate_lv(cmd, lvl->lv)) {
- log_error("Unable to deactivate %s LV %s "
- "after wiping for resync.",
- (seg_is_raid(seg)) ? "metadata" : "log",
- display_lvname(lvl->lv));
- return 0;
- }
- }
+ if (!activate_and_wipe_lvlist(&device_list, 0))
+ return 0;
/* Wait until devices are away */
if (!sync_local_dev_names(lv->vg->cmd)) {
@@ -448,6 +424,8 @@ static int _lvchange_resync(struct cmd_context *cmd, struct logical_volume *lv)
return 0;
}
+ lv->status &= ~LV_ACTIVATION_SKIP;
+
if (!_vg_write_commit(lv, NULL))
return 0;