aboutsummaryrefslogtreecommitdiffstats
path: root/mm/backing-dev.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/backing-dev.c')
-rw-r--r--mm/backing-dev.c36
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)
676static void cgwb_bdi_destroy(struct backing_dev_info *bdi) 681static 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
765int bdi_init(struct backing_dev_info *bdi) 772int 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}
777EXPORT_SYMBOL(bdi_init); 791EXPORT_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
826void bdi_destroy(struct backing_dev_info *bdi) 840void 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
854void 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
860void bdi_destroy(struct backing_dev_info *bdi)
861{
862 bdi_unregister(bdi);
863 bdi_exit(bdi);
864}
841EXPORT_SYMBOL(bdi_destroy); 865EXPORT_SYMBOL(bdi_destroy);
842 866
843/* 867/*