From: Baokun Li <libaokun@linux.alibaba.com>
To: linux-ext4@vger.kernel.org
Cc: tytso@mit.edu, adilger.kernel@dilger.ca, jack@suse.cz,
yi.zhang@huawei.com, ojaswin@linux.ibm.com,
ritesh.list@gmail.com
Subject: [PATCH e2fsprogs 5/5] tests: add orphan-cleanup flush regression test
Date: Tue, 14 Jul 2026 14:31:36 +0800 [thread overview]
Message-ID: <20260714063136.1284287-6-libaokun@linux.alibaba.com> (raw)
In-Reply-To: <20260714063136.1284287-1-libaokun@linux.alibaba.com>
Add f_orphan_flush_abort, which drives e2fsck directly:
1. Build an ext4 image whose inode 12 is an orphan (links_count 0,
s_last_orphan = 12).
2. Run e2fsck with a nonexistent bad-blocks file so that orphan
cleanup runs first and then read_bad_blocks_file aborts the run
via exit() before the normal superblock write-back.
3. Check that s_last_orphan is 0 on disk afterwards.
Without the flush after orphan cleanup, s_last_orphan stays stale on
disk (still 12) while the orphan inode has already been written back,
which the kernel rejects as a "bad orphan inode" on next mount.
Signed-off-by: Baokun Li <libaokun@linux.alibaba.com>
---
tests/f_orphan_flush_abort/expect.1 | 7 ++++
tests/f_orphan_flush_abort/name | 1 +
tests/f_orphan_flush_abort/script | 61 +++++++++++++++++++++++++++++
3 files changed, 69 insertions(+)
create mode 100644 tests/f_orphan_flush_abort/expect.1
create mode 100644 tests/f_orphan_flush_abort/name
create mode 100644 tests/f_orphan_flush_abort/script
diff --git a/tests/f_orphan_flush_abort/expect.1 b/tests/f_orphan_flush_abort/expect.1
new file mode 100644
index 000000000000..0a6d09f16e36
--- /dev/null
+++ b/tests/f_orphan_flush_abort/expect.1
@@ -0,0 +1,7 @@
+Clearing orphaned inode 12 (uid=0, gid=0, mode=0100644, size=8192)
+read_bad_blocks_file: No such file or directory while trying to open test.img
+
+test.img: ***** FILE SYSTEM WAS MODIFIED *****
+Exit status is 9
+Orphan before e2fsck: 12
+Orphan after e2fsck: 0 (cleared)
diff --git a/tests/f_orphan_flush_abort/name b/tests/f_orphan_flush_abort/name
new file mode 100644
index 000000000000..c9292546c6dd
--- /dev/null
+++ b/tests/f_orphan_flush_abort/name
@@ -0,0 +1 @@
+orphan cleanup superblock flush survives a later abort
diff --git a/tests/f_orphan_flush_abort/script b/tests/f_orphan_flush_abort/script
new file mode 100644
index 000000000000..9c18011b40db
--- /dev/null
+++ b/tests/f_orphan_flush_abort/script
@@ -0,0 +1,61 @@
+if ! test -x $DEBUGFS_EXE; then
+ echo "$test_name: $test_description: skipped (no debugfs)"
+ return 0
+fi
+
+TEST_DATA="$test_name.tmp"
+OUT=$test_name.log
+
+dd if=/dev/zero of=$TEST_DATA bs=8k count=1 > /dev/null 2>&1
+
+$MKE2FS -Fq -t ext4 -o Linux $TMPFILE 4M > /dev/null 2>&1
+
+# Create an orphan inode: testfile becomes inode 12 (the first regular inode
+# on a fresh fs), drop its link count to 0 and point s_last_orphan at it so
+# e2fsck will run orphan cleanup.
+$DEBUGFS -w $TMPFILE << EOF > /dev/null 2>&1
+write $TEST_DATA testfile
+set_inode_field testfile links_count 0
+set_super_value last_orphan 12
+unlink testfile
+quit
+EOF
+
+ORPHAN_BEFORE=$($DUMPE2FS $TMPFILE 2>&1 | grep -E "First orphan inode" | awk '{print $NF}')
+
+cp /dev/null $OUT
+
+# Run e2fsck with a nonexistent bad blocks file. Orphan cleanup runs first
+# and clears s_last_orphan, then read_bad_blocks_file fails and e2fsck aborts
+# via exit() before the normal superblock write-back. The fix flushes the
+# superblock right after orphan cleanup, so s_last_orphan is 0 on disk even
+# though the run aborted; without it the disk keeps a stale s_last_orphan
+# while the orphan inode has already been written back, which the kernel
+# rejects as a "bad orphan inode" on next mount.
+$FSCK -yf -l /nonexistent/bad_blocks_file $TMPFILE > $OUT.new 2>&1
+status=$?
+echo "Exit status is $status" >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s|$TMPFILE|test.img|g" $OUT.new > $OUT
+rm -f $OUT.new
+
+ORPHAN_AFTER=$($DUMPE2FS $TMPFILE 2>&1 | grep -E "First orphan inode" | awk '{print $NF}')
+
+echo "Orphan before e2fsck: $ORPHAN_BEFORE" >> $OUT
+if [ -z "$ORPHAN_AFTER" ]; then
+ echo "Orphan after e2fsck: 0 (cleared)" >> $OUT
+else
+ echo "Orphan after e2fsck: $ORPHAN_AFTER (BUG: should be 0!)" >> $OUT
+fi
+
+cmp -s $OUT $test_dir/expect.1
+status=$?
+if [ "$status" -eq 0 ]; then
+ echo "$test_name: $test_description: ok"
+ touch $test_name.ok
+else
+ echo "$test_name: $test_description: failed"
+ diff $DIFF_OPTS $test_dir/expect.1 $OUT > $test_name.failed
+fi
+
+rm -f $TEST_DATA
+unset OUT TEST_DATA
--
2.43.7
prev parent reply other threads:[~2026-07-14 6:31 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-14 6:31 [PATCH e2fsprogs 0/5] fsck: fix stale "bad orphan inode" after fsck runs Baokun Li
2026-07-14 6:31 ` [PATCH e2fsprogs 1/5] fsck: consume -l option instead of passing to e2fsck Baokun Li
2026-07-14 6:31 ` [PATCH e2fsprogs 2/5] fsck: fix -C fd option parsing when fd is a separate argument Baokun Li
2026-07-14 6:31 ` [PATCH e2fsprogs 3/5] e2fsck: flush superblock immediately after orphan cleanup Baokun Li
2026-07-14 6:31 ` [PATCH e2fsprogs 4/5] tests: add fsck option-parsing regression test Baokun Li
2026-07-14 6:31 ` Baokun Li [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=20260714063136.1284287-6-libaokun@linux.alibaba.com \
--to=libaokun@linux.alibaba.com \
--cc=adilger.kernel@dilger.ca \
--cc=jack@suse.cz \
--cc=linux-ext4@vger.kernel.org \
--cc=ojaswin@linux.ibm.com \
--cc=ritesh.list@gmail.com \
--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.