diff options
-rw-r--r-- | Documentation/sysctl/vm.txt | 28 | ||||
-rw-r--r-- | include/linux/writeback.h | 2 | ||||
-rw-r--r-- | kernel/sysctl.c | 23 | ||||
-rw-r--r-- | mm/pdflush.c | 31 |
4 files changed, 72 insertions, 12 deletions
diff --git a/Documentation/sysctl/vm.txt b/Documentation/sysctl/vm.txt index 3197fc83bc51..97c4b3284329 100644 --- a/Documentation/sysctl/vm.txt +++ b/Documentation/sysctl/vm.txt | |||
@@ -39,6 +39,8 @@ Currently, these files are in /proc/sys/vm: | |||
39 | - nr_hugepages | 39 | - nr_hugepages |
40 | - nr_overcommit_hugepages | 40 | - nr_overcommit_hugepages |
41 | - nr_pdflush_threads | 41 | - nr_pdflush_threads |
42 | - nr_pdflush_threads_min | ||
43 | - nr_pdflush_threads_max | ||
42 | - nr_trim_pages (only if CONFIG_MMU=n) | 44 | - nr_trim_pages (only if CONFIG_MMU=n) |
43 | - numa_zonelist_order | 45 | - numa_zonelist_order |
44 | - oom_dump_tasks | 46 | - oom_dump_tasks |
@@ -463,6 +465,32 @@ The default value is 0. | |||
463 | 465 | ||
464 | ============================================================== | 466 | ============================================================== |
465 | 467 | ||
468 | nr_pdflush_threads_min | ||
469 | |||
470 | This value controls the minimum number of pdflush threads. | ||
471 | |||
472 | At boot time, the kernel will create and maintain 'nr_pdflush_threads_min' | ||
473 | threads for the kernel's lifetime. | ||
474 | |||
475 | The default value is 2. The minimum value you can specify is 1, and | ||
476 | the maximum value is the current setting of 'nr_pdflush_threads_max'. | ||
477 | |||
478 | See 'nr_pdflush_threads_max' below for more information. | ||
479 | |||
480 | ============================================================== | ||
481 | |||
482 | nr_pdflush_threads_max | ||
483 | |||
484 | This value controls the maximum number of pdflush threads that can be | ||
485 | created. The pdflush algorithm will create a new pdflush thread (up to | ||
486 | this maximum) if no pdflush threads have been available for >= 1 second. | ||
487 | |||
488 | The default value is 8. The minimum value you can specify is the | ||
489 | current value of 'nr_pdflush_threads_min' and the | ||
490 | maximum is 1000. | ||
491 | |||
492 | ============================================================== | ||
493 | |||
466 | overcommit_memory: | 494 | overcommit_memory: |
467 | 495 | ||
468 | This value contains a flag that enables memory overcommitment. | 496 | This value contains a flag that enables memory overcommitment. |
diff --git a/include/linux/writeback.h b/include/linux/writeback.h index 93445477f86a..9c1ed1fb6ddb 100644 --- a/include/linux/writeback.h +++ b/include/linux/writeback.h | |||
@@ -168,6 +168,8 @@ void writeback_set_ratelimit(void); | |||
168 | /* pdflush.c */ | 168 | /* pdflush.c */ |
169 | extern int nr_pdflush_threads; /* Global so it can be exported to sysctl | 169 | extern int nr_pdflush_threads; /* Global so it can be exported to sysctl |
170 | read-only. */ | 170 | read-only. */ |
171 | extern int nr_pdflush_threads_max; /* Global so it can be exported to sysctl */ | ||
172 | extern int nr_pdflush_threads_min; /* Global so it can be exported to sysctl */ | ||
171 | 173 | ||
172 | 174 | ||
173 | #endif /* WRITEBACK_H */ | 175 | #endif /* WRITEBACK_H */ |
diff --git a/kernel/sysctl.c b/kernel/sysctl.c index b125e3387568..72eb1a41dcab 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c | |||
@@ -101,6 +101,7 @@ static int __maybe_unused one = 1; | |||
101 | static int __maybe_unused two = 2; | 101 | static int __maybe_unused two = 2; |
102 | static unsigned long one_ul = 1; | 102 | static unsigned long one_ul = 1; |
103 | static int one_hundred = 100; | 103 | static int one_hundred = 100; |
104 | static int one_thousand = 1000; | ||
104 | 105 | ||
105 | /* this is needed for the proc_dointvec_minmax for [fs_]overflow UID and GID */ | 106 | /* this is needed for the proc_dointvec_minmax for [fs_]overflow UID and GID */ |
106 | static int maxolduid = 65535; | 107 | static int maxolduid = 65535; |
@@ -1027,6 +1028,28 @@ static struct ctl_table vm_table[] = { | |||
1027 | .proc_handler = &proc_dointvec, | 1028 | .proc_handler = &proc_dointvec, |
1028 | }, | 1029 | }, |
1029 | { | 1030 | { |
1031 | .ctl_name = CTL_UNNUMBERED, | ||
1032 | .procname = "nr_pdflush_threads_min", | ||
1033 | .data = &nr_pdflush_threads_min, | ||
1034 | .maxlen = sizeof nr_pdflush_threads_min, | ||
1035 | .mode = 0644 /* read-write */, | ||
1036 | .proc_handler = &proc_dointvec_minmax, | ||
1037 | .strategy = &sysctl_intvec, | ||
1038 | .extra1 = &one, | ||
1039 | .extra2 = &nr_pdflush_threads_max, | ||
1040 | }, | ||
1041 | { | ||
1042 | .ctl_name = CTL_UNNUMBERED, | ||
1043 | .procname = "nr_pdflush_threads_max", | ||
1044 | .data = &nr_pdflush_threads_max, | ||
1045 | .maxlen = sizeof nr_pdflush_threads_max, | ||
1046 | .mode = 0644 /* read-write */, | ||
1047 | .proc_handler = &proc_dointvec_minmax, | ||
1048 | .strategy = &sysctl_intvec, | ||
1049 | .extra1 = &nr_pdflush_threads_min, | ||
1050 | .extra2 = &one_thousand, | ||
1051 | }, | ||
1052 | { | ||
1030 | .ctl_name = VM_SWAPPINESS, | 1053 | .ctl_name = VM_SWAPPINESS, |
1031 | .procname = "swappiness", | 1054 | .procname = "swappiness", |
1032 | .data = &vm_swappiness, | 1055 | .data = &vm_swappiness, |
diff --git a/mm/pdflush.c b/mm/pdflush.c index 235ac440c44e..f2caf96993f8 100644 --- a/mm/pdflush.c +++ b/mm/pdflush.c | |||
@@ -58,6 +58,14 @@ static DEFINE_SPINLOCK(pdflush_lock); | |||
58 | int nr_pdflush_threads = 0; | 58 | int nr_pdflush_threads = 0; |
59 | 59 | ||
60 | /* | 60 | /* |
61 | * The max/min number of pdflush threads. R/W by sysctl at | ||
62 | * /proc/sys/vm/nr_pdflush_threads_max/min | ||
63 | */ | ||
64 | int nr_pdflush_threads_max __read_mostly = MAX_PDFLUSH_THREADS; | ||
65 | int nr_pdflush_threads_min __read_mostly = MIN_PDFLUSH_THREADS; | ||
66 | |||
67 | |||
68 | /* | ||
61 | * The time at which the pdflush thread pool last went empty | 69 | * The time at which the pdflush thread pool last went empty |
62 | */ | 70 | */ |
63 | static unsigned long last_empty_jifs; | 71 | static unsigned long last_empty_jifs; |
@@ -68,7 +76,7 @@ static unsigned long last_empty_jifs; | |||
68 | * Thread pool management algorithm: | 76 | * Thread pool management algorithm: |
69 | * | 77 | * |
70 | * - The minimum and maximum number of pdflush instances are bound | 78 | * - The minimum and maximum number of pdflush instances are bound |
71 | * by MIN_PDFLUSH_THREADS and MAX_PDFLUSH_THREADS. | 79 | * by nr_pdflush_threads_min and nr_pdflush_threads_max. |
72 | * | 80 | * |
73 | * - If there have been no idle pdflush instances for 1 second, create | 81 | * - If there have been no idle pdflush instances for 1 second, create |
74 | * a new one. | 82 | * a new one. |
@@ -134,14 +142,13 @@ static int __pdflush(struct pdflush_work *my_work) | |||
134 | * To throttle creation, we reset last_empty_jifs. | 142 | * To throttle creation, we reset last_empty_jifs. |
135 | */ | 143 | */ |
136 | if (time_after(jiffies, last_empty_jifs + 1 * HZ)) { | 144 | if (time_after(jiffies, last_empty_jifs + 1 * HZ)) { |
137 | if (list_empty(&pdflush_list)) { | 145 | if (list_empty(&pdflush_list) && |
138 | if (nr_pdflush_threads < MAX_PDFLUSH_THREADS) { | 146 | nr_pdflush_threads < nr_pdflush_threads_max) { |
139 | last_empty_jifs = jiffies; | 147 | last_empty_jifs = jiffies; |
140 | nr_pdflush_threads++; | 148 | nr_pdflush_threads++; |
141 | spin_unlock_irq(&pdflush_lock); | 149 | spin_unlock_irq(&pdflush_lock); |
142 | start_one_pdflush_thread(); | 150 | start_one_pdflush_thread(); |
143 | spin_lock_irq(&pdflush_lock); | 151 | spin_lock_irq(&pdflush_lock); |
144 | } | ||
145 | } | 152 | } |
146 | } | 153 | } |
147 | 154 | ||
@@ -153,7 +160,7 @@ static int __pdflush(struct pdflush_work *my_work) | |||
153 | */ | 160 | */ |
154 | if (list_empty(&pdflush_list)) | 161 | if (list_empty(&pdflush_list)) |
155 | continue; | 162 | continue; |
156 | if (nr_pdflush_threads <= MIN_PDFLUSH_THREADS) | 163 | if (nr_pdflush_threads <= nr_pdflush_threads_min) |
157 | continue; | 164 | continue; |
158 | pdf = list_entry(pdflush_list.prev, struct pdflush_work, list); | 165 | pdf = list_entry(pdflush_list.prev, struct pdflush_work, list); |
159 | if (time_after(jiffies, pdf->when_i_went_to_sleep + 1 * HZ)) { | 166 | if (time_after(jiffies, pdf->when_i_went_to_sleep + 1 * HZ)) { |
@@ -259,9 +266,9 @@ static int __init pdflush_init(void) | |||
259 | * Pre-set nr_pdflush_threads... If we fail to create, | 266 | * Pre-set nr_pdflush_threads... If we fail to create, |
260 | * the count will be decremented. | 267 | * the count will be decremented. |
261 | */ | 268 | */ |
262 | nr_pdflush_threads = MIN_PDFLUSH_THREADS; | 269 | nr_pdflush_threads = nr_pdflush_threads_min; |
263 | 270 | ||
264 | for (i = 0; i < MIN_PDFLUSH_THREADS; i++) | 271 | for (i = 0; i < nr_pdflush_threads_min; i++) |
265 | start_one_pdflush_thread(); | 272 | start_one_pdflush_thread(); |
266 | return 0; | 273 | return 0; |
267 | } | 274 | } |