Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ext4: fix checks for orphan inodes

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>

authored by

Jan Kara and committed by
Theodore Ts'o
acf943e9 44d2a72f

+15 -9
+10
fs/ext4/ext4.h
··· 1996 1996 #define NEXT_ORPHAN(inode) EXT4_I(inode)->i_dtime 1997 1997 1998 1998 /* 1999 + * Check whether the inode is tracked as orphan (either in orphan file or 2000 + * orphan list). 2001 + */ 2002 + static inline bool ext4_inode_orphan_tracked(struct inode *inode) 2003 + { 2004 + return ext4_test_inode_state(inode, EXT4_STATE_ORPHAN_FILE) || 2005 + !list_empty(&EXT4_I(inode)->i_orphan); 2006 + } 2007 + 2008 + /* 1999 2009 * Codes for operating systems 2000 2010 */ 2001 2011 #define EXT4_OS_LINUX 0
+1 -1
fs/ext4/file.c
··· 354 354 * to cleanup the orphan list in ext4_handle_inode_extension(). Do it 355 355 * now. 356 356 */ 357 - if (!list_empty(&EXT4_I(inode)->i_orphan) && inode->i_nlink) { 357 + if (ext4_inode_orphan_tracked(inode) && inode->i_nlink) { 358 358 handle_t *handle = ext4_journal_start(inode, EXT4_HT_INODE, 2); 359 359 360 360 if (IS_ERR(handle)) {
+1 -1
fs/ext4/inode.c
··· 4719 4719 * old inodes get re-used with the upper 16 bits of the 4720 4720 * uid/gid intact. 4721 4721 */ 4722 - if (ei->i_dtime && list_empty(&ei->i_orphan)) { 4722 + if (ei->i_dtime && !ext4_inode_orphan_tracked(inode)) { 4723 4723 raw_inode->i_uid_high = 0; 4724 4724 raw_inode->i_gid_high = 0; 4725 4725 } else {
+1 -5
fs/ext4/orphan.c
··· 109 109 110 110 WARN_ON_ONCE(!(inode->i_state & (I_NEW | I_FREEING)) && 111 111 !inode_is_locked(inode)); 112 - /* 113 - * Inode orphaned in orphan file or in orphan list? 114 - */ 115 - if (ext4_test_inode_state(inode, EXT4_STATE_ORPHAN_FILE) || 116 - !list_empty(&EXT4_I(inode)->i_orphan)) 112 + if (ext4_inode_orphan_tracked(inode)) 117 113 return 0; 118 114 119 115 /*
+2 -2
fs/ext4/super.c
··· 1447 1447 1448 1448 static void ext4_destroy_inode(struct inode *inode) 1449 1449 { 1450 - if (!list_empty(&(EXT4_I(inode)->i_orphan))) { 1450 + if (ext4_inode_orphan_tracked(inode)) { 1451 1451 ext4_msg(inode->i_sb, KERN_ERR, 1452 - "Inode %lu (%p): orphan list check failed!", 1452 + "Inode %lu (%p): inode tracked as orphan!", 1453 1453 inode->i_ino, EXT4_I(inode)); 1454 1454 print_hex_dump(KERN_INFO, "", DUMP_PREFIX_ADDRESS, 16, 4, 1455 1455 EXT4_I(inode), sizeof(struct ext4_inode_info),