Skip to content

Commit 60d7ebc

Browse files
adam900710kdave
authored andcommitted
btrfs: prepare scrub to support bs > ps cases
This involves: - Migrate scrub_stripe::pages[] to folios[] - Use btrfs_alloc_folio_array() and folio_put() to alloc above array. - Migrate scrub_stripe_get_kaddr() and scrub_stripe_get_paddr() to use folio interfaces - Migrate raid56_parity_cache_data_pages() to raid56_parity_cache_data_folios() Since scrub is the only caller still using pages. This helper will copy the folio array contents into rbio::stripe_pages, with sector uptodate flags updated. And a new ASSERT() to make sure bs > ps cases will not hit this path. Since most scrub code is based on kaddr/paddr, the migration itself is pretty straightforward. And since we're here, also move the loop to set the stripe_sectors[].uptodate out of the copy loop. As we always mark all the sectors as uptodate for the data stripe, it's easier to do in one go, other than doing it inside the copy loop. Signed-off-by: Qu Wenruo <wqu@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
1 parent e8c0bab commit 60d7ebc

File tree

3 files changed

+60
-39
lines changed

3 files changed

+60
-39
lines changed

fs/btrfs/raid56.c

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2844,19 +2844,22 @@ void raid56_parity_submit_scrub_rbio(struct btrfs_raid_bio *rbio)
28442844
* This is for scrub call sites where we already have correct data contents.
28452845
* This allows us to avoid reading data stripes again.
28462846
*
2847-
* Unfortunately here we have to do page copy, other than reusing the pages.
2847+
* Unfortunately here we have to do folio copy, other than reusing the pages.
28482848
* This is due to the fact rbio has its own page management for its cache.
28492849
*/
2850-
void raid56_parity_cache_data_pages(struct btrfs_raid_bio *rbio,
2851-
struct page **data_pages, u64 data_logical)
2850+
void raid56_parity_cache_data_folios(struct btrfs_raid_bio *rbio,
2851+
struct folio **data_folios, u64 data_logical)
28522852
{
2853+
struct btrfs_fs_info *fs_info = rbio->bioc->fs_info;
28532854
const u64 offset_in_full_stripe = data_logical -
28542855
rbio->bioc->full_stripe_logical;
2855-
const int page_index = offset_in_full_stripe >> PAGE_SHIFT;
2856-
const u32 sectorsize = rbio->bioc->fs_info->sectorsize;
2857-
const u32 sectors_per_page = PAGE_SIZE / sectorsize;
2856+
unsigned int findex = 0;
2857+
unsigned int foffset = 0;
28582858
int ret;
28592859

2860+
/* We shouldn't hit RAID56 for bs > ps cases for now. */
2861+
ASSERT(fs_info->sectorsize <= PAGE_SIZE);
2862+
28602863
/*
28612864
* If we hit ENOMEM temporarily, but later at
28622865
* raid56_parity_submit_scrub_rbio() time it succeeded, we just do
@@ -2873,14 +2876,25 @@ void raid56_parity_cache_data_pages(struct btrfs_raid_bio *rbio,
28732876
ASSERT(IS_ALIGNED(offset_in_full_stripe, BTRFS_STRIPE_LEN));
28742877
ASSERT(offset_in_full_stripe < (rbio->nr_data << BTRFS_STRIPE_LEN_SHIFT));
28752878

2876-
for (int page_nr = 0; page_nr < (BTRFS_STRIPE_LEN >> PAGE_SHIFT); page_nr++) {
2877-
struct page *dst = rbio->stripe_pages[page_nr + page_index];
2878-
struct page *src = data_pages[page_nr];
2879-
2880-
memcpy_page(dst, 0, src, 0, PAGE_SIZE);
2881-
for (int sector_nr = sectors_per_page * page_index;
2882-
sector_nr < sectors_per_page * (page_index + 1);
2883-
sector_nr++)
2884-
rbio->stripe_sectors[sector_nr].uptodate = true;
2879+
for (unsigned int cur_off = offset_in_full_stripe;
2880+
cur_off < offset_in_full_stripe + BTRFS_STRIPE_LEN;
2881+
cur_off += PAGE_SIZE) {
2882+
const unsigned int pindex = cur_off >> PAGE_SHIFT;
2883+
void *kaddr;
2884+
2885+
kaddr = kmap_local_page(rbio->stripe_pages[pindex]);
2886+
memcpy_from_folio(kaddr, data_folios[findex], foffset, PAGE_SIZE);
2887+
kunmap_local(kaddr);
2888+
2889+
foffset += PAGE_SIZE;
2890+
ASSERT(foffset <= folio_size(data_folios[findex]));
2891+
if (foffset == folio_size(data_folios[findex])) {
2892+
findex++;
2893+
foffset = 0;
2894+
}
28852895
}
2896+
for (unsigned int sector_nr = offset_in_full_stripe >> fs_info->sectorsize_bits;
2897+
sector_nr < (offset_in_full_stripe + BTRFS_STRIPE_LEN) >> fs_info->sectorsize_bits;
2898+
sector_nr++)
2899+
rbio->stripe_sectors[sector_nr].uptodate = true;
28862900
}

fs/btrfs/raid56.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -201,8 +201,8 @@ struct btrfs_raid_bio *raid56_parity_alloc_scrub_rbio(struct bio *bio,
201201
unsigned long *dbitmap, int stripe_nsectors);
202202
void raid56_parity_submit_scrub_rbio(struct btrfs_raid_bio *rbio);
203203

204-
void raid56_parity_cache_data_pages(struct btrfs_raid_bio *rbio,
205-
struct page **data_pages, u64 data_logical);
204+
void raid56_parity_cache_data_folios(struct btrfs_raid_bio *rbio,
205+
struct folio **data_folios, u64 data_logical);
206206

207207
int btrfs_alloc_stripe_hash_table(struct btrfs_fs_info *info);
208208
void btrfs_free_stripe_hash_table(struct btrfs_fs_info *info);

fs/btrfs/scrub.c

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ enum {
130130
scrub_bitmap_nr_last,
131131
};
132132

133-
#define SCRUB_STRIPE_PAGES (BTRFS_STRIPE_LEN / PAGE_SIZE)
133+
#define SCRUB_STRIPE_MAX_FOLIOS (BTRFS_STRIPE_LEN / PAGE_SIZE)
134134

135135
/*
136136
* Represent one contiguous range with a length of BTRFS_STRIPE_LEN.
@@ -139,7 +139,7 @@ struct scrub_stripe {
139139
struct scrub_ctx *sctx;
140140
struct btrfs_block_group *bg;
141141

142-
struct page *pages[SCRUB_STRIPE_PAGES];
142+
struct folio *folios[SCRUB_STRIPE_MAX_FOLIOS];
143143
struct scrub_sector_verification *sectors;
144144

145145
struct btrfs_device *dev;
@@ -339,10 +339,10 @@ static void release_scrub_stripe(struct scrub_stripe *stripe)
339339
if (!stripe)
340340
return;
341341

342-
for (int i = 0; i < SCRUB_STRIPE_PAGES; i++) {
343-
if (stripe->pages[i])
344-
__free_page(stripe->pages[i]);
345-
stripe->pages[i] = NULL;
342+
for (int i = 0; i < SCRUB_STRIPE_MAX_FOLIOS; i++) {
343+
if (stripe->folios[i])
344+
folio_put(stripe->folios[i]);
345+
stripe->folios[i] = NULL;
346346
}
347347
kfree(stripe->sectors);
348348
kfree(stripe->csums);
@@ -355,6 +355,7 @@ static void release_scrub_stripe(struct scrub_stripe *stripe)
355355
static int init_scrub_stripe(struct btrfs_fs_info *fs_info,
356356
struct scrub_stripe *stripe)
357357
{
358+
const u32 min_folio_shift = PAGE_SHIFT + fs_info->block_min_order;
358359
int ret;
359360

360361
memset(stripe, 0, sizeof(*stripe));
@@ -367,7 +368,9 @@ static int init_scrub_stripe(struct btrfs_fs_info *fs_info,
367368
atomic_set(&stripe->pending_io, 0);
368369
spin_lock_init(&stripe->write_error_lock);
369370

370-
ret = btrfs_alloc_page_array(SCRUB_STRIPE_PAGES, stripe->pages, false);
371+
ASSERT(BTRFS_STRIPE_LEN >> min_folio_shift <= SCRUB_STRIPE_MAX_FOLIOS);
372+
ret = btrfs_alloc_folio_array(BTRFS_STRIPE_LEN >> min_folio_shift,
373+
fs_info->block_min_order, stripe->folios);
371374
if (ret < 0)
372375
goto error;
373376

@@ -687,27 +690,30 @@ static int fill_writer_pointer_gap(struct scrub_ctx *sctx, u64 physical)
687690

688691
static void *scrub_stripe_get_kaddr(struct scrub_stripe *stripe, int sector_nr)
689692
{
690-
u32 offset = (sector_nr << stripe->bg->fs_info->sectorsize_bits);
691-
const struct page *page = stripe->pages[offset >> PAGE_SHIFT];
693+
struct btrfs_fs_info *fs_info = stripe->bg->fs_info;
694+
const u32 min_folio_shift = PAGE_SHIFT + fs_info->block_min_order;
695+
u32 offset = (sector_nr << fs_info->sectorsize_bits);
696+
const struct folio *folio = stripe->folios[offset >> min_folio_shift];
692697

693-
/* stripe->pages[] is allocated by us and no highmem is allowed. */
694-
ASSERT(page);
695-
ASSERT(!PageHighMem(page));
696-
return page_address(page) + offset_in_page(offset);
698+
/* stripe->folios[] is allocated by us and no highmem is allowed. */
699+
ASSERT(folio);
700+
ASSERT(!folio_test_partial_kmap(folio));
701+
return folio_address(folio) + offset_in_folio(folio, offset);
697702
}
698703

699704
static phys_addr_t scrub_stripe_get_paddr(struct scrub_stripe *stripe, int sector_nr)
700705
{
701706
struct btrfs_fs_info *fs_info = stripe->bg->fs_info;
707+
const u32 min_folio_shift = PAGE_SHIFT + fs_info->block_min_order;
702708
u32 offset = (sector_nr << fs_info->sectorsize_bits);
703-
const struct page *page = stripe->pages[offset >> PAGE_SHIFT];
709+
const struct folio *folio = stripe->folios[offset >> min_folio_shift];
704710

705-
/* stripe->pages[] is allocated by us and no highmem is allowed. */
706-
ASSERT(page);
707-
ASSERT(!PageHighMem(page));
708-
/* And the range must be contained inside the page. */
709-
ASSERT(offset_in_page(offset) + fs_info->sectorsize <= PAGE_SIZE);
710-
return page_to_phys(page) + offset_in_page(offset);
711+
/* stripe->folios[] is allocated by us and no highmem is allowed. */
712+
ASSERT(folio);
713+
ASSERT(!folio_test_partial_kmap(folio));
714+
/* And the range must be contained inside the folio. */
715+
ASSERT(offset_in_folio(folio, offset) + fs_info->sectorsize <= folio_size(folio));
716+
return page_to_phys(folio_page(folio, 0)) + offset_in_folio(folio, offset);
711717
}
712718

713719
static void scrub_verify_one_metadata(struct scrub_stripe *stripe, int sector_nr)
@@ -1872,6 +1878,7 @@ static void scrub_submit_initial_read(struct scrub_ctx *sctx,
18721878
{
18731879
struct btrfs_fs_info *fs_info = sctx->fs_info;
18741880
struct btrfs_bio *bbio;
1881+
const u32 min_folio_shift = PAGE_SHIFT + fs_info->block_min_order;
18751882
unsigned int nr_sectors = stripe_length(stripe) >> fs_info->sectorsize_bits;
18761883
int mirror = stripe->mirror_num;
18771884

@@ -1884,7 +1891,7 @@ static void scrub_submit_initial_read(struct scrub_ctx *sctx,
18841891
return;
18851892
}
18861893

1887-
bbio = btrfs_bio_alloc(SCRUB_STRIPE_PAGES, REQ_OP_READ, fs_info,
1894+
bbio = btrfs_bio_alloc(BTRFS_STRIPE_LEN >> min_folio_shift, REQ_OP_READ, fs_info,
18881895
scrub_read_endio, stripe);
18891896

18901897
bbio->bio.bi_iter.bi_sector = stripe->logical >> SECTOR_SHIFT;
@@ -2215,7 +2222,7 @@ static int scrub_raid56_parity_stripe(struct scrub_ctx *sctx,
22152222
for (int i = 0; i < data_stripes; i++) {
22162223
stripe = &sctx->raid56_data_stripes[i];
22172224

2218-
raid56_parity_cache_data_pages(rbio, stripe->pages,
2225+
raid56_parity_cache_data_folios(rbio, stripe->folios,
22192226
full_stripe_start + (i << BTRFS_STRIPE_LEN_SHIFT));
22202227
}
22212228
raid56_parity_submit_scrub_rbio(rbio);

0 commit comments

Comments
 (0)