| From foo@baz Fri Mar 16 15:43:17 CET 2018 |
| From: Heinz Mauelshagen <heinzm@redhat.com> |
| Date: Sat, 2 Dec 2017 01:03:51 +0100 |
| Subject: dm raid: fix raid set size revalidation |
| |
| From: Heinz Mauelshagen <heinzm@redhat.com> |
| |
| |
| [ Upstream commit 61e06e2c3ebd986050958513bfa40dceed756f8f ] |
| |
| The raid set size is being revalidated unconditionally before a |
| reshaping conversion is started. MD requires the size to only be |
| reduced in case of a stripe removing (i.e. shrinking) reshape but not |
| when growing because the raid array has to stay small until after the |
| growing reshape finishes. |
| |
| Fix by avoiding the size revalidation in preresume unless a shrinking |
| reshape is requested. |
| |
| Signed-off-by: Heinz Mauelshagen <heinzm@redhat.com> |
| Signed-off-by: Mike Snitzer <snitzer@redhat.com> |
| Signed-off-by: Sasha Levin <alexander.levin@microsoft.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/md/dm-raid.c | 30 ++++++++++++++++++++---------- |
| 1 file changed, 20 insertions(+), 10 deletions(-) |
| |
| --- a/drivers/md/dm-raid.c |
| +++ b/drivers/md/dm-raid.c |
| @@ -675,15 +675,11 @@ static struct raid_type *get_raid_type_b |
| return NULL; |
| } |
| |
| -/* |
| - * Conditionally change bdev capacity of @rs |
| - * in case of a disk add/remove reshape |
| - */ |
| -static void rs_set_capacity(struct raid_set *rs) |
| +/* Adjust rdev sectors */ |
| +static void rs_set_rdev_sectors(struct raid_set *rs) |
| { |
| struct mddev *mddev = &rs->md; |
| struct md_rdev *rdev; |
| - struct gendisk *gendisk = dm_disk(dm_table_get_md(rs->ti->table)); |
| |
| /* |
| * raid10 sets rdev->sector to the device size, which |
| @@ -692,8 +688,16 @@ static void rs_set_capacity(struct raid_ |
| rdev_for_each(rdev, mddev) |
| if (!test_bit(Journal, &rdev->flags)) |
| rdev->sectors = mddev->dev_sectors; |
| +} |
| |
| - set_capacity(gendisk, mddev->array_sectors); |
| +/* |
| + * Change bdev capacity of @rs in case of a disk add/remove reshape |
| + */ |
| +static void rs_set_capacity(struct raid_set *rs) |
| +{ |
| + struct gendisk *gendisk = dm_disk(dm_table_get_md(rs->ti->table)); |
| + |
| + set_capacity(gendisk, rs->md.array_sectors); |
| revalidate_disk(gendisk); |
| } |
| |
| @@ -1674,8 +1678,11 @@ static void do_table_event(struct work_s |
| struct raid_set *rs = container_of(ws, struct raid_set, md.event_work); |
| |
| smp_rmb(); /* Make sure we access most actual mddev properties */ |
| - if (!rs_is_reshaping(rs)) |
| + if (!rs_is_reshaping(rs)) { |
| + if (rs_is_raid10(rs)) |
| + rs_set_rdev_sectors(rs); |
| rs_set_capacity(rs); |
| + } |
| dm_table_event(rs->ti->table); |
| } |
| |
| @@ -3845,11 +3852,10 @@ static int raid_preresume(struct dm_targ |
| mddev->resync_min = mddev->recovery_cp; |
| } |
| |
| - rs_set_capacity(rs); |
| - |
| /* Check for any reshape request unless new raid set */ |
| if (test_and_clear_bit(RT_FLAG_RESHAPE_RS, &rs->runtime_flags)) { |
| /* Initiate a reshape. */ |
| + rs_set_rdev_sectors(rs); |
| mddev_lock_nointr(mddev); |
| r = rs_start_reshape(rs); |
| mddev_unlock(mddev); |
| @@ -3878,6 +3884,10 @@ static void raid_resume(struct dm_target |
| mddev->ro = 0; |
| mddev->in_sync = 0; |
| |
| + /* Only reduce raid set size before running a disk removing reshape. */ |
| + if (mddev->delta_disks < 0) |
| + rs_set_capacity(rs); |
| + |
| /* |
| * Keep the RAID set frozen if reshape/rebuild flags are set. |
| * The RAID set is unfrozen once the next table load/resume, |