diff options
author | Tejun Heo <tj@kernel.org> | 2019-08-26 12:06:54 -0400 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2019-08-27 11:22:38 -0400 |
commit | ed288dc0d4aa29f65bd25b31b5cb866aa5664ff9 (patch) | |
tree | fbca2981025e2f6300933da4de6423ee3298b4a0 | |
parent | 34f8fe501f0624de115d087680c84000b5d9abc9 (diff) |
writeback: Separate out wb_get_lookup() from wb_get_create()
Separate out wb_get_lookup() which doesn't try to create one if there
isn't already one from wb_get_create(). This will be used by later
patches.
Reviewed-by: Jan Kara <jack@suse.cz>
Signed-off-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
-rw-r--r-- | include/linux/backing-dev.h | 2 | ||||
-rw-r--r-- | mm/backing-dev.c | 55 |
2 files changed, 39 insertions, 18 deletions
diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h index 84cdcfbc763f..97967ce06de3 100644 --- a/include/linux/backing-dev.h +++ b/include/linux/backing-dev.h | |||
@@ -230,6 +230,8 @@ static inline int bdi_sched_wait(void *word) | |||
230 | struct bdi_writeback_congested * | 230 | struct bdi_writeback_congested * |
231 | wb_congested_get_create(struct backing_dev_info *bdi, int blkcg_id, gfp_t gfp); | 231 | wb_congested_get_create(struct backing_dev_info *bdi, int blkcg_id, gfp_t gfp); |
232 | void wb_congested_put(struct bdi_writeback_congested *congested); | 232 | void wb_congested_put(struct bdi_writeback_congested *congested); |
233 | struct bdi_writeback *wb_get_lookup(struct backing_dev_info *bdi, | ||
234 | struct cgroup_subsys_state *memcg_css); | ||
233 | struct bdi_writeback *wb_get_create(struct backing_dev_info *bdi, | 235 | struct bdi_writeback *wb_get_create(struct backing_dev_info *bdi, |
234 | struct cgroup_subsys_state *memcg_css, | 236 | struct cgroup_subsys_state *memcg_css, |
235 | gfp_t gfp); | 237 | gfp_t gfp); |
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 | */ |
643 | struct 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 | */ | ||
644 | struct bdi_writeback *wb_get_create(struct backing_dev_info *bdi, | 676 | struct 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; |