--- /dev/null
+From acf943e9768ec9d9be80982ca0ebc4bfd6b7631e Mon Sep 17 00:00:00 2001
+From: Jan Kara <jack@suse.cz>
+Date: Thu, 25 Sep 2025 14:30:39 +0200
+Subject: ext4: fix checks for orphan inodes
+
+From: Jan Kara <jack@suse.cz>
+
+commit acf943e9768ec9d9be80982ca0ebc4bfd6b7631e upstream.
+
+When orphan file feature is enabled, inode can be tracked as orphan
+either in the standard orphan list or in the orphan file. The first can
+be tested by checking ei->i_orphan list head, the second is recorded by
+EXT4_STATE_ORPHAN_FILE inode state flag. There are several places where
+we want to check whether inode is tracked as orphan and only some of
+them properly check for both possibilities. Luckily the consequences are
+mostly minor, the worst that can happen is that we track an inode as
+orphan although we don't need to and e2fsck then complains (resulting in
+occasional ext4/307 xfstest failures). Fix the problem by introducing a
+helper for checking whether an inode is tracked as orphan and use it in
+appropriate places.
+
+Fixes: 4a79a98c7b19 ("ext4: Improve scalability of ext4 orphan file handling")
+Cc: stable@kernel.org
+Signed-off-by: Jan Kara <jack@suse.cz>
+Reviewed-by: Zhang Yi <yi.zhang@huawei.com>
+Message-ID: <20250925123038.20264-2-jack@suse.cz>
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ext4/ext4.h | 10 ++++++++++
+ fs/ext4/file.c | 2 +-
+ fs/ext4/inode.c | 2 +-
+ fs/ext4/orphan.c | 6 +-----
+ fs/ext4/super.c | 4 ++--
+ 5 files changed, 15 insertions(+), 9 deletions(-)
+
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1944,6 +1944,16 @@ static inline bool ext4_verity_in_progre
+ #define NEXT_ORPHAN(inode) EXT4_I(inode)->i_dtime
+
+ /*
++ * Check whether the inode is tracked as orphan (either in orphan file or
++ * orphan list).
++ */
++static inline bool ext4_inode_orphan_tracked(struct inode *inode)
++{
++ return ext4_test_inode_state(inode, EXT4_STATE_ORPHAN_FILE) ||
++ !list_empty(&EXT4_I(inode)->i_orphan);
++}
++
++/*
+ * Codes for operating systems
+ */
+ #define EXT4_OS_LINUX 0
+--- a/fs/ext4/file.c
++++ b/fs/ext4/file.c
+@@ -327,7 +327,7 @@ static void ext4_inode_extension_cleanup
+ * to cleanup the orphan list in ext4_handle_inode_extension(). Do it
+ * now.
+ */
+- if (!list_empty(&EXT4_I(inode)->i_orphan) && inode->i_nlink) {
++ if (ext4_inode_orphan_tracked(inode) && inode->i_nlink) {
+ handle_t *handle = ext4_journal_start(inode, EXT4_HT_INODE, 2);
+
+ if (IS_ERR(handle)) {
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -5122,7 +5122,7 @@ static int ext4_do_update_inode(handle_t
+ * old inodes get re-used with the upper 16 bits of the
+ * uid/gid intact.
+ */
+- if (ei->i_dtime && list_empty(&ei->i_orphan)) {
++ if (ei->i_dtime && !ext4_inode_orphan_tracked(inode)) {
+ raw_inode->i_uid_high = 0;
+ raw_inode->i_gid_high = 0;
+ } else {
+--- a/fs/ext4/orphan.c
++++ b/fs/ext4/orphan.c
+@@ -109,11 +109,7 @@ int ext4_orphan_add(handle_t *handle, st
+
+ WARN_ON_ONCE(!(inode->i_state & (I_NEW | I_FREEING)) &&
+ !inode_is_locked(inode));
+- /*
+- * Inode orphaned in orphan file or in orphan list?
+- */
+- if (ext4_test_inode_state(inode, EXT4_STATE_ORPHAN_FILE) ||
+- !list_empty(&EXT4_I(inode)->i_orphan))
++ if (ext4_inode_orphan_tracked(inode))
+ return 0;
+
+ /*
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1352,9 +1352,9 @@ static void ext4_free_in_core_inode(stru
+
+ static void ext4_destroy_inode(struct inode *inode)
+ {
+- if (!list_empty(&(EXT4_I(inode)->i_orphan))) {
++ if (ext4_inode_orphan_tracked(inode)) {
+ ext4_msg(inode->i_sb, KERN_ERR,
+- "Inode %lu (%p): orphan list check failed!",
++ "Inode %lu (%p): inode tracked as orphan!",
+ inode->i_ino, EXT4_I(inode));
+ print_hex_dump(KERN_INFO, "", DUMP_PREFIX_ADDRESS, 16, 4,
+ EXT4_I(inode), sizeof(struct ext4_inode_info),