Re: [PATCH RFC 0/2] Defer final iputs for dirty-time inodes in PF_MEMALLOC context

From: Jan Kara

Date: Tue Sep 01 2026 - 08:41:50 EST


I'm sorry for the delayed reply. Due to vacation and backlog after it it
took me long to get back to this.

On Thu 13-08-26 12:43:28, Mikhail Rudenko wrote:
> The motivation for this small series is the following kernel WARNING:
>
> [ 893.915584] ------------[ cut here ]------------
> [ 893.915589] WARNING: mm/page_alloc.c:4749 at __alloc_pages_slowpath.constprop.0+0xd4d/0x10f0, CPU#1: stress-ng-vm/3784

<snip>

> It was initially observed in the wild on linux 6.12.y, but later I
> reproduced it in Qemu with linux 7.0.11. I believe it is still an
> issue in the mainline master. Similar issue was reported earlier [1],
> but looks like no real analysis was performed then.
>
> The warning is triggered when a process with PF_MEMALLOC flag set
> requests a __GFP_NOFAIL page allocation. In this case, the allocation
> comes from ext4_dirty_inode() called when shrinker frees a dentry,
> resulting in i_count of an inode going zero, which in it turn can
> trigger sync_lazytime() if said inode has I_DIRTY_TIME flag, resulting
> in inode becoming dirty. On ext4 this causes an immediate journal
> transaction, which may lead to __GFP_NOFAIL allocation in the
> slowpath.

Yes, we are well aware of this problem. It actually goes significantly
further than just lazytime processing.

> The proposed approach to fix this basically boils down to "if need to
> do sync_lazytime() in PF_MEMALLOC context, defer instead".
>
> Patch 1 adds basic per-superblock infrastracture for deferring iputs:
> a workqueue, a work_struct, a list, a bool flag, a spinlock, and some
> glue code. A tricky place is superblock shutdown: we should stop
> accepting deferred iputs not too early, so that no legit cases fail to
> defer, and not too late, so that superblock is still operational and
> we can flush the workqueue. Since we cannot enter
> deactivate_locked_super() from PF_MEMALLOC context, stopping after
> shrinker_free() seems safe.
>
> Patch 2 uses this infrastructure to defer iputs of inodes with
> I_DIRTY_TIME, which would trigger sync_lazytime() otherwise, when
> running in PF_MEMALLOC context. Clumping default and PF_MEMALLOC paths
> together in iput() would have resulted in decreased readablity, so I
> avoided that by setting up a separate iput_memalloc(), at cost of
> slight code duplication.

Thanks for your patches. I've actually submitted patches to address this
problem back at the end of April [1]. In particularly the problem you
report was addressed somewhat differently by patch 1. We've then discussed
them at LSF/MM/BPF summit and people mostly agreed with the approach, just
there were some requests for better parallelization of deferred inode
reclaim (which I so far failed to implement). But it's currently high on my
todo list so I should hopefully send v2 of the patches for the next merge
window.

Honza

[1] https://lore.kernel.org/all/20260429174850.18223-1-jack@xxxxxxx/
--
Jan Kara <jack@xxxxxxxx>
SUSE Labs, CR