md/raid5: consider updating reshape_position at start of reshape.
authorNeilBrown <neilb@suse.com>
Mon, 6 Jul 2015 02:28:45 +0000 (12:28 +1000)
committerNeilBrown <neilb@suse.com>
Mon, 31 Aug 2015 17:31:20 +0000 (19:31 +0200)
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>
drivers/md/raid5.c

index f757023fc4580680bfdd6e178f93acb62cb1f31e..256b05d1117be643e4094703c01e9bd79b2aef9c 100644 (file)
@@ -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)