--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
-@@ -3309,8 +3309,7 @@ void ext4_exit_mballoc(void)
+@@ -3308,8 +3308,7 @@ void ext4_exit_mballoc(void)
* Returns 0 if success or error code
*/
static noinline_for_stack int
{
struct buffer_head *bitmap_bh = NULL;
struct ext4_group_desc *gdp;
-@@ -3397,13 +3396,6 @@ ext4_mb_mark_diskspace_used(struct ext4_
+@@ -3396,13 +3395,6 @@ ext4_mb_mark_diskspace_used(struct ext4_
ext4_unlock_group(sb, ac->ac_b_ex.fe_group);
percpu_counter_sub(&sbi->s_freeclusters_counter, ac->ac_b_ex.fe_len);
if (sbi->s_log_groups_per_flex) {
ext4_group_t flex_group = ext4_flex_group(sbi,
-@@ -5272,7 +5264,7 @@ repeat:
+@@ -5271,7 +5263,7 @@ repeat:
ext4_mb_pa_free(ac);
}
if (likely(ac->ac_status == AC_STATUS_FOUND)) {
if (*errp) {
ext4_discard_allocated_blocks(ac);
goto errout;
-@@ -5304,12 +5296,9 @@ out:
+@@ -5303,12 +5295,9 @@ out:
kmem_cache_free(ext4_ac_cachep, ac);
if (inquota && ar->len < inquota)
dquot_free_block(ar->inode, EXT4_C2B(sbi, inquota - ar->len));
+++ /dev/null
-From stable+bounces-219642-greg=kroah.com@vger.kernel.org Wed Feb 25 15:53:58 2026
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 25 Feb 2026 09:52:28 -0500
-Subject: ext4: fix e4b bitmap inconsistency reports
-To: stable@vger.kernel.org
-Cc: Yongjian Sun <sunyongjian1@huawei.com>, Zhang Yi <yi.zhang@huawei.com>, Baokun Li <libaokun1@huawei.com>, Jan Kara <jack@suse.cz>, Theodore Ts'o <tytso@mit.edu>, stable@kernel.org, Sasha Levin <sashal@kernel.org>
-Message-ID: <20260225145229.546147-1-sashal@kernel.org>
-
-From: Yongjian Sun <sunyongjian1@huawei.com>
-
-[ Upstream commit bdc56a9c46b2a99c12313122b9352b619a2e719e ]
-
-A bitmap inconsistency issue was observed during stress tests under
-mixed huge-page workloads. Ext4 reported multiple e4b bitmap check
-failures like:
-
-ext4_mb_complex_scan_group:2508: group 350, 8179 free clusters as
-per group info. But got 8192 blocks
-
-Analysis and experimentation confirmed that the issue is caused by a
-race condition between page migration and bitmap modification. Although
-this timing window is extremely narrow, it is still hit in practice:
-
-folio_lock ext4_mb_load_buddy
-__migrate_folio
- check ref count
- folio_mc_copy __filemap_get_folio
- folio_try_get(folio)
- ......
- mb_mark_used
- ext4_mb_unload_buddy
- __folio_migrate_mapping
- folio_ref_freeze
-folio_unlock
-
-The root cause of this issue is that the fast path of load_buddy only
-increments the folio's reference count, which is insufficient to prevent
-concurrent folio migration. We observed that the folio migration process
-acquires the folio lock. Therefore, we can determine whether to take the
-fast path in load_buddy by checking the lock status. If the folio is
-locked, we opt for the slow path (which acquires the lock) to close this
-concurrency window.
-
-Additionally, this change addresses the following issues:
-
-When the DOUBLE_CHECK macro is enabled to inspect bitmap-related
-issues, the following error may be triggered:
-
-corruption in group 324 at byte 784(6272): f in copy != ff on
-disk/prealloc
-
-Analysis reveals that this is a false positive. There is a specific race
-window where the bitmap and the group descriptor become momentarily
-inconsistent, leading to this error report:
-
-ext4_mb_load_buddy ext4_mb_load_buddy
- __filemap_get_folio(create|lock)
- folio_lock
- ext4_mb_init_cache
- folio_mark_uptodate
- __filemap_get_folio(no lock)
- ......
- mb_mark_used
- mb_mark_used_double
- mb_cmp_bitmaps
- mb_set_bits(e4b->bd_bitmap)
- folio_unlock
-
-The original logic assumed that since mb_cmp_bitmaps is called when the
-bitmap is newly loaded from disk, the folio lock would be sufficient to
-prevent concurrent access. However, this overlooks a specific race
-condition: if another process attempts to load buddy and finds the folio
-is already in an uptodate state, it will immediately begin using it without
-holding folio lock.
-
-Signed-off-by: Yongjian Sun <sunyongjian1@huawei.com>
-Reviewed-by: Zhang Yi <yi.zhang@huawei.com>
-Reviewed-by: Baokun Li <libaokun1@huawei.com>
-Reviewed-by: Jan Kara <jack@suse.cz>
-Link: https://patch.msgid.link/20260106090820.836242-1-sunyongjian@huaweicloud.com
-Signed-off-by: Theodore Ts'o <tytso@mit.edu>
-Cc: stable@kernel.org
-[ folio -> page ]
-Signed-off-by: Sasha Levin <sashal@kernel.org>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- fs/ext4/mballoc.c | 21 +++++++++++----------
- 1 file changed, 11 insertions(+), 10 deletions(-)
-
---- a/fs/ext4/mballoc.c
-+++ b/fs/ext4/mballoc.c
-@@ -1230,16 +1230,17 @@ ext4_mb_load_buddy_gfp(struct super_bloc
- /* we could use find_or_create_page(), but it locks page
- * what we'd like to avoid in fast path ... */
- page = find_get_page_flags(inode->i_mapping, pnum, FGP_ACCESSED);
-- if (page == NULL || !PageUptodate(page)) {
-+ if (page == NULL || !PageUptodate(page) || PageLocked(page)) {
-+ /*
-+ * PageLocked is employed to detect ongoing page
-+ * migrations, since concurrent migrations can lead to
-+ * bitmap inconsistency. And if we are not uptodate that
-+ * implies somebody just created the page but is yet to
-+ * initialize it. We can drop the page reference and
-+ * try to get the page with lock in both cases to avoid
-+ * concurrency.
-+ */
- if (page)
-- /*
-- * drop the page reference and try
-- * to get the page with lock. If we
-- * are not uptodate that implies
-- * somebody just created the page but
-- * is yet to initialize the same. So
-- * wait for it to initialize.
-- */
- put_page(page);
- page = find_or_create_page(inode->i_mapping, pnum, gfp);
- if (page) {
-@@ -1274,7 +1275,7 @@ ext4_mb_load_buddy_gfp(struct super_bloc
- poff = block % blocks_per_page;
-
- page = find_get_page_flags(inode->i_mapping, pnum, FGP_ACCESSED);
-- if (page == NULL || !PageUptodate(page)) {
-+ if (page == NULL || !PageUptodate(page) || PageLocked(page)) {
- if (page)
- put_page(page);
- page = find_or_create_page(inode->i_mapping, pnum, gfp);
drm-exynos-vidi-use-ctx-lock-to-protect-struct-vidi_context-member-variables-related-to-memory-alloc-free.patch
ext4-don-t-set-ext4_get_blocks_convert-when-splitting-before-submitting-i-o.patch
ext4-drop-extent-cache-when-splitting-extent-fails.patch
-ext4-fix-e4b-bitmap-inconsistency-reports.patch
ext4-fix-dirtyclusters-double-decrement-on-fs-shutdown.patch
ata-libata-remove-pointless-vprintk-calls.patch
ata-libata-scsi-refactor-ata_scsi_translate.patch
/*
* Choose next group by traversing largest_free_order lists. Updates *new_cr if
* cr level needs an update.
-@@ -2701,10 +2716,7 @@ ext4_mb_regular_allocator(struct ext4_al
+@@ -2700,10 +2715,7 @@ ext4_mb_regular_allocator(struct ext4_al
sb = ac->ac_sb;
sbi = EXT4_SB(sb);
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
-@@ -3835,8 +3835,7 @@ void ext4_exit_mballoc(void)
+@@ -3834,8 +3834,7 @@ void ext4_exit_mballoc(void)
* Returns 0 if success or error code
*/
static noinline_for_stack int
{
struct buffer_head *bitmap_bh = NULL;
struct ext4_group_desc *gdp;
-@@ -3924,13 +3923,6 @@ ext4_mb_mark_diskspace_used(struct ext4_
+@@ -3923,13 +3922,6 @@ ext4_mb_mark_diskspace_used(struct ext4_
ext4_unlock_group(sb, ac->ac_b_ex.fe_group);
percpu_counter_sub(&sbi->s_freeclusters_counter, ac->ac_b_ex.fe_len);
if (sbi->s_log_groups_per_flex) {
ext4_group_t flex_group = ext4_flex_group(sbi,
-@@ -5802,7 +5794,7 @@ repeat:
+@@ -5801,7 +5793,7 @@ repeat:
ext4_mb_pa_free(ac);
}
if (likely(ac->ac_status == AC_STATUS_FOUND)) {
if (*errp) {
ext4_discard_allocated_blocks(ac);
goto errout;
-@@ -5834,12 +5826,9 @@ out:
+@@ -5833,12 +5825,9 @@ out:
kmem_cache_free(ext4_ac_cachep, ac);
if (inquota && ar->len < inquota)
dquot_free_block(ar->inode, EXT4_C2B(sbi, inquota - ar->len));
+++ /dev/null
-From stable+bounces-219635-greg=kroah.com@vger.kernel.org Wed Feb 25 15:38:14 2026
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 25 Feb 2026 09:33:49 -0500
-Subject: ext4: fix e4b bitmap inconsistency reports
-To: stable@vger.kernel.org
-Cc: Yongjian Sun <sunyongjian1@huawei.com>, Zhang Yi <yi.zhang@huawei.com>, Baokun Li <libaokun1@huawei.com>, Jan Kara <jack@suse.cz>, Theodore Ts'o <tytso@mit.edu>, stable@kernel.org, Sasha Levin <sashal@kernel.org>
-Message-ID: <20260225143349.471932-1-sashal@kernel.org>
-
-From: Yongjian Sun <sunyongjian1@huawei.com>
-
-[ Upstream commit bdc56a9c46b2a99c12313122b9352b619a2e719e ]
-
-A bitmap inconsistency issue was observed during stress tests under
-mixed huge-page workloads. Ext4 reported multiple e4b bitmap check
-failures like:
-
-ext4_mb_complex_scan_group:2508: group 350, 8179 free clusters as
-per group info. But got 8192 blocks
-
-Analysis and experimentation confirmed that the issue is caused by a
-race condition between page migration and bitmap modification. Although
-this timing window is extremely narrow, it is still hit in practice:
-
-folio_lock ext4_mb_load_buddy
-__migrate_folio
- check ref count
- folio_mc_copy __filemap_get_folio
- folio_try_get(folio)
- ......
- mb_mark_used
- ext4_mb_unload_buddy
- __folio_migrate_mapping
- folio_ref_freeze
-folio_unlock
-
-The root cause of this issue is that the fast path of load_buddy only
-increments the folio's reference count, which is insufficient to prevent
-concurrent folio migration. We observed that the folio migration process
-acquires the folio lock. Therefore, we can determine whether to take the
-fast path in load_buddy by checking the lock status. If the folio is
-locked, we opt for the slow path (which acquires the lock) to close this
-concurrency window.
-
-Additionally, this change addresses the following issues:
-
-When the DOUBLE_CHECK macro is enabled to inspect bitmap-related
-issues, the following error may be triggered:
-
-corruption in group 324 at byte 784(6272): f in copy != ff on
-disk/prealloc
-
-Analysis reveals that this is a false positive. There is a specific race
-window where the bitmap and the group descriptor become momentarily
-inconsistent, leading to this error report:
-
-ext4_mb_load_buddy ext4_mb_load_buddy
- __filemap_get_folio(create|lock)
- folio_lock
- ext4_mb_init_cache
- folio_mark_uptodate
- __filemap_get_folio(no lock)
- ......
- mb_mark_used
- mb_mark_used_double
- mb_cmp_bitmaps
- mb_set_bits(e4b->bd_bitmap)
- folio_unlock
-
-The original logic assumed that since mb_cmp_bitmaps is called when the
-bitmap is newly loaded from disk, the folio lock would be sufficient to
-prevent concurrent access. However, this overlooks a specific race
-condition: if another process attempts to load buddy and finds the folio
-is already in an uptodate state, it will immediately begin using it without
-holding folio lock.
-
-Signed-off-by: Yongjian Sun <sunyongjian1@huawei.com>
-Reviewed-by: Zhang Yi <yi.zhang@huawei.com>
-Reviewed-by: Baokun Li <libaokun1@huawei.com>
-Reviewed-by: Jan Kara <jack@suse.cz>
-Link: https://patch.msgid.link/20260106090820.836242-1-sunyongjian@huaweicloud.com
-Signed-off-by: Theodore Ts'o <tytso@mit.edu>
-Cc: stable@kernel.org
-[ folio -> page ]
-Signed-off-by: Sasha Levin <sashal@kernel.org>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- fs/ext4/mballoc.c | 21 +++++++++++----------
- 1 file changed, 11 insertions(+), 10 deletions(-)
-
---- a/fs/ext4/mballoc.c
-+++ b/fs/ext4/mballoc.c
-@@ -1568,16 +1568,17 @@ ext4_mb_load_buddy_gfp(struct super_bloc
- /* we could use find_or_create_page(), but it locks page
- * what we'd like to avoid in fast path ... */
- page = find_get_page_flags(inode->i_mapping, pnum, FGP_ACCESSED);
-- if (page == NULL || !PageUptodate(page)) {
-+ if (page == NULL || !PageUptodate(page) || PageLocked(page)) {
-+ /*
-+ * PageLocked is employed to detect ongoing page
-+ * migrations, since concurrent migrations can lead to
-+ * bitmap inconsistency. And if we are not uptodate that
-+ * implies somebody just created the page but is yet to
-+ * initialize it. We can drop the page reference and
-+ * try to get the page with lock in both cases to avoid
-+ * concurrency.
-+ */
- if (page)
-- /*
-- * drop the page reference and try
-- * to get the page with lock. If we
-- * are not uptodate that implies
-- * somebody just created the page but
-- * is yet to initialize the same. So
-- * wait for it to initialize.
-- */
- put_page(page);
- page = find_or_create_page(inode->i_mapping, pnum, gfp);
- if (page) {
-@@ -1612,7 +1613,7 @@ ext4_mb_load_buddy_gfp(struct super_bloc
- poff = block % blocks_per_page;
-
- page = find_get_page_flags(inode->i_mapping, pnum, FGP_ACCESSED);
-- if (page == NULL || !PageUptodate(page)) {
-+ if (page == NULL || !PageUptodate(page) || PageLocked(page)) {
- if (page)
- put_page(page);
- page = find_or_create_page(inode->i_mapping, pnum, gfp);
ksmbd-call-ksmbd_vfs_kern_path_end_removing-on-some-error-paths.patch
ext4-don-t-set-ext4_get_blocks_convert-when-splitting-before-submitting-i-o.patch
ext4-drop-extent-cache-when-splitting-extent-fails.patch
-ext4-fix-e4b-bitmap-inconsistency-reports.patch
ext4-fix-dirtyclusters-double-decrement-on-fs-shutdown.patch
ksmbd-fix-null-pointer-dereference-error-in-generate_encryptionkey.patch
ext4-always-allocate-blocks-only-from-groups-inode-can-use.patch
/*
* Choose next group by traversing largest_free_order lists. Updates *new_cr if
* cr level needs an update.
-@@ -2672,10 +2687,7 @@ ext4_mb_regular_allocator(struct ext4_al
+@@ -2656,10 +2671,7 @@ ext4_mb_regular_allocator(struct ext4_al
sb = ac->ac_sb;
sbi = EXT4_SB(sb);
+++ /dev/null
-From 9bf9a4739682b7ab30f065a3f82cfee4fdc10feb Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 16 Apr 2024 18:28:54 +0100
-Subject: ext4: convert bd_bitmap_page to bd_bitmap_folio
-
-From: Matthew Wilcox (Oracle) <willy@infradead.org>
-
-[ Upstream commit 99b150d84e4939735cfce245e32e3d29312c68ec ]
-
-There is no need to make this a multi-page folio, so leave all the
-infrastructure around it in pages. But since we're locking it, playing
-with its refcount and checking whether it's uptodate, it needs to move
-to the folio API.
-
-Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
-Link: https://lore.kernel.org/r/20240416172900.244637-2-willy@infradead.org
-Signed-off-by: Theodore Ts'o <tytso@mit.edu>
-Stable-dep-of: bdc56a9c46b2 ("ext4: fix e4b bitmap inconsistency reports")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- fs/ext4/mballoc.c | 98 ++++++++++++++++++++++++-----------------------
- fs/ext4/mballoc.h | 2 +-
- 2 files changed, 52 insertions(+), 48 deletions(-)
-
-diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
-index 899d7eb6df3dc..083e4904ed679 100644
---- a/fs/ext4/mballoc.c
-+++ b/fs/ext4/mballoc.c
-@@ -1345,9 +1345,10 @@ static int ext4_mb_get_buddy_page_lock(struct super_block *sb,
- int block, pnum, poff;
- int blocks_per_page;
- struct page *page;
-+ struct folio *folio;
-
- e4b->bd_buddy_page = NULL;
-- e4b->bd_bitmap_page = NULL;
-+ e4b->bd_bitmap_folio = NULL;
-
- blocks_per_page = PAGE_SIZE / sb->s_blocksize;
- /*
-@@ -1358,12 +1359,13 @@ static int ext4_mb_get_buddy_page_lock(struct super_block *sb,
- block = group * 2;
- pnum = block / blocks_per_page;
- poff = block % blocks_per_page;
-- page = find_or_create_page(inode->i_mapping, pnum, gfp);
-- if (!page)
-- return -ENOMEM;
-- BUG_ON(page->mapping != inode->i_mapping);
-- e4b->bd_bitmap_page = page;
-- e4b->bd_bitmap = page_address(page) + (poff * sb->s_blocksize);
-+ folio = __filemap_get_folio(inode->i_mapping, pnum,
-+ FGP_LOCK | FGP_ACCESSED | FGP_CREAT, gfp);
-+ if (IS_ERR(folio))
-+ return PTR_ERR(folio);
-+ BUG_ON(folio->mapping != inode->i_mapping);
-+ e4b->bd_bitmap_folio = folio;
-+ e4b->bd_bitmap = folio_address(folio) + (poff * sb->s_blocksize);
-
- if (blocks_per_page >= 2) {
- /* buddy and bitmap are on the same page */
-@@ -1381,9 +1383,9 @@ static int ext4_mb_get_buddy_page_lock(struct super_block *sb,
-
- static void ext4_mb_put_buddy_page_lock(struct ext4_buddy *e4b)
- {
-- if (e4b->bd_bitmap_page) {
-- unlock_page(e4b->bd_bitmap_page);
-- put_page(e4b->bd_bitmap_page);
-+ if (e4b->bd_bitmap_folio) {
-+ folio_unlock(e4b->bd_bitmap_folio);
-+ folio_put(e4b->bd_bitmap_folio);
- }
- if (e4b->bd_buddy_page) {
- unlock_page(e4b->bd_buddy_page);
-@@ -1403,6 +1405,7 @@ int ext4_mb_init_group(struct super_block *sb, ext4_group_t group, gfp_t gfp)
- struct ext4_group_info *this_grp;
- struct ext4_buddy e4b;
- struct page *page;
-+ struct folio *folio;
- int ret = 0;
-
- might_sleep();
-@@ -1429,11 +1432,11 @@ int ext4_mb_init_group(struct super_block *sb, ext4_group_t group, gfp_t gfp)
- goto err;
- }
-
-- page = e4b.bd_bitmap_page;
-- ret = ext4_mb_init_cache(page, NULL, gfp);
-+ folio = e4b.bd_bitmap_folio;
-+ ret = ext4_mb_init_cache(&folio->page, NULL, gfp);
- if (ret)
- goto err;
-- if (!PageUptodate(page)) {
-+ if (!folio_test_uptodate(folio)) {
- ret = -EIO;
- goto err;
- }
-@@ -1475,6 +1478,7 @@ ext4_mb_load_buddy_gfp(struct super_block *sb, ext4_group_t group,
- int pnum;
- int poff;
- struct page *page;
-+ struct folio *folio;
- int ret;
- struct ext4_group_info *grp;
- struct ext4_sb_info *sbi = EXT4_SB(sb);
-@@ -1493,7 +1497,7 @@ ext4_mb_load_buddy_gfp(struct super_block *sb, ext4_group_t group,
- e4b->bd_sb = sb;
- e4b->bd_group = group;
- e4b->bd_buddy_page = NULL;
-- e4b->bd_bitmap_page = NULL;
-+ e4b->bd_bitmap_folio = NULL;
-
- if (unlikely(EXT4_MB_GRP_NEED_INIT(grp))) {
- /*
-@@ -1514,53 +1518,53 @@ ext4_mb_load_buddy_gfp(struct super_block *sb, ext4_group_t group,
- pnum = block / blocks_per_page;
- poff = block % blocks_per_page;
-
-- /* we could use find_or_create_page(), but it locks page
-- * what we'd like to avoid in fast path ... */
-- page = find_get_page_flags(inode->i_mapping, pnum, FGP_ACCESSED);
-- if (page == NULL || !PageUptodate(page)) {
-- if (page)
-+ /* Avoid locking the folio in the fast path ... */
-+ folio = __filemap_get_folio(inode->i_mapping, pnum, FGP_ACCESSED, 0);
-+ if (IS_ERR(folio) || !folio_test_uptodate(folio)) {
-+ if (!IS_ERR(folio))
- /*
-- * drop the page reference and try
-- * to get the page with lock. If we
-+ * drop the folio reference and try
-+ * to get the folio with lock. If we
- * are not uptodate that implies
-- * somebody just created the page but
-- * is yet to initialize the same. So
-+ * somebody just created the folio but
-+ * is yet to initialize it. So
- * wait for it to initialize.
- */
-- put_page(page);
-- page = find_or_create_page(inode->i_mapping, pnum, gfp);
-- if (page) {
-- if (WARN_RATELIMIT(page->mapping != inode->i_mapping,
-- "ext4: bitmap's paging->mapping != inode->i_mapping\n")) {
-+ folio_put(folio);
-+ folio = __filemap_get_folio(inode->i_mapping, pnum,
-+ FGP_LOCK | FGP_ACCESSED | FGP_CREAT, gfp);
-+ if (!IS_ERR(folio)) {
-+ if (WARN_RATELIMIT(folio->mapping != inode->i_mapping,
-+ "ext4: bitmap's mapping != inode->i_mapping\n")) {
- /* should never happen */
-- unlock_page(page);
-+ folio_unlock(folio);
- ret = -EINVAL;
- goto err;
- }
-- if (!PageUptodate(page)) {
-- ret = ext4_mb_init_cache(page, NULL, gfp);
-+ if (!folio_test_uptodate(folio)) {
-+ ret = ext4_mb_init_cache(&folio->page, NULL, gfp);
- if (ret) {
-- unlock_page(page);
-+ folio_unlock(folio);
- goto err;
- }
-- mb_cmp_bitmaps(e4b, page_address(page) +
-+ mb_cmp_bitmaps(e4b, folio_address(folio) +
- (poff * sb->s_blocksize));
- }
-- unlock_page(page);
-+ folio_unlock(folio);
- }
- }
-- if (page == NULL) {
-- ret = -ENOMEM;
-+ if (IS_ERR(folio)) {
-+ ret = PTR_ERR(folio);
- goto err;
- }
-- if (!PageUptodate(page)) {
-+ if (!folio_test_uptodate(folio)) {
- ret = -EIO;
- goto err;
- }
-
- /* Pages marked accessed already */
-- e4b->bd_bitmap_page = page;
-- e4b->bd_bitmap = page_address(page) + (poff * sb->s_blocksize);
-+ e4b->bd_bitmap_folio = folio;
-+ e4b->bd_bitmap = folio_address(folio) + (poff * sb->s_blocksize);
-
- block++;
- pnum = block / blocks_per_page;
-@@ -1608,8 +1612,8 @@ ext4_mb_load_buddy_gfp(struct super_block *sb, ext4_group_t group,
- err:
- if (page)
- put_page(page);
-- if (e4b->bd_bitmap_page)
-- put_page(e4b->bd_bitmap_page);
-+ if (e4b->bd_bitmap_folio)
-+ folio_put(e4b->bd_bitmap_folio);
-
- e4b->bd_buddy = NULL;
- e4b->bd_bitmap = NULL;
-@@ -1624,8 +1628,8 @@ static int ext4_mb_load_buddy(struct super_block *sb, ext4_group_t group,
-
- static void ext4_mb_unload_buddy(struct ext4_buddy *e4b)
- {
-- if (e4b->bd_bitmap_page)
-- put_page(e4b->bd_bitmap_page);
-+ if (e4b->bd_bitmap_folio)
-+ folio_put(e4b->bd_bitmap_folio);
- if (e4b->bd_buddy_page)
- put_page(e4b->bd_buddy_page);
- }
-@@ -2050,7 +2054,7 @@ static void ext4_mb_use_best_found(struct ext4_allocation_context *ac,
- * double allocate blocks. The reference is dropped
- * in ext4_mb_release_context
- */
-- ac->ac_bitmap_page = e4b->bd_bitmap_page;
-+ ac->ac_bitmap_page = &e4b->bd_bitmap_folio->page;
- get_page(ac->ac_bitmap_page);
- ac->ac_buddy_page = e4b->bd_buddy_page;
- get_page(ac->ac_buddy_page);
-@@ -3715,7 +3719,7 @@ static void ext4_free_data_in_buddy(struct super_block *sb,
- * balance refcounts from ext4_mb_free_metadata()
- */
- put_page(e4b.bd_buddy_page);
-- put_page(e4b.bd_bitmap_page);
-+ folio_put(e4b.bd_bitmap_folio);
- }
- ext4_unlock_group(sb, entry->efd_group);
- ext4_mb_unload_buddy(&e4b);
-@@ -5888,7 +5892,7 @@ ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b,
- struct rb_node *parent = NULL, *new_node;
-
- BUG_ON(!ext4_handle_valid(handle));
-- BUG_ON(e4b->bd_bitmap_page == NULL);
-+ BUG_ON(e4b->bd_bitmap_folio == NULL);
- BUG_ON(e4b->bd_buddy_page == NULL);
-
- new_node = &new_entry->efd_node;
-@@ -5901,7 +5905,7 @@ ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b,
- * on-disk bitmap and lose not-yet-available
- * blocks */
- get_page(e4b->bd_buddy_page);
-- get_page(e4b->bd_bitmap_page);
-+ folio_get(e4b->bd_bitmap_folio);
- }
- while (*n) {
- parent = *n;
-diff --git a/fs/ext4/mballoc.h b/fs/ext4/mballoc.h
-index 2d95fcab941f6..24e7c7a04f674 100644
---- a/fs/ext4/mballoc.h
-+++ b/fs/ext4/mballoc.h
-@@ -203,7 +203,7 @@ struct ext4_allocation_context {
- struct ext4_buddy {
- struct page *bd_buddy_page;
- void *bd_buddy;
-- struct page *bd_bitmap_page;
-+ struct folio *bd_bitmap_folio;
- void *bd_bitmap;
- struct ext4_group_info *bd_info;
- struct super_block *bd_sb;
---
-2.51.0
-
+++ /dev/null
-From 59bc2b64c23cc29f4fb10fb79724c6163dbf06e9 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 16 Apr 2024 18:28:55 +0100
-Subject: ext4: convert bd_buddy_page to bd_buddy_folio
-
-From: Matthew Wilcox (Oracle) <willy@infradead.org>
-
-[ Upstream commit 5eea586b47f05b5f5518cf8f9dd9283a01a8066d ]
-
-There is no need to make this a multi-page folio, so leave all the
-infrastructure around it in pages. But since we're locking it, playing
-with its refcount and checking whether it's uptodate, it needs to move
-to the folio API.
-
-Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
-Link: https://lore.kernel.org/r/20240416172900.244637-3-willy@infradead.org
-Signed-off-by: Theodore Ts'o <tytso@mit.edu>
-Stable-dep-of: bdc56a9c46b2 ("ext4: fix e4b bitmap inconsistency reports")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- fs/ext4/mballoc.c | 91 +++++++++++++++++++++++------------------------
- fs/ext4/mballoc.h | 2 +-
- 2 files changed, 46 insertions(+), 47 deletions(-)
-
-diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
-index 083e4904ed679..19e5b57387d60 100644
---- a/fs/ext4/mballoc.c
-+++ b/fs/ext4/mballoc.c
-@@ -1336,7 +1336,7 @@ static int ext4_mb_init_cache(struct page *page, char *incore, gfp_t gfp)
- * Lock the buddy and bitmap pages. This make sure other parallel init_group
- * on the same buddy page doesn't happen whild holding the buddy page lock.
- * Return locked buddy and bitmap pages on e4b struct. If buddy and bitmap
-- * are on the same page e4b->bd_buddy_page is NULL and return value is 0.
-+ * are on the same page e4b->bd_buddy_folio is NULL and return value is 0.
- */
- static int ext4_mb_get_buddy_page_lock(struct super_block *sb,
- ext4_group_t group, struct ext4_buddy *e4b, gfp_t gfp)
-@@ -1344,10 +1344,9 @@ static int ext4_mb_get_buddy_page_lock(struct super_block *sb,
- struct inode *inode = EXT4_SB(sb)->s_buddy_cache;
- int block, pnum, poff;
- int blocks_per_page;
-- struct page *page;
- struct folio *folio;
-
-- e4b->bd_buddy_page = NULL;
-+ e4b->bd_buddy_folio = NULL;
- e4b->bd_bitmap_folio = NULL;
-
- blocks_per_page = PAGE_SIZE / sb->s_blocksize;
-@@ -1373,11 +1372,12 @@ static int ext4_mb_get_buddy_page_lock(struct super_block *sb,
- }
-
- /* blocks_per_page == 1, hence we need another page for the buddy */
-- page = find_or_create_page(inode->i_mapping, block + 1, gfp);
-- if (!page)
-- return -ENOMEM;
-- BUG_ON(page->mapping != inode->i_mapping);
-- e4b->bd_buddy_page = page;
-+ folio = __filemap_get_folio(inode->i_mapping, block + 1,
-+ FGP_LOCK | FGP_ACCESSED | FGP_CREAT, gfp);
-+ if (IS_ERR(folio))
-+ return PTR_ERR(folio);
-+ BUG_ON(folio->mapping != inode->i_mapping);
-+ e4b->bd_buddy_folio = folio;
- return 0;
- }
-
-@@ -1387,9 +1387,9 @@ static void ext4_mb_put_buddy_page_lock(struct ext4_buddy *e4b)
- folio_unlock(e4b->bd_bitmap_folio);
- folio_put(e4b->bd_bitmap_folio);
- }
-- if (e4b->bd_buddy_page) {
-- unlock_page(e4b->bd_buddy_page);
-- put_page(e4b->bd_buddy_page);
-+ if (e4b->bd_buddy_folio) {
-+ folio_unlock(e4b->bd_buddy_folio);
-+ folio_put(e4b->bd_buddy_folio);
- }
- }
-
-@@ -1404,7 +1404,6 @@ int ext4_mb_init_group(struct super_block *sb, ext4_group_t group, gfp_t gfp)
-
- struct ext4_group_info *this_grp;
- struct ext4_buddy e4b;
-- struct page *page;
- struct folio *folio;
- int ret = 0;
-
-@@ -1441,7 +1440,7 @@ int ext4_mb_init_group(struct super_block *sb, ext4_group_t group, gfp_t gfp)
- goto err;
- }
-
-- if (e4b.bd_buddy_page == NULL) {
-+ if (e4b.bd_buddy_folio == NULL) {
- /*
- * If both the bitmap and buddy are in
- * the same page we don't need to force
-@@ -1451,11 +1450,11 @@ int ext4_mb_init_group(struct super_block *sb, ext4_group_t group, gfp_t gfp)
- goto err;
- }
- /* init buddy cache */
-- page = e4b.bd_buddy_page;
-- ret = ext4_mb_init_cache(page, e4b.bd_bitmap, gfp);
-+ folio = e4b.bd_buddy_folio;
-+ ret = ext4_mb_init_cache(&folio->page, e4b.bd_bitmap, gfp);
- if (ret)
- goto err;
-- if (!PageUptodate(page)) {
-+ if (!folio_test_uptodate(folio)) {
- ret = -EIO;
- goto err;
- }
-@@ -1477,7 +1476,6 @@ ext4_mb_load_buddy_gfp(struct super_block *sb, ext4_group_t group,
- int block;
- int pnum;
- int poff;
-- struct page *page;
- struct folio *folio;
- int ret;
- struct ext4_group_info *grp;
-@@ -1496,7 +1494,7 @@ ext4_mb_load_buddy_gfp(struct super_block *sb, ext4_group_t group,
- e4b->bd_info = grp;
- e4b->bd_sb = sb;
- e4b->bd_group = group;
-- e4b->bd_buddy_page = NULL;
-+ e4b->bd_buddy_folio = NULL;
- e4b->bd_bitmap_folio = NULL;
-
- if (unlikely(EXT4_MB_GRP_NEED_INIT(grp))) {
-@@ -1562,7 +1560,7 @@ ext4_mb_load_buddy_gfp(struct super_block *sb, ext4_group_t group,
- goto err;
- }
-
-- /* Pages marked accessed already */
-+ /* Folios marked accessed already */
- e4b->bd_bitmap_folio = folio;
- e4b->bd_bitmap = folio_address(folio) + (poff * sb->s_blocksize);
-
-@@ -1570,48 +1568,49 @@ ext4_mb_load_buddy_gfp(struct super_block *sb, ext4_group_t group,
- pnum = block / blocks_per_page;
- poff = block % blocks_per_page;
-
-- page = find_get_page_flags(inode->i_mapping, pnum, FGP_ACCESSED);
-- if (page == NULL || !PageUptodate(page)) {
-- if (page)
-- put_page(page);
-- page = find_or_create_page(inode->i_mapping, pnum, gfp);
-- if (page) {
-- if (WARN_RATELIMIT(page->mapping != inode->i_mapping,
-- "ext4: buddy bitmap's page->mapping != inode->i_mapping\n")) {
-+ folio = __filemap_get_folio(inode->i_mapping, pnum, FGP_ACCESSED, 0);
-+ if (IS_ERR(folio) || !folio_test_uptodate(folio)) {
-+ if (!IS_ERR(folio))
-+ folio_put(folio);
-+ folio = __filemap_get_folio(inode->i_mapping, pnum,
-+ FGP_LOCK | FGP_ACCESSED | FGP_CREAT, gfp);
-+ if (!IS_ERR(folio)) {
-+ if (WARN_RATELIMIT(folio->mapping != inode->i_mapping,
-+ "ext4: buddy bitmap's mapping != inode->i_mapping\n")) {
- /* should never happen */
-- unlock_page(page);
-+ folio_unlock(folio);
- ret = -EINVAL;
- goto err;
- }
-- if (!PageUptodate(page)) {
-- ret = ext4_mb_init_cache(page, e4b->bd_bitmap,
-+ if (!folio_test_uptodate(folio)) {
-+ ret = ext4_mb_init_cache(&folio->page, e4b->bd_bitmap,
- gfp);
- if (ret) {
-- unlock_page(page);
-+ folio_unlock(folio);
- goto err;
- }
- }
-- unlock_page(page);
-+ folio_unlock(folio);
- }
- }
-- if (page == NULL) {
-- ret = -ENOMEM;
-+ if (IS_ERR(folio)) {
-+ ret = PTR_ERR(folio);
- goto err;
- }
-- if (!PageUptodate(page)) {
-+ if (!folio_test_uptodate(folio)) {
- ret = -EIO;
- goto err;
- }
-
-- /* Pages marked accessed already */
-- e4b->bd_buddy_page = page;
-- e4b->bd_buddy = page_address(page) + (poff * sb->s_blocksize);
-+ /* Folios marked accessed already */
-+ e4b->bd_buddy_folio = folio;
-+ e4b->bd_buddy = folio_address(folio) + (poff * sb->s_blocksize);
-
- return 0;
-
- err:
-- if (page)
-- put_page(page);
-+ if (folio)
-+ folio_put(folio);
- if (e4b->bd_bitmap_folio)
- folio_put(e4b->bd_bitmap_folio);
-
-@@ -1630,8 +1629,8 @@ static void ext4_mb_unload_buddy(struct ext4_buddy *e4b)
- {
- if (e4b->bd_bitmap_folio)
- folio_put(e4b->bd_bitmap_folio);
-- if (e4b->bd_buddy_page)
-- put_page(e4b->bd_buddy_page);
-+ if (e4b->bd_buddy_folio)
-+ folio_put(e4b->bd_buddy_folio);
- }
-
-
-@@ -2056,7 +2055,7 @@ static void ext4_mb_use_best_found(struct ext4_allocation_context *ac,
- */
- ac->ac_bitmap_page = &e4b->bd_bitmap_folio->page;
- get_page(ac->ac_bitmap_page);
-- ac->ac_buddy_page = e4b->bd_buddy_page;
-+ ac->ac_buddy_page = &e4b->bd_buddy_folio->page;
- get_page(ac->ac_buddy_page);
- /* store last allocated for subsequent stream allocation */
- if (ac->ac_flags & EXT4_MB_STREAM_ALLOC) {
-@@ -3718,7 +3717,7 @@ static void ext4_free_data_in_buddy(struct super_block *sb,
- /* No more items in the per group rb tree
- * balance refcounts from ext4_mb_free_metadata()
- */
-- put_page(e4b.bd_buddy_page);
-+ folio_put(e4b.bd_buddy_folio);
- folio_put(e4b.bd_bitmap_folio);
- }
- ext4_unlock_group(sb, entry->efd_group);
-@@ -5893,7 +5892,7 @@ ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b,
-
- BUG_ON(!ext4_handle_valid(handle));
- BUG_ON(e4b->bd_bitmap_folio == NULL);
-- BUG_ON(e4b->bd_buddy_page == NULL);
-+ BUG_ON(e4b->bd_buddy_folio == NULL);
-
- new_node = &new_entry->efd_node;
- cluster = new_entry->efd_start_cluster;
-@@ -5904,7 +5903,7 @@ ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b,
- * otherwise we'll refresh it from
- * on-disk bitmap and lose not-yet-available
- * blocks */
-- get_page(e4b->bd_buddy_page);
-+ folio_get(e4b->bd_buddy_folio);
- folio_get(e4b->bd_bitmap_folio);
- }
- while (*n) {
-diff --git a/fs/ext4/mballoc.h b/fs/ext4/mballoc.h
-index 24e7c7a04f674..fe4dbbbbe8725 100644
---- a/fs/ext4/mballoc.h
-+++ b/fs/ext4/mballoc.h
-@@ -201,7 +201,7 @@ struct ext4_allocation_context {
- #define AC_STATUS_BREAK 3
-
- struct ext4_buddy {
-- struct page *bd_buddy_page;
-+ struct folio *bd_buddy_folio;
- void *bd_buddy;
- struct folio *bd_bitmap_folio;
- void *bd_bitmap;
---
-2.51.0
-
+++ /dev/null
-From 11456f1e7f8fd43116ec9285865f0107561666d7 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Thu, 16 Mar 2023 17:07:32 -0400
-Subject: ext4: convert some BUG_ON's in mballoc to use WARN_RATELIMITED
- instead
-
-From: Theodore Ts'o <tytso@mit.edu>
-
-[ Upstream commit 19b8b035a776939ceb3de0f45aded4751d7849ef ]
-
-In cases where we have an obvious way of continuing, let's use
-WARN_RATELIMITED() instead of BUG_ON().
-
-Signed-off-by: Theodore Ts'o <tytso@mit.edu>
-Stable-dep-of: bdc56a9c46b2 ("ext4: fix e4b bitmap inconsistency reports")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- fs/ext4/mballoc.c | 25 +++++++++++++++++++------
- 1 file changed, 19 insertions(+), 6 deletions(-)
-
-diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
-index 7431ff97a68c8..2a385dc610704 100644
---- a/fs/ext4/mballoc.c
-+++ b/fs/ext4/mballoc.c
-@@ -1531,7 +1531,13 @@ ext4_mb_load_buddy_gfp(struct super_block *sb, ext4_group_t group,
- put_page(page);
- page = find_or_create_page(inode->i_mapping, pnum, gfp);
- if (page) {
-- BUG_ON(page->mapping != inode->i_mapping);
-+ if (WARN_RATELIMIT(page->mapping != inode->i_mapping,
-+ "ext4: bitmap's paging->mapping != inode->i_mapping\n")) {
-+ /* should never happen */
-+ unlock_page(page);
-+ ret = -EINVAL;
-+ goto err;
-+ }
- if (!PageUptodate(page)) {
- ret = ext4_mb_init_cache(page, NULL, gfp);
- if (ret) {
-@@ -1567,7 +1573,13 @@ ext4_mb_load_buddy_gfp(struct super_block *sb, ext4_group_t group,
- put_page(page);
- page = find_or_create_page(inode->i_mapping, pnum, gfp);
- if (page) {
-- BUG_ON(page->mapping != inode->i_mapping);
-+ if (WARN_RATELIMIT(page->mapping != inode->i_mapping,
-+ "ext4: buddy bitmap's page->mapping != inode->i_mapping\n")) {
-+ /* should never happen */
-+ unlock_page(page);
-+ ret = -EINVAL;
-+ goto err;
-+ }
- if (!PageUptodate(page)) {
- ret = ext4_mb_init_cache(page, e4b->bd_bitmap,
- gfp);
-@@ -2286,7 +2298,9 @@ void ext4_mb_simple_scan_group(struct ext4_allocation_context *ac,
- continue;
-
- buddy = mb_find_buddy(e4b, i, &max);
-- BUG_ON(buddy == NULL);
-+ if (WARN_RATELIMIT(buddy == NULL,
-+ "ext4: mb_simple_scan_group: mb_find_buddy failed, (%d)\n", i))
-+ continue;
-
- k = mb_find_next_zero_bit(buddy, max, 0);
- if (k >= max) {
-@@ -4312,15 +4326,14 @@ static void ext4_discard_allocated_blocks(struct ext4_allocation_context *ac)
- if (ac->ac_f_ex.fe_len == 0)
- return;
- err = ext4_mb_load_buddy(ac->ac_sb, ac->ac_f_ex.fe_group, &e4b);
-- if (err) {
-+ if (WARN_RATELIMIT(err,
-+ "ext4: mb_load_buddy failed (%d)", err))
- /*
- * This should never happen since we pin the
- * pages in the ext4_allocation_context so
- * ext4_mb_load_buddy() should never fail.
- */
-- WARN(1, "mb_load_buddy failed (%d)", err);
- return;
-- }
- ext4_lock_group(ac->ac_sb, ac->ac_f_ex.fe_group);
- mb_free_blocks(ac->ac_inode, &e4b, ac->ac_f_ex.fe_start,
- ac->ac_f_ex.fe_len);
---
-2.51.0
-
+++ /dev/null
-From 0d7deff40dcb876a7530df9c8888e5c63cb9b2e9 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 24 Oct 2023 11:52:15 +0800
-Subject: ext4: delete redundant calculations in ext4_mb_get_buddy_page_lock()
-
-From: Gou Hao <gouhao@uniontech.com>
-
-[ Upstream commit f2fec3e99a32d7c14dbf63c824f8286ebc94b18d ]
-
-'blocks_per_page' is always 1 after 'if (blocks_per_page >= 2)',
-'pnum' and 'block' are equal in this case.
-
-Signed-off-by: Gou Hao <gouhao@uniontech.com>
-Reviewed-by: Jan Kara <jack@suse.cz>
-Link: https://lore.kernel.org/r/20231024035215.29474-1-gouhao@uniontech.com
-Signed-off-by: Theodore Ts'o <tytso@mit.edu>
-Stable-dep-of: bdc56a9c46b2 ("ext4: fix e4b bitmap inconsistency reports")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- fs/ext4/mballoc.c | 5 ++---
- 1 file changed, 2 insertions(+), 3 deletions(-)
-
-diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
-index 2a385dc610704..899d7eb6df3dc 100644
---- a/fs/ext4/mballoc.c
-+++ b/fs/ext4/mballoc.c
-@@ -1370,9 +1370,8 @@ static int ext4_mb_get_buddy_page_lock(struct super_block *sb,
- return 0;
- }
-
-- block++;
-- pnum = block / blocks_per_page;
-- page = find_or_create_page(inode->i_mapping, pnum, gfp);
-+ /* blocks_per_page == 1, hence we need another page for the buddy */
-+ page = find_or_create_page(inode->i_mapping, block + 1, gfp);
- if (!page)
- return -ENOMEM;
- BUG_ON(page->mapping != inode->i_mapping);
---
-2.51.0
-
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
-@@ -3815,8 +3815,7 @@ void ext4_exit_mballoc(void)
+@@ -3799,8 +3799,7 @@ void ext4_exit_mballoc(void)
* Returns 0 if success or error code
*/
static noinline_for_stack int
{
struct buffer_head *bitmap_bh = NULL;
struct ext4_group_desc *gdp;
-@@ -3904,13 +3903,6 @@ ext4_mb_mark_diskspace_used(struct ext4_
+@@ -3888,13 +3887,6 @@ ext4_mb_mark_diskspace_used(struct ext4_
ext4_unlock_group(sb, ac->ac_b_ex.fe_group);
percpu_counter_sub(&sbi->s_freeclusters_counter, ac->ac_b_ex.fe_len);
if (sbi->s_log_groups_per_flex) {
ext4_group_t flex_group = ext4_flex_group(sbi,
-@@ -5804,7 +5796,7 @@ repeat:
+@@ -5789,7 +5781,7 @@ repeat:
ext4_mb_pa_free(ac);
}
if (likely(ac->ac_status == AC_STATUS_FOUND)) {
if (*errp) {
ext4_discard_allocated_blocks(ac);
goto errout;
-@@ -5836,12 +5828,9 @@ out:
+@@ -5821,12 +5813,9 @@ out:
kmem_cache_free(ext4_ac_cachep, ac);
if (inquota && ar->len < inquota)
dquot_free_block(ar->inode, EXT4_C2B(sbi, inquota - ar->len));
+++ /dev/null
-From 8eb91fc9f27360846321ecc3684e3577eaf0e9c5 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 6 Jan 2026 17:08:20 +0800
-Subject: ext4: fix e4b bitmap inconsistency reports
-
-From: Yongjian Sun <sunyongjian1@huawei.com>
-
-[ Upstream commit bdc56a9c46b2a99c12313122b9352b619a2e719e ]
-
-A bitmap inconsistency issue was observed during stress tests under
-mixed huge-page workloads. Ext4 reported multiple e4b bitmap check
-failures like:
-
-ext4_mb_complex_scan_group:2508: group 350, 8179 free clusters as
-per group info. But got 8192 blocks
-
-Analysis and experimentation confirmed that the issue is caused by a
-race condition between page migration and bitmap modification. Although
-this timing window is extremely narrow, it is still hit in practice:
-
-folio_lock ext4_mb_load_buddy
-__migrate_folio
- check ref count
- folio_mc_copy __filemap_get_folio
- folio_try_get(folio)
- ......
- mb_mark_used
- ext4_mb_unload_buddy
- __folio_migrate_mapping
- folio_ref_freeze
-folio_unlock
-
-The root cause of this issue is that the fast path of load_buddy only
-increments the folio's reference count, which is insufficient to prevent
-concurrent folio migration. We observed that the folio migration process
-acquires the folio lock. Therefore, we can determine whether to take the
-fast path in load_buddy by checking the lock status. If the folio is
-locked, we opt for the slow path (which acquires the lock) to close this
-concurrency window.
-
-Additionally, this change addresses the following issues:
-
-When the DOUBLE_CHECK macro is enabled to inspect bitmap-related
-issues, the following error may be triggered:
-
-corruption in group 324 at byte 784(6272): f in copy != ff on
-disk/prealloc
-
-Analysis reveals that this is a false positive. There is a specific race
-window where the bitmap and the group descriptor become momentarily
-inconsistent, leading to this error report:
-
-ext4_mb_load_buddy ext4_mb_load_buddy
- __filemap_get_folio(create|lock)
- folio_lock
- ext4_mb_init_cache
- folio_mark_uptodate
- __filemap_get_folio(no lock)
- ......
- mb_mark_used
- mb_mark_used_double
- mb_cmp_bitmaps
- mb_set_bits(e4b->bd_bitmap)
- folio_unlock
-
-The original logic assumed that since mb_cmp_bitmaps is called when the
-bitmap is newly loaded from disk, the folio lock would be sufficient to
-prevent concurrent access. However, this overlooks a specific race
-condition: if another process attempts to load buddy and finds the folio
-is already in an uptodate state, it will immediately begin using it without
-holding folio lock.
-
-Signed-off-by: Yongjian Sun <sunyongjian1@huawei.com>
-Reviewed-by: Zhang Yi <yi.zhang@huawei.com>
-Reviewed-by: Baokun Li <libaokun1@huawei.com>
-Reviewed-by: Jan Kara <jack@suse.cz>
-Link: https://patch.msgid.link/20260106090820.836242-1-sunyongjian@huaweicloud.com
-Signed-off-by: Theodore Ts'o <tytso@mit.edu>
-Cc: stable@kernel.org
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- fs/ext4/mballoc.c | 21 +++++++++++----------
- 1 file changed, 11 insertions(+), 10 deletions(-)
-
-diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
-index 19e5b57387d60..93e05e6159fb8 100644
---- a/fs/ext4/mballoc.c
-+++ b/fs/ext4/mballoc.c
-@@ -1518,16 +1518,17 @@ ext4_mb_load_buddy_gfp(struct super_block *sb, ext4_group_t group,
-
- /* Avoid locking the folio in the fast path ... */
- folio = __filemap_get_folio(inode->i_mapping, pnum, FGP_ACCESSED, 0);
-- if (IS_ERR(folio) || !folio_test_uptodate(folio)) {
-+ if (IS_ERR(folio) || !folio_test_uptodate(folio) || folio_test_locked(folio)) {
-+ /*
-+ * folio_test_locked is employed to detect ongoing folio
-+ * migrations, since concurrent migrations can lead to
-+ * bitmap inconsistency. And if we are not uptodate that
-+ * implies somebody just created the folio but is yet to
-+ * initialize it. We can drop the folio reference and
-+ * try to get the folio with lock in both cases to avoid
-+ * concurrency.
-+ */
- if (!IS_ERR(folio))
-- /*
-- * drop the folio reference and try
-- * to get the folio with lock. If we
-- * are not uptodate that implies
-- * somebody just created the folio but
-- * is yet to initialize it. So
-- * wait for it to initialize.
-- */
- folio_put(folio);
- folio = __filemap_get_folio(inode->i_mapping, pnum,
- FGP_LOCK | FGP_ACCESSED | FGP_CREAT, gfp);
-@@ -1569,7 +1570,7 @@ ext4_mb_load_buddy_gfp(struct super_block *sb, ext4_group_t group,
- poff = block % blocks_per_page;
-
- folio = __filemap_get_folio(inode->i_mapping, pnum, FGP_ACCESSED, 0);
-- if (IS_ERR(folio) || !folio_test_uptodate(folio)) {
-+ if (IS_ERR(folio) || !folio_test_uptodate(folio) || folio_test_locked(folio)) {
- if (!IS_ERR(folio))
- folio_put(folio);
- folio = __filemap_get_folio(inode->i_mapping, pnum,
---
-2.51.0
-
+++ /dev/null
-From 7aab117c2ca817532e7de8771816a7b77ef0e0d0 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Sat, 4 Mar 2023 01:21:10 +0800
-Subject: ext4: remove unnecessary e4b->bd_buddy_page check in
- ext4_mb_load_buddy_gfp
-
-From: Kemeng Shi <shikemeng@huaweicloud.com>
-
-[ Upstream commit 285164b80175157c18a06425cf25591c9f942b1a ]
-
-e4b->bd_buddy_page is only set if we initialize ext4_buddy successfully. So
-e4b->bd_buddy_page is always NULL in error handle branch. Just remove the
-dead check.
-
-Signed-off-by: Kemeng Shi <shikemeng@huaweicloud.com>
-Reviewed-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
-Link: https://lore.kernel.org/r/20230303172120.3800725-11-shikemeng@huaweicloud.com
-Signed-off-by: Theodore Ts'o <tytso@mit.edu>
-Stable-dep-of: bdc56a9c46b2 ("ext4: fix e4b bitmap inconsistency reports")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- fs/ext4/mballoc.c | 3 +--
- 1 file changed, 1 insertion(+), 2 deletions(-)
-
-diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
-index 71e15007ffdf4..7431ff97a68c8 100644
---- a/fs/ext4/mballoc.c
-+++ b/fs/ext4/mballoc.c
-@@ -1599,8 +1599,7 @@ ext4_mb_load_buddy_gfp(struct super_block *sb, ext4_group_t group,
- put_page(page);
- if (e4b->bd_bitmap_page)
- put_page(e4b->bd_bitmap_page);
-- if (e4b->bd_buddy_page)
-- put_page(e4b->bd_buddy_page);
-+
- e4b->bd_buddy = NULL;
- e4b->bd_bitmap = NULL;
- return ret;
---
-2.51.0
-
ext4-don-t-zero-the-entire-extent-if-ext4_ext_data_p.patch
ext4-drop-extent-cache-after-doing-partial_valid1-ze.patch
ext4-drop-extent-cache-when-splitting-extent-fails.patch
-ext4-remove-unnecessary-e4b-bd_buddy_page-check-in-e.patch
-ext4-convert-some-bug_on-s-in-mballoc-to-use-warn_ra.patch
-ext4-delete-redundant-calculations-in-ext4_mb_get_bu.patch
-ext4-convert-bd_bitmap_page-to-bd_bitmap_folio.patch
-ext4-convert-bd_buddy_page-to-bd_buddy_folio.patch
-ext4-fix-e4b-bitmap-inconsistency-reports.patch
mfd-qcom-pm8xxx-convert-to-platform-remove-callback-.patch
mfd-qcom-pm8xxx-fix-of-populate-on-driver-rebind.patch
mfd-omap-usb-host-convert-to-platform-remove-callbac.patch