Skip to content

Commit

Permalink
md/raid5: Check all disks in a stripe_head for reshape progress
Browse files Browse the repository at this point in the history
When testing if a previous stripe has had reshape expand past it, use
the earliest or latest logical sector in all the disks for that stripe
head. This will allow adding multiple disks at a time in a subesquent
patch.

To do this cleaner, refactor the check into a helper function called
stripe_ahead_of_reshape().

Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Song Liu <song@kernel.org>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
  • Loading branch information
lsgunth authored and axboe committed Aug 2, 2022
1 parent 4ad1d98 commit 486f605
Showing 1 changed file with 39 additions and 14 deletions.
53 changes: 39 additions & 14 deletions drivers/md/raid5.c
Original file line number Diff line number Diff line change
Expand Up @@ -5819,6 +5819,40 @@ static bool ahead_of_reshape(struct mddev *mddev, sector_t sector,
sector >= reshape_sector;
}

static bool range_ahead_of_reshape(struct mddev *mddev, sector_t min,
sector_t max, sector_t reshape_sector)
{
return mddev->reshape_backwards ? max < reshape_sector :
min >= reshape_sector;
}

static bool stripe_ahead_of_reshape(struct mddev *mddev, struct r5conf *conf,
struct stripe_head *sh)
{
sector_t max_sector = 0, min_sector = MaxSector;
bool ret = false;
int dd_idx;

for (dd_idx = 0; dd_idx < sh->disks; dd_idx++) {
if (dd_idx == sh->pd_idx)
continue;

min_sector = min(min_sector, sh->dev[dd_idx].sector);
max_sector = min(max_sector, sh->dev[dd_idx].sector);
}

spin_lock_irq(&conf->device_lock);

if (!range_ahead_of_reshape(mddev, min_sector, max_sector,
conf->reshape_progress))
/* mismatch, need to try again */
ret = true;

spin_unlock_irq(&conf->device_lock);

return ret;
}

enum stripe_result {
STRIPE_SUCCESS = 0,
STRIPE_RETRY,
Expand Down Expand Up @@ -5883,27 +5917,18 @@ static enum stripe_result make_stripe_request(struct mddev *mddev,
return STRIPE_FAIL;
}

if (unlikely(previous)) {
if (unlikely(previous) &&
stripe_ahead_of_reshape(mddev, conf, sh)) {
/*
* Expansion might have moved on while waiting for a
* stripe, so we must do the range check again.
* Expansion moved on while waiting for a stripe.
* Expansion could still move past after this
* test, but as we are holding a reference to
* 'sh', we know that if that happens,
* STRIPE_EXPANDING will get set and the expansion
* won't proceed until we finish with the stripe.
*/
int must_retry = 0;
spin_lock_irq(&conf->device_lock);
if (!ahead_of_reshape(mddev, logical_sector,
conf->reshape_progress))
/* mismatch, need to try again */
must_retry = 1;
spin_unlock_irq(&conf->device_lock);
if (must_retry) {
ret = STRIPE_SCHEDULE_AND_RETRY;
goto out_release;
}
ret = STRIPE_SCHEDULE_AND_RETRY;
goto out_release;
}

if (read_seqcount_retry(&conf->gen_lock, seq)) {
Expand Down

0 comments on commit 486f605

Please sign in to comment.