Blame view

block/blk-mq-sysfs.c 8.07 KB
320ae51fe   Jens Axboe   blk-mq: new multi...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/backing-dev.h>
  #include <linux/bio.h>
  #include <linux/blkdev.h>
  #include <linux/mm.h>
  #include <linux/init.h>
  #include <linux/slab.h>
  #include <linux/workqueue.h>
  #include <linux/smp.h>
  
  #include <linux/blk-mq.h>
  #include "blk-mq.h"
  #include "blk-mq-tag.h"
  
  static void blk_mq_sysfs_release(struct kobject *kobj)
  {
  }
6c8b232ef   Ming Lei   blk-mq: make life...
19
20
21
22
  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);
01388df37   Ming Lei   blk-mq: free hctx...
23
  	free_cpumask_var(hctx->cpumask);
6c8b232ef   Ming Lei   blk-mq: make life...
24
25
26
  	kfree(hctx->ctxs);
  	kfree(hctx);
  }
320ae51fe   Jens Axboe   blk-mq: new multi...
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
  struct blk_mq_ctx_sysfs_entry {
  	struct attribute attr;
  	ssize_t (*show)(struct blk_mq_ctx *, char *);
  	ssize_t (*store)(struct blk_mq_ctx *, const char *, size_t);
  };
  
  struct blk_mq_hw_ctx_sysfs_entry {
  	struct attribute attr;
  	ssize_t (*show)(struct blk_mq_hw_ctx *, char *);
  	ssize_t (*store)(struct blk_mq_hw_ctx *, const char *, size_t);
  };
  
  static ssize_t blk_mq_sysfs_show(struct kobject *kobj, struct attribute *attr,
  				 char *page)
  {
  	struct blk_mq_ctx_sysfs_entry *entry;
  	struct blk_mq_ctx *ctx;
  	struct request_queue *q;
  	ssize_t res;
  
  	entry = container_of(attr, struct blk_mq_ctx_sysfs_entry, attr);
  	ctx = container_of(kobj, struct blk_mq_ctx, kobj);
  	q = ctx->queue;
  
  	if (!entry->show)
  		return -EIO;
  
  	res = -ENOENT;
  	mutex_lock(&q->sysfs_lock);
  	if (!blk_queue_dying(q))
  		res = entry->show(ctx, page);
  	mutex_unlock(&q->sysfs_lock);
  	return res;
  }
  
  static ssize_t blk_mq_sysfs_store(struct kobject *kobj, struct attribute *attr,
  				  const char *page, size_t length)
  {
  	struct blk_mq_ctx_sysfs_entry *entry;
  	struct blk_mq_ctx *ctx;
  	struct request_queue *q;
  	ssize_t res;
  
  	entry = container_of(attr, struct blk_mq_ctx_sysfs_entry, attr);
  	ctx = container_of(kobj, struct blk_mq_ctx, kobj);
  	q = ctx->queue;
  
  	if (!entry->store)
  		return -EIO;
  
  	res = -ENOENT;
  	mutex_lock(&q->sysfs_lock);
  	if (!blk_queue_dying(q))
  		res = entry->store(ctx, page, length);
  	mutex_unlock(&q->sysfs_lock);
  	return res;
  }
  
  static ssize_t blk_mq_hw_sysfs_show(struct kobject *kobj,
  				    struct attribute *attr, char *page)
  {
  	struct blk_mq_hw_ctx_sysfs_entry *entry;
  	struct blk_mq_hw_ctx *hctx;
  	struct request_queue *q;
  	ssize_t res;
  
  	entry = container_of(attr, struct blk_mq_hw_ctx_sysfs_entry, attr);
  	hctx = container_of(kobj, struct blk_mq_hw_ctx, kobj);
  	q = hctx->queue;
  
  	if (!entry->show)
  		return -EIO;
  
  	res = -ENOENT;
  	mutex_lock(&q->sysfs_lock);
  	if (!blk_queue_dying(q))
  		res = entry->show(hctx, page);
  	mutex_unlock(&q->sysfs_lock);
  	return res;
  }
  
  static ssize_t blk_mq_hw_sysfs_store(struct kobject *kobj,
  				     struct attribute *attr, const char *page,
  				     size_t length)
  {
  	struct blk_mq_hw_ctx_sysfs_entry *entry;
  	struct blk_mq_hw_ctx *hctx;
  	struct request_queue *q;
  	ssize_t res;
  
  	entry = container_of(attr, struct blk_mq_hw_ctx_sysfs_entry, attr);
  	hctx = container_of(kobj, struct blk_mq_hw_ctx, kobj);
  	q = hctx->queue;
  
  	if (!entry->store)
  		return -EIO;
  
  	res = -ENOENT;
  	mutex_lock(&q->sysfs_lock);
  	if (!blk_queue_dying(q))
  		res = entry->store(hctx, page, length);
  	mutex_unlock(&q->sysfs_lock);
  	return res;
  }
d96b37c0a   Omar Sandoval   blk-mq: move tags...
131
132
  static ssize_t blk_mq_hw_sysfs_nr_tags_show(struct blk_mq_hw_ctx *hctx,
  					    char *page)
bd166ef18   Jens Axboe   blk-mq-sched: add...
133
  {
d96b37c0a   Omar Sandoval   blk-mq: move tags...
134
135
  	return sprintf(page, "%u
  ", hctx->tags->nr_tags);
bd166ef18   Jens Axboe   blk-mq-sched: add...
136
  }
d96b37c0a   Omar Sandoval   blk-mq: move tags...
137
138
  static ssize_t blk_mq_hw_sysfs_nr_reserved_tags_show(struct blk_mq_hw_ctx *hctx,
  						     char *page)
320ae51fe   Jens Axboe   blk-mq: new multi...
139
  {
d96b37c0a   Omar Sandoval   blk-mq: move tags...
140
141
  	return sprintf(page, "%u
  ", hctx->tags->nr_reserved_tags);
320ae51fe   Jens Axboe   blk-mq: new multi...
142
  }
676141e48   Jens Axboe   blk-mq: don't dum...
143
144
  static ssize_t blk_mq_hw_sysfs_cpus_show(struct blk_mq_hw_ctx *hctx, char *page)
  {
cb2da43e3   Jens Axboe   blk-mq: simplify ...
145
  	unsigned int i, first = 1;
676141e48   Jens Axboe   blk-mq: don't dum...
146
  	ssize_t ret = 0;
cb2da43e3   Jens Axboe   blk-mq: simplify ...
147
  	for_each_cpu(i, hctx->cpumask) {
676141e48   Jens Axboe   blk-mq: don't dum...
148
149
150
151
152
153
154
  		if (first)
  			ret += sprintf(ret + page, "%u", i);
  		else
  			ret += sprintf(ret + page, ", %u", i);
  
  		first = 0;
  	}
676141e48   Jens Axboe   blk-mq: don't dum...
155
156
157
158
  	ret += sprintf(ret + page, "
  ");
  	return ret;
  }
320ae51fe   Jens Axboe   blk-mq: new multi...
159
  static struct attribute *default_ctx_attrs[] = {
320ae51fe   Jens Axboe   blk-mq: new multi...
160
161
  	NULL,
  };
d96b37c0a   Omar Sandoval   blk-mq: move tags...
162
163
164
165
166
167
168
169
  static struct blk_mq_hw_ctx_sysfs_entry blk_mq_hw_sysfs_nr_tags = {
  	.attr = {.name = "nr_tags", .mode = S_IRUGO },
  	.show = blk_mq_hw_sysfs_nr_tags_show,
  };
  static struct blk_mq_hw_ctx_sysfs_entry blk_mq_hw_sysfs_nr_reserved_tags = {
  	.attr = {.name = "nr_reserved_tags", .mode = S_IRUGO },
  	.show = blk_mq_hw_sysfs_nr_reserved_tags_show,
  };
676141e48   Jens Axboe   blk-mq: don't dum...
170
171
172
173
  static struct blk_mq_hw_ctx_sysfs_entry blk_mq_hw_sysfs_cpus = {
  	.attr = {.name = "cpu_list", .mode = S_IRUGO },
  	.show = blk_mq_hw_sysfs_cpus_show,
  };
320ae51fe   Jens Axboe   blk-mq: new multi...
174
175
  
  static struct attribute *default_hw_ctx_attrs[] = {
d96b37c0a   Omar Sandoval   blk-mq: move tags...
176
177
  	&blk_mq_hw_sysfs_nr_tags.attr,
  	&blk_mq_hw_sysfs_nr_reserved_tags.attr,
676141e48   Jens Axboe   blk-mq: don't dum...
178
  	&blk_mq_hw_sysfs_cpus.attr,
320ae51fe   Jens Axboe   blk-mq: new multi...
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
  	NULL,
  };
  
  static const struct sysfs_ops blk_mq_sysfs_ops = {
  	.show	= blk_mq_sysfs_show,
  	.store	= blk_mq_sysfs_store,
  };
  
  static const struct sysfs_ops blk_mq_hw_sysfs_ops = {
  	.show	= blk_mq_hw_sysfs_show,
  	.store	= blk_mq_hw_sysfs_store,
  };
  
  static struct kobj_type blk_mq_ktype = {
  	.sysfs_ops	= &blk_mq_sysfs_ops,
  	.release	= blk_mq_sysfs_release,
  };
  
  static struct kobj_type blk_mq_ctx_ktype = {
  	.sysfs_ops	= &blk_mq_sysfs_ops,
  	.default_attrs	= default_ctx_attrs,
74170118b   Ming Lei   Revert "blk-mq: f...
200
  	.release	= blk_mq_sysfs_release,
320ae51fe   Jens Axboe   blk-mq: new multi...
201
202
203
204
205
  };
  
  static struct kobj_type blk_mq_hw_ktype = {
  	.sysfs_ops	= &blk_mq_hw_sysfs_ops,
  	.default_attrs	= default_hw_ctx_attrs,
6c8b232ef   Ming Lei   blk-mq: make life...
206
  	.release	= blk_mq_hw_sysfs_release,
320ae51fe   Jens Axboe   blk-mq: new multi...
207
  };
ee3c5db08   Fengguang Wu   blk-mq: blk_mq_un...
208
  static void blk_mq_unregister_hctx(struct blk_mq_hw_ctx *hctx)
67aec14ce   Jens Axboe   blk-mq: make the ...
209
210
211
  {
  	struct blk_mq_ctx *ctx;
  	int i;
4593fdbe7   Akinobu Mita   blk-mq: fix sysfs...
212
  	if (!hctx->nr_ctx)
67aec14ce   Jens Axboe   blk-mq: make the ...
213
214
215
216
217
218
219
  		return;
  
  	hctx_for_each_ctx(hctx, ctx, i)
  		kobject_del(&ctx->kobj);
  
  	kobject_del(&hctx->kobj);
  }
ee3c5db08   Fengguang Wu   blk-mq: blk_mq_un...
220
  static int blk_mq_register_hctx(struct blk_mq_hw_ctx *hctx)
67aec14ce   Jens Axboe   blk-mq: make the ...
221
222
223
224
  {
  	struct request_queue *q = hctx->queue;
  	struct blk_mq_ctx *ctx;
  	int i, ret;
4593fdbe7   Akinobu Mita   blk-mq: fix sysfs...
225
  	if (!hctx->nr_ctx)
67aec14ce   Jens Axboe   blk-mq: make the ...
226
227
228
229
230
231
232
233
234
235
236
237
238
239
  		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;
  }
f00fb650d   Mike Snitzer   block: properly p...
240
  void blk_mq_unregister_dev(struct device *dev, struct request_queue *q)
320ae51fe   Jens Axboe   blk-mq: new multi...
241
  {
851573660   Andrey Vagin   block: fix memory...
242
  	struct blk_mq_hw_ctx *hctx;
7ea5fe31c   Ming Lei   blk-mq: make life...
243
  	int i;
851573660   Andrey Vagin   block: fix memory...
244

2d0364c8c   Bart Van Assche   blk-mq: Register ...
245
  	lockdep_assert_held(&q->sysfs_lock);
6c8b232ef   Ming Lei   blk-mq: make life...
246
  	queue_for_each_hw_ctx(q, hctx, i)
67aec14ce   Jens Axboe   blk-mq: make the ...
247
  		blk_mq_unregister_hctx(hctx);
320ae51fe   Jens Axboe   blk-mq: new multi...
248
249
  	kobject_uevent(&q->mq_kobj, KOBJ_REMOVE);
  	kobject_del(&q->mq_kobj);
b21d5b301   Matias Bjørling   blk-mq: register ...
250
  	kobject_put(&dev->kobj);
4593fdbe7   Akinobu Mita   blk-mq: fix sysfs...
251
252
  
  	q->mq_sysfs_init_done = false;
c0f3fd2b3   Jens Axboe   blk-mq: fix deadl...
253
  }
868f2f0b7   Keith Busch   blk-mq: dynamic h...
254
255
256
257
  void blk_mq_hctx_kobj_init(struct blk_mq_hw_ctx *hctx)
  {
  	kobject_init(&hctx->kobj, &blk_mq_hw_ktype);
  }
7ea5fe31c   Ming Lei   blk-mq: make life...
258
259
260
261
262
263
264
265
266
267
268
  void blk_mq_sysfs_deinit(struct request_queue *q)
  {
  	struct blk_mq_ctx *ctx;
  	int cpu;
  
  	for_each_possible_cpu(cpu) {
  		ctx = per_cpu_ptr(q->queue_ctx, cpu);
  		kobject_put(&ctx->kobj);
  	}
  	kobject_put(&q->mq_kobj);
  }
737f98cfe   Ming Lei   blk-mq: initializ...
269
  void blk_mq_sysfs_init(struct request_queue *q)
67aec14ce   Jens Axboe   blk-mq: make the ...
270
  {
67aec14ce   Jens Axboe   blk-mq: make the ...
271
  	struct blk_mq_ctx *ctx;
897bb0c7f   Thomas Gleixner   blk-mq: Use prope...
272
  	int cpu;
67aec14ce   Jens Axboe   blk-mq: make the ...
273
274
  
  	kobject_init(&q->mq_kobj, &blk_mq_ktype);
897bb0c7f   Thomas Gleixner   blk-mq: Use prope...
275
276
  	for_each_possible_cpu(cpu) {
  		ctx = per_cpu_ptr(q->queue_ctx, cpu);
06a41a99d   Takashi Iwai   blk-mq: Fix unini...
277
  		kobject_init(&ctx->kobj, &blk_mq_ctx_ktype);
897bb0c7f   Thomas Gleixner   blk-mq: Use prope...
278
  	}
67aec14ce   Jens Axboe   blk-mq: make the ...
279
  }
2d0364c8c   Bart Van Assche   blk-mq: Register ...
280
  int __blk_mq_register_dev(struct device *dev, struct request_queue *q)
320ae51fe   Jens Axboe   blk-mq: new multi...
281
  {
320ae51fe   Jens Axboe   blk-mq: new multi...
282
  	struct blk_mq_hw_ctx *hctx;
67aec14ce   Jens Axboe   blk-mq: make the ...
283
  	int ret, i;
320ae51fe   Jens Axboe   blk-mq: new multi...
284

2d0364c8c   Bart Van Assche   blk-mq: Register ...
285
286
  	WARN_ON_ONCE(!q->kobj.parent);
  	lockdep_assert_held(&q->sysfs_lock);
4593fdbe7   Akinobu Mita   blk-mq: fix sysfs...
287

320ae51fe   Jens Axboe   blk-mq: new multi...
288
289
  	ret = kobject_add(&q->mq_kobj, kobject_get(&dev->kobj), "%s", "mq");
  	if (ret < 0)
4593fdbe7   Akinobu Mita   blk-mq: fix sysfs...
290
  		goto out;
320ae51fe   Jens Axboe   blk-mq: new multi...
291
292
293
294
  
  	kobject_uevent(&q->mq_kobj, KOBJ_ADD);
  
  	queue_for_each_hw_ctx(q, hctx, i) {
67aec14ce   Jens Axboe   blk-mq: make the ...
295
  		ret = blk_mq_register_hctx(hctx);
320ae51fe   Jens Axboe   blk-mq: new multi...
296
  		if (ret)
f05d1ba78   Bart Van Assche   blk-mq: Only unre...
297
  			goto unreg;
320ae51fe   Jens Axboe   blk-mq: new multi...
298
  	}
f05d1ba78   Bart Van Assche   blk-mq: Only unre...
299
  	q->mq_sysfs_init_done = true;
2d0364c8c   Bart Van Assche   blk-mq: Register ...
300

4593fdbe7   Akinobu Mita   blk-mq: fix sysfs...
301
  out:
2d0364c8c   Bart Van Assche   blk-mq: Register ...
302
  	return ret;
f05d1ba78   Bart Van Assche   blk-mq: Only unre...
303
304
305
306
  
  unreg:
  	while (--i >= 0)
  		blk_mq_unregister_hctx(q->queue_hw_ctx[i]);
f05d1ba78   Bart Van Assche   blk-mq: Only unre...
307
308
309
310
  	kobject_uevent(&q->mq_kobj, KOBJ_REMOVE);
  	kobject_del(&q->mq_kobj);
  	kobject_put(&dev->kobj);
  	return ret;
2d0364c8c   Bart Van Assche   blk-mq: Register ...
311
312
313
314
315
316
317
318
319
  }
  
  int blk_mq_register_dev(struct device *dev, struct request_queue *q)
  {
  	int ret;
  
  	mutex_lock(&q->sysfs_lock);
  	ret = __blk_mq_register_dev(dev, q);
  	mutex_unlock(&q->sysfs_lock);
320ae51fe   Jens Axboe   blk-mq: new multi...
320

4593fdbe7   Akinobu Mita   blk-mq: fix sysfs...
321
  	return ret;
320ae51fe   Jens Axboe   blk-mq: new multi...
322
  }
b21d5b301   Matias Bjørling   blk-mq: register ...
323
  EXPORT_SYMBOL_GPL(blk_mq_register_dev);
67aec14ce   Jens Axboe   blk-mq: make the ...
324
325
326
327
328
  
  void blk_mq_sysfs_unregister(struct request_queue *q)
  {
  	struct blk_mq_hw_ctx *hctx;
  	int i;
2d0364c8c   Bart Van Assche   blk-mq: Register ...
329
  	mutex_lock(&q->sysfs_lock);
4593fdbe7   Akinobu Mita   blk-mq: fix sysfs...
330
  	if (!q->mq_sysfs_init_done)
2d0364c8c   Bart Van Assche   blk-mq: Register ...
331
  		goto unlock;
4593fdbe7   Akinobu Mita   blk-mq: fix sysfs...
332

67aec14ce   Jens Axboe   blk-mq: make the ...
333
334
  	queue_for_each_hw_ctx(q, hctx, i)
  		blk_mq_unregister_hctx(hctx);
2d0364c8c   Bart Van Assche   blk-mq: Register ...
335
336
337
  
  unlock:
  	mutex_unlock(&q->sysfs_lock);
67aec14ce   Jens Axboe   blk-mq: make the ...
338
339
340
341
342
343
  }
  
  int blk_mq_sysfs_register(struct request_queue *q)
  {
  	struct blk_mq_hw_ctx *hctx;
  	int i, ret = 0;
2d0364c8c   Bart Van Assche   blk-mq: Register ...
344
  	mutex_lock(&q->sysfs_lock);
4593fdbe7   Akinobu Mita   blk-mq: fix sysfs...
345
  	if (!q->mq_sysfs_init_done)
2d0364c8c   Bart Van Assche   blk-mq: Register ...
346
  		goto unlock;
4593fdbe7   Akinobu Mita   blk-mq: fix sysfs...
347

67aec14ce   Jens Axboe   blk-mq: make the ...
348
349
350
351
352
  	queue_for_each_hw_ctx(q, hctx, i) {
  		ret = blk_mq_register_hctx(hctx);
  		if (ret)
  			break;
  	}
2d0364c8c   Bart Van Assche   blk-mq: Register ...
353
354
  unlock:
  	mutex_unlock(&q->sysfs_lock);
67aec14ce   Jens Axboe   blk-mq: make the ...
355
356
  	return ret;
  }