From: Qu Wenruo <wqu@suse.com>
To: linux-btrfs@vger.kernel.org
Subject: [PATCH v2 12/17] btrfs: return proper mapped length for RAID56 profiles in __btrfs_map_block()
Date: Mon, 6 Dec 2021 10:29:32 +0800 [thread overview]
Message-ID: <20211206022937.26465-13-wqu@suse.com> (raw)
In-Reply-To: <20211206022937.26465-1-wqu@suse.com>
For profiles other than RAID56, __btrfs_map_block() returns @map_length
as min(stripe_end, logical + *length), which is also the same result
from btrfs_get_io_geometry().
But for RAID56, __btrfs_map_block() returns @map_length as stripe_len.
This strange behavior is going to hurt incoming bio split at
btrfs_map_bio() time, as we will use @map_length as bio split size.
Fix this behavior by:
- Return @map_length by the same calculatioin as other profiles
- Save stripe_len into btrfs_io_context
- Pass btrfs_io_context::stripe_len to raid56_*() functions
- Update raid56_*() functions to make its stripe_len parameter more
explicit
- Update scrub_stripe_index_and_offset() to properly name its
parameters
- Add extra ASSERT()s to make sure the passed stripe_len is correct
Signed-off-by: Qu Wenruo <wqu@suse.com>
---
fs/btrfs/raid56.c | 12 ++++++++++--
fs/btrfs/raid56.h | 2 +-
fs/btrfs/scrub.c | 14 ++++++++------
fs/btrfs/volumes.c | 13 ++++++++++---
fs/btrfs/volumes.h | 1 +
5 files changed, 30 insertions(+), 12 deletions(-)
diff --git a/fs/btrfs/raid56.c b/fs/btrfs/raid56.c
index 13e726c88a81..d35cfd750b76 100644
--- a/fs/btrfs/raid56.c
+++ b/fs/btrfs/raid56.c
@@ -969,6 +969,8 @@ static struct btrfs_raid_bio *alloc_rbio(struct btrfs_fs_info *fs_info,
int stripe_npages = DIV_ROUND_UP(stripe_len, PAGE_SIZE);
void *p;
+ ASSERT(stripe_len == BTRFS_STRIPE_LEN);
+
rbio = kzalloc(sizeof(*rbio) +
sizeof(*rbio->stripe_pages) * num_pages +
sizeof(*rbio->bio_pages) * num_pages +
@@ -1725,6 +1727,9 @@ int raid56_parity_write(struct bio *bio, struct btrfs_io_context *bioc,
struct blk_plug_cb *cb;
int ret;
+ /* Currently we only support fixed stripe len */
+ ASSERT(stripe_len == BTRFS_STRIPE_LEN);
+
rbio = alloc_rbio(fs_info, bioc, stripe_len);
if (IS_ERR(rbio)) {
btrfs_put_bioc(bioc);
@@ -2122,6 +2127,9 @@ int raid56_parity_recover(struct bio *bio, struct btrfs_io_context *bioc,
struct btrfs_raid_bio *rbio;
int ret;
+ /* Currently we only support fixed stripe len */
+ ASSERT(stripe_len == BTRFS_STRIPE_LEN);
+
if (generic_io) {
ASSERT(bioc->mirror_num == mirror_num);
btrfs_bio(bio)->mirror_num = mirror_num;
@@ -2671,12 +2679,12 @@ void raid56_parity_submit_scrub_rbio(struct btrfs_raid_bio *rbio)
struct btrfs_raid_bio *
raid56_alloc_missing_rbio(struct bio *bio, struct btrfs_io_context *bioc,
- u64 length)
+ u64 stripe_len)
{
struct btrfs_fs_info *fs_info = bioc->fs_info;
struct btrfs_raid_bio *rbio;
- rbio = alloc_rbio(fs_info, bioc, length);
+ rbio = alloc_rbio(fs_info, bioc, stripe_len);
if (IS_ERR(rbio))
return NULL;
diff --git a/fs/btrfs/raid56.h b/fs/btrfs/raid56.h
index 72c00fc284b5..7322dcae4498 100644
--- a/fs/btrfs/raid56.h
+++ b/fs/btrfs/raid56.h
@@ -46,7 +46,7 @@ void raid56_parity_submit_scrub_rbio(struct btrfs_raid_bio *rbio);
struct btrfs_raid_bio *
raid56_alloc_missing_rbio(struct bio *bio, struct btrfs_io_context *bioc,
- u64 length);
+ u64 stripe_len);
void raid56_submit_missing_rbio(struct btrfs_raid_bio *rbio);
int btrfs_alloc_stripe_hash_table(struct btrfs_fs_info *info);
diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c
index 15a123e67108..59bb2d08e697 100644
--- a/fs/btrfs/scrub.c
+++ b/fs/btrfs/scrub.c
@@ -1229,13 +1229,15 @@ static inline int scrub_nr_raid_mirrors(struct btrfs_io_context *bioc)
static inline void scrub_stripe_index_and_offset(u64 logical, u64 map_type,
u64 *raid_map,
- u64 mapped_length,
+ u64 stripe_len,
int nstripes, int mirror,
int *stripe_index,
u64 *stripe_offset)
{
int i;
+ ASSERT(stripe_len == BTRFS_STRIPE_LEN);
+
if (map_type & BTRFS_BLOCK_GROUP_RAID56_MASK) {
/* RAID5/6 */
for (i = 0; i < nstripes; i++) {
@@ -1244,7 +1246,7 @@ static inline void scrub_stripe_index_and_offset(u64 logical, u64 map_type,
continue;
if (logical >= raid_map[i] &&
- logical < raid_map[i] + mapped_length)
+ logical < raid_map[i] + stripe_len)
break;
}
@@ -1349,7 +1351,7 @@ static int scrub_setup_recheck_block(struct scrub_block *original_sblock,
scrub_stripe_index_and_offset(logical,
bioc->map_type,
bioc->raid_map,
- mapped_length,
+ bioc->stripe_len,
bioc->num_stripes -
bioc->num_tgtdevs,
mirror_index,
@@ -1401,7 +1403,7 @@ static int scrub_submit_raid56_bio_wait(struct btrfs_fs_info *fs_info,
mirror_num = spage->sblock->pagev[0]->mirror_num;
ret = raid56_parity_recover(bio, spage->recover->bioc,
- spage->recover->map_length,
+ spage->recover->bioc->stripe_len,
mirror_num, 0);
if (ret)
return ret;
@@ -2230,7 +2232,7 @@ static void scrub_missing_raid56_pages(struct scrub_block *sblock)
bio->bi_private = sblock;
bio->bi_end_io = scrub_missing_raid56_end_io;
- rbio = raid56_alloc_missing_rbio(bio, bioc, length);
+ rbio = raid56_alloc_missing_rbio(bio, bioc, bioc->stripe_len);
if (!rbio)
goto rbio_out;
@@ -2846,7 +2848,7 @@ static void scrub_parity_check_and_repair(struct scrub_parity *sparity)
bio->bi_private = sparity;
bio->bi_end_io = scrub_parity_bio_endio;
- rbio = raid56_parity_alloc_scrub_rbio(bio, bioc, length,
+ rbio = raid56_parity_alloc_scrub_rbio(bio, bioc, bioc->stripe_len,
sparity->scrub_dev,
sparity->dbitmap,
sparity->nsectors);
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index fba08cfcbd4e..6d962450e355 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -6051,6 +6051,7 @@ static int __btrfs_map_block_for_discard(struct btrfs_fs_info *fs_info,
ret = -ENOMEM;
goto out;
}
+ bioc->stripe_len = map->stripe_len;
for (i = 0; i < num_stripes; i++) {
bioc->stripes[i].physical =
@@ -6406,6 +6407,7 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info,
{
struct extent_map *em;
struct map_lookup *map;
+ const u64 orig_length = *length;
u64 stripe_offset;
u64 stripe_nr;
u64 stripe_len;
@@ -6427,6 +6429,7 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info,
ASSERT(bioc_ret);
ASSERT(op != BTRFS_MAP_DISCARD);
+ ASSERT(orig_length);
em = btrfs_get_chunk_map(fs_info, logical, *length);
ASSERT(!IS_ERR(em));
@@ -6522,7 +6525,10 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info,
num_stripes = map->num_stripes;
max_errors = nr_parity_stripes(map);
- *length = map->stripe_len;
+ /* Return the length to the full stripe end */
+ *length = min(raid56_full_stripe_start + em->start +
+ data_stripes * stripe_len,
+ logical + orig_length) - logical;
stripe_index = 0;
stripe_offset = 0;
} else {
@@ -6574,6 +6580,7 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info,
ret = -ENOMEM;
goto out;
}
+ bioc->stripe_len = map->stripe_len;
for (i = 0; i < num_stripes; i++) {
bioc->stripes[i].physical = map->stripes[stripe_index].physical +
@@ -6824,9 +6831,9 @@ static int submit_one_mapped_range(struct btrfs_fs_info *fs_info, struct bio *bi
/* In this case, map_length has been set to the length of
a single stripe; not the whole write */
if (btrfs_op(bio) == BTRFS_MAP_WRITE) {
- ret = raid56_parity_write(bio, bioc, map_length);
+ ret = raid56_parity_write(bio, bioc, bioc->stripe_len);
} else {
- ret = raid56_parity_recover(bio, bioc, map_length,
+ ret = raid56_parity_recover(bio, bioc, bioc->stripe_len,
mirror_num, 1);
}
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h
index a7f3fd4b4226..04c016a844f8 100644
--- a/fs/btrfs/volumes.h
+++ b/fs/btrfs/volumes.h
@@ -449,6 +449,7 @@ struct btrfs_io_context {
struct bio *orig_bio;
void *private;
atomic_t error;
+ u32 stripe_len;
int max_errors;
int num_stripes;
int mirror_num;
--
2.34.1
next prev parent reply other threads:[~2021-12-06 2:30 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-12-06 2:29 [PATCH v2 00/17] btrfs: split bio at btrfs_map_bio() time Qu Wenruo
2021-12-06 2:29 ` [PATCH v2 01/17] btrfs: update an stale comment on btrfs_submit_bio_hook() Qu Wenruo
2021-12-06 2:29 ` [PATCH v2 02/17] btrfs: save bio::bi_iter into btrfs_bio::iter before any endio Qu Wenruo
2021-12-06 2:29 ` [PATCH v2 03/17] btrfs: use correct bio size for error message in btrfs_end_dio_bio() Qu Wenruo
2021-12-06 2:29 ` [PATCH v2 04/17] btrfs: refactor btrfs_map_bio() Qu Wenruo
2021-12-06 2:29 ` [PATCH v2 05/17] btrfs: move btrfs_bio_wq_end_io() calls into submit_stripe_bio() Qu Wenruo
2021-12-06 2:29 ` [PATCH v2 06/17] btrfs: replace btrfs_dio_private::refs with btrfs_dio_private::pending_bytes Qu Wenruo
2021-12-09 10:02 ` Johannes Thumshirn
2021-12-09 10:35 ` Qu Wenruo
2021-12-06 2:29 ` [PATCH v2 07/17] btrfs: introduce btrfs_bio_split() helper Qu Wenruo
2021-12-06 2:29 ` [PATCH v2 08/17] btrfs: make data buffered read path to handle split bio properly Qu Wenruo
2021-12-06 2:29 ` [PATCH v2 09/17] btrfs: make data buffered write endio function to be split bio compatible Qu Wenruo
2021-12-06 2:29 ` [PATCH v2 10/17] btrfs: make metadata write endio functions " Qu Wenruo
2021-12-06 2:29 ` [PATCH v2 11/17] btrfs: make dec_and_test_compressed_bio() " Qu Wenruo
2021-12-06 2:29 ` Qu Wenruo [this message]
2021-12-06 2:29 ` [PATCH v2 13/17] btrfs: allow btrfs_map_bio() to split bio according to chunk stripe boundaries Qu Wenruo
2021-12-06 2:29 ` [PATCH v2 14/17] btrfs: remove buffered IO stripe boundary calculation Qu Wenruo
2021-12-06 2:29 ` [PATCH v2 15/17] btrfs: remove stripe boundary calculation for compressed IO Qu Wenruo
2021-12-06 2:29 ` [PATCH v2 16/17] btrfs: remove the stripe boundary calculation for direct IO Qu Wenruo
2021-12-06 2:29 ` [PATCH v2 17/17] btrfs: unexport btrfs_get_io_geometry() Qu Wenruo
2021-12-09 10:06 ` [PATCH v2 00/17] btrfs: split bio at btrfs_map_bio() time Johannes Thumshirn
2021-12-09 10:52 ` Johannes Thumshirn
2021-12-09 11:08 ` Qu Wenruo
2021-12-09 11:13 ` Johannes Thumshirn
2022-01-12 0:33 ` Qu Wenruo
2022-01-12 9:00 ` Johannes Thumshirn
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=20211206022937.26465-13-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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).