diff options
Diffstat (limited to 'mm/page-writeback.c')
-rw-r--r-- | mm/page-writeback.c | 77 |
1 files changed, 71 insertions, 6 deletions
diff --git a/mm/page-writeback.c b/mm/page-writeback.c index 5e00f1772c20..789b6adbef37 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c | |||
@@ -164,9 +164,20 @@ int dirty_ratio_handler(struct ctl_table *table, int write, | |||
164 | */ | 164 | */ |
165 | static inline void __bdi_writeout_inc(struct backing_dev_info *bdi) | 165 | static inline void __bdi_writeout_inc(struct backing_dev_info *bdi) |
166 | { | 166 | { |
167 | __prop_inc_percpu(&vm_completions, &bdi->completions); | 167 | __prop_inc_percpu_max(&vm_completions, &bdi->completions, |
168 | bdi->max_prop_frac); | ||
168 | } | 169 | } |
169 | 170 | ||
171 | void bdi_writeout_inc(struct backing_dev_info *bdi) | ||
172 | { | ||
173 | unsigned long flags; | ||
174 | |||
175 | local_irq_save(flags); | ||
176 | __bdi_writeout_inc(bdi); | ||
177 | local_irq_restore(flags); | ||
178 | } | ||
179 | EXPORT_SYMBOL_GPL(bdi_writeout_inc); | ||
180 | |||
170 | static inline void task_dirty_inc(struct task_struct *tsk) | 181 | static inline void task_dirty_inc(struct task_struct *tsk) |
171 | { | 182 | { |
172 | prop_inc_single(&vm_dirties, &tsk->dirties); | 183 | prop_inc_single(&vm_dirties, &tsk->dirties); |
@@ -200,7 +211,8 @@ clip_bdi_dirty_limit(struct backing_dev_info *bdi, long dirty, long *pbdi_dirty) | |||
200 | avail_dirty = dirty - | 211 | avail_dirty = dirty - |
201 | (global_page_state(NR_FILE_DIRTY) + | 212 | (global_page_state(NR_FILE_DIRTY) + |
202 | global_page_state(NR_WRITEBACK) + | 213 | global_page_state(NR_WRITEBACK) + |
203 | global_page_state(NR_UNSTABLE_NFS)); | 214 | global_page_state(NR_UNSTABLE_NFS) + |
215 | global_page_state(NR_WRITEBACK_TEMP)); | ||
204 | 216 | ||
205 | if (avail_dirty < 0) | 217 | if (avail_dirty < 0) |
206 | avail_dirty = 0; | 218 | avail_dirty = 0; |
@@ -243,6 +255,55 @@ static void task_dirty_limit(struct task_struct *tsk, long *pdirty) | |||
243 | } | 255 | } |
244 | 256 | ||
245 | /* | 257 | /* |
258 | * | ||
259 | */ | ||
260 | static DEFINE_SPINLOCK(bdi_lock); | ||
261 | static unsigned int bdi_min_ratio; | ||
262 | |||
263 | int bdi_set_min_ratio(struct backing_dev_info *bdi, unsigned int min_ratio) | ||
264 | { | ||
265 | int ret = 0; | ||
266 | unsigned long flags; | ||
267 | |||
268 | spin_lock_irqsave(&bdi_lock, flags); | ||
269 | if (min_ratio > bdi->max_ratio) { | ||
270 | ret = -EINVAL; | ||
271 | } else { | ||
272 | min_ratio -= bdi->min_ratio; | ||
273 | if (bdi_min_ratio + min_ratio < 100) { | ||
274 | bdi_min_ratio += min_ratio; | ||
275 | bdi->min_ratio += min_ratio; | ||
276 | } else { | ||
277 | ret = -EINVAL; | ||
278 | } | ||
279 | } | ||
280 | spin_unlock_irqrestore(&bdi_lock, flags); | ||
281 | |||
282 | return ret; | ||
283 | } | ||
284 | |||
285 | int bdi_set_max_ratio(struct backing_dev_info *bdi, unsigned max_ratio) | ||
286 | { | ||
287 | unsigned long flags; | ||
288 | int ret = 0; | ||
289 | |||
290 | if (max_ratio > 100) | ||
291 | return -EINVAL; | ||
292 | |||
293 | spin_lock_irqsave(&bdi_lock, flags); | ||
294 | if (bdi->min_ratio > max_ratio) { | ||
295 | ret = -EINVAL; | ||
296 | } else { | ||
297 | bdi->max_ratio = max_ratio; | ||
298 | bdi->max_prop_frac = (PROP_FRAC_BASE * max_ratio) / 100; | ||
299 | } | ||
300 | spin_unlock_irqrestore(&bdi_lock, flags); | ||
301 | |||
302 | return ret; | ||
303 | } | ||
304 | EXPORT_SYMBOL(bdi_set_max_ratio); | ||
305 | |||
306 | /* | ||
246 | * Work out the current dirty-memory clamping and background writeout | 307 | * Work out the current dirty-memory clamping and background writeout |
247 | * thresholds. | 308 | * thresholds. |
248 | * | 309 | * |
@@ -300,7 +361,7 @@ static unsigned long determine_dirtyable_memory(void) | |||
300 | return x + 1; /* Ensure that we never return 0 */ | 361 | return x + 1; /* Ensure that we never return 0 */ |
301 | } | 362 | } |
302 | 363 | ||
303 | static void | 364 | void |
304 | get_dirty_limits(long *pbackground, long *pdirty, long *pbdi_dirty, | 365 | get_dirty_limits(long *pbackground, long *pdirty, long *pbdi_dirty, |
305 | struct backing_dev_info *bdi) | 366 | struct backing_dev_info *bdi) |
306 | { | 367 | { |
@@ -330,7 +391,7 @@ get_dirty_limits(long *pbackground, long *pdirty, long *pbdi_dirty, | |||
330 | *pdirty = dirty; | 391 | *pdirty = dirty; |
331 | 392 | ||
332 | if (bdi) { | 393 | if (bdi) { |
333 | u64 bdi_dirty = dirty; | 394 | u64 bdi_dirty; |
334 | long numerator, denominator; | 395 | long numerator, denominator; |
335 | 396 | ||
336 | /* | 397 | /* |
@@ -338,8 +399,12 @@ get_dirty_limits(long *pbackground, long *pdirty, long *pbdi_dirty, | |||
338 | */ | 399 | */ |
339 | bdi_writeout_fraction(bdi, &numerator, &denominator); | 400 | bdi_writeout_fraction(bdi, &numerator, &denominator); |
340 | 401 | ||
402 | bdi_dirty = (dirty * (100 - bdi_min_ratio)) / 100; | ||
341 | bdi_dirty *= numerator; | 403 | bdi_dirty *= numerator; |
342 | do_div(bdi_dirty, denominator); | 404 | do_div(bdi_dirty, denominator); |
405 | bdi_dirty += (dirty * bdi->min_ratio) / 100; | ||
406 | if (bdi_dirty > (dirty * bdi->max_ratio) / 100) | ||
407 | bdi_dirty = dirty * bdi->max_ratio / 100; | ||
343 | 408 | ||
344 | *pbdi_dirty = bdi_dirty; | 409 | *pbdi_dirty = bdi_dirty; |
345 | clip_bdi_dirty_limit(bdi, dirty, pbdi_dirty); | 410 | clip_bdi_dirty_limit(bdi, dirty, pbdi_dirty); |
@@ -1192,7 +1257,7 @@ int test_clear_page_writeback(struct page *page) | |||
1192 | radix_tree_tag_clear(&mapping->page_tree, | 1257 | radix_tree_tag_clear(&mapping->page_tree, |
1193 | page_index(page), | 1258 | page_index(page), |
1194 | PAGECACHE_TAG_WRITEBACK); | 1259 | PAGECACHE_TAG_WRITEBACK); |
1195 | if (bdi_cap_writeback_dirty(bdi)) { | 1260 | if (bdi_cap_account_writeback(bdi)) { |
1196 | __dec_bdi_stat(bdi, BDI_WRITEBACK); | 1261 | __dec_bdi_stat(bdi, BDI_WRITEBACK); |
1197 | __bdi_writeout_inc(bdi); | 1262 | __bdi_writeout_inc(bdi); |
1198 | } | 1263 | } |
@@ -1221,7 +1286,7 @@ int test_set_page_writeback(struct page *page) | |||
1221 | radix_tree_tag_set(&mapping->page_tree, | 1286 | radix_tree_tag_set(&mapping->page_tree, |
1222 | page_index(page), | 1287 | page_index(page), |
1223 | PAGECACHE_TAG_WRITEBACK); | 1288 | PAGECACHE_TAG_WRITEBACK); |
1224 | if (bdi_cap_writeback_dirty(bdi)) | 1289 | if (bdi_cap_account_writeback(bdi)) |
1225 | __inc_bdi_stat(bdi, BDI_WRITEBACK); | 1290 | __inc_bdi_stat(bdi, BDI_WRITEBACK); |
1226 | } | 1291 | } |
1227 | if (!PageDirty(page)) | 1292 | if (!PageDirty(page)) |