aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md
diff options
context:
space:
mode:
authorHeinz Mauelshagen <heinzm@redhat.com>2017-02-28 13:17:49 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-03-12 00:41:44 -0500
commit2937e22c2314cdfe31d82e2cc36af4be863be978 (patch)
tree1b8452382f180247be755c67a19b53c53bd5e66b /drivers/md
parentb7f874eedc9308a43b0d29e2a12f848be724fca7 (diff)
dm raid: fix data corruption on reshape request
commit d36a19541fe8f392778ac137d60f9be8dfdd8f9d upstream. The lvm2 sequence to manage dm-raid constructor flags that trigger a rebuild or a reshape is defined as: 1) load table with flags (e.g. rebuild/delta_disks/data_offset) 2) clear out the flags in lvm2 metadata 3) store the lvm2 metadata, reload the table to reset the flags previously established during the initial load (1) -- in order to prevent repeatedly requesting a rebuild or a reshape on activation Currently, loading an inactive table with rebuild/reshape flags specified will cause dm-raid to rebuild/reshape on resume and thus start updating the raid metadata (about the progress). When the second table reload, to reset the flags, occurs the constructor accesses the volatile progress state kept in the raid superblocks. Because the active mapping is still processing the rebuild/reshape, that position will be stale by the time the device is resumed. In the reshape case, this causes data corruption by processing already reshaped stripes again. In the rebuild case, it does _not_ cause data corruption but instead involves superfluous rebuilds. Fix by keeping the raid set frozen during the first resume and then allow the rebuild/reshape during the second resume. Fixes: 9dbd1aa3a ("dm raid: add reshaping support to the target") Signed-off-by: Heinz Mauelshagen <heinzm@redhat.com> Signed-off-by: Mike Snitzer <snitzer@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/md')
-rw-r--r--drivers/md/dm-raid.c12
1 files changed, 11 insertions, 1 deletions
diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c
index af2d79b52484..15daa36fcea6 100644
--- a/drivers/md/dm-raid.c
+++ b/drivers/md/dm-raid.c
@@ -3621,6 +3621,8 @@ static int raid_preresume(struct dm_target *ti)
3621 return r; 3621 return r;
3622} 3622}
3623 3623
3624#define RESUME_STAY_FROZEN_FLAGS (CTR_FLAG_DELTA_DISKS | CTR_FLAG_DATA_OFFSET)
3625
3624static void raid_resume(struct dm_target *ti) 3626static void raid_resume(struct dm_target *ti)
3625{ 3627{
3626 struct raid_set *rs = ti->private; 3628 struct raid_set *rs = ti->private;
@@ -3638,7 +3640,15 @@ static void raid_resume(struct dm_target *ti)
3638 mddev->ro = 0; 3640 mddev->ro = 0;
3639 mddev->in_sync = 0; 3641 mddev->in_sync = 0;
3640 3642
3641 clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery); 3643 /*
3644 * Keep the RAID set frozen if reshape/rebuild flags are set.
3645 * The RAID set is unfrozen once the next table load/resume,
3646 * which clears the reshape/rebuild flags, occurs.
3647 * This ensures that the constructor for the inactive table
3648 * retrieves an up-to-date reshape_position.
3649 */
3650 if (!(rs->ctr_flags & RESUME_STAY_FROZEN_FLAGS))
3651 clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
3642 3652
3643 if (mddev->suspended) 3653 if (mddev->suspended)
3644 mddev_resume(mddev); 3654 mddev_resume(mddev);