Skip to content

Commit acf943e

Browse files
jankaratytso
authored andcommitted
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: 4a79a98 ("ext4: Improve scalability of ext4 orphan file handling") Cc: [email protected] Signed-off-by: Jan Kara <[email protected]> Reviewed-by: Zhang Yi <[email protected]> Message-ID: <[email protected]> Signed-off-by: Theodore Ts'o <[email protected]>
1 parent 44d2a72 commit acf943e

File tree

5 files changed

+15
-9
lines changed

5 files changed

+15
-9
lines changed

fs/ext4/ext4.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1995,6 +1995,16 @@ static inline bool ext4_verity_in_progress(struct inode *inode)
19951995

19961996
#define NEXT_ORPHAN(inode) EXT4_I(inode)->i_dtime
19971997

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+
19982008
/*
19992009
* Codes for operating systems
20002010
*/

fs/ext4/file.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,7 @@ static void ext4_inode_extension_cleanup(struct inode *inode, bool need_trunc)
354354
* to cleanup the orphan list in ext4_handle_inode_extension(). Do it
355355
* now.
356356
*/
357-
if (!list_empty(&EXT4_I(inode)->i_orphan) && inode->i_nlink) {
357+
if (ext4_inode_orphan_tracked(inode) && inode->i_nlink) {
358358
handle_t *handle = ext4_journal_start(inode, EXT4_HT_INODE, 2);
359359

360360
if (IS_ERR(handle)) {

fs/ext4/inode.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4719,7 +4719,7 @@ static int ext4_fill_raw_inode(struct inode *inode, struct ext4_inode *raw_inode
47194719
* old inodes get re-used with the upper 16 bits of the
47204720
* uid/gid intact.
47214721
*/
4722-
if (ei->i_dtime && list_empty(&ei->i_orphan)) {
4722+
if (ei->i_dtime && !ext4_inode_orphan_tracked(inode)) {
47234723
raw_inode->i_uid_high = 0;
47244724
raw_inode->i_gid_high = 0;
47254725
} else {

fs/ext4/orphan.c

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -109,11 +109,7 @@ int ext4_orphan_add(handle_t *handle, struct inode *inode)
109109

110110
WARN_ON_ONCE(!(inode->i_state & (I_NEW | I_FREEING)) &&
111111
!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))
117113
return 0;
118114

119115
/*

fs/ext4/super.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1447,9 +1447,9 @@ static void ext4_free_in_core_inode(struct inode *inode)
14471447

14481448
static void ext4_destroy_inode(struct inode *inode)
14491449
{
1450-
if (!list_empty(&(EXT4_I(inode)->i_orphan))) {
1450+
if (ext4_inode_orphan_tracked(inode)) {
14511451
ext4_msg(inode->i_sb, KERN_ERR,
1452-
"Inode %lu (%p): orphan list check failed!",
1452+
"Inode %lu (%p): inode tracked as orphan!",
14531453
inode->i_ino, EXT4_I(inode));
14541454
print_hex_dump(KERN_INFO, "", DUMP_PREFIX_ADDRESS, 16, 4,
14551455
EXT4_I(inode), sizeof(struct ext4_inode_info),

0 commit comments

Comments
 (0)