mmotm: Replace the watermark-related union in struct zone with a watermark[] array V3
Subsystems (6)
PATCH 1/1 mmotm: Replace the watermark-related union in struct zone with a watermark[] array V3
Changelog since V2
o Remove RFC, no code change.
o Added Ack-ed from Dave Hansen. Kosaki Motohiro said it "looked good" but did not actually ack.
Changelog since V1
o Use N_wmark_pages accessors instead of array accesses
Patch page-allocator-use-allocation-flags-as-an-index-to-the-zone-watermark in -mm added a union to struct zone where the watermarks could be accessed with either zone->pages_* or a pages_mark array. The concern was that this aliasing caused more confusion that it helped.
This patch replaces the union with a watermark array that is indexed with WMARK_* defines accessed via helpers. All call sites that use zone->pages_* are updated to use the helpers for accessing the values and the array offsets for setting.
---
Documentation/sysctl/vm.txt | 11 ++++++----- Documentation/vm/balance | 18 +++++++++--------- arch/m32r/mm/discontig.c | 6 +++--- include/linux/mmzone.h | 20 ++++++++++++++------ mm/page_alloc.c | 41 +++++++++++++++++++++-------------------- mm/vmscan.c | 39 +++++++++++++++++++++------------------ mm/vmstat.c | 6 +++--- 7 files changed, 77 insertions(+), 64 deletions(-)
Documentation/sysctl/vm.txt +6 -5
@@ -235,8 +235,8 @@ These protections are added to score to judge whether this zone should be used for page allocation or should be reclaimed. In this example, if normal pages (index=2) are required to this DMA zone and -pages_high is used for watermark, the kernel judges this zone should not be -used because pages_free(1355) is smaller than watermark + protection[2] +watermark[WMARK_HIGH] is used for watermark, the kernel judges this zone should +not be used because pages_free(1355) is smaller than watermark + protection[2] (4 + 2004 = 2008). If this protection value is 0, this zone would be used for normal page requirement. If requirement is DMA zone(index=0), protection[0] (=0) is used.
@@ -282,9 +282,10 @@ The default value is 65536. min_free_kbytes: This is used to force the Linux VM to keep a minimum number -of kilobytes free. The VM uses this number to compute a pages_min -value for each lowmem zone in the system. Each lowmem zone gets -a number of reserved free pages based proportionally on its size. +of kilobytes free. The VM uses this number to compute a +watermark[WMARK_MIN] value for each lowmem zone in the system. +Each lowmem zone gets a number of reserved free pages based +proportionally on its size. Some minimal amount of memory is needed to satisfy PF_MEMALLOC allocations; if you set this to lower than 1024KB, your system will
Documentation/vm/balance +9 -9
@@ -75,15 +75,15 @@ Page stealing from process memory and shm is done if stealing the page would alleviate memory pressure on any zone in the page's node that has fallen below its watermark. -pages_min/pages_low/pages_high/low_on_memory/zone_wake_kswapd: These are -per-zone fields, used to determine when a zone needs to be balanced. When -the number of pages falls below pages_min, the hysteric field low_on_memory -gets set. This stays set till the number of free pages becomes pages_high. -When low_on_memory is set, page allocation requests will try to free some -pages in the zone (providing GFP_WAIT is set in the request). Orthogonal -to this, is the decision to poke kswapd to free some zone pages. That -decision is not hysteresis based, and is done when the number of free -pages is below pages_low; in which case zone_wake_kswapd is also set. +watemark[WMARK_MIN/WMARK_LOW/WMARK_HIGH]/low_on_memory/zone_wake_kswapd: These +are per-zone fields, used to determine when a zone needs to be balanced. When +the number of pages falls below watermark[WMARK_MIN], the hysteric field +low_on_memory gets set. This stays set till the number of free pages becomes +watermark[WMARK_HIGH]. When low_on_memory is set, page allocation requests will +try to free some pages in the zone (providing GFP_WAIT is set in the request). +Orthogonal to this, is the decision to poke kswapd to free some zone pages. +That decision is not hysteresis based, and is done when the number of free +pages is below watermark[WMARK_LOW]; in which case zone_wake_kswapd is also set. (Good) Ideas that I have heard:
arch/m32r/mm/discontig.c +3 -3
@@ -154,9 +154,9 @@ unsigned long __init zone_sizes_init(void)* Use all area of internal RAM. * see __alloc_pages() */ -NODE_DATA (1 )->node_zones->pages_min =0 ; -NODE_DATA (1 )->node_zones->pages_low =0 ; -NODE_DATA (1 )->node_zones->pages_high =0 ; +NODE_DATA (1 )->node_zones->watermark[WMARK_MIN ] =0 ; +NODE_DATA (1 )->node_zones->watermark[WMARK_LOW ] =0 ; +NODE_DATA (1 )->node_zones->watermark[WMARK_HIGH ] =0 ;return holes; }
include/linux/mmzone.h +14 -6
@@ -163,6 +163,17 @@ static inline int is_unevictable_lru(enum lru_list l)#endif } +enum zone_watermarks { +WMARK_MIN , +WMARK_LOW , +WMARK_HIGH , +NR_WMARK +}; + +#define min_wmark_pages (z) (z->watermark[WMARK_MIN]) +#define low_wmark_pages (z) (z->watermark[WMARK_LOW]) +#define high_wmark_pages (z) (z->watermark[WMARK_HIGH]) +struct per_cpu_pages {int count;/* number of pages in the list */ int high;/* high watermark, emptying needed */
@@ -275,12 +286,9 @@ struct zone_reclaim_stat {struct zone {/* Fields commonly accessed by the page allocator */ -union { -struct { -unsigned long pages_min, pages_low, pages_high; - }; -unsigned long pages_mark[3 ]; - }; + +/* zone watermarks, access with *_wmark_pages(zone) macros */ +unsigned long watermark[NR_WMARK ];/* * We don't know if the memory that we're going to allocate will be freeable
mm/page_alloc.c +21 -20
110 lines not on this page · raw message
mm/vmscan.c +21 -18
@@ -1437,7 +1437,7 @@ static void get_scan_ratio(struct zone *zone, struct scan_control *sc, free =zone_page_state (zone,NR_FREE_PAGES );/* If we have very few page cache pages, force-scan anon pages. */ -if (unlikely (file + free <= zone->pages_high)) { +if (unlikely (file + free <=high_wmark_pages (zone))) { percent[0 ] =100 ; percent[1 ] =0 ;return ;
@@ -1586,11 +1586,13 @@ static void shrink_zone(int priority, struct zone *zone,* try to reclaim pages from zones which will satisfy the caller's allocation * request. * -* We reclaim from a zone even if that zone is over pages_high. Because: +* We reclaim from a zone even if that zone is over high_wmark_pages(zone). +* Because: * a) The caller may be trying to free *extra* pages to satisfy a higher-order * allocation or -* b) The zones may be over pages_high but they must go *over* pages_high to -* satisfy the `incremental min' zone defense algorithm. +* b) The target zone may be at high_wmark_pages(zone) but the lower zones +* must go *over* high_wmark_pages(zone) to satisfy the `incremental min' +* zone defense algorithm. * * If a zone is deemed to be full of pinned pages then just give it a light * scan then give up on it.
@@ -1796,7 +1798,7 @@ unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *mem_cont,/* * For kswapd, balance_pgdat() will work across all this node's zones until -* they are all at pages_high. +* they are all at high_wmark_pages(zone). * * Returns the number of pages which were actually freed. *
@@ -1809,11 +1811,11 @@ unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *mem_cont,* the zone for when the problem goes away. * * kswapd scans the zones in the highmem->normal->dma direction. It skips -* zones which have free_pages > pages_high, but once a zone is found to have -* free_pages <= pages_high, we scan that zone and the lower zones regardless -* of the number of free pages in the lower zones. This interoperates with -* the page allocator fallback scheme to ensure that aging of pages is balanced -* across the zones. +* zones which have free_pages > high_wmark_pages(zone), but once a zone is +* found to have free_pages <= high_wmark_pages(zone), we scan that zone and the +* lower zones regardless of the number of free pages in the lower zones. This +* interoperates with the page allocator fallback scheme to ensure that aging +* of pages is balanced across the zones. */ static unsigned long balance_pgdat (pg_data_t *pgdat,int order) {
@@ -1834,7 +1836,8 @@ static unsigned long balance_pgdat(pg_data_t *pgdat, int order) };/* * temp_priority is used to remember the scanning priority at which -* this zone was successfully refilled to free_pages == pages_high. +* this zone was successfully refilled to +* free_pages == high_wmark_pages(zone). */ int temp_priority[MAX_NR_ZONES ];
@@ -1879,8 +1882,8 @@ loop_again:shrink_active_list (SWAP_CLUSTER_MAX , zone, &sc, priority,0 ); -if (!zone_watermark_ok (zone, order, zone->pages_high, -0 ,0 )) { +if (!zone_watermark_ok (zone, order, +high_wmark_pages (zone),0 ,0 )) { end_zone = i;break ; }
@@ -1914,8 +1917,8 @@ loop_again: priority != DEF_PRIORITY)continue ; -if (!zone_watermark_ok (zone, order, zone->pages_high, - end_zone,0 )) +if (!zone_watermark_ok (zone, order, +high_wmark_pages (zone), end_zone,0 )) all_zones_ok =0 ; temp_priority[i] = priority; sc.nr_scanned =0 ;
@@ -1924,8 +1927,8 @@ loop_again:* We put equal pressure on every zone, unless one * zone has way too many pages free already. */ -if (!zone_watermark_ok (zone, order,8 *zone->pages_high, - end_zone,0 )) +if (!zone_watermark_ok (zone, order, +8 *high_wmark_pages (zone), end_zone,0 ))shrink_zone (priority, zone, &sc); reclaim_state->reclaimed_slab =0 ; nr_slab = shrink_slab(sc.nr_scanned, GFP_KERNEL,
@@ -2091,7 +2094,7 @@ void wakeup_kswapd(struct zone *zone, int order)return ; pgdat = zone->zone_pgdat; -if (zone_watermark_ok (zone, order, zone->pages_low,0 ,0 )) +if (zone_watermark_ok (zone, order,low_wmark_pages (zone),0 ,0 ))return ;if (pgdat->kswapd_max_order < order) pgdat->kswapd_max_order = order;
mm/vmstat.c +3 -3
@@ -725,9 +725,9 @@ static void zoneinfo_show_print(struct seq_file *m, pg_data_t *pgdat,"\n spanned %lu" "\n present %lu" ,zone_page_state (zone,NR_FREE_PAGES ), - zone->pages_min, - zone->pages_low, - zone->pages_high, +min_wmark_pages (zone), +low_wmark_pages (zone), +high_wmark_pages (zone), zone->pages_scanned, zone->spanned_pages, zone->present_pages);
Signature · 9 lines
Mel Gorman Part-time Phd Student Linux Technology Center University of Limerick IBM Dublin Software Lab -- 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>