diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c index 36cccf6005c44b98ee1a09639ee164daa3136d06..8012c7891c8caffb0656efb4de118e616fab9621 100644 --- a/block/blk-cgroup.c +++ b/block/blk-cgroup.c @@ -881,6 +881,14 @@ int blkg_conf_prep(struct blkcg *blkcg, const struct blkcg_policy *pol, q = disk->queue; + /* + * blkcg_deactivate_policy() requires queue to be frozen, we can grab + * q_usage_counter to prevent concurrent with blkcg_deactivate_policy(). + */ + ret = blk_queue_enter(q, 0); + if (ret) + goto fail; + rcu_read_lock(); spin_lock_irq(q->queue_lock); @@ -915,13 +923,13 @@ int blkg_conf_prep(struct blkcg *blkcg, const struct blkcg_policy *pol, new_blkg = blkg_alloc(pos, q, GFP_KERNEL); if (unlikely(!new_blkg)) { ret = -ENOMEM; - goto fail; + goto fail_exit_queue; } if (radix_tree_preload(GFP_KERNEL)) { blkg_free(new_blkg); ret = -ENOMEM; - goto fail; + goto fail_exit_queue; } rcu_read_lock(); @@ -950,6 +958,7 @@ int blkg_conf_prep(struct blkcg *blkcg, const struct blkcg_policy *pol, goto success; } success: + blk_queue_exit(q); ctx->disk = disk; ctx->blkg = blkg; ctx->body = input; @@ -960,6 +969,8 @@ int blkg_conf_prep(struct blkcg *blkcg, const struct blkcg_policy *pol, fail_unlock: spin_unlock_irq(q->queue_lock); rcu_read_unlock(); +fail_exit_queue: + blk_queue_exit(q); fail: put_disk_and_module(disk); /*