Commit ecf5fc6
mm, vmscan: Do not wait for page writeback for GFP_NOFS allocations
Nikolay has reported a hang when a memcg reclaim got stuck with the
following backtrace:
PID: 18308 TASK: ffff883d7c9b0a30 CPU: 1 COMMAND: "rsync"
#0 __schedule at ffffffff815ab152
SolidRun#1 schedule at ffffffff815ab76e
SolidRun#2 schedule_timeout at ffffffff815ae5e5
SolidRun#3 io_schedule_timeout at ffffffff815aad6a
SolidRun#4 bit_wait_io at ffffffff815abfc6
SolidRun#5 __wait_on_bit at ffffffff815abda5
SolidRun#6 wait_on_page_bit at ffffffff8111fd4f
SolidRun#7 shrink_page_list at ffffffff81135445
SolidRun#8 shrink_inactive_list at ffffffff81135845
SolidRun#9 shrink_lruvec at ffffffff81135ead
SolidRun#10 shrink_zone at ffffffff811360c3
SolidRun#11 shrink_zones at ffffffff81136eff
SolidRun#12 do_try_to_free_pages at ffffffff8113712f
SolidRun#13 try_to_free_mem_cgroup_pages at ffffffff811372be
SolidRun#14 try_charge at ffffffff81189423
SolidRun#15 mem_cgroup_try_charge at ffffffff8118c6f5
SolidRun#16 __add_to_page_cache_locked at ffffffff8112137d
SolidRun#17 add_to_page_cache_lru at ffffffff81121618
SolidRun#18 pagecache_get_page at ffffffff8112170b
SolidRun#19 grow_dev_page at ffffffff811c8297
SolidRun#20 __getblk_slow at ffffffff811c91d6
SolidRun#21 __getblk_gfp at ffffffff811c92c1
SolidRun#22 ext4_ext_grow_indepth at ffffffff8124565c
SolidRun#23 ext4_ext_create_new_leaf at ffffffff81246ca8
SolidRun#24 ext4_ext_insert_extent at ffffffff81246f09
SolidRun#25 ext4_ext_map_blocks at ffffffff8124a848
SolidRun#26 ext4_map_blocks at ffffffff8121a5b7
SolidRun#27 mpage_map_one_extent at ffffffff8121b1fa
SolidRun#28 mpage_map_and_submit_extent at ffffffff8121f07b
SolidRun#29 ext4_writepages at ffffffff8121f6d5
SolidRun#30 do_writepages at ffffffff8112c490
SolidRun#31 __filemap_fdatawrite_range at ffffffff81120199
SolidRun#32 filemap_flush at ffffffff8112041c
SolidRun#33 ext4_alloc_da_blocks at ffffffff81219da1
SolidRun#34 ext4_rename at ffffffff81229b91
SolidRun#35 ext4_rename2 at ffffffff81229e32
SolidRun#36 vfs_rename at ffffffff811a08a5
SolidRun#37 SYSC_renameat2 at ffffffff811a3ffc
SolidRun#38 sys_renameat2 at ffffffff811a408e
SolidRun#39 sys_rename at ffffffff8119e51e
SolidRun#40 system_call_fastpath at ffffffff815afa89
Dave Chinner has properly pointed out that this is a deadlock in the
reclaim code because ext4 doesn't submit pages which are marked by
PG_writeback right away.
The heuristic was introduced by commit e62e384 ("memcg: prevent OOM
with too many dirty pages") and it was applied only when may_enter_fs
was specified. The code has been changed by c3b94f4 ("memcg:
further prevent OOM with too many dirty pages") which has removed the
__GFP_FS restriction with a reasoning that we do not get into the fs
code. But this is not sufficient apparently because the fs doesn't
necessarily submit pages marked PG_writeback for IO right away.
ext4_bio_write_page calls io_submit_add_bh but that doesn't necessarily
submit the bio. Instead it tries to map more pages into the bio and
mpage_map_one_extent might trigger memcg charge which might end up
waiting on a page which is marked PG_writeback but hasn't been submitted
yet so we would end up waiting for something that never finishes.
Fix this issue by replacing __GFP_IO by may_enter_fs check (for case 2)
before we go to wait on the writeback. The page fault path, which is
the only path that triggers memcg oom killer since 3.12, shouldn't
require GFP_NOFS and so we shouldn't reintroduce the premature OOM
killer issue which was originally addressed by the heuristic.
As per David Chinner the xfs is doing similar thing since 2.6.15 already
so ext4 is not the only affected filesystem. Moreover he notes:
: For example: IO completion might require unwritten extent conversion
: which executes filesystem transactions and GFP_NOFS allocations. The
: writeback flag on the pages can not be cleared until unwritten
: extent conversion completes. Hence memory reclaim cannot wait on
: page writeback to complete in GFP_NOFS context because it is not
: safe to do so, memcg reclaim or otherwise.
Cc: [email protected] # 3.9+
[[email protected]: corrected the control flow]
Fixes: c3b94f4 ("memcg: further prevent OOM with too many dirty pages")
Reported-by: Nikolay Borisov <[email protected]>
Signed-off-by: Michal Hocko <[email protected]>
Signed-off-by: Hugh Dickins <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>1 parent 6c84461 commit ecf5fc6
1 file changed
Lines changed: 6 additions & 10 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
973 | 973 | | |
974 | 974 | | |
975 | 975 | | |
976 | | - | |
977 | | - | |
| 976 | + | |
| 977 | + | |
| 978 | + | |
978 | 979 | | |
979 | 980 | | |
980 | | - | |
| 981 | + | |
| 982 | + | |
981 | 983 | | |
982 | 984 | | |
983 | 985 | | |
984 | 986 | | |
985 | 987 | | |
986 | | - | |
987 | | - | |
988 | | - | |
989 | | - | |
990 | | - | |
991 | | - | |
992 | 988 | | |
993 | 989 | | |
994 | 990 | | |
| |||
1005 | 1001 | | |
1006 | 1002 | | |
1007 | 1003 | | |
1008 | | - | |
| 1004 | + | |
1009 | 1005 | | |
1010 | 1006 | | |
1011 | 1007 | | |
| |||
0 commit comments