summaryrefslogtreecommitdiffstats
path: root/mm/backing-dev.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/backing-dev.c')
-rw-r--r--mm/backing-dev.c55
1 files changed, 37 insertions, 18 deletions
diff --git a/mm/backing-dev.c b/mm/backing-dev.c
index 612aa7c5ddbd..d9daa3e422d0 100644
--- a/mm/backing-dev.c
+++ b/mm/backing-dev.c
@@ -618,13 +618,12 @@ out_put:
618} 618}
619 619
620/** 620/**
621 * wb_get_create - get wb for a given memcg, create if necessary 621 * wb_get_lookup - get wb for a given memcg
622 * @bdi: target bdi 622 * @bdi: target bdi
623 * @memcg_css: cgroup_subsys_state of the target memcg (must have positive ref) 623 * @memcg_css: cgroup_subsys_state of the target memcg (must have positive ref)
624 * @gfp: allocation mask to use
625 * 624 *
626 * Try to get the wb for @memcg_css on @bdi. If it doesn't exist, try to 625 * Try to get the wb for @memcg_css on @bdi. The returned wb has its
627 * create one. The returned wb has its refcount incremented. 626 * refcount incremented.
628 * 627 *
629 * This function uses css_get() on @memcg_css and thus expects its refcnt 628 * This function uses css_get() on @memcg_css and thus expects its refcnt
630 * to be positive on invocation. IOW, rcu_read_lock() protection on 629 * to be positive on invocation. IOW, rcu_read_lock() protection on
@@ -641,6 +640,39 @@ out_put:
641 * each lookup. On mismatch, the existing wb is discarded and a new one is 640 * each lookup. On mismatch, the existing wb is discarded and a new one is
642 * created. 641 * created.
643 */ 642 */
643struct bdi_writeback *wb_get_lookup(struct backing_dev_info *bdi,
644 struct cgroup_subsys_state *memcg_css)
645{
646 struct bdi_writeback *wb;
647
648 if (!memcg_css->parent)
649 return &bdi->wb;
650
651 rcu_read_lock();
652 wb = radix_tree_lookup(&bdi->cgwb_tree, memcg_css->id);
653 if (wb) {
654 struct cgroup_subsys_state *blkcg_css;
655
656 /* see whether the blkcg association has changed */
657 blkcg_css = cgroup_get_e_css(memcg_css->cgroup, &io_cgrp_subsys);
658 if (unlikely(wb->blkcg_css != blkcg_css || !wb_tryget(wb)))
659 wb = NULL;
660 css_put(blkcg_css);
661 }
662 rcu_read_unlock();
663
664 return wb;
665}
666
667/**
668 * wb_get_create - get wb for a given memcg, create if necessary
669 * @bdi: target bdi
670 * @memcg_css: cgroup_subsys_state of the target memcg (must have positive ref)
671 * @gfp: allocation mask to use
672 *
673 * Try to get the wb for @memcg_css on @bdi. If it doesn't exist, try to
674 * create one. See wb_get_lookup() for more details.
675 */
644struct bdi_writeback *wb_get_create(struct backing_dev_info *bdi, 676struct bdi_writeback *wb_get_create(struct backing_dev_info *bdi,
645 struct cgroup_subsys_state *memcg_css, 677 struct cgroup_subsys_state *memcg_css,
646 gfp_t gfp) 678 gfp_t gfp)
@@ -653,20 +685,7 @@ struct bdi_writeback *wb_get_create(struct backing_dev_info *bdi,
653 return &bdi->wb; 685 return &bdi->wb;
654 686
655 do { 687 do {
656 rcu_read_lock(); 688 wb = wb_get_lookup(bdi, memcg_css);
657 wb = radix_tree_lookup(&bdi->cgwb_tree, memcg_css->id);
658 if (wb) {
659 struct cgroup_subsys_state *blkcg_css;
660
661 /* see whether the blkcg association has changed */
662 blkcg_css = cgroup_get_e_css(memcg_css->cgroup,
663 &io_cgrp_subsys);
664 if (unlikely(wb->blkcg_css != blkcg_css ||
665 !wb_tryget(wb)))
666 wb = NULL;
667 css_put(blkcg_css);
668 }
669 rcu_read_unlock();
670 } while (!wb && !cgwb_create(bdi, memcg_css, gfp)); 689 } while (!wb && !cgwb_create(bdi, memcg_css, gfp));
671 690
672 return wb; 691 return wb;