@@ -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+
13611409static int rmw_assemble_write_bios (struct btrfs_raid_bio * rbio ,
13621410 struct bio_list * bio_list )
13631411{
0 commit comments