diff options
Diffstat (limited to 'mm/backing-dev.c')
-rw-r--r-- | mm/backing-dev.c | 107 |
1 files changed, 25 insertions, 82 deletions
diff --git a/mm/backing-dev.c b/mm/backing-dev.c index 0ae0df55000b..7690ec77c722 100644 --- a/mm/backing-dev.c +++ b/mm/backing-dev.c | |||
@@ -14,19 +14,10 @@ | |||
14 | 14 | ||
15 | static atomic_long_t bdi_seq = ATOMIC_LONG_INIT(0); | 15 | static atomic_long_t bdi_seq = ATOMIC_LONG_INIT(0); |
16 | 16 | ||
17 | struct backing_dev_info default_backing_dev_info = { | ||
18 | .name = "default", | ||
19 | .ra_pages = VM_MAX_READAHEAD * 1024 / PAGE_CACHE_SIZE, | ||
20 | .state = 0, | ||
21 | .capabilities = BDI_CAP_MAP_COPY, | ||
22 | }; | ||
23 | EXPORT_SYMBOL_GPL(default_backing_dev_info); | ||
24 | |||
25 | struct backing_dev_info noop_backing_dev_info = { | 17 | struct backing_dev_info noop_backing_dev_info = { |
26 | .name = "noop", | 18 | .name = "noop", |
27 | .capabilities = BDI_CAP_NO_ACCT_AND_WRITEBACK, | 19 | .capabilities = BDI_CAP_NO_ACCT_AND_WRITEBACK, |
28 | }; | 20 | }; |
29 | EXPORT_SYMBOL_GPL(noop_backing_dev_info); | ||
30 | 21 | ||
31 | static struct class *bdi_class; | 22 | static struct class *bdi_class; |
32 | 23 | ||
@@ -40,17 +31,6 @@ LIST_HEAD(bdi_list); | |||
40 | /* bdi_wq serves all asynchronous writeback tasks */ | 31 | /* bdi_wq serves all asynchronous writeback tasks */ |
41 | struct workqueue_struct *bdi_wq; | 32 | struct workqueue_struct *bdi_wq; |
42 | 33 | ||
43 | static void bdi_lock_two(struct bdi_writeback *wb1, struct bdi_writeback *wb2) | ||
44 | { | ||
45 | if (wb1 < wb2) { | ||
46 | spin_lock(&wb1->list_lock); | ||
47 | spin_lock_nested(&wb2->list_lock, 1); | ||
48 | } else { | ||
49 | spin_lock(&wb2->list_lock); | ||
50 | spin_lock_nested(&wb1->list_lock, 1); | ||
51 | } | ||
52 | } | ||
53 | |||
54 | #ifdef CONFIG_DEBUG_FS | 34 | #ifdef CONFIG_DEBUG_FS |
55 | #include <linux/debugfs.h> | 35 | #include <linux/debugfs.h> |
56 | #include <linux/seq_file.h> | 36 | #include <linux/seq_file.h> |
@@ -264,9 +244,6 @@ static int __init default_bdi_init(void) | |||
264 | if (!bdi_wq) | 244 | if (!bdi_wq) |
265 | return -ENOMEM; | 245 | return -ENOMEM; |
266 | 246 | ||
267 | err = bdi_init(&default_backing_dev_info); | ||
268 | if (!err) | ||
269 | bdi_register(&default_backing_dev_info, NULL, "default"); | ||
270 | err = bdi_init(&noop_backing_dev_info); | 247 | err = bdi_init(&noop_backing_dev_info); |
271 | 248 | ||
272 | return err; | 249 | return err; |
@@ -355,19 +332,19 @@ EXPORT_SYMBOL(bdi_register_dev); | |||
355 | */ | 332 | */ |
356 | static void bdi_wb_shutdown(struct backing_dev_info *bdi) | 333 | static void bdi_wb_shutdown(struct backing_dev_info *bdi) |
357 | { | 334 | { |
358 | if (!bdi_cap_writeback_dirty(bdi)) | 335 | /* Make sure nobody queues further work */ |
336 | spin_lock_bh(&bdi->wb_lock); | ||
337 | if (!test_and_clear_bit(BDI_registered, &bdi->state)) { | ||
338 | spin_unlock_bh(&bdi->wb_lock); | ||
359 | return; | 339 | return; |
340 | } | ||
341 | spin_unlock_bh(&bdi->wb_lock); | ||
360 | 342 | ||
361 | /* | 343 | /* |
362 | * Make sure nobody finds us on the bdi_list anymore | 344 | * Make sure nobody finds us on the bdi_list anymore |
363 | */ | 345 | */ |
364 | bdi_remove_from_list(bdi); | 346 | bdi_remove_from_list(bdi); |
365 | 347 | ||
366 | /* Make sure nobody queues further work */ | ||
367 | spin_lock_bh(&bdi->wb_lock); | ||
368 | clear_bit(BDI_registered, &bdi->state); | ||
369 | spin_unlock_bh(&bdi->wb_lock); | ||
370 | |||
371 | /* | 348 | /* |
372 | * Drain work list and shutdown the delayed_work. At this point, | 349 | * Drain work list and shutdown the delayed_work. At this point, |
373 | * @bdi->bdi_list is empty telling bdi_Writeback_workfn() that @bdi | 350 | * @bdi->bdi_list is empty telling bdi_Writeback_workfn() that @bdi |
@@ -375,37 +352,22 @@ static void bdi_wb_shutdown(struct backing_dev_info *bdi) | |||
375 | */ | 352 | */ |
376 | mod_delayed_work(bdi_wq, &bdi->wb.dwork, 0); | 353 | mod_delayed_work(bdi_wq, &bdi->wb.dwork, 0); |
377 | flush_delayed_work(&bdi->wb.dwork); | 354 | flush_delayed_work(&bdi->wb.dwork); |
378 | WARN_ON(!list_empty(&bdi->work_list)); | ||
379 | WARN_ON(delayed_work_pending(&bdi->wb.dwork)); | ||
380 | } | 355 | } |
381 | 356 | ||
382 | /* | 357 | /* |
383 | * This bdi is going away now, make sure that no super_blocks point to it | 358 | * Called when the device behind @bdi has been removed or ejected. |
359 | * | ||
360 | * We can't really do much here except for reducing the dirty ratio at | ||
361 | * the moment. In the future we should be able to set a flag so that | ||
362 | * the filesystem can handle errors at mark_inode_dirty time instead | ||
363 | * of only at writeback time. | ||
384 | */ | 364 | */ |
385 | static void bdi_prune_sb(struct backing_dev_info *bdi) | ||
386 | { | ||
387 | struct super_block *sb; | ||
388 | |||
389 | spin_lock(&sb_lock); | ||
390 | list_for_each_entry(sb, &super_blocks, s_list) { | ||
391 | if (sb->s_bdi == bdi) | ||
392 | sb->s_bdi = &default_backing_dev_info; | ||
393 | } | ||
394 | spin_unlock(&sb_lock); | ||
395 | } | ||
396 | |||
397 | void bdi_unregister(struct backing_dev_info *bdi) | 365 | void bdi_unregister(struct backing_dev_info *bdi) |
398 | { | 366 | { |
399 | if (bdi->dev) { | 367 | if (WARN_ON_ONCE(!bdi->dev)) |
400 | bdi_set_min_ratio(bdi, 0); | 368 | return; |
401 | trace_writeback_bdi_unregister(bdi); | ||
402 | bdi_prune_sb(bdi); | ||
403 | 369 | ||
404 | bdi_wb_shutdown(bdi); | 370 | bdi_set_min_ratio(bdi, 0); |
405 | bdi_debug_unregister(bdi); | ||
406 | device_unregister(bdi->dev); | ||
407 | bdi->dev = NULL; | ||
408 | } | ||
409 | } | 371 | } |
410 | EXPORT_SYMBOL(bdi_unregister); | 372 | EXPORT_SYMBOL(bdi_unregister); |
411 | 373 | ||
@@ -474,37 +436,19 @@ void bdi_destroy(struct backing_dev_info *bdi) | |||
474 | { | 436 | { |
475 | int i; | 437 | int i; |
476 | 438 | ||
477 | /* | 439 | bdi_wb_shutdown(bdi); |
478 | * Splice our entries to the default_backing_dev_info. This | ||
479 | * condition shouldn't happen. @wb must be empty at this point and | ||
480 | * dirty inodes on it might cause other issues. This workaround is | ||
481 | * added by ce5f8e779519 ("writeback: splice dirty inode entries to | ||
482 | * default bdi on bdi_destroy()") without root-causing the issue. | ||
483 | * | ||
484 | * http://lkml.kernel.org/g/1253038617-30204-11-git-send-email-jens.axboe@oracle.com | ||
485 | * http://thread.gmane.org/gmane.linux.file-systems/35341/focus=35350 | ||
486 | * | ||
487 | * We should probably add WARN_ON() to find out whether it still | ||
488 | * happens and track it down if so. | ||
489 | */ | ||
490 | if (bdi_has_dirty_io(bdi)) { | ||
491 | struct bdi_writeback *dst = &default_backing_dev_info.wb; | ||
492 | |||
493 | bdi_lock_two(&bdi->wb, dst); | ||
494 | list_splice(&bdi->wb.b_dirty, &dst->b_dirty); | ||
495 | list_splice(&bdi->wb.b_io, &dst->b_io); | ||
496 | list_splice(&bdi->wb.b_more_io, &dst->b_more_io); | ||
497 | spin_unlock(&bdi->wb.list_lock); | ||
498 | spin_unlock(&dst->list_lock); | ||
499 | } | ||
500 | |||
501 | bdi_unregister(bdi); | ||
502 | 440 | ||
441 | WARN_ON(!list_empty(&bdi->work_list)); | ||
503 | WARN_ON(delayed_work_pending(&bdi->wb.dwork)); | 442 | WARN_ON(delayed_work_pending(&bdi->wb.dwork)); |
504 | 443 | ||
444 | if (bdi->dev) { | ||
445 | bdi_debug_unregister(bdi); | ||
446 | device_unregister(bdi->dev); | ||
447 | bdi->dev = NULL; | ||
448 | } | ||
449 | |||
505 | for (i = 0; i < NR_BDI_STAT_ITEMS; i++) | 450 | for (i = 0; i < NR_BDI_STAT_ITEMS; i++) |
506 | percpu_counter_destroy(&bdi->bdi_stat[i]); | 451 | percpu_counter_destroy(&bdi->bdi_stat[i]); |
507 | |||
508 | fprop_local_destroy_percpu(&bdi->completions); | 452 | fprop_local_destroy_percpu(&bdi->completions); |
509 | } | 453 | } |
510 | EXPORT_SYMBOL(bdi_destroy); | 454 | EXPORT_SYMBOL(bdi_destroy); |
@@ -513,13 +457,12 @@ EXPORT_SYMBOL(bdi_destroy); | |||
513 | * For use from filesystems to quickly init and register a bdi associated | 457 | * For use from filesystems to quickly init and register a bdi associated |
514 | * with dirty writeback | 458 | * with dirty writeback |
515 | */ | 459 | */ |
516 | int bdi_setup_and_register(struct backing_dev_info *bdi, char *name, | 460 | int bdi_setup_and_register(struct backing_dev_info *bdi, char *name) |
517 | unsigned int cap) | ||
518 | { | 461 | { |
519 | int err; | 462 | int err; |
520 | 463 | ||
521 | bdi->name = name; | 464 | bdi->name = name; |
522 | bdi->capabilities = cap; | 465 | bdi->capabilities = 0; |
523 | err = bdi_init(bdi); | 466 | err = bdi_init(bdi); |
524 | if (err) | 467 | if (err) |
525 | return err; | 468 | return err; |