mm: kswapd spinning on unreclaimable nodes - fixes and cleanups
Subsystems (6)
Johannes Weiner
maintainercover mm: kswapd spinning on unreclaimable nodes - fixes and cleanups
Hi,
Jia reported a scenario in which the kswapd of a node indefinitely spins at 100% CPU usage. We have seen similar cases at Facebook.
The kernel's current method of judging its ability to reclaim a node (or whether to back off and sleep) is based on the amount of scanned pages in proportion to the amount of reclaimable pages. In Jia's and our scenarios, there are no reclaimable pages in the node, however, and the condition for backing off is never met. Kswapd busyloops in an attempt to restore the watermarks while having nothing to work with.
This series reworks the definition of an unreclaimable node based not on scanning but on whether kswapd is able to actually reclaim pages in MAX_RECLAIM_RETRIES (16) consecutive runs. This is the same criteria the page allocator uses for giving up on direct reclaim and invoking the OOM killer. If it cannot free any pages, kswapd will go to sleep and leave further attempts to direct reclaim invocations, which will either make progress and re-enable kswapd, or invoke the OOM killer.
Patch #1 fixes the immediate problem Jia reported, the remainder are smaller fixlets, cleanups, and overall phasing out of the old method.
Patch #6 is the odd one out. It's a nice cleanup to get_scan_count(), and directly related to #5, but in itself not relevant to the series.
If the whole series is too ambitious for 4.11, I would consider the first three patches fixes, the rest cleanups.
Thanks
include/linux/mmzone.h | 3 +- mm/internal.h | 7 +- mm/migrate.c | 3 - mm/page_alloc.c | 39 +++-------- mm/vmscan.c | 169 ++++++++++++++++++----------------------------- mm/vmstat.c | 24 ++----- 6 files changed, 89 insertions(+), 156 deletions(-)
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Johannes Weiner
maintainerPATCH 1/9 mm: fix 100% CPU kswapd busyloop on unreclaimable nodes
Jia He reports a problem with kswapd spinning at 100% CPU when requesting more hugepages than memory available in the system:
$ echo 4000 >/proc/sys/vm/nr_hugepages
top - 13:42:59 up 3:37, 1 user, load average: 1.09, 1.03, 1.01
Tasks: 1 total, 1 running, 0 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.0 us, 12.5 sy, 0.0 ni, 85.5 id, 2.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem: 31371520 total, 30915136 used, 456384 free, 320 buffers KiB Swap: 6284224 total, 115712 used, 6168512 free. 48192 cached Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
76 root 20 0 0 0 0 R 100.0 0.000 217:17.29 kswapd3
At that time, there are no reclaimable pages left in the node, but as kswapd fails to restore the high watermarks it refuses to go to sleep.
Kswapd needs to back away from nodes that fail to balance. Up until 1d82de618ddd ("mm, vmscan: make kswapd reclaim in terms of nodes") kswapd had such a mechanism. It considered zones whose theoretically reclaimable pages it had reclaimed six times over as unreclaimable and backed away from them. This guard was erroneously removed as the patch changed the definition of a balanced node.
However, simply restoring this code wouldn't help in the case reported
here: there *are* no reclaimable pages that could be scanned until the threshold is met. Kswapd would stay awake anyway.
Introduce a new and much simpler way of backing off. If kswapd runs through MAX_RECLAIM_RETRIES (16) cycles without reclaiming a single page, make it back off from the node. This is the same number of shots direct reclaim takes before declaring OOM. Kswapd will go to sleep on that node until a direct reclaimer manages to reclaim some pages, thus proving the node reclaimable again.
v2: move MAX_RECLAIM_RETRIES to mm/internal.h (Michal)
--- include/linux/mmzone.h | 2 ++ mm/internal.h | 6 ++++++ mm/page_alloc.c | 9 ++------- mm/vmscan.c | 27 ++++++++++++++++++++------- mm/vmstat.c | 2 +- 5 files changed, 31 insertions(+), 15 deletions(-)
include/linux/mmzone.h +2 -0
@@ -630,6 +630,8 @@ typedef struct pglist_data {int kswapd_order;enum zone_type kswapd_classzone_idx; +int kswapd_failures;/* Number of 'reclaimed == 0' runs */ +#ifdef CONFIG_COMPACTION int kcompactd_max_order;enum zone_type kcompactd_classzone_idx;
mm/internal.h +6 -0
@@ -81,6 +81,12 @@ static inline void set_page_refcounted(struct page *page)extern unsigned long highest_memmap_pfn;/* +* Maximum number of reclaim retries without progress before the OOM +* killer is consider the only way forward. +*/ +#define MAX_RECLAIM_RETRIES 16 + +/* * in mm/vmscan.c: */ extern int isolate_lru_page (struct page *page);
mm/page_alloc.c +2 -7
@@ -3516,12 +3516,6 @@ bool gfp_pfmemalloc_allowed(gfp_t gfp_mask) }/* -* Maximum number of reclaim retries without any progress before OOM killer -* is consider as the only way to move forward. -*/ -#define MAX_RECLAIM_RETRIES 16 - -/* * Checks whether it makes sense to retry the reclaim to make a forward progress * for the given allocation request. * The reclaim feedback represented by did_some_progress (any progress during
@@ -4527,7 +4521,8 @@ void show_free_areas(unsigned int filter, nodemask_t *nodemask)K (node_page_state (pgdat,NR_WRITEBACK_TEMP )),K (node_page_state (pgdat,NR_UNSTABLE_NFS )),node_page_state (pgdat,NR_PAGES_SCANNED ), - !pgdat_reclaimable(pgdat) ? "yes" : "no"); + pgdat->kswapd_failures >=MAX_RECLAIM_RETRIES ? + "yes" : "no"); }for_each_populated_zone (zone) {
mm/vmscan.c +20 -7
@@ -2626,6 +2626,15 @@ static bool shrink_node(pg_data_t *pgdat, struct scan_control *sc) }while (should_continue_reclaim (pgdat, sc->nr_reclaimed - nr_reclaimed, sc->nr_scanned - nr_scanned, sc)); +/* +* Kswapd gives up on balancing particular nodes after too +* many failures to reclaim anything from them and goes to +* sleep. On reclaim progress, reset the failure counter. A +* successful direct reclaim run will revive a dormant kswapd. +*/ +if (reclaimable) + pgdat->kswapd_failures =0 ; +return reclaimable; }
@@ -2700,10 +2709,6 @@ static void shrink_zones(struct zonelist *zonelist, struct scan_control *sc) GFP_KERNEL | __GFP_HARDWALL))continue ; -if (sc->priority !=DEF_PRIORITY && - !pgdat_reclaimable (zone->zone_pgdat)) -continue ;/* Let kswapd poll it */ -/* * If we already have plenty of memory free for * compaction in this zone, don't free any more.
@@ -3134,6 +3139,10 @@ static bool prepare_kswapd_sleep(pg_data_t *pgdat, int order, int classzone_idx)if (waitqueue_active (&pgdat->pfmemalloc_wait))wake_up_all (&pgdat->pfmemalloc_wait); +/* Hopeless node, leave it to direct reclaim */ +if (pgdat->kswapd_failures >=MAX_RECLAIM_RETRIES ) +return true; +for (i =0 ; i <= classzone_idx; i++) {struct zone *zone = pgdat->node_zones + i;
@@ -3316,6 +3325,9 @@ static int balance_pgdat(pg_data_t *pgdat, int order, int classzone_idx) sc.priority--; }while (sc.priority >=1 ); +if (!sc.nr_reclaimed) + pgdat->kswapd_failures++; + out:/* * Return the order kswapd stopped reclaiming at as
@@ -3515,6 +3527,10 @@ void wakeup_kswapd(struct zone *zone, int order, enum zone_type classzone_idx)if (!waitqueue_active (&pgdat->kswapd_wait))return ; +/* Hopeless node, leave it to direct reclaim */ +if (pgdat->kswapd_failures >=MAX_RECLAIM_RETRIES ) +return ; +/* Only wake kswapd if all zones are unbalanced */ for (z =0 ; z <= classzone_idx; z++) { zone = pgdat->node_zones + z;
@@ -3785,9 +3801,6 @@ int node_reclaim(struct pglist_data *pgdat, gfp_t gfp_mask, unsigned int order) sum_zone_node_page_state(pgdat->node_id, NR_SLAB_RECLAIMABLE) <= pgdat->min_slab_pages)return NODE_RECLAIM_FULL ; -if (!pgdat_reclaimable (pgdat)) -return NODE_RECLAIM_FULL ; -/* * Do not scan if the allocation should not be delayed. */
mm/vmstat.c +1 -1
@@ -1422,7 +1422,7 @@ static void zoneinfo_show_print(struct seq_file *m, pg_data_t *pgdat,"\n node_unreclaimable: %u" "\n start_pfn: %lu" "\n node_inactive_ratio: %u" , - !pgdat_reclaimable (zone->zone_pgdat), + pgdat->kswapd_failures >=MAX_RECLAIM_RETRIES , zone->zone_start_pfn, zone->zone_pgdat->inactive_ratio);seq_putc (m,'\n' );
Signature · 7 lines
2.11.1 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH 1/9] mm: fix 100% CPU kswapd busyloop on unreclaimable nodes
Quoted 36 lines · Johannes Weiner
Jia He reports a problem with kswapd spinning at 100% CPU when requesting more hugepages than memory available in the system:
$ echo 4000 >/proc/sys/vm/nr_hugepagestop - 13:42:59 up 3:37, 1 user, load average: 1.09, 1.03, 1.01
Tasks: 1 total, 1 running, 0 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.0 us, 12.5 sy, 0.0 ni, 85.5 id, 2.0 wa, 0.0 hi, 0.0 si, 0.0 stKiB Mem: 31371520 total, 30915136 used, 456384 free, 320 buffers KiB Swap: 6284224 total, 115712 used, 6168512 free. 48192 cached MemPID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
76 root 20 0 0 0 0 R 100.0 0.000 217:17.29 kswapd3At that time, there are no reclaimable pages left in the node, but as kswapd fails to restore the high watermarks it refuses to go to sleep.
Kswapd needs to back away from nodes that fail to balance. Up until
1d82de618ddd("mm, vmscan: make kswapd reclaim in terms of nodes") kswapd had such a mechanism. It considered zones whose theoretically reclaimable pages it had reclaimed six times over as unreclaimable and backed away from them. This guard was erroneously removed as the patch changed the definition of a balanced node.However, simply restoring this code wouldn't help in the case reported
here: there *are* no reclaimable pages that could be scanned until the threshold is met. Kswapd would stay awake anyway.Introduce a new and much simpler way of backing off. If kswapd runs through
MAX_RECLAIM_RETRIES(16) cycles without reclaiming a single page, make it back off from the node. This is the same number of shots direct reclaim takes before declaring OOM. Kswapd will go to sleep on that node until a direct reclaimer manages to reclaim some pages, thus proving the node reclaimable again.
Quoted 7 lines
v2: move
MAX_RECLAIM_RETRIEStomm/internal.h(Michal)Reported-by Jia He <[email protected]>Signed-off-by Johannes Weiner <[email protected]>Tested-by Jia He <[email protected]>Acked-by Michal Hocko <[email protected]>---
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH 1/9] mm: fix 100% CPU kswapd busyloop on unreclaimable nodes
In reply to Johannes WeinerQuoted 28 lines · Johannes Weiner
Jia He reports a problem with kswapd spinning at 100% CPU when requesting more hugepages than memory available in the system:
$ echo 4000 >/proc/sys/vm/nr_hugepagestop - 13:42:59 up 3:37, 1 user, load average: 1.09, 1.03, 1.01
Tasks: 1 total, 1 running, 0 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.0 us, 12.5 sy, 0.0 ni, 85.5 id, 2.0 wa, 0.0 hi, 0.0 si, 0.0 stKiB Mem: 31371520 total, 30915136 used, 456384 free, 320 buffers KiB Swap: 6284224 total, 115712 used, 6168512 free. 48192 cached MemPID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
76 root 20 0 0 0 0 R 100.0 0.000 217:17.29 kswapd3At that time, there are no reclaimable pages left in the node, but as kswapd fails to restore the high watermarks it refuses to go to sleep.
Kswapd needs to back away from nodes that fail to balance. Up until
1d82de618ddd("mm, vmscan: make kswapd reclaim in terms of nodes") kswapd had such a mechanism. It considered zones whose theoretically reclaimable pages it had reclaimed six times over as unreclaimable and backed away from them. This guard was erroneously removed as the patch changed the definition of a balanced node.However, simply restoring this code wouldn't help in the case reported
here: there *are* no reclaimable pages that could be scanned until the threshold is met. Kswapd would stay awake anyway.
Quoted 7 lines
Introduce a new and much simpler way of backing off. If kswapd runs through
MAX_RECLAIM_RETRIES(16) cycles without reclaiming a single page, make it back off from the node. This is the same number of shots direct reclaim takes before declaring OOM. Kswapd will go to sleep on that node until a direct reclaimer manages to reclaim some pages, thus proving the node reclaimable again.
Should the condition of wait_event_killable in throttle_direct_reclaim be changed to (pfmemalloc_watermark_ok(pgdat) || pgdat->kswapd_failures >= MAX_RECLAIM_RETRIES)?
Quoted 158 lines
v2: move
MAX_RECLAIM_RETRIEStomm/internal.h(Michal)Reported-by Jia He <[email protected]>Signed-off-by Johannes Weiner <[email protected]>Tested-by Jia He <[email protected]>Acked-by Michal Hocko <[email protected]>--- include/linux/mmzone.h | 2 ++ mm/internal.h | 6 ++++++ mm/page_alloc.c | 9 ++------- mm/vmscan.c | 27 ++++++++++++++++++++------- mm/vmstat.c | 2 +- 5 files changed, 31 insertions(+), 15 deletions(-)include/linux/mmzone.h +2
-0@@ -630,6 +630,8 @@ typedef struct pglist_data {int kswapd_order;enum zone_type kswapd_classzone_idx; +int kswapd_failures;/* Number of 'reclaimed == 0' runs */ +#ifdef CONFIG_COMPACTION int kcompactd_max_order;enum zone_type kcompactd_classzone_idx;mm/internal.h +6
-0@@ -81,6 +81,12 @@ static inline void set_page_refcounted(struct page *page)extern unsigned long highest_memmap_pfn;/* +* Maximum number of reclaim retries without progress before the OOM +* killer is consider the only way forward. +*/ +#define MAX_RECLAIM_RETRIES 16 + +/* * in mm/vmscan.c: */ extern int isolate_lru_page (struct page *page);mm/page_alloc.c +2
-7@@ -3516,12 +3516,6 @@ bool gfp_pfmemalloc_allowed(gfp_t gfp_mask) }/* -* Maximum number of reclaim retries without any progress before OOM killer -* is consider as the only way to move forward. -*/ -#define MAX_RECLAIM_RETRIES 16 - -/* * Checks whether it makes sense to retry the reclaim to make a forward progress * for the given allocation request. * The reclaim feedback represented by did_some_progress (any progress during @@ -4527,7 +4521,8 @@ void show_free_areas(unsigned int filter, nodemask_t *nodemask)K (node_page_state (pgdat,NR_WRITEBACK_TEMP )),K (node_page_state (pgdat,NR_UNSTABLE_NFS )),node_page_state (pgdat,NR_PAGES_SCANNED ), - !pgdat_reclaimable(pgdat) ? "yes" : "no"); + pgdat->kswapd_failures >=MAX_RECLAIM_RETRIES ? + "yes" : "no"); }for_each_populated_zone (zone) {mm/vmscan.c +20
-7@@ -2626,6 +2626,15 @@ static bool shrink_node(pg_data_t *pgdat, struct scan_control *sc) }while (should_continue_reclaim (pgdat, sc->nr_reclaimed - nr_reclaimed, sc->nr_scanned - nr_scanned, sc)); +/* +* Kswapd gives up on balancing particular nodes after too +* many failures to reclaim anything from them and goes to +* sleep. On reclaim progress, reset the failure counter. A +* successful direct reclaim run will revive a dormant kswapd. +*/ +if (reclaimable) + pgdat->kswapd_failures =0 ; +return reclaimable; }@@ -2700,10 +2709,6 @@ static void shrink_zones(struct zonelist *zonelist, struct scan_control *sc) GFP_KERNEL | __GFP_HARDWALL))continue ; -if (sc->priority !=DEF_PRIORITY && - !pgdat_reclaimable (zone->zone_pgdat)) -continue ;/* Let kswapd poll it */ -/* * If we already have plenty of memory free for * compaction in this zone, don't free any more. @@ -3134,6 +3139,10 @@ static bool prepare_kswapd_sleep(pg_data_t *pgdat, int order, int classzone_idx)if (waitqueue_active (&pgdat->pfmemalloc_wait))wake_up_all (&pgdat->pfmemalloc_wait); +/* Hopeless node, leave it to direct reclaim */ +if (pgdat->kswapd_failures >=MAX_RECLAIM_RETRIES ) +return true; +for (i =0 ; i <= classzone_idx; i++) {struct zone *zone = pgdat->node_zones + i;@@ -3316,6 +3325,9 @@ static int balance_pgdat(pg_data_t *pgdat, int order, int classzone_idx) sc.priority--; }while (sc.priority >=1 ); +if (!sc.nr_reclaimed) + pgdat->kswapd_failures++; + out:/* * Return the order kswapd stopped reclaiming at as @@ -3515,6 +3527,10 @@ void wakeup_kswapd(struct zone *zone, int order, enum zone_type classzone_idx)if (!waitqueue_active (&pgdat->kswapd_wait))return ; +/* Hopeless node, leave it to direct reclaim */ +if (pgdat->kswapd_failures >=MAX_RECLAIM_RETRIES ) +return ; +/* Only wake kswapd if all zones are unbalanced */ for (z =0 ; z <= classzone_idx; z++) { zone = pgdat->node_zones + z;@@ -3785,9 +3801,6 @@ int node_reclaim(struct pglist_data *pgdat, gfp_t gfp_mask, unsigned int order) sum_zone_node_page_state(pgdat->node_id, NR_SLAB_RECLAIMABLE) <= pgdat->min_slab_pages)return NODE_RECLAIM_FULL ; -if (!pgdat_reclaimable (pgdat)) -return NODE_RECLAIM_FULL ; -/* * Do not scan if the allocation should not be delayed. */ mm/vmstat.c +1
-2@@ -1422,7 +1422,7 @@ static void zoneinfo_show_print(struct seq_file *m, pg_data_t *pgdat,"\n node_unreclaimable: %u" "\n start_pfn: %lu" "\n node_inactive_ratio: %u" , - !pgdat_reclaimable (zone->zone_pgdat), + pgdat->kswapd_failures >=MAX_RECLAIM_RETRIES , zone->zone_start_pfn, zone->zone_pgdat->inactive_ratio);seq_putc (m,'\n' ); --
Quoted 2 lines
2.11.1
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH 1/9] mm: fix 100% CPU kswapd busyloop on unreclaimable nodes
In reply to Johannes WeinerHi Johannes,
Quoted 138 lines · Johannes Weiner
Jia He reports a problem with kswapd spinning at 100% CPU when requesting more hugepages than memory available in the system:
$ echo 4000 >/proc/sys/vm/nr_hugepagestop - 13:42:59 up 3:37, 1 user, load average: 1.09, 1.03, 1.01
Tasks: 1 total, 1 running, 0 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.0 us, 12.5 sy, 0.0 ni, 85.5 id, 2.0 wa, 0.0 hi, 0.0 si, 0.0 stKiB Mem: 31371520 total, 30915136 used, 456384 free, 320 buffers KiB Swap: 6284224 total, 115712 used, 6168512 free. 48192 cached MemPID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
76 root 20 0 0 0 0 R 100.0 0.000 217:17.29 kswapd3At that time, there are no reclaimable pages left in the node, but as kswapd fails to restore the high watermarks it refuses to go to sleep.
Kswapd needs to back away from nodes that fail to balance. Up until
1d82de618ddd("mm, vmscan: make kswapd reclaim in terms of nodes") kswapd had such a mechanism. It considered zones whose theoretically reclaimable pages it had reclaimed six times over as unreclaimable and backed away from them. This guard was erroneously removed as the patch changed the definition of a balanced node.However, simply restoring this code wouldn't help in the case reported
here: there *are* no reclaimable pages that could be scanned until the threshold is met. Kswapd would stay awake anyway.Introduce a new and much simpler way of backing off. If kswapd runs through
MAX_RECLAIM_RETRIES(16) cycles without reclaiming a single page, make it back off from the node. This is the same number of shots direct reclaim takes before declaring OOM. Kswapd will go to sleep on that node until a direct reclaimer manages to reclaim some pages, thus proving the node reclaimable again.v2: move
MAX_RECLAIM_RETRIEStomm/internal.h(Michal)Reported-by Jia He <[email protected]>Signed-off-by Johannes Weiner <[email protected]>Tested-by Jia He <[email protected]>Acked-by Michal Hocko <[email protected]>--- include/linux/mmzone.h | 2 ++ mm/internal.h | 6 ++++++ mm/page_alloc.c | 9 ++------- mm/vmscan.c | 27 ++++++++++++++++++++------- mm/vmstat.c | 2 +- 5 files changed, 31 insertions(+), 15 deletions(-)include/linux/mmzone.h +2
-0@@ -630,6 +630,8 @@ typedef struct pglist_data {int kswapd_order;enum zone_type kswapd_classzone_idx; +int kswapd_failures;/* Number of 'reclaimed == 0' runs */ +#ifdef CONFIG_COMPACTION int kcompactd_max_order;enum zone_type kcompactd_classzone_idx;mm/internal.h +6
-0@@ -81,6 +81,12 @@ static inline void set_page_refcounted(struct page *page)extern unsigned long highest_memmap_pfn;/* +* Maximum number of reclaim retries without progress before the OOM +* killer is consider the only way forward. +*/ +#define MAX_RECLAIM_RETRIES 16 + +/* * in mm/vmscan.c: */ extern int isolate_lru_page (struct page *page);mm/page_alloc.c +2
-7@@ -3516,12 +3516,6 @@ bool gfp_pfmemalloc_allowed(gfp_t gfp_mask) }/* -* Maximum number of reclaim retries without any progress before OOM killer -* is consider as the only way to move forward. -*/ -#define MAX_RECLAIM_RETRIES 16 - -/* * Checks whether it makes sense to retry the reclaim to make a forward progress * for the given allocation request. * The reclaim feedback represented by did_some_progress (any progress during @@ -4527,7 +4521,8 @@ void show_free_areas(unsigned int filter, nodemask_t *nodemask)K (node_page_state (pgdat,NR_WRITEBACK_TEMP )),K (node_page_state (pgdat,NR_UNSTABLE_NFS )),node_page_state (pgdat,NR_PAGES_SCANNED ), - !pgdat_reclaimable(pgdat) ? "yes" : "no"); + pgdat->kswapd_failures >=MAX_RECLAIM_RETRIES ? + "yes" : "no"); }for_each_populated_zone (zone) {mm/vmscan.c +9
-4@@ -2626,6 +2626,15 @@ static bool shrink_node(pg_data_t *pgdat, struct scan_control *sc) }while (should_continue_reclaim (pgdat, sc->nr_reclaimed - nr_reclaimed, sc->nr_scanned - nr_scanned, sc)); +/* +* Kswapd gives up on balancing particular nodes after too +* many failures to reclaim anything from them and goes to +* sleep. On reclaim progress, reset the failure counter. A +* successful direct reclaim run will revive a dormant kswapd. +*/ +if (reclaimable) + pgdat->kswapd_failures =0 ; +return reclaimable; }@@ -2700,10 +2709,6 @@ static void shrink_zones(struct zonelist *zonelist, struct scan_control *sc) GFP_KERNEL | __GFP_HARDWALL))continue ; -if (sc->priority !=DEF_PRIORITY && - !pgdat_reclaimable (zone->zone_pgdat)) -continue ;/* Let kswapd poll it */ -/* * If we already have plenty of memory free for * compaction in this zone, don't free any more.
mm/vmscan.c static bool prepare_kswapd_sleep(pg_data_t *pgdat, int order, int classzone_idx) · line 3142
Quoted 4 lines
mm/vmscan.c +1
-0@@ -3134,6 +3139,10 @@ static bool prepare_kswapd_sleep(pg_data_t *pgdat, int order, int classzone_idx)if (waitqueue_active (&pgdat->pfmemalloc_wait))wake_up_all (&pgdat->pfmemalloc_wait); +/* Hopeless node, leave it to direct reclaim */
I hope to clear what we want by deferring the job to direct reclaim. Direct reclaim is much limited reclaim worker by serveral things(e.g., avoid writeback for stack overflow, NOIO|NOFS context) so what do we want for direct reclaimer to do even if kswapd can make forward progress? OOM?
mm/vmscan.c static int balance_pgdat(pg_data_t *pgdat, int order, int classzone_idx) · line 3329
Quoted 12 lines
mm/vmscan.c +5
-0+if (pgdat->kswapd_failures >=MAX_RECLAIM_RETRIES ) +return true; +for (i =0 ; i <= classzone_idx; i++) {struct zone *zone = pgdat->node_zones + i;@@ -3316,6 +3325,9 @@ static int balance_pgdat(pg_data_t *pgdat, int order, int classzone_idx) sc.priority--; }while (sc.priority >=1 ); +if (!sc.nr_reclaimed) + pgdat->kswapd_failures++;
sc.nr_reclaimed is reset to zero in above big loop's beginning so most of time, it pgdat->kswapd_failures is increased.
Quoted 46 lines
mm/vmscan.c +5
-3+ out:/* * Return the order kswapd stopped reclaiming at as @@ -3515,6 +3527,10 @@ void wakeup_kswapd(struct zone *zone, int order, enum zone_type classzone_idx)if (!waitqueue_active (&pgdat->kswapd_wait))return ; +/* Hopeless node, leave it to direct reclaim */ +if (pgdat->kswapd_failures >=MAX_RECLAIM_RETRIES ) +return ; +/* Only wake kswapd if all zones are unbalanced */ for (z =0 ; z <= classzone_idx; z++) { zone = pgdat->node_zones + z;@@ -3785,9 +3801,6 @@ int node_reclaim(struct pglist_data *pgdat, gfp_t gfp_mask, unsigned int order) sum_zone_node_page_state(pgdat->node_id, NR_SLAB_RECLAIMABLE) <= pgdat->min_slab_pages)return NODE_RECLAIM_FULL ; -if (!pgdat_reclaimable (pgdat)) -return NODE_RECLAIM_FULL ; -/* * Do not scan if the allocation should not be delayed. */ mm/vmstat.c +1
-1@@ -1422,7 +1422,7 @@ static void zoneinfo_show_print(struct seq_file *m, pg_data_t *pgdat,"\n node_unreclaimable: %u" "\n start_pfn: %lu" "\n node_inactive_ratio: %u" , - !pgdat_reclaimable (zone->zone_pgdat), + pgdat->kswapd_failures >=MAX_RECLAIM_RETRIES , zone->zone_start_pfn, zone->zone_pgdat->inactive_ratio);seq_putc (m,'\n' );Signature · 7 lines
2.11.1 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Michal Hocko
reviewerRe: [PATCH 1/9] mm: fix 100% CPU kswapd busyloop on unreclaimable nodes
Quoted 144 lines · Minchan Kim
Hi Johannes,
Quoted 141 lines · Johannes Weiner
Jia He reports a problem with kswapd spinning at 100% CPU when requesting more hugepages than memory available in the system:
$ echo 4000 >/proc/sys/vm/nr_hugepagestop - 13:42:59 up 3:37, 1 user, load average: 1.09, 1.03, 1.01
Tasks: 1 total, 1 running, 0 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.0 us, 12.5 sy, 0.0 ni, 85.5 id, 2.0 wa, 0.0 hi, 0.0 si, 0.0 stKiB Mem: 31371520 total, 30915136 used, 456384 free, 320 buffers KiB Swap: 6284224 total, 115712 used, 6168512 free. 48192 cached MemPID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
76 root 20 0 0 0 0 R 100.0 0.000 217:17.29 kswapd3At that time, there are no reclaimable pages left in the node, but as kswapd fails to restore the high watermarks it refuses to go to sleep.
Kswapd needs to back away from nodes that fail to balance. Up until
1d82de618ddd("mm, vmscan: make kswapd reclaim in terms of nodes") kswapd had such a mechanism. It considered zones whose theoretically reclaimable pages it had reclaimed six times over as unreclaimable and backed away from them. This guard was erroneously removed as the patch changed the definition of a balanced node.However, simply restoring this code wouldn't help in the case reported
here: there *are* no reclaimable pages that could be scanned until the threshold is met. Kswapd would stay awake anyway.Introduce a new and much simpler way of backing off. If kswapd runs through
MAX_RECLAIM_RETRIES(16) cycles without reclaiming a single page, make it back off from the node. This is the same number of shots direct reclaim takes before declaring OOM. Kswapd will go to sleep on that node until a direct reclaimer manages to reclaim some pages, thus proving the node reclaimable again.v2: move
MAX_RECLAIM_RETRIEStomm/internal.h(Michal)Reported-by Jia He <[email protected]>Signed-off-by Johannes Weiner <[email protected]>Tested-by Jia He <[email protected]>Acked-by Michal Hocko <[email protected]>--- include/linux/mmzone.h | 2 ++ mm/internal.h | 6 ++++++ mm/page_alloc.c | 9 ++------- mm/vmscan.c | 27 ++++++++++++++++++++------- mm/vmstat.c | 2 +- 5 files changed, 31 insertions(+), 15 deletions(-)include/linux/mmzone.h +2
-0@@ -630,6 +630,8 @@ typedef struct pglist_data {int kswapd_order;enum zone_type kswapd_classzone_idx; +int kswapd_failures;/* Number of 'reclaimed == 0' runs */ +#ifdef CONFIG_COMPACTION int kcompactd_max_order;enum zone_type kcompactd_classzone_idx;mm/internal.h +6
-0@@ -81,6 +81,12 @@ static inline void set_page_refcounted(struct page *page)extern unsigned long highest_memmap_pfn;/* +* Maximum number of reclaim retries without progress before the OOM +* killer is consider the only way forward. +*/ +#define MAX_RECLAIM_RETRIES 16 + +/* * in mm/vmscan.c: */ extern int isolate_lru_page (struct page *page);mm/page_alloc.c +2
-7@@ -3516,12 +3516,6 @@ bool gfp_pfmemalloc_allowed(gfp_t gfp_mask) }/* -* Maximum number of reclaim retries without any progress before OOM killer -* is consider as the only way to move forward. -*/ -#define MAX_RECLAIM_RETRIES 16 - -/* * Checks whether it makes sense to retry the reclaim to make a forward progress * for the given allocation request. * The reclaim feedback represented by did_some_progress (any progress during @@ -4527,7 +4521,8 @@ void show_free_areas(unsigned int filter, nodemask_t *nodemask)K (node_page_state (pgdat,NR_WRITEBACK_TEMP )),K (node_page_state (pgdat,NR_UNSTABLE_NFS )),node_page_state (pgdat,NR_PAGES_SCANNED ), - !pgdat_reclaimable(pgdat) ? "yes" : "no"); + pgdat->kswapd_failures >=MAX_RECLAIM_RETRIES ? + "yes" : "no"); }for_each_populated_zone (zone) {mm/vmscan.c +9
-4@@ -2626,6 +2626,15 @@ static bool shrink_node(pg_data_t *pgdat, struct scan_control *sc) }while (should_continue_reclaim (pgdat, sc->nr_reclaimed - nr_reclaimed, sc->nr_scanned - nr_scanned, sc)); +/* +* Kswapd gives up on balancing particular nodes after too +* many failures to reclaim anything from them and goes to +* sleep. On reclaim progress, reset the failure counter. A +* successful direct reclaim run will revive a dormant kswapd. +*/ +if (reclaimable) + pgdat->kswapd_failures =0 ; +return reclaimable; }@@ -2700,10 +2709,6 @@ static void shrink_zones(struct zonelist *zonelist, struct scan_control *sc) GFP_KERNEL | __GFP_HARDWALL))continue ; -if (sc->priority !=DEF_PRIORITY && - !pgdat_reclaimable (zone->zone_pgdat)) -continue ;/* Let kswapd poll it */ -/* * If we already have plenty of memory free for * compaction in this zone, don't free any more. @@ -3134,6 +3139,10 @@ static bool prepare_kswapd_sleep(pg_data_t *pgdat, int order, int classzone_idx)if (waitqueue_active (&pgdat->pfmemalloc_wait))wake_up_all (&pgdat->pfmemalloc_wait);
Quoted 5 lines
mm/vmscan.c static bool prepare_kswapd_sleep(pg_data_t *pgdat, int order, int classzone_idx) · line 3142
Quoted 1 line
mm/vmscan.c +1
-0+/* Hopeless node, leave it to direct reclaim */ I hope to clear what we want by deferring the job to direct reclaim. Direct reclaim is much limited reclaim worker by serveral
things(e.g., avoid writeback for stack overflow, NOIO|NOFS context)
This is true but if kswapd cannot reclaim anything at all then we do not have much choice left
Quoted 3 lines
so what do we
want for direct reclaimer to do even if kswapd can make forward progress? OOM?
yes resp. back off for costly high order requests and leave the node unbalanced.
Quoted 10 lines
Quoted 10 lines
mm/vmscan.c +3
-0+if (pgdat->kswapd_failures >=MAX_RECLAIM_RETRIES ) +return true; +for (i =0 ; i <= classzone_idx; i++) {struct zone *zone = pgdat->node_zones + i;@@ -3316,6 +3325,9 @@ static int balance_pgdat(pg_data_t *pgdat, int order, int classzone_idx) sc.priority--; }while (sc.priority >=1 );
Quoted 5 lines
mm/vmscan.c static int balance_pgdat(pg_data_t *pgdat, int order, int classzone_idx) · line 3329
Quoted 2 lines
mm/vmscan.c +2
-0+if (!sc.nr_reclaimed) + pgdat->kswapd_failures++;sc.nr_reclaimed is reset to zero in above big loop's beginning so most of time, it
pgdat->kswapd_failuresis increased.
But then we increase the counter in kswapd_shrink_node or do I miss your point? Are you suggesting to use the aggregate nr_reclaimed over all priorities because the last round might have made no progress?
Signature · 8 lines
Michal Hocko SUSE Labs -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH 1/9] mm: fix 100% CPU kswapd busyloop on unreclaimable nodes
Hi Michal,
Quoted 154 lines · Michal Hocko
Quoted 144 lines · Minchan Kim
Hi Johannes,
Quoted 141 lines · Johannes Weiner
Jia He reports a problem with kswapd spinning at 100% CPU when requesting more hugepages than memory available in the system:
$ echo 4000 >/proc/sys/vm/nr_hugepagestop - 13:42:59 up 3:37, 1 user, load average: 1.09, 1.03, 1.01
Tasks: 1 total, 1 running, 0 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.0 us, 12.5 sy, 0.0 ni, 85.5 id, 2.0 wa, 0.0 hi, 0.0 si, 0.0 stKiB Mem: 31371520 total, 30915136 used, 456384 free, 320 buffers KiB Swap: 6284224 total, 115712 used, 6168512 free. 48192 cached MemPID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
76 root 20 0 0 0 0 R 100.0 0.000 217:17.29 kswapd3At that time, there are no reclaimable pages left in the node, but as kswapd fails to restore the high watermarks it refuses to go to sleep.
Kswapd needs to back away from nodes that fail to balance. Up until
1d82de618ddd("mm, vmscan: make kswapd reclaim in terms of nodes") kswapd had such a mechanism. It considered zones whose theoretically reclaimable pages it had reclaimed six times over as unreclaimable and backed away from them. This guard was erroneously removed as the patch changed the definition of a balanced node.However, simply restoring this code wouldn't help in the case reported
here: there *are* no reclaimable pages that could be scanned until the threshold is met. Kswapd would stay awake anyway.Introduce a new and much simpler way of backing off. If kswapd runs through
MAX_RECLAIM_RETRIES(16) cycles without reclaiming a single page, make it back off from the node. This is the same number of shots direct reclaim takes before declaring OOM. Kswapd will go to sleep on that node until a direct reclaimer manages to reclaim some pages, thus proving the node reclaimable again.v2: move
MAX_RECLAIM_RETRIEStomm/internal.h(Michal)Reported-by Jia He <[email protected]>Signed-off-by Johannes Weiner <[email protected]>Tested-by Jia He <[email protected]>Acked-by Michal Hocko <[email protected]>--- include/linux/mmzone.h | 2 ++ mm/internal.h | 6 ++++++ mm/page_alloc.c | 9 ++------- mm/vmscan.c | 27 ++++++++++++++++++++------- mm/vmstat.c | 2 +- 5 files changed, 31 insertions(+), 15 deletions(-)include/linux/mmzone.h +2
-0@@ -630,6 +630,8 @@ typedef struct pglist_data {int kswapd_order;enum zone_type kswapd_classzone_idx; +int kswapd_failures;/* Number of 'reclaimed == 0' runs */ +#ifdef CONFIG_COMPACTION int kcompactd_max_order;enum zone_type kcompactd_classzone_idx;mm/internal.h +6
-0@@ -81,6 +81,12 @@ static inline void set_page_refcounted(struct page *page)extern unsigned long highest_memmap_pfn;/* +* Maximum number of reclaim retries without progress before the OOM +* killer is consider the only way forward. +*/ +#define MAX_RECLAIM_RETRIES 16 + +/* * in mm/vmscan.c: */ extern int isolate_lru_page (struct page *page);mm/page_alloc.c +2
-7@@ -3516,12 +3516,6 @@ bool gfp_pfmemalloc_allowed(gfp_t gfp_mask) }/* -* Maximum number of reclaim retries without any progress before OOM killer -* is consider as the only way to move forward. -*/ -#define MAX_RECLAIM_RETRIES 16 - -/* * Checks whether it makes sense to retry the reclaim to make a forward progress * for the given allocation request. * The reclaim feedback represented by did_some_progress (any progress during @@ -4527,7 +4521,8 @@ void show_free_areas(unsigned int filter, nodemask_t *nodemask)K (node_page_state (pgdat,NR_WRITEBACK_TEMP )),K (node_page_state (pgdat,NR_UNSTABLE_NFS )),node_page_state (pgdat,NR_PAGES_SCANNED ), - !pgdat_reclaimable(pgdat) ? "yes" : "no"); + pgdat->kswapd_failures >=MAX_RECLAIM_RETRIES ? + "yes" : "no"); }for_each_populated_zone (zone) {mm/vmscan.c +9
-4@@ -2626,6 +2626,15 @@ static bool shrink_node(pg_data_t *pgdat, struct scan_control *sc) }while (should_continue_reclaim (pgdat, sc->nr_reclaimed - nr_reclaimed, sc->nr_scanned - nr_scanned, sc)); +/* +* Kswapd gives up on balancing particular nodes after too +* many failures to reclaim anything from them and goes to +* sleep. On reclaim progress, reset the failure counter. A +* successful direct reclaim run will revive a dormant kswapd. +*/ +if (reclaimable) + pgdat->kswapd_failures =0 ; +return reclaimable; }@@ -2700,10 +2709,6 @@ static void shrink_zones(struct zonelist *zonelist, struct scan_control *sc) GFP_KERNEL | __GFP_HARDWALL))continue ; -if (sc->priority !=DEF_PRIORITY && - !pgdat_reclaimable (zone->zone_pgdat)) -continue ;/* Let kswapd poll it */ -/* * If we already have plenty of memory free for * compaction in this zone, don't free any more. @@ -3134,6 +3139,10 @@ static bool prepare_kswapd_sleep(pg_data_t *pgdat, int order, int classzone_idx)if (waitqueue_active (&pgdat->pfmemalloc_wait))wake_up_all (&pgdat->pfmemalloc_wait);Quoted 5 lines
mm/vmscan.c static bool prepare_kswapd_sleep(pg_data_t *pgdat, int order, int classzone_idx) · line 3142
Quoted 1 line
mm/vmscan.c +1
-0+/* Hopeless node, leave it to direct reclaim */ I hope to clear what we want by deferring the job to direct reclaim. Direct reclaim is much limited reclaim worker by serveral
things(e.g., avoid writeback for stack overflow, NOIO|NOFS context)This is true but if kswapd cannot reclaim anything at all then we do not have much choice left
Quoted 6 lines
Quoted 3 lines
so what do we
want for direct reclaimer to do even if kswapd can make forward progress? OOM?yes resp. back off for costly high order requests and leave the node unbalanced.
Okay, I just wanted to clear it out because we have kept logic to prevent CPU burn out of direct reclaim in case of being full with unreclaiamble pages of zones. And this patch removes it in shrink_zones. It might be optimized to cut off direct reclaim if kswapd failure is higher than threshold so we reach OOM fast without pointless retrial to reclaim in direct reclaim path but I guess it would be rare case so no worth to optimize.
commit 36fb7f8
Author: Andrew Morton <[email protected]> Date: Thu Nov 21 19:32:34 2002 -0800
[PATCH] handle zones which are full of unreclaimable pages
Quoted 17 lines
Quoted 11 lines
Quoted 11 lines
mm/vmscan.c +3
-0+if (pgdat->kswapd_failures >=MAX_RECLAIM_RETRIES ) +return true; +for (i =0 ; i <= classzone_idx; i++) {struct zone *zone = pgdat->node_zones + i;@@ -3316,6 +3325,9 @@ static int balance_pgdat(pg_data_t *pgdat, int order, int classzone_idx) sc.priority--; }while (sc.priority >=1 );Quoted 5 lines
mm/vmscan.c static int balance_pgdat(pg_data_t *pgdat, int order, int classzone_idx) · line 3329
Quoted 2 lines
mm/vmscan.c +2
-0+if (!sc.nr_reclaimed) + pgdat->kswapd_failures++;sc.nr_reclaimed is reset to zero in above big loop's beginning so most of time, it
pgdat->kswapd_failuresis increased.
Quoted 3 lines
But then we increase the counter in
kswapd_shrink_nodeor do I miss your point? Are you suggesting to use the aggregatenr_reclaimedover all priorities because the last round might have made no progress?
Yes.
Let's assume there is severe memory pressure so there would be less LRU pages than sum += highwatermark of eligible zones(As well, user can configure watermark big in a specific zone). In that case, kswapd will increase prioirity by kswapd_shrink_node's return check although it reclaims a few of pages.
Also, process can consume pages kswapd reclaimed in parallel without entering slow path because it uses *low* watermark. So there would be no chance to reset kswapd_failure to zero until it goes slow path.
Also, although it goes direct reclaim's slow path, it cannot wakeup kswapd until it can make forward progress which is condition to reset kswapd_failure and consider direct reclaimer's context is easily limited with NO_[FS|IO] so sometime, it would be hard to make forward progress.
We can rule out that situation easily via aggregating nr_reclaimed in balance_pgdat, simply. Why not?
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Johannes Weiner
maintainerRe: [PATCH 1/9] mm: fix 100% CPU kswapd busyloop on unreclaimable nodes
Quoted 7 lines · Minchan Kim
Quoted 6 lines · Michal Hocko
Quoted 5 lines · Minchan Kim
Quoted 4 lines · Johannes Weiner
(quoted diff) +0
-0@@ -3316,6 +3325,9 @@ static int balance_pgdat(pg_data_t *pgdat, int order, int classzone_idx) sc.priority--; } while (sc.priority >= 1);
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Review static int balance_pgdat(pg_data_t *pgdat, int order, int classzone_idx) · line 3329
Quoted 2 lines
(quoted diff) +2
-0+ if (!sc.nr_reclaimed) + pgdat->kswapd_failures++;sc.nr_reclaimed is reset to zero in above big loop's beginning so most of time, it
pgdat->kswapd_failuresis increased.
That wasn't intentional; I didn't see the sc.nr_reclaimed reset.
---
Re: [PATCH 1/9] mm: fix 100% CPU kswapd busyloop on unreclaimable nodes
Quoted 37 lines · Johannes Weiner
Quoted 7 lines · Minchan Kim
Quoted 6 lines · Michal Hocko
Quoted 5 lines · Minchan Kim
Quoted 4 lines · Johannes Weiner
(quoted diff) +0
-0@@ -3316,6 +3325,9 @@ static int balance_pgdat(pg_data_t *pgdat, int order, int classzone_idx) sc.priority--; } while (sc.priority >= 1);Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Review static int balance_pgdat(pg_data_t *pgdat, int order, int classzone_idx) · line 3329
Quoted 2 lines
(quoted diff) +2
-0+ if (!sc.nr_reclaimed) + pgdat->kswapd_failures++;sc.nr_reclaimed is reset to zero in above big loop's beginning so most of time, it
pgdat->kswapd_failuresis increased.That wasn't intentional; I didn't see the sc.nr_reclaimed reset.
---
From
e126db716926ff353b35f3a6205bd5853e01877bMon Sep 17 00:00:00 2001
From: Johannes Weiner <[email protected]>
Date: Mon, 6 Mar 2017 10:53:59 -0500
Subject: [PATCH] mm: fix 100% CPU kswapd busyloop on unreclaimable nodes fixCheck kswapd failure against the cumulative
nr_reclaimedcount, not against the count from the lowest priority iteration.Suggested-by Minchan Kim <[email protected]>Signed-off-by Johannes Weiner <[email protected]>--- mm/vmscan.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)mm/vmscan.c +0
-0
mm/vmscan.c static int balance_pgdat(pg_data_t *pgdat, int order, int classzone_idx) · line 3184
Quoted 7 lines
mm/vmscan.c +1
-1@@ -3179,9 +3179,9 @@ static int balance_pgdat(pg_data_t *pgdat, int order, int classzone_idx)count_vm_event (PAGEOUTRUN ); do { + unsigned long nr_reclaimed = sc.nr_reclaimed; bool raise_priority = true; - sc.nr_reclaimed = 0;
This has another effect that we'll reclaim less pages than we're currently doing if we are balancing for high order request. And it looks worth including that info also in log message.
Quoted 14 lines
mm/vmscan.c +2
-2sc.reclaim_idx = classzone_idx;/* @@ -3271,7 +3271,8 @@ static int balance_pgdat(pg_data_t *pgdat, int order, int classzone_idx)* Raise priority if scanning rate is too low or there was no * progress in reclaiming pages */ -if (raise_priority || !sc.nr_reclaimed) + nr_reclaimed = sc.nr_reclaimed - nr_reclaimed; +if (raise_priority || !nr_reclaimed) sc.priority--; }while (sc.priority >=1 ); --
Quoted 1 line
2.11.1
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Minchan Kim
Acked-byRe: [PATCH 1/9] mm: fix 100% CPU kswapd busyloop on unreclaimable nodes
In reply to Johannes WeinerQuoted 23 lines · Johannes Weiner
Quoted 7 lines · Minchan Kim
Quoted 6 lines · Michal Hocko
Quoted 5 lines · Minchan Kim
Quoted 4 lines · Johannes Weiner
(quoted diff) +0
-0@@ -3316,6 +3325,9 @@ static int balance_pgdat(pg_data_t *pgdat, int order, int classzone_idx) sc.priority--; } while (sc.priority >= 1);Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Review static int balance_pgdat(pg_data_t *pgdat, int order, int classzone_idx) · line 3329
Quoted 2 lines
(quoted diff) +2
-0+ if (!sc.nr_reclaimed) + pgdat->kswapd_failures++;sc.nr_reclaimed is reset to zero in above big loop's beginning so most of time, it
pgdat->kswapd_failuresis increased.That wasn't intentional; I didn't see the sc.nr_reclaimed reset.
---
From
e126db716926ff353b35f3a6205bd5853e01877bMon Sep 17 00:00:00 2001
From: Johannes Weiner <[email protected]>
Date: Mon, 6 Mar 2017 10:53:59 -0500
Subject: [PATCH] mm: fix 100% CPU kswapd busyloop on unreclaimable nodes fix
Quoted 5 lines
Check kswapd failure against the cumulative
nr_reclaimedcount, not against the count from the lowest priority iteration.Suggested-by Minchan Kim <[email protected]>Signed-off-by Johannes Weiner <[email protected]>
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Michal Hocko
reviewerRe: [PATCH 1/9] mm: fix 100% CPU kswapd busyloop on unreclaimable nodes
In reply to Johannes WeinerOn Mon 06-03-17 11:24:10, Johannes Weiner wrote:
[...]
Quoted 30 lines
Quoted 1 line
From
e126db716926ff353b35f3a6205bd5853e01877bMon Sep 17 00:00:00 2001From: Johannes Weiner <[email protected]>
Date: Mon, 6 Mar 2017 10:53:59 -0500
Subject: [PATCH] mm: fix 100% CPU kswapd busyloop on unreclaimable nodes fixCheck kswapd failure against the cumulative
nr_reclaimedcount, not against the count from the lowest priority iteration.Suggested-by Minchan Kim <[email protected]>Signed-off-by Johannes Weiner <[email protected]>--- mm/vmscan.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)mm/vmscan.c +1
-1@@ -3179,9 +3179,9 @@ static int balance_pgdat(pg_data_t *pgdat, int order, int classzone_idx)count_vm_event (PAGEOUTRUN ); do { + unsigned long nr_reclaimed = sc.nr_reclaimed; bool raise_priority = true; - sc.nr_reclaimed = 0; sc.reclaim_idx = classzone_idx; /*
mm/vmscan.c static int balance_pgdat(pg_data_t *pgdat, int order, int classzone_idx) · line 3278
Quoted 9 lines
mm/vmscan.c +2
-1@@ -3271,7 +3271,8 @@ static int balance_pgdat(pg_data_t *pgdat, int order, int classzone_idx)* Raise priority if scanning rate is too low or there was no * progress in reclaiming pages */ -if (raise_priority || !sc.nr_reclaimed) + nr_reclaimed = sc.nr_reclaimed - nr_reclaimed; +if (raise_priority || !nr_reclaimed) sc.priority--; }while (sc.priority >=1 );
I would rather not play with the sc state here. From a quick look at least
/*
* Fragmentation may mean that the system cannot be rebalanced for
* high-order allocations. If twice the allocation size has been
* reclaimed then recheck watermarks only at order-0 to prevent
* excessive reclaim. Assume that a process requested a high-order
* can direct reclaim/compact.
*/
if (sc->order && sc->nr_reclaimed >= compact_gap(sc->order))
sc->order = 0;
does rely on the value. Wouldn't something like the following be safer?
---
mm/vmscan.c +5 -1
@@ -3183,6 +3183,7 @@ static int balance_pgdat(pg_data_t *pgdat, int order, int classzone_idx) .may_unmap = 1, .may_swap = 1, }; +bool reclaimable = false;count_vm_event (PAGEOUTRUN ); do {
@@ -3274,6 +3275,9 @@ static int balance_pgdat(pg_data_t *pgdat, int order, int classzone_idx)if (try_to_freeze () ||kthread_should_stop ())break ; +if (sc.nr_reclaimed) + reclaimable = true; +/* * Raise priority if scanning rate is too low or there was no * progress in reclaiming pages
@@ -3282,7 +3286,7 @@ static int balance_pgdat(pg_data_t *pgdat, int order, int classzone_idx) sc.priority--; }while (sc.priority >=1 ); -if (!sc.nr_reclaimed) +if (!reclaimable) pgdat->kswapd_failures++; out:
Signature · 8 lines
Michal Hocko SUSE Labs -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Johannes Weiner
maintainerRe: [PATCH 1/9] mm: fix 100% CPU kswapd busyloop on unreclaimable nodes
Quoted 24 lines · Michal Hocko
Review static int balance_pgdat(pg_data_t *pgdat, int order, int classzone_idx) · line 3278
Quoted 10 lines · Johannes Weiner
(quoted diff) +2
-1@@ -3271,7 +3271,8 @@ static int balance_pgdat(pg_data_t *pgdat, int order, int classzone_idx) * Raise priority if scanning rate is too low or there was no * progress in reclaiming pages */ - if (raise_priority || !sc.nr_reclaimed) + nr_reclaimed = sc.nr_reclaimed - nr_reclaimed; + if (raise_priority || !nr_reclaimed) sc.priority--; } while (sc.priority >= 1);I would rather not play with the sc state here. From a quick look at least
/*
* Fragmentation may mean that the system cannot be rebalanced for
* high-order allocations. If twice the allocation size has been
* reclaimed then recheck watermarks only at order-0 to prevent
* excessive reclaim. Assume that a process requested a high-order
* can direct reclaim/compact.
*/
if (sc->order&&sc->nr_reclaimed>=compact_gap(sc->order))
sc->order= 0;
Quoted 1 line
does rely on the value. Wouldn't something like the following be safer?
Well, what behavior is correct, though? This check looks like an argument *against* resetting sc.nr_reclaimed.
If kswapd is woken up for a higher order, this check sets a reclaim cutoff beyond which it should give up on the order and balance for 0.
That's on the scope of the kswapd invocation. Applying this threshold to the outcome of just the preceeding priority seems like a mistake.
Mel? Vlastimil?
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH 1/9] mm: fix 100% CPU kswapd busyloop on unreclaimable nodes
Quoted 30 lines · Johannes Weiner
Quoted 24 lines · Michal Hocko
Review static int balance_pgdat(pg_data_t *pgdat, int order, int classzone_idx) · line 3278
Quoted 10 lines · Johannes Weiner
(quoted diff) +2
-1@@ -3271,7 +3271,8 @@ static int balance_pgdat(pg_data_t *pgdat, int order, int classzone_idx) * Raise priority if scanning rate is too low or there was no * progress in reclaiming pages */ - if (raise_priority || !sc.nr_reclaimed) + nr_reclaimed = sc.nr_reclaimed - nr_reclaimed; + if (raise_priority || !nr_reclaimed) sc.priority--; } while (sc.priority >= 1);I would rather not play with the sc state here. From a quick look at least
/*
* Fragmentation may mean that the system cannot be rebalanced for
* high-order allocations. If twice the allocation size has been
* reclaimed then recheck watermarks only at order-0 to prevent
* excessive reclaim. Assume that a process requested a high-order
* can direct reclaim/compact.
*/
if (sc->order&&sc->nr_reclaimed>=compact_gap(sc->order))
sc->order= 0;Quoted 1 line
does rely on the value. Wouldn't something like the following be safer?
Well, what behavior is correct, though? This check looks like an argument *against* resetting sc.nr_reclaimed.
Quoted 7 lines
If kswapd is woken up for a higher order, this check sets a reclaim cutoff beyond which it should give up on the order and balance for 0.
That's on the scope of the kswapd invocation. Applying this threshold to the outcome of just the preceeding priority seems like a mistake.
Mel? Vlastimil?
I cannot say which is definitely the correct behaviour. The current behaviour is conservative due to the historical concerns about kswapd reclaiming the world. The hazard as I see it is that resetting it *may* lead to more aggressive reclaim for high-order allocations. That may be a welcome outcome to some that really want high-order pages and be unwelcome to others that prefer pages to remain resident.
However, in this case it's a tight window and problems would be tricky to detect. THP allocations won't trigger the behaviour and with vmalloc'd stack, I'd expect that only SLUB-intensive workloads using high-order pages would trigger any adverse behaviour. While I'm mildly concerned, I would be a little surprised if it actually caused runaway reclaim.
Signature · 8 lines
Mel Gorman SUSE Labs -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Johannes Weiner
maintainerPATCH 2/9 mm: fix check for reclaimable pages in PF_MEMALLOC reclaim throttling
In reply to Johannes WeinerPF_MEMALLOC direct reclaimers get throttled on a node when the sum of all free pages in each zone fall below half the min watermark. During the summation, we want to exclude zones that don't have reclaimables. Checking the same pgdat over and over again doesn't make sense.
--- mm/vmscan.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
mm/vmscan.c +4 -2
@@ -2838,8 +2838,10 @@ static bool pfmemalloc_watermark_ok(pg_data_t *pgdat)for (i =0 ; i <=ZONE_NORMAL ; i++) { zone = &pgdat->node_zones[i]; -if (!managed_zone (zone) || -pgdat_reclaimable_pages (pgdat) ==0 ) +if (!managed_zone (zone)) +continue ; + +if (!zone_reclaimable_pages (zone))continue ; pfmemalloc_reserve +=min_wmark_pages (zone);
Signature · 7 lines
2.11.1 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH 2/9] mm: fix check for reclaimable pages in PF_MEMALLOC reclaim throttling
Quoted 7 lines · Johannes Weiner
PF_MEMALLOCdirect reclaimers get throttled on a node when the sum of all free pages in each zone fall below half the min watermark. During the summation, we want to exclude zones that don't have reclaimables. Checking the same pgdat over and over again doesn't make sense.Fixes 599d0c954f91 ("mm, vmscan: move LRU lists to node")Signed-off-by Johannes Weiner <[email protected]>
Quoted 23 lines
--- mm/vmscan.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)mm/vmscan.c +4
-2@@ -2838,8 +2838,10 @@ static bool pfmemalloc_watermark_ok(pg_data_t *pgdat)for (i =0 ; i <=ZONE_NORMAL ; i++) { zone = &pgdat->node_zones[i]; -if (!managed_zone (zone) || -pgdat_reclaimable_pages (pgdat) ==0 ) +if (!managed_zone (zone)) +continue ; + +if (!zone_reclaimable_pages (zone))continue ; pfmemalloc_reserve +=min_wmark_pages (zone);Signature · 1 line
2.11.1
Signature · 8 lines
Michal Hocko SUSE Labs -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH 2/9] mm: fix check for reclaimable pages in PF_MEMALLOC reclaim throttling
In reply to Johannes WeinerQuoted 9 lines · Johannes Weiner
PF_MEMALLOCdirect reclaimers get throttled on a node when the sum of all free pages in each zone fall below half the min watermark. During the summation, we want to exclude zones that don't have reclaimables. Checking the same pgdat over and over again doesn't make sense.Fixes 599d0c954f91 ("mm, vmscan: move LRU lists to node")Signed-off-by Johannes Weiner <[email protected]>---
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Johannes Weiner
maintainerPATCH 3/9 mm: remove seemingly spurious reclaimability check from laptop_mode gating
In reply to Johannes Weiner1d82de618ddd ("mm, vmscan: make kswapd reclaim in terms of nodes") allowed laptop_mode=1 to start writing not just when the priority drops to DEF_PRIORITY - 2 but also when the node is unreclaimable. That appears to be a spurious change in this patch as I doubt the series was tested with laptop_mode, and neither is that particular change mentioned in the changelog. Remove it, it's still recent.
--- mm/vmscan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
mm/vmscan.c +1 -1
@@ -3288,7 +3288,7 @@ static int balance_pgdat(pg_data_t *pgdat, int order, int classzone_idx)* If we're getting trouble reclaiming, start doing writepage * even in laptop mode. */ -if (sc.priority <DEF_PRIORITY -2 || !pgdat_reclaimable (pgdat)) +if (sc.priority <DEF_PRIORITY -2 ) sc.may_writepage =1 ;/* Call soft limit reclaim before calling shrink_node. */
Signature · 7 lines
2.11.1 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH 3/9] mm: remove seemingly spurious reclaimability check from laptop_mode gating
Quoted 6 lines · Johannes Weiner
1d82de618ddd("mm, vmscan: make kswapd reclaim in terms of nodes") allowed laptop_mode=1 to start writing not just when the priority drops toDEF_PRIORITY- 2 but also when the node is unreclaimable. That appears to be a spurious change in this patch as I doubt the series was tested withlaptop_mode, and neither is that particular change mentioned in the changelog. Remove it, it's still recent.
The less pgdat_reclaimable we have the better IMHO. If this is really needed then I would appreciate a proper explanation because each such a heuristic is just a head scratcher - especially after few years when all the details are long forgotten.
Quoted 1 line
Signed-off-by Johannes Weiner <[email protected]>
Quoted 19 lines
--- mm/vmscan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)mm/vmscan.c +1
-1@@ -3288,7 +3288,7 @@ static int balance_pgdat(pg_data_t *pgdat, int order, int classzone_idx)* If we're getting trouble reclaiming, start doing writepage * even in laptop mode. */ -if (sc.priority <DEF_PRIORITY -2 || !pgdat_reclaimable (pgdat)) +if (sc.priority <DEF_PRIORITY -2 ) sc.may_writepage =1 ;/* Call soft limit reclaim before calling shrink_node. */ Signature · 1 line
2.11.1
Signature · 8 lines
Michal Hocko SUSE Labs -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH 3/9] mm: remove seemingly spurious reclaimability check from laptop_mode gating
In reply to Johannes WeinerQuoted 5 lines · Johannes Weiner
1d82de618ddd("mm, vmscan: make kswapd reclaim in terms of nodes") allowed laptop_mode=1 to start writing not just when the priority drops toDEF_PRIORITY- 2 but also when the node is unreclaimable. That appears to be a spurious change in this patch as I doubt the series was tested withlaptop_mode,
laptop_mode was not tested.
Quoted 4 lines
and neither is that particular
change mentioned in the changelog. Remove it, it's still recent.Signed-off-by Johannes Weiner <[email protected]>
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH 3/9] mm: remove seemingly spurious reclaimability check from laptop_mode gating
In reply to Johannes WeinerQuoted 10 lines · Johannes Weiner
1d82de618ddd("mm, vmscan: make kswapd reclaim in terms of nodes") allowed laptop_mode=1 to start writing not just when the priority drops toDEF_PRIORITY- 2 but also when the node is unreclaimable. That appears to be a spurious change in this patch as I doubt the series was tested withlaptop_mode, and neither is that particular change mentioned in the changelog. Remove it, it's still recent.Signed-off-by Johannes Weiner <[email protected]>---
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Johannes Weiner
maintainerPATCH 4/9 mm: remove unnecessary reclaimability check from NUMA balancing target
In reply to Johannes WeinerNUMA balancing already checks the watermarks of the target node to decide whether it's a suitable balancing target. Whether the node is reclaimable or not is irrelevant when we don't intend to reclaim.
--- mm/migrate.c | 3 --- 1 file changed, 3 deletions(-)
mm/migrate.c +0 -3
@@ -1718,9 +1718,6 @@ static bool migrate_balanced_pgdat(struct pglist_data *pgdat, {int z; -if (!pgdat_reclaimable (pgdat)) -return false; -for (z = pgdat->nr_zones -1 ; z >=0 ; z--) {struct zone *zone = pgdat->node_zones + z;
Signature · 7 lines
2.11.1 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH 4/9] mm: remove unnecessary reclaimability check from NUMA balancing target
Quoted 3 lines · Johannes Weiner
NUMA balancing already checks the watermarks of the target node to decide whether it's a suitable balancing target. Whether the node is reclaimable or not is irrelevant when we don't intend to reclaim.
I guess the original intention was to skip nodes which are under strong memory pressure but I agree that this is questionable heuristic.
Quoted 1 line
Signed-off-by Johannes Weiner <[email protected]>
Quoted 20 lines
--- mm/migrate.c | 3 --- 1 file changed, 3 deletions(-)mm/migrate.c +0
-3@@ -1718,9 +1718,6 @@ static bool migrate_balanced_pgdat(struct pglist_data *pgdat, {int z; -if (!pgdat_reclaimable (pgdat)) -return false; -for (z = pgdat->nr_zones -1 ; z >=0 ; z--) {struct zone *zone = pgdat->node_zones + z;Signature · 1 line
2.11.1
Signature · 8 lines
Michal Hocko SUSE Labs -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH 4/9] mm: remove unnecessary reclaimability check from NUMA balancing target
In reply to Johannes WeinerQuoted 7 lines · Johannes Weiner
NUMA balancing already checks the watermarks of the target node to decide whether it's a suitable balancing target. Whether the node is reclaimable or not is irrelevant when we don't intend to reclaim.
Signed-off-by Johannes Weiner <[email protected]>---
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Johannes Weiner
maintainerPATCH 5/9 mm: don't avoid high-priority reclaim on unreclaimable nodes
In reply to Johannes Weiner246e87a93934 ("memcg: fix get_scan_count() for small targets") sought to avoid high reclaim priorities for kswapd by forcing it to scan a minimum amount of pages when lru_pages >> priority yielded nothing.
b95a2f2d486d ("mm: vmscan: convert global reclaim to per-memcg LRU lists"), due to switching global reclaim to a round-robin scheme over all cgroups, had to restrict this forceful behavior to unreclaimable zones in order to prevent massive overreclaim with many cgroups.
The latter patch effectively neutered the behavior completely for all but extreme memory pressure. But in those situations we might as well drop the reclaimers to lower priority levels. Remove the check.
--- mm/vmscan.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-)
mm/vmscan.c +5 -14
@@ -2129,22 +2129,13 @@ static void get_scan_count(struct lruvec *lruvec, struct mem_cgroup *memcg,int pass;/* -* If the zone or memcg is small, nr[l] can be 0. This -* results in no scanning on this priority and a potential -* priority drop. Global direct reclaim can go to the next -* zone and tends to have no problems. Global kswapd is for -* zone balancing and it needs to scan a minimum amount. When +* If the zone or memcg is small, nr[l] can be 0. When * reclaiming for a memcg, a priority drop can cause high -* latencies, so it's better to scan a minimum amount there as -* well. +* latencies, so it's better to scan a minimum amount. When a +* cgroup has already been deleted, scrape out the remaining +* cache forcefully to get rid of the lingering state. */ -if (current_is_kswapd ()) { -if (!pgdat_reclaimable (pgdat)) - force_scan = true; -if (!mem_cgroup_online (memcg)) - force_scan = true; - } -if (!global_reclaim (sc)) +if (!global_reclaim (sc) || !mem_cgroup_online (memcg)) force_scan = true;/* If we have no swap space, do not bother scanning anon pages. */
Signature · 7 lines
2.11.1 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH 5/9] mm: don't avoid high-priority reclaim on unreclaimable nodes
Quoted 9 lines · Johannes Weiner
246e87a93934("memcg: fixget_scan_count()for small targets") sought to avoid high reclaim priorities for kswapd by forcing it to scan a minimum amount of pages whenlru_pages>> priority yielded nothing.
b95a2f2d486d("mm: vmscan: convert global reclaim to per-memcg LRU lists"), due to switching global reclaim to a round-robin scheme over all cgroups, had to restrict this forceful behavior to unreclaimable zones in order to prevent massive overreclaim with many cgroups.
Quoted 5 lines
The latter patch effectively neutered the behavior completely for all but extreme memory pressure. But in those situations we might as well drop the reclaimers to lower priority levels. Remove the check.
Signed-off-by Johannes Weiner <[email protected]>
Quoted 38 lines
--- mm/vmscan.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-)mm/vmscan.c +5
-14@@ -2129,22 +2129,13 @@ static void get_scan_count(struct lruvec *lruvec, struct mem_cgroup *memcg,int pass;/* -* If the zone or memcg is small, nr[l] can be 0. This -* results in no scanning on this priority and a potential -* priority drop. Global direct reclaim can go to the next -* zone and tends to have no problems. Global kswapd is for -* zone balancing and it needs to scan a minimum amount. When +* If the zone or memcg is small, nr[l] can be 0. When * reclaiming for a memcg, a priority drop can cause high -* latencies, so it's better to scan a minimum amount there as -* well. +* latencies, so it's better to scan a minimum amount. When a +* cgroup has already been deleted, scrape out the remaining +* cache forcefully to get rid of the lingering state. */ -if (current_is_kswapd ()) { -if (!pgdat_reclaimable (pgdat)) - force_scan = true; -if (!mem_cgroup_online (memcg)) - force_scan = true; - } -if (!global_reclaim (sc)) +if (!global_reclaim (sc) || !mem_cgroup_online (memcg)) force_scan = true;/* If we have no swap space, do not bother scanning anon pages. */ Signature · 1 line
2.11.1
Signature · 8 lines
Michal Hocko SUSE Labs -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH 5/9] mm: don't avoid high-priority reclaim on unreclaimable nodes
In reply to Johannes WeinerQuoted 10 lines · Johannes Weiner
246e87a93934("memcg: fixget_scan_count()for small targets") sought to avoid high reclaim priorities for kswapd by forcing it to scan a minimum amount of pages whenlru_pages>> priority yielded nothing.
b95a2f2d486d("mm: vmscan: convert global reclaim to per-memcg LRU lists"), due to switching global reclaim to a round-robin scheme over all cgroups, had to restrict this forceful behavior to unreclaimable zones in order to prevent massive overreclaim with many cgroups.
Quoted 9 lines
The latter patch effectively neutered the behavior completely for all but extreme memory pressure. But in those situations we might as well drop the reclaimers to lower priority levels. Remove the check.
Signed-off-by Johannes Weiner <[email protected]>--- mm/vmscan.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-)
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Johannes Weiner
maintainerPATCH 6/9 mm: don't avoid high-priority reclaim on memcg limit reclaim
In reply to Johannes Weiner246e87a93934 ("memcg: fix get_scan_count() for small targets") sought to avoid high reclaim priorities for memcg by forcing it to scan a minimum amount of pages when lru_pages >> priority yielded nothing. This was done at a time when reclaim decisions like dirty throttling were tied to the priority level.
Nowadays, the only meaningful thing still tied to priority dropping below DEF_PRIORITY - 2 is gating whether laptop_mode=1 is generally allowed to write. But that is from an era where direct reclaim was still allowed to call ->writepage, and kswapd nowadays avoids writes until it's scanned every clean page in the system. Potential changes to how quick sc->may_writepage could trigger are of little concern.
Remove the force_scan stuff, as well as the ugly multi-pass target calculation that it necessitated.
--- mm/vmscan.c | 94 ++++++++++++++++++++++++------------------------------------- 1 file changed, 37 insertions(+), 57 deletions(-)
mm/vmscan.c +37 -57
@@ -2122,21 +2122,8 @@ static void get_scan_count(struct lruvec *lruvec, struct mem_cgroup *memcg,unsigned long anon_prio, file_prio;enum scan_balance scan_balance;unsigned long anon, file; -bool force_scan = false;unsigned long ap, fp;enum lru_list lru; -bool some_scanned; -int pass; - -/* -* If the zone or memcg is small, nr[l] can be 0. When -* reclaiming for a memcg, a priority drop can cause high -* latencies, so it's better to scan a minimum amount. When a -* cgroup has already been deleted, scrape out the remaining -* cache forcefully to get rid of the lingering state. -*/ -if (!global_reclaim (sc) || !mem_cgroup_online (memcg)) - force_scan = true;/* If we have no swap space, do not bother scanning anon pages. */ if (!sc->may_swap ||mem_cgroup_get_nr_swap_pages (memcg) <=0 ) {
@@ -2267,55 +2254,48 @@ static void get_scan_count(struct lruvec *lruvec, struct mem_cgroup *memcg, fraction[1 ] = fp; denominator = ap + fp +1 ; out: - some_scanned = false; -/* Only use force_scan on second pass. */ -for (pass =0 ; !some_scanned && pass <2 ; pass++) { - *lru_pages =0 ; -for_each_evictable_lru (lru) { -int file =is_file_lru (lru); -unsigned long size; -unsigned long scan; - - size =lruvec_lru_size (lruvec, lru, sc->reclaim_idx); - scan = size >> sc->priority; - -if (!scan && pass && force_scan) - scan =min (size,SWAP_CLUSTER_MAX ); - -switch (scan_balance) { -case SCAN_EQUAL : -/* Scan lists relative to size */ -break ; -case SCAN_FRACT : -/* -* Scan types proportional to swappiness and -* their relative recent reclaim efficiency. -*/ - scan =div64_u64 (scan * fraction[file], - denominator); -break ; -case SCAN_FILE : -case SCAN_ANON : -/* Scan one type exclusively */ -if ((scan_balance ==SCAN_FILE ) != file) { - size =0 ; - scan =0 ; - } -break ; -default : -/* Look ma, no brain */ -BUG (); - } + *lru_pages =0 ; +for_each_evictable_lru (lru) { +int file =is_file_lru (lru); +unsigned long size; +unsigned long scan; - *lru_pages += size; - nr[lru] = scan; + size =lruvec_lru_size (lruvec, lru, sc->reclaim_idx); + scan = size >> sc->priority; +/* +* If the cgroup's already been deleted, make sure to +* scrape out the remaining cache. +*/ +if (!scan && !mem_cgroup_online (memcg)) + scan =min (size,SWAP_CLUSTER_MAX ); +switch (scan_balance) { +case SCAN_EQUAL : +/* Scan lists relative to size */ +break ; +case SCAN_FRACT :/* -* Skip the second pass and don't force_scan, -* if we found something to scan. +* Scan types proportional to swappiness and +* their relative recent reclaim efficiency. */ - some_scanned |= !!scan; + scan =div64_u64 (scan * fraction[file], + denominator); +break ; +case SCAN_FILE : +case SCAN_ANON : +/* Scan one type exclusively */ +if ((scan_balance ==SCAN_FILE ) != file) { + size =0 ; + scan =0 ; + } +break ; +default : +/* Look ma, no brain */ +BUG (); } + + *lru_pages += size; + nr[lru] = scan; } }
Signature · 7 lines
2.11.1 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Michal Hocko
reviewerRe: [PATCH 6/9] mm: don't avoid high-priority reclaim on memcg limit reclaim
Quoted 13 lines · Johannes Weiner
246e87a93934("memcg: fixget_scan_count()for small targets") sought to avoid high reclaim priorities for memcg by forcing it to scan a minimum amount of pages whenlru_pages>> priority yielded nothing. This was done at a time when reclaim decisions like dirty throttling were tied to the priority level.Nowadays, the only meaningful thing still tied to priority dropping below
DEF_PRIORITY- 2 is gating whether laptop_mode=1 is generally allowed to write. But that is from an era where direct reclaim was still allowed to call ->writepage, and kswapd nowadays avoids writes until it's scanned every clean page in the system. Potential changes to how quicksc->may_writepagecould trigger are of little concern.
Quoted 2 lines
Remove the
force_scanstuff, as well as the ugly multi-pass target calculation that it necessitated.
I _really_ like this, I hated the multi-pass part. One thig that I am worried about and changelog doesn't mention it is what we are going to do about small (<16MB) memcgs. On one hand they were already ignored in the global reclaim so this is nothing really new but maybe we want to preserve the behavior for the memcg reclaim at least which would reduce side effect of this patch which is a great cleanup otherwise. Or at least be explicit about this in the changelog.
Btw. why cannot we simply force scan at least SWAP_CLUSTER_MAX unconditionally?
mm/vmscan.c static void get_scan_count(struct lruvec *lruvec, struct mem_cgroup *memcg, · line 2267
Quoted 3 lines
mm/vmscan.c +3
-0+/* +* If the cgroup's already been deleted, make sure to +* scrape out the remaining cache.
Also make sure that small memcgs will not get unnoticed during the memcg reclaim
mm/vmscan.c static void get_scan_count(struct lruvec *lruvec, struct mem_cgroup *memcg, · line 2269
Quoted 2 lines
mm/vmscan.c +2
-0+*/ +if (!scan && !mem_cgroup_online (memcg))
if (!scan && (!mem_cgroup_online(memcg) || !global_reclaim(sc)))
Quoted 2 lines
mm/vmscan.c +1
-0+ scan =min (size,SWAP_CLUSTER_MAX );
Signature · 8 lines
Michal Hocko SUSE Labs -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Johannes Weiner
maintainerRe: [PATCH 6/9] mm: don't avoid high-priority reclaim on memcg limit reclaim
Quoted 17 lines · Michal Hocko
Quoted 13 lines · Johannes Weiner
246e87a93934("memcg: fixget_scan_count()for small targets") sought to avoid high reclaim priorities for memcg by forcing it to scan a minimum amount of pages whenlru_pages>> priority yielded nothing. This was done at a time when reclaim decisions like dirty throttling were tied to the priority level.Nowadays, the only meaningful thing still tied to priority dropping below
DEF_PRIORITY- 2 is gating whether laptop_mode=1 is generally allowed to write. But that is from an era where direct reclaim was still allowed to call ->writepage, and kswapd nowadays avoids writes until it's scanned every clean page in the system. Potential changes to how quicksc->may_writepagecould trigger are of little concern.Quoted 2 lines
Remove the
force_scanstuff, as well as the ugly multi-pass target calculation that it necessitated.
Quoted 7 lines
I _really_ like this, I hated the multi-pass part. One thig that I am worried about and changelog doesn't mention it is what we are going to do about small (<16MB) memcgs. On one hand they were already ignored in the global reclaim so this is nothing really new but maybe we want to preserve the behavior for the memcg reclaim at least which would reduce side effect of this patch which is a great cleanup otherwise. Or at least be explicit about this in the changelog.
<16MB groups are a legitimate concern during global reclaim, but we have done it this way for a long time and it never seemed to have mattered in practice.
And for limit reclaim, this should be much less of a concern. It just means we no longer scan these groups at DEF_PRIORITY and will have to increase the scan window. I don't see a problem with that. And that consequence of higher priorities is right in the patch subject.
Quoted 9 lines
Btw. why cannot we simply force scan at least
SWAP_CLUSTER_MAXunconditionally?mm/vmscan.c static void get_scan_count(struct lruvec *lruvec, struct mem_cgroup *memcg, · line 2267
Quoted 3 lines
mm/vmscan.c +3
-0+/* +* If the cgroup's already been deleted, make sure to +* scrape out the remaining cache. Also make sure that small memcgs will not get unnoticed during the memcg reclaim
Quoted 4 lines
mm/vmscan.c static void get_scan_count(struct lruvec *lruvec, struct mem_cgroup *memcg, · line 2269
Quoted 2 lines
mm/vmscan.c +2
-0+*/ +if (!scan && !mem_cgroup_online (memcg))if (!scan && (!mem_cgroup_online(memcg) || !global_reclaim(sc)))
With this I'd be worried about regressing the setups pointed out in 6f04f48dc9c0 ("mm: only force scan in reclaim when none of the LRUs are big enough.").
Granted, that patch is a little dubious. IMO, we should be steering the LRU balance through references and, in that case in particular, with swappiness. Using the default 60 for zswap is too low.
Plus, I would expect the refault detection code that was introduced around the same time as this patch to counter-act the hot file thrashing that is mentioned in that patch's changelog.
Nevertheless, it seems a bit gratuitous to go against that change so directly when global reclaim hasn't historically been a problem with groups <16MB. Limit reclaim should be fine too.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH 6/9] mm: don't avoid high-priority reclaim on memcg limit reclaim
Quoted 26 lines · Johannes Weiner
Quoted 17 lines · Michal Hocko
Quoted 13 lines · Johannes Weiner
246e87a93934("memcg: fixget_scan_count()for small targets") sought to avoid high reclaim priorities for memcg by forcing it to scan a minimum amount of pages whenlru_pages>> priority yielded nothing. This was done at a time when reclaim decisions like dirty throttling were tied to the priority level.Nowadays, the only meaningful thing still tied to priority dropping below
DEF_PRIORITY- 2 is gating whether laptop_mode=1 is generally allowed to write. But that is from an era where direct reclaim was still allowed to call ->writepage, and kswapd nowadays avoids writes until it's scanned every clean page in the system. Potential changes to how quicksc->may_writepagecould trigger are of little concern.Quoted 2 lines
Remove the
force_scanstuff, as well as the ugly multi-pass target calculation that it necessitated.Quoted 7 lines
I _really_ like this, I hated the multi-pass part. One thig that I am worried about and changelog doesn't mention it is what we are going to do about small (<16MB) memcgs. On one hand they were already ignored in the global reclaim so this is nothing really new but maybe we want to preserve the behavior for the memcg reclaim at least which would reduce side effect of this patch which is a great cleanup otherwise. Or at least be explicit about this in the changelog.
Quoted 3 lines
<16MB groups are a legitimate concern during global reclaim, but we have done it this way for a long time and it never seemed to have mattered in practice.
Yeah, this is not really easy to spot because there are usually other memcgs which can be reclaimed.
Quoted 4 lines
And for limit reclaim, this should be much less of a concern. It just means we no longer scan these groups at
DEF_PRIORITYand will have to increase the scan window. I don't see a problem with that. And that consequence of higher priorities is right in the patch subject.
well the memory pressure spills over to others in the same hierarchy. But I agree this shouldn't a disaster.
Quoted 22 lines
Quoted 9 lines
Btw. why cannot we simply force scan at least
SWAP_CLUSTER_MAXunconditionally?mm/vmscan.c static void get_scan_count(struct lruvec *lruvec, struct mem_cgroup *memcg, · line 2267
Quoted 3 lines
mm/vmscan.c +3
-0+/* +* If the cgroup's already been deleted, make sure to +* scrape out the remaining cache. Also make sure that small memcgs will not get unnoticed during the memcg reclaim
Quoted 4 lines
mm/vmscan.c static void get_scan_count(struct lruvec *lruvec, struct mem_cgroup *memcg, · line 2269
Quoted 2 lines
mm/vmscan.c +2
-0+*/ +if (!scan && !mem_cgroup_online (memcg))if (!scan && (!mem_cgroup_online(memcg) || !global_reclaim(sc)))With this I'd be worried about regressing the setups pointed out in
6f04f48dc9c0("mm: only force scan in reclaim when none of the LRUs are big enough.").Granted, that patch is a little dubious. IMO, we should be steering the LRU balance through references and, in that case in particular, with swappiness. Using the default 60 for zswap is too low.
Quoted 7 lines
Plus, I would expect the refault detection code that was introduced around the same time as this patch to counter-act the hot file thrashing that is mentioned in that patch's changelog.
Nevertheless, it seems a bit gratuitous to go against that change so directly when global reclaim hasn't historically been a problem with groups <16MB. Limit reclaim should be fine too.
As I've already mentioned, I really love this patch I just think this is a subtle side effect. The above reasoning should be good enough I believe.
Anyway I forgot to add, I will leave the decision whether to have this in a separate patch or just added to the changelog to you.
Signature · 8 lines
Michal Hocko SUSE Labs -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH 6/9] mm: don't avoid high-priority reclaim on memcg limit reclaim
In reply to Johannes WeinerQuoted 14 lines · Johannes Weiner
246e87a93934("memcg: fixget_scan_count()for small targets") sought to avoid high reclaim priorities for memcg by forcing it to scan a minimum amount of pages whenlru_pages>> priority yielded nothing. This was done at a time when reclaim decisions like dirty throttling were tied to the priority level.Nowadays, the only meaningful thing still tied to priority dropping below
DEF_PRIORITY- 2 is gating whether laptop_mode=1 is generally allowed to write. But that is from an era where direct reclaim was still allowed to call ->writepage, and kswapd nowadays avoids writes until it's scanned every clean page in the system. Potential changes to how quicksc->may_writepagecould trigger are of little concern.
Quoted 5 lines
Remove the
force_scanstuff, as well as the ugly multi-pass target calculation that it necessitated.Signed-off-by Johannes Weiner <[email protected]>---
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Johannes Weiner
maintainerPATCH 7/9 mm: delete NR_PAGES_SCANNED and pgdat_reclaimable()
In reply to Johannes WeinerNR_PAGES_SCANNED counts number of pages scanned since the last page free event in the allocator. This was used primarily to measure the reclaimability of zones and nodes, and determine when reclaim should give up on them. In that role, it has been replaced in the preceeding patches by a different mechanism.
Being implemented as an efficient vmstat counter, it was automatically exported to userspace as well. It's however unlikely that anyone outside the kernel is using this counter in any meaningful way.
Remove the counter and the unused pgdat_reclaimable().
--- include/linux/mmzone.h | 1 - mm/internal.h | 1 - mm/page_alloc.c | 15 +++------------ mm/vmscan.c | 9 --------- mm/vmstat.c | 22 +++------------------- 5 files changed, 6 insertions(+), 42 deletions(-)
include/linux/mmzone.h +0 -1
@@ -149,7 +149,6 @@ enum node_stat_item {NR_UNEVICTABLE ,/* " " " " " */ NR_ISOLATED_ANON ,/* Temporary isolated pages from anon lru */ NR_ISOLATED_FILE ,/* Temporary isolated pages from file lru */ -NR_PAGES_SCANNED ,/* pages scanned since last reclaim */ WORKINGSET_REFAULT ,WORKINGSET_ACTIVATE , WORKINGSET_NODERECLAIM,
mm/internal.h +0 -1
@@ -91,7 +91,6 @@ extern unsigned long highest_memmap_pfn;*/ extern int isolate_lru_page (struct page *page);extern void putback_lru_page (struct page *page); -extern bool pgdat_reclaimable (struct pglist_data *pgdat);/* * in mm/rmap.c:
mm/page_alloc.c +3 -12
@@ -1088,15 +1088,11 @@ static void free_pcppages_bulk(struct zone *zone, int count, {int migratetype =0 ;int batch_free =0 ; -unsigned long nr_scanned, flags; +unsigned long flags;bool isolated_pageblocks;spin_lock_irqsave (&zone->lock, flags); isolated_pageblocks =has_isolate_pageblock (zone); - nr_scanned =node_page_state (zone->zone_pgdat,NR_PAGES_SCANNED ); -if (nr_scanned) -__mod_node_page_state (zone->zone_pgdat,NR_PAGES_SCANNED , -nr_scanned); -while (count) {struct page *page;struct list_head *list;
@@ -1148,13 +1144,10 @@ static void free_one_page(struct zone *zone, unsigned int order, int migratetype) { -unsigned long nr_scanned, flags; +unsigned long flags; +spin_lock_irqsave (&zone->lock, flags);__count_vm_events (PGFREE ,1 << order); - nr_scanned =node_page_state (zone->zone_pgdat,NR_PAGES_SCANNED ); -if (nr_scanned) -__mod_node_page_state (zone->zone_pgdat,NR_PAGES_SCANNED , -nr_scanned); -if (unlikely (has_isolate_pageblock (zone) ||is_migrate_isolate (migratetype))) { migratetype =get_pfnblock_migratetype (page, pfn);
@@ -4497,7 +4490,6 @@ void show_free_areas(unsigned int filter, nodemask_t *nodemask)#endif " writeback_tmp:%lukB" " unstable:%lukB" -" pages_scanned:%lu" " all_unreclaimable? %s" "\n" , pgdat->node_id,
@@ -4520,7 +4512,6 @@ void show_free_areas(unsigned int filter, nodemask_t *nodemask)K (node_page_state (pgdat,NR_SHMEM )),K (node_page_state (pgdat,NR_WRITEBACK_TEMP )),K (node_page_state (pgdat,NR_UNSTABLE_NFS )), -node_page_state (pgdat,NR_PAGES_SCANNED ), pgdat->kswapd_failures >=MAX_RECLAIM_RETRIES ? "yes" : "no"); }
mm/vmscan.c +0 -9
@@ -229,12 +229,6 @@ unsigned long pgdat_reclaimable_pages(struct pglist_data *pgdat)return nr; } -bool pgdat_reclaimable (struct pglist_data *pgdat) -{ -return node_page_state_snapshot (pgdat,NR_PAGES_SCANNED ) < -pgdat_reclaimable_pages (pgdat) *6 ; -} -/** * lruvec_lru_size - Returns the number of pages on the given LRU list. * @lruvec: lru vector
@@ -1749,7 +1743,6 @@ shrink_inactive_list(unsigned long nr_to_scan, struct lruvec *lruvec, reclaim_stat->recent_scanned[file] += nr_taken;if (global_reclaim (sc)) { -__mod_node_page_state (pgdat,NR_PAGES_SCANNED , nr_scanned);if (current_is_kswapd ())__count_vm_events (PGSCAN_KSWAPD , nr_scanned);else
@@ -1952,8 +1945,6 @@ static void shrink_active_list(unsigned long nr_to_scan,__mod_node_page_state (pgdat,NR_ISOLATED_ANON + file, nr_taken); reclaim_stat->recent_scanned[file] += nr_taken; -if (global_reclaim (sc)) -__mod_node_page_state (pgdat,NR_PAGES_SCANNED , nr_scanned);__count_vm_events (PGREFILL , nr_scanned);spin_unlock_irq (&pgdat->lru_lock);
mm/vmstat.c +3 -19
@@ -954,7 +954,6 @@ const char * const vmstat_text[] = {"nr_unevictable" ,"nr_isolated_anon" ,"nr_isolated_file" , -"nr_pages_scanned" ,"workingset_refault" ,"workingset_activate" , "workingset_nodereclaim",
@@ -1375,7 +1374,6 @@ static void zoneinfo_show_print(struct seq_file *m, pg_data_t *pgdat,"\n min %lu" "\n low %lu" "\n high %lu" -"\n node_scanned %lu" "\n spanned %lu" "\n present %lu" "\n managed %lu",
@@ -1383,7 +1381,6 @@ static void zoneinfo_show_print(struct seq_file *m, pg_data_t *pgdat,min_wmark_pages (zone),low_wmark_pages (zone),high_wmark_pages (zone), -node_page_state (zone->zone_pgdat,NR_PAGES_SCANNED ), zone->spanned_pages, zone->present_pages, zone->managed_pages);
@@ -1584,22 +1581,9 @@ int vmstat_refresh(struct ctl_table *table, int write,for (i =0 ; i <NR_VM_ZONE_STAT_ITEMS ; i++) { val =atomic_long_read (&vm_zone_stat[i]);if (val <0 ) { -switch (i) { -case NR_PAGES_SCANNED : -/* -* This is often seen to go negative in -* recent kernels, but not to go permanently -* negative. Whilst it would be nicer not to -* have exceptions, rooting them out would be -* another task, of rather low priority. -*/ -break ; -default : -pr_warn ("%s: %s %ld\n" , - __func__, vmstat_text[i], val); - err = -EINVAL ; -break ; - } +pr_warn ("%s: %s %ld\n" , + __func__, vmstat_text[i], val); + err = -EINVAL ; } }if (err)
Signature · 7 lines
2.11.1 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH 7/9] mm: delete NR_PAGES_SCANNED and pgdat_reclaimable()
Quoted 11 lines · Johannes Weiner
NR_PAGES_SCANNEDcounts number of pages scanned since the last page free event in the allocator. This was used primarily to measure the reclaimability of zones and nodes, and determine when reclaim should give up on them. In that role, it has been replaced in the preceeding patches by a different mechanism.Being implemented as an efficient vmstat counter, it was automatically exported to userspace as well. It's however unlikely that anyone outside the kernel is using this counter in any meaningful way.
Remove the counter and the unused
pgdat_reclaimable().
\o/
Quoted 1 line
Signed-off-by Johannes Weiner <[email protected]>
Quoted 175 lines
--- include/linux/mmzone.h | 1 - mm/internal.h | 1 - mm/page_alloc.c | 15 +++------------ mm/vmscan.c | 9 --------- mm/vmstat.c | 22 +++------------------- 5 files changed, 6 insertions(+), 42 deletions(-)include/linux/mmzone.h +0
-1@@ -149,7 +149,6 @@ enum node_stat_item {NR_UNEVICTABLE ,/* " " " " " */ NR_ISOLATED_ANON ,/* Temporary isolated pages from anon lru */ NR_ISOLATED_FILE ,/* Temporary isolated pages from file lru */ -NR_PAGES_SCANNED ,/* pages scanned since last reclaim */ WORKINGSET_REFAULT ,WORKINGSET_ACTIVATE , WORKINGSET_NODERECLAIM,mm/internal.h +0
-1@@ -91,7 +91,6 @@ extern unsigned long highest_memmap_pfn;*/ extern int isolate_lru_page (struct page *page);extern void putback_lru_page (struct page *page); -extern bool pgdat_reclaimable (struct pglist_data *pgdat);/* * in mm/rmap.c: mm/page_alloc.c +3
-12@@ -1088,15 +1088,11 @@ static void free_pcppages_bulk(struct zone *zone, int count, {int migratetype =0 ;int batch_free =0 ; -unsigned long nr_scanned, flags; +unsigned long flags;bool isolated_pageblocks;spin_lock_irqsave (&zone->lock, flags); isolated_pageblocks =has_isolate_pageblock (zone); - nr_scanned =node_page_state (zone->zone_pgdat,NR_PAGES_SCANNED ); -if (nr_scanned) -__mod_node_page_state (zone->zone_pgdat,NR_PAGES_SCANNED , -nr_scanned); -while (count) {struct page *page;struct list_head *list;@@ -1148,13 +1144,10 @@ static void free_one_page(struct zone *zone, unsigned int order, int migratetype) { -unsigned long nr_scanned, flags; +unsigned long flags; +spin_lock_irqsave (&zone->lock, flags);__count_vm_events (PGFREE ,1 << order); - nr_scanned =node_page_state (zone->zone_pgdat,NR_PAGES_SCANNED ); -if (nr_scanned) -__mod_node_page_state (zone->zone_pgdat,NR_PAGES_SCANNED , -nr_scanned); -if (unlikely (has_isolate_pageblock (zone) ||is_migrate_isolate (migratetype))) { migratetype =get_pfnblock_migratetype (page, pfn);@@ -4497,7 +4490,6 @@ void show_free_areas(unsigned int filter, nodemask_t *nodemask)#endif " writeback_tmp:%lukB" " unstable:%lukB" -" pages_scanned:%lu" " all_unreclaimable? %s" "\n" , pgdat->node_id,@@ -4520,7 +4512,6 @@ void show_free_areas(unsigned int filter, nodemask_t *nodemask)K (node_page_state (pgdat,NR_SHMEM )),K (node_page_state (pgdat,NR_WRITEBACK_TEMP )),K (node_page_state (pgdat,NR_UNSTABLE_NFS )), -node_page_state (pgdat,NR_PAGES_SCANNED ), pgdat->kswapd_failures >=MAX_RECLAIM_RETRIES ? "yes" : "no"); }mm/vmscan.c +0
-9@@ -229,12 +229,6 @@ unsigned long pgdat_reclaimable_pages(struct pglist_data *pgdat)return nr; } -bool pgdat_reclaimable (struct pglist_data *pgdat) -{ -return node_page_state_snapshot (pgdat,NR_PAGES_SCANNED ) < -pgdat_reclaimable_pages (pgdat) *6 ; -} -/** * lruvec_lru_size - Returns the number of pages on the given LRU list. * @lruvec: lru vector @@ -1749,7 +1743,6 @@ shrink_inactive_list(unsigned long nr_to_scan, struct lruvec *lruvec, reclaim_stat->recent_scanned[file] += nr_taken;if (global_reclaim (sc)) { -__mod_node_page_state (pgdat,NR_PAGES_SCANNED , nr_scanned);if (current_is_kswapd ())__count_vm_events (PGSCAN_KSWAPD , nr_scanned);else @@ -1952,8 +1945,6 @@ static void shrink_active_list(unsigned long nr_to_scan,__mod_node_page_state (pgdat,NR_ISOLATED_ANON + file, nr_taken); reclaim_stat->recent_scanned[file] += nr_taken; -if (global_reclaim (sc)) -__mod_node_page_state (pgdat,NR_PAGES_SCANNED , nr_scanned);__count_vm_events (PGREFILL , nr_scanned);spin_unlock_irq (&pgdat->lru_lock);mm/vmstat.c +3
-19@@ -954,7 +954,6 @@ const char * const vmstat_text[] = {"nr_unevictable" ,"nr_isolated_anon" ,"nr_isolated_file" , -"nr_pages_scanned" ,"workingset_refault" ,"workingset_activate" , "workingset_nodereclaim",@@ -1375,7 +1374,6 @@ static void zoneinfo_show_print(struct seq_file *m, pg_data_t *pgdat,"\n min %lu" "\n low %lu" "\n high %lu" -"\n node_scanned %lu" "\n spanned %lu" "\n present %lu" "\n managed %lu",@@ -1383,7 +1381,6 @@ static void zoneinfo_show_print(struct seq_file *m, pg_data_t *pgdat,min_wmark_pages (zone),low_wmark_pages (zone),high_wmark_pages (zone), -node_page_state (zone->zone_pgdat,NR_PAGES_SCANNED ), zone->spanned_pages, zone->present_pages, zone->managed_pages);@@ -1584,22 +1581,9 @@ int vmstat_refresh(struct ctl_table *table, int write,for (i =0 ; i <NR_VM_ZONE_STAT_ITEMS ; i++) { val =atomic_long_read (&vm_zone_stat[i]);if (val <0 ) { -switch (i) { -case NR_PAGES_SCANNED : -/* -* This is often seen to go negative in -* recent kernels, but not to go permanently -* negative. Whilst it would be nicer not to -* have exceptions, rooting them out would be -* another task, of rather low priority. -*/ -break ; -default : -pr_warn ("%s: %s %ld\n" , - __func__, vmstat_text[i], val); - err = -EINVAL ; -break ; - } +pr_warn ("%s: %s %ld\n" , + __func__, vmstat_text[i], val); + err = -EINVAL ; } }if (err)Signature · 1 line
2.11.1
Signature · 8 lines
Michal Hocko SUSE Labs -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH 7/9] mm: delete NR_PAGES_SCANNED and pgdat_reclaimable()
In reply to Johannes WeinerQuoted 7 lines · Johannes Weiner
NR_PAGES_SCANNEDcounts number of pages scanned since the last page free event in the allocator. This was used primarily to measure the reclaimability of zones and nodes, and determine when reclaim should give up on them. In that role, it has been replaced in the preceeding patches by a different mechanism.
Quoted 8 lines
Being implemented as an efficient vmstat counter, it was automatically exported to userspace as well. It's however unlikely that anyone outside the kernel is using this counter in any meaningful way.
Remove the counter and the unused
pgdat_reclaimable().Signed-off-by Johannes Weiner <[email protected]>---
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Johannes Weiner
maintainerPATCH 8/9 Revert "mm, vmscan: account for skipped pages as a partial scan"
In reply to Johannes WeinerThis reverts commit d7f05528eedb047efe2288cff777676b028747b6.
Now that reclaimability of a node is no longer based on the ratio between pages scanned and theoretically reclaimable pages, we can remove accounting tricks for pages skipped due to zone constraints.
--- mm/vmscan.c | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-)
mm/vmscan.c +4 -18
@@ -1471,12 +1471,12 @@ static unsigned long isolate_lru_pages(unsigned long nr_to_scan,unsigned long nr_taken =0 ;unsigned long nr_zone_taken[MAX_NR_ZONES ] = {0 };unsigned long nr_skipped[MAX_NR_ZONES ] = {0 , }; -unsigned long skipped =0 , total_skipped =0 ; +unsigned long skipped =0 ;unsigned long scan, nr_pages;LIST_HEAD (pages_skipped);for (scan =0 ; scan < nr_to_scan && nr_taken < nr_to_scan && - !list_empty (src);) { + !list_empty (src); scan++) {struct page *page; page =lru_to_page (src);
@@ -1490,12 +1490,6 @@ static unsigned long isolate_lru_pages(unsigned long nr_to_scan,continue ; } -/* -* Account for scanned and skipped separetly to avoid the pgdat -* being prematurely marked unreclaimable by pgdat_reclaimable. -*/ - scan++; -switch (__isolate_lru_page (page, mode)) {case 0 : nr_pages =hpage_nr_pages (page);
@@ -1524,6 +1518,7 @@ static unsigned long isolate_lru_pages(unsigned long nr_to_scan,if (!list_empty (&pages_skipped)) {int zid; +list_splice (&pages_skipped, src);for (zid =0 ; zid <MAX_NR_ZONES ; zid++) {if (!nr_skipped[zid])continue ;
@@ -1531,17 +1526,8 @@ static unsigned long isolate_lru_pages(unsigned long nr_to_scan,__count_zid_vm_events (PGSCAN_SKIP , zid, nr_skipped[zid]); skipped += nr_skipped[zid]; } - -/* -* Account skipped pages as a partial scan as the pgdat may be -* close to unreclaimable. If the LRU list is empty, account -* skipped pages as a full scan. -*/ - total_skipped =list_empty (src) ? skipped : skipped >>2 ; - -list_splice (&pages_skipped, src); } - *nr_scanned = scan + total_skipped; + *nr_scanned = scan;trace_mm_vmscan_lru_isolate (sc->reclaim_idx, sc->order, nr_to_scan, scan, skipped, nr_taken, mode, lru);update_lru_sizes (lruvec, lru, nr_zone_taken);
Signature · 7 lines
2.11.1 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH 8/9] Revert "mm, vmscan: account for skipped pages as a partial scan"
Quoted 7 lines · Johannes Weiner
This reverts commit
d7f05528eedb047efe2288cff777676b028747b6.Now that reclaimability of a node is no longer based on the ratio between pages scanned and theoretically reclaimable pages, we can remove accounting tricks for pages skipped due to zone constraints.
Signed-off-by Johannes Weiner <[email protected]>
Quoted 65 lines
--- mm/vmscan.c | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-)mm/vmscan.c +4
-18@@ -1471,12 +1471,12 @@ static unsigned long isolate_lru_pages(unsigned long nr_to_scan,unsigned long nr_taken =0 ;unsigned long nr_zone_taken[MAX_NR_ZONES ] = {0 };unsigned long nr_skipped[MAX_NR_ZONES ] = {0 , }; -unsigned long skipped =0 , total_skipped =0 ; +unsigned long skipped =0 ;unsigned long scan, nr_pages;LIST_HEAD (pages_skipped);for (scan =0 ; scan < nr_to_scan && nr_taken < nr_to_scan && - !list_empty (src);) { + !list_empty (src); scan++) {struct page *page; page =lru_to_page (src);@@ -1490,12 +1490,6 @@ static unsigned long isolate_lru_pages(unsigned long nr_to_scan,continue ; } -/* -* Account for scanned and skipped separetly to avoid the pgdat -* being prematurely marked unreclaimable by pgdat_reclaimable. -*/ - scan++; -switch (__isolate_lru_page (page, mode)) {case 0 : nr_pages =hpage_nr_pages (page);@@ -1524,6 +1518,7 @@ static unsigned long isolate_lru_pages(unsigned long nr_to_scan,if (!list_empty (&pages_skipped)) {int zid; +list_splice (&pages_skipped, src);for (zid =0 ; zid <MAX_NR_ZONES ; zid++) {if (!nr_skipped[zid])continue ;@@ -1531,17 +1526,8 @@ static unsigned long isolate_lru_pages(unsigned long nr_to_scan,__count_zid_vm_events (PGSCAN_SKIP , zid, nr_skipped[zid]); skipped += nr_skipped[zid]; } - -/* -* Account skipped pages as a partial scan as the pgdat may be -* close to unreclaimable. If the LRU list is empty, account -* skipped pages as a full scan. -*/ - total_skipped =list_empty (src) ? skipped : skipped >>2 ; - -list_splice (&pages_skipped, src); } - *nr_scanned = scan + total_skipped; + *nr_scanned = scan;trace_mm_vmscan_lru_isolate (sc->reclaim_idx, sc->order, nr_to_scan, scan, skipped, nr_taken, mode, lru);update_lru_sizes (lruvec, lru, nr_zone_taken);Signature · 1 line
2.11.1
Signature · 8 lines
Michal Hocko SUSE Labs -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH 8/9] Revert "mm, vmscan: account for skipped pages as a partial scan"
In reply to Johannes WeinerQuoted 9 lines · Johannes Weiner
This reverts commit
d7f05528eedb047efe2288cff777676b028747b6.Now that reclaimability of a node is no longer based on the ratio between pages scanned and theoretically reclaimable pages, we can remove accounting tricks for pages skipped due to zone constraints.
Signed-off-by Johannes Weiner <[email protected]>---
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Johannes Weiner
maintainerPATCH 9/9 mm: remove unnecessary back-off function when retrying page reclaim
In reply to Johannes WeinerThe backoff mechanism is not needed. If we have MAX_RECLAIM_RETRIES loops without progress, we'll OOM anyway; backing off might cut one or two iterations off that in the rare OOM case. If we have intermittent success reclaiming a few pages, the backoff function gets reset also, and so is of little help in these scenarios.
We might want a backoff function for when there IS progress, but not enough to be satisfactory. But this isn't that. Remove it.
--- mm/page_alloc.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-)
mm/page_alloc.c +6 -9
@@ -3511,11 +3511,10 @@ bool gfp_pfmemalloc_allowed(gfp_t gfp_mask)/* * Checks whether it makes sense to retry the reclaim to make a forward progress * for the given allocation request. -* The reclaim feedback represented by did_some_progress (any progress during -* the last reclaim round) and no_progress_loops (number of reclaim rounds without -* any progress in a row) is considered as well as the reclaimable pages on the -* applicable zone list (with a backoff mechanism which is a function of -* no_progress_loops). +* +* We give up when we either have tried MAX_RECLAIM_RETRIES in a row +* without success, or when we couldn't even meet the watermark if we +* reclaimed all remaining pages on the LRU lists. * * Returns true if a retry is viable or false to enter the oom path. */
@@ -3560,13 +3559,11 @@ should_reclaim_retry(gfp_t gfp_mask, unsigned order,bool wmark; available = reclaimable =zone_reclaimable_pages (zone); - available -=DIV_ROUND_UP ((*no_progress_loops) * available, -MAX_RECLAIM_RETRIES ); available +=zone_page_state_snapshot (zone,NR_FREE_PAGES );/* -* Would the allocation succeed if we reclaimed the whole -* available? +* Would the allocation succeed if we reclaimed all +* reclaimable pages? */ wmark =__zone_watermark_ok (zone, order, min_wmark,ac_classzone_idx (ac), alloc_flags, available);
Signature · 7 lines
2.11.1 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH 9/9] mm: remove unnecessary back-off function when retrying page reclaim
Quoted 5 lines · Johannes Weiner
The backoff mechanism is not needed. If we have
MAX_RECLAIM_RETRIESloops without progress, we'll OOM anyway; backing off might cut one or two iterations off that in the rare OOM case. If we have intermittent success reclaiming a few pages, the backoff function gets reset also, and so is of little help in these scenarios.
Yes, as already mentioned elsewhere the original intention was to a more graceful oom convergence when we are trashing over last few reclaimable pages but as the code evolved the result is not all that great.
Quoted 2 lines
We might want a backoff function for when there IS progress, but not enough to be satisfactory. But this isn't that. Remove it.
Completely agreed.
Quoted 1 line
Signed-off-by Johannes Weiner <[email protected]>
Quoted 42 lines
--- mm/page_alloc.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-)mm/page_alloc.c +6
-9@@ -3511,11 +3511,10 @@ bool gfp_pfmemalloc_allowed(gfp_t gfp_mask)/* * Checks whether it makes sense to retry the reclaim to make a forward progress * for the given allocation request. -* The reclaim feedback represented by did_some_progress (any progress during -* the last reclaim round) and no_progress_loops (number of reclaim rounds without -* any progress in a row) is considered as well as the reclaimable pages on the -* applicable zone list (with a backoff mechanism which is a function of -* no_progress_loops). +* +* We give up when we either have tried MAX_RECLAIM_RETRIES in a row +* without success, or when we couldn't even meet the watermark if we +* reclaimed all remaining pages on the LRU lists. * * Returns true if a retry is viable or false to enter the oom path. */ @@ -3560,13 +3559,11 @@ should_reclaim_retry(gfp_t gfp_mask, unsigned order,bool wmark; available = reclaimable =zone_reclaimable_pages (zone); - available -=DIV_ROUND_UP ((*no_progress_loops) * available, -MAX_RECLAIM_RETRIES ); available +=zone_page_state_snapshot (zone,NR_FREE_PAGES );/* -* Would the allocation succeed if we reclaimed the whole -* available? +* Would the allocation succeed if we reclaimed all +* reclaimable pages? */ wmark =__zone_watermark_ok (zone, order, min_wmark,ac_classzone_idx (ac), alloc_flags, available);Signature · 1 line
2.11.1
Signature · 8 lines
Michal Hocko SUSE Labs -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH 9/9] mm: remove unnecessary back-off function when retrying page reclaim
In reply to Johannes WeinerQuoted 7 lines · Johannes Weiner
The backoff mechanism is not needed. If we have
MAX_RECLAIM_RETRIESloops without progress, we'll OOM anyway; backing off might cut one or two iterations off that in the rare OOM case. If we have intermittent success reclaiming a few pages, the backoff function gets reset also, and so is of little help in these scenarios.
Quoted 5 lines
We might want a backoff function for when there IS progress, but not enough to be satisfactory. But this isn't that. Remove it.
Signed-off-by Johannes Weiner <[email protected]>---
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>