All of lore.kernel.org
 help / color / mirror / Atom feed
From: Qu Wenruo <wqu@suse.com>
To: linux-btrfs@vger.kernel.org
Subject: [PATCH 02/14] btrfs: raid56: allow scrub operation to update both P and Q stripes
Date: Mon,  3 Jul 2023 15:32:26 +0800	[thread overview]
Message-ID: <af2b86a9089423882813409531e3bcd1d8479b38.1688368617.git.wqu@suse.com> (raw)
In-Reply-To: <cover.1688368617.git.wqu@suse.com>

Current the scrub_rbio() workload (used by
raid56_parity_alloc_scrub_rbio() then
raid56_parity_submit_scrub_rbio()) can only handle one P/Q stripe
workload.

But inside finish_parity_scrub() we always do the P/Q generation and
verification for both P/Q stripes.

For the incoming scrub_logical feature, we want to verify P/Q stripes in
one go, so here we introduce the ability to scrub both P/Q stripes.

To do that the following things are modified:

- raid56_parity_alloc_scrub_rbio() to allows empty @scrub_dev
  Thankfully we don't have any extra sanity checks to reject such
  empty parameter.

- Verify both P and Q stripes if @rbio->scrubp is 0
  Now we do the verification in a loop, and skip the stripe if
  rbio->scrubp is not zero and does not match the stripe number.

- Add bad sectors of both P/Q stripes to writeback
  Unfortunately we're using the same dbitmap, this means if only one
  of the P/Q stripes is corrupted, we would write both.
  However we can accept the slightly extra cost for it.

Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 fs/btrfs/raid56.c | 56 +++++++++++++++++++++++++++++++++++------------
 1 file changed, 42 insertions(+), 14 deletions(-)

diff --git a/fs/btrfs/raid56.c b/fs/btrfs/raid56.c
index cc783da065b4..d96bfc3a16fc 100644
--- a/fs/btrfs/raid56.c
+++ b/fs/btrfs/raid56.c
@@ -2363,7 +2363,14 @@ struct btrfs_raid_bio *raid56_parity_alloc_scrub_rbio(struct bio *bio,
 			break;
 		}
 	}
-	ASSERT(i < rbio->real_stripes);
+	/*
+	 * If @scrub_dev is specified, @scrubp must be the stripe number of
+	 * P or Q stripe.
+	 */
+	if (scrub_dev) {
+		ASSERT(rbio->scrubp >= rbio->nr_data);
+		ASSERT(rbio->scrubp < rbio->real_stripes);
+	}
 
 	bitmap_copy(&rbio->dbitmap, dbitmap, rbio->stripe_nsectors);
 	return rbio;
@@ -2426,7 +2433,8 @@ static int finish_parity_scrub(struct btrfs_raid_bio *rbio)
 	 * Replace is running and our P/Q stripe is being replaced, then we
 	 * need to duplicate the final write to replace target.
 	 */
-	if (bioc->replace_nr_stripes && bioc->replace_stripe_src == rbio->scrubp) {
+	if (rbio->scrubp && bioc->replace_nr_stripes &&
+	    bioc->replace_stripe_src == rbio->scrubp) {
 		is_replace = 1;
 		bitmap_copy(pbitmap, &rbio->dbitmap, rbio->stripe_nsectors);
 	}
@@ -2464,6 +2472,7 @@ static int finish_parity_scrub(struct btrfs_raid_bio *rbio)
 
 	for_each_set_bit(sectornr, &rbio->dbitmap, rbio->stripe_nsectors) {
 		struct sector_ptr *sector;
+		bool found_error = false;
 		void *parity;
 
 		/* first collect one page from each data stripe */
@@ -2484,14 +2493,22 @@ static int finish_parity_scrub(struct btrfs_raid_bio *rbio)
 		}
 
 		/* Check scrubbing parity and repair it */
-		sector = rbio_stripe_sector(rbio, rbio->scrubp, sectornr);
-		parity = kmap_local_page(sector->page) + sector->pgoff;
-		if (memcmp(parity, pointers[rbio->scrubp], sectorsize) != 0)
-			memcpy(parity, pointers[rbio->scrubp], sectorsize);
-		else
+		for (int i = rbio->nr_data; i < rbio->real_stripes; i++) {
+			/* Skip this stripe if it's not our scrub target. */
+			if (rbio->scrubp && i != rbio->scrubp)
+				continue;
+
+			sector = rbio_stripe_sector(rbio, i, sectornr);
+			parity = kmap_local_page(sector->page) + sector->pgoff;
+			if (memcmp(parity, pointers[i], sectorsize) != 0) {
+				memcpy(parity, pointers[i], sectorsize);
+				found_error = true;
+			}
+			kunmap_local(parity);
+		}
+		if (!found_error)
 			/* Parity is right, needn't writeback */
 			bitmap_clear(&rbio->dbitmap, sectornr, 1);
-		kunmap_local(parity);
 
 		for (stripe = nr_data - 1; stripe >= 0; stripe--)
 			kunmap_local(pointers[stripe]);
@@ -2514,11 +2531,16 @@ static int finish_parity_scrub(struct btrfs_raid_bio *rbio)
 	for_each_set_bit(sectornr, &rbio->dbitmap, rbio->stripe_nsectors) {
 		struct sector_ptr *sector;
 
-		sector = rbio_stripe_sector(rbio, rbio->scrubp, sectornr);
-		ret = rbio_add_io_sector(rbio, &bio_list, sector, rbio->scrubp,
-					 sectornr, REQ_OP_WRITE);
-		if (ret)
-			goto cleanup;
+		for (int i = rbio->nr_data; i < rbio->real_stripes; i++) {
+			/* Skip this stripe if it's not our scrub target. */
+			if (rbio->scrubp && i != rbio->scrubp)
+				continue;
+			sector = rbio_stripe_sector(rbio, i, sectornr);
+			ret = rbio_add_io_sector(rbio, &bio_list, sector, i,
+						 sectornr, REQ_OP_WRITE);
+			if (ret)
+				goto cleanup;
+		}
 	}
 
 	if (!is_replace)
@@ -2529,6 +2551,12 @@ static int finish_parity_scrub(struct btrfs_raid_bio *rbio)
 	 * the target device.  Check we have a valid source stripe number.
 	 */
 	ASSERT(rbio->bioc->replace_stripe_src >= 0);
+	/*
+	 * For dev-replace case, scrubp must be provided by the caller at
+	 * raid56_parity_alloc_scrub_rbio().
+	 */
+	ASSERT(rbio->scrubp >= rbio->nr_data);
+	ASSERT(rbio->scrubp < rbio->real_stripes);
 	for_each_set_bit(sectornr, pbitmap, rbio->stripe_nsectors) {
 		struct sector_ptr *sector;
 
@@ -2625,7 +2653,7 @@ static int recover_scrub_rbio(struct btrfs_raid_bio *rbio)
 		 * scrubbing parity, luckily, use the other one to repair the
 		 * data, or we can not repair the data stripe.
 		 */
-		if (failp != rbio->scrubp) {
+		if (rbio->scrubp && failp != rbio->scrubp) {
 			ret = -EIO;
 			goto out;
 		}
-- 
2.41.0


  parent reply	other threads:[~2023-07-03  7:33 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-07-03  7:32 [PATCH 00/14] btrfs: scrub: introduce SCRUB_LOGICAL flag Qu Wenruo
2023-07-03  7:32 ` [PATCH 01/14] btrfs: raid56: remove unnecessary parameter for raid56_parity_alloc_scrub_rbio() Qu Wenruo
2023-07-03 12:33   ` Anand Jain
2023-07-12 16:23   ` Christoph Hellwig
2023-07-03  7:32 ` Qu Wenruo [this message]
2023-07-12 16:24   ` [PATCH 02/14] btrfs: raid56: allow scrub operation to update both P and Q stripes Christoph Hellwig
2023-07-03  7:32 ` [PATCH 03/14] btrfs: raid56: allow caching P/Q stripes Qu Wenruo
2023-07-12 16:27   ` Christoph Hellwig
2023-07-03  7:32 ` [PATCH 04/14] btrfs: raid56: add the interfaces to submit recovery rbio Qu Wenruo
2023-07-03  7:32 ` [PATCH 05/14] btrfs: add the ability to read P/Q stripes directly Qu Wenruo
2023-07-03  9:46   ` Qu Wenruo
2023-07-03  7:32 ` [PATCH 06/14] btrfs: scrub: make scrub_ctx::stripes dynamically allocated Qu Wenruo
2023-07-03  7:32 ` [PATCH 07/14] btrfs: scrub: introduce the skeleton for logical-scrub Qu Wenruo
2023-07-03  7:32 ` [PATCH 08/14] btrfs: scrub: extract the common preparation before scrubbing a block group Qu Wenruo
2023-07-03  7:32 ` [PATCH 09/14] btrfs: scrub: implement the chunk iteration code for scrub_logical Qu Wenruo
2023-07-03  7:32 ` [PATCH 10/14] btrfs: scrub: implement the basic extent iteration code Qu Wenruo
2023-07-03  7:32 ` [PATCH 11/14] btrfs: scrub: implement the repair part of scrub logical Qu Wenruo
2023-07-03  7:32 ` [PATCH 12/14] btrfs: scrub: add RAID56 support for queue_scrub_logical_stripes() Qu Wenruo
2023-07-03  7:32 ` [PATCH 13/14] btrfs: scrub: introduce the RAID56 data recovery path for scrub logical Qu Wenruo
2023-07-03  7:32 ` [PATCH 14/14] btrfs: scrub: implement the RAID56 P/Q scrub code Qu Wenruo
2023-07-03 12:58 ` [PATCH 00/14] btrfs: scrub: introduce SCRUB_LOGICAL flag Graham Cobb
2023-07-03 22:40   ` Qu Wenruo
2023-07-03 23:19     ` Graham Cobb
2023-07-13 12:14 ` David Sterba

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=af2b86a9089423882813409531e3bcd1d8479b38.1688368617.git.wqu@suse.com \
    --to=wqu@suse.com \
    --cc=linux-btrfs@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.