Commit 36920044 authored by Qu Wenruo's avatar Qu Wenruo Committed by David Sterba
Browse files

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: default avatarQu Wenruo <wqu@suse.com>
Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent f31f09f6
Loading
Loading
Loading
Loading
+55 −42
Original line number Diff line number Diff line
@@ -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));