btrfs: move kmapping out of btrfs_check_sector_csum()
authorChristoph Hellwig <hch@lst.de>
Wed, 9 Apr 2025 11:10:38 +0000 (13:10 +0200)
committerDavid Sterba <dsterba@suse.com>
Thu, 15 May 2025 12:30:46 +0000 (14:30 +0200)
Move kmapping the page out of btrfs_check_sector_csum().

This allows using bvec_kmap_local() where suitable and reduces the number
of kmap*() calls in the raid56 code.

This also means btrfs_check_sector_csum() will only accept a properly
kmapped address.

Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/btrfs_inode.h
fs/btrfs/inode.c
fs/btrfs/raid56.c
fs/btrfs/scrub.c

index 4e2952cf5766edd66ab25d67c06a50da480f6a49..a5ebd2b9e2423ca396c537f28c6a2f5553cd368f 100644 (file)
@@ -529,8 +529,8 @@ static inline void btrfs_update_inode_mapping_flags(struct btrfs_inode *inode)
 #define CSUM_FMT                               "0x%*phN"
 #define CSUM_FMT_VALUE(size, bytes)            size, bytes
 
-int btrfs_check_sector_csum(struct btrfs_fs_info *fs_info, struct page *page,
-                           u32 pgoff, u8 *csum, const u8 * const csum_expected);
+int btrfs_check_sector_csum(struct btrfs_fs_info *fs_info, void *kaddr, u8 *csum,
+                           const u8 * const csum_expected);
 bool btrfs_data_csum_ok(struct btrfs_bio *bbio, struct btrfs_device *dev,
                        u32 bio_offset, struct bio_vec *bv);
 noinline int can_nocow_extent(struct btrfs_inode *inode, u64 offset, u64 *len,
index 71ae3cfcc9bed6d39badfa5a4a753567a567e925..e1c1ea41211e4580e98cf40bc021cd13a7a002ab 100644 (file)
@@ -3328,20 +3328,16 @@ int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered)
 /*
  * Verify the checksum for a single sector without any extra action that depend
  * on the type of I/O.
+ *
+ * @kaddr must be a properly kmapped address.
  */
-int btrfs_check_sector_csum(struct btrfs_fs_info *fs_info, struct page *page,
-                           u32 pgoff, u8 *csum, const u8 * const csum_expected)
+int btrfs_check_sector_csum(struct btrfs_fs_info *fs_info, void *kaddr, u8 *csum,
+                           const u8 * const csum_expected)
 {
        SHASH_DESC_ON_STACK(shash, fs_info->csum_shash);
-       char *kaddr;
-
-       ASSERT(pgoff + fs_info->sectorsize <= PAGE_SIZE);
 
        shash->tfm = fs_info->csum_shash;
-
-       kaddr = kmap_local_page(page) + pgoff;
        crypto_shash_digest(shash, kaddr, fs_info->sectorsize, csum);
-       kunmap_local(kaddr);
 
        if (memcmp(csum, csum_expected, fs_info->csum_size))
                return -EIO;
@@ -3370,6 +3366,7 @@ bool btrfs_data_csum_ok(struct btrfs_bio *bbio, struct btrfs_device *dev,
        u64 end = file_offset + bv->bv_len - 1;
        u8 *csum_expected;
        u8 csum[BTRFS_CSUM_SIZE];
+       void *kaddr;
 
        ASSERT(bv->bv_len == fs_info->sectorsize);
 
@@ -3387,9 +3384,12 @@ bool btrfs_data_csum_ok(struct btrfs_bio *bbio, struct btrfs_device *dev,
 
        csum_expected = bbio->csum + (bio_offset >> fs_info->sectorsize_bits) *
                                fs_info->csum_size;
-       if (btrfs_check_sector_csum(fs_info, bv->bv_page, bv->bv_offset, csum,
-                                   csum_expected))
+       kaddr = bvec_kmap_local(bv);
+       if (btrfs_check_sector_csum(fs_info, kaddr, csum, csum_expected)) {
+               kunmap_local(kaddr);
                goto zeroit;
+       }
+       kunmap_local(kaddr);
        return true;
 
 zeroit:
index cdd373c277848e418dead620f5be7515e354f521..bd6350e8f5c51e9a9105193bfb6275c2c43e6930 100644 (file)
@@ -1575,11 +1575,11 @@ static void verify_bio_data_sectors(struct btrfs_raid_bio *rbio,
                return;
 
        bio_for_each_segment_all(bvec, bio, iter_all) {
-               int bv_offset;
+               void *kaddr;
 
-               for (bv_offset = bvec->bv_offset;
-                    bv_offset < bvec->bv_offset + bvec->bv_len;
-                    bv_offset += fs_info->sectorsize, total_sector_nr++) {
+               kaddr = bvec_kmap_local(bvec);
+               for (u32 off = 0; off < bvec->bv_len;
+                    off += fs_info->sectorsize, total_sector_nr++) {
                        u8 csum_buf[BTRFS_CSUM_SIZE];
                        u8 *expected_csum = rbio->csum_buf +
                                            total_sector_nr * fs_info->csum_size;
@@ -1589,11 +1589,12 @@ static void verify_bio_data_sectors(struct btrfs_raid_bio *rbio,
                        if (!test_bit(total_sector_nr, rbio->csum_bitmap))
                                continue;
 
-                       ret = btrfs_check_sector_csum(fs_info, bvec->bv_page,
-                               bv_offset, csum_buf, expected_csum);
+                       ret = btrfs_check_sector_csum(fs_info, kaddr + off,
+                                                     csum_buf, expected_csum);
                        if (ret < 0)
                                set_bit(total_sector_nr, rbio->error_bitmap);
                }
+               kunmap_local(kaddr);
        }
 }
 
@@ -1791,6 +1792,7 @@ static int verify_one_sector(struct btrfs_raid_bio *rbio,
        struct sector_ptr *sector;
        u8 csum_buf[BTRFS_CSUM_SIZE];
        u8 *csum_expected;
+       void *kaddr;
        int ret;
 
        if (!rbio->csum_bitmap || !rbio->csum_buf)
@@ -1811,11 +1813,12 @@ static int verify_one_sector(struct btrfs_raid_bio *rbio,
 
        ASSERT(sector->page);
 
+       kaddr = kmap_local_page(sector->page) + sector->pgoff;
        csum_expected = rbio->csum_buf +
                        (stripe_nr * rbio->stripe_nsectors + sector_nr) *
                        fs_info->csum_size;
-       ret = btrfs_check_sector_csum(fs_info, sector->page, sector->pgoff,
-                                     csum_buf, csum_expected);
+       ret = btrfs_check_sector_csum(fs_info, kaddr, csum_buf, csum_expected);
+       kunmap_local(kaddr);
        return ret;
 }
 
index c3b2e29e3e019d7118dec237baf86c020b42694d..3794205a47a4e6beeb5610ec10e29ce6645df61e 100644 (file)
@@ -694,6 +694,7 @@ static void scrub_verify_one_sector(struct scrub_stripe *stripe, int sector_nr)
        struct page *page = scrub_stripe_get_page(stripe, sector_nr);
        unsigned int pgoff = scrub_stripe_get_page_offset(stripe, sector_nr);
        u8 csum_buf[BTRFS_CSUM_SIZE];
+       void *kaddr;
        int ret;
 
        ASSERT(sector_nr >= 0 && sector_nr < stripe->nr_sectors);
@@ -737,7 +738,9 @@ static void scrub_verify_one_sector(struct scrub_stripe *stripe, int sector_nr)
                return;
        }
 
-       ret = btrfs_check_sector_csum(fs_info, page, pgoff, csum_buf, sector->csum);
+       kaddr = kmap_local_page(page) + pgoff;
+       ret = btrfs_check_sector_csum(fs_info, kaddr, csum_buf, sector->csum);
+       kunmap_local(kaddr);
        if (ret < 0) {
                set_bit(sector_nr, &stripe->csum_error_bitmap);
                set_bit(sector_nr, &stripe->error_bitmap);