Skip to content

Commit 826325b

Browse files
adam900710kdave
authored andcommitted
btrfs: raid56: prepare generate_pq_vertical() for bs > ps cases
Unlike btrfs_calculate_block_csum_pages(), we cannot handle multiple pages at the same time for P/Q generation. So here we introduce a new @step_nr, and various helpers to grab the sub-block page from the rbio, and generate the P/Q stripe page by page. Signed-off-by: Qu Wenruo <wqu@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
1 parent 91cd1b5 commit 826325b

1 file changed

Lines changed: 70 additions & 22 deletions

File tree

fs/btrfs/raid56.c

Lines changed: 70 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -711,20 +711,25 @@ static phys_addr_t rbio_stripe_paddr(const struct btrfs_raid_bio *rbio,
711711
return rbio->stripe_paddrs[rbio_paddr_index(rbio, stripe_nr, sector_nr, 0)];
712712
}
713713

714-
/* Grab a paddr inside P stripe */
715-
static phys_addr_t rbio_pstripe_paddr(const struct btrfs_raid_bio *rbio,
716-
unsigned int sector_nr)
714+
static phys_addr_t rbio_stripe_step_paddr(const struct btrfs_raid_bio *rbio,
715+
unsigned int stripe_nr, unsigned int sector_nr,
716+
unsigned int step_nr)
717717
{
718-
return rbio_stripe_paddr(rbio, rbio->nr_data, sector_nr);
718+
return rbio->stripe_paddrs[rbio_paddr_index(rbio, stripe_nr, sector_nr, step_nr)];
719719
}
720720

721-
/* Grab a paddr inside Q stripe, return INVALID_PADDR if not RAID6 */
722-
static phys_addr_t rbio_qstripe_paddr(const struct btrfs_raid_bio *rbio,
723-
unsigned int sector_nr)
721+
static phys_addr_t rbio_pstripe_step_paddr(const struct btrfs_raid_bio *rbio,
722+
unsigned int sector_nr, unsigned int step_nr)
723+
{
724+
return rbio_stripe_step_paddr(rbio, rbio->nr_data, sector_nr, step_nr);
725+
}
726+
727+
static phys_addr_t rbio_qstripe_step_paddr(const struct btrfs_raid_bio *rbio,
728+
unsigned int sector_nr, unsigned int step_nr)
724729
{
725730
if (rbio->nr_data + 1 == rbio->real_stripes)
726731
return INVALID_PADDR;
727-
return rbio_stripe_paddr(rbio, rbio->nr_data + 1, sector_nr);
732+
return rbio_stripe_step_paddr(rbio, rbio->nr_data + 1, sector_nr, step_nr);
728733
}
729734

730735
/*
@@ -998,6 +1003,38 @@ static phys_addr_t sector_paddr_in_rbio(struct btrfs_raid_bio *rbio,
9981003
return rbio->stripe_paddrs[index];
9991004
}
10001005

1006+
/*
1007+
* Similar to sector_paddr_in_rbio(), but with extra consideration for
1008+
* bs > ps cases, where we can have multiple steps for a fs block.
1009+
*/
1010+
static phys_addr_t step_paddr_in_rbio(struct btrfs_raid_bio *rbio,
1011+
int stripe_nr, int sector_nr, int step_nr,
1012+
bool bio_list_only)
1013+
{
1014+
phys_addr_t ret = INVALID_PADDR;
1015+
int index;
1016+
1017+
ASSERT_RBIO_STRIPE(stripe_nr >= 0 && stripe_nr < rbio->real_stripes,
1018+
rbio, stripe_nr);
1019+
ASSERT_RBIO_SECTOR(sector_nr >= 0 && sector_nr < rbio->stripe_nsectors,
1020+
rbio, sector_nr);
1021+
ASSERT_RBIO_SECTOR(step_nr >= 0 && step_nr < rbio->sector_nsteps,
1022+
rbio, sector_nr);
1023+
1024+
index = (stripe_nr * rbio->stripe_nsectors + sector_nr) * rbio->sector_nsteps + step_nr;
1025+
ASSERT(index >= 0 && index < rbio->nr_sectors * rbio->sector_nsteps);
1026+
1027+
scoped_guard(spinlock, &rbio->bio_list_lock) {
1028+
if (rbio->bio_paddrs[index] != INVALID_PADDR || bio_list_only) {
1029+
/* Don't return sector without a valid page pointer */
1030+
if (rbio->bio_paddrs[index] != INVALID_PADDR)
1031+
ret = rbio->bio_paddrs[index];
1032+
return ret;
1033+
}
1034+
}
1035+
return rbio->stripe_paddrs[index];
1036+
}
1037+
10011038
/*
10021039
* allocation and initial setup for the btrfs_raid_bio. Not
10031040
* this does not allocate any pages for rbio->pages.
@@ -1319,45 +1356,56 @@ static inline void *kmap_local_paddr(phys_addr_t paddr)
13191356
return kmap_local_page(phys_to_page(paddr)) + offset_in_page(paddr);
13201357
}
13211358

1322-
/* Generate PQ for one vertical stripe. */
1323-
static void generate_pq_vertical(struct btrfs_raid_bio *rbio, int sectornr)
1359+
static void generate_pq_vertical_step(struct btrfs_raid_bio *rbio, unsigned int sector_nr,
1360+
unsigned int step_nr)
13241361
{
13251362
void **pointers = rbio->finish_pointers;
1326-
const u32 sectorsize = rbio->bioc->fs_info->sectorsize;
1363+
const u32 step = min(rbio->bioc->fs_info->sectorsize, PAGE_SIZE);
13271364
int stripe;
13281365
const bool has_qstripe = rbio->bioc->map_type & BTRFS_BLOCK_GROUP_RAID6;
13291366

13301367
/* First collect one sector from each data stripe */
13311368
for (stripe = 0; stripe < rbio->nr_data; stripe++)
13321369
pointers[stripe] = kmap_local_paddr(
1333-
sector_paddr_in_rbio(rbio, stripe, sectornr, 0));
1370+
step_paddr_in_rbio(rbio, stripe, sector_nr, step_nr, 0));
13341371

13351372
/* Then add the parity stripe */
1336-
set_bit(rbio_sector_index(rbio, rbio->nr_data, sectornr),
1337-
rbio->stripe_uptodate_bitmap);
1338-
pointers[stripe++] = kmap_local_paddr(rbio_pstripe_paddr(rbio, sectornr));
1373+
pointers[stripe++] = kmap_local_paddr(rbio_pstripe_step_paddr(rbio, sector_nr, step_nr));
13391374

13401375
if (has_qstripe) {
13411376
/*
13421377
* RAID6, add the qstripe and call the library function
13431378
* to fill in our p/q
13441379
*/
1345-
set_bit(rbio_sector_index(rbio, rbio->nr_data + 1, sectornr),
1346-
rbio->stripe_uptodate_bitmap);
1347-
pointers[stripe++] = kmap_local_paddr(rbio_qstripe_paddr(rbio, sectornr));
1380+
pointers[stripe++] = kmap_local_paddr(
1381+
rbio_qstripe_step_paddr(rbio, sector_nr, step_nr));
13481382

13491383
assert_rbio(rbio);
1350-
raid6_call.gen_syndrome(rbio->real_stripes, sectorsize,
1351-
pointers);
1384+
raid6_call.gen_syndrome(rbio->real_stripes, step, pointers);
13521385
} else {
13531386
/* raid5 */
1354-
memcpy(pointers[rbio->nr_data], pointers[0], sectorsize);
1355-
run_xor(pointers + 1, rbio->nr_data - 1, sectorsize);
1387+
memcpy(pointers[rbio->nr_data], pointers[0], step);
1388+
run_xor(pointers + 1, rbio->nr_data - 1, step);
13561389
}
13571390
for (stripe = stripe - 1; stripe >= 0; stripe--)
13581391
kunmap_local(pointers[stripe]);
13591392
}
13601393

1394+
/* Generate PQ for one vertical stripe. */
1395+
static void generate_pq_vertical(struct btrfs_raid_bio *rbio, int sectornr)
1396+
{
1397+
const bool has_qstripe = (rbio->bioc->map_type & BTRFS_BLOCK_GROUP_RAID6);
1398+
1399+
for (int i = 0; i < rbio->sector_nsteps; i++)
1400+
generate_pq_vertical_step(rbio, sectornr, i);
1401+
1402+
set_bit(rbio_sector_index(rbio, rbio->nr_data, sectornr),
1403+
rbio->stripe_uptodate_bitmap);
1404+
if (has_qstripe)
1405+
set_bit(rbio_sector_index(rbio, rbio->nr_data + 1, sectornr),
1406+
rbio->stripe_uptodate_bitmap);
1407+
}
1408+
13611409
static int rmw_assemble_write_bios(struct btrfs_raid_bio *rbio,
13621410
struct bio_list *bio_list)
13631411
{

0 commit comments

Comments
 (0)