diff options
-rw-r--r-- | block/bio.c | 62 | ||||
-rw-r--r-- | include/linux/blk-cgroup.h | 52 | ||||
-rw-r--r-- | include/linux/cgroup.h | 2 | ||||
-rw-r--r-- | kernel/cgroup/cgroup.c | 48 |
4 files changed, 81 insertions, 83 deletions
diff --git a/block/bio.c b/block/bio.c index 71cfe3720ea7..c39251e69447 100644 --- a/block/bio.c +++ b/block/bio.c | |||
@@ -1978,18 +1978,30 @@ int bio_associate_blkg(struct bio *bio, struct blkcg_gq *blkg) | |||
1978 | return 0; | 1978 | return 0; |
1979 | } | 1979 | } |
1980 | 1980 | ||
1981 | /** | ||
1982 | * __bio_associate_blkg_from_css - internal blkg association function | ||
1983 | * | ||
1984 | * This in the core association function that all association paths rely on. | ||
1985 | * A blkg reference is taken which is released upon freeing of the bio. | ||
1986 | */ | ||
1981 | static int __bio_associate_blkg_from_css(struct bio *bio, | 1987 | static int __bio_associate_blkg_from_css(struct bio *bio, |
1982 | struct cgroup_subsys_state *css) | 1988 | struct cgroup_subsys_state *css) |
1983 | { | 1989 | { |
1990 | struct request_queue *q = bio->bi_disk->queue; | ||
1984 | struct blkcg_gq *blkg; | 1991 | struct blkcg_gq *blkg; |
1992 | int ret; | ||
1985 | 1993 | ||
1986 | rcu_read_lock(); | 1994 | rcu_read_lock(); |
1987 | 1995 | ||
1988 | blkg = blkg_lookup_create(css_to_blkcg(css), bio->bi_disk->queue); | 1996 | if (!css || !css->parent) |
1997 | blkg = q->root_blkg; | ||
1998 | else | ||
1999 | blkg = blkg_lookup_create(css_to_blkcg(css), q); | ||
1989 | 2000 | ||
1990 | rcu_read_unlock(); | 2001 | ret = bio_associate_blkg(bio, blkg); |
1991 | 2002 | ||
1992 | return bio_associate_blkg(bio, blkg); | 2003 | rcu_read_unlock(); |
2004 | return ret; | ||
1993 | } | 2005 | } |
1994 | 2006 | ||
1995 | /** | 2007 | /** |
@@ -1998,13 +2010,14 @@ static int __bio_associate_blkg_from_css(struct bio *bio, | |||
1998 | * @css: target css | 2010 | * @css: target css |
1999 | * | 2011 | * |
2000 | * Associate @bio with the blkg found by combining the css's blkg and the | 2012 | * Associate @bio with the blkg found by combining the css's blkg and the |
2001 | * request_queue of the @bio. This takes a reference on the css that will | 2013 | * request_queue of the @bio. This falls back to the queue's root_blkg if |
2002 | * be put upon freeing of @bio. | 2014 | * the association fails with the css. |
2003 | */ | 2015 | */ |
2004 | int bio_associate_blkg_from_css(struct bio *bio, | 2016 | int bio_associate_blkg_from_css(struct bio *bio, |
2005 | struct cgroup_subsys_state *css) | 2017 | struct cgroup_subsys_state *css) |
2006 | { | 2018 | { |
2007 | css_get(css); | 2019 | if (unlikely(bio->bi_blkg)) |
2020 | return -EBUSY; | ||
2008 | return __bio_associate_blkg_from_css(bio, css); | 2021 | return __bio_associate_blkg_from_css(bio, css); |
2009 | } | 2022 | } |
2010 | EXPORT_SYMBOL_GPL(bio_associate_blkg_from_css); | 2023 | EXPORT_SYMBOL_GPL(bio_associate_blkg_from_css); |
@@ -2016,22 +2029,29 @@ EXPORT_SYMBOL_GPL(bio_associate_blkg_from_css); | |||
2016 | * @page: the page to lookup the blkcg from | 2029 | * @page: the page to lookup the blkcg from |
2017 | * | 2030 | * |
2018 | * Associate @bio with the blkg from @page's owning memcg and the respective | 2031 | * Associate @bio with the blkg from @page's owning memcg and the respective |
2019 | * request_queue. This works like every other associate function wrt | 2032 | * request_queue. If cgroup_e_css returns NULL, fall back to the queue's |
2020 | * references. | 2033 | * root_blkg. |
2021 | * | 2034 | * |
2022 | * Note: this must be called after bio has an associated device. | 2035 | * Note: this must be called after bio has an associated device. |
2023 | */ | 2036 | */ |
2024 | int bio_associate_blkg_from_page(struct bio *bio, struct page *page) | 2037 | int bio_associate_blkg_from_page(struct bio *bio, struct page *page) |
2025 | { | 2038 | { |
2026 | struct cgroup_subsys_state *css; | 2039 | struct cgroup_subsys_state *css; |
2040 | int ret; | ||
2027 | 2041 | ||
2028 | if (unlikely(bio->bi_blkg)) | 2042 | if (unlikely(bio->bi_blkg)) |
2029 | return -EBUSY; | 2043 | return -EBUSY; |
2030 | if (!page->mem_cgroup) | 2044 | if (!page->mem_cgroup) |
2031 | return 0; | 2045 | return 0; |
2032 | css = cgroup_get_e_css(page->mem_cgroup->css.cgroup, &io_cgrp_subsys); | ||
2033 | 2046 | ||
2034 | return __bio_associate_blkg_from_css(bio, css); | 2047 | rcu_read_lock(); |
2048 | |||
2049 | css = cgroup_e_css(page->mem_cgroup->css.cgroup, &io_cgrp_subsys); | ||
2050 | |||
2051 | ret = __bio_associate_blkg_from_css(bio, css); | ||
2052 | |||
2053 | rcu_read_unlock(); | ||
2054 | return ret; | ||
2035 | } | 2055 | } |
2036 | #endif /* CONFIG_MEMCG */ | 2056 | #endif /* CONFIG_MEMCG */ |
2037 | 2057 | ||
@@ -2041,12 +2061,12 @@ int bio_associate_blkg_from_page(struct bio *bio, struct page *page) | |||
2041 | * @bio: target bio | 2061 | * @bio: target bio |
2042 | * | 2062 | * |
2043 | * Associate @bio with the blkg found from the bio's css and the request_queue. | 2063 | * Associate @bio with the blkg found from the bio's css and the request_queue. |
2044 | * If one is not found, bio_lookup_blkg creates the blkg. | 2064 | * If one is not found, bio_lookup_blkg creates the blkg. This falls back to |
2065 | * the queue's root_blkg if association fails. | ||
2045 | */ | 2066 | */ |
2046 | int bio_associate_create_blkg(struct request_queue *q, struct bio *bio) | 2067 | int bio_associate_create_blkg(struct request_queue *q, struct bio *bio) |
2047 | { | 2068 | { |
2048 | struct blkcg *blkcg; | 2069 | struct cgroup_subsys_state *css; |
2049 | struct blkcg_gq *blkg; | ||
2050 | int ret = 0; | 2070 | int ret = 0; |
2051 | 2071 | ||
2052 | /* someone has already associated this bio with a blkg */ | 2072 | /* someone has already associated this bio with a blkg */ |
@@ -2055,15 +2075,9 @@ int bio_associate_create_blkg(struct request_queue *q, struct bio *bio) | |||
2055 | 2075 | ||
2056 | rcu_read_lock(); | 2076 | rcu_read_lock(); |
2057 | 2077 | ||
2058 | blkcg = css_to_blkcg(blkcg_get_css()); | 2078 | css = blkcg_css(); |
2059 | 2079 | ||
2060 | if (!blkcg->css.parent) { | 2080 | ret = __bio_associate_blkg_from_css(bio, css); |
2061 | ret = bio_associate_blkg(bio, q->root_blkg); | ||
2062 | } else { | ||
2063 | blkg = blkg_lookup_create(blkcg, q); | ||
2064 | |||
2065 | ret = bio_associate_blkg(bio, blkg); | ||
2066 | } | ||
2067 | 2081 | ||
2068 | rcu_read_unlock(); | 2082 | rcu_read_unlock(); |
2069 | return ret; | 2083 | return ret; |
@@ -2080,8 +2094,6 @@ void bio_disassociate_task(struct bio *bio) | |||
2080 | bio->bi_ioc = NULL; | 2094 | bio->bi_ioc = NULL; |
2081 | } | 2095 | } |
2082 | if (bio->bi_blkg) { | 2096 | if (bio->bi_blkg) { |
2083 | /* a ref is always taken on css */ | ||
2084 | css_put(&bio_blkcg(bio)->css); | ||
2085 | blkg_put(bio->bi_blkg); | 2097 | blkg_put(bio->bi_blkg); |
2086 | bio->bi_blkg = NULL; | 2098 | bio->bi_blkg = NULL; |
2087 | } | 2099 | } |
@@ -2094,10 +2106,8 @@ void bio_disassociate_task(struct bio *bio) | |||
2094 | */ | 2106 | */ |
2095 | void bio_clone_blkg_association(struct bio *dst, struct bio *src) | 2107 | void bio_clone_blkg_association(struct bio *dst, struct bio *src) |
2096 | { | 2108 | { |
2097 | if (src->bi_blkg) { | 2109 | if (src->bi_blkg) |
2098 | css_get(&bio_blkcg(src)->css); | ||
2099 | bio_associate_blkg(dst, src->bi_blkg); | 2110 | bio_associate_blkg(dst, src->bi_blkg); |
2100 | } | ||
2101 | } | 2111 | } |
2102 | EXPORT_SYMBOL_GPL(bio_clone_blkg_association); | 2112 | EXPORT_SYMBOL_GPL(bio_clone_blkg_association); |
2103 | #endif /* CONFIG_BLK_CGROUP */ | 2113 | #endif /* CONFIG_BLK_CGROUP */ |
diff --git a/include/linux/blk-cgroup.h b/include/linux/blk-cgroup.h index c41cfcc2b4d8..2951ea3541b1 100644 --- a/include/linux/blk-cgroup.h +++ b/include/linux/blk-cgroup.h | |||
@@ -249,47 +249,6 @@ static inline struct cgroup_subsys_state *blkcg_css(void) | |||
249 | return task_css(current, io_cgrp_id); | 249 | return task_css(current, io_cgrp_id); |
250 | } | 250 | } |
251 | 251 | ||
252 | /** | ||
253 | * blkcg_get_css - find and get a reference to the css | ||
254 | * | ||
255 | * Find the css associated with either the kthread or the current task. | ||
256 | * This takes a reference on the blkcg which will need to be managed by the | ||
257 | * caller. | ||
258 | */ | ||
259 | static inline struct cgroup_subsys_state *blkcg_get_css(void) | ||
260 | { | ||
261 | struct cgroup_subsys_state *css; | ||
262 | |||
263 | rcu_read_lock(); | ||
264 | |||
265 | css = kthread_blkcg(); | ||
266 | if (css) { | ||
267 | css_get(css); | ||
268 | } else { | ||
269 | /* | ||
270 | * This is a bit complicated. It is possible task_css is seeing | ||
271 | * an old css pointer here. This is caused by the current | ||
272 | * thread migrating away from this cgroup and this cgroup dying. | ||
273 | * css_tryget() will fail when trying to take a ref on a cgroup | ||
274 | * that's ref count has hit 0. | ||
275 | * | ||
276 | * Therefore, if it does fail, this means current must have | ||
277 | * been swapped away already and this is waiting for it to | ||
278 | * propagate on the polling cpu. Hence the use of cpu_relax(). | ||
279 | */ | ||
280 | while (true) { | ||
281 | css = task_css(current, io_cgrp_id); | ||
282 | if (likely(css_tryget(css))) | ||
283 | break; | ||
284 | cpu_relax(); | ||
285 | } | ||
286 | } | ||
287 | |||
288 | rcu_read_unlock(); | ||
289 | |||
290 | return css; | ||
291 | } | ||
292 | |||
293 | static inline struct blkcg *css_to_blkcg(struct cgroup_subsys_state *css) | 252 | static inline struct blkcg *css_to_blkcg(struct cgroup_subsys_state *css) |
294 | { | 253 | { |
295 | return css ? container_of(css, struct blkcg, css) : NULL; | 254 | return css ? container_of(css, struct blkcg, css) : NULL; |
@@ -628,10 +587,8 @@ static inline struct request_list *blk_get_rl(struct request_queue *q, | |||
628 | rcu_read_lock(); | 587 | rcu_read_lock(); |
629 | 588 | ||
630 | blkcg = bio_blkcg(bio); | 589 | blkcg = bio_blkcg(bio); |
631 | if (blkcg) | 590 | if (!blkcg) |
632 | css_get(&blkcg->css); | 591 | blkcg = css_to_blkcg(blkcg_css()); |
633 | else | ||
634 | blkcg = css_to_blkcg(blkcg_get_css()); | ||
635 | 592 | ||
636 | /* bypass blkg lookup and use @q->root_rl directly for root */ | 593 | /* bypass blkg lookup and use @q->root_rl directly for root */ |
637 | if (blkcg == &blkcg_root) | 594 | if (blkcg == &blkcg_root) |
@@ -646,7 +603,8 @@ static inline struct request_list *blk_get_rl(struct request_queue *q, | |||
646 | if (unlikely(!blkg)) | 603 | if (unlikely(!blkg)) |
647 | goto root_rl; | 604 | goto root_rl; |
648 | 605 | ||
649 | blkg_get(blkg); | 606 | if (!blkg_try_get(blkg)) |
607 | goto root_rl; | ||
650 | rcu_read_unlock(); | 608 | rcu_read_unlock(); |
651 | return &blkg->rl; | 609 | return &blkg->rl; |
652 | root_rl: | 610 | root_rl: |
@@ -663,8 +621,6 @@ root_rl: | |||
663 | */ | 621 | */ |
664 | static inline void blk_put_rl(struct request_list *rl) | 622 | static inline void blk_put_rl(struct request_list *rl) |
665 | { | 623 | { |
666 | /* an additional ref is always taken for rl */ | ||
667 | css_put(&rl->blkg->blkcg->css); | ||
668 | if (rl->blkg->blkcg != &blkcg_root) | 624 | if (rl->blkg->blkcg != &blkcg_root) |
669 | blkg_put(rl->blkg); | 625 | blkg_put(rl->blkg); |
670 | } | 626 | } |
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h index 32c553556bbd..b8bcbdeb2eac 100644 --- a/include/linux/cgroup.h +++ b/include/linux/cgroup.h | |||
@@ -93,6 +93,8 @@ extern struct css_set init_css_set; | |||
93 | 93 | ||
94 | bool css_has_online_children(struct cgroup_subsys_state *css); | 94 | bool css_has_online_children(struct cgroup_subsys_state *css); |
95 | struct cgroup_subsys_state *css_from_id(int id, struct cgroup_subsys *ss); | 95 | struct cgroup_subsys_state *css_from_id(int id, struct cgroup_subsys *ss); |
96 | struct cgroup_subsys_state *cgroup_e_css(struct cgroup *cgroup, | ||
97 | struct cgroup_subsys *ss); | ||
96 | struct cgroup_subsys_state *cgroup_get_e_css(struct cgroup *cgroup, | 98 | struct cgroup_subsys_state *cgroup_get_e_css(struct cgroup *cgroup, |
97 | struct cgroup_subsys *ss); | 99 | struct cgroup_subsys *ss); |
98 | struct cgroup_subsys_state *css_tryget_online_from_dir(struct dentry *dentry, | 100 | struct cgroup_subsys_state *css_tryget_online_from_dir(struct dentry *dentry, |
diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c index aae10baf1902..48fb22e49467 100644 --- a/kernel/cgroup/cgroup.c +++ b/kernel/cgroup/cgroup.c | |||
@@ -492,7 +492,7 @@ static struct cgroup_subsys_state *cgroup_tryget_css(struct cgroup *cgrp, | |||
492 | } | 492 | } |
493 | 493 | ||
494 | /** | 494 | /** |
495 | * cgroup_e_css - obtain a cgroup's effective css for the specified subsystem | 495 | * cgroup_e_css_by_mask - obtain a cgroup's effective css for the specified ss |
496 | * @cgrp: the cgroup of interest | 496 | * @cgrp: the cgroup of interest |
497 | * @ss: the subsystem of interest (%NULL returns @cgrp->self) | 497 | * @ss: the subsystem of interest (%NULL returns @cgrp->self) |
498 | * | 498 | * |
@@ -501,8 +501,8 @@ static struct cgroup_subsys_state *cgroup_tryget_css(struct cgroup *cgrp, | |||
501 | * enabled. If @ss is associated with the hierarchy @cgrp is on, this | 501 | * enabled. If @ss is associated with the hierarchy @cgrp is on, this |
502 | * function is guaranteed to return non-NULL css. | 502 | * function is guaranteed to return non-NULL css. |
503 | */ | 503 | */ |
504 | static struct cgroup_subsys_state *cgroup_e_css(struct cgroup *cgrp, | 504 | static struct cgroup_subsys_state *cgroup_e_css_by_mask(struct cgroup *cgrp, |
505 | struct cgroup_subsys *ss) | 505 | struct cgroup_subsys *ss) |
506 | { | 506 | { |
507 | lockdep_assert_held(&cgroup_mutex); | 507 | lockdep_assert_held(&cgroup_mutex); |
508 | 508 | ||
@@ -523,6 +523,35 @@ static struct cgroup_subsys_state *cgroup_e_css(struct cgroup *cgrp, | |||
523 | } | 523 | } |
524 | 524 | ||
525 | /** | 525 | /** |
526 | * cgroup_e_css - obtain a cgroup's effective css for the specified subsystem | ||
527 | * @cgrp: the cgroup of interest | ||
528 | * @ss: the subsystem of interest | ||
529 | * | ||
530 | * Find and get the effective css of @cgrp for @ss. The effective css is | ||
531 | * defined as the matching css of the nearest ancestor including self which | ||
532 | * has @ss enabled. If @ss is not mounted on the hierarchy @cgrp is on, | ||
533 | * the root css is returned, so this function always returns a valid css. | ||
534 | * | ||
535 | * The returned css is not guaranteed to be online, and therefore it is the | ||
536 | * callers responsiblity to tryget a reference for it. | ||
537 | */ | ||
538 | struct cgroup_subsys_state *cgroup_e_css(struct cgroup *cgrp, | ||
539 | struct cgroup_subsys *ss) | ||
540 | { | ||
541 | struct cgroup_subsys_state *css; | ||
542 | |||
543 | do { | ||
544 | css = cgroup_css(cgrp, ss); | ||
545 | |||
546 | if (css) | ||
547 | return css; | ||
548 | cgrp = cgroup_parent(cgrp); | ||
549 | } while (cgrp); | ||
550 | |||
551 | return init_css_set.subsys[ss->id]; | ||
552 | } | ||
553 | |||
554 | /** | ||
526 | * cgroup_get_e_css - get a cgroup's effective css for the specified subsystem | 555 | * cgroup_get_e_css - get a cgroup's effective css for the specified subsystem |
527 | * @cgrp: the cgroup of interest | 556 | * @cgrp: the cgroup of interest |
528 | * @ss: the subsystem of interest | 557 | * @ss: the subsystem of interest |
@@ -604,10 +633,11 @@ EXPORT_SYMBOL_GPL(of_css); | |||
604 | * | 633 | * |
605 | * Should be called under cgroup_[tree_]mutex. | 634 | * Should be called under cgroup_[tree_]mutex. |
606 | */ | 635 | */ |
607 | #define for_each_e_css(css, ssid, cgrp) \ | 636 | #define for_each_e_css(css, ssid, cgrp) \ |
608 | for ((ssid) = 0; (ssid) < CGROUP_SUBSYS_COUNT; (ssid)++) \ | 637 | for ((ssid) = 0; (ssid) < CGROUP_SUBSYS_COUNT; (ssid)++) \ |
609 | if (!((css) = cgroup_e_css(cgrp, cgroup_subsys[(ssid)]))) \ | 638 | if (!((css) = cgroup_e_css_by_mask(cgrp, \ |
610 | ; \ | 639 | cgroup_subsys[(ssid)]))) \ |
640 | ; \ | ||
611 | else | 641 | else |
612 | 642 | ||
613 | /** | 643 | /** |
@@ -1006,7 +1036,7 @@ static struct css_set *find_existing_css_set(struct css_set *old_cset, | |||
1006 | * @ss is in this hierarchy, so we want the | 1036 | * @ss is in this hierarchy, so we want the |
1007 | * effective css from @cgrp. | 1037 | * effective css from @cgrp. |
1008 | */ | 1038 | */ |
1009 | template[i] = cgroup_e_css(cgrp, ss); | 1039 | template[i] = cgroup_e_css_by_mask(cgrp, ss); |
1010 | } else { | 1040 | } else { |
1011 | /* | 1041 | /* |
1012 | * @ss is not in this hierarchy, so we don't want | 1042 | * @ss is not in this hierarchy, so we don't want |
@@ -3019,7 +3049,7 @@ static int cgroup_apply_control(struct cgroup *cgrp) | |||
3019 | return ret; | 3049 | return ret; |
3020 | 3050 | ||
3021 | /* | 3051 | /* |
3022 | * At this point, cgroup_e_css() results reflect the new csses | 3052 | * At this point, cgroup_e_css_by_mask() results reflect the new csses |
3023 | * making the following cgroup_update_dfl_csses() properly update | 3053 | * making the following cgroup_update_dfl_csses() properly update |
3024 | * css associations of all tasks in the subtree. | 3054 | * css associations of all tasks in the subtree. |
3025 | */ | 3055 | */ |