From c5e19d906a658f27fa858b09a95d9551b1a69bd0 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Fri, 17 Jul 2015 12:06:02 +1000 Subject: [PATCH] md: be careful when testing resync_max against curr_resync_completed. While it generally shouldn't happen, it is not impossible for curr_resync_completed to exceed resync_max. This can particularly happen when reshaping RAID5 - the current status isn't copied to curr_resync_completed promptly, so when it is, it can exceed resync_max. This happens when the reshape is 'frozen', resync_max is set low, and reshape is re-enabled. Taking a difference between two unsigned numbers is always dangerous anyway, so add a test to behave correctly if curr_resync_completed > resync_max Signed-off-by: NeilBrown --- drivers/md/md.c | 3 ++- drivers/md/raid5.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index 5b62a3d49e12..b326cd26b027 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -7834,7 +7834,8 @@ void md_do_sync(struct md_thread *thread) > (max_sectors >> 4)) || time_after_eq(jiffies, update_time + UPDATE_FREQUENCY) || (j - mddev->curr_resync_completed)*2 - >= mddev->resync_max - mddev->curr_resync_completed + >= mddev->resync_max - mddev->curr_resync_completed || + mddev->curr_resync_completed > mddev->resync_max )) { /* time to update curr_resync_completed */ wait_event(mddev->recovery_wait, diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 19bbdbe1a52f..1c27aa10f89c 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -5542,7 +5542,8 @@ static sector_t reshape_request(struct mddev *mddev, sector_t sector_nr, int *sk sector_nr += reshape_sectors; retn = reshape_sectors; finish: - if ((sector_nr - mddev->curr_resync_completed) * 2 + if (mddev->curr_resync_completed > mddev->resync_max || + (sector_nr - mddev->curr_resync_completed) * 2 >= mddev->resync_max - mddev->curr_resync_completed) { /* Cannot proceed until we've updated the superblock... */ wait_event(conf->wait_for_overlap,