[PATCH v5 3/4] btrfs: scrub: implement calc_sector_number() in a faster way
Qu Wenruo <[email protected]>
| Newsgroups | org.kernel.vger.linux-btrfs |
|---|---|
| Message-ID | <b761a5ecf46388d29c3d4c1eee434bd1c9108dab.1783251701.git.wqu@suse.com> |
Currently calc_sector_number() is implemented by comparing the first
bvec of the bbio against all blocks inside a scrub_stripe.
This implementation is a little inefficient, and depends on how the
scrub buffer is implemented.
One of the reason implementing such complex function is that, we do not
save the original bvec_iter inside a write btrfs_bio.
Although a read bbio has btrfs_bio::saved_iter to get the original
logical bytenr, it's not implemented for write bios.
On the other hand, since commit 81cea6cd7041 ("btrfs: remove
btrfs_bio::fs_info by extracting it from btrfs_bio::inode"), we always
set the btrfs_bio::file_offset as the logical bytenr for scrub, and that
member will not be modified during IO.
So this means we have a stable way to determine the logical bytenr for a
scrub bio, now calc_sector_number() is just as simple as:
return (bbio->file_offset - stripe->logical) >> sectorsize_bits;
Since we're here, also add an ASSERT() to make sure the bbio is inside
the stripe, and change the return type to unsigned int to be extra safe.
Signed-off-by: Qu Wenruo <[email protected]>
---
fs/btrfs/scrub.c | 25 +++++++++++++------------
1 file changed, 13 insertions(+), 12 deletions(-)
diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c
index d95002edc20e..2224bca96a46 100644
--- a/fs/btrfs/scrub.c
+++ b/fs/btrfs/scrub.c
@@ -864,16 +864,19 @@ static void scrub_verify_one_stripe(struct scrub_stripe *stripe, unsigned long b
}
}
-static int calc_sector_number(struct scrub_stripe *stripe, struct bio_vec *first_bvec)
+static unsigned int calc_sector_number(const struct btrfs_bio *bbio)
{
- int i;
+ const struct scrub_stripe *stripe = bbio->private;
+ const struct btrfs_fs_info *fs_info = stripe->bg->fs_info;
- for (i = 0; i < stripe->nr_sectors; i++) {
- if (scrub_stripe_get_kaddr(stripe, i) == bvec_virt(first_bvec))
- break;
- }
- ASSERT(i < stripe->nr_sectors);
- return i;
+ /* Scrub bbios all have their @file_offset set to the logical bytenr. */
+ ASSERT(bbio->file_offset >= stripe->logical &&
+ bbio->file_offset < stripe->logical + (stripe->nr_sectors <<
+ fs_info->sectorsize_bits),
+ "scrub bio logical=%llu stripe logical=%llu stripe len=%u",
+ bbio->file_offset, stripe->logical,
+ stripe->nr_sectors << fs_info->sectorsize_bits);
+ return (bbio->file_offset - stripe->logical) >> fs_info->sectorsize_bits;
}
/*
@@ -885,12 +888,10 @@ static void scrub_read_endio_common(struct btrfs_bio *bbio)
{
struct scrub_stripe *stripe = bbio->private;
struct btrfs_fs_info *fs_info = stripe->bg->fs_info;
- int sector_nr = calc_sector_number(stripe, bio_first_bvec_all(&bbio->bio));
+ unsigned int sector_nr = calc_sector_number(bbio);
const u32 bio_size = bio_get_size(&bbio->bio);
const u32 sectors = bio_size >> fs_info->sectorsize_bits;
- ASSERT(sector_nr < stripe->nr_sectors);
-
if (bbio->bio.bi_status) {
scrub_bitmap_set_io_error(stripe, sector_nr, sectors);
scrub_bitmap_set_error(stripe, sector_nr, sectors);
@@ -1264,7 +1265,7 @@ static void scrub_write_endio(struct btrfs_bio *bbio)
{
struct scrub_stripe *stripe = bbio->private;
struct btrfs_fs_info *fs_info = stripe->bg->fs_info;
- int sector_nr = calc_sector_number(stripe, bio_first_bvec_all(&bbio->bio));
+ unsigned int sector_nr = calc_sector_number(bbio);
const u32 bio_size = bio_get_size(&bbio->bio);
if (bbio->bio.bi_status) {
--
2.54.0