blk-mq: make lifetime consistent between hctx and its kobject
authorMing Lei <tom.leiming@gmail.com>
Wed, 22 Feb 2017 10:14:01 +0000 (18:14 +0800)
committerJens Axboe <axboe@fb.com>
Wed, 8 Mar 2017 16:56:12 +0000 (09:56 -0700)
This patch removes kobject_put() over hctx in __blk_mq_unregister_dev(),
and trys to keep lifetime consistent between hctx and hctx's kobject.

Now blk_mq_sysfs_register() and blk_mq_sysfs_unregister() become
totally symmetrical, and kobject's refcounter drops to zero just
when the hctx is freed.

Signed-off-by: Ming Lei <tom.leiming@gmail.com>
Tested-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Jens Axboe <axboe@fb.com>
block/blk-mq-sysfs.c
block/blk-mq.c

index 77fb238..cb19ec1 100644 (file)
@@ -17,6 +17,14 @@ static void blk_mq_sysfs_release(struct kobject *kobj)
 {
 }
 
+static void blk_mq_hw_sysfs_release(struct kobject *kobj)
+{
+       struct blk_mq_hw_ctx *hctx = container_of(kobj, struct blk_mq_hw_ctx,
+                                                 kobj);
+       kfree(hctx->ctxs);
+       kfree(hctx);
+}
+
 struct blk_mq_ctx_sysfs_entry {
        struct attribute attr;
        ssize_t (*show)(struct blk_mq_ctx *, char *);
@@ -200,7 +208,7 @@ static struct kobj_type blk_mq_ctx_ktype = {
 static struct kobj_type blk_mq_hw_ktype = {
        .sysfs_ops      = &blk_mq_hw_sysfs_ops,
        .default_attrs  = default_hw_ctx_attrs,
-       .release        = blk_mq_sysfs_release,
+       .release        = blk_mq_hw_sysfs_release,
 };
 
 static void blk_mq_unregister_hctx(struct blk_mq_hw_ctx *hctx)
@@ -244,12 +252,9 @@ static void __blk_mq_unregister_dev(struct device *dev, struct request_queue *q)
        struct blk_mq_hw_ctx *hctx;
        int i;
 
-       queue_for_each_hw_ctx(q, hctx, i) {
+       queue_for_each_hw_ctx(q, hctx, i)
                blk_mq_unregister_hctx(hctx);
 
-               kobject_put(&hctx->kobj);
-       }
-
        blk_mq_debugfs_unregister_hctxs(q);
 
        kobject_uevent(&q->mq_kobj, KOBJ_REMOVE);
index b985c23..f70595e 100644 (file)
@@ -2256,8 +2256,7 @@ void blk_mq_release(struct request_queue *q)
        queue_for_each_hw_ctx(q, hctx, i) {
                if (!hctx)
                        continue;
-               kfree(hctx->ctxs);
-               kfree(hctx);
+               kobject_put(&hctx->kobj);
        }
 
        q->mq_map = NULL;
@@ -2336,8 +2335,6 @@ static void blk_mq_realloc_hw_ctxs(struct blk_mq_tag_set *set,
                        blk_mq_exit_hctx(q, set, hctx, j);
                        free_cpumask_var(hctx->cpumask);
                        kobject_put(&hctx->kobj);
-                       kfree(hctx->ctxs);
-                       kfree(hctx);
                        hctxs[j] = NULL;
 
                }