Re: iomap_writepages WARN_ON_ONCE(PF_MEMALLOC)
From: Shakeel Butt
Date: Sat Jul 04 2026 - 00:40:37 EST
On Wed, Jul 01, 2026 at 10:51:06PM +0200, Andreas Gruenbacher wrote:
> Hi Christoph,
>
> I'm running into a problem with the following check in
> iomap_writepages() on gfs2 in RHEL-8:
>
> /*
> * Writeback from reclaim context should never happen except in the case
> * of a VM regression so warn about it and refuse to write the data.
> */
> if (WARN_ON_ONCE((current->flags & (PF_MEMALLOC | PF_KSWAPD)) ==
> PF_MEMALLOC))
> return -EIO;
>
> In my case, reclaim is triggered by the following command:
>
> echo anything > /sys/fs/cgroup/memory/.../memory.force_empty
>
> And we end up on this code path:
>
> mem_cgroup_force_empty_write -> mem_cgroup_force_empty ->
> try_to_free_mem_cgroup_pages -> do_try_to_free_pages ->
> shrink_zones -> shrink_node -> shrink_node_memcgs -> shrink_slab ->
> do_shrink_slab -> super_cache_scan -> prune_icache_sb -> dispose_list ->
> evict -> gfs2_evict_inode -> evict_linked_inode -> gfs2_log_flush ->
> gfs2_ordered_write -> filemap_fdatawrite -> __filemap_fdatawrite ->
> __filemap_fdatawrite_range -> do_writepages -> gfs2_writepages ->
> iomap_writepages
I don't see anything specific to memcg here as the same code path as above can
be taken in the global reclaim. The main question is why gfs2 is evicting a
dirty inode from reclaim. If you check prune_icache_sb which uses
inode_lru_isolate() to select inodes to evict and inode_lru_isolate() has
(inode_state_read(inode) & ~I_REFERENCED) check to filter dirty inodes.
It seems to me that gfs2 and VFS are not agreeing if an inode is dirty or not
and a simple search in gfs2 shows that it is doing (inode->i_flags & I_DIRTY)
instead of (inode_state_read(inode) & I_DIRTY)). Since core vfs code is using
inode_state_read() wrapper to check inode state, I am assuming that is the right
way to do it.