Re: [PATCH 1/1] fs: fix deadlock in insert_inode_locked() waiting for inode eviction

From: Xiang Shen

Date: Thu Mar 26 2026 - 19:43:33 EST


Withdrawing this in favor of Jan Kara's ext4-side fix.

Sorry for the noise.


On Fri, 27 Mar 2026 at 10:40, Xiang Shen <turyshen@xxxxxxxxx> wrote:
>
> Withdrawing this in favor of Jan Kara's ext4-side fix.
>
> Sorry for the noise.
>
> On Fri, 27 Mar 2026 at 10:29, Mateusz Guzik <mjguzik@xxxxxxxxx> wrote:
>>
>> On Fri, Mar 27, 2026 at 12:21 AM Xiang Shen <turyshen@xxxxxxxxx> wrote:
>> >
>> > Commit 88ec797c4680 ("fs: make insert_inode_locked() wait for inode
>> > destruction") changed insert_inode_locked() to sleep via
>> > __wait_on_freeing_inode() when it encounters an inode being freed. This
>> > introduces a deadlock when the caller already holds resources that the
>> > eviction path needs.
>> >
>> > For example, ext4_new_inode() holds an active jbd2 journal handle when
>> > it calls insert_inode_locked(). If a stale inode with the same ino is
>> > being freed, the function now sleeps waiting for eviction to complete.
>> > However, ext4_evict_inode() needs to start a new journal transaction via
>> > ext4_journal_start(), which may block in add_transaction_credits()
>> > waiting for the current transaction to commit. That transaction cannot
>> > commit because the caller's handle (in ext4_new_inode) is still active,
>> > resulting in a deadlock:
>> >
>> > Thread A (ext4_new_inode) Thread B (evicting old inode)
>> > ------------------------- ----------------------------
>> > jbd2_journal_start() -> handle
>> > insert_inode_locked()
>> > finds old inode I_FREEING
>> > __wait_on_freeing_inode()
>> > schedule() [waits for B] ext4_evict_inode()
>> > ext4_journal_start()
>> > add_transaction_credits()
>> > [waits for T to commit]
>> > [T blocked by A's handle]
>> >
>> > Fix this by replacing the blocking __wait_on_freeing_inode() call with a
>> > non-blocking drop-and-retry loop. When a freeing inode is encountered,
>> > drop both i_lock and inode_hash_lock, yield the CPU with cond_resched(),
>> > and restart the outer while(1) loop via continue.
>> >
>>
>> Please see the ext4 fix:
>> https://lore.kernel.org/linux-ext4/20260320090428.24899-2-jack@xxxxxxx/