diff options
Diffstat (limited to 'mm')
-rw-r--r-- | mm/page-writeback.c | 85 |
1 files changed, 34 insertions, 51 deletions
diff --git a/mm/page-writeback.c b/mm/page-writeback.c index de9836f43db5..e630188ccc40 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c | |||
@@ -99,23 +99,6 @@ EXPORT_SYMBOL(laptop_mode); | |||
99 | 99 | ||
100 | static void background_writeout(unsigned long _min_pages); | 100 | static void background_writeout(unsigned long _min_pages); |
101 | 101 | ||
102 | struct writeback_state | ||
103 | { | ||
104 | unsigned long nr_dirty; | ||
105 | unsigned long nr_unstable; | ||
106 | unsigned long nr_mapped; | ||
107 | unsigned long nr_writeback; | ||
108 | }; | ||
109 | |||
110 | static void get_writeback_state(struct writeback_state *wbs) | ||
111 | { | ||
112 | wbs->nr_dirty = global_page_state(NR_FILE_DIRTY); | ||
113 | wbs->nr_unstable = global_page_state(NR_UNSTABLE_NFS); | ||
114 | wbs->nr_mapped = global_page_state(NR_FILE_MAPPED) + | ||
115 | global_page_state(NR_ANON_PAGES); | ||
116 | wbs->nr_writeback = global_page_state(NR_WRITEBACK); | ||
117 | } | ||
118 | |||
119 | /* | 102 | /* |
120 | * Work out the current dirty-memory clamping and background writeout | 103 | * Work out the current dirty-memory clamping and background writeout |
121 | * thresholds. | 104 | * thresholds. |
@@ -134,8 +117,8 @@ static void get_writeback_state(struct writeback_state *wbs) | |||
134 | * clamping level. | 117 | * clamping level. |
135 | */ | 118 | */ |
136 | static void | 119 | static void |
137 | get_dirty_limits(struct writeback_state *wbs, long *pbackground, long *pdirty, | 120 | get_dirty_limits(long *pbackground, long *pdirty, |
138 | struct address_space *mapping) | 121 | struct address_space *mapping) |
139 | { | 122 | { |
140 | int background_ratio; /* Percentages */ | 123 | int background_ratio; /* Percentages */ |
141 | int dirty_ratio; | 124 | int dirty_ratio; |
@@ -145,8 +128,6 @@ get_dirty_limits(struct writeback_state *wbs, long *pbackground, long *pdirty, | |||
145 | unsigned long available_memory = total_pages; | 128 | unsigned long available_memory = total_pages; |
146 | struct task_struct *tsk; | 129 | struct task_struct *tsk; |
147 | 130 | ||
148 | get_writeback_state(wbs); | ||
149 | |||
150 | #ifdef CONFIG_HIGHMEM | 131 | #ifdef CONFIG_HIGHMEM |
151 | /* | 132 | /* |
152 | * If this mapping can only allocate from low memory, | 133 | * If this mapping can only allocate from low memory, |
@@ -157,7 +138,9 @@ get_dirty_limits(struct writeback_state *wbs, long *pbackground, long *pdirty, | |||
157 | #endif | 138 | #endif |
158 | 139 | ||
159 | 140 | ||
160 | unmapped_ratio = 100 - (wbs->nr_mapped * 100) / total_pages; | 141 | unmapped_ratio = 100 - ((global_page_state(NR_FILE_MAPPED) + |
142 | global_page_state(NR_ANON_PAGES)) * 100) / | ||
143 | total_pages; | ||
161 | 144 | ||
162 | dirty_ratio = vm_dirty_ratio; | 145 | dirty_ratio = vm_dirty_ratio; |
163 | if (dirty_ratio > unmapped_ratio / 2) | 146 | if (dirty_ratio > unmapped_ratio / 2) |
@@ -190,7 +173,6 @@ get_dirty_limits(struct writeback_state *wbs, long *pbackground, long *pdirty, | |||
190 | */ | 173 | */ |
191 | static void balance_dirty_pages(struct address_space *mapping) | 174 | static void balance_dirty_pages(struct address_space *mapping) |
192 | { | 175 | { |
193 | struct writeback_state wbs; | ||
194 | long nr_reclaimable; | 176 | long nr_reclaimable; |
195 | long background_thresh; | 177 | long background_thresh; |
196 | long dirty_thresh; | 178 | long dirty_thresh; |
@@ -208,11 +190,12 @@ static void balance_dirty_pages(struct address_space *mapping) | |||
208 | .range_cyclic = 1, | 190 | .range_cyclic = 1, |
209 | }; | 191 | }; |
210 | 192 | ||
211 | get_dirty_limits(&wbs, &background_thresh, | 193 | get_dirty_limits(&background_thresh, &dirty_thresh, mapping); |
212 | &dirty_thresh, mapping); | 194 | nr_reclaimable = global_page_state(NR_FILE_DIRTY) + |
213 | nr_reclaimable = wbs.nr_dirty + wbs.nr_unstable; | 195 | global_page_state(NR_UNSTABLE_NFS); |
214 | if (nr_reclaimable + wbs.nr_writeback <= dirty_thresh) | 196 | if (nr_reclaimable + global_page_state(NR_WRITEBACK) <= |
215 | break; | 197 | dirty_thresh) |
198 | break; | ||
216 | 199 | ||
217 | if (!dirty_exceeded) | 200 | if (!dirty_exceeded) |
218 | dirty_exceeded = 1; | 201 | dirty_exceeded = 1; |
@@ -225,11 +208,14 @@ static void balance_dirty_pages(struct address_space *mapping) | |||
225 | */ | 208 | */ |
226 | if (nr_reclaimable) { | 209 | if (nr_reclaimable) { |
227 | writeback_inodes(&wbc); | 210 | writeback_inodes(&wbc); |
228 | get_dirty_limits(&wbs, &background_thresh, | 211 | get_dirty_limits(&background_thresh, |
229 | &dirty_thresh, mapping); | 212 | &dirty_thresh, mapping); |
230 | nr_reclaimable = wbs.nr_dirty + wbs.nr_unstable; | 213 | nr_reclaimable = global_page_state(NR_FILE_DIRTY) + |
231 | if (nr_reclaimable + wbs.nr_writeback <= dirty_thresh) | 214 | global_page_state(NR_UNSTABLE_NFS); |
232 | break; | 215 | if (nr_reclaimable + |
216 | global_page_state(NR_WRITEBACK) | ||
217 | <= dirty_thresh) | ||
218 | break; | ||
233 | pages_written += write_chunk - wbc.nr_to_write; | 219 | pages_written += write_chunk - wbc.nr_to_write; |
234 | if (pages_written >= write_chunk) | 220 | if (pages_written >= write_chunk) |
235 | break; /* We've done our duty */ | 221 | break; /* We've done our duty */ |
@@ -237,8 +223,9 @@ static void balance_dirty_pages(struct address_space *mapping) | |||
237 | blk_congestion_wait(WRITE, HZ/10); | 223 | blk_congestion_wait(WRITE, HZ/10); |
238 | } | 224 | } |
239 | 225 | ||
240 | if (nr_reclaimable + wbs.nr_writeback <= dirty_thresh && dirty_exceeded) | 226 | if (nr_reclaimable + global_page_state(NR_WRITEBACK) |
241 | dirty_exceeded = 0; | 227 | <= dirty_thresh && dirty_exceeded) |
228 | dirty_exceeded = 0; | ||
242 | 229 | ||
243 | if (writeback_in_progress(bdi)) | 230 | if (writeback_in_progress(bdi)) |
244 | return; /* pdflush is already working this queue */ | 231 | return; /* pdflush is already working this queue */ |
@@ -300,12 +287,11 @@ EXPORT_SYMBOL(balance_dirty_pages_ratelimited_nr); | |||
300 | 287 | ||
301 | void throttle_vm_writeout(void) | 288 | void throttle_vm_writeout(void) |
302 | { | 289 | { |
303 | struct writeback_state wbs; | ||
304 | long background_thresh; | 290 | long background_thresh; |
305 | long dirty_thresh; | 291 | long dirty_thresh; |
306 | 292 | ||
307 | for ( ; ; ) { | 293 | for ( ; ; ) { |
308 | get_dirty_limits(&wbs, &background_thresh, &dirty_thresh, NULL); | 294 | get_dirty_limits(&background_thresh, &dirty_thresh, NULL); |
309 | 295 | ||
310 | /* | 296 | /* |
311 | * Boost the allowable dirty threshold a bit for page | 297 | * Boost the allowable dirty threshold a bit for page |
@@ -313,8 +299,9 @@ void throttle_vm_writeout(void) | |||
313 | */ | 299 | */ |
314 | dirty_thresh += dirty_thresh / 10; /* wheeee... */ | 300 | dirty_thresh += dirty_thresh / 10; /* wheeee... */ |
315 | 301 | ||
316 | if (wbs.nr_unstable + wbs.nr_writeback <= dirty_thresh) | 302 | if (global_page_state(NR_UNSTABLE_NFS) + |
317 | break; | 303 | global_page_state(NR_WRITEBACK) <= dirty_thresh) |
304 | break; | ||
318 | blk_congestion_wait(WRITE, HZ/10); | 305 | blk_congestion_wait(WRITE, HZ/10); |
319 | } | 306 | } |
320 | } | 307 | } |
@@ -337,12 +324,12 @@ static void background_writeout(unsigned long _min_pages) | |||
337 | }; | 324 | }; |
338 | 325 | ||
339 | for ( ; ; ) { | 326 | for ( ; ; ) { |
340 | struct writeback_state wbs; | ||
341 | long background_thresh; | 327 | long background_thresh; |
342 | long dirty_thresh; | 328 | long dirty_thresh; |
343 | 329 | ||
344 | get_dirty_limits(&wbs, &background_thresh, &dirty_thresh, NULL); | 330 | get_dirty_limits(&background_thresh, &dirty_thresh, NULL); |
345 | if (wbs.nr_dirty + wbs.nr_unstable < background_thresh | 331 | if (global_page_state(NR_FILE_DIRTY) + |
332 | global_page_state(NR_UNSTABLE_NFS) < background_thresh | ||
346 | && min_pages <= 0) | 333 | && min_pages <= 0) |
347 | break; | 334 | break; |
348 | wbc.encountered_congestion = 0; | 335 | wbc.encountered_congestion = 0; |
@@ -366,12 +353,9 @@ static void background_writeout(unsigned long _min_pages) | |||
366 | */ | 353 | */ |
367 | int wakeup_pdflush(long nr_pages) | 354 | int wakeup_pdflush(long nr_pages) |
368 | { | 355 | { |
369 | if (nr_pages == 0) { | 356 | if (nr_pages == 0) |
370 | struct writeback_state wbs; | 357 | nr_pages = global_page_state(NR_FILE_DIRTY) + |
371 | 358 | global_page_state(NR_UNSTABLE_NFS); | |
372 | get_writeback_state(&wbs); | ||
373 | nr_pages = wbs.nr_dirty + wbs.nr_unstable; | ||
374 | } | ||
375 | return pdflush_operation(background_writeout, nr_pages); | 359 | return pdflush_operation(background_writeout, nr_pages); |
376 | } | 360 | } |
377 | 361 | ||
@@ -402,7 +386,6 @@ static void wb_kupdate(unsigned long arg) | |||
402 | unsigned long start_jif; | 386 | unsigned long start_jif; |
403 | unsigned long next_jif; | 387 | unsigned long next_jif; |
404 | long nr_to_write; | 388 | long nr_to_write; |
405 | struct writeback_state wbs; | ||
406 | struct writeback_control wbc = { | 389 | struct writeback_control wbc = { |
407 | .bdi = NULL, | 390 | .bdi = NULL, |
408 | .sync_mode = WB_SYNC_NONE, | 391 | .sync_mode = WB_SYNC_NONE, |
@@ -415,11 +398,11 @@ static void wb_kupdate(unsigned long arg) | |||
415 | 398 | ||
416 | sync_supers(); | 399 | sync_supers(); |
417 | 400 | ||
418 | get_writeback_state(&wbs); | ||
419 | oldest_jif = jiffies - dirty_expire_interval; | 401 | oldest_jif = jiffies - dirty_expire_interval; |
420 | start_jif = jiffies; | 402 | start_jif = jiffies; |
421 | next_jif = start_jif + dirty_writeback_interval; | 403 | next_jif = start_jif + dirty_writeback_interval; |
422 | nr_to_write = wbs.nr_dirty + wbs.nr_unstable + | 404 | nr_to_write = global_page_state(NR_FILE_DIRTY) + |
405 | global_page_state(NR_UNSTABLE_NFS) + | ||
423 | (inodes_stat.nr_inodes - inodes_stat.nr_unused); | 406 | (inodes_stat.nr_inodes - inodes_stat.nr_unused); |
424 | while (nr_to_write > 0) { | 407 | while (nr_to_write > 0) { |
425 | wbc.encountered_congestion = 0; | 408 | wbc.encountered_congestion = 0; |