mirror of
https://gitee.com/bianbu-linux/linux-6.6
synced 2025-04-24 14:07:52 -04:00
vmscan: all_unreclaimable() use zone->all_unreclaimable as a name
all_unreclaimable check in direct reclaim has been introduced at 2.6.19 by following commit. 2006 Sep 25; commit408d8544
; oom: use unreclaimable info And it went through strange history. firstly, following commit broke the logic unintentionally. 2008 Apr 29; commita41f24ea
; page allocator: smarter retry of costly-order allocations Two years later, I've found obvious meaningless code fragment and restored original intention by following commit. 2010 Jun 04; commitbb21c7ce
; vmscan: fix do_try_to_free_pages() return value when priority==0 But, the logic didn't works when 32bit highmem system goes hibernation and Minchan slightly changed the algorithm and fixed it . 2010 Sep 22: commitd1908362
: vmscan: check all_unreclaimable in direct reclaim path But, recently, Andrey Vagin found the new corner case. Look, struct zone { .. int all_unreclaimable; .. unsigned long pages_scanned; .. } zone->all_unreclaimable and zone->pages_scanned are neigher atomic variables nor protected by lock. Therefore zones can become a state of zone->page_scanned=0 and zone->all_unreclaimable=1. In this case, current all_unreclaimable() return false even though zone->all_unreclaimabe=1. This resulted in the kernel hanging up when executing a loop of the form 1. fork 2. mmap 3. touch memory 4. read memory 5. munmmap as described in1348725 (1348725)
Is this ignorable minor issue? No. Unfortunately, x86 has very small dma zone and it become zone->all_unreclamble=1 easily. and if it become all_unreclaimable=1, it never restore all_unreclaimable=0. Why? if all_unreclaimable=1, vmscan only try DEF_PRIORITY reclaim and a-few-lru-pages>>DEF_PRIORITY always makes 0. that mean no page scan at all! Eventually, oom-killer never works on such systems. That said, we can't use zone->pages_scanned for this purpose. This patch restore all_unreclaimable() use zone->all_unreclaimable as old. and in addition, to add oom_killer_disabled check to avoid reintroduce the issue of commitd1908362
("vmscan: check all_unreclaimable in direct reclaim path"). Reported-by: Andrey Vagin <avagin@openvz.org> Signed-off-by: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> Cc: Nick Piggin <npiggin@kernel.dk> Reviewed-by: Minchan Kim <minchan.kim@gmail.com> Reviewed-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Acked-by: David Rientjes <rientjes@google.com> Cc: <stable@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
fe936dfc23
commit
929bea7c71
1 changed files with 13 additions and 11 deletions
24
mm/vmscan.c
24
mm/vmscan.c
|
@ -41,6 +41,7 @@
|
|||
#include <linux/memcontrol.h>
|
||||
#include <linux/delayacct.h>
|
||||
#include <linux/sysctl.h>
|
||||
#include <linux/oom.h>
|
||||
|
||||
#include <asm/tlbflush.h>
|
||||
#include <asm/div64.h>
|
||||
|
@ -1988,17 +1989,12 @@ static bool zone_reclaimable(struct zone *zone)
|
|||
return zone->pages_scanned < zone_reclaimable_pages(zone) * 6;
|
||||
}
|
||||
|
||||
/*
|
||||
* As hibernation is going on, kswapd is freezed so that it can't mark
|
||||
* the zone into all_unreclaimable. It can't handle OOM during hibernation.
|
||||
* So let's check zone's unreclaimable in direct reclaim as well as kswapd.
|
||||
*/
|
||||
/* All zones in zonelist are unreclaimable? */
|
||||
static bool all_unreclaimable(struct zonelist *zonelist,
|
||||
struct scan_control *sc)
|
||||
{
|
||||
struct zoneref *z;
|
||||
struct zone *zone;
|
||||
bool all_unreclaimable = true;
|
||||
|
||||
for_each_zone_zonelist_nodemask(zone, z, zonelist,
|
||||
gfp_zone(sc->gfp_mask), sc->nodemask) {
|
||||
|
@ -2006,13 +2002,11 @@ static bool all_unreclaimable(struct zonelist *zonelist,
|
|||
continue;
|
||||
if (!cpuset_zone_allowed_hardwall(zone, GFP_KERNEL))
|
||||
continue;
|
||||
if (zone_reclaimable(zone)) {
|
||||
all_unreclaimable = false;
|
||||
break;
|
||||
}
|
||||
if (!zone->all_unreclaimable)
|
||||
return false;
|
||||
}
|
||||
|
||||
return all_unreclaimable;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2108,6 +2102,14 @@ out:
|
|||
if (sc->nr_reclaimed)
|
||||
return sc->nr_reclaimed;
|
||||
|
||||
/*
|
||||
* As hibernation is going on, kswapd is freezed so that it can't mark
|
||||
* the zone into all_unreclaimable. Thus bypassing all_unreclaimable
|
||||
* check.
|
||||
*/
|
||||
if (oom_killer_disabled)
|
||||
return 0;
|
||||
|
||||
/* top priority shrink_zones still had more to do? don't OOM, then */
|
||||
if (scanning_global_lru(sc) && !all_unreclaimable(zonelist, sc))
|
||||
return 1;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue