mirror of
https://github.com/torvalds/linux.git
synced 2024-12-31 23:31:29 +00:00
blkcg: invoke blkcg_policy->pd_init() after parent is linked
Currently, when creating a new blkcg_gq, each policy's pd_init_fn() is invoked in blkg_alloc() before the parent is linked. This makes it difficult for policies to perform initializations which are dependent on the parent. This patch moves pd_init_fn() invocations to blkg_create() after the parent blkg is linked where the new blkg is fully initialized. As this means that blkg_free() can't assume that pd's are initialized, pd_exit_fn() invocations are moved to __blkg_release(). This guarantees that pd_exit_fn() is also invoked with fully initialized blkgs with valid parent pointers. This will help implementing hierarchy support in blk-throttle. Signed-off-by: Tejun Heo <tj@kernel.org> Acked-by: Vivek Goyal <vgoyal@redhat.com>
This commit is contained in:
parent
aa539cb38f
commit
db61367038
@ -51,18 +51,8 @@ static void blkg_free(struct blkcg_gq *blkg)
|
||||
if (!blkg)
|
||||
return;
|
||||
|
||||
for (i = 0; i < BLKCG_MAX_POLS; i++) {
|
||||
struct blkcg_policy *pol = blkcg_policy[i];
|
||||
struct blkg_policy_data *pd = blkg->pd[i];
|
||||
|
||||
if (!pd)
|
||||
continue;
|
||||
|
||||
if (pol && pol->pd_exit_fn)
|
||||
pol->pd_exit_fn(blkg);
|
||||
|
||||
kfree(pd);
|
||||
}
|
||||
for (i = 0; i < BLKCG_MAX_POLS; i++)
|
||||
kfree(blkg->pd[i]);
|
||||
|
||||
blk_exit_rl(&blkg->rl);
|
||||
kfree(blkg);
|
||||
@ -114,10 +104,6 @@ static struct blkcg_gq *blkg_alloc(struct blkcg *blkcg, struct request_queue *q,
|
||||
blkg->pd[i] = pd;
|
||||
pd->blkg = blkg;
|
||||
pd->plid = i;
|
||||
|
||||
/* invoke per-policy init */
|
||||
if (pol->pd_init_fn)
|
||||
pol->pd_init_fn(blkg);
|
||||
}
|
||||
|
||||
return blkg;
|
||||
@ -214,7 +200,7 @@ static struct blkcg_gq *blkg_create(struct blkcg *blkcg,
|
||||
}
|
||||
blkg = new_blkg;
|
||||
|
||||
/* link parent and insert */
|
||||
/* link parent */
|
||||
if (blkcg_parent(blkcg)) {
|
||||
blkg->parent = __blkg_lookup(blkcg_parent(blkcg), q, false);
|
||||
if (WARN_ON_ONCE(!blkg->parent)) {
|
||||
@ -224,6 +210,15 @@ static struct blkcg_gq *blkg_create(struct blkcg *blkcg,
|
||||
blkg_get(blkg->parent);
|
||||
}
|
||||
|
||||
/* invoke per-policy init */
|
||||
for (i = 0; i < BLKCG_MAX_POLS; i++) {
|
||||
struct blkcg_policy *pol = blkcg_policy[i];
|
||||
|
||||
if (blkg->pd[i] && pol->pd_init_fn)
|
||||
pol->pd_init_fn(blkg);
|
||||
}
|
||||
|
||||
/* insert */
|
||||
spin_lock(&blkcg->lock);
|
||||
ret = radix_tree_insert(&blkcg->blkg_tree, q->id, blkg);
|
||||
if (likely(!ret)) {
|
||||
@ -381,6 +376,16 @@ static void blkg_rcu_free(struct rcu_head *rcu_head)
|
||||
|
||||
void __blkg_release(struct blkcg_gq *blkg)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* tell policies that this one is being freed */
|
||||
for (i = 0; i < BLKCG_MAX_POLS; i++) {
|
||||
struct blkcg_policy *pol = blkcg_policy[i];
|
||||
|
||||
if (blkg->pd[i] && pol->pd_exit_fn)
|
||||
pol->pd_exit_fn(blkg);
|
||||
}
|
||||
|
||||
/* release the blkcg and parent blkg refs this blkg has been holding */
|
||||
css_put(&blkg->blkcg->css);
|
||||
if (blkg->parent)
|
||||
|
Loading…
Reference in New Issue
Block a user