mirror of
https://github.com/torvalds/linux.git
synced 2026-05-31 02:24:24 +02:00
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>
This commit is contained in:
parent
91cd1b5865
commit
826325b6d0
|
|
@ -711,20 +711,25 @@ static phys_addr_t rbio_stripe_paddr(const struct btrfs_raid_bio *rbio,
|
|||
return rbio->stripe_paddrs[rbio_paddr_index(rbio, stripe_nr, sector_nr, 0)];
|
||||
}
|
||||
|
||||
/* Grab a paddr inside P stripe */
|
||||
static phys_addr_t rbio_pstripe_paddr(const struct btrfs_raid_bio *rbio,
|
||||
unsigned int sector_nr)
|
||||
static phys_addr_t rbio_stripe_step_paddr(const struct btrfs_raid_bio *rbio,
|
||||
unsigned int stripe_nr, unsigned int sector_nr,
|
||||
unsigned int step_nr)
|
||||
{
|
||||
return rbio_stripe_paddr(rbio, rbio->nr_data, sector_nr);
|
||||
return rbio->stripe_paddrs[rbio_paddr_index(rbio, stripe_nr, sector_nr, step_nr)];
|
||||
}
|
||||
|
||||
/* Grab a paddr inside Q stripe, return INVALID_PADDR if not RAID6 */
|
||||
static phys_addr_t rbio_qstripe_paddr(const struct btrfs_raid_bio *rbio,
|
||||
unsigned int sector_nr)
|
||||
static phys_addr_t rbio_pstripe_step_paddr(const struct btrfs_raid_bio *rbio,
|
||||
unsigned int sector_nr, unsigned int step_nr)
|
||||
{
|
||||
return rbio_stripe_step_paddr(rbio, rbio->nr_data, sector_nr, step_nr);
|
||||
}
|
||||
|
||||
static phys_addr_t rbio_qstripe_step_paddr(const struct btrfs_raid_bio *rbio,
|
||||
unsigned int sector_nr, unsigned int step_nr)
|
||||
{
|
||||
if (rbio->nr_data + 1 == rbio->real_stripes)
|
||||
return INVALID_PADDR;
|
||||
return rbio_stripe_paddr(rbio, rbio->nr_data + 1, sector_nr);
|
||||
return rbio_stripe_step_paddr(rbio, rbio->nr_data + 1, sector_nr, step_nr);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -998,6 +1003,38 @@ static phys_addr_t sector_paddr_in_rbio(struct btrfs_raid_bio *rbio,
|
|||
return rbio->stripe_paddrs[index];
|
||||
}
|
||||
|
||||
/*
|
||||
* Similar to sector_paddr_in_rbio(), but with extra consideration for
|
||||
* bs > ps cases, where we can have multiple steps for a fs block.
|
||||
*/
|
||||
static phys_addr_t step_paddr_in_rbio(struct btrfs_raid_bio *rbio,
|
||||
int stripe_nr, int sector_nr, int step_nr,
|
||||
bool bio_list_only)
|
||||
{
|
||||
phys_addr_t ret = INVALID_PADDR;
|
||||
int index;
|
||||
|
||||
ASSERT_RBIO_STRIPE(stripe_nr >= 0 && stripe_nr < rbio->real_stripes,
|
||||
rbio, stripe_nr);
|
||||
ASSERT_RBIO_SECTOR(sector_nr >= 0 && sector_nr < rbio->stripe_nsectors,
|
||||
rbio, sector_nr);
|
||||
ASSERT_RBIO_SECTOR(step_nr >= 0 && step_nr < rbio->sector_nsteps,
|
||||
rbio, sector_nr);
|
||||
|
||||
index = (stripe_nr * rbio->stripe_nsectors + sector_nr) * rbio->sector_nsteps + step_nr;
|
||||
ASSERT(index >= 0 && index < rbio->nr_sectors * rbio->sector_nsteps);
|
||||
|
||||
scoped_guard(spinlock, &rbio->bio_list_lock) {
|
||||
if (rbio->bio_paddrs[index] != INVALID_PADDR || bio_list_only) {
|
||||
/* Don't return sector without a valid page pointer */
|
||||
if (rbio->bio_paddrs[index] != INVALID_PADDR)
|
||||
ret = rbio->bio_paddrs[index];
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return rbio->stripe_paddrs[index];
|
||||
}
|
||||
|
||||
/*
|
||||
* allocation and initial setup for the btrfs_raid_bio. Not
|
||||
* this does not allocate any pages for rbio->pages.
|
||||
|
|
@ -1319,45 +1356,56 @@ static inline void *kmap_local_paddr(phys_addr_t paddr)
|
|||
return kmap_local_page(phys_to_page(paddr)) + offset_in_page(paddr);
|
||||
}
|
||||
|
||||
/* Generate PQ for one vertical stripe. */
|
||||
static void generate_pq_vertical(struct btrfs_raid_bio *rbio, int sectornr)
|
||||
static void generate_pq_vertical_step(struct btrfs_raid_bio *rbio, unsigned int sector_nr,
|
||||
unsigned int step_nr)
|
||||
{
|
||||
void **pointers = rbio->finish_pointers;
|
||||
const u32 sectorsize = rbio->bioc->fs_info->sectorsize;
|
||||
const u32 step = min(rbio->bioc->fs_info->sectorsize, PAGE_SIZE);
|
||||
int stripe;
|
||||
const bool has_qstripe = rbio->bioc->map_type & BTRFS_BLOCK_GROUP_RAID6;
|
||||
|
||||
/* First collect one sector from each data stripe */
|
||||
for (stripe = 0; stripe < rbio->nr_data; stripe++)
|
||||
pointers[stripe] = kmap_local_paddr(
|
||||
sector_paddr_in_rbio(rbio, stripe, sectornr, 0));
|
||||
step_paddr_in_rbio(rbio, stripe, sector_nr, step_nr, 0));
|
||||
|
||||
/* Then add the parity stripe */
|
||||
set_bit(rbio_sector_index(rbio, rbio->nr_data, sectornr),
|
||||
rbio->stripe_uptodate_bitmap);
|
||||
pointers[stripe++] = kmap_local_paddr(rbio_pstripe_paddr(rbio, sectornr));
|
||||
pointers[stripe++] = kmap_local_paddr(rbio_pstripe_step_paddr(rbio, sector_nr, step_nr));
|
||||
|
||||
if (has_qstripe) {
|
||||
/*
|
||||
* RAID6, add the qstripe and call the library function
|
||||
* to fill in our p/q
|
||||
*/
|
||||
set_bit(rbio_sector_index(rbio, rbio->nr_data + 1, sectornr),
|
||||
rbio->stripe_uptodate_bitmap);
|
||||
pointers[stripe++] = kmap_local_paddr(rbio_qstripe_paddr(rbio, sectornr));
|
||||
pointers[stripe++] = kmap_local_paddr(
|
||||
rbio_qstripe_step_paddr(rbio, sector_nr, step_nr));
|
||||
|
||||
assert_rbio(rbio);
|
||||
raid6_call.gen_syndrome(rbio->real_stripes, sectorsize,
|
||||
pointers);
|
||||
raid6_call.gen_syndrome(rbio->real_stripes, step, pointers);
|
||||
} else {
|
||||
/* raid5 */
|
||||
memcpy(pointers[rbio->nr_data], pointers[0], sectorsize);
|
||||
run_xor(pointers + 1, rbio->nr_data - 1, sectorsize);
|
||||
memcpy(pointers[rbio->nr_data], pointers[0], step);
|
||||
run_xor(pointers + 1, rbio->nr_data - 1, step);
|
||||
}
|
||||
for (stripe = stripe - 1; stripe >= 0; stripe--)
|
||||
kunmap_local(pointers[stripe]);
|
||||
}
|
||||
|
||||
/* Generate PQ for one vertical stripe. */
|
||||
static void generate_pq_vertical(struct btrfs_raid_bio *rbio, int sectornr)
|
||||
{
|
||||
const bool has_qstripe = (rbio->bioc->map_type & BTRFS_BLOCK_GROUP_RAID6);
|
||||
|
||||
for (int i = 0; i < rbio->sector_nsteps; i++)
|
||||
generate_pq_vertical_step(rbio, sectornr, i);
|
||||
|
||||
set_bit(rbio_sector_index(rbio, rbio->nr_data, sectornr),
|
||||
rbio->stripe_uptodate_bitmap);
|
||||
if (has_qstripe)
|
||||
set_bit(rbio_sector_index(rbio, rbio->nr_data + 1, sectornr),
|
||||
rbio->stripe_uptodate_bitmap);
|
||||
}
|
||||
|
||||
static int rmw_assemble_write_bios(struct btrfs_raid_bio *rbio,
|
||||
struct bio_list *bio_list)
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user