From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: stable@vger.kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
patches@lists.linux.dev, Jan Kara <jack@suse.cz>,
Zhang Yi <yi.zhang@huawei.com>, Theodore Tso <tytso@mit.edu>
Subject: [PATCH 6.16 5/9] ext4: restart handle if credits are insufficient during allocating blocks
Date: Fri, 22 Aug 2025 14:37:05 +0200 [thread overview]
Message-ID: <20250822123516.985354032@linuxfoundation.org> (raw)
In-Reply-To: <20250822123516.780248736@linuxfoundation.org>
6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhang Yi <yi.zhang@huawei.com>
commit e2c4c49dee64ca2f42ad2958cbe1805de96b6732 upstream.
After large folios are supported on ext4, writing back a sufficiently
large and discontinuous folio may consume a significant number of
journal credits, placing considerable strain on the journal. For
example, in a 20GB filesystem with 1K block size and 1MB journal size,
writing back a 2MB folio could require thousands of credits in the
worst-case scenario (when each block is discontinuous and distributed
across different block groups), potentially exceeding the journal size.
This issue can also occur in ext4_write_begin() and ext4_page_mkwrite()
when delalloc is not enabled.
Fix this by ensuring that there are sufficient journal credits before
allocating an extent in mpage_map_one_extent() and
ext4_block_write_begin(). If there are not enough credits, return
-EAGAIN, exit the current mapping loop, restart a new handle and a new
transaction, and allocating blocks on this folio again in the next
iteration.
Suggested-by: Jan Kara <jack@suse.cz>
Signed-off-by: Zhang Yi <yi.zhang@huawei.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Link: https://patch.msgid.link/20250707140814.542883-6-yi.zhang@huaweicloud.com
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/ext4/inode.c | 41 ++++++++++++++++++++++++++++++++++++-----
1 file changed, 36 insertions(+), 5 deletions(-)
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -877,6 +877,26 @@ static void ext4_update_bh_state(struct
} while (unlikely(!try_cmpxchg(&bh->b_state, &old_state, new_state)));
}
+/*
+ * Make sure that the current journal transaction has enough credits to map
+ * one extent. Return -EAGAIN if it cannot extend the current running
+ * transaction.
+ */
+static inline int ext4_journal_ensure_extent_credits(handle_t *handle,
+ struct inode *inode)
+{
+ int credits;
+ int ret;
+
+ /* Called from ext4_da_write_begin() which has no handle started? */
+ if (!handle)
+ return 0;
+
+ credits = ext4_chunk_trans_blocks(inode, 1);
+ ret = __ext4_journal_ensure_credits(handle, credits, credits, 0);
+ return ret <= 0 ? ret : -EAGAIN;
+}
+
static int _ext4_get_block(struct inode *inode, sector_t iblock,
struct buffer_head *bh, int flags)
{
@@ -1175,7 +1195,9 @@ int ext4_block_write_begin(handle_t *han
clear_buffer_new(bh);
if (!buffer_mapped(bh)) {
WARN_ON(bh->b_size != blocksize);
- err = get_block(inode, block, bh, 1);
+ err = ext4_journal_ensure_extent_credits(handle, inode);
+ if (!err)
+ err = get_block(inode, block, bh, 1);
if (err)
break;
if (buffer_new(bh)) {
@@ -1374,8 +1396,9 @@ retry_journal:
ext4_orphan_del(NULL, inode);
}
- if (ret == -ENOSPC &&
- ext4_should_retry_alloc(inode->i_sb, &retries))
+ if (ret == -EAGAIN ||
+ (ret == -ENOSPC &&
+ ext4_should_retry_alloc(inode->i_sb, &retries)))
goto retry_journal;
folio_put(folio);
return ret;
@@ -2324,6 +2347,11 @@ static int mpage_map_one_extent(handle_t
int get_blocks_flags;
int err, dioread_nolock;
+ /* Make sure transaction has enough credits for this extent */
+ err = ext4_journal_ensure_extent_credits(handle, inode);
+ if (err < 0)
+ return err;
+
trace_ext4_da_write_pages_extent(inode, map);
/*
* Call ext4_map_blocks() to allocate any delayed allocation blocks, or
@@ -2451,7 +2479,7 @@ static int mpage_map_and_submit_extent(h
* In the case of ENOSPC, if ext4_count_free_blocks()
* is non-zero, a commit should free up blocks.
*/
- if ((err == -ENOMEM) ||
+ if ((err == -ENOMEM) || (err == -EAGAIN) ||
(err == -ENOSPC && ext4_count_free_clusters(sb))) {
/*
* We may have already allocated extents for
@@ -2957,6 +2985,8 @@ retry:
ret = 0;
continue;
}
+ if (ret == -EAGAIN)
+ ret = 0;
/* Fatal error - ENOMEM, EIO... */
if (ret)
break;
@@ -6751,7 +6781,8 @@ vm_fault_t ext4_page_mkwrite(struct vm_f
retry_alloc:
/* Start journal and allocate blocks */
err = ext4_block_page_mkwrite(inode, folio, get_block);
- if (err == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries))
+ if (err == -EAGAIN ||
+ (err == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries)))
goto retry_alloc;
out_ret:
ret = vmf_fs_error(err);
next prev parent reply other threads:[~2025-08-22 12:37 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-08-22 12:37 [PATCH 6.16 0/9] 6.16.3-rc1 review Greg Kroah-Hartman
2025-08-22 12:37 ` [PATCH 6.16 1/9] ext4: process folios writeback in bytes Greg Kroah-Hartman
2025-08-22 12:37 ` [PATCH 6.16 2/9] ext4: move the calculation of wbc->nr_to_write to mpage_folio_done() Greg Kroah-Hartman
2025-08-22 12:37 ` [PATCH 6.16 3/9] ext4: fix stale data if it bail out of the extents mapping loop Greg Kroah-Hartman
2025-08-22 12:37 ` [PATCH 6.16 4/9] ext4: refactor the block allocation process of ext4_page_mkwrite() Greg Kroah-Hartman
2025-08-22 12:37 ` Greg Kroah-Hartman [this message]
2025-08-22 12:37 ` [PATCH 6.16 6/9] ext4: enhance tracepoints during the folios writeback Greg Kroah-Hartman
2025-08-22 12:37 ` [PATCH 6.16 7/9] ext4: correct the reserved credits for extent conversion Greg Kroah-Hartman
2025-08-22 12:37 ` [PATCH 6.16 8/9] ext4: reserved credits for one extent during the folio writeback Greg Kroah-Hartman
2025-08-22 12:37 ` [PATCH 6.16 9/9] ext4: replace ext4_writepage_trans_blocks() Greg Kroah-Hartman
2025-08-22 13:42 ` [PATCH 6.16 0/9] 6.16.3-rc1 review Ronald Warsow
2025-08-22 14:49 ` Markus Reichelt
2025-08-22 14:59 ` Greg KH
2025-08-22 21:00 ` Takeshi Ogasawara
2025-08-22 21:29 ` Florian Fainelli
2025-08-22 23:27 ` Peter Schneider
2025-08-23 8:32 ` Naresh Kamboju
2025-08-23 12:42 ` Brett A C Sheffield
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250822123516.985354032@linuxfoundation.org \
--to=gregkh@linuxfoundation.org \
--cc=jack@suse.cz \
--cc=patches@lists.linux.dev \
--cc=stable@vger.kernel.org \
--cc=tytso@mit.edu \
--cc=yi.zhang@huawei.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.