Blame view

block/blk-mq-sysfs.c 8.52 KB
3dcf60bcb   Christoph Hellwig   block: add SPDX t...
1
  // SPDX-License-Identifier: GPL-2.0
320ae51fe   Jens Axboe   blk-mq: new multi...
2
3
4
5
6
7
8
9
10
11
12
13
  #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>
c7e2d94b3   Ming Lei   blk-mq: free hw q...
14
  #include "blk.h"
320ae51fe   Jens Axboe   blk-mq: new multi...
15
16
17
18
19
  #include "blk-mq.h"
  #include "blk-mq-tag.h"
  
  static void blk_mq_sysfs_release(struct kobject *kobj)
  {
1db4909e7   Ming Lei   blk-mq: not embed...
20
21
22
23
24
25
26
27
28
29
30
31
  	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);
320ae51fe   Jens Axboe   blk-mq: new multi...
32
  }
6c8b232ef   Ming Lei   blk-mq: make life...
33
34
35
36
  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);
c7e2d94b3   Ming Lei   blk-mq: free hw q...
37

1b97871b5   Ming Lei   blk-mq: move canc...
38
  	cancel_delayed_work_sync(&hctx->run_work);
c7e2d94b3   Ming Lei   blk-mq: free hw q...
39
40
41
42
  	if (hctx->flags & BLK_MQ_F_BLOCKING)
  		cleanup_srcu_struct(hctx->srcu);
  	blk_free_flush_queue(hctx->fq);
  	sbitmap_free(&hctx->ctx_map);
01388df37   Ming Lei   blk-mq: free hctx...
43
  	free_cpumask_var(hctx->cpumask);
6c8b232ef   Ming Lei   blk-mq: make life...
44
45
46
  	kfree(hctx->ctxs);
  	kfree(hctx);
  }
320ae51fe   Jens Axboe   blk-mq: new multi...
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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
  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...
151
152
  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...
153
  {
d96b37c0a   Omar Sandoval   blk-mq: move tags...
154
155
  	return sprintf(page, "%u
  ", hctx->tags->nr_tags);
bd166ef18   Jens Axboe   blk-mq-sched: add...
156
  }
d96b37c0a   Omar Sandoval   blk-mq: move tags...
157
158
  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...
159
  {
d96b37c0a   Omar Sandoval   blk-mq: move tags...
160
161
  	return sprintf(page, "%u
  ", hctx->tags->nr_reserved_tags);
320ae51fe   Jens Axboe   blk-mq: new multi...
162
  }
676141e48   Jens Axboe   blk-mq: don't dum...
163
164
  static ssize_t blk_mq_hw_sysfs_cpus_show(struct blk_mq_hw_ctx *hctx, char *page)
  {
285b07348   Ming Lei   blk-mq: avoid sys...
165
  	const size_t size = PAGE_SIZE - 1;
cb2da43e3   Jens Axboe   blk-mq: simplify ...
166
  	unsigned int i, first = 1;
285b07348   Ming Lei   blk-mq: avoid sys...
167
  	int ret = 0, pos = 0;
676141e48   Jens Axboe   blk-mq: don't dum...
168

cb2da43e3   Jens Axboe   blk-mq: simplify ...
169
  	for_each_cpu(i, hctx->cpumask) {
676141e48   Jens Axboe   blk-mq: don't dum...
170
  		if (first)
285b07348   Ming Lei   blk-mq: avoid sys...
171
  			ret = snprintf(pos + page, size - pos, "%u", i);
676141e48   Jens Axboe   blk-mq: don't dum...
172
  		else
285b07348   Ming Lei   blk-mq: avoid sys...
173
174
175
176
  			ret = snprintf(pos + page, size - pos, ", %u", i);
  
  		if (ret >= size - pos)
  			break;
676141e48   Jens Axboe   blk-mq: don't dum...
177
178
  
  		first = 0;
285b07348   Ming Lei   blk-mq: avoid sys...
179
  		pos += ret;
676141e48   Jens Axboe   blk-mq: don't dum...
180
  	}
e13c3c219   Ming Lei   blk-mq: make sure...
181
182
  	ret = snprintf(pos + page, size + 1 - pos, "
  ");
285b07348   Ming Lei   blk-mq: avoid sys...
183
  	return pos + ret;
676141e48   Jens Axboe   blk-mq: don't dum...
184
  }
d96b37c0a   Omar Sandoval   blk-mq: move tags...
185
  static struct blk_mq_hw_ctx_sysfs_entry blk_mq_hw_sysfs_nr_tags = {
5657a819a   Joe Perches   block drivers/blo...
186
  	.attr = {.name = "nr_tags", .mode = 0444 },
d96b37c0a   Omar Sandoval   blk-mq: move tags...
187
188
189
  	.show = blk_mq_hw_sysfs_nr_tags_show,
  };
  static struct blk_mq_hw_ctx_sysfs_entry blk_mq_hw_sysfs_nr_reserved_tags = {
5657a819a   Joe Perches   block drivers/blo...
190
  	.attr = {.name = "nr_reserved_tags", .mode = 0444 },
d96b37c0a   Omar Sandoval   blk-mq: move tags...
191
192
  	.show = blk_mq_hw_sysfs_nr_reserved_tags_show,
  };
676141e48   Jens Axboe   blk-mq: don't dum...
193
  static struct blk_mq_hw_ctx_sysfs_entry blk_mq_hw_sysfs_cpus = {
5657a819a   Joe Perches   block drivers/blo...
194
  	.attr = {.name = "cpu_list", .mode = 0444 },
676141e48   Jens Axboe   blk-mq: don't dum...
195
196
  	.show = blk_mq_hw_sysfs_cpus_show,
  };
320ae51fe   Jens Axboe   blk-mq: new multi...
197
198
  
  static struct attribute *default_hw_ctx_attrs[] = {
d96b37c0a   Omar Sandoval   blk-mq: move tags...
199
200
  	&blk_mq_hw_sysfs_nr_tags.attr,
  	&blk_mq_hw_sysfs_nr_reserved_tags.attr,
676141e48   Jens Axboe   blk-mq: don't dum...
201
  	&blk_mq_hw_sysfs_cpus.attr,
320ae51fe   Jens Axboe   blk-mq: new multi...
202
203
  	NULL,
  };
800f5aa1e   Kimberly Brown   block: Replace al...
204
  ATTRIBUTE_GROUPS(default_hw_ctx);
320ae51fe   Jens Axboe   blk-mq: new multi...
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
  
  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,
1db4909e7   Ming Lei   blk-mq: not embed...
223
  	.release	= blk_mq_ctx_sysfs_release,
320ae51fe   Jens Axboe   blk-mq: new multi...
224
225
226
227
  };
  
  static struct kobj_type blk_mq_hw_ktype = {
  	.sysfs_ops	= &blk_mq_hw_sysfs_ops,
800f5aa1e   Kimberly Brown   block: Replace al...
228
  	.default_groups = default_hw_ctx_groups,
6c8b232ef   Ming Lei   blk-mq: make life...
229
  	.release	= blk_mq_hw_sysfs_release,
320ae51fe   Jens Axboe   blk-mq: new multi...
230
  };
ee3c5db08   Fengguang Wu   blk-mq: blk_mq_un...
231
  static void blk_mq_unregister_hctx(struct blk_mq_hw_ctx *hctx)
67aec14ce   Jens Axboe   blk-mq: make the ...
232
233
234
  {
  	struct blk_mq_ctx *ctx;
  	int i;
4593fdbe7   Akinobu Mita   blk-mq: fix sysfs...
235
  	if (!hctx->nr_ctx)
67aec14ce   Jens Axboe   blk-mq: make the ...
236
237
238
239
240
241
242
  		return;
  
  	hctx_for_each_ctx(hctx, ctx, i)
  		kobject_del(&ctx->kobj);
  
  	kobject_del(&hctx->kobj);
  }
ee3c5db08   Fengguang Wu   blk-mq: blk_mq_un...
243
  static int blk_mq_register_hctx(struct blk_mq_hw_ctx *hctx)
67aec14ce   Jens Axboe   blk-mq: make the ...
244
245
246
247
  {
  	struct request_queue *q = hctx->queue;
  	struct blk_mq_ctx *ctx;
  	int i, ret;
4593fdbe7   Akinobu Mita   blk-mq: fix sysfs...
248
  	if (!hctx->nr_ctx)
67aec14ce   Jens Axboe   blk-mq: make the ...
249
  		return 0;
1db4909e7   Ming Lei   blk-mq: not embed...
250
  	ret = kobject_add(&hctx->kobj, q->mq_kobj, "%u", hctx->queue_num);
67aec14ce   Jens Axboe   blk-mq: make the ...
251
252
253
254
255
256
257
258
259
260
261
  	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;
  }
667257e8b   Mike Snitzer   block: properly p...
262
  void blk_mq_unregister_dev(struct device *dev, struct request_queue *q)
320ae51fe   Jens Axboe   blk-mq: new multi...
263
  {
851573660   Andrey Vagin   block: fix memory...
264
  	struct blk_mq_hw_ctx *hctx;
7ea5fe31c   Ming Lei   blk-mq: make life...
265
  	int i;
851573660   Andrey Vagin   block: fix memory...
266

cecf5d87f   Ming Lei   block: split .sys...
267
  	lockdep_assert_held(&q->sysfs_dir_lock);
2d0364c8c   Bart Van Assche   blk-mq: Register ...
268

6c8b232ef   Ming Lei   blk-mq: make life...
269
  	queue_for_each_hw_ctx(q, hctx, i)
67aec14ce   Jens Axboe   blk-mq: make the ...
270
  		blk_mq_unregister_hctx(hctx);
1db4909e7   Ming Lei   blk-mq: not embed...
271
272
  	kobject_uevent(q->mq_kobj, KOBJ_REMOVE);
  	kobject_del(q->mq_kobj);
b21d5b301   Matias Bjørling   blk-mq: register ...
273
  	kobject_put(&dev->kobj);
4593fdbe7   Akinobu Mita   blk-mq: fix sysfs...
274
275
  
  	q->mq_sysfs_init_done = false;
c0f3fd2b3   Jens Axboe   blk-mq: fix deadl...
276
  }
868f2f0b7   Keith Busch   blk-mq: dynamic h...
277
278
279
280
  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...
281
282
283
284
285
286
287
288
289
  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);
  	}
1db4909e7   Ming Lei   blk-mq: not embed...
290
  	kobject_put(q->mq_kobj);
7ea5fe31c   Ming Lei   blk-mq: make life...
291
  }
737f98cfe   Ming Lei   blk-mq: initializ...
292
  void blk_mq_sysfs_init(struct request_queue *q)
67aec14ce   Jens Axboe   blk-mq: make the ...
293
  {
67aec14ce   Jens Axboe   blk-mq: make the ...
294
  	struct blk_mq_ctx *ctx;
897bb0c7f   Thomas Gleixner   blk-mq: Use prope...
295
  	int cpu;
67aec14ce   Jens Axboe   blk-mq: make the ...
296

1db4909e7   Ming Lei   blk-mq: not embed...
297
  	kobject_init(q->mq_kobj, &blk_mq_ktype);
67aec14ce   Jens Axboe   blk-mq: make the ...
298

897bb0c7f   Thomas Gleixner   blk-mq: Use prope...
299
300
  	for_each_possible_cpu(cpu) {
  		ctx = per_cpu_ptr(q->queue_ctx, cpu);
1db4909e7   Ming Lei   blk-mq: not embed...
301
302
  
  		kobject_get(q->mq_kobj);
06a41a99d   Takashi Iwai   blk-mq: Fix unini...
303
  		kobject_init(&ctx->kobj, &blk_mq_ctx_ktype);
897bb0c7f   Thomas Gleixner   blk-mq: Use prope...
304
  	}
67aec14ce   Jens Axboe   blk-mq: make the ...
305
  }
2d0364c8c   Bart Van Assche   blk-mq: Register ...
306
  int __blk_mq_register_dev(struct device *dev, struct request_queue *q)
320ae51fe   Jens Axboe   blk-mq: new multi...
307
  {
320ae51fe   Jens Axboe   blk-mq: new multi...
308
  	struct blk_mq_hw_ctx *hctx;
67aec14ce   Jens Axboe   blk-mq: make the ...
309
  	int ret, i;
320ae51fe   Jens Axboe   blk-mq: new multi...
310

2d0364c8c   Bart Van Assche   blk-mq: Register ...
311
  	WARN_ON_ONCE(!q->kobj.parent);
cecf5d87f   Ming Lei   block: split .sys...
312
  	lockdep_assert_held(&q->sysfs_dir_lock);
4593fdbe7   Akinobu Mita   blk-mq: fix sysfs...
313

1db4909e7   Ming Lei   blk-mq: not embed...
314
  	ret = kobject_add(q->mq_kobj, kobject_get(&dev->kobj), "%s", "mq");
320ae51fe   Jens Axboe   blk-mq: new multi...
315
  	if (ret < 0)
4593fdbe7   Akinobu Mita   blk-mq: fix sysfs...
316
  		goto out;
320ae51fe   Jens Axboe   blk-mq: new multi...
317

1db4909e7   Ming Lei   blk-mq: not embed...
318
  	kobject_uevent(q->mq_kobj, KOBJ_ADD);
320ae51fe   Jens Axboe   blk-mq: new multi...
319
320
  
  	queue_for_each_hw_ctx(q, hctx, i) {
67aec14ce   Jens Axboe   blk-mq: make the ...
321
  		ret = blk_mq_register_hctx(hctx);
320ae51fe   Jens Axboe   blk-mq: new multi...
322
  		if (ret)
f05d1ba78   Bart Van Assche   blk-mq: Only unre...
323
  			goto unreg;
320ae51fe   Jens Axboe   blk-mq: new multi...
324
  	}
f05d1ba78   Bart Van Assche   blk-mq: Only unre...
325
  	q->mq_sysfs_init_done = true;
2d0364c8c   Bart Van Assche   blk-mq: Register ...
326

4593fdbe7   Akinobu Mita   blk-mq: fix sysfs...
327
  out:
2d0364c8c   Bart Van Assche   blk-mq: Register ...
328
  	return ret;
f05d1ba78   Bart Van Assche   blk-mq: Only unre...
329
330
331
332
  
  unreg:
  	while (--i >= 0)
  		blk_mq_unregister_hctx(q->queue_hw_ctx[i]);
1db4909e7   Ming Lei   blk-mq: not embed...
333
334
  	kobject_uevent(q->mq_kobj, KOBJ_REMOVE);
  	kobject_del(q->mq_kobj);
f05d1ba78   Bart Van Assche   blk-mq: Only unre...
335
336
  	kobject_put(&dev->kobj);
  	return ret;
2d0364c8c   Bart Van Assche   blk-mq: Register ...
337
  }
67aec14ce   Jens Axboe   blk-mq: make the ...
338
339
340
341
  void blk_mq_sysfs_unregister(struct request_queue *q)
  {
  	struct blk_mq_hw_ctx *hctx;
  	int i;
cecf5d87f   Ming Lei   block: split .sys...
342
  	mutex_lock(&q->sysfs_dir_lock);
4593fdbe7   Akinobu Mita   blk-mq: fix sysfs...
343
  	if (!q->mq_sysfs_init_done)
2d0364c8c   Bart Van Assche   blk-mq: Register ...
344
  		goto unlock;
4593fdbe7   Akinobu Mita   blk-mq: fix sysfs...
345

67aec14ce   Jens Axboe   blk-mq: make the ...
346
347
  	queue_for_each_hw_ctx(q, hctx, i)
  		blk_mq_unregister_hctx(hctx);
2d0364c8c   Bart Van Assche   blk-mq: Register ...
348
349
  
  unlock:
cecf5d87f   Ming Lei   block: split .sys...
350
  	mutex_unlock(&q->sysfs_dir_lock);
67aec14ce   Jens Axboe   blk-mq: make the ...
351
352
353
354
355
356
  }
  
  int blk_mq_sysfs_register(struct request_queue *q)
  {
  	struct blk_mq_hw_ctx *hctx;
  	int i, ret = 0;
cecf5d87f   Ming Lei   block: split .sys...
357
  	mutex_lock(&q->sysfs_dir_lock);
4593fdbe7   Akinobu Mita   blk-mq: fix sysfs...
358
  	if (!q->mq_sysfs_init_done)
2d0364c8c   Bart Van Assche   blk-mq: Register ...
359
  		goto unlock;
4593fdbe7   Akinobu Mita   blk-mq: fix sysfs...
360

67aec14ce   Jens Axboe   blk-mq: make the ...
361
362
363
364
365
  	queue_for_each_hw_ctx(q, hctx, i) {
  		ret = blk_mq_register_hctx(hctx);
  		if (ret)
  			break;
  	}
2d0364c8c   Bart Van Assche   blk-mq: Register ...
366
  unlock:
cecf5d87f   Ming Lei   block: split .sys...
367
  	mutex_unlock(&q->sysfs_dir_lock);
2d0364c8c   Bart Van Assche   blk-mq: Register ...
368

67aec14ce   Jens Axboe   blk-mq: make the ...
369
370
  	return ret;
  }