linux-btrfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3] btrfs: reduce memory usage for btrfs_raid_bio structure
@ 2025-10-09  4:39 Qu Wenruo
  2025-10-09  4:39 ` [PATCH 1/3] btrfs: raid56: remove sector_ptr::has_paddr member Qu Wenruo
                   ` (3 more replies)
  0 siblings, 4 replies; 6+ messages in thread
From: Qu Wenruo @ 2025-10-09  4:39 UTC (permalink / raw)
  To: linux-btrfs

This series replace the following members of btrfs_raid_bio:

	struct sector_ptr bio_sectors[nr_sectors]
	struct sector_ptr stripe_sectors[nr_sectors]

To the following ones:

	phys_addr_t bio_sectors[nr_sectors]
	phys_addr_t stripe_sectors[nr_sectors]
	unsigned long uptodate_bitmap[nr_sectors]

For x86_64 (4K page size) with the fixed 64K stripe size and 3 disks, the
memory usage of those members (not the full structure) will be reduced from:

	8 * 2 + 48 * 16 * 2 = 1552

To
	8 * 3 + 48 * 8 * 2 + 8 * 2 = 808

Almost halved the memory usage.

The memory saving comes from:

- Compat sector_ptr::uptodate bit into a bitmap
  This not only saves space, but also allow us to call bitmap_*()
  helpers when we need to set multiple bits in one go (mostly for
  subpage cases)

- Remove sector_ptr::uptodate flag
  We can use a special paddr (not NULL though) to indicate if the paddr
  is valid or not.

- Get rid of sector_ptr
  That structure has extra bits that take a full byte for each flag.
  This is the biggest space saving.

Qu Wenruo (3):
  btrfs: raid56: remove sector_ptr::has_paddr member
  btrfs: raid56: move sector_ptr::uptodate into a dedicated bitmap
  btrfs: raid56: remove sector_ptr structure

 fs/btrfs/raid56.c | 347 ++++++++++++++++++++++------------------------
 fs/btrfs/raid56.h |  17 +--
 2 files changed, 168 insertions(+), 196 deletions(-)

-- 
2.50.1


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 1/3] btrfs: raid56: remove sector_ptr::has_paddr member
  2025-10-09  4:39 [PATCH 0/3] btrfs: reduce memory usage for btrfs_raid_bio structure Qu Wenruo
@ 2025-10-09  4:39 ` Qu Wenruo
  2025-10-09  4:40 ` [PATCH 2/3] btrfs: raid56: move sector_ptr::uptodate into a dedicated bitmap Qu Wenruo
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 6+ messages in thread
From: Qu Wenruo @ 2025-10-09  4:39 UTC (permalink / raw)
  To: linux-btrfs

We can use paddr -1 as an indicator for unset/uninitialized paddr.

We can not use 0 paddr, unlike virtual address 0 which is never mapped
thus will always trigger a page fault, physical address 0 may be a valid
page.

So here we follow swiotlb to use (paddr)-1 as a special indicator for
invalid/unset physical address.

Even if the PFN may still be valid, our usage of the physical address
should always be aligned to fs block size (or page size for bs > ps
cases), thus such -1 paddr should never be a valid one.

With this special -1 paddr, we can get rid of has_paddr member and save
1 byte for sector_ptr structure.

Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 fs/btrfs/raid56.c | 46 ++++++++++++++++++++++++++--------------------
 1 file changed, 26 insertions(+), 20 deletions(-)

diff --git a/fs/btrfs/raid56.c b/fs/btrfs/raid56.c
index 0135dceb7baa..60e81b79f939 100644
--- a/fs/btrfs/raid56.c
+++ b/fs/btrfs/raid56.c
@@ -133,6 +133,12 @@ struct btrfs_stripe_hash_table {
 	struct btrfs_stripe_hash table[];
 };
 
+/*
+ * The PFN may still be valid, but our paddrs should always be block size
+ * aligned, thus such -1 paddr is definitely not a valid one.
+ */
+#define INVALID_PADDR	(~(phys_addr_t)0)
+
 /*
  * A structure to present a sector inside a page, the length is fixed to
  * sectorsize;
@@ -141,9 +147,10 @@ struct sector_ptr {
 	/*
 	 * Blocks from the bio list can still be highmem.
 	 * So here we use physical address to present a page and the offset inside it.
+	 *
+	 * If it's INVALID_PADDR then it's not set.
 	 */
 	phys_addr_t paddr;
-	bool has_paddr;
 	bool uptodate;
 };
 
@@ -263,7 +270,7 @@ static void cache_rbio_pages(struct btrfs_raid_bio *rbio)
 
 	for (i = 0; i < rbio->nr_sectors; i++) {
 		/* Some range not covered by bio (partial write), skip it */
-		if (!rbio->bio_sectors[i].has_paddr) {
+		if (rbio->bio_sectors[i].paddr == INVALID_PADDR) {
 			/*
 			 * Even if the sector is not covered by bio, if it is
 			 * a data sector it should still be uptodate as it is
@@ -335,7 +342,6 @@ static void index_stripe_sectors(struct btrfs_raid_bio *rbio)
 		if (!rbio->stripe_pages[page_index])
 			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);
@@ -972,9 +978,9 @@ static struct sector_ptr *sector_in_rbio(struct btrfs_raid_bio *rbio,
 
 	spin_lock(&rbio->bio_list_lock);
 	sector = &rbio->bio_sectors[index];
-	if (sector->has_paddr || bio_list_only) {
+	if (sector->paddr != INVALID_PADDR || bio_list_only) {
 		/* Don't return sector without a valid page pointer */
-		if (!sector->has_paddr)
+		if (sector->paddr == INVALID_PADDR)
 			sector = NULL;
 		spin_unlock(&rbio->bio_list_lock);
 		return sector;
@@ -1032,6 +1038,10 @@ static struct btrfs_raid_bio *alloc_rbio(struct btrfs_fs_info *fs_info,
 		kfree(rbio);
 		return ERR_PTR(-ENOMEM);
 	}
+	for (int i = 0; i < num_sectors; i++) {
+		rbio->stripe_sectors[i].paddr = INVALID_PADDR;
+		rbio->bio_sectors[i].paddr = INVALID_PADDR;
+	}
 
 	bio_list_init(&rbio->bio_list);
 	init_waitqueue_head(&rbio->io_wait);
@@ -1152,7 +1162,7 @@ static int rbio_add_io_sector(struct btrfs_raid_bio *rbio,
 			   rbio, stripe_nr);
 	ASSERT_RBIO_SECTOR(sector_nr >= 0 && sector_nr < rbio->stripe_nsectors,
 			   rbio, sector_nr);
-	ASSERT(sector->has_paddr);
+	ASSERT(sector->paddr != INVALID_PADDR);
 
 	stripe = &rbio->bioc->stripes[stripe_nr];
 	disk_start = stripe->physical + sector_nr * sectorsize;
@@ -1216,7 +1226,6 @@ static void index_one_bio(struct btrfs_raid_bio *rbio, struct bio *bio)
 		unsigned int index = (offset >> sectorsize_bits);
 		struct sector_ptr *sector = &rbio->bio_sectors[index];
 
-		sector->has_paddr = true;
 		sector->paddr = paddr;
 		offset += sectorsize;
 	}
@@ -1299,7 +1308,7 @@ static void assert_rbio(struct btrfs_raid_bio *rbio)
 static inline void *kmap_local_sector(const struct sector_ptr *sector)
 {
 	/* The sector pointer must have a page mapped to it. */
-	ASSERT(sector->has_paddr);
+	ASSERT(sector->paddr != INVALID_PADDR);
 
 	return kmap_local_page(phys_to_page(sector->paddr)) +
 	       offset_in_page(sector->paddr);
@@ -1498,7 +1507,7 @@ static struct sector_ptr *find_stripe_sector(struct btrfs_raid_bio *rbio,
 	for (i = 0; i < rbio->nr_sectors; i++) {
 		struct sector_ptr *sector = &rbio->stripe_sectors[i];
 
-		if (sector->has_paddr && sector->paddr == paddr)
+		if (sector->paddr == paddr)
 			return sector;
 	}
 	return NULL;
@@ -1532,8 +1541,7 @@ static int get_bio_sector_nr(struct btrfs_raid_bio *rbio, struct bio *bio)
 	for (i = 0; i < rbio->nr_sectors; i++) {
 		if (rbio->stripe_sectors[i].paddr == bvec_paddr)
 			break;
-		if (rbio->bio_sectors[i].has_paddr &&
-		    rbio->bio_sectors[i].paddr == bvec_paddr)
+		if (rbio->bio_sectors[i].paddr == bvec_paddr)
 			break;
 	}
 	ASSERT(i < rbio->nr_sectors);
@@ -2317,7 +2325,7 @@ static bool need_read_stripe_sectors(struct btrfs_raid_bio *rbio)
 		 * thus this rbio can not be cached one, as cached one must
 		 * have all its data sectors present and uptodate.
 		 */
-		if (!sector->has_paddr || !sector->uptodate)
+		if (sector->paddr == INVALID_PADDR || !sector->uptodate)
 			return true;
 	}
 	return false;
@@ -2508,8 +2516,8 @@ static int finish_parity_scrub(struct btrfs_raid_bio *rbio)
 	int sectornr;
 	bool has_qstripe;
 	struct page *page;
-	struct sector_ptr p_sector = { 0 };
-	struct sector_ptr q_sector = { 0 };
+	struct sector_ptr p_sector = { .paddr = INVALID_PADDR };
+	struct sector_ptr q_sector = { .paddr = INVALID_PADDR };
 	struct bio_list bio_list;
 	int is_replace = 0;
 	int ret;
@@ -2542,7 +2550,6 @@ static int finish_parity_scrub(struct btrfs_raid_bio *rbio)
 	page = alloc_page(GFP_NOFS);
 	if (!page)
 		return -ENOMEM;
-	p_sector.has_paddr = true;
 	p_sector.paddr = page_to_phys(page);
 	p_sector.uptodate = 1;
 	page = NULL;
@@ -2552,10 +2559,9 @@ static int finish_parity_scrub(struct btrfs_raid_bio *rbio)
 		page = alloc_page(GFP_NOFS);
 		if (!page) {
 			__free_page(phys_to_page(p_sector.paddr));
-			p_sector.has_paddr = false;
+			p_sector.paddr = INVALID_PADDR;
 			return -ENOMEM;
 		}
-		q_sector.has_paddr = true;
 		q_sector.paddr = page_to_phys(page);
 		q_sector.uptodate = 1;
 		page = NULL;
@@ -2604,10 +2610,10 @@ static int finish_parity_scrub(struct btrfs_raid_bio *rbio)
 
 	kunmap_local(pointers[nr_data]);
 	__free_page(phys_to_page(p_sector.paddr));
-	p_sector.has_paddr = false;
-	if (q_sector.has_paddr) {
+	p_sector.paddr = INVALID_PADDR;
+	if (q_sector.paddr != INVALID_PADDR) {
 		__free_page(phys_to_page(q_sector.paddr));
-		q_sector.has_paddr = false;
+		q_sector.paddr = INVALID_PADDR;
 	}
 
 	/*
-- 
2.50.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 2/3] btrfs: raid56: move sector_ptr::uptodate into a dedicated bitmap
  2025-10-09  4:39 [PATCH 0/3] btrfs: reduce memory usage for btrfs_raid_bio structure Qu Wenruo
  2025-10-09  4:39 ` [PATCH 1/3] btrfs: raid56: remove sector_ptr::has_paddr member Qu Wenruo
@ 2025-10-09  4:40 ` Qu Wenruo
  2025-10-09  4:40 ` [PATCH 3/3] btrfs: raid56: remove sector_ptr structure Qu Wenruo
  2025-11-10 22:58 ` [PATCH 0/3] btrfs: reduce memory usage for btrfs_raid_bio structure Qu Wenruo
  3 siblings, 0 replies; 6+ messages in thread
From: Qu Wenruo @ 2025-10-09  4:40 UTC (permalink / raw)
  To: linux-btrfs

The uptodate boolean member can be extracted into a bitmap, which will
save us some space (1 bit in a byte vs 8 bits in a byte).

Furthermore we do not need to record the uptodate bitmap for bio
sectors, as if bio_sectors[].paddr is valid it means there is a bio and
will be uptodate.

Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 fs/btrfs/raid56.c | 69 +++++++++++++++++++++++------------------------
 fs/btrfs/raid56.h |  3 +++
 2 files changed, 37 insertions(+), 35 deletions(-)

diff --git a/fs/btrfs/raid56.c b/fs/btrfs/raid56.c
index 60e81b79f939..77ff1ac29886 100644
--- a/fs/btrfs/raid56.c
+++ b/fs/btrfs/raid56.c
@@ -151,7 +151,6 @@ struct sector_ptr {
 	 * If it's INVALID_PADDR then it's not set.
 	 */
 	phys_addr_t paddr;
-	bool uptodate;
 };
 
 static void rmw_rbio_work(struct work_struct *work);
@@ -277,13 +276,13 @@ static void cache_rbio_pages(struct btrfs_raid_bio *rbio)
 			 * read from disk.
 			 */
 			if (i < rbio->nr_data * rbio->stripe_nsectors)
-				ASSERT(rbio->stripe_sectors[i].uptodate);
+				ASSERT(test_bit(i, rbio->stripe_uptodate_bitmap));
 			continue;
 		}
 
 		memcpy_sectors(&rbio->stripe_sectors[i], &rbio->bio_sectors[i],
 				rbio->bioc->fs_info->sectorsize);
-		rbio->stripe_sectors[i].uptodate = 1;
+		set_bit(i, rbio->stripe_uptodate_bitmap);
 	}
 	set_bit(RBIO_CACHE_READY_BIT, &rbio->flags);
 }
@@ -318,7 +317,7 @@ static bool full_page_sectors_uptodate(struct btrfs_raid_bio *rbio,
 	for (i = sectors_per_page * page_nr;
 	     i < sectors_per_page * page_nr + sectors_per_page;
 	     i++) {
-		if (!rbio->stripe_sectors[i].uptodate)
+		if (!test_bit(i, rbio->stripe_uptodate_bitmap))
 			return false;
 	}
 	return true;
@@ -353,17 +352,14 @@ static void steal_rbio_page(struct btrfs_raid_bio *src,
 {
 	const u32 sectorsize = src->bioc->fs_info->sectorsize;
 	const u32 sectors_per_page = PAGE_SIZE / sectorsize;
-	int i;
 
 	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;
 
-	/* Also update the sector->uptodate bits. */
-	for (i = sectors_per_page * page_nr;
-	     i < sectors_per_page * page_nr + sectors_per_page; i++)
-		dest->stripe_sectors[i].uptodate = true;
+	/* Also update the stripe_uptodate_bitmap bits. */
+	bitmap_set(dest->stripe_uptodate_bitmap, sectors_per_page * page_nr, sectors_per_page);
 }
 
 static bool is_data_stripe_page(struct btrfs_raid_bio *rbio, int page_nr)
@@ -1031,9 +1027,10 @@ static struct btrfs_raid_bio *alloc_rbio(struct btrfs_fs_info *fs_info,
 				       GFP_NOFS);
 	rbio->finish_pointers = kcalloc(real_stripes, sizeof(void *), GFP_NOFS);
 	rbio->error_bitmap = bitmap_zalloc(num_sectors, GFP_NOFS);
+	rbio->stripe_uptodate_bitmap = bitmap_zalloc(num_sectors, GFP_NOFS);
 
 	if (!rbio->stripe_pages || !rbio->bio_sectors || !rbio->stripe_sectors ||
-	    !rbio->finish_pointers || !rbio->error_bitmap) {
+	    !rbio->finish_pointers || !rbio->error_bitmap || !rbio->stripe_uptodate_bitmap) {
 		free_raid_bio_pointers(rbio);
 		kfree(rbio);
 		return ERR_PTR(-ENOMEM);
@@ -1331,7 +1328,8 @@ static void generate_pq_vertical(struct btrfs_raid_bio *rbio, int sectornr)
 
 	/* Then add the parity stripe */
 	sector = rbio_pstripe_sector(rbio, sectornr);
-	sector->uptodate = 1;
+	set_bit(rbio_stripe_sector_index(rbio, rbio->nr_data, sectornr),
+		rbio->stripe_uptodate_bitmap);
 	pointers[stripe++] = kmap_local_sector(sector);
 
 	if (has_qstripe) {
@@ -1340,7 +1338,8 @@ static void generate_pq_vertical(struct btrfs_raid_bio *rbio, int sectornr)
 		 * to fill in our p/q
 		 */
 		sector = rbio_qstripe_sector(rbio, sectornr);
-		sector->uptodate = 1;
+		set_bit(rbio_stripe_sector_index(rbio, rbio->nr_data + 1, sectornr),
+			rbio->stripe_uptodate_bitmap);
 		pointers[stripe++] = kmap_local_sector(sector);
 
 		assert_rbio(rbio);
@@ -1496,21 +1495,20 @@ 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.
+ * Return the index inside the rbio->stripe_sectors[] array.
+ *
+ * Return -1 if not found.
  */
-static struct sector_ptr *find_stripe_sector(struct btrfs_raid_bio *rbio,
-					     phys_addr_t paddr)
+static int find_stripe_sector_nr(struct btrfs_raid_bio *rbio,
+				 phys_addr_t paddr)
 {
-	int i;
-
-	for (i = 0; i < rbio->nr_sectors; i++) {
+	for (int i = 0; i < rbio->nr_sectors; i++) {
 		struct sector_ptr *sector = &rbio->stripe_sectors[i];
 
 		if (sector->paddr == paddr)
-			return sector;
+			return i;
 	}
-	return NULL;
+	return -1;
 }
 
 /*
@@ -1525,11 +1523,11 @@ static void set_bio_pages_uptodate(struct btrfs_raid_bio *rbio, struct bio *bio)
 	ASSERT(!bio_flagged(bio, BIO_CLONED));
 
 	btrfs_bio_for_each_block_all(paddr, bio, blocksize) {
-		struct sector_ptr *sector = find_stripe_sector(rbio, paddr);
+		int sector_nr = find_stripe_sector_nr(rbio, paddr);
 
-		ASSERT(sector);
-		if (sector)
-			sector->uptodate = 1;
+		ASSERT(sector_nr >= 0);
+		if (sector_nr >= 0)
+			set_bit(sector_nr, rbio->stripe_uptodate_bitmap);
 	}
 }
 
@@ -1963,7 +1961,8 @@ static int recover_vertical(struct btrfs_raid_bio *rbio, int sector_nr,
 			goto cleanup;
 
 		sector = rbio_stripe_sector(rbio, faila, sector_nr);
-		sector->uptodate = 1;
+		set_bit(rbio_stripe_sector_index(rbio, faila, sector_nr),
+			rbio->stripe_uptodate_bitmap);
 	}
 	if (failb >= 0) {
 		ret = verify_one_sector(rbio, failb, sector_nr);
@@ -1971,7 +1970,8 @@ static int recover_vertical(struct btrfs_raid_bio *rbio, int sector_nr,
 			goto cleanup;
 
 		sector = rbio_stripe_sector(rbio, failb, sector_nr);
-		sector->uptodate = 1;
+		set_bit(rbio_stripe_sector_index(rbio, failb, sector_nr),
+			rbio->stripe_uptodate_bitmap);
 	}
 
 cleanup:
@@ -2325,7 +2325,8 @@ static bool need_read_stripe_sectors(struct btrfs_raid_bio *rbio)
 		 * thus this rbio can not be cached one, as cached one must
 		 * have all its data sectors present and uptodate.
 		 */
-		if (sector->paddr == INVALID_PADDR || !sector->uptodate)
+		if (sector->paddr == INVALID_PADDR ||
+		    !test_bit(i, rbio->stripe_uptodate_bitmap))
 			return true;
 	}
 	return false;
@@ -2551,7 +2552,6 @@ static int finish_parity_scrub(struct btrfs_raid_bio *rbio)
 	if (!page)
 		return -ENOMEM;
 	p_sector.paddr = page_to_phys(page);
-	p_sector.uptodate = 1;
 	page = NULL;
 
 	if (has_qstripe) {
@@ -2563,7 +2563,6 @@ static int finish_parity_scrub(struct btrfs_raid_bio *rbio)
 			return -ENOMEM;
 		}
 		q_sector.paddr = page_to_phys(page);
-		q_sector.uptodate = 1;
 		page = NULL;
 		pointers[rbio->real_stripes - 1] = kmap_local_sector(&q_sector);
 	}
@@ -2781,7 +2780,8 @@ static int scrub_assemble_read_bios(struct btrfs_raid_bio *rbio)
 		 * The bio cache may have handed us an uptodate sector.  If so,
 		 * use it.
 		 */
-		if (sector->uptodate)
+		if (test_bit(rbio_stripe_sector_index(rbio, stripe, sectornr),
+			     rbio->stripe_uptodate_bitmap))
 			continue;
 
 		ret = rbio_add_io_sector(rbio, &bio_list, sector, stripe,
@@ -2899,8 +2899,7 @@ void raid56_parity_cache_data_folios(struct btrfs_raid_bio *rbio,
 			foffset = 0;
 		}
 	}
-	for (unsigned int sector_nr = offset_in_full_stripe >> fs_info->sectorsize_bits;
-	     sector_nr < (offset_in_full_stripe + BTRFS_STRIPE_LEN) >> fs_info->sectorsize_bits;
-	     sector_nr++)
-		rbio->stripe_sectors[sector_nr].uptodate = true;
+	bitmap_set(rbio->stripe_uptodate_bitmap,
+		   offset_in_full_stripe >> fs_info->sectorsize_bits,
+		   BTRFS_STRIPE_LEN >> fs_info->sectorsize_bits);
 }
diff --git a/fs/btrfs/raid56.h b/fs/btrfs/raid56.h
index 84c4d1d29c7a..b636de4af7ac 100644
--- a/fs/btrfs/raid56.h
+++ b/fs/btrfs/raid56.h
@@ -124,6 +124,9 @@ struct btrfs_raid_bio {
 	 */
 	struct sector_ptr *stripe_sectors;
 
+	/* Each set bit means the corresponding sector in stripe_sectors[] is uptodate. */
+	unsigned long *stripe_uptodate_bitmap;
+
 	/* Allocated with real_stripes-many pointers for finish_*() calls */
 	void **finish_pointers;
 
-- 
2.50.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 3/3] btrfs: raid56: remove sector_ptr structure
  2025-10-09  4:39 [PATCH 0/3] btrfs: reduce memory usage for btrfs_raid_bio structure Qu Wenruo
  2025-10-09  4:39 ` [PATCH 1/3] btrfs: raid56: remove sector_ptr::has_paddr member Qu Wenruo
  2025-10-09  4:40 ` [PATCH 2/3] btrfs: raid56: move sector_ptr::uptodate into a dedicated bitmap Qu Wenruo
@ 2025-10-09  4:40 ` Qu Wenruo
  2025-11-10 22:58 ` [PATCH 0/3] btrfs: reduce memory usage for btrfs_raid_bio structure Qu Wenruo
  3 siblings, 0 replies; 6+ messages in thread
From: Qu Wenruo @ 2025-10-09  4:40 UTC (permalink / raw)
  To: linux-btrfs

Since sector_ptr structure is now only containing a single paddr, there
is no need to use that structure.

Instead use phys_addr_t array for bio and stripe pointers.

This means several helpers are also needed to accept a paddr instead of
a sector_ptr pointer.

Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 fs/btrfs/raid56.c | 276 +++++++++++++++++++++-------------------------
 fs/btrfs/raid56.h |  14 +--
 2 files changed, 127 insertions(+), 163 deletions(-)

diff --git a/fs/btrfs/raid56.c b/fs/btrfs/raid56.c
index 77ff1ac29886..75a24fbfbe38 100644
--- a/fs/btrfs/raid56.c
+++ b/fs/btrfs/raid56.c
@@ -139,20 +139,6 @@ struct btrfs_stripe_hash_table {
  */
 #define INVALID_PADDR	(~(phys_addr_t)0)
 
-/*
- * A structure to present a sector inside a page, the length is fixed to
- * sectorsize;
- */
-struct sector_ptr {
-	/*
-	 * Blocks from the bio list can still be highmem.
-	 * So here we use physical address to present a page and the offset inside it.
-	 *
-	 * If it's INVALID_PADDR then it's not set.
-	 */
-	phys_addr_t paddr;
-};
-
 static void rmw_rbio_work(struct work_struct *work);
 static void rmw_rbio_work_locked(struct work_struct *work);
 static void index_rbio_pages(struct btrfs_raid_bio *rbio);
@@ -165,8 +151,8 @@ static void free_raid_bio_pointers(struct btrfs_raid_bio *rbio)
 {
 	bitmap_free(rbio->error_bitmap);
 	kfree(rbio->stripe_pages);
-	kfree(rbio->bio_sectors);
-	kfree(rbio->stripe_sectors);
+	kfree(rbio->bio_paddrs);
+	kfree(rbio->stripe_paddrs);
 	kfree(rbio->finish_pointers);
 }
 
@@ -241,12 +227,17 @@ int btrfs_alloc_stripe_hash_table(struct btrfs_fs_info *info)
 	return 0;
 }
 
-static void memcpy_sectors(const struct sector_ptr *dst,
-			   const struct sector_ptr *src, u32 blocksize)
+static void memcpy_from_bio_to_stripe(struct btrfs_raid_bio *rbio, unsigned int sector_nr)
 {
-	memcpy_page(phys_to_page(dst->paddr), offset_in_page(dst->paddr),
-		    phys_to_page(src->paddr), offset_in_page(src->paddr),
-		    blocksize);
+	phys_addr_t dst = rbio->stripe_paddrs[sector_nr];
+	phys_addr_t src = rbio->bio_paddrs[sector_nr];
+
+	ASSERT(dst != INVALID_PADDR);
+	ASSERT(src != INVALID_PADDR);
+
+	memcpy_page(phys_to_page(dst), offset_in_page(dst),
+		    phys_to_page(src), offset_in_page(src),
+		    rbio->bioc->fs_info->sectorsize);
 }
 
 /*
@@ -269,7 +260,7 @@ static void cache_rbio_pages(struct btrfs_raid_bio *rbio)
 
 	for (i = 0; i < rbio->nr_sectors; i++) {
 		/* Some range not covered by bio (partial write), skip it */
-		if (rbio->bio_sectors[i].paddr == INVALID_PADDR) {
+		if (rbio->bio_paddrs[i] == INVALID_PADDR) {
 			/*
 			 * Even if the sector is not covered by bio, if it is
 			 * a data sector it should still be uptodate as it is
@@ -280,8 +271,7 @@ static void cache_rbio_pages(struct btrfs_raid_bio *rbio)
 			continue;
 		}
 
-		memcpy_sectors(&rbio->stripe_sectors[i], &rbio->bio_sectors[i],
-				rbio->bioc->fs_info->sectorsize);
+		memcpy_from_bio_to_stripe(rbio, i);
 		set_bit(i, rbio->stripe_uptodate_bitmap);
 	}
 	set_bit(RBIO_CACHE_READY_BIT, &rbio->flags);
@@ -341,9 +331,8 @@ static void index_stripe_sectors(struct btrfs_raid_bio *rbio)
 		if (!rbio->stripe_pages[page_index])
 			continue;
 
-		rbio->stripe_sectors[i].paddr =
-			page_to_phys(rbio->stripe_pages[page_index]) +
-			offset_in_page(offset);
+		rbio->stripe_paddrs[i] = page_to_phys(rbio->stripe_pages[page_index] +
+						      offset_in_page(offset));
 	}
 }
 
@@ -689,29 +678,28 @@ static unsigned int rbio_stripe_sector_index(const struct btrfs_raid_bio *rbio,
 	return stripe_nr * rbio->stripe_nsectors + sector_nr;
 }
 
-/* Return a sector from rbio->stripe_sectors, not from the bio list */
-static struct sector_ptr *rbio_stripe_sector(const struct btrfs_raid_bio *rbio,
-					     unsigned int stripe_nr,
-					     unsigned int sector_nr)
+/* Return a paddr from rbio->stripe_sectors, not from the bio list */
+static phys_addr_t rbio_stripe_paddr(const struct btrfs_raid_bio *rbio,
+					    unsigned int stripe_nr,
+					    unsigned int sector_nr)
 {
-	return &rbio->stripe_sectors[rbio_stripe_sector_index(rbio, stripe_nr,
-							      sector_nr)];
+	return rbio->stripe_paddrs[rbio_stripe_sector_index(rbio, stripe_nr, sector_nr)];
 }
 
-/* Grab a sector inside P stripe */
-static struct sector_ptr *rbio_pstripe_sector(const struct btrfs_raid_bio *rbio,
-					      unsigned int sector_nr)
+/* Grab a paddr inside P stripe */
+static phys_addr_t rbio_pstripe_paddr(const struct btrfs_raid_bio *rbio,
+				      unsigned int sector_nr)
 {
-	return rbio_stripe_sector(rbio, rbio->nr_data, sector_nr);
+	return rbio_stripe_paddr(rbio, rbio->nr_data, sector_nr);
 }
 
-/* Grab a sector inside Q stripe, return NULL if not RAID6 */
-static struct sector_ptr *rbio_qstripe_sector(const struct btrfs_raid_bio *rbio,
-					      unsigned int sector_nr)
+/* Grab a paddr inside Q stripe, return INVALID_PADDR if not RAID6 */
+static phys_addr_t rbio_qstripe_paddr(const struct btrfs_raid_bio *rbio,
+				      unsigned int sector_nr)
 {
 	if (rbio->nr_data + 1 == rbio->real_stripes)
-		return NULL;
-	return rbio_stripe_sector(rbio, rbio->nr_data + 1, sector_nr);
+		return INVALID_PADDR;
+	return rbio_stripe_paddr(rbio, rbio->nr_data + 1, sector_nr);
 }
 
 /*
@@ -946,7 +934,7 @@ static void rbio_orig_end_io(struct btrfs_raid_bio *rbio, blk_status_t status)
 }
 
 /*
- * Get a sector pointer specified by its @stripe_nr and @sector_nr.
+ * Get the paddr specified by its @stripe_nr and @sector_nr.
  *
  * @rbio:               The raid bio
  * @stripe_nr:          Stripe number, valid range [0, real_stripe)
@@ -957,11 +945,11 @@ static void rbio_orig_end_io(struct btrfs_raid_bio *rbio, blk_status_t status)
  * The read/modify/write code wants to reuse the original bio page as much
  * as possible, and only use stripe_sectors as fallback.
  */
-static struct sector_ptr *sector_in_rbio(struct btrfs_raid_bio *rbio,
-					 int stripe_nr, int sector_nr,
-					 bool bio_list_only)
+static phys_addr_t sector_paddr_in_rbio(struct btrfs_raid_bio *rbio,
+					int stripe_nr, int sector_nr,
+					bool bio_list_only)
 {
-	struct sector_ptr *sector;
+	phys_addr_t ret = INVALID_PADDR;
 	int index;
 
 	ASSERT_RBIO_STRIPE(stripe_nr >= 0 && stripe_nr < rbio->real_stripes,
@@ -973,17 +961,16 @@ static struct sector_ptr *sector_in_rbio(struct btrfs_raid_bio *rbio,
 	ASSERT(index >= 0 && index < rbio->nr_sectors);
 
 	spin_lock(&rbio->bio_list_lock);
-	sector = &rbio->bio_sectors[index];
-	if (sector->paddr != INVALID_PADDR || bio_list_only) {
+	if (rbio->bio_paddrs[index] != INVALID_PADDR || bio_list_only) {
 		/* Don't return sector without a valid page pointer */
-		if (sector->paddr == INVALID_PADDR)
-			sector = NULL;
+		if (rbio->bio_paddrs[index] != INVALID_PADDR)
+			ret = rbio->bio_paddrs[index];
 		spin_unlock(&rbio->bio_list_lock);
-		return sector;
+		return ret;
 	}
 	spin_unlock(&rbio->bio_list_lock);
 
-	return &rbio->stripe_sectors[index];
+	return rbio->stripe_paddrs[index];
 }
 
 /*
@@ -1021,23 +1008,21 @@ static struct btrfs_raid_bio *alloc_rbio(struct btrfs_fs_info *fs_info,
 		return ERR_PTR(-ENOMEM);
 	rbio->stripe_pages = kcalloc(num_pages, sizeof(struct page *),
 				     GFP_NOFS);
-	rbio->bio_sectors = kcalloc(num_sectors, sizeof(struct sector_ptr),
-				    GFP_NOFS);
-	rbio->stripe_sectors = kcalloc(num_sectors, sizeof(struct sector_ptr),
-				       GFP_NOFS);
+	rbio->bio_paddrs = kcalloc(num_sectors, sizeof(phys_addr_t), GFP_NOFS);
+	rbio->stripe_paddrs = kcalloc(num_sectors, sizeof(phys_addr_t), GFP_NOFS);
 	rbio->finish_pointers = kcalloc(real_stripes, sizeof(void *), GFP_NOFS);
 	rbio->error_bitmap = bitmap_zalloc(num_sectors, GFP_NOFS);
 	rbio->stripe_uptodate_bitmap = bitmap_zalloc(num_sectors, GFP_NOFS);
 
-	if (!rbio->stripe_pages || !rbio->bio_sectors || !rbio->stripe_sectors ||
+	if (!rbio->stripe_pages || !rbio->bio_paddrs || !rbio->stripe_paddrs ||
 	    !rbio->finish_pointers || !rbio->error_bitmap || !rbio->stripe_uptodate_bitmap) {
 		free_raid_bio_pointers(rbio);
 		kfree(rbio);
 		return ERR_PTR(-ENOMEM);
 	}
 	for (int i = 0; i < num_sectors; i++) {
-		rbio->stripe_sectors[i].paddr = INVALID_PADDR;
-		rbio->bio_sectors[i].paddr = INVALID_PADDR;
+		rbio->stripe_paddrs[i] = INVALID_PADDR;
+		rbio->bio_paddrs[i] = INVALID_PADDR;
 	}
 
 	bio_list_init(&rbio->bio_list);
@@ -1136,12 +1121,12 @@ static int get_rbio_veritical_errors(struct btrfs_raid_bio *rbio, int sector_nr,
  * Return 0 if everything went well.
  * Return <0 for error.
  */
-static int rbio_add_io_sector(struct btrfs_raid_bio *rbio,
-			      struct bio_list *bio_list,
-			      struct sector_ptr *sector,
-			      unsigned int stripe_nr,
-			      unsigned int sector_nr,
-			      enum req_op op)
+static int rbio_add_io_paddr(struct btrfs_raid_bio *rbio,
+			     struct bio_list *bio_list,
+			     phys_addr_t paddr,
+			     unsigned int stripe_nr,
+			     unsigned int sector_nr,
+			     enum req_op op)
 {
 	const u32 sectorsize = rbio->bioc->fs_info->sectorsize;
 	struct bio *last = bio_list->tail;
@@ -1159,7 +1144,7 @@ static int rbio_add_io_sector(struct btrfs_raid_bio *rbio,
 			   rbio, stripe_nr);
 	ASSERT_RBIO_SECTOR(sector_nr >= 0 && sector_nr < rbio->stripe_nsectors,
 			   rbio, sector_nr);
-	ASSERT(sector->paddr != INVALID_PADDR);
+	ASSERT(paddr != INVALID_PADDR);
 
 	stripe = &rbio->bioc->stripes[stripe_nr];
 	disk_start = stripe->physical + sector_nr * sectorsize;
@@ -1190,8 +1175,8 @@ static int rbio_add_io_sector(struct btrfs_raid_bio *rbio,
 		 */
 		if (last_end == disk_start && !last->bi_status &&
 		    last->bi_bdev == stripe->dev->bdev) {
-			ret = bio_add_page(last, phys_to_page(sector->paddr),
-					   sectorsize, offset_in_page(sector->paddr));
+			ret = bio_add_page(last, phys_to_page(paddr), sectorsize,
+					   offset_in_page(paddr));
 			if (ret == sectorsize)
 				return 0;
 		}
@@ -1204,8 +1189,7 @@ static int rbio_add_io_sector(struct btrfs_raid_bio *rbio,
 	bio->bi_iter.bi_sector = disk_start >> SECTOR_SHIFT;
 	bio->bi_private = rbio;
 
-	__bio_add_page(bio, phys_to_page(sector->paddr), sectorsize,
-		       offset_in_page(sector->paddr));
+	__bio_add_page(bio, phys_to_page(paddr), sectorsize, offset_in_page(paddr));
 	bio_list_add(bio_list, bio);
 	return 0;
 }
@@ -1221,9 +1205,8 @@ static void index_one_bio(struct btrfs_raid_bio *rbio, struct bio *bio)
 
 	btrfs_bio_for_each_block(paddr, bio, &iter, sectorsize) {
 		unsigned int index = (offset >> sectorsize_bits);
-		struct sector_ptr *sector = &rbio->bio_sectors[index];
 
-		sector->paddr = paddr;
+		rbio->bio_paddrs[index] = paddr;
 		offset += sectorsize;
 	}
 }
@@ -1302,13 +1285,12 @@ static void assert_rbio(struct btrfs_raid_bio *rbio)
 	ASSERT_RBIO(rbio->nr_data < rbio->real_stripes, rbio);
 }
 
-static inline void *kmap_local_sector(const struct sector_ptr *sector)
+static inline void *kmap_local_paddr(phys_addr_t paddr)
 {
 	/* The sector pointer must have a page mapped to it. */
-	ASSERT(sector->paddr != INVALID_PADDR);
+	ASSERT(paddr != INVALID_PADDR);
 
-	return kmap_local_page(phys_to_page(sector->paddr)) +
-	       offset_in_page(sector->paddr);
+	return kmap_local_page(phys_to_page(paddr)) + offset_in_page(paddr);
 }
 
 /* Generate PQ for one vertical stripe. */
@@ -1316,31 +1298,27 @@ static void generate_pq_vertical(struct btrfs_raid_bio *rbio, int sectornr)
 {
 	void **pointers = rbio->finish_pointers;
 	const u32 sectorsize = rbio->bioc->fs_info->sectorsize;
-	struct sector_ptr *sector;
 	int stripe;
 	const bool has_qstripe = rbio->bioc->map_type & BTRFS_BLOCK_GROUP_RAID6;
 
 	/* First collect one sector from each data stripe */
-	for (stripe = 0; stripe < rbio->nr_data; stripe++) {
-		sector = sector_in_rbio(rbio, stripe, sectornr, 0);
-		pointers[stripe] = kmap_local_sector(sector);
-	}
+	for (stripe = 0; stripe < rbio->nr_data; stripe++)
+		pointers[stripe] = kmap_local_paddr(
+				sector_paddr_in_rbio(rbio, stripe, sectornr, 0));
 
 	/* Then add the parity stripe */
-	sector = rbio_pstripe_sector(rbio, sectornr);
 	set_bit(rbio_stripe_sector_index(rbio, rbio->nr_data, sectornr),
 		rbio->stripe_uptodate_bitmap);
-	pointers[stripe++] = kmap_local_sector(sector);
+	pointers[stripe++] = kmap_local_paddr(rbio_pstripe_paddr(rbio, sectornr));
 
 	if (has_qstripe) {
 		/*
 		 * RAID6, add the qstripe and call the library function
 		 * to fill in our p/q
 		 */
-		sector = rbio_qstripe_sector(rbio, sectornr);
 		set_bit(rbio_stripe_sector_index(rbio, rbio->nr_data + 1, sectornr),
 			rbio->stripe_uptodate_bitmap);
-		pointers[stripe++] = kmap_local_sector(sector);
+		pointers[stripe++] = kmap_local_paddr(rbio_qstripe_paddr(rbio, sectornr));
 
 		assert_rbio(rbio);
 		raid6_call.gen_syndrome(rbio->real_stripes, sectorsize,
@@ -1380,7 +1358,7 @@ static int rmw_assemble_write_bios(struct btrfs_raid_bio *rbio,
 	 */
 	for (total_sector_nr = 0; total_sector_nr < rbio->nr_sectors;
 	     total_sector_nr++) {
-		struct sector_ptr *sector;
+		phys_addr_t paddr;
 
 		stripe = total_sector_nr / rbio->stripe_nsectors;
 		sectornr = total_sector_nr % rbio->stripe_nsectors;
@@ -1390,15 +1368,15 @@ static int rmw_assemble_write_bios(struct btrfs_raid_bio *rbio,
 			continue;
 
 		if (stripe < rbio->nr_data) {
-			sector = sector_in_rbio(rbio, stripe, sectornr, 1);
-			if (!sector)
+			paddr = sector_paddr_in_rbio(rbio, stripe, sectornr, 1);
+			if (paddr == INVALID_PADDR)
 				continue;
 		} else {
-			sector = rbio_stripe_sector(rbio, stripe, sectornr);
+			paddr = rbio_stripe_paddr(rbio, stripe, sectornr);
 		}
 
-		ret = rbio_add_io_sector(rbio, bio_list, sector, stripe,
-					 sectornr, REQ_OP_WRITE);
+		ret = rbio_add_io_paddr(rbio, bio_list, paddr, stripe,
+					sectornr, REQ_OP_WRITE);
 		if (ret)
 			goto error;
 	}
@@ -1415,7 +1393,7 @@ static int rmw_assemble_write_bios(struct btrfs_raid_bio *rbio,
 
 	for (total_sector_nr = 0; total_sector_nr < rbio->nr_sectors;
 	     total_sector_nr++) {
-		struct sector_ptr *sector;
+		phys_addr_t paddr;
 
 		stripe = total_sector_nr / rbio->stripe_nsectors;
 		sectornr = total_sector_nr % rbio->stripe_nsectors;
@@ -1440,14 +1418,14 @@ static int rmw_assemble_write_bios(struct btrfs_raid_bio *rbio,
 			continue;
 
 		if (stripe < rbio->nr_data) {
-			sector = sector_in_rbio(rbio, stripe, sectornr, 1);
-			if (!sector)
+			paddr = sector_paddr_in_rbio(rbio, stripe, sectornr, 1);
+			if (paddr == INVALID_PADDR)
 				continue;
 		} else {
-			sector = rbio_stripe_sector(rbio, stripe, sectornr);
+			paddr = rbio_stripe_paddr(rbio, stripe, sectornr);
 		}
 
-		ret = rbio_add_io_sector(rbio, bio_list, sector,
+		ret = rbio_add_io_paddr(rbio, bio_list, paddr,
 					 rbio->real_stripes,
 					 sectornr, REQ_OP_WRITE);
 		if (ret)
@@ -1503,9 +1481,7 @@ static int find_stripe_sector_nr(struct btrfs_raid_bio *rbio,
 				 phys_addr_t paddr)
 {
 	for (int i = 0; i < rbio->nr_sectors; i++) {
-		struct sector_ptr *sector = &rbio->stripe_sectors[i];
-
-		if (sector->paddr == paddr)
+		if (rbio->stripe_paddrs[i] == paddr)
 			return i;
 	}
 	return -1;
@@ -1537,9 +1513,9 @@ static int get_bio_sector_nr(struct btrfs_raid_bio *rbio, struct bio *bio)
 	int i;
 
 	for (i = 0; i < rbio->nr_sectors; i++) {
-		if (rbio->stripe_sectors[i].paddr == bvec_paddr)
+		if (rbio->stripe_paddrs[i] == bvec_paddr)
 			break;
-		if (rbio->bio_sectors[i].paddr == bvec_paddr)
+		if (rbio->bio_paddrs[i] == bvec_paddr)
 			break;
 	}
 	ASSERT(i < rbio->nr_sectors);
@@ -1791,7 +1767,7 @@ static int verify_one_sector(struct btrfs_raid_bio *rbio,
 			     int stripe_nr, int sector_nr)
 {
 	struct btrfs_fs_info *fs_info = rbio->bioc->fs_info;
-	struct sector_ptr *sector;
+	phys_addr_t paddr;
 	u8 csum_buf[BTRFS_CSUM_SIZE];
 	u8 *csum_expected;
 	int ret;
@@ -1807,15 +1783,15 @@ static int verify_one_sector(struct btrfs_raid_bio *rbio,
 	 * bio list if possible.
 	 */
 	if (rbio->operation == BTRFS_RBIO_READ_REBUILD) {
-		sector = sector_in_rbio(rbio, stripe_nr, sector_nr, 0);
+		paddr = sector_paddr_in_rbio(rbio, stripe_nr, sector_nr, 0);
 	} else {
-		sector = rbio_stripe_sector(rbio, stripe_nr, sector_nr);
+		paddr = rbio_stripe_paddr(rbio, stripe_nr, sector_nr);
 	}
 
 	csum_expected = rbio->csum_buf +
 			(stripe_nr * rbio->stripe_nsectors + sector_nr) *
 			fs_info->csum_size;
-	ret = btrfs_check_block_csum(fs_info, sector->paddr, csum_buf, csum_expected);
+	ret = btrfs_check_block_csum(fs_info, paddr, csum_buf, csum_expected);
 	return ret;
 }
 
@@ -1828,7 +1804,6 @@ static int recover_vertical(struct btrfs_raid_bio *rbio, int sector_nr,
 			    void **pointers, void **unmap_array)
 {
 	struct btrfs_fs_info *fs_info = rbio->bioc->fs_info;
-	struct sector_ptr *sector;
 	const u32 sectorsize = fs_info->sectorsize;
 	int found_errors;
 	int faila;
@@ -1863,16 +1838,18 @@ static int recover_vertical(struct btrfs_raid_bio *rbio, int sector_nr,
 	 * pointer order.
 	 */
 	for (stripe_nr = 0; stripe_nr < rbio->real_stripes; stripe_nr++) {
+		phys_addr_t paddr;
+
 		/*
 		 * If we're rebuilding a read, we have to use pages from the
 		 * bio list if possible.
 		 */
 		if (rbio->operation == BTRFS_RBIO_READ_REBUILD) {
-			sector = sector_in_rbio(rbio, stripe_nr, sector_nr, 0);
+			paddr = sector_paddr_in_rbio(rbio, stripe_nr, sector_nr, 0);
 		} else {
-			sector = rbio_stripe_sector(rbio, stripe_nr, sector_nr);
+			paddr = rbio_stripe_paddr(rbio, stripe_nr, sector_nr);
 		}
-		pointers[stripe_nr] = kmap_local_sector(sector);
+		pointers[stripe_nr] = kmap_local_paddr(paddr);
 		unmap_array[stripe_nr] = pointers[stripe_nr];
 	}
 
@@ -1960,7 +1937,6 @@ static int recover_vertical(struct btrfs_raid_bio *rbio, int sector_nr,
 		if (ret < 0)
 			goto cleanup;
 
-		sector = rbio_stripe_sector(rbio, faila, sector_nr);
 		set_bit(rbio_stripe_sector_index(rbio, faila, sector_nr),
 			rbio->stripe_uptodate_bitmap);
 	}
@@ -1969,7 +1945,6 @@ static int recover_vertical(struct btrfs_raid_bio *rbio, int sector_nr,
 		if (ret < 0)
 			goto cleanup;
 
-		sector = rbio_stripe_sector(rbio, failb, sector_nr);
 		set_bit(rbio_stripe_sector_index(rbio, failb, sector_nr),
 			rbio->stripe_uptodate_bitmap);
 	}
@@ -2051,7 +2026,7 @@ static void recover_rbio(struct btrfs_raid_bio *rbio)
 	     total_sector_nr++) {
 		int stripe = total_sector_nr / rbio->stripe_nsectors;
 		int sectornr = total_sector_nr % rbio->stripe_nsectors;
-		struct sector_ptr *sector;
+		phys_addr_t paddr;
 
 		/*
 		 * Skip the range which has error.  It can be a range which is
@@ -2068,8 +2043,8 @@ static void recover_rbio(struct btrfs_raid_bio *rbio)
 			continue;
 		}
 
-		sector = rbio_stripe_sector(rbio, stripe, sectornr);
-		ret = rbio_add_io_sector(rbio, &bio_list, sector, stripe,
+		paddr = rbio_stripe_paddr(rbio, stripe, sectornr);
+		ret = rbio_add_io_paddr(rbio, &bio_list, paddr, stripe,
 					 sectornr, REQ_OP_READ);
 		if (ret < 0) {
 			bio_list_put(&bio_list);
@@ -2258,12 +2233,12 @@ static int rmw_read_wait_recover(struct btrfs_raid_bio *rbio)
 	 */
 	for (total_sector_nr = 0; total_sector_nr < rbio->nr_sectors;
 	     total_sector_nr++) {
-		struct sector_ptr *sector;
 		int stripe = total_sector_nr / rbio->stripe_nsectors;
 		int sectornr = total_sector_nr % rbio->stripe_nsectors;
+		phys_addr_t paddr;
 
-		sector = rbio_stripe_sector(rbio, stripe, sectornr);
-		ret = rbio_add_io_sector(rbio, &bio_list, sector,
+		paddr = rbio_stripe_paddr(rbio, stripe, sectornr);
+		ret = rbio_add_io_paddr(rbio, &bio_list, paddr,
 			       stripe, sectornr, REQ_OP_READ);
 		if (ret) {
 			bio_list_put(&bio_list);
@@ -2318,14 +2293,14 @@ static bool need_read_stripe_sectors(struct btrfs_raid_bio *rbio)
 	int i;
 
 	for (i = 0; i < rbio->nr_data * rbio->stripe_nsectors; i++) {
-		struct sector_ptr *sector = &rbio->stripe_sectors[i];
+		phys_addr_t paddr = rbio->stripe_paddrs[i];
 
 		/*
 		 * We have a sector which doesn't have page nor uptodate,
 		 * thus this rbio can not be cached one, as cached one must
 		 * have all its data sectors present and uptodate.
 		 */
-		if (sector->paddr == INVALID_PADDR ||
+		if (paddr == INVALID_PADDR ||
 		    !test_bit(i, rbio->stripe_uptodate_bitmap))
 			return true;
 	}
@@ -2517,8 +2492,8 @@ static int finish_parity_scrub(struct btrfs_raid_bio *rbio)
 	int sectornr;
 	bool has_qstripe;
 	struct page *page;
-	struct sector_ptr p_sector = { .paddr = INVALID_PADDR };
-	struct sector_ptr q_sector = { .paddr = INVALID_PADDR };
+	phys_addr_t p_paddr = INVALID_PADDR;
+	phys_addr_t q_paddr = INVALID_PADDR;
 	struct bio_list bio_list;
 	int is_replace = 0;
 	int ret;
@@ -2551,36 +2526,34 @@ static int finish_parity_scrub(struct btrfs_raid_bio *rbio)
 	page = alloc_page(GFP_NOFS);
 	if (!page)
 		return -ENOMEM;
-	p_sector.paddr = page_to_phys(page);
+	p_paddr = page_to_phys(page);
 	page = NULL;
+	pointers[nr_data] = kmap_local_paddr(p_paddr);
 
 	if (has_qstripe) {
 		/* RAID6, allocate and map temp space for the Q stripe */
 		page = alloc_page(GFP_NOFS);
 		if (!page) {
-			__free_page(phys_to_page(p_sector.paddr));
-			p_sector.paddr = INVALID_PADDR;
+			__free_page(phys_to_page(p_paddr));
+			p_paddr = INVALID_PADDR;
 			return -ENOMEM;
 		}
-		q_sector.paddr = page_to_phys(page);
+		q_paddr = page_to_phys(page);
 		page = NULL;
-		pointers[rbio->real_stripes - 1] = kmap_local_sector(&q_sector);
+		pointers[rbio->real_stripes - 1] = kmap_local_paddr(q_paddr);
 	}
 
 	bitmap_clear(rbio->error_bitmap, 0, rbio->nr_sectors);
 
 	/* Map the parity stripe just once */
-	pointers[nr_data] = kmap_local_sector(&p_sector);
 
 	for_each_set_bit(sectornr, &rbio->dbitmap, rbio->stripe_nsectors) {
-		struct sector_ptr *sector;
 		void *parity;
 
 		/* first collect one page from each data stripe */
-		for (stripe = 0; stripe < nr_data; stripe++) {
-			sector = sector_in_rbio(rbio, stripe, sectornr, 0);
-			pointers[stripe] = kmap_local_sector(sector);
-		}
+		for (stripe = 0; stripe < nr_data; stripe++)
+			pointers[stripe] = kmap_local_paddr(
+					sector_paddr_in_rbio(rbio, stripe, sectornr, 0));
 
 		if (has_qstripe) {
 			assert_rbio(rbio);
@@ -2594,8 +2567,7 @@ static int finish_parity_scrub(struct btrfs_raid_bio *rbio)
 		}
 
 		/* Check scrubbing parity and repair it */
-		sector = rbio_stripe_sector(rbio, rbio->scrubp, sectornr);
-		parity = kmap_local_sector(sector);
+		parity = kmap_local_paddr(rbio_stripe_paddr(rbio, rbio->scrubp, sectornr));
 		if (memcmp(parity, pointers[rbio->scrubp], sectorsize) != 0)
 			memcpy(parity, pointers[rbio->scrubp], sectorsize);
 		else
@@ -2608,11 +2580,11 @@ static int finish_parity_scrub(struct btrfs_raid_bio *rbio)
 	}
 
 	kunmap_local(pointers[nr_data]);
-	__free_page(phys_to_page(p_sector.paddr));
-	p_sector.paddr = INVALID_PADDR;
-	if (q_sector.paddr != INVALID_PADDR) {
-		__free_page(phys_to_page(q_sector.paddr));
-		q_sector.paddr = INVALID_PADDR;
+	__free_page(phys_to_page(p_paddr));
+	p_paddr = INVALID_PADDR;
+	if (q_paddr != INVALID_PADDR) {
+		__free_page(phys_to_page(q_paddr));
+		q_paddr = INVALID_PADDR;
 	}
 
 	/*
@@ -2621,10 +2593,10 @@ static int finish_parity_scrub(struct btrfs_raid_bio *rbio)
 	 * everything else.
 	 */
 	for_each_set_bit(sectornr, &rbio->dbitmap, rbio->stripe_nsectors) {
-		struct sector_ptr *sector;
+		phys_addr_t paddr;
 
-		sector = rbio_stripe_sector(rbio, rbio->scrubp, sectornr);
-		ret = rbio_add_io_sector(rbio, &bio_list, sector, rbio->scrubp,
+		paddr = rbio_stripe_paddr(rbio, rbio->scrubp, sectornr);
+		ret = rbio_add_io_paddr(rbio, &bio_list, paddr, rbio->scrubp,
 					 sectornr, REQ_OP_WRITE);
 		if (ret)
 			goto cleanup;
@@ -2639,10 +2611,10 @@ static int finish_parity_scrub(struct btrfs_raid_bio *rbio)
 	 */
 	ASSERT_RBIO(rbio->bioc->replace_stripe_src >= 0, rbio);
 	for_each_set_bit(sectornr, pbitmap, rbio->stripe_nsectors) {
-		struct sector_ptr *sector;
+		phys_addr_t paddr;
 
-		sector = rbio_stripe_sector(rbio, rbio->scrubp, sectornr);
-		ret = rbio_add_io_sector(rbio, &bio_list, sector,
+		paddr = rbio_stripe_paddr(rbio, rbio->scrubp, sectornr);
+		ret = rbio_add_io_paddr(rbio, &bio_list, paddr,
 					 rbio->real_stripes,
 					 sectornr, REQ_OP_WRITE);
 		if (ret)
@@ -2760,7 +2732,7 @@ static int scrub_assemble_read_bios(struct btrfs_raid_bio *rbio)
 	     total_sector_nr++) {
 		int sectornr = total_sector_nr % rbio->stripe_nsectors;
 		int stripe = total_sector_nr / rbio->stripe_nsectors;
-		struct sector_ptr *sector;
+		phys_addr_t paddr;
 
 		/* No data in the vertical stripe, no need to read. */
 		if (!test_bit(sectornr, &rbio->dbitmap))
@@ -2768,14 +2740,14 @@ static int scrub_assemble_read_bios(struct btrfs_raid_bio *rbio)
 
 		/*
 		 * We want to find all the sectors missing from the rbio and
-		 * read them from the disk. If sector_in_rbio() finds a sector
+		 * read them from the disk. If sector_paddr_in_rbio() finds a sector
 		 * in the bio list we don't need to read it off the stripe.
 		 */
-		sector = sector_in_rbio(rbio, stripe, sectornr, 1);
-		if (sector)
+		paddr = sector_paddr_in_rbio(rbio, stripe, sectornr, 1);
+		if (paddr == INVALID_PADDR)
 			continue;
 
-		sector = rbio_stripe_sector(rbio, stripe, sectornr);
+		paddr = rbio_stripe_paddr(rbio, stripe, sectornr);
 		/*
 		 * The bio cache may have handed us an uptodate sector.  If so,
 		 * use it.
@@ -2784,7 +2756,7 @@ static int scrub_assemble_read_bios(struct btrfs_raid_bio *rbio)
 			     rbio->stripe_uptodate_bitmap))
 			continue;
 
-		ret = rbio_add_io_sector(rbio, &bio_list, sector, stripe,
+		ret = rbio_add_io_paddr(rbio, &bio_list, paddr, stripe,
 					 sectornr, REQ_OP_READ);
 		if (ret) {
 			bio_list_put(&bio_list);
diff --git a/fs/btrfs/raid56.h b/fs/btrfs/raid56.h
index b636de4af7ac..42a45716fb03 100644
--- a/fs/btrfs/raid56.h
+++ b/fs/btrfs/raid56.h
@@ -16,7 +16,6 @@
 #include "volumes.h"
 
 struct page;
-struct sector_ptr;
 struct btrfs_fs_info;
 
 enum btrfs_rbio_ops {
@@ -116,13 +115,10 @@ struct btrfs_raid_bio {
 	struct page **stripe_pages;
 
 	/* Pointers to the sectors in the bio_list, for faster lookup */
-	struct sector_ptr *bio_sectors;
+	phys_addr_t *bio_paddrs;
 
-	/*
-	 * For subpage support, we need to map each sector to above
-	 * stripe_pages.
-	 */
-	struct sector_ptr *stripe_sectors;
+	/* Pointers to the sectors in the stripe_pages[]. */
+	phys_addr_t *stripe_paddrs;
 
 	/* Each set bit means the corresponding sector in stripe_sectors[] is uptodate. */
 	unsigned long *stripe_uptodate_bitmap;
@@ -134,10 +130,6 @@ struct btrfs_raid_bio {
 	 * The bitmap recording where IO errors happened.
 	 * Each bit is corresponding to one sector in either bio_sectors[] or
 	 * stripe_sectors[] array.
-	 *
-	 * The reason we don't use another bit in sector_ptr is, we have two
-	 * arrays of sectors, and a lot of IO can use sectors in both arrays.
-	 * Thus making it much harder to iterate.
 	 */
 	unsigned long *error_bitmap;
 
-- 
2.50.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH 0/3] btrfs: reduce memory usage for btrfs_raid_bio structure
  2025-10-09  4:39 [PATCH 0/3] btrfs: reduce memory usage for btrfs_raid_bio structure Qu Wenruo
                   ` (2 preceding siblings ...)
  2025-10-09  4:40 ` [PATCH 3/3] btrfs: raid56: remove sector_ptr structure Qu Wenruo
@ 2025-11-10 22:58 ` Qu Wenruo
  2025-11-11 13:11   ` David Sterba
  3 siblings, 1 reply; 6+ messages in thread
From: Qu Wenruo @ 2025-11-10 22:58 UTC (permalink / raw)
  To: linux-btrfs



在 2025/10/9 15:09, Qu Wenruo 写道:
> This series replace the following members of btrfs_raid_bio:
> 
> 	struct sector_ptr bio_sectors[nr_sectors]
> 	struct sector_ptr stripe_sectors[nr_sectors]
> 
> To the following ones:
> 
> 	phys_addr_t bio_sectors[nr_sectors]
> 	phys_addr_t stripe_sectors[nr_sectors]
> 	unsigned long uptodate_bitmap[nr_sectors]
> 
> For x86_64 (4K page size) with the fixed 64K stripe size and 3 disks, the
> memory usage of those members (not the full structure) will be reduced from:
> 
> 	8 * 2 + 48 * 16 * 2 = 1552
> 
> To
> 	8 * 3 + 48 * 8 * 2 + 8 * 2 = 808
> 
> Almost halved the memory usage.

A gentle ping.

Any feedback? Further bs > ps enablement relies on this as the first step.

Thanks,
Qu

> 
> The memory saving comes from:
> 
> - Compat sector_ptr::uptodate bit into a bitmap
>    This not only saves space, but also allow us to call bitmap_*()
>    helpers when we need to set multiple bits in one go (mostly for
>    subpage cases)
> 
> - Remove sector_ptr::uptodate flag
>    We can use a special paddr (not NULL though) to indicate if the paddr
>    is valid or not.
> 
> - Get rid of sector_ptr
>    That structure has extra bits that take a full byte for each flag.
>    This is the biggest space saving.
> 
> Qu Wenruo (3):
>    btrfs: raid56: remove sector_ptr::has_paddr member
>    btrfs: raid56: move sector_ptr::uptodate into a dedicated bitmap
>    btrfs: raid56: remove sector_ptr structure
> 
>   fs/btrfs/raid56.c | 347 ++++++++++++++++++++++------------------------
>   fs/btrfs/raid56.h |  17 +--
>   2 files changed, 168 insertions(+), 196 deletions(-)
> 


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 0/3] btrfs: reduce memory usage for btrfs_raid_bio structure
  2025-11-10 22:58 ` [PATCH 0/3] btrfs: reduce memory usage for btrfs_raid_bio structure Qu Wenruo
@ 2025-11-11 13:11   ` David Sterba
  0 siblings, 0 replies; 6+ messages in thread
From: David Sterba @ 2025-11-11 13:11 UTC (permalink / raw)
  To: Qu Wenruo; +Cc: linux-btrfs

On Tue, Nov 11, 2025 at 09:28:18AM +1030, Qu Wenruo wrote:
> 
> 
> 在 2025/10/9 15:09, Qu Wenruo 写道:
> > This series replace the following members of btrfs_raid_bio:
> > 
> > 	struct sector_ptr bio_sectors[nr_sectors]
> > 	struct sector_ptr stripe_sectors[nr_sectors]
> > 
> > To the following ones:
> > 
> > 	phys_addr_t bio_sectors[nr_sectors]
> > 	phys_addr_t stripe_sectors[nr_sectors]
> > 	unsigned long uptodate_bitmap[nr_sectors]
> > 
> > For x86_64 (4K page size) with the fixed 64K stripe size and 3 disks, the
> > memory usage of those members (not the full structure) will be reduced from:
> > 
> > 	8 * 2 + 48 * 16 * 2 = 1552
> > 
> > To
> > 	8 * 3 + 48 * 8 * 2 + 8 * 2 = 808
> > 
> > Almost halved the memory usage.
> 
> A gentle ping.
> 
> Any feedback? Further bs > ps enablement relies on this as the first step.

Sorry I missed this series, please add it to for-next.

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2025-11-11 13:11 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-10-09  4:39 [PATCH 0/3] btrfs: reduce memory usage for btrfs_raid_bio structure Qu Wenruo
2025-10-09  4:39 ` [PATCH 1/3] btrfs: raid56: remove sector_ptr::has_paddr member Qu Wenruo
2025-10-09  4:40 ` [PATCH 2/3] btrfs: raid56: move sector_ptr::uptodate into a dedicated bitmap Qu Wenruo
2025-10-09  4:40 ` [PATCH 3/3] btrfs: raid56: remove sector_ptr structure Qu Wenruo
2025-11-10 22:58 ` [PATCH 0/3] btrfs: reduce memory usage for btrfs_raid_bio structure Qu Wenruo
2025-11-11 13:11   ` David Sterba

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).