summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLogan Gunthorpe <logang@deltatee.com>2022-06-16 13:19:42 -0600
committerSong Liu <song@kernel.org>2022-07-03 07:55:42 -0700
commit76816a91b3d24670e5f0e8b5ab49aa6f9c497147 (patch)
treed25a3599f91d2da80f0223249cc19076ae45f915
parentb16d91f9b7ea286cff87173a3c4284a61f12f096 (diff)
md/raid5: Check all disks in a stripe_head for reshape progress
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>
-rw-r--r--drivers/md/raid5.c53
1 files changed, 39 insertions, 14 deletions
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index f12773c2387a..b27b754ee18c 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -5818,6 +5818,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,
@@ -5882,27 +5916,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)) {