diff options
-rw-r--r-- | Documentation/sysctl/vm.txt | 18 | ||||
-rw-r--r-- | include/linux/mm.h | 1 | ||||
-rw-r--r-- | include/linux/mmzone.h | 2 | ||||
-rw-r--r-- | kernel/sysctl.c | 10 | ||||
-rw-r--r-- | mm/page_alloc.c | 29 |
5 files changed, 58 insertions, 2 deletions
diff --git a/Documentation/sysctl/vm.txt b/Documentation/sysctl/vm.txt index 89a887c76629..cb0368459da3 100644 --- a/Documentation/sysctl/vm.txt +++ b/Documentation/sysctl/vm.txt | |||
@@ -803,6 +803,24 @@ performance impact. Reclaim code needs to take various locks to find freeable | |||
803 | directory and inode objects. With vfs_cache_pressure=1000, it will look for | 803 | directory and inode objects. With vfs_cache_pressure=1000, it will look for |
804 | ten times more freeable objects than there are. | 804 | ten times more freeable objects than there are. |
805 | 805 | ||
806 | ============================================================= | ||
807 | |||
808 | watermark_scale_factor: | ||
809 | |||
810 | This factor controls the aggressiveness of kswapd. It defines the | ||
811 | amount of memory left in a node/system before kswapd is woken up and | ||
812 | how much memory needs to be free before kswapd goes back to sleep. | ||
813 | |||
814 | The unit is in fractions of 10,000. The default value of 10 means the | ||
815 | distances between watermarks are 0.1% of the available memory in the | ||
816 | node/system. The maximum value is 1000, or 10% of memory. | ||
817 | |||
818 | A high rate of threads entering direct reclaim (allocstall) or kswapd | ||
819 | going to sleep prematurely (kswapd_low_wmark_hit_quickly) can indicate | ||
820 | that the number of free pages kswapd maintains for latency reasons is | ||
821 | too small for the allocation bursts occurring in the system. This knob | ||
822 | can then be used to tune kswapd aggressiveness accordingly. | ||
823 | |||
806 | ============================================================== | 824 | ============================================================== |
807 | 825 | ||
808 | zone_reclaim_mode: | 826 | zone_reclaim_mode: |
diff --git a/include/linux/mm.h b/include/linux/mm.h index 75d1907b9009..f7fd64227d3a 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h | |||
@@ -1889,6 +1889,7 @@ extern void zone_pcp_reset(struct zone *zone); | |||
1889 | 1889 | ||
1890 | /* page_alloc.c */ | 1890 | /* page_alloc.c */ |
1891 | extern int min_free_kbytes; | 1891 | extern int min_free_kbytes; |
1892 | extern int watermark_scale_factor; | ||
1892 | 1893 | ||
1893 | /* nommu.c */ | 1894 | /* nommu.c */ |
1894 | extern atomic_long_t mmap_pages_allocated; | 1895 | extern atomic_long_t mmap_pages_allocated; |
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index bdd9a270a813..c60df9257cc7 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h | |||
@@ -841,6 +841,8 @@ static inline int is_highmem(struct zone *zone) | |||
841 | struct ctl_table; | 841 | struct ctl_table; |
842 | int min_free_kbytes_sysctl_handler(struct ctl_table *, int, | 842 | int min_free_kbytes_sysctl_handler(struct ctl_table *, int, |
843 | void __user *, size_t *, loff_t *); | 843 | void __user *, size_t *, loff_t *); |
844 | int watermark_scale_factor_sysctl_handler(struct ctl_table *, int, | ||
845 | void __user *, size_t *, loff_t *); | ||
844 | extern int sysctl_lowmem_reserve_ratio[MAX_NR_ZONES-1]; | 846 | extern int sysctl_lowmem_reserve_ratio[MAX_NR_ZONES-1]; |
845 | int lowmem_reserve_ratio_sysctl_handler(struct ctl_table *, int, | 847 | int lowmem_reserve_ratio_sysctl_handler(struct ctl_table *, int, |
846 | void __user *, size_t *, loff_t *); | 848 | void __user *, size_t *, loff_t *); |
diff --git a/kernel/sysctl.c b/kernel/sysctl.c index f5102fabef7f..725587f10667 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c | |||
@@ -126,6 +126,7 @@ static int __maybe_unused two = 2; | |||
126 | static int __maybe_unused four = 4; | 126 | static int __maybe_unused four = 4; |
127 | static unsigned long one_ul = 1; | 127 | static unsigned long one_ul = 1; |
128 | static int one_hundred = 100; | 128 | static int one_hundred = 100; |
129 | static int one_thousand = 1000; | ||
129 | #ifdef CONFIG_PRINTK | 130 | #ifdef CONFIG_PRINTK |
130 | static int ten_thousand = 10000; | 131 | static int ten_thousand = 10000; |
131 | #endif | 132 | #endif |
@@ -1404,6 +1405,15 @@ static struct ctl_table vm_table[] = { | |||
1404 | .extra1 = &zero, | 1405 | .extra1 = &zero, |
1405 | }, | 1406 | }, |
1406 | { | 1407 | { |
1408 | .procname = "watermark_scale_factor", | ||
1409 | .data = &watermark_scale_factor, | ||
1410 | .maxlen = sizeof(watermark_scale_factor), | ||
1411 | .mode = 0644, | ||
1412 | .proc_handler = watermark_scale_factor_sysctl_handler, | ||
1413 | .extra1 = &one, | ||
1414 | .extra2 = &one_thousand, | ||
1415 | }, | ||
1416 | { | ||
1407 | .procname = "percpu_pagelist_fraction", | 1417 | .procname = "percpu_pagelist_fraction", |
1408 | .data = &percpu_pagelist_fraction, | 1418 | .data = &percpu_pagelist_fraction, |
1409 | .maxlen = sizeof(percpu_pagelist_fraction), | 1419 | .maxlen = sizeof(percpu_pagelist_fraction), |
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 941b802e11ec..d156310aedeb 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
@@ -249,6 +249,7 @@ compound_page_dtor * const compound_page_dtors[] = { | |||
249 | 249 | ||
250 | int min_free_kbytes = 1024; | 250 | int min_free_kbytes = 1024; |
251 | int user_min_free_kbytes = -1; | 251 | int user_min_free_kbytes = -1; |
252 | int watermark_scale_factor = 10; | ||
252 | 253 | ||
253 | static unsigned long __meminitdata nr_kernel_pages; | 254 | static unsigned long __meminitdata nr_kernel_pages; |
254 | static unsigned long __meminitdata nr_all_pages; | 255 | static unsigned long __meminitdata nr_all_pages; |
@@ -6347,8 +6348,17 @@ static void __setup_per_zone_wmarks(void) | |||
6347 | zone->watermark[WMARK_MIN] = tmp; | 6348 | zone->watermark[WMARK_MIN] = tmp; |
6348 | } | 6349 | } |
6349 | 6350 | ||
6350 | zone->watermark[WMARK_LOW] = min_wmark_pages(zone) + (tmp >> 2); | 6351 | /* |
6351 | zone->watermark[WMARK_HIGH] = min_wmark_pages(zone) + (tmp >> 1); | 6352 | * Set the kswapd watermarks distance according to the |
6353 | * scale factor in proportion to available memory, but | ||
6354 | * ensure a minimum size on small systems. | ||
6355 | */ | ||
6356 | tmp = max_t(u64, tmp >> 2, | ||
6357 | mult_frac(zone->managed_pages, | ||
6358 | watermark_scale_factor, 10000)); | ||
6359 | |||
6360 | zone->watermark[WMARK_LOW] = min_wmark_pages(zone) + tmp; | ||
6361 | zone->watermark[WMARK_HIGH] = min_wmark_pages(zone) + tmp * 2; | ||
6352 | 6362 | ||
6353 | __mod_zone_page_state(zone, NR_ALLOC_BATCH, | 6363 | __mod_zone_page_state(zone, NR_ALLOC_BATCH, |
6354 | high_wmark_pages(zone) - low_wmark_pages(zone) - | 6364 | high_wmark_pages(zone) - low_wmark_pages(zone) - |
@@ -6489,6 +6499,21 @@ int min_free_kbytes_sysctl_handler(struct ctl_table *table, int write, | |||
6489 | return 0; | 6499 | return 0; |
6490 | } | 6500 | } |
6491 | 6501 | ||
6502 | int watermark_scale_factor_sysctl_handler(struct ctl_table *table, int write, | ||
6503 | void __user *buffer, size_t *length, loff_t *ppos) | ||
6504 | { | ||
6505 | int rc; | ||
6506 | |||
6507 | rc = proc_dointvec_minmax(table, write, buffer, length, ppos); | ||
6508 | if (rc) | ||
6509 | return rc; | ||
6510 | |||
6511 | if (write) | ||
6512 | setup_per_zone_wmarks(); | ||
6513 | |||
6514 | return 0; | ||
6515 | } | ||
6516 | |||
6492 | #ifdef CONFIG_NUMA | 6517 | #ifdef CONFIG_NUMA |
6493 | int sysctl_min_unmapped_ratio_sysctl_handler(struct ctl_table *table, int write, | 6518 | int sysctl_min_unmapped_ratio_sysctl_handler(struct ctl_table *table, int write, |
6494 | void __user *buffer, size_t *length, loff_t *ppos) | 6519 | void __user *buffer, size_t *length, loff_t *ppos) |