xref: /linux/block/blk-mq-sysfs.c (revision 676141e48af7463717896352e69c10f945ac22dd)
1320ae51fSJens Axboe #include <linux/kernel.h>
2320ae51fSJens Axboe #include <linux/module.h>
3320ae51fSJens Axboe #include <linux/backing-dev.h>
4320ae51fSJens Axboe #include <linux/bio.h>
5320ae51fSJens Axboe #include <linux/blkdev.h>
6320ae51fSJens Axboe #include <linux/mm.h>
7320ae51fSJens Axboe #include <linux/init.h>
8320ae51fSJens Axboe #include <linux/slab.h>
9320ae51fSJens Axboe #include <linux/workqueue.h>
10320ae51fSJens Axboe #include <linux/smp.h>
11320ae51fSJens Axboe 
12320ae51fSJens Axboe #include <linux/blk-mq.h>
13320ae51fSJens Axboe #include "blk-mq.h"
14320ae51fSJens Axboe #include "blk-mq-tag.h"
15320ae51fSJens Axboe 
16320ae51fSJens Axboe static void blk_mq_sysfs_release(struct kobject *kobj)
17320ae51fSJens Axboe {
18320ae51fSJens Axboe }
19320ae51fSJens Axboe 
20320ae51fSJens Axboe struct blk_mq_ctx_sysfs_entry {
21320ae51fSJens Axboe 	struct attribute attr;
22320ae51fSJens Axboe 	ssize_t (*show)(struct blk_mq_ctx *, char *);
23320ae51fSJens Axboe 	ssize_t (*store)(struct blk_mq_ctx *, const char *, size_t);
24320ae51fSJens Axboe };
25320ae51fSJens Axboe 
26320ae51fSJens Axboe struct blk_mq_hw_ctx_sysfs_entry {
27320ae51fSJens Axboe 	struct attribute attr;
28320ae51fSJens Axboe 	ssize_t (*show)(struct blk_mq_hw_ctx *, char *);
29320ae51fSJens Axboe 	ssize_t (*store)(struct blk_mq_hw_ctx *, const char *, size_t);
30320ae51fSJens Axboe };
31320ae51fSJens Axboe 
32320ae51fSJens Axboe static ssize_t blk_mq_sysfs_show(struct kobject *kobj, struct attribute *attr,
33320ae51fSJens Axboe 				 char *page)
34320ae51fSJens Axboe {
35320ae51fSJens Axboe 	struct blk_mq_ctx_sysfs_entry *entry;
36320ae51fSJens Axboe 	struct blk_mq_ctx *ctx;
37320ae51fSJens Axboe 	struct request_queue *q;
38320ae51fSJens Axboe 	ssize_t res;
39320ae51fSJens Axboe 
40320ae51fSJens Axboe 	entry = container_of(attr, struct blk_mq_ctx_sysfs_entry, attr);
41320ae51fSJens Axboe 	ctx = container_of(kobj, struct blk_mq_ctx, kobj);
42320ae51fSJens Axboe 	q = ctx->queue;
43320ae51fSJens Axboe 
44320ae51fSJens Axboe 	if (!entry->show)
45320ae51fSJens Axboe 		return -EIO;
46320ae51fSJens Axboe 
47320ae51fSJens Axboe 	res = -ENOENT;
48320ae51fSJens Axboe 	mutex_lock(&q->sysfs_lock);
49320ae51fSJens Axboe 	if (!blk_queue_dying(q))
50320ae51fSJens Axboe 		res = entry->show(ctx, page);
51320ae51fSJens Axboe 	mutex_unlock(&q->sysfs_lock);
52320ae51fSJens Axboe 	return res;
53320ae51fSJens Axboe }
54320ae51fSJens Axboe 
55320ae51fSJens Axboe static ssize_t blk_mq_sysfs_store(struct kobject *kobj, struct attribute *attr,
56320ae51fSJens Axboe 				  const char *page, size_t length)
57320ae51fSJens Axboe {
58320ae51fSJens Axboe 	struct blk_mq_ctx_sysfs_entry *entry;
59320ae51fSJens Axboe 	struct blk_mq_ctx *ctx;
60320ae51fSJens Axboe 	struct request_queue *q;
61320ae51fSJens Axboe 	ssize_t res;
62320ae51fSJens Axboe 
63320ae51fSJens Axboe 	entry = container_of(attr, struct blk_mq_ctx_sysfs_entry, attr);
64320ae51fSJens Axboe 	ctx = container_of(kobj, struct blk_mq_ctx, kobj);
65320ae51fSJens Axboe 	q = ctx->queue;
66320ae51fSJens Axboe 
67320ae51fSJens Axboe 	if (!entry->store)
68320ae51fSJens Axboe 		return -EIO;
69320ae51fSJens Axboe 
70320ae51fSJens Axboe 	res = -ENOENT;
71320ae51fSJens Axboe 	mutex_lock(&q->sysfs_lock);
72320ae51fSJens Axboe 	if (!blk_queue_dying(q))
73320ae51fSJens Axboe 		res = entry->store(ctx, page, length);
74320ae51fSJens Axboe 	mutex_unlock(&q->sysfs_lock);
75320ae51fSJens Axboe 	return res;
76320ae51fSJens Axboe }
77320ae51fSJens Axboe 
78320ae51fSJens Axboe static ssize_t blk_mq_hw_sysfs_show(struct kobject *kobj,
79320ae51fSJens Axboe 				    struct attribute *attr, char *page)
80320ae51fSJens Axboe {
81320ae51fSJens Axboe 	struct blk_mq_hw_ctx_sysfs_entry *entry;
82320ae51fSJens Axboe 	struct blk_mq_hw_ctx *hctx;
83320ae51fSJens Axboe 	struct request_queue *q;
84320ae51fSJens Axboe 	ssize_t res;
85320ae51fSJens Axboe 
86320ae51fSJens Axboe 	entry = container_of(attr, struct blk_mq_hw_ctx_sysfs_entry, attr);
87320ae51fSJens Axboe 	hctx = container_of(kobj, struct blk_mq_hw_ctx, kobj);
88320ae51fSJens Axboe 	q = hctx->queue;
89320ae51fSJens Axboe 
90320ae51fSJens Axboe 	if (!entry->show)
91320ae51fSJens Axboe 		return -EIO;
92320ae51fSJens Axboe 
93320ae51fSJens Axboe 	res = -ENOENT;
94320ae51fSJens Axboe 	mutex_lock(&q->sysfs_lock);
95320ae51fSJens Axboe 	if (!blk_queue_dying(q))
96320ae51fSJens Axboe 		res = entry->show(hctx, page);
97320ae51fSJens Axboe 	mutex_unlock(&q->sysfs_lock);
98320ae51fSJens Axboe 	return res;
99320ae51fSJens Axboe }
100320ae51fSJens Axboe 
101320ae51fSJens Axboe static ssize_t blk_mq_hw_sysfs_store(struct kobject *kobj,
102320ae51fSJens Axboe 				     struct attribute *attr, const char *page,
103320ae51fSJens Axboe 				     size_t length)
104320ae51fSJens Axboe {
105320ae51fSJens Axboe 	struct blk_mq_hw_ctx_sysfs_entry *entry;
106320ae51fSJens Axboe 	struct blk_mq_hw_ctx *hctx;
107320ae51fSJens Axboe 	struct request_queue *q;
108320ae51fSJens Axboe 	ssize_t res;
109320ae51fSJens Axboe 
110320ae51fSJens Axboe 	entry = container_of(attr, struct blk_mq_hw_ctx_sysfs_entry, attr);
111320ae51fSJens Axboe 	hctx = container_of(kobj, struct blk_mq_hw_ctx, kobj);
112320ae51fSJens Axboe 	q = hctx->queue;
113320ae51fSJens Axboe 
114320ae51fSJens Axboe 	if (!entry->store)
115320ae51fSJens Axboe 		return -EIO;
116320ae51fSJens Axboe 
117320ae51fSJens Axboe 	res = -ENOENT;
118320ae51fSJens Axboe 	mutex_lock(&q->sysfs_lock);
119320ae51fSJens Axboe 	if (!blk_queue_dying(q))
120320ae51fSJens Axboe 		res = entry->store(hctx, page, length);
121320ae51fSJens Axboe 	mutex_unlock(&q->sysfs_lock);
122320ae51fSJens Axboe 	return res;
123320ae51fSJens Axboe }
124320ae51fSJens Axboe 
125320ae51fSJens Axboe static ssize_t blk_mq_sysfs_dispatched_show(struct blk_mq_ctx *ctx, char *page)
126320ae51fSJens Axboe {
127320ae51fSJens Axboe 	return sprintf(page, "%lu %lu\n", ctx->rq_dispatched[1],
128320ae51fSJens Axboe 				ctx->rq_dispatched[0]);
129320ae51fSJens Axboe }
130320ae51fSJens Axboe 
131320ae51fSJens Axboe static ssize_t blk_mq_sysfs_merged_show(struct blk_mq_ctx *ctx, char *page)
132320ae51fSJens Axboe {
133320ae51fSJens Axboe 	return sprintf(page, "%lu\n", ctx->rq_merged);
134320ae51fSJens Axboe }
135320ae51fSJens Axboe 
136320ae51fSJens Axboe static ssize_t blk_mq_sysfs_completed_show(struct blk_mq_ctx *ctx, char *page)
137320ae51fSJens Axboe {
138320ae51fSJens Axboe 	return sprintf(page, "%lu %lu\n", ctx->rq_completed[1],
139320ae51fSJens Axboe 				ctx->rq_completed[0]);
140320ae51fSJens Axboe }
141320ae51fSJens Axboe 
142320ae51fSJens Axboe static ssize_t sysfs_list_show(char *page, struct list_head *list, char *msg)
143320ae51fSJens Axboe {
144320ae51fSJens Axboe 	char *start_page = page;
145320ae51fSJens Axboe 	struct request *rq;
146320ae51fSJens Axboe 
147320ae51fSJens Axboe 	page += sprintf(page, "%s:\n", msg);
148320ae51fSJens Axboe 
149320ae51fSJens Axboe 	list_for_each_entry(rq, list, queuelist)
150320ae51fSJens Axboe 		page += sprintf(page, "\t%p\n", rq);
151320ae51fSJens Axboe 
152320ae51fSJens Axboe 	return page - start_page;
153320ae51fSJens Axboe }
154320ae51fSJens Axboe 
155320ae51fSJens Axboe static ssize_t blk_mq_sysfs_rq_list_show(struct blk_mq_ctx *ctx, char *page)
156320ae51fSJens Axboe {
157320ae51fSJens Axboe 	ssize_t ret;
158320ae51fSJens Axboe 
159320ae51fSJens Axboe 	spin_lock(&ctx->lock);
160320ae51fSJens Axboe 	ret = sysfs_list_show(page, &ctx->rq_list, "CTX pending");
161320ae51fSJens Axboe 	spin_unlock(&ctx->lock);
162320ae51fSJens Axboe 
163320ae51fSJens Axboe 	return ret;
164320ae51fSJens Axboe }
165320ae51fSJens Axboe 
166320ae51fSJens Axboe static ssize_t blk_mq_hw_sysfs_queued_show(struct blk_mq_hw_ctx *hctx,
167320ae51fSJens Axboe 					   char *page)
168320ae51fSJens Axboe {
169320ae51fSJens Axboe 	return sprintf(page, "%lu\n", hctx->queued);
170320ae51fSJens Axboe }
171320ae51fSJens Axboe 
172320ae51fSJens Axboe static ssize_t blk_mq_hw_sysfs_run_show(struct blk_mq_hw_ctx *hctx, char *page)
173320ae51fSJens Axboe {
174320ae51fSJens Axboe 	return sprintf(page, "%lu\n", hctx->run);
175320ae51fSJens Axboe }
176320ae51fSJens Axboe 
177320ae51fSJens Axboe static ssize_t blk_mq_hw_sysfs_dispatched_show(struct blk_mq_hw_ctx *hctx,
178320ae51fSJens Axboe 					       char *page)
179320ae51fSJens Axboe {
180320ae51fSJens Axboe 	char *start_page = page;
181320ae51fSJens Axboe 	int i;
182320ae51fSJens Axboe 
183320ae51fSJens Axboe 	page += sprintf(page, "%8u\t%lu\n", 0U, hctx->dispatched[0]);
184320ae51fSJens Axboe 
185320ae51fSJens Axboe 	for (i = 1; i < BLK_MQ_MAX_DISPATCH_ORDER; i++) {
186320ae51fSJens Axboe 		unsigned long d = 1U << (i - 1);
187320ae51fSJens Axboe 
188320ae51fSJens Axboe 		page += sprintf(page, "%8lu\t%lu\n", d, hctx->dispatched[i]);
189320ae51fSJens Axboe 	}
190320ae51fSJens Axboe 
191320ae51fSJens Axboe 	return page - start_page;
192320ae51fSJens Axboe }
193320ae51fSJens Axboe 
194320ae51fSJens Axboe static ssize_t blk_mq_hw_sysfs_rq_list_show(struct blk_mq_hw_ctx *hctx,
195320ae51fSJens Axboe 					    char *page)
196320ae51fSJens Axboe {
197320ae51fSJens Axboe 	ssize_t ret;
198320ae51fSJens Axboe 
199320ae51fSJens Axboe 	spin_lock(&hctx->lock);
200320ae51fSJens Axboe 	ret = sysfs_list_show(page, &hctx->dispatch, "HCTX pending");
201320ae51fSJens Axboe 	spin_unlock(&hctx->lock);
202320ae51fSJens Axboe 
203320ae51fSJens Axboe 	return ret;
204320ae51fSJens Axboe }
205320ae51fSJens Axboe 
206320ae51fSJens Axboe static ssize_t blk_mq_hw_sysfs_ipi_show(struct blk_mq_hw_ctx *hctx, char *page)
207320ae51fSJens Axboe {
208320ae51fSJens Axboe 	ssize_t ret;
209320ae51fSJens Axboe 
210320ae51fSJens Axboe 	spin_lock(&hctx->lock);
211320ae51fSJens Axboe 	ret = sprintf(page, "%u\n", !!(hctx->flags & BLK_MQ_F_SHOULD_IPI));
212320ae51fSJens Axboe 	spin_unlock(&hctx->lock);
213320ae51fSJens Axboe 
214320ae51fSJens Axboe 	return ret;
215320ae51fSJens Axboe }
216320ae51fSJens Axboe 
217320ae51fSJens Axboe static ssize_t blk_mq_hw_sysfs_ipi_store(struct blk_mq_hw_ctx *hctx,
218320ae51fSJens Axboe 					 const char *page, size_t len)
219320ae51fSJens Axboe {
220320ae51fSJens Axboe 	struct blk_mq_ctx *ctx;
221320ae51fSJens Axboe 	unsigned long ret;
222320ae51fSJens Axboe 	unsigned int i;
223320ae51fSJens Axboe 
224320ae51fSJens Axboe 	if (kstrtoul(page, 10, &ret)) {
225320ae51fSJens Axboe 		pr_err("blk-mq-sysfs: invalid input '%s'\n", page);
226320ae51fSJens Axboe 		return -EINVAL;
227320ae51fSJens Axboe 	}
228320ae51fSJens Axboe 
229320ae51fSJens Axboe 	spin_lock(&hctx->lock);
230320ae51fSJens Axboe 	if (ret)
231320ae51fSJens Axboe 		hctx->flags |= BLK_MQ_F_SHOULD_IPI;
232320ae51fSJens Axboe 	else
233320ae51fSJens Axboe 		hctx->flags &= ~BLK_MQ_F_SHOULD_IPI;
234320ae51fSJens Axboe 	spin_unlock(&hctx->lock);
235320ae51fSJens Axboe 
236320ae51fSJens Axboe 	hctx_for_each_ctx(hctx, ctx, i)
237320ae51fSJens Axboe 		ctx->ipi_redirect = !!ret;
238320ae51fSJens Axboe 
239320ae51fSJens Axboe 	return len;
240320ae51fSJens Axboe }
241320ae51fSJens Axboe 
242320ae51fSJens Axboe static ssize_t blk_mq_hw_sysfs_tags_show(struct blk_mq_hw_ctx *hctx, char *page)
243320ae51fSJens Axboe {
244320ae51fSJens Axboe 	return blk_mq_tag_sysfs_show(hctx->tags, page);
245320ae51fSJens Axboe }
246320ae51fSJens Axboe 
247*676141e4SJens Axboe static ssize_t blk_mq_hw_sysfs_cpus_show(struct blk_mq_hw_ctx *hctx, char *page)
248*676141e4SJens Axboe {
249*676141e4SJens Axboe 	unsigned int i, queue_num, first = 1;
250*676141e4SJens Axboe 	ssize_t ret = 0;
251*676141e4SJens Axboe 
252*676141e4SJens Axboe 	blk_mq_disable_hotplug();
253*676141e4SJens Axboe 
254*676141e4SJens Axboe 	for_each_online_cpu(i) {
255*676141e4SJens Axboe 		queue_num = hctx->queue->mq_map[i];
256*676141e4SJens Axboe 		if (queue_num != hctx->queue_num)
257*676141e4SJens Axboe 			continue;
258*676141e4SJens Axboe 
259*676141e4SJens Axboe 		if (first)
260*676141e4SJens Axboe 			ret += sprintf(ret + page, "%u", i);
261*676141e4SJens Axboe 		else
262*676141e4SJens Axboe 			ret += sprintf(ret + page, ", %u", i);
263*676141e4SJens Axboe 
264*676141e4SJens Axboe 		first = 0;
265*676141e4SJens Axboe 	}
266*676141e4SJens Axboe 
267*676141e4SJens Axboe 	blk_mq_enable_hotplug();
268*676141e4SJens Axboe 
269*676141e4SJens Axboe 	ret += sprintf(ret + page, "\n");
270*676141e4SJens Axboe 	return ret;
271*676141e4SJens Axboe }
272*676141e4SJens Axboe 
273320ae51fSJens Axboe static struct blk_mq_ctx_sysfs_entry blk_mq_sysfs_dispatched = {
274320ae51fSJens Axboe 	.attr = {.name = "dispatched", .mode = S_IRUGO },
275320ae51fSJens Axboe 	.show = blk_mq_sysfs_dispatched_show,
276320ae51fSJens Axboe };
277320ae51fSJens Axboe static struct blk_mq_ctx_sysfs_entry blk_mq_sysfs_merged = {
278320ae51fSJens Axboe 	.attr = {.name = "merged", .mode = S_IRUGO },
279320ae51fSJens Axboe 	.show = blk_mq_sysfs_merged_show,
280320ae51fSJens Axboe };
281320ae51fSJens Axboe static struct blk_mq_ctx_sysfs_entry blk_mq_sysfs_completed = {
282320ae51fSJens Axboe 	.attr = {.name = "completed", .mode = S_IRUGO },
283320ae51fSJens Axboe 	.show = blk_mq_sysfs_completed_show,
284320ae51fSJens Axboe };
285320ae51fSJens Axboe static struct blk_mq_ctx_sysfs_entry blk_mq_sysfs_rq_list = {
286320ae51fSJens Axboe 	.attr = {.name = "rq_list", .mode = S_IRUGO },
287320ae51fSJens Axboe 	.show = blk_mq_sysfs_rq_list_show,
288320ae51fSJens Axboe };
289320ae51fSJens Axboe 
290320ae51fSJens Axboe static struct attribute *default_ctx_attrs[] = {
291320ae51fSJens Axboe 	&blk_mq_sysfs_dispatched.attr,
292320ae51fSJens Axboe 	&blk_mq_sysfs_merged.attr,
293320ae51fSJens Axboe 	&blk_mq_sysfs_completed.attr,
294320ae51fSJens Axboe 	&blk_mq_sysfs_rq_list.attr,
295320ae51fSJens Axboe 	NULL,
296320ae51fSJens Axboe };
297320ae51fSJens Axboe 
298320ae51fSJens Axboe static struct blk_mq_hw_ctx_sysfs_entry blk_mq_hw_sysfs_queued = {
299320ae51fSJens Axboe 	.attr = {.name = "queued", .mode = S_IRUGO },
300320ae51fSJens Axboe 	.show = blk_mq_hw_sysfs_queued_show,
301320ae51fSJens Axboe };
302320ae51fSJens Axboe static struct blk_mq_hw_ctx_sysfs_entry blk_mq_hw_sysfs_run = {
303320ae51fSJens Axboe 	.attr = {.name = "run", .mode = S_IRUGO },
304320ae51fSJens Axboe 	.show = blk_mq_hw_sysfs_run_show,
305320ae51fSJens Axboe };
306320ae51fSJens Axboe static struct blk_mq_hw_ctx_sysfs_entry blk_mq_hw_sysfs_dispatched = {
307320ae51fSJens Axboe 	.attr = {.name = "dispatched", .mode = S_IRUGO },
308320ae51fSJens Axboe 	.show = blk_mq_hw_sysfs_dispatched_show,
309320ae51fSJens Axboe };
310320ae51fSJens Axboe static struct blk_mq_hw_ctx_sysfs_entry blk_mq_hw_sysfs_pending = {
311320ae51fSJens Axboe 	.attr = {.name = "pending", .mode = S_IRUGO },
312320ae51fSJens Axboe 	.show = blk_mq_hw_sysfs_rq_list_show,
313320ae51fSJens Axboe };
314320ae51fSJens Axboe static struct blk_mq_hw_ctx_sysfs_entry blk_mq_hw_sysfs_ipi = {
315320ae51fSJens Axboe 	.attr = {.name = "ipi_redirect", .mode = S_IRUGO | S_IWUSR},
316320ae51fSJens Axboe 	.show = blk_mq_hw_sysfs_ipi_show,
317320ae51fSJens Axboe 	.store = blk_mq_hw_sysfs_ipi_store,
318320ae51fSJens Axboe };
319320ae51fSJens Axboe static struct blk_mq_hw_ctx_sysfs_entry blk_mq_hw_sysfs_tags = {
320320ae51fSJens Axboe 	.attr = {.name = "tags", .mode = S_IRUGO },
321320ae51fSJens Axboe 	.show = blk_mq_hw_sysfs_tags_show,
322320ae51fSJens Axboe };
323*676141e4SJens Axboe static struct blk_mq_hw_ctx_sysfs_entry blk_mq_hw_sysfs_cpus = {
324*676141e4SJens Axboe 	.attr = {.name = "cpu_list", .mode = S_IRUGO },
325*676141e4SJens Axboe 	.show = blk_mq_hw_sysfs_cpus_show,
326*676141e4SJens Axboe };
327320ae51fSJens Axboe 
328320ae51fSJens Axboe static struct attribute *default_hw_ctx_attrs[] = {
329320ae51fSJens Axboe 	&blk_mq_hw_sysfs_queued.attr,
330320ae51fSJens Axboe 	&blk_mq_hw_sysfs_run.attr,
331320ae51fSJens Axboe 	&blk_mq_hw_sysfs_dispatched.attr,
332320ae51fSJens Axboe 	&blk_mq_hw_sysfs_pending.attr,
333320ae51fSJens Axboe 	&blk_mq_hw_sysfs_ipi.attr,
334320ae51fSJens Axboe 	&blk_mq_hw_sysfs_tags.attr,
335*676141e4SJens Axboe 	&blk_mq_hw_sysfs_cpus.attr,
336320ae51fSJens Axboe 	NULL,
337320ae51fSJens Axboe };
338320ae51fSJens Axboe 
339320ae51fSJens Axboe static const struct sysfs_ops blk_mq_sysfs_ops = {
340320ae51fSJens Axboe 	.show	= blk_mq_sysfs_show,
341320ae51fSJens Axboe 	.store	= blk_mq_sysfs_store,
342320ae51fSJens Axboe };
343320ae51fSJens Axboe 
344320ae51fSJens Axboe static const struct sysfs_ops blk_mq_hw_sysfs_ops = {
345320ae51fSJens Axboe 	.show	= blk_mq_hw_sysfs_show,
346320ae51fSJens Axboe 	.store	= blk_mq_hw_sysfs_store,
347320ae51fSJens Axboe };
348320ae51fSJens Axboe 
349320ae51fSJens Axboe static struct kobj_type blk_mq_ktype = {
350320ae51fSJens Axboe 	.sysfs_ops	= &blk_mq_sysfs_ops,
351320ae51fSJens Axboe 	.release	= blk_mq_sysfs_release,
352320ae51fSJens Axboe };
353320ae51fSJens Axboe 
354320ae51fSJens Axboe static struct kobj_type blk_mq_ctx_ktype = {
355320ae51fSJens Axboe 	.sysfs_ops	= &blk_mq_sysfs_ops,
356320ae51fSJens Axboe 	.default_attrs	= default_ctx_attrs,
357320ae51fSJens Axboe 	.release	= blk_mq_sysfs_release,
358320ae51fSJens Axboe };
359320ae51fSJens Axboe 
360320ae51fSJens Axboe static struct kobj_type blk_mq_hw_ktype = {
361320ae51fSJens Axboe 	.sysfs_ops	= &blk_mq_hw_sysfs_ops,
362320ae51fSJens Axboe 	.default_attrs	= default_hw_ctx_attrs,
363320ae51fSJens Axboe 	.release	= blk_mq_sysfs_release,
364320ae51fSJens Axboe };
365320ae51fSJens Axboe 
366320ae51fSJens Axboe void blk_mq_unregister_disk(struct gendisk *disk)
367320ae51fSJens Axboe {
368320ae51fSJens Axboe 	struct request_queue *q = disk->queue;
36985157366SAndrey Vagin 	struct blk_mq_hw_ctx *hctx;
37085157366SAndrey Vagin 	struct blk_mq_ctx *ctx;
37185157366SAndrey Vagin 	int i, j;
37285157366SAndrey Vagin 
37385157366SAndrey Vagin 	queue_for_each_hw_ctx(q, hctx, i) {
37485157366SAndrey Vagin 		hctx_for_each_ctx(hctx, ctx, j) {
37585157366SAndrey Vagin 			kobject_del(&ctx->kobj);
37685157366SAndrey Vagin 			kobject_put(&ctx->kobj);
37785157366SAndrey Vagin 		}
37885157366SAndrey Vagin 		kobject_del(&hctx->kobj);
37985157366SAndrey Vagin 		kobject_put(&hctx->kobj);
38085157366SAndrey Vagin 	}
381320ae51fSJens Axboe 
382320ae51fSJens Axboe 	kobject_uevent(&q->mq_kobj, KOBJ_REMOVE);
383320ae51fSJens Axboe 	kobject_del(&q->mq_kobj);
38485157366SAndrey Vagin 	kobject_put(&q->mq_kobj);
385320ae51fSJens Axboe 
386320ae51fSJens Axboe 	kobject_put(&disk_to_dev(disk)->kobj);
387320ae51fSJens Axboe }
388320ae51fSJens Axboe 
389320ae51fSJens Axboe int blk_mq_register_disk(struct gendisk *disk)
390320ae51fSJens Axboe {
391320ae51fSJens Axboe 	struct device *dev = disk_to_dev(disk);
392320ae51fSJens Axboe 	struct request_queue *q = disk->queue;
393320ae51fSJens Axboe 	struct blk_mq_hw_ctx *hctx;
394320ae51fSJens Axboe 	struct blk_mq_ctx *ctx;
395320ae51fSJens Axboe 	int ret, i, j;
396320ae51fSJens Axboe 
397320ae51fSJens Axboe 	kobject_init(&q->mq_kobj, &blk_mq_ktype);
398320ae51fSJens Axboe 
399320ae51fSJens Axboe 	ret = kobject_add(&q->mq_kobj, kobject_get(&dev->kobj), "%s", "mq");
400320ae51fSJens Axboe 	if (ret < 0)
401320ae51fSJens Axboe 		return ret;
402320ae51fSJens Axboe 
403320ae51fSJens Axboe 	kobject_uevent(&q->mq_kobj, KOBJ_ADD);
404320ae51fSJens Axboe 
405320ae51fSJens Axboe 	queue_for_each_hw_ctx(q, hctx, i) {
406320ae51fSJens Axboe 		kobject_init(&hctx->kobj, &blk_mq_hw_ktype);
407320ae51fSJens Axboe 		ret = kobject_add(&hctx->kobj, &q->mq_kobj, "%u", i);
408320ae51fSJens Axboe 		if (ret)
409320ae51fSJens Axboe 			break;
410320ae51fSJens Axboe 
411320ae51fSJens Axboe 		if (!hctx->nr_ctx)
412320ae51fSJens Axboe 			continue;
413320ae51fSJens Axboe 
414320ae51fSJens Axboe 		hctx_for_each_ctx(hctx, ctx, j) {
415320ae51fSJens Axboe 			kobject_init(&ctx->kobj, &blk_mq_ctx_ktype);
416320ae51fSJens Axboe 			ret = kobject_add(&ctx->kobj, &hctx->kobj, "cpu%u", ctx->cpu);
417320ae51fSJens Axboe 			if (ret)
418320ae51fSJens Axboe 				break;
419320ae51fSJens Axboe 		}
420320ae51fSJens Axboe 	}
421320ae51fSJens Axboe 
422320ae51fSJens Axboe 	if (ret) {
423320ae51fSJens Axboe 		blk_mq_unregister_disk(disk);
424320ae51fSJens Axboe 		return ret;
425320ae51fSJens Axboe 	}
426320ae51fSJens Axboe 
427320ae51fSJens Axboe 	return 0;
428320ae51fSJens Axboe }
429