Skip to content

Commit 0c90eed

Browse files
jankaratytso
authored andcommitted
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: 88ec797 ("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
1 parent d15e4b0 commit 0c90eed

1 file changed

Lines changed: 21 additions & 0 deletions

File tree

fs/ext4/super.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1523,6 +1523,27 @@ void ext4_clear_inode(struct inode *inode)
15231523
invalidate_inode_buffers(inode);
15241524
clear_inode(inode);
15251525
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);
15261547
ext4_es_remove_extent(inode, 0, EXT_MAX_BLOCKS);
15271548
dquot_drop(inode);
15281549
if (EXT4_I(inode)->jinode) {

0 commit comments

Comments
 (0)