|
@@ -327,6 +327,42 @@ static struct kobj_type blk_mq_hw_ktype = {
|
|
|
.release = blk_mq_sysfs_release,
|
|
|
};
|
|
|
|
|
|
+void blk_mq_unregister_hctx(struct blk_mq_hw_ctx *hctx)
|
|
|
+{
|
|
|
+ struct blk_mq_ctx *ctx;
|
|
|
+ int i;
|
|
|
+
|
|
|
+ if (!hctx->nr_ctx || !(hctx->flags & BLK_MQ_F_SYSFS_UP))
|
|
|
+ return;
|
|
|
+
|
|
|
+ hctx_for_each_ctx(hctx, ctx, i)
|
|
|
+ kobject_del(&ctx->kobj);
|
|
|
+
|
|
|
+ kobject_del(&hctx->kobj);
|
|
|
+}
|
|
|
+
|
|
|
+int blk_mq_register_hctx(struct blk_mq_hw_ctx *hctx)
|
|
|
+{
|
|
|
+ struct request_queue *q = hctx->queue;
|
|
|
+ struct blk_mq_ctx *ctx;
|
|
|
+ int i, ret;
|
|
|
+
|
|
|
+ if (!hctx->nr_ctx || !(hctx->flags & BLK_MQ_F_SYSFS_UP))
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ ret = kobject_add(&hctx->kobj, &q->mq_kobj, "%u", hctx->queue_num);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+
|
|
|
+ hctx_for_each_ctx(hctx, ctx, i) {
|
|
|
+ ret = kobject_add(&ctx->kobj, &hctx->kobj, "cpu%u", ctx->cpu);
|
|
|
+ if (ret)
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
void blk_mq_unregister_disk(struct gendisk *disk)
|
|
|
{
|
|
|
struct request_queue *q = disk->queue;
|
|
@@ -335,11 +371,11 @@ void blk_mq_unregister_disk(struct gendisk *disk)
|
|
|
int i, j;
|
|
|
|
|
|
queue_for_each_hw_ctx(q, hctx, i) {
|
|
|
- hctx_for_each_ctx(hctx, ctx, j) {
|
|
|
- kobject_del(&ctx->kobj);
|
|
|
+ blk_mq_unregister_hctx(hctx);
|
|
|
+
|
|
|
+ hctx_for_each_ctx(hctx, ctx, j)
|
|
|
kobject_put(&ctx->kobj);
|
|
|
- }
|
|
|
- kobject_del(&hctx->kobj);
|
|
|
+
|
|
|
kobject_put(&hctx->kobj);
|
|
|
}
|
|
|
|
|
@@ -350,15 +386,30 @@ void blk_mq_unregister_disk(struct gendisk *disk)
|
|
|
kobject_put(&disk_to_dev(disk)->kobj);
|
|
|
}
|
|
|
|
|
|
+static void blk_mq_sysfs_init(struct request_queue *q)
|
|
|
+{
|
|
|
+ struct blk_mq_hw_ctx *hctx;
|
|
|
+ struct blk_mq_ctx *ctx;
|
|
|
+ int i, j;
|
|
|
+
|
|
|
+ kobject_init(&q->mq_kobj, &blk_mq_ktype);
|
|
|
+
|
|
|
+ queue_for_each_hw_ctx(q, hctx, i) {
|
|
|
+ kobject_init(&hctx->kobj, &blk_mq_hw_ktype);
|
|
|
+
|
|
|
+ hctx_for_each_ctx(hctx, ctx, j)
|
|
|
+ kobject_init(&ctx->kobj, &blk_mq_ctx_ktype);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
int blk_mq_register_disk(struct gendisk *disk)
|
|
|
{
|
|
|
struct device *dev = disk_to_dev(disk);
|
|
|
struct request_queue *q = disk->queue;
|
|
|
struct blk_mq_hw_ctx *hctx;
|
|
|
- struct blk_mq_ctx *ctx;
|
|
|
- int ret, i, j;
|
|
|
+ int ret, i;
|
|
|
|
|
|
- kobject_init(&q->mq_kobj, &blk_mq_ktype);
|
|
|
+ blk_mq_sysfs_init(q);
|
|
|
|
|
|
ret = kobject_add(&q->mq_kobj, kobject_get(&dev->kobj), "%s", "mq");
|
|
|
if (ret < 0)
|
|
@@ -367,20 +418,10 @@ int blk_mq_register_disk(struct gendisk *disk)
|
|
|
kobject_uevent(&q->mq_kobj, KOBJ_ADD);
|
|
|
|
|
|
queue_for_each_hw_ctx(q, hctx, i) {
|
|
|
- kobject_init(&hctx->kobj, &blk_mq_hw_ktype);
|
|
|
- ret = kobject_add(&hctx->kobj, &q->mq_kobj, "%u", i);
|
|
|
+ hctx->flags |= BLK_MQ_F_SYSFS_UP;
|
|
|
+ ret = blk_mq_register_hctx(hctx);
|
|
|
if (ret)
|
|
|
break;
|
|
|
-
|
|
|
- if (!hctx->nr_ctx)
|
|
|
- continue;
|
|
|
-
|
|
|
- hctx_for_each_ctx(hctx, ctx, j) {
|
|
|
- kobject_init(&ctx->kobj, &blk_mq_ctx_ktype);
|
|
|
- ret = kobject_add(&ctx->kobj, &hctx->kobj, "cpu%u", ctx->cpu);
|
|
|
- if (ret)
|
|
|
- break;
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
if (ret) {
|
|
@@ -390,3 +431,26 @@ int blk_mq_register_disk(struct gendisk *disk)
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
+
|
|
|
+void blk_mq_sysfs_unregister(struct request_queue *q)
|
|
|
+{
|
|
|
+ struct blk_mq_hw_ctx *hctx;
|
|
|
+ int i;
|
|
|
+
|
|
|
+ queue_for_each_hw_ctx(q, hctx, i)
|
|
|
+ blk_mq_unregister_hctx(hctx);
|
|
|
+}
|
|
|
+
|
|
|
+int blk_mq_sysfs_register(struct request_queue *q)
|
|
|
+{
|
|
|
+ struct blk_mq_hw_ctx *hctx;
|
|
|
+ int i, ret = 0;
|
|
|
+
|
|
|
+ queue_for_each_hw_ctx(q, hctx, i) {
|
|
|
+ ret = blk_mq_register_hctx(hctx);
|
|
|
+ if (ret)
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|