btrfs: raid56: avoid double for loop inside finish_rmw()

We can easily calculate the stripe number and sector number inside the
stripe.  Thus there is not much need for a double for loop.

For the only case we want to skip the whole stripe, we can manually
increase @total_sector_nr.
This is not a recommended behavior, thus every time the iterator gets
modified there will be a comment along with an ASSERT() for it.

Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
Qu Wenruo 2022-06-02 15:51:18 +08:00 committed by David Sterba
parent f31f09f6be
commit 3692004465

View File

@ -1182,7 +1182,10 @@ static noinline void finish_rmw(struct btrfs_raid_bio *rbio)
const u32 sectorsize = bioc->fs_info->sectorsize;
void **pointers = rbio->finish_pointers;
int nr_data = rbio->nr_data;
/* The total sector number inside the full stripe. */
int total_sector_nr;
int stripe;
/* Sector number inside a stripe. */
int sectornr;
bool has_qstripe;
struct bio_list bio_list;
@ -1267,14 +1270,16 @@ static noinline void finish_rmw(struct btrfs_raid_bio *rbio)
}
/*
* time to start writing. Make bios for everything from the
* higher layers (the bio_list in our rbio) and our p/q. Ignore
* everything else.
* Start writing. Make bios for everything from the higher layers (the
* bio_list in our rbio) and our P/Q. Ignore everything else.
*/
for (stripe = 0; stripe < rbio->real_stripes; stripe++) {
for (sectornr = 0; sectornr < rbio->stripe_nsectors; sectornr++) {
for (total_sector_nr = 0; total_sector_nr < rbio->nr_sectors;
total_sector_nr++) {
struct sector_ptr *sector;
stripe = total_sector_nr / rbio->stripe_nsectors;
sectornr = total_sector_nr % rbio->stripe_nsectors;
/* This vertical stripe has no data, skip it. */
if (!test_bit(sectornr, &rbio->dbitmap))
continue;
@ -1293,18 +1298,27 @@ static noinline void finish_rmw(struct btrfs_raid_bio *rbio)
if (ret)
goto cleanup;
}
}
if (likely(!bioc->num_tgtdevs))
goto write_data;
for (stripe = 0; stripe < rbio->real_stripes; stripe++) {
if (!bioc->tgtdev_map[stripe])
continue;
for (sectornr = 0; sectornr < rbio->stripe_nsectors; sectornr++) {
for (total_sector_nr = 0; total_sector_nr < rbio->nr_sectors;
total_sector_nr++) {
struct sector_ptr *sector;
stripe = total_sector_nr / rbio->stripe_nsectors;
sectornr = total_sector_nr % rbio->stripe_nsectors;
if (!bioc->tgtdev_map[stripe]) {
/*
* We can skip the whole stripe completely, note
* total_sector_nr will be increased by one anyway.
*/
ASSERT(sectornr == 0);
total_sector_nr += rbio->stripe_nsectors - 1;
continue;
}
/* This vertical stripe has no data, skip it. */
if (!test_bit(sectornr, &rbio->dbitmap))
continue;
@ -1324,7 +1338,6 @@ static noinline void finish_rmw(struct btrfs_raid_bio *rbio)
if (ret)
goto cleanup;
}
}
write_data:
atomic_set(&rbio->stripes_pending, bio_list_size(&bio_list));