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 deadlock on inode reallocation

Currently there is a race in ext4 when reallocating freed inode
resulting in a deadlock:

Task1 Task2
ext4_evict_inode()
handle = ext4_journal_start();
...
if (IS_SYNC(inode))
handle->h_sync = 1;
ext4_free_inode()
ext4_new_inode()
handle = ext4_journal_start()
finds the bit in inode bitmap
already clear
insert_inode_locked()
waits for inode to be
removed from the hash.
ext4_journal_stop(handle)
jbd2_journal_stop(handle)
jbd2_log_wait_commit(journal, tid);
- deadlocks waiting for transaction handle Task2 holds

Fix the problem by removing inode from the hash already in
ext4_clear_inode() by which time all IO for the inode is done so reuse
is already fine but we are still before possibly blocking on transaction
commit.

Reported-by: "Lai, Yi" <yi1.lai@linux.intel.com>
Link: https://lore.kernel.org/all/abNvb2PcrKj1FBeC@ly-workstation
Fixes: 88ec797c4680 ("fs: make insert_inode_locked() wait for inode destruction")
CC: stable@vger.kernel.org
Signed-off-by: Jan Kara <jack@suse.cz>
Link: https://patch.msgid.link/20260320090428.24899-2-jack@suse.cz
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Cc: stable@kernel.org

authored by

Jan Kara and committed by
Theodore Ts'o
0c90eed1 d15e4b0a

+21
+21
fs/ext4/super.c
··· 1523 1523 invalidate_inode_buffers(inode); 1524 1524 clear_inode(inode); 1525 1525 ext4_discard_preallocations(inode); 1526 + /* 1527 + * We must remove the inode from the hash before ext4_free_inode() 1528 + * clears the bit in inode bitmap as otherwise another process reusing 1529 + * the inode will block in insert_inode_hash() waiting for inode 1530 + * eviction to complete while holding transaction handle open, but 1531 + * ext4_evict_inode() still running for that inode could block waiting 1532 + * for transaction commit if the inode is marked as IS_SYNC => deadlock. 1533 + * 1534 + * Removing the inode from the hash here is safe. There are two cases 1535 + * to consider: 1536 + * 1) The inode still has references to it (i_nlink > 0). In that case 1537 + * we are keeping the inode and once we remove the inode from the hash, 1538 + * iget() can create the new inode structure for the same inode number 1539 + * and we are fine with that as all IO on behalf of the inode is 1540 + * finished. 1541 + * 2) We are deleting the inode (i_nlink == 0). In that case inode 1542 + * number cannot be reused until ext4_free_inode() clears the bit in 1543 + * the inode bitmap, at which point all IO is done and reuse is fine 1544 + * again. 1545 + */ 1546 + remove_inode_hash(inode); 1526 1547 ext4_es_remove_extent(inode, 0, EXT_MAX_BLOCKS); 1527 1548 dquot_drop(inode); 1528 1549 if (EXT4_I(inode)->jinode) {