aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.com>2015-07-06 12:28:45 +1000
committerNeilBrown <neilb@suse.com>2015-08-31 19:31:20 +0200
commit92140480ed59a006b245efd33a195fde62d1845f (patch)
treebcd753ecf5a203c17fd056a51faceff52cc7126f /drivers/md
parentmd: close some races between setting and checking sync_action. (diff)
downloadlinux-dev-92140480ed59a006b245efd33a195fde62d1845f.tar.xz
linux-dev-92140480ed59a006b245efd33a195fde62d1845f.zip
md/raid5: consider updating reshape_position at start of reshape.
md/raid5 only updates ->reshape_position (which is stored in metadata and is authoritative) occasionally, but particularly when getting closed to ->resync_max as it must be correct when ->resync_max is reached. When mdadm tries to stop an array which is reshaping it will: - freeze the reshape, - set resync_max to where the reshape has reached. - unfreeze the reshape. When this happens, the reshape is aborted and then restarted. The restart doesn't check that resync_max is close, and so doesn't update ->reshape_position like it should. This results in the reshape stopping, but ->reshape_position being incorrect. So on that first call to reshape_request, make sure ->reshape_position is updated if needed. Signed-off-by: NeilBrown <neilb@suse.com>
Diffstat (limited to 'drivers/md')
-rw-r--r--drivers/md/raid5.c8
1 files changed, 6 insertions, 2 deletions
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index f757023fc458..256b05d1117b 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -5347,6 +5347,7 @@ static sector_t reshape_request(struct mddev *mddev, sector_t sector_nr, int *sk
sector_t stripe_addr;
int reshape_sectors;
struct list_head stripes;
+ sector_t retn;
if (sector_nr == 0) {
/* If restarting in the middle, skip the initial sectors */
@@ -5362,7 +5363,8 @@ static sector_t reshape_request(struct mddev *mddev, sector_t sector_nr, int *sk
mddev->curr_resync_completed = sector_nr;
sysfs_notify(&mddev->kobj, NULL, "sync_completed");
*skipped = 1;
- return sector_nr;
+ retn = sector_nr;
+ goto finish;
}
}
@@ -5535,6 +5537,8 @@ static sector_t reshape_request(struct mddev *mddev, sector_t sector_nr, int *sk
* then we need to write out the superblock.
*/
sector_nr += reshape_sectors;
+ retn = reshape_sectors;
+finish:
if ((sector_nr - mddev->curr_resync_completed) * 2
>= mddev->resync_max - mddev->curr_resync_completed) {
/* Cannot proceed until we've updated the superblock... */
@@ -5560,7 +5564,7 @@ static sector_t reshape_request(struct mddev *mddev, sector_t sector_nr, int *sk
sysfs_notify(&mddev->kobj, NULL, "sync_completed");
}
ret:
- return reshape_sectors;
+ return retn;
}
static inline sector_t sync_request(struct mddev *mddev, sector_t sector_nr, int *skipped)