Skip to content

Commit f4521b0

Browse files
adam900710kdave
authored andcommitted
btrfs: migrate eb_bitmap_offset() to folio interfaces
[BUG] Test case btrfs/002 would fail if larger folios are enabled for metadata: assertion failed: folio, in fs/btrfs/extent_io.c:4358 ------------[ cut here ]------------ kernel BUG at fs/btrfs/extent_io.c:4358! invalid opcode: 0000 [#1] PREEMPT SMP NOPTI CPU: 1 PID: 30916 Comm: fsstress Tainted: G OE 6.7.0-rc3-custom+ raspberrypi#128 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS unknown 2/2/2022 RIP: 0010:assert_eb_folio_uptodate+0x98/0xe0 [btrfs] Call Trace: <TASK> extent_buffer_test_bit+0x3c/0x70 [btrfs] free_space_test_bit+0xcd/0x140 [btrfs] modify_free_space_bitmap+0x27a/0x430 [btrfs] add_to_free_space_tree+0x8d/0x160 [btrfs] __btrfs_free_extent.isra.0+0xef1/0x13c0 [btrfs] __btrfs_run_delayed_refs+0x786/0x13c0 [btrfs] btrfs_run_delayed_refs+0x33/0x120 [btrfs] btrfs_commit_transaction+0xa2/0x1350 [btrfs] iterate_supers+0x77/0xe0 ksys_sync+0x60/0xa0 __do_sys_sync+0xa/0x20 do_syscall_64+0x3f/0xf0 entry_SYSCALL_64_after_hwframe+0x6e/0x76 </TASK> [CAUSE] The function extent_buffer_test_bit() is not folio compatible. It still assumes the old fixed page size, when an extent buffer with large folio passed in, only eb->folios[0] is populated. Then if the target bit range falls in the 2nd page of the folio, then we would check eb->folios[1], and trigger the ASSERT(). [FIX] Just migrate eb_bitmap_offset() to folio interfaces, using the folio_size() to replace PAGE_SIZE. Signed-off-by: Qu Wenruo <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent a700ca5 commit f4521b0

File tree

1 file changed

+10
-12
lines changed

1 file changed

+10
-12
lines changed

fs/btrfs/extent_io.c

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4459,22 +4459,22 @@ void copy_extent_buffer(const struct extent_buffer *dst,
44594459
}
44604460

44614461
/*
4462-
* Calculate the page and offset of the byte containing the given bit number.
4462+
* Calculate the folio and offset of the byte containing the given bit number.
44634463
*
44644464
* @eb: the extent buffer
44654465
* @start: offset of the bitmap item in the extent buffer
44664466
* @nr: bit number
4467-
* @page_index: return index of the page in the extent buffer that contains
4467+
* @folio_index: return index of the folio in the extent buffer that contains
44684468
* the given bit number
4469-
* @page_offset: return offset into the page given by page_index
4469+
* @folio_offset: return offset into the folio given by folio_index
44704470
*
44714471
* This helper hides the ugliness of finding the byte in an extent buffer which
44724472
* contains a given bit.
44734473
*/
44744474
static inline void eb_bitmap_offset(const struct extent_buffer *eb,
44754475
unsigned long start, unsigned long nr,
4476-
unsigned long *page_index,
4477-
size_t *page_offset)
4476+
unsigned long *folio_index,
4477+
size_t *folio_offset)
44784478
{
44794479
size_t byte_offset = BIT_BYTE(nr);
44804480
size_t offset;
@@ -4484,10 +4484,10 @@ static inline void eb_bitmap_offset(const struct extent_buffer *eb,
44844484
* the bitmap item in the extent buffer + the offset of the byte in the
44854485
* bitmap item.
44864486
*/
4487-
offset = start + offset_in_page(eb->start) + byte_offset;
4487+
offset = start + offset_in_folio(eb->folios[0], eb->start) + byte_offset;
44884488

4489-
*page_index = offset >> PAGE_SHIFT;
4490-
*page_offset = offset_in_page(offset);
4489+
*folio_index = offset >> folio_shift(eb->folios[0]);
4490+
*folio_offset = offset_in_folio(eb->folios[0], offset);
44914491
}
44924492

44934493
/*
@@ -4500,15 +4500,13 @@ static inline void eb_bitmap_offset(const struct extent_buffer *eb,
45004500
int extent_buffer_test_bit(const struct extent_buffer *eb, unsigned long start,
45014501
unsigned long nr)
45024502
{
4503-
u8 *kaddr;
4504-
struct page *page;
45054503
unsigned long i;
45064504
size_t offset;
4505+
u8 *kaddr;
45074506

45084507
eb_bitmap_offset(eb, start, nr, &i, &offset);
4509-
page = folio_page(eb->folios[i], 0);
45104508
assert_eb_folio_uptodate(eb, i);
4511-
kaddr = page_address(page);
4509+
kaddr = folio_address(eb->folios[i]);
45124510
return 1U & (kaddr[offset] >> (nr & (BITS_PER_BYTE - 1)));
45134511
}
45144512

0 commit comments

Comments
 (0)