* [PATCH 1/2] btrfs: prepare raid56 to support bs > ps cases
2025-09-12 3:59 [PATCH 0/2] btrfs: prepare raid56 and scrub to support bs > ps cases Qu Wenruo
@ 2025-09-12 3:59 ` Qu Wenruo
2025-09-12 3:59 ` [PATCH 2/2] btrfs: prepare scrub " Qu Wenruo
2025-09-17 7:31 ` [PATCH 0/2] btrfs: prepare raid56 and " Qu Wenruo
2 siblings, 0 replies; 4+ messages in thread
From: Qu Wenruo @ 2025-09-12 3:59 UTC (permalink / raw)
To: linux-btrfs
This involves the following conversion:
- btrfs_raid_bio::nr_pages -> nr_folios
- btrfs_raid_bio::stripe_npages -> stripe_nfolios
- btrfs_raid_bio::stripe_pages[] -> stripe_folios[]
- Involved comments using "page"
- Remove the PAGE_SIZE alignment check against sectorsize
There is one exception, function raid56_parity_cache_data_pages() is
utilized by scrub, and it doesn't support bs > ps yet.
So add an ASSERT() inside that function to make sure it's only called
when bs <= ps.
Signed-off-by: Qu Wenruo <wqu@suse.com>
---
fs/btrfs/misc.h | 5 ++
fs/btrfs/raid56.c | 181 ++++++++++++++++++++++++----------------------
fs/btrfs/raid56.h | 22 ++++--
3 files changed, 115 insertions(+), 93 deletions(-)
diff --git a/fs/btrfs/misc.h b/fs/btrfs/misc.h
index 60f9b000d644..3bedffbd51ba 100644
--- a/fs/btrfs/misc.h
+++ b/fs/btrfs/misc.h
@@ -214,4 +214,9 @@ static inline u64 folio_end(struct folio *folio)
return folio_pos(folio) + folio_size(folio);
}
+static inline phys_addr_t folio_to_phys(const struct folio *folio)
+{
+ return page_to_phys(folio_page(folio, 0));
+}
+
#endif
diff --git a/fs/btrfs/raid56.c b/fs/btrfs/raid56.c
index 2b4f577dcf39..ac94335dd262 100644
--- a/fs/btrfs/raid56.c
+++ b/fs/btrfs/raid56.c
@@ -158,7 +158,7 @@ static void scrub_rbio_work_locked(struct work_struct *work);
static void free_raid_bio_pointers(struct btrfs_raid_bio *rbio)
{
bitmap_free(rbio->error_bitmap);
- kfree(rbio->stripe_pages);
+ kfree(rbio->stripe_folios);
kfree(rbio->bio_sectors);
kfree(rbio->stripe_sectors);
kfree(rbio->finish_pointers);
@@ -166,8 +166,6 @@ static void free_raid_bio_pointers(struct btrfs_raid_bio *rbio)
static void free_raid_bio(struct btrfs_raid_bio *rbio)
{
- int i;
-
if (!refcount_dec_and_test(&rbio->refs))
return;
@@ -175,10 +173,10 @@ static void free_raid_bio(struct btrfs_raid_bio *rbio)
WARN_ON(!list_empty(&rbio->hash_list));
WARN_ON(!bio_list_empty(&rbio->bio_list));
- for (i = 0; i < rbio->nr_pages; i++) {
- if (rbio->stripe_pages[i]) {
- __free_page(rbio->stripe_pages[i]);
- rbio->stripe_pages[i] = NULL;
+ for (int i = 0; i < rbio->nr_folios; i++) {
+ if (rbio->stripe_folios[i]) {
+ folio_put(rbio->stripe_folios[i]);
+ rbio->stripe_folios[i] = NULL;
}
}
@@ -299,17 +297,16 @@ static int rbio_bucket(struct btrfs_raid_bio *rbio)
return hash_64(num >> 16, BTRFS_STRIPE_HASH_TABLE_BITS);
}
-static bool full_page_sectors_uptodate(struct btrfs_raid_bio *rbio,
- unsigned int page_nr)
+static bool full_folio_sectors_uptodate(struct btrfs_raid_bio *rbio,
+ unsigned int folio_nr)
{
- const u32 sectorsize = rbio->bioc->fs_info->sectorsize;
- const u32 sectors_per_page = PAGE_SIZE / sectorsize;
+ struct btrfs_fs_info *fs_info = rbio->bioc->fs_info;
+ const u32 sectors_per_folio = btrfs_min_folio_size(fs_info) >> fs_info->sectorsize_bits;
int i;
- ASSERT(page_nr < rbio->nr_pages);
+ ASSERT(folio_nr < rbio->nr_folios);
- for (i = sectors_per_page * page_nr;
- i < sectors_per_page * page_nr + sectors_per_page;
+ for (i = sectors_per_folio * folio_nr; i < sectors_per_folio * (folio_nr + 1);
i++) {
if (!rbio->stripe_sectors[i].uptodate)
return false;
@@ -324,53 +321,54 @@ static bool full_page_sectors_uptodate(struct btrfs_raid_bio *rbio,
*/
static void index_stripe_sectors(struct btrfs_raid_bio *rbio)
{
- const u32 sectorsize = rbio->bioc->fs_info->sectorsize;
- u32 offset;
- int i;
+ struct btrfs_fs_info *fs_info = rbio->bioc->fs_info;
+ const u32 blocksize = fs_info->sectorsize;
+ const u32 min_folio_shift = PAGE_SHIFT + fs_info->block_min_order;
- for (i = 0, offset = 0; i < rbio->nr_sectors; i++, offset += sectorsize) {
- int page_index = offset >> PAGE_SHIFT;
+ for (u32 offset = 0; offset < rbio->nr_folios << min_folio_shift; offset += blocksize) {
+ const unsigned int findex = offset >> min_folio_shift;
+ const unsigned int sindex = offset >> fs_info->sectorsize_bits;
+ struct folio *folio = rbio->stripe_folios[findex];
- ASSERT(page_index < rbio->nr_pages);
- if (!rbio->stripe_pages[page_index])
+ ASSERT(findex < rbio->nr_folios);
+ if (!folio)
continue;
-
- rbio->stripe_sectors[i].has_paddr = true;
- rbio->stripe_sectors[i].paddr =
- page_to_phys(rbio->stripe_pages[page_index]) +
- offset_in_page(offset);
+ rbio->stripe_sectors[sindex].has_paddr = true;
+ rbio->stripe_sectors[sindex].paddr = folio_to_phys(folio) +
+ offset_in_folio(folio, offset);
}
}
-static void steal_rbio_page(struct btrfs_raid_bio *src,
- struct btrfs_raid_bio *dest, int page_nr)
+static void steal_rbio_folio(struct btrfs_raid_bio *src,
+ struct btrfs_raid_bio *dest, int folio_nr)
{
- const u32 sectorsize = src->bioc->fs_info->sectorsize;
- const u32 sectors_per_page = PAGE_SIZE / sectorsize;
- int i;
+ struct btrfs_fs_info *fs_info = src->bioc->fs_info;
+ const u32 sectors_per_folio = btrfs_min_folio_size(fs_info) >> fs_info->sectorsize_bits;
- if (dest->stripe_pages[page_nr])
- __free_page(dest->stripe_pages[page_nr]);
- dest->stripe_pages[page_nr] = src->stripe_pages[page_nr];
- src->stripe_pages[page_nr] = NULL;
+ if (dest->stripe_folios[folio_nr])
+ folio_put(dest->stripe_folios[folio_nr]);
+ dest->stripe_folios[folio_nr] = src->stripe_folios[folio_nr];
+ src->stripe_folios[folio_nr] = NULL;
/* Also update the sector->uptodate bits. */
- for (i = sectors_per_page * page_nr;
- i < sectors_per_page * page_nr + sectors_per_page; i++)
+ for (int i = sectors_per_folio * folio_nr;
+ i < sectors_per_folio * (folio_nr + 1); i++)
dest->stripe_sectors[i].uptodate = true;
}
-static bool is_data_stripe_page(struct btrfs_raid_bio *rbio, int page_nr)
+static bool is_data_stripe_folio(struct btrfs_raid_bio *rbio, int folio_nr)
{
- const int sector_nr = (page_nr << PAGE_SHIFT) >>
+ struct btrfs_fs_info *fs_info = rbio->bioc->fs_info;
+ const unsigned int min_folio_shift = PAGE_SHIFT + fs_info->block_min_order;
+ const int sector_nr = (folio_nr << min_folio_shift) >>
rbio->bioc->fs_info->sectorsize_bits;
/*
- * We have ensured PAGE_SIZE is aligned with sectorsize, thus
- * we won't have a page which is half data half parity.
+ * We have ensured folio size is aligned with sectorsize, thus
+ * we won't have a folio which is half data half parity.
*
- * Thus if the first sector of the page belongs to data stripes, then
- * the full page belongs to data stripes.
+ * Thus if the first sector of the folio belongs to data stripes, then
+ * the full folio belongs to data stripes.
*/
return (sector_nr < rbio->nr_data * rbio->stripe_nsectors);
}
@@ -384,28 +382,26 @@ static bool is_data_stripe_page(struct btrfs_raid_bio *rbio, int page_nr)
*/
static void steal_rbio(struct btrfs_raid_bio *src, struct btrfs_raid_bio *dest)
{
- int i;
-
if (!test_bit(RBIO_CACHE_READY_BIT, &src->flags))
return;
- for (i = 0; i < dest->nr_pages; i++) {
- struct page *p = src->stripe_pages[i];
+ for (int i = 0; i < dest->nr_folios; i++) {
+ struct folio *folio = src->stripe_folios[i];
/*
- * We don't need to steal P/Q pages as they will always be
+ * We don't need to steal P/Q folio as they will always be
* regenerated for RMW or full write anyway.
*/
- if (!is_data_stripe_page(src, i))
+ if (!is_data_stripe_folio(src, i))
continue;
/*
* If @src already has RBIO_CACHE_READY_BIT, it should have
* all data stripe pages present and uptodate.
*/
- ASSERT(p);
- ASSERT(full_page_sectors_uptodate(src, i));
- steal_rbio_page(src, dest, i);
+ ASSERT(folio);
+ ASSERT(full_folio_sectors_uptodate(src, i));
+ steal_rbio_folio(src, dest, i);
}
index_stripe_sectors(dest);
index_stripe_sectors(src);
@@ -991,16 +987,15 @@ static struct sector_ptr *sector_in_rbio(struct btrfs_raid_bio *rbio,
static struct btrfs_raid_bio *alloc_rbio(struct btrfs_fs_info *fs_info,
struct btrfs_io_context *bioc)
{
+ const unsigned int min_folio_shift = PAGE_SHIFT + fs_info->block_min_order;
const unsigned int real_stripes = bioc->num_stripes - bioc->replace_nr_stripes;
- const unsigned int stripe_npages = BTRFS_STRIPE_LEN >> PAGE_SHIFT;
- const unsigned int num_pages = stripe_npages * real_stripes;
+ const unsigned int stripe_nfolios = BTRFS_STRIPE_LEN >> min_folio_shift;
+ const unsigned int num_folios = stripe_nfolios * real_stripes;
const unsigned int stripe_nsectors =
BTRFS_STRIPE_LEN >> fs_info->sectorsize_bits;
const unsigned int num_sectors = stripe_nsectors * real_stripes;
struct btrfs_raid_bio *rbio;
- /* PAGE_SIZE must also be aligned to sectorsize for subpage support */
- ASSERT(IS_ALIGNED(PAGE_SIZE, fs_info->sectorsize));
/*
* Our current stripe len should be fixed to 64k thus stripe_nsectors
* (at most 16) should be no larger than BITS_PER_LONG.
@@ -1017,8 +1012,7 @@ static struct btrfs_raid_bio *alloc_rbio(struct btrfs_fs_info *fs_info,
rbio = kzalloc(sizeof(*rbio), GFP_NOFS);
if (!rbio)
return ERR_PTR(-ENOMEM);
- rbio->stripe_pages = kcalloc(num_pages, sizeof(struct page *),
- GFP_NOFS);
+ rbio->stripe_folios = kcalloc(num_folios, sizeof(struct folio *), GFP_NOFS);
rbio->bio_sectors = kcalloc(num_sectors, sizeof(struct sector_ptr),
GFP_NOFS);
rbio->stripe_sectors = kcalloc(num_sectors, sizeof(struct sector_ptr),
@@ -1026,7 +1020,7 @@ static struct btrfs_raid_bio *alloc_rbio(struct btrfs_fs_info *fs_info,
rbio->finish_pointers = kcalloc(real_stripes, sizeof(void *), GFP_NOFS);
rbio->error_bitmap = bitmap_zalloc(num_sectors, GFP_NOFS);
- if (!rbio->stripe_pages || !rbio->bio_sectors || !rbio->stripe_sectors ||
+ if (!rbio->stripe_folios || !rbio->bio_sectors || !rbio->stripe_sectors ||
!rbio->finish_pointers || !rbio->error_bitmap) {
free_raid_bio_pointers(rbio);
kfree(rbio);
@@ -1041,10 +1035,10 @@ static struct btrfs_raid_bio *alloc_rbio(struct btrfs_fs_info *fs_info,
INIT_LIST_HEAD(&rbio->hash_list);
btrfs_get_bioc(bioc);
rbio->bioc = bioc;
- rbio->nr_pages = num_pages;
+ rbio->nr_folios = num_folios;
rbio->nr_sectors = num_sectors;
rbio->real_stripes = real_stripes;
- rbio->stripe_npages = stripe_npages;
+ rbio->stripe_nfolios = stripe_nfolios;
rbio->stripe_nsectors = stripe_nsectors;
refcount_set(&rbio->refs, 1);
atomic_set(&rbio->stripes_pending, 0);
@@ -1061,7 +1055,8 @@ static int alloc_rbio_pages(struct btrfs_raid_bio *rbio)
{
int ret;
- ret = btrfs_alloc_page_array(rbio->nr_pages, rbio->stripe_pages, false);
+ ret = btrfs_alloc_folio_array(rbio->nr_folios, rbio->bioc->fs_info->block_min_order,
+ rbio->stripe_folios);
if (ret < 0)
return ret;
/* Mapping all sectors */
@@ -1072,14 +1067,14 @@ static int alloc_rbio_pages(struct btrfs_raid_bio *rbio)
/* only allocate pages for p/q stripes */
static int alloc_rbio_parity_pages(struct btrfs_raid_bio *rbio)
{
- const int data_pages = rbio->nr_data * rbio->stripe_npages;
+ const unsigned int data_folios = rbio->nr_data * rbio->stripe_nfolios;
int ret;
- ret = btrfs_alloc_page_array(rbio->nr_pages - data_pages,
- rbio->stripe_pages + data_pages, false);
+ ret = btrfs_alloc_folio_array(rbio->nr_folios - data_folios,
+ rbio->bioc->fs_info->block_min_order,
+ rbio->stripe_folios + data_folios);
if (ret < 0)
return ret;
-
index_stripe_sectors(rbio);
return 0;
}
@@ -1488,7 +1483,7 @@ static void set_rbio_range_error(struct btrfs_raid_bio *rbio, struct bio *bio)
/*
* For subpage case, we can no longer set page Up-to-date directly for
- * stripe_pages[], thus we need to locate the sector.
+ * stripe_folios[], thus we need to locate the sector.
*/
static struct sector_ptr *find_stripe_sector(struct btrfs_raid_bio *rbio,
phys_addr_t paddr)
@@ -1633,10 +1628,11 @@ static void submit_read_wait_bio_list(struct btrfs_raid_bio *rbio,
static int alloc_rbio_data_pages(struct btrfs_raid_bio *rbio)
{
- const int data_pages = rbio->nr_data * rbio->stripe_npages;
+ const unsigned int data_folios = rbio->nr_data * rbio->stripe_nfolios;
int ret;
- ret = btrfs_alloc_page_array(data_pages, rbio->stripe_pages, false);
+ ret = btrfs_alloc_folio_array(data_folios, rbio->bioc->fs_info->block_min_order,
+ rbio->stripe_folios);
if (ret < 0)
return ret;
@@ -2475,23 +2471,25 @@ struct btrfs_raid_bio *raid56_parity_alloc_scrub_rbio(struct bio *bio,
*/
static int alloc_rbio_essential_pages(struct btrfs_raid_bio *rbio)
{
- const u32 sectorsize = rbio->bioc->fs_info->sectorsize;
+ struct btrfs_fs_info *fs_info = rbio->bioc->fs_info;
+ const u32 sectorsize = fs_info->sectorsize;
+ const u32 min_folio_shift = PAGE_SHIFT + fs_info->block_min_order;
int total_sector_nr;
for (total_sector_nr = 0; total_sector_nr < rbio->nr_sectors;
total_sector_nr++) {
- struct page *page;
+ struct folio *folio;
int sectornr = total_sector_nr % rbio->stripe_nsectors;
- int index = (total_sector_nr * sectorsize) >> PAGE_SHIFT;
+ unsigned int findex = (total_sector_nr * sectorsize) >> min_folio_shift;
if (!test_bit(sectornr, &rbio->dbitmap))
continue;
- if (rbio->stripe_pages[index])
+ if (rbio->stripe_folios[findex])
continue;
- page = alloc_page(GFP_NOFS);
- if (!page)
+ folio = folio_alloc(GFP_NOFS, fs_info->block_min_order);
+ if (!folio)
return -ENOMEM;
- rbio->stripe_pages[index] = page;
+ rbio->stripe_folios[findex] = folio;
}
index_stripe_sectors(rbio);
return 0;
@@ -2850,13 +2848,19 @@ void raid56_parity_submit_scrub_rbio(struct btrfs_raid_bio *rbio)
void raid56_parity_cache_data_pages(struct btrfs_raid_bio *rbio,
struct page **data_pages, u64 data_logical)
{
+ struct btrfs_fs_info *fs_info = rbio->bioc->fs_info;
const u64 offset_in_full_stripe = data_logical -
rbio->bioc->full_stripe_logical;
- const int page_index = offset_in_full_stripe >> PAGE_SHIFT;
- const u32 sectorsize = rbio->bioc->fs_info->sectorsize;
- const u32 sectors_per_page = PAGE_SIZE / sectorsize;
+ const u32 min_folio_size = btrfs_min_folio_size(fs_info);
+ const u32 min_folio_shift = PAGE_SHIFT + fs_info->block_min_order;
int ret;
+ /*
+ * The caller is not yet converted to follow min_folio_shift. So our
+ * minimal folio order must be 0 for now.
+ */
+ ASSERT(fs_info->block_min_order == 0);
+
/*
* If we hit ENOMEM temporarily, but later at
* raid56_parity_submit_scrub_rbio() time it succeeded, we just do
@@ -2873,13 +2877,20 @@ void raid56_parity_cache_data_pages(struct btrfs_raid_bio *rbio,
ASSERT(IS_ALIGNED(offset_in_full_stripe, BTRFS_STRIPE_LEN));
ASSERT(offset_in_full_stripe < (rbio->nr_data << BTRFS_STRIPE_LEN_SHIFT));
- for (int page_nr = 0; page_nr < (BTRFS_STRIPE_LEN >> PAGE_SHIFT); page_nr++) {
- struct page *dst = rbio->stripe_pages[page_nr + page_index];
- struct page *src = data_pages[page_nr];
+ for (int cur = offset_in_full_stripe; cur < offset_in_full_stripe + BTRFS_STRIPE_LEN;
+ cur += min_folio_size) {
+ struct folio *dest = rbio->stripe_folios[cur >> min_folio_shift];
+ struct folio *src = page_folio(data_pages[(cur - offset_in_full_stripe) >>
+ min_folio_shift]);
- memcpy_page(dst, 0, src, 0, PAGE_SIZE);
- for (int sector_nr = sectors_per_page * page_index;
- sector_nr < sectors_per_page * (page_index + 1);
+ ASSERT(dest);
+ ASSERT(src);
+ /* Folios from source and destination should have the same order. */
+ ASSERT(folio_order(dest) == folio_order(src));
+ folio_copy(dest, src);
+
+ for (int sector_nr = cur >> fs_info->sectorsize_bits;
+ sector_nr < (cur + BTRFS_STRIPE_LEN) >> fs_info->sectorsize_bits;
sector_nr++)
rbio->stripe_sectors[sector_nr].uptodate = true;
}
diff --git a/fs/btrfs/raid56.h b/fs/btrfs/raid56.h
index 0d7b4c2fb6ae..ddf6a7687eb6 100644
--- a/fs/btrfs/raid56.h
+++ b/fs/btrfs/raid56.h
@@ -64,8 +64,11 @@ struct btrfs_raid_bio {
*/
enum btrfs_rbio_ops operation;
- /* How many pages there are for the full stripe including P/Q */
- u16 nr_pages;
+ /*
+ * How many folios there are for the full stripe including P/Q.
+ * The folio size should be based on the fs_info::block_min_order.
+ */
+ u16 nr_folios;
/* How many sectors there are for the full stripe including P/Q */
u16 nr_sectors;
@@ -76,8 +79,8 @@ struct btrfs_raid_bio {
/* Number of all stripes (including P/Q) */
u8 real_stripes;
- /* How many pages there are for each stripe */
- u8 stripe_npages;
+ /* How many folios there are for each stripe. */
+ u8 stripe_nfolios;
/* How many sectors there are for each stripe */
u8 stripe_nsectors;
@@ -110,17 +113,20 @@ struct btrfs_raid_bio {
*/
/*
- * Pointers to pages that we allocated for reading/writing stripes
+ * Pointers to folios that we allocated for reading/writing stripes
* directly from the disk (including P/Q).
+ *
+ * All folios are following fs_info::block_min_order, so that no block
+ * will cross folio boundary.
*/
- struct page **stripe_pages;
+ struct folio **stripe_folios;
/* Pointers to the sectors in the bio_list, for faster lookup */
struct sector_ptr *bio_sectors;
/*
- * For subpage support, we need to map each sector to above
- * stripe_pages.
+ * For bs < ps support, we need to map each sector to above
+ * stripe_folios.
*/
struct sector_ptr *stripe_sectors;
--
2.50.1
^ permalink raw reply related [flat|nested] 4+ messages in thread* [PATCH 2/2] btrfs: prepare scrub to support bs > ps cases
2025-09-12 3:59 [PATCH 0/2] btrfs: prepare raid56 and scrub to support bs > ps cases Qu Wenruo
2025-09-12 3:59 ` [PATCH 1/2] btrfs: prepare raid56 " Qu Wenruo
@ 2025-09-12 3:59 ` Qu Wenruo
2025-09-17 7:31 ` [PATCH 0/2] btrfs: prepare raid56 and " Qu Wenruo
2 siblings, 0 replies; 4+ messages in thread
From: Qu Wenruo @ 2025-09-12 3:59 UTC (permalink / raw)
To: linux-btrfs
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.
Since most scrub code is based on kaddr/paddr, the migration itself is
pretty straightforward.
Signed-off-by: Qu Wenruo <wqu@suse.com>
---
fs/btrfs/raid56.c | 15 ++++----------
fs/btrfs/raid56.h | 4 ++--
fs/btrfs/scrub.c | 51 +++++++++++++++++++++++++++--------------------
3 files changed, 35 insertions(+), 35 deletions(-)
diff --git a/fs/btrfs/raid56.c b/fs/btrfs/raid56.c
index ac94335dd262..4074ff4ddb1d 100644
--- a/fs/btrfs/raid56.c
+++ b/fs/btrfs/raid56.c
@@ -2842,11 +2842,11 @@ void raid56_parity_submit_scrub_rbio(struct btrfs_raid_bio *rbio)
* This is for scrub call sites where we already have correct data contents.
* This allows us to avoid reading data stripes again.
*
- * Unfortunately here we have to do page copy, other than reusing the pages.
+ * Unfortunately here we have to do folio copy, other than reusing the pages.
* This is due to the fact rbio has its own page management for its cache.
*/
-void raid56_parity_cache_data_pages(struct btrfs_raid_bio *rbio,
- struct page **data_pages, u64 data_logical)
+void raid56_parity_cache_data_folios(struct btrfs_raid_bio *rbio,
+ struct folio **data_folios, u64 data_logical)
{
struct btrfs_fs_info *fs_info = rbio->bioc->fs_info;
const u64 offset_in_full_stripe = data_logical -
@@ -2855,12 +2855,6 @@ void raid56_parity_cache_data_pages(struct btrfs_raid_bio *rbio,
const u32 min_folio_shift = PAGE_SHIFT + fs_info->block_min_order;
int ret;
- /*
- * The caller is not yet converted to follow min_folio_shift. So our
- * minimal folio order must be 0 for now.
- */
- ASSERT(fs_info->block_min_order == 0);
-
/*
* If we hit ENOMEM temporarily, but later at
* raid56_parity_submit_scrub_rbio() time it succeeded, we just do
@@ -2880,8 +2874,7 @@ void raid56_parity_cache_data_pages(struct btrfs_raid_bio *rbio,
for (int cur = offset_in_full_stripe; cur < offset_in_full_stripe + BTRFS_STRIPE_LEN;
cur += min_folio_size) {
struct folio *dest = rbio->stripe_folios[cur >> min_folio_shift];
- struct folio *src = page_folio(data_pages[(cur - offset_in_full_stripe) >>
- min_folio_shift]);
+ struct folio *src = data_folios[(cur - offset_in_full_stripe) >> min_folio_shift];
ASSERT(dest);
ASSERT(src);
diff --git a/fs/btrfs/raid56.h b/fs/btrfs/raid56.h
index ddf6a7687eb6..5662a3a2f04b 100644
--- a/fs/btrfs/raid56.h
+++ b/fs/btrfs/raid56.h
@@ -207,8 +207,8 @@ struct btrfs_raid_bio *raid56_parity_alloc_scrub_rbio(struct bio *bio,
unsigned long *dbitmap, int stripe_nsectors);
void raid56_parity_submit_scrub_rbio(struct btrfs_raid_bio *rbio);
-void raid56_parity_cache_data_pages(struct btrfs_raid_bio *rbio,
- struct page **data_pages, u64 data_logical);
+void raid56_parity_cache_data_folios(struct btrfs_raid_bio *rbio,
+ struct folio **data_folios, u64 data_logical);
int btrfs_alloc_stripe_hash_table(struct btrfs_fs_info *info);
void btrfs_free_stripe_hash_table(struct btrfs_fs_info *info);
diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c
index 979d33d8c193..cddf798c32e8 100644
--- a/fs/btrfs/scrub.c
+++ b/fs/btrfs/scrub.c
@@ -130,7 +130,7 @@ enum {
scrub_bitmap_nr_last,
};
-#define SCRUB_STRIPE_PAGES (BTRFS_STRIPE_LEN / PAGE_SIZE)
+#define SCRUB_STRIPE_MAX_FOLIOS (BTRFS_STRIPE_LEN / PAGE_SIZE)
/*
* Represent one contiguous range with a length of BTRFS_STRIPE_LEN.
@@ -139,7 +139,7 @@ struct scrub_stripe {
struct scrub_ctx *sctx;
struct btrfs_block_group *bg;
- struct page *pages[SCRUB_STRIPE_PAGES];
+ struct folio *folios[SCRUB_STRIPE_MAX_FOLIOS];
struct scrub_sector_verification *sectors;
struct btrfs_device *dev;
@@ -339,10 +339,10 @@ static void release_scrub_stripe(struct scrub_stripe *stripe)
if (!stripe)
return;
- for (int i = 0; i < SCRUB_STRIPE_PAGES; i++) {
- if (stripe->pages[i])
- __free_page(stripe->pages[i]);
- stripe->pages[i] = NULL;
+ for (int i = 0; i < SCRUB_STRIPE_MAX_FOLIOS; i++) {
+ if (stripe->folios[i])
+ folio_put(stripe->folios[i]);
+ stripe->folios[i] = NULL;
}
kfree(stripe->sectors);
kfree(stripe->csums);
@@ -355,6 +355,7 @@ static void release_scrub_stripe(struct scrub_stripe *stripe)
static int init_scrub_stripe(struct btrfs_fs_info *fs_info,
struct scrub_stripe *stripe)
{
+ const u32 min_folio_shift = PAGE_SHIFT + fs_info->block_min_order;
int ret;
memset(stripe, 0, sizeof(*stripe));
@@ -367,7 +368,9 @@ static int init_scrub_stripe(struct btrfs_fs_info *fs_info,
atomic_set(&stripe->pending_io, 0);
spin_lock_init(&stripe->write_error_lock);
- ret = btrfs_alloc_page_array(SCRUB_STRIPE_PAGES, stripe->pages, false);
+ ASSERT(BTRFS_STRIPE_LEN >> min_folio_shift <= SCRUB_STRIPE_MAX_FOLIOS);
+ ret = btrfs_alloc_folio_array(BTRFS_STRIPE_LEN >> min_folio_shift,
+ fs_info->block_min_order, stripe->folios);
if (ret < 0)
goto error;
@@ -687,27 +690,30 @@ static int fill_writer_pointer_gap(struct scrub_ctx *sctx, u64 physical)
static void *scrub_stripe_get_kaddr(struct scrub_stripe *stripe, int sector_nr)
{
- u32 offset = (sector_nr << stripe->bg->fs_info->sectorsize_bits);
- const struct page *page = stripe->pages[offset >> PAGE_SHIFT];
+ struct btrfs_fs_info *fs_info = stripe->bg->fs_info;
+ const u32 min_folio_shift = PAGE_SHIFT + fs_info->block_min_order;
+ u32 offset = (sector_nr << fs_info->sectorsize_bits);
+ const struct folio *folio = stripe->folios[offset >> min_folio_shift];
- /* stripe->pages[] is allocated by us and no highmem is allowed. */
- ASSERT(page);
- ASSERT(!PageHighMem(page));
- return page_address(page) + offset_in_page(offset);
+ /* stripe->folios[] is allocated by us and no highmem is allowed. */
+ ASSERT(folio);
+ ASSERT(!folio_test_partial_kmap(folio));
+ return folio_address(folio) + offset_in_folio(folio, offset);
}
static phys_addr_t scrub_stripe_get_paddr(struct scrub_stripe *stripe, int sector_nr)
{
struct btrfs_fs_info *fs_info = stripe->bg->fs_info;
+ const u32 min_folio_shift = PAGE_SHIFT + fs_info->block_min_order;
u32 offset = (sector_nr << fs_info->sectorsize_bits);
- const struct page *page = stripe->pages[offset >> PAGE_SHIFT];
+ const struct folio *folio = stripe->folios[offset >> min_folio_shift];
- /* stripe->pages[] is allocated by us and no highmem is allowed. */
- ASSERT(page);
- ASSERT(!PageHighMem(page));
- /* And the range must be contained inside the page. */
- ASSERT(offset_in_page(offset) + fs_info->sectorsize <= PAGE_SIZE);
- return page_to_phys(page) + offset_in_page(offset);
+ /* stripe->folios[] is allocated by us and no highmem is allowed. */
+ ASSERT(folio);
+ ASSERT(!folio_test_partial_kmap(folio));
+ /* And the range must be contained inside the folio. */
+ ASSERT(offset_in_folio(folio, offset) + fs_info->sectorsize <= folio_size(folio));
+ return folio_to_phys(folio) + offset_in_folio(folio, offset);
}
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,
{
struct btrfs_fs_info *fs_info = sctx->fs_info;
struct btrfs_bio *bbio;
+ const u32 min_folio_shift = PAGE_SHIFT + fs_info->block_min_order;
unsigned int nr_sectors = stripe_length(stripe) >> fs_info->sectorsize_bits;
int mirror = stripe->mirror_num;
@@ -1884,7 +1891,7 @@ static void scrub_submit_initial_read(struct scrub_ctx *sctx,
return;
}
- bbio = btrfs_bio_alloc(SCRUB_STRIPE_PAGES, REQ_OP_READ, fs_info,
+ bbio = btrfs_bio_alloc(BTRFS_STRIPE_LEN >> min_folio_shift, REQ_OP_READ, fs_info,
scrub_read_endio, stripe);
bbio->bio.bi_iter.bi_sector = stripe->logical >> SECTOR_SHIFT;
@@ -2215,7 +2222,7 @@ static int scrub_raid56_parity_stripe(struct scrub_ctx *sctx,
for (int i = 0; i < data_stripes; i++) {
stripe = &sctx->raid56_data_stripes[i];
- raid56_parity_cache_data_pages(rbio, stripe->pages,
+ raid56_parity_cache_data_folios(rbio, stripe->folios,
full_stripe_start + (i << BTRFS_STRIPE_LEN_SHIFT));
}
raid56_parity_submit_scrub_rbio(rbio);
--
2.50.1
^ permalink raw reply related [flat|nested] 4+ messages in thread