Commit ef069b97 authored by Tejun Heo's avatar Tejun Heo Committed by Jens Axboe

blkcg: perpcu_ref init/exit should be done from blkg_alloc/free()

blkg alloc is performed as a separate step from the rest of blkg
creation so that GFP_KERNEL allocations can be used when creating
blkgs from configuration file writes because otherwise user actions
may fail due to failures of opportunistic GFP_NOWAIT allocations.

While making blkgs use percpu_ref, 7fcf2b03 ("blkcg: change blkg
reference counting to use percpu_ref") incorrectly added unconditional
opportunistic percpu_ref_init() to blkg_create() breaking this
guarantee.

This patch moves percpu_ref_init() to blkg_alloc() so makes it use
@gfp_mask that blkg_alloc() is called with.  Also, percpu_ref_exit()
is moved to blkg_free() for consistency.
Signed-off-by: default avatarTejun Heo <tj@kernel.org>
Fixes: 7fcf2b03 ("blkcg: change blkg reference counting to use percpu_ref")
Cc: Dennis Zhou <dennis@kernel.org>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent f539da82
...@@ -79,6 +79,7 @@ static void blkg_free(struct blkcg_gq *blkg) ...@@ -79,6 +79,7 @@ static void blkg_free(struct blkcg_gq *blkg)
blkg_rwstat_exit(&blkg->stat_ios); blkg_rwstat_exit(&blkg->stat_ios);
blkg_rwstat_exit(&blkg->stat_bytes); blkg_rwstat_exit(&blkg->stat_bytes);
percpu_ref_exit(&blkg->refcnt);
kfree(blkg); kfree(blkg);
} }
...@@ -86,8 +87,6 @@ static void __blkg_release(struct rcu_head *rcu) ...@@ -86,8 +87,6 @@ static void __blkg_release(struct rcu_head *rcu)
{ {
struct blkcg_gq *blkg = container_of(rcu, struct blkcg_gq, rcu_head); struct blkcg_gq *blkg = container_of(rcu, struct blkcg_gq, rcu_head);
percpu_ref_exit(&blkg->refcnt);
/* release the blkcg and parent blkg refs this blkg has been holding */ /* release the blkcg and parent blkg refs this blkg has been holding */
css_put(&blkg->blkcg->css); css_put(&blkg->blkcg->css);
if (blkg->parent) if (blkg->parent)
...@@ -132,6 +131,9 @@ static struct blkcg_gq *blkg_alloc(struct blkcg *blkcg, struct request_queue *q, ...@@ -132,6 +131,9 @@ static struct blkcg_gq *blkg_alloc(struct blkcg *blkcg, struct request_queue *q,
if (!blkg) if (!blkg)
return NULL; return NULL;
if (percpu_ref_init(&blkg->refcnt, blkg_release, 0, gfp_mask))
goto err_free;
if (blkg_rwstat_init(&blkg->stat_bytes, gfp_mask) || if (blkg_rwstat_init(&blkg->stat_bytes, gfp_mask) ||
blkg_rwstat_init(&blkg->stat_ios, gfp_mask)) blkg_rwstat_init(&blkg->stat_ios, gfp_mask))
goto err_free; goto err_free;
...@@ -244,11 +246,6 @@ static struct blkcg_gq *blkg_create(struct blkcg *blkcg, ...@@ -244,11 +246,6 @@ static struct blkcg_gq *blkg_create(struct blkcg *blkcg,
blkg_get(blkg->parent); blkg_get(blkg->parent);
} }
ret = percpu_ref_init(&blkg->refcnt, blkg_release, 0,
GFP_NOWAIT | __GFP_NOWARN);
if (ret)
goto err_cancel_ref;
/* invoke per-policy init */ /* invoke per-policy init */
for (i = 0; i < BLKCG_MAX_POLS; i++) { for (i = 0; i < BLKCG_MAX_POLS; i++) {
struct blkcg_policy *pol = blkcg_policy[i]; struct blkcg_policy *pol = blkcg_policy[i];
...@@ -281,8 +278,6 @@ static struct blkcg_gq *blkg_create(struct blkcg *blkcg, ...@@ -281,8 +278,6 @@ static struct blkcg_gq *blkg_create(struct blkcg *blkcg,
blkg_put(blkg); blkg_put(blkg);
return ERR_PTR(ret); return ERR_PTR(ret);
err_cancel_ref:
percpu_ref_exit(&blkg->refcnt);
err_put_congested: err_put_congested:
wb_congested_put(wb_congested); wb_congested_put(wb_congested);
err_put_css: err_put_css:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment