summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/sysctl/vm.txt18
-rw-r--r--include/linux/mm.h1
-rw-r--r--include/linux/mmzone.h2
-rw-r--r--kernel/sysctl.c10
-rw-r--r--mm/page_alloc.c29
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
803directory and inode objects. With vfs_cache_pressure=1000, it will look for 803directory and inode objects. With vfs_cache_pressure=1000, it will look for
804ten times more freeable objects than there are. 804ten times more freeable objects than there are.
805 805
806=============================================================
807
808watermark_scale_factor:
809
810This factor controls the aggressiveness of kswapd. It defines the
811amount of memory left in a node/system before kswapd is woken up and
812how much memory needs to be free before kswapd goes back to sleep.
813
814The unit is in fractions of 10,000. The default value of 10 means the
815distances between watermarks are 0.1% of the available memory in the
816node/system. The maximum value is 1000, or 10% of memory.
817
818A high rate of threads entering direct reclaim (allocstall) or kswapd
819going to sleep prematurely (kswapd_low_wmark_hit_quickly) can indicate
820that the number of free pages kswapd maintains for latency reasons is
821too small for the allocation bursts occurring in the system. This knob
822can then be used to tune kswapd aggressiveness accordingly.
823
806============================================================== 824==============================================================
807 825
808zone_reclaim_mode: 826zone_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 */
1891extern int min_free_kbytes; 1891extern int min_free_kbytes;
1892extern int watermark_scale_factor;
1892 1893
1893/* nommu.c */ 1894/* nommu.c */
1894extern atomic_long_t mmap_pages_allocated; 1895extern 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)
841struct ctl_table; 841struct ctl_table;
842int min_free_kbytes_sysctl_handler(struct ctl_table *, int, 842int min_free_kbytes_sysctl_handler(struct ctl_table *, int,
843 void __user *, size_t *, loff_t *); 843 void __user *, size_t *, loff_t *);
844int watermark_scale_factor_sysctl_handler(struct ctl_table *, int,
845 void __user *, size_t *, loff_t *);
844extern int sysctl_lowmem_reserve_ratio[MAX_NR_ZONES-1]; 846extern int sysctl_lowmem_reserve_ratio[MAX_NR_ZONES-1];
845int lowmem_reserve_ratio_sysctl_handler(struct ctl_table *, int, 847int 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;
126static int __maybe_unused four = 4; 126static int __maybe_unused four = 4;
127static unsigned long one_ul = 1; 127static unsigned long one_ul = 1;
128static int one_hundred = 100; 128static int one_hundred = 100;
129static int one_thousand = 1000;
129#ifdef CONFIG_PRINTK 130#ifdef CONFIG_PRINTK
130static int ten_thousand = 10000; 131static 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
250int min_free_kbytes = 1024; 250int min_free_kbytes = 1024;
251int user_min_free_kbytes = -1; 251int user_min_free_kbytes = -1;
252int watermark_scale_factor = 10;
252 253
253static unsigned long __meminitdata nr_kernel_pages; 254static unsigned long __meminitdata nr_kernel_pages;
254static unsigned long __meminitdata nr_all_pages; 255static 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
6502int 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
6493int sysctl_min_unmapped_ratio_sysctl_handler(struct ctl_table *table, int write, 6518int 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)