Skip to content

Commit d70cef0

Browse files
weiny2kdave
authored andcommitted
btrfs: fix raid6 qstripe kmap
When a qstripe is required an extra page is allocated and mapped. There were 3 problems: 1) There is no corresponding call of kunmap() for the qstripe page. 2) There is no reason to map the qstripe page more than once if the number of bits set in rbio->dbitmap is greater than one. 3) There is no reason to map the parity page and unmap it each time through the loop. The page memory can continue to be reused with a single mapping on each iteration by raid6_call.gen_syndrome() without remapping. So map the page for the duration of the loop. Similarly, improve the algorithm by mapping the parity page just 1 time. Fixes: 5a6ac9e ("Btrfs, raid56: support parity scrub on raid56") CC: stable@vger.kernel.org # 4.4.x: c17af96: btrfs: raid56: simplify tracking of Q stripe presence CC: stable@vger.kernel.org # 4.4.x Signed-off-by: Ira Weiny <ira.weiny@intel.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
1 parent 9d294a6 commit d70cef0

1 file changed

Lines changed: 10 additions & 11 deletions

File tree

fs/btrfs/raid56.c

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2362,16 +2362,21 @@ static noinline void finish_parity_scrub(struct btrfs_raid_bio *rbio,
23622362
SetPageUptodate(p_page);
23632363

23642364
if (has_qstripe) {
2365+
/* RAID6, allocate and map temp space for the Q stripe */
23652366
q_page = alloc_page(GFP_NOFS | __GFP_HIGHMEM);
23662367
if (!q_page) {
23672368
__free_page(p_page);
23682369
goto cleanup;
23692370
}
23702371
SetPageUptodate(q_page);
2372+
pointers[rbio->real_stripes - 1] = kmap(q_page);
23712373
}
23722374

23732375
atomic_set(&rbio->error, 0);
23742376

2377+
/* Map the parity stripe just once */
2378+
pointers[nr_data] = kmap(p_page);
2379+
23752380
for_each_set_bit(pagenr, rbio->dbitmap, rbio->stripe_npages) {
23762381
struct page *p;
23772382
void *parity;
@@ -2381,16 +2386,8 @@ static noinline void finish_parity_scrub(struct btrfs_raid_bio *rbio,
23812386
pointers[stripe] = kmap(p);
23822387
}
23832388

2384-
/* then add the parity stripe */
2385-
pointers[stripe++] = kmap(p_page);
2386-
23872389
if (has_qstripe) {
2388-
/*
2389-
* raid6, add the qstripe and call the
2390-
* library function to fill in our p/q
2391-
*/
2392-
pointers[stripe++] = kmap(q_page);
2393-
2390+
/* RAID6, call the library function to fill in our P/Q */
23942391
raid6_call.gen_syndrome(rbio->real_stripes, PAGE_SIZE,
23952392
pointers);
23962393
} else {
@@ -2411,12 +2408,14 @@ static noinline void finish_parity_scrub(struct btrfs_raid_bio *rbio,
24112408

24122409
for (stripe = 0; stripe < nr_data; stripe++)
24132410
kunmap(page_in_rbio(rbio, stripe, pagenr, 0));
2414-
kunmap(p_page);
24152411
}
24162412

2413+
kunmap(p_page);
24172414
__free_page(p_page);
2418-
if (q_page)
2415+
if (q_page) {
2416+
kunmap(q_page);
24192417
__free_page(q_page);
2418+
}
24202419

24212420
writeback:
24222421
/*

0 commit comments

Comments
 (0)