linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Sasha Levin <sashal@kernel.org>
To: tytso@mit.edu
Cc: yi.zhang@huawei.com, linux-ext4@vger.kernel.org,
	linux-kernel@vger.kernel.org, Sasha Levin <sashal@kernel.org>,
	stable@vger.kernel.org
Subject: [PATCH] ext4: fix JBD2 credit overflow with large folios
Date: Mon, 30 Jun 2025 09:13:24 -0400	[thread overview]
Message-ID: <20250630131324.1253313-1-sashal@kernel.org> (raw)

When large folios are enabled, the blocks-per-folio calculation in
ext4_da_writepages_trans_blocks() can overflow the journal transaction
limits, causing the writeback path to fail with errors like:

  JBD2: kworker/u8:0 wants too many credits credits:416 rsv_credits:21 max:334

This occurs with small block sizes (1KB) and large folios (32MB), where
the calculation results in 32768 blocks per folio. The transaction credit
calculation then requests more credits than the journal can handle, leading
to the following warning and writeback failure:

  WARNING: CPU: 1 PID: 43 at fs/jbd2/transaction.c:334 start_this_handle+0x4c0/0x4e0
  EXT4-fs (loop0): ext4_do_writepages: jbd2_start: 9223372036854775807 pages, ino 14; err -28

Call trace leading to the issue:
  ext4_do_writepages()
    ext4_da_writepages_trans_blocks()
      bpp = ext4_journal_blocks_per_folio() // Returns 32768 for 32MB folio with 1KB blocks
      ext4_meta_trans_blocks(inode, MAX_WRITEPAGES_EXTENT_LEN + bpp - 1, bpp)
        // With bpp=32768, lblocks=34815, pextents=32768
        // Returns credits=415, but with overhead becomes 416 > max 334
    ext4_journal_start_with_reserve()
      jbd2_journal_start_reserved()
        start_this_handle()
          // Fails with warning when credits:416 > max:334

The issue was introduced by commit d6bf294773a47 ("ext4/jbd2: convert
jbd2_journal_blocks_per_page() to support large folio"), which added
support for large folios but didn't account for the journal credit limits.

Fix this by capping the blocks-per-folio value at 8192 in the writeback
path. This is the value we'd get with 32MB folios and 4KB blocks, or 8MB
folios with 1KB blocks, which is reasonable and safe for typical journal
configurations.

Fixes: d6bf294773a4 ("ext4/jbd2: convert jbd2_journal_blocks_per_page() to support large folio")
Cc: stable@vger.kernel.org
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 fs/ext4/inode.c | 34 ++++++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)

diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index be9a4cba35fd5..860e59a176c97 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -2070,6 +2070,14 @@ static int mpage_submit_folio(struct mpage_da_data *mpd, struct folio *folio)
  */
 #define MAX_WRITEPAGES_EXTENT_LEN 2048
 
+/*
+ * Maximum blocks per folio to avoid JBD2 credit overflow.
+ * This is the value we'd get with 32MB folios and 4KB blocks,
+ * or 8MB folios with 1KB blocks, which is reasonable and safe
+ * for typical journal configurations.
+ */
+#define MAX_BLOCKS_PER_FOLIO_FOR_WRITEBACK 8192
+
 /*
  * mpage_add_bh_to_extent - try to add bh to extent of blocks to map
  *
@@ -2481,6 +2489,18 @@ static int ext4_da_writepages_trans_blocks(struct inode *inode)
 {
 	int bpp = ext4_journal_blocks_per_folio(inode);
 
+	/*
+	 * With large folios, blocks per folio can get excessively large,
+	 * especially with small block sizes. For example, with 32MB folios
+	 * (order 11) and 1KB blocks, we get 32768 blocks per folio. This
+	 * leads to credit requests that overflow the journal's transaction
+	 * limit.
+	 *
+	 * Limit the value to avoid excessive credit requests.
+	 */
+	if (bpp > MAX_BLOCKS_PER_FOLIO_FOR_WRITEBACK)
+		bpp = MAX_BLOCKS_PER_FOLIO_FOR_WRITEBACK;
+
 	return ext4_meta_trans_blocks(inode,
 				MAX_WRITEPAGES_EXTENT_LEN + bpp - 1, bpp);
 }
@@ -2559,6 +2579,13 @@ static int mpage_prepare_extent_to_map(struct mpage_da_data *mpd)
 	handle_t *handle = NULL;
 	int bpp = ext4_journal_blocks_per_folio(mpd->inode);
 
+	/*
+	 * With large folios, blocks per folio can get excessively large,
+	 * especially with small block sizes. Cap it to avoid credit overflow.
+	 */
+	if (bpp > MAX_BLOCKS_PER_FOLIO_FOR_WRITEBACK)
+		bpp = MAX_BLOCKS_PER_FOLIO_FOR_WRITEBACK;
+
 	if (mpd->wbc->sync_mode == WB_SYNC_ALL || mpd->wbc->tagged_writepages)
 		tag = PAGECACHE_TAG_TOWRITE;
 	else
@@ -6179,6 +6206,13 @@ int ext4_writepage_trans_blocks(struct inode *inode)
 	int bpp = ext4_journal_blocks_per_folio(inode);
 	int ret;
 
+	/*
+	 * With large folios, blocks per folio can get excessively large,
+	 * especially with small block sizes. Cap it to avoid credit overflow.
+	 */
+	if (bpp > MAX_BLOCKS_PER_FOLIO_FOR_WRITEBACK)
+		bpp = MAX_BLOCKS_PER_FOLIO_FOR_WRITEBACK;
+
 	ret = ext4_meta_trans_blocks(inode, bpp, bpp);
 
 	/* Account for data blocks for journalled mode */
-- 
2.39.5


             reply	other threads:[~2025-06-30 13:13 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-06-30 13:13 Sasha Levin [this message]
2025-06-30 13:58 ` [PATCH] ext4: fix JBD2 credit overflow with large folios Zhang Yi
2025-06-30 15:01   ` Sasha Levin

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=20250630131324.1253313-1-sashal@kernel.org \
    --to=sashal@kernel.org \
    --cc=linux-ext4@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --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 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).