diff options
Diffstat (limited to 'mm/backing-dev.c')
-rw-r--r-- | mm/backing-dev.c | 36 |
1 files changed, 30 insertions, 6 deletions
diff --git a/mm/backing-dev.c b/mm/backing-dev.c index 2df8ddcb0ca0..619984fc07ec 100644 --- a/mm/backing-dev.c +++ b/mm/backing-dev.c | |||
@@ -480,6 +480,10 @@ static void cgwb_release_workfn(struct work_struct *work) | |||
480 | release_work); | 480 | release_work); |
481 | struct backing_dev_info *bdi = wb->bdi; | 481 | struct backing_dev_info *bdi = wb->bdi; |
482 | 482 | ||
483 | spin_lock_irq(&cgwb_lock); | ||
484 | list_del_rcu(&wb->bdi_node); | ||
485 | spin_unlock_irq(&cgwb_lock); | ||
486 | |||
483 | wb_shutdown(wb); | 487 | wb_shutdown(wb); |
484 | 488 | ||
485 | css_put(wb->memcg_css); | 489 | css_put(wb->memcg_css); |
@@ -575,6 +579,7 @@ static int cgwb_create(struct backing_dev_info *bdi, | |||
575 | ret = radix_tree_insert(&bdi->cgwb_tree, memcg_css->id, wb); | 579 | ret = radix_tree_insert(&bdi->cgwb_tree, memcg_css->id, wb); |
576 | if (!ret) { | 580 | if (!ret) { |
577 | atomic_inc(&bdi->usage_cnt); | 581 | atomic_inc(&bdi->usage_cnt); |
582 | list_add_tail_rcu(&wb->bdi_node, &bdi->wb_list); | ||
578 | list_add(&wb->memcg_node, memcg_cgwb_list); | 583 | list_add(&wb->memcg_node, memcg_cgwb_list); |
579 | list_add(&wb->blkcg_node, blkcg_cgwb_list); | 584 | list_add(&wb->blkcg_node, blkcg_cgwb_list); |
580 | css_get(memcg_css); | 585 | css_get(memcg_css); |
@@ -676,7 +681,7 @@ static int cgwb_bdi_init(struct backing_dev_info *bdi) | |||
676 | static void cgwb_bdi_destroy(struct backing_dev_info *bdi) | 681 | static void cgwb_bdi_destroy(struct backing_dev_info *bdi) |
677 | { | 682 | { |
678 | struct radix_tree_iter iter; | 683 | struct radix_tree_iter iter; |
679 | struct bdi_writeback_congested *congested, *congested_n; | 684 | struct rb_node *rbn; |
680 | void **slot; | 685 | void **slot; |
681 | 686 | ||
682 | WARN_ON(test_bit(WB_registered, &bdi->wb.state)); | 687 | WARN_ON(test_bit(WB_registered, &bdi->wb.state)); |
@@ -686,9 +691,11 @@ static void cgwb_bdi_destroy(struct backing_dev_info *bdi) | |||
686 | radix_tree_for_each_slot(slot, &bdi->cgwb_tree, &iter, 0) | 691 | radix_tree_for_each_slot(slot, &bdi->cgwb_tree, &iter, 0) |
687 | cgwb_kill(*slot); | 692 | cgwb_kill(*slot); |
688 | 693 | ||
689 | rbtree_postorder_for_each_entry_safe(congested, congested_n, | 694 | while ((rbn = rb_first(&bdi->cgwb_congested_tree))) { |
690 | &bdi->cgwb_congested_tree, rb_node) { | 695 | struct bdi_writeback_congested *congested = |
691 | rb_erase(&congested->rb_node, &bdi->cgwb_congested_tree); | 696 | rb_entry(rbn, struct bdi_writeback_congested, rb_node); |
697 | |||
698 | rb_erase(rbn, &bdi->cgwb_congested_tree); | ||
692 | congested->bdi = NULL; /* mark @congested unlinked */ | 699 | congested->bdi = NULL; /* mark @congested unlinked */ |
693 | } | 700 | } |
694 | 701 | ||
@@ -764,15 +771,22 @@ static void cgwb_bdi_destroy(struct backing_dev_info *bdi) { } | |||
764 | 771 | ||
765 | int bdi_init(struct backing_dev_info *bdi) | 772 | int bdi_init(struct backing_dev_info *bdi) |
766 | { | 773 | { |
774 | int ret; | ||
775 | |||
767 | bdi->dev = NULL; | 776 | bdi->dev = NULL; |
768 | 777 | ||
769 | bdi->min_ratio = 0; | 778 | bdi->min_ratio = 0; |
770 | bdi->max_ratio = 100; | 779 | bdi->max_ratio = 100; |
771 | bdi->max_prop_frac = FPROP_FRAC_BASE; | 780 | bdi->max_prop_frac = FPROP_FRAC_BASE; |
772 | INIT_LIST_HEAD(&bdi->bdi_list); | 781 | INIT_LIST_HEAD(&bdi->bdi_list); |
782 | INIT_LIST_HEAD(&bdi->wb_list); | ||
773 | init_waitqueue_head(&bdi->wb_waitq); | 783 | init_waitqueue_head(&bdi->wb_waitq); |
774 | 784 | ||
775 | return cgwb_bdi_init(bdi); | 785 | ret = cgwb_bdi_init(bdi); |
786 | |||
787 | list_add_tail_rcu(&bdi->wb.bdi_node, &bdi->wb_list); | ||
788 | |||
789 | return ret; | ||
776 | } | 790 | } |
777 | EXPORT_SYMBOL(bdi_init); | 791 | EXPORT_SYMBOL(bdi_init); |
778 | 792 | ||
@@ -823,7 +837,7 @@ static void bdi_remove_from_list(struct backing_dev_info *bdi) | |||
823 | synchronize_rcu_expedited(); | 837 | synchronize_rcu_expedited(); |
824 | } | 838 | } |
825 | 839 | ||
826 | void bdi_destroy(struct backing_dev_info *bdi) | 840 | void bdi_unregister(struct backing_dev_info *bdi) |
827 | { | 841 | { |
828 | /* make sure nobody finds us on the bdi_list anymore */ | 842 | /* make sure nobody finds us on the bdi_list anymore */ |
829 | bdi_remove_from_list(bdi); | 843 | bdi_remove_from_list(bdi); |
@@ -835,9 +849,19 @@ void bdi_destroy(struct backing_dev_info *bdi) | |||
835 | device_unregister(bdi->dev); | 849 | device_unregister(bdi->dev); |
836 | bdi->dev = NULL; | 850 | bdi->dev = NULL; |
837 | } | 851 | } |
852 | } | ||
838 | 853 | ||
854 | void bdi_exit(struct backing_dev_info *bdi) | ||
855 | { | ||
856 | WARN_ON_ONCE(bdi->dev); | ||
839 | wb_exit(&bdi->wb); | 857 | wb_exit(&bdi->wb); |
840 | } | 858 | } |
859 | |||
860 | void bdi_destroy(struct backing_dev_info *bdi) | ||
861 | { | ||
862 | bdi_unregister(bdi); | ||
863 | bdi_exit(bdi); | ||
864 | } | ||
841 | EXPORT_SYMBOL(bdi_destroy); | 865 | EXPORT_SYMBOL(bdi_destroy); |
842 | 866 | ||
843 | /* | 867 | /* |