]> git.baikalelectronics.ru Git - kernel.git/commitdiff
btrfs: raid56: make __raid_recover_endio_io() subpage compatible
authorQu Wenruo <wqu@suse.com>
Fri, 1 Apr 2022 11:23:23 +0000 (19:23 +0800)
committerDavid Sterba <dsterba@suse.com>
Mon, 16 May 2022 15:03:15 +0000 (17:03 +0200)
This involves:

- Use sector_ptr interface to grab the pointers

- Add sector->pgoff to pointers[]

- Rebuild data using sectorsize instead of PAGE_SIZE

- Use memcpy() to replace copy_page()

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 93e4a0ffbf7b1a2b9b1c86d5372dd17ede22fb86..0b446bdd92c521c18855cf64031ccd218bb951f1 100644 (file)
@@ -1932,14 +1932,18 @@ int raid56_parity_write(struct bio *bio, struct btrfs_io_context *bioc, u32 stri
  */
 static void __raid_recover_end_io(struct btrfs_raid_bio *rbio)
 {
-       int pagenr, stripe;
+       const u32 sectorsize = rbio->bioc->fs_info->sectorsize;
+       int sectornr, stripe;
        void **pointers;
        void **unmap_array;
        int faila = -1, failb = -1;
-       struct page *page;
        blk_status_t err;
        int i;
 
+       /*
+        * This array stores the pointer for each sector, thus it has the extra
+        * pgoff value added from each sector
+        */
        pointers = kcalloc(rbio->real_stripes, sizeof(void *), GFP_NOFS);
        if (!pointers) {
                err = BLK_STS_RESOURCE;
@@ -1968,43 +1972,44 @@ static void __raid_recover_end_io(struct btrfs_raid_bio *rbio)
 
        index_rbio_pages(rbio);
 
-       for (pagenr = 0; pagenr < rbio->stripe_npages; pagenr++) {
+       for (sectornr = 0; sectornr < rbio->stripe_nsectors; sectornr++) {
+               struct sector_ptr *sector;
+
                /*
                 * Now we just use bitmap to mark the horizontal stripes in
                 * which we have data when doing parity scrub.
                 */
                if (rbio->operation == BTRFS_RBIO_PARITY_SCRUB &&
-                   !test_bit(pagenr, rbio->dbitmap))
+                   !test_bit(sectornr, rbio->dbitmap))
                        continue;
 
                /*
-                * Setup our array of pointers with pages from each stripe
+                * Setup our array of pointers with sectors from each stripe
                 *
                 * NOTE: store a duplicate array of pointers to preserve the
                 * pointer order
                 */
                for (stripe = 0; stripe < rbio->real_stripes; stripe++) {
                        /*
-                        * if we're rebuilding a read, we have to use
+                        * If we're rebuilding a read, we have to use
                         * pages from the bio list
                         */
                        if ((rbio->operation == BTRFS_RBIO_READ_REBUILD ||
                             rbio->operation == BTRFS_RBIO_REBUILD_MISSING) &&
                            (stripe == faila || stripe == failb)) {
-                               page = page_in_rbio(rbio, stripe, pagenr, 0);
+                               sector = sector_in_rbio(rbio, stripe, sectornr, 0);
                        } else {
-                               page = rbio_stripe_page(rbio, stripe, pagenr);
+                               sector = rbio_stripe_sector(rbio, stripe, sectornr);
                        }
-                       pointers[stripe] = kmap_local_page(page);
+                       ASSERT(sector->page);
+                       pointers[stripe] = kmap_local_page(sector->page) +
+                                          sector->pgoff;
                        unmap_array[stripe] = pointers[stripe];
                }
 
-               /* all raid6 handling here */
+               /* All raid6 handling here */
                if (rbio->bioc->map_type & BTRFS_BLOCK_GROUP_RAID6) {
-                       /*
-                        * single failure, rebuild from parity raid5
-                        * style
-                        */
+                       /* Single failure, rebuild from parity raid5 style */
                        if (failb < 0) {
                                if (faila == rbio->nr_data) {
                                        /*
@@ -2047,10 +2052,10 @@ static void __raid_recover_end_io(struct btrfs_raid_bio *rbio)
 
                        if (rbio->bioc->raid_map[failb] == RAID5_P_STRIPE) {
                                raid6_datap_recov(rbio->real_stripes,
-                                                 PAGE_SIZE, faila, pointers);
+                                                 sectorsize, faila, pointers);
                        } else {
                                raid6_2data_recov(rbio->real_stripes,
-                                                 PAGE_SIZE, faila, failb,
+                                                 sectorsize, faila, failb,
                                                  pointers);
                        }
                } else {
@@ -2060,7 +2065,7 @@ static void __raid_recover_end_io(struct btrfs_raid_bio *rbio)
                        BUG_ON(failb != -1);
 pstripe:
                        /* Copy parity block into failed block to start with */
-                       copy_page(pointers[faila], pointers[rbio->nr_data]);
+                       memcpy(pointers[faila], pointers[rbio->nr_data], sectorsize);
 
                        /* rearrange the pointer array */
                        p = pointers[faila];
@@ -2069,7 +2074,7 @@ pstripe:
                        pointers[rbio->nr_data - 1] = p;
 
                        /* xor in the rest */
-                       run_xor(pointers, rbio->nr_data - 1, PAGE_SIZE);
+                       run_xor(pointers, rbio->nr_data - 1, sectorsize);
                }
                /* if we're doing this rebuild as part of an rmw, go through
                 * and set all of our private rbio pages in the
@@ -2078,14 +2083,14 @@ pstripe:
                 * other endio functions will fiddle the uptodate bits
                 */
                if (rbio->operation == BTRFS_RBIO_WRITE) {
-                       for (i = 0;  i < rbio->stripe_npages; i++) {
+                       for (i = 0;  i < rbio->stripe_nsectors; i++) {
                                if (faila != -1) {
-                                       page = rbio_stripe_page(rbio, faila, i);
-                                       SetPageUptodate(page);
+                                       sector = rbio_stripe_sector(rbio, faila, i);
+                                       sector->uptodate = 1;
                                }
                                if (failb != -1) {
-                                       page = rbio_stripe_page(rbio, failb, i);
-                                       SetPageUptodate(page);
+                                       sector = rbio_stripe_sector(rbio, failb, i);
+                                       sector->uptodate = 1;
                                }
                        }
                }