OSDN Git Service

Merge tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux
[uclinux-h8/linux.git] / block / blk-mq-sysfs.c
index aafb442..3f9c3f4 100644 (file)
 
 static void blk_mq_sysfs_release(struct kobject *kobj)
 {
+       struct blk_mq_ctxs *ctxs = container_of(kobj, struct blk_mq_ctxs, kobj);
+
+       free_percpu(ctxs->queue_ctx);
+       kfree(ctxs);
+}
+
+static void blk_mq_ctx_sysfs_release(struct kobject *kobj)
+{
+       struct blk_mq_ctx *ctx = container_of(kobj, struct blk_mq_ctx, kobj);
+
+       /* ctx->ctxs won't be released until all ctx are freed */
+       kobject_put(&ctx->ctxs->kobj);
 }
 
 static void blk_mq_hw_sysfs_release(struct kobject *kobj)
@@ -203,7 +215,7 @@ static struct kobj_type blk_mq_ktype = {
 static struct kobj_type blk_mq_ctx_ktype = {
        .sysfs_ops      = &blk_mq_sysfs_ops,
        .default_attrs  = default_ctx_attrs,
-       .release        = blk_mq_sysfs_release,
+       .release        = blk_mq_ctx_sysfs_release,
 };
 
 static struct kobj_type blk_mq_hw_ktype = {
@@ -235,7 +247,7 @@ static int blk_mq_register_hctx(struct blk_mq_hw_ctx *hctx)
        if (!hctx->nr_ctx)
                return 0;
 
-       ret = kobject_add(&hctx->kobj, &q->mq_kobj, "%u", hctx->queue_num);
+       ret = kobject_add(&hctx->kobj, q->mq_kobj, "%u", hctx->queue_num);
        if (ret)
                return ret;
 
@@ -258,8 +270,8 @@ void blk_mq_unregister_dev(struct device *dev, struct request_queue *q)
        queue_for_each_hw_ctx(q, hctx, i)
                blk_mq_unregister_hctx(hctx);
 
-       kobject_uevent(&q->mq_kobj, KOBJ_REMOVE);
-       kobject_del(&q->mq_kobj);
+       kobject_uevent(q->mq_kobj, KOBJ_REMOVE);
+       kobject_del(q->mq_kobj);
        kobject_put(&dev->kobj);
 
        q->mq_sysfs_init_done = false;
@@ -279,7 +291,7 @@ void blk_mq_sysfs_deinit(struct request_queue *q)
                ctx = per_cpu_ptr(q->queue_ctx, cpu);
                kobject_put(&ctx->kobj);
        }
-       kobject_put(&q->mq_kobj);
+       kobject_put(q->mq_kobj);
 }
 
 void blk_mq_sysfs_init(struct request_queue *q)
@@ -287,10 +299,12 @@ void blk_mq_sysfs_init(struct request_queue *q)
        struct blk_mq_ctx *ctx;
        int cpu;
 
-       kobject_init(&q->mq_kobj, &blk_mq_ktype);
+       kobject_init(q->mq_kobj, &blk_mq_ktype);
 
        for_each_possible_cpu(cpu) {
                ctx = per_cpu_ptr(q->queue_ctx, cpu);
+
+               kobject_get(q->mq_kobj);
                kobject_init(&ctx->kobj, &blk_mq_ctx_ktype);
        }
 }
@@ -303,11 +317,11 @@ int __blk_mq_register_dev(struct device *dev, struct request_queue *q)
        WARN_ON_ONCE(!q->kobj.parent);
        lockdep_assert_held(&q->sysfs_lock);
 
-       ret = kobject_add(&q->mq_kobj, kobject_get(&dev->kobj), "%s", "mq");
+       ret = kobject_add(q->mq_kobj, kobject_get(&dev->kobj), "%s", "mq");
        if (ret < 0)
                goto out;
 
-       kobject_uevent(&q->mq_kobj, KOBJ_ADD);
+       kobject_uevent(q->mq_kobj, KOBJ_ADD);
 
        queue_for_each_hw_ctx(q, hctx, i) {
                ret = blk_mq_register_hctx(hctx);
@@ -324,8 +338,8 @@ unreg:
        while (--i >= 0)
                blk_mq_unregister_hctx(q->queue_hw_ctx[i]);
 
-       kobject_uevent(&q->mq_kobj, KOBJ_REMOVE);
-       kobject_del(&q->mq_kobj);
+       kobject_uevent(q->mq_kobj, KOBJ_REMOVE);
+       kobject_del(q->mq_kobj);
        kobject_put(&dev->kobj);
        return ret;
 }
@@ -340,7 +354,6 @@ int blk_mq_register_dev(struct device *dev, struct request_queue *q)
 
        return ret;
 }
-EXPORT_SYMBOL_GPL(blk_mq_register_dev);
 
 void blk_mq_sysfs_unregister(struct request_queue *q)
 {