diff options
| -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; |
