Skip to content

Commit e0eadfc

Browse files
adam900710kdave
authored andcommitted
btrfs: raid56: prepare verify_one_sector() to support bs > ps cases
The function verify_one_sector() assume each fs block can be mapped by one page, blocking bs > ps support for raid56. Prepare it for bs > ps cases by: - Introduce helpers to get a paddrs pointer Thankfully all the higher layer bio should still be aligned to fs block size, thus a fs block should still be fully covered by the bio. Introduce sector_paddrs_in_rbio() and rbio_stripe_paddrs(), which will return a paddrs pointer inside btrfs_raid_bio::bio_paddrs[] or stripe_paddrs[]. The pointer can be directly passed to btrfs_calculate_block_csum_pages() to verify the checksum. - Open code btrfs_check_block_csum() btrfs_check_block_csum() only supports fs blocks backed by large folios. But for raid56 we can have fs blocks backed by multiple non-contiguous pages, e.g. direct IO, encoded read/write/send. So instead of using btrfs_check_block_csum(), open code it to use btrfs_calculate_block_csum_pages(). Signed-off-by: Qu Wenruo <wqu@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
1 parent 9ba67fd commit e0eadfc

1 file changed

Lines changed: 49 additions & 6 deletions

File tree

fs/btrfs/raid56.c

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -732,6 +732,13 @@ static phys_addr_t rbio_qstripe_step_paddr(const struct btrfs_raid_bio *rbio,
732732
return rbio_stripe_step_paddr(rbio, rbio->nr_data + 1, sector_nr, step_nr);
733733
}
734734

735+
/* Return a paddr pointer into the rbio::stripe_paddrs[] for the specified sector. */
736+
static phys_addr_t *rbio_stripe_paddrs(const struct btrfs_raid_bio *rbio,
737+
unsigned int stripe_nr, unsigned int sector_nr)
738+
{
739+
return &rbio->stripe_paddrs[rbio_paddr_index(rbio, stripe_nr, sector_nr, 0)];
740+
}
741+
735742
/*
736743
* The first stripe in the table for a logical address
737744
* has the lock. rbios are added in one of three ways:
@@ -1003,6 +1010,41 @@ static phys_addr_t sector_paddr_in_rbio(struct btrfs_raid_bio *rbio,
10031010
return rbio->stripe_paddrs[index];
10041011
}
10051012

1013+
/*
1014+
* Get paddr pointer for the sector specified by its @stripe_nr and @sector_nr.
1015+
*
1016+
* @rbio: The raid bio
1017+
* @stripe_nr: Stripe number, valid range [0, real_stripe)
1018+
* @sector_nr: Sector number inside the stripe,
1019+
* valid range [0, stripe_nsectors)
1020+
* @bio_list_only: Whether to use sectors inside the bio list only.
1021+
*
1022+
* The read/modify/write code wants to reuse the original bio page as much
1023+
* as possible, and only use stripe_sectors as fallback.
1024+
*
1025+
* Return NULL if bio_list_only is set but the specified sector has no
1026+
* coresponding bio.
1027+
*/
1028+
static phys_addr_t *sector_paddrs_in_rbio(struct btrfs_raid_bio *rbio,
1029+
int stripe_nr, int sector_nr,
1030+
bool bio_list_only)
1031+
{
1032+
phys_addr_t *ret = NULL;
1033+
const int index = rbio_paddr_index(rbio, stripe_nr, sector_nr, 0);
1034+
1035+
ASSERT(index >= 0 && index < rbio->nr_sectors * rbio->sector_nsteps);
1036+
1037+
scoped_guard(spinlock, &rbio->bio_list_lock) {
1038+
if (rbio->bio_paddrs[index] != INVALID_PADDR || bio_list_only) {
1039+
/* Don't return sector without a valid page pointer */
1040+
if (rbio->bio_paddrs[index] != INVALID_PADDR)
1041+
ret = &rbio->bio_paddrs[index];
1042+
return ret;
1043+
}
1044+
}
1045+
return &rbio->stripe_paddrs[index];
1046+
}
1047+
10061048
/*
10071049
* Similar to sector_paddr_in_rbio(), but with extra consideration for
10081050
* bs > ps cases, where we can have multiple steps for a fs block.
@@ -1832,10 +1874,9 @@ static int verify_one_sector(struct btrfs_raid_bio *rbio,
18321874
int stripe_nr, int sector_nr)
18331875
{
18341876
struct btrfs_fs_info *fs_info = rbio->bioc->fs_info;
1835-
phys_addr_t paddr;
1877+
phys_addr_t *paddrs;
18361878
u8 csum_buf[BTRFS_CSUM_SIZE];
18371879
u8 *csum_expected;
1838-
int ret;
18391880

18401881
if (!rbio->csum_bitmap || !rbio->csum_buf)
18411882
return 0;
@@ -1848,16 +1889,18 @@ static int verify_one_sector(struct btrfs_raid_bio *rbio,
18481889
* bio list if possible.
18491890
*/
18501891
if (rbio->operation == BTRFS_RBIO_READ_REBUILD) {
1851-
paddr = sector_paddr_in_rbio(rbio, stripe_nr, sector_nr, 0);
1892+
paddrs = sector_paddrs_in_rbio(rbio, stripe_nr, sector_nr, 0);
18521893
} else {
1853-
paddr = rbio_stripe_paddr(rbio, stripe_nr, sector_nr);
1894+
paddrs = rbio_stripe_paddrs(rbio, stripe_nr, sector_nr);
18541895
}
18551896

18561897
csum_expected = rbio->csum_buf +
18571898
(stripe_nr * rbio->stripe_nsectors + sector_nr) *
18581899
fs_info->csum_size;
1859-
ret = btrfs_check_block_csum(fs_info, paddr, csum_buf, csum_expected);
1860-
return ret;
1900+
btrfs_calculate_block_csum_pages(fs_info, paddrs, csum_buf);
1901+
if (unlikely(memcmp(csum_buf, csum_expected, fs_info->csum_size) != 0))
1902+
return -EIO;
1903+
return 0;
18611904
}
18621905

18631906
static void recover_vertical_step(struct btrfs_raid_bio *rbio,

0 commit comments

Comments
 (0)