public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: kth5965@gmail.com
To: Chao Yu <chao@kernel.org>,
	jaegeuk@kernel.org, linux-f2fs-devel@lists.sourceforge.net
Cc: syzbot+fc026e87558558f75c00@syzkaller.appspotmail.com,
	linux-kernel@vger.kernel.org
Subject: Re: [f2fs-dev] [PATCH v2] f2fs: evict: truncate page cache before clear_inode
Date: Wed,  1 Apr 2026 00:24:29 +0900	[thread overview]
Message-ID: <20260331152429.163173-1-kth5965@gmail.com> (raw)
In-Reply-To: <37c11065-e055-41b8-82a8-68f2fdf56ac3@kernel.org>

Sorry for the late reply.

I worked in that direction, and the fix ended up touching a bit more than I first expected.

One part that grew a bit was the empty/no-data inline conversion side.
To handle that case cleanly, I ended up consolidating part of the inline-state teardown so the no-data path and the normal inline-conversion cleanup follow the same path.
This also lets f2fs_convert_inline_inode() avoid grabbing folio #0 in the empty inline case.

With the current version, the reproducer no longer reaches the late clear_inode() BUG and instead fails earlier with Failed to read root inode.

If you think that cleanup change should be trimmed or split out, please let me know.

The current diff is below.

diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c
index 0a1052d5ee62..89e8a0fbb923 100644
--- a/fs/f2fs/inline.c
+++ b/fs/f2fs/inline.c
@@ -53,8 +53,8 @@ bool f2fs_sanity_check_inline_data(struct inode *inode, struct folio *ifolio)
	if (!f2fs_has_inline_data(inode))
		return false;

-	if (inode_has_blocks(inode, ifolio))
-		return false;
+	if (!f2fs_exist_data(inode) && inode_has_blocks(inode, ifolio))
+		return true;

	if (!support_inline_data(inode))
		return true;
@@ -142,6 +142,17 @@ int f2fs_read_inline_data(struct inode *inode, struct folio *folio)
	return 0;
 }

+static void f2fs_clear_inline_inode(struct dnode_of_data *dn)
+{
+	f2fs_folio_wait_writeback(dn->inode_folio, NODE, true, true);
+	clear_inode_flag(dn->inode, FI_DATA_EXIST);
+	stat_dec_inline_inode(dn->inode);
+	clear_inode_flag(dn->inode, FI_INLINE_DATA);
+	set_raw_inline(dn->inode, F2FS_INODE(dn->inode_folio));
+	folio_mark_dirty(dn->inode_folio);
+	folio_clear_f2fs_inline(dn->inode_folio);
+}
+
 int f2fs_convert_inline_folio(struct dnode_of_data *dn, struct folio *folio)
 {
	struct f2fs_io_info fio = {
@@ -157,8 +168,10 @@ int f2fs_convert_inline_folio(struct dnode_of_data *dn, struct folio *folio)
	struct node_info ni;
	int dirty, err;

-	if (!f2fs_exist_data(dn->inode))
-		goto clear_out;
+	if (!f2fs_exist_data(dn->inode)) {
+		f2fs_clear_inline_inode(dn);
+		goto out;
+	}

	err = f2fs_reserve_block(dn, 0);
	if (err)
		return err;
@@ -206,10 +219,8 @@ int f2fs_convert_inline_folio(struct dnode_of_data *dn, struct folio *folio)

	/* clear inline data and flag after data writeback */
	f2fs_truncate_inline_inode(dn->inode, dn->inode_folio, 0);
-	folio_clear_f2fs_inline(dn->inode_folio);
-clear_out:
-	stat_dec_inline_inode(dn->inode);
-	clear_inode_flag(dn->inode, FI_INLINE_DATA);
+	f2fs_clear_inline_inode(dn);
+out:
	f2fs_put_dnode(dn);
	return 0;
 }
@@ -219,7 +230,7 @@ int f2fs_convert_inline_inode(struct inode *inode)
	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
	struct dnode_of_data dn;
	struct f2fs_lock_context lc;
-	struct folio *ifolio, *folio;
+	struct folio *ifolio, *folio = NULL;
	int err = 0;

	if (f2fs_hw_is_readonly(sbi) || f2fs_readonly(sbi->sb))
		return -EROFS;
@@ -232,9 +243,13 @@ int f2fs_convert_inline_inode(struct inode *inode)
	if (err)
		return err;

-	folio = f2fs_grab_cache_folio(inode->i_mapping, 0, false);
-	if (IS_ERR(folio))
-		return PTR_ERR(folio);
+	if (f2fs_exist_data(inode)) {
+		folio = f2fs_grab_cache_folio(inode->i_mapping, 0, false);
+		if (IS_ERR(folio))
+			return PTR_ERR(folio);
+	}
+
+	set_new_dnode(&dn, inode, NULL, NULL, 0);

	f2fs_lock_op(sbi, &lc);

@@ -249,11 +264,11 @@ int f2fs_convert_inline_inode(struct inode *inode)
	if (f2fs_has_inline_data(inode))
		err = f2fs_convert_inline_folio(&dn, folio);

-	f2fs_put_dnode(&dn);
 out:
+	f2fs_put_dnode(&dn);
	f2fs_unlock_op(sbi, &lc);
-
-	f2fs_folio_put(folio, true);
+	if (folio)
+		f2fs_folio_put(folio, true);

	if (!err)
		f2fs_balance_fs(sbi, dn.node_changed);

      reply	other threads:[~2026-03-31 15:24 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-02-24 16:06 [PATCH] f2fs: evict: truncate page cache before clear_inode Taerang Kim
2026-02-24 16:54 ` [PATCH v2] " Taerang Kim
2026-03-09  7:44   ` Chao Yu
2026-03-09 14:25     ` [f2fs-dev] " kth5965
2026-03-13  7:45       ` Chao Yu
2026-03-17 15:28     ` kth5965
2026-03-18  3:40       ` Chao Yu
2026-03-19 15:11         ` kth5965
2026-03-23  3:14           ` Chao Yu
2026-03-31 15:24             ` kth5965 [this message]

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=20260331152429.163173-1-kth5965@gmail.com \
    --to=kth5965@gmail.com \
    --cc=chao@kernel.org \
    --cc=jaegeuk@kernel.org \
    --cc=linux-f2fs-devel@lists.sourceforge.net \
    --cc=linux-kernel@vger.kernel.org \
    --cc=syzbot+fc026e87558558f75c00@syzkaller.appspotmail.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