]> git.baikalelectronics.ru Git - kernel.git/commitdiff
btrfs: raid56: avoid double for loop inside finish_rmw()
authorQu Wenruo <wqu@suse.com>
Thu, 2 Jun 2022 07:51:18 +0000 (15:51 +0800)
committerDavid Sterba <dsterba@suse.com>
Mon, 25 Jul 2022 15:45:34 +0000 (17:45 +0200)
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>
fs/btrfs/raid56.c

index 3c58869779375b19411e5c5664d9bebd4ef7d01d..c63845c036dff1cd44a553f47514124e081335d8 100644 (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,63 +1270,73 @@ 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++) {
-                       struct sector_ptr *sector;
+       for (total_sector_nr = 0; total_sector_nr < rbio->nr_sectors;
+            total_sector_nr++) {
+               struct sector_ptr *sector;
 
-                       /* This vertical stripe has no data, skip it. */
-                       if (!test_bit(sectornr, &rbio->dbitmap))
-                               continue;
+               stripe = total_sector_nr / rbio->stripe_nsectors;
+               sectornr = total_sector_nr % rbio->stripe_nsectors;
 
-                       if (stripe < rbio->nr_data) {
-                               sector = sector_in_rbio(rbio, stripe, sectornr, 1);
-                               if (!sector)
-                                       continue;
-                       } else {
-                               sector = rbio_stripe_sector(rbio, stripe, sectornr);
-                       }
+               /* This vertical stripe has no data, skip it. */
+               if (!test_bit(sectornr, &rbio->dbitmap))
+                       continue;
 
-                       ret = rbio_add_io_sector(rbio, &bio_list, sector, stripe,
-                                                sectornr, rbio->stripe_len,
-                                                REQ_OP_WRITE);
-                       if (ret)
-                               goto cleanup;
+               if (stripe < rbio->nr_data) {
+                       sector = sector_in_rbio(rbio, stripe, sectornr, 1);
+                       if (!sector)
+                               continue;
+               } else {
+                       sector = rbio_stripe_sector(rbio, stripe, sectornr);
                }
+
+               ret = rbio_add_io_sector(rbio, &bio_list, sector, stripe,
+                                        sectornr, rbio->stripe_len,
+                                        REQ_OP_WRITE);
+               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 (total_sector_nr = 0; total_sector_nr < rbio->nr_sectors;
+            total_sector_nr++) {
+               struct sector_ptr *sector;
 
-               for (sectornr = 0; sectornr < rbio->stripe_nsectors; sectornr++) {
-                       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;
+               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;
+               }
 
-                       if (stripe < rbio->nr_data) {
-                               sector = sector_in_rbio(rbio, stripe, sectornr, 1);
-                               if (!sector)
-                                       continue;
-                       } else {
-                               sector = rbio_stripe_sector(rbio, stripe, sectornr);
-                       }
+               /* This vertical stripe has no data, skip it. */
+               if (!test_bit(sectornr, &rbio->dbitmap))
+                       continue;
 
-                       ret = rbio_add_io_sector(rbio, &bio_list, sector,
-                                              rbio->bioc->tgtdev_map[stripe],
-                                              sectornr, rbio->stripe_len,
-                                              REQ_OP_WRITE);
-                       if (ret)
-                               goto cleanup;
+               if (stripe < rbio->nr_data) {
+                       sector = sector_in_rbio(rbio, stripe, sectornr, 1);
+                       if (!sector)
+                               continue;
+               } else {
+                       sector = rbio_stripe_sector(rbio, stripe, sectornr);
                }
+
+               ret = rbio_add_io_sector(rbio, &bio_list, sector,
+                                        rbio->bioc->tgtdev_map[stripe],
+                                        sectornr, rbio->stripe_len,
+                                        REQ_OP_WRITE);
+               if (ret)
+                       goto cleanup;
        }
 
 write_data: