Blame view

block/blk-mq-sysfs.c 10.6 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
19
20
21
22
23
24
25
26
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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
  #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)
  {
  }
  
  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;
  }
  
  static ssize_t blk_mq_sysfs_dispatched_show(struct blk_mq_ctx *ctx, char *page)
  {
  	return sprintf(page, "%lu %lu
  ", ctx->rq_dispatched[1],
  				ctx->rq_dispatched[0]);
  }
  
  static ssize_t blk_mq_sysfs_merged_show(struct blk_mq_ctx *ctx, char *page)
  {
  	return sprintf(page, "%lu
  ", ctx->rq_merged);
  }
  
  static ssize_t blk_mq_sysfs_completed_show(struct blk_mq_ctx *ctx, char *page)
  {
  	return sprintf(page, "%lu %lu
  ", ctx->rq_completed[1],
  				ctx->rq_completed[0]);
  }
  
  static ssize_t sysfs_list_show(char *page, struct list_head *list, char *msg)
  {
  	char *start_page = page;
  	struct request *rq;
  
  	page += sprintf(page, "%s:
  ", msg);
  
  	list_for_each_entry(rq, list, queuelist)
  		page += sprintf(page, "\t%p
  ", rq);
  
  	return page - start_page;
  }
  
  static ssize_t blk_mq_sysfs_rq_list_show(struct blk_mq_ctx *ctx, char *page)
  {
  	ssize_t ret;
  
  	spin_lock(&ctx->lock);
  	ret = sysfs_list_show(page, &ctx->rq_list, "CTX pending");
  	spin_unlock(&ctx->lock);
  
  	return ret;
  }
  
  static ssize_t blk_mq_hw_sysfs_queued_show(struct blk_mq_hw_ctx *hctx,
  					   char *page)
  {
  	return sprintf(page, "%lu
  ", hctx->queued);
  }
  
  static ssize_t blk_mq_hw_sysfs_run_show(struct blk_mq_hw_ctx *hctx, char *page)
  {
  	return sprintf(page, "%lu
  ", hctx->run);
  }
  
  static ssize_t blk_mq_hw_sysfs_dispatched_show(struct blk_mq_hw_ctx *hctx,
  					       char *page)
  {
  	char *start_page = page;
  	int i;
  
  	page += sprintf(page, "%8u\t%lu
  ", 0U, hctx->dispatched[0]);
  
  	for (i = 1; i < BLK_MQ_MAX_DISPATCH_ORDER; i++) {
  		unsigned long d = 1U << (i - 1);
  
  		page += sprintf(page, "%8lu\t%lu
  ", d, hctx->dispatched[i]);
  	}
  
  	return page - start_page;
  }
  
  static ssize_t blk_mq_hw_sysfs_rq_list_show(struct blk_mq_hw_ctx *hctx,
  					    char *page)
  {
  	ssize_t ret;
  
  	spin_lock(&hctx->lock);
  	ret = sysfs_list_show(page, &hctx->dispatch, "HCTX pending");
  	spin_unlock(&hctx->lock);
  
  	return ret;
  }
320ae51fe   Jens Axboe   blk-mq: new multi...
214
215
216
217
  static ssize_t blk_mq_hw_sysfs_tags_show(struct blk_mq_hw_ctx *hctx, char *page)
  {
  	return blk_mq_tag_sysfs_show(hctx->tags, page);
  }
0d2602ca3   Jens Axboe   blk-mq: improve s...
218
219
220
221
222
  static ssize_t blk_mq_hw_sysfs_active_show(struct blk_mq_hw_ctx *hctx, char *page)
  {
  	return sprintf(page, "%u
  ", atomic_read(&hctx->nr_active));
  }
676141e48   Jens Axboe   blk-mq: don't dum...
223
224
  static ssize_t blk_mq_hw_sysfs_cpus_show(struct blk_mq_hw_ctx *hctx, char *page)
  {
cb2da43e3   Jens Axboe   blk-mq: simplify ...
225
  	unsigned int i, first = 1;
676141e48   Jens Axboe   blk-mq: don't dum...
226
227
228
  	ssize_t ret = 0;
  
  	blk_mq_disable_hotplug();
cb2da43e3   Jens Axboe   blk-mq: simplify ...
229
  	for_each_cpu(i, hctx->cpumask) {
676141e48   Jens Axboe   blk-mq: don't dum...
230
231
232
233
234
235
236
237
238
239
240
241
242
243
  		if (first)
  			ret += sprintf(ret + page, "%u", i);
  		else
  			ret += sprintf(ret + page, ", %u", i);
  
  		first = 0;
  	}
  
  	blk_mq_enable_hotplug();
  
  	ret += sprintf(ret + page, "
  ");
  	return ret;
  }
320ae51fe   Jens Axboe   blk-mq: new multi...
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
  static struct blk_mq_ctx_sysfs_entry blk_mq_sysfs_dispatched = {
  	.attr = {.name = "dispatched", .mode = S_IRUGO },
  	.show = blk_mq_sysfs_dispatched_show,
  };
  static struct blk_mq_ctx_sysfs_entry blk_mq_sysfs_merged = {
  	.attr = {.name = "merged", .mode = S_IRUGO },
  	.show = blk_mq_sysfs_merged_show,
  };
  static struct blk_mq_ctx_sysfs_entry blk_mq_sysfs_completed = {
  	.attr = {.name = "completed", .mode = S_IRUGO },
  	.show = blk_mq_sysfs_completed_show,
  };
  static struct blk_mq_ctx_sysfs_entry blk_mq_sysfs_rq_list = {
  	.attr = {.name = "rq_list", .mode = S_IRUGO },
  	.show = blk_mq_sysfs_rq_list_show,
  };
  
  static struct attribute *default_ctx_attrs[] = {
  	&blk_mq_sysfs_dispatched.attr,
  	&blk_mq_sysfs_merged.attr,
  	&blk_mq_sysfs_completed.attr,
  	&blk_mq_sysfs_rq_list.attr,
  	NULL,
  };
  
  static struct blk_mq_hw_ctx_sysfs_entry blk_mq_hw_sysfs_queued = {
  	.attr = {.name = "queued", .mode = S_IRUGO },
  	.show = blk_mq_hw_sysfs_queued_show,
  };
  static struct blk_mq_hw_ctx_sysfs_entry blk_mq_hw_sysfs_run = {
  	.attr = {.name = "run", .mode = S_IRUGO },
  	.show = blk_mq_hw_sysfs_run_show,
  };
  static struct blk_mq_hw_ctx_sysfs_entry blk_mq_hw_sysfs_dispatched = {
  	.attr = {.name = "dispatched", .mode = S_IRUGO },
  	.show = blk_mq_hw_sysfs_dispatched_show,
  };
0d2602ca3   Jens Axboe   blk-mq: improve s...
281
282
283
284
  static struct blk_mq_hw_ctx_sysfs_entry blk_mq_hw_sysfs_active = {
  	.attr = {.name = "active", .mode = S_IRUGO },
  	.show = blk_mq_hw_sysfs_active_show,
  };
320ae51fe   Jens Axboe   blk-mq: new multi...
285
286
287
288
  static struct blk_mq_hw_ctx_sysfs_entry blk_mq_hw_sysfs_pending = {
  	.attr = {.name = "pending", .mode = S_IRUGO },
  	.show = blk_mq_hw_sysfs_rq_list_show,
  };
320ae51fe   Jens Axboe   blk-mq: new multi...
289
290
291
292
  static struct blk_mq_hw_ctx_sysfs_entry blk_mq_hw_sysfs_tags = {
  	.attr = {.name = "tags", .mode = S_IRUGO },
  	.show = blk_mq_hw_sysfs_tags_show,
  };
676141e48   Jens Axboe   blk-mq: don't dum...
293
294
295
296
  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...
297
298
299
300
301
302
  
  static struct attribute *default_hw_ctx_attrs[] = {
  	&blk_mq_hw_sysfs_queued.attr,
  	&blk_mq_hw_sysfs_run.attr,
  	&blk_mq_hw_sysfs_dispatched.attr,
  	&blk_mq_hw_sysfs_pending.attr,
320ae51fe   Jens Axboe   blk-mq: new multi...
303
  	&blk_mq_hw_sysfs_tags.attr,
676141e48   Jens Axboe   blk-mq: don't dum...
304
  	&blk_mq_hw_sysfs_cpus.attr,
0d2602ca3   Jens Axboe   blk-mq: improve s...
305
  	&blk_mq_hw_sysfs_active.attr,
320ae51fe   Jens Axboe   blk-mq: new multi...
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
  	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,
  	.release	= blk_mq_sysfs_release,
  };
  
  static struct kobj_type blk_mq_hw_ktype = {
  	.sysfs_ops	= &blk_mq_hw_sysfs_ops,
  	.default_attrs	= default_hw_ctx_attrs,
  	.release	= blk_mq_sysfs_release,
  };
ee3c5db08   Fengguang Wu   blk-mq: blk_mq_un...
335
  static void blk_mq_unregister_hctx(struct blk_mq_hw_ctx *hctx)
67aec14ce   Jens Axboe   blk-mq: make the ...
336
337
338
339
340
341
342
343
344
345
346
347
  {
  	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);
  }
ee3c5db08   Fengguang Wu   blk-mq: blk_mq_un...
348
  static int blk_mq_register_hctx(struct blk_mq_hw_ctx *hctx)
67aec14ce   Jens Axboe   blk-mq: make the ...
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
  {
  	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;
  }
320ae51fe   Jens Axboe   blk-mq: new multi...
369
370
371
  void blk_mq_unregister_disk(struct gendisk *disk)
  {
  	struct request_queue *q = disk->queue;
851573660   Andrey Vagin   block: fix memory...
372
373
374
375
376
  	struct blk_mq_hw_ctx *hctx;
  	struct blk_mq_ctx *ctx;
  	int i, j;
  
  	queue_for_each_hw_ctx(q, hctx, i) {
67aec14ce   Jens Axboe   blk-mq: make the ...
377
378
379
  		blk_mq_unregister_hctx(hctx);
  
  		hctx_for_each_ctx(hctx, ctx, j)
851573660   Andrey Vagin   block: fix memory...
380
  			kobject_put(&ctx->kobj);
67aec14ce   Jens Axboe   blk-mq: make the ...
381

851573660   Andrey Vagin   block: fix memory...
382
383
  		kobject_put(&hctx->kobj);
  	}
320ae51fe   Jens Axboe   blk-mq: new multi...
384
385
386
  
  	kobject_uevent(&q->mq_kobj, KOBJ_REMOVE);
  	kobject_del(&q->mq_kobj);
851573660   Andrey Vagin   block: fix memory...
387
  	kobject_put(&q->mq_kobj);
320ae51fe   Jens Axboe   blk-mq: new multi...
388
389
390
  
  	kobject_put(&disk_to_dev(disk)->kobj);
  }
67aec14ce   Jens Axboe   blk-mq: make the ...
391
392
393
394
  static void blk_mq_sysfs_init(struct request_queue *q)
  {
  	struct blk_mq_hw_ctx *hctx;
  	struct blk_mq_ctx *ctx;
06a41a99d   Takashi Iwai   blk-mq: Fix unini...
395
  	int i;
67aec14ce   Jens Axboe   blk-mq: make the ...
396
397
  
  	kobject_init(&q->mq_kobj, &blk_mq_ktype);
06a41a99d   Takashi Iwai   blk-mq: Fix unini...
398
  	queue_for_each_hw_ctx(q, hctx, i)
67aec14ce   Jens Axboe   blk-mq: make the ...
399
  		kobject_init(&hctx->kobj, &blk_mq_hw_ktype);
06a41a99d   Takashi Iwai   blk-mq: Fix unini...
400
401
  	queue_for_each_ctx(q, ctx, i)
  		kobject_init(&ctx->kobj, &blk_mq_ctx_ktype);
67aec14ce   Jens Axboe   blk-mq: make the ...
402
  }
17497acbd   Tejun Heo   blk-mq, percpu_re...
403
404
405
406
407
  /* see blk_register_queue() */
  void blk_mq_finish_init(struct request_queue *q)
  {
  	percpu_ref_switch_to_percpu(&q->mq_usage_counter);
  }
320ae51fe   Jens Axboe   blk-mq: new multi...
408
409
410
411
412
  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;
67aec14ce   Jens Axboe   blk-mq: make the ...
413
  	int ret, i;
320ae51fe   Jens Axboe   blk-mq: new multi...
414

67aec14ce   Jens Axboe   blk-mq: make the ...
415
  	blk_mq_sysfs_init(q);
320ae51fe   Jens Axboe   blk-mq: new multi...
416
417
418
419
420
421
422
423
  
  	ret = kobject_add(&q->mq_kobj, kobject_get(&dev->kobj), "%s", "mq");
  	if (ret < 0)
  		return ret;
  
  	kobject_uevent(&q->mq_kobj, KOBJ_ADD);
  
  	queue_for_each_hw_ctx(q, hctx, i) {
67aec14ce   Jens Axboe   blk-mq: make the ...
424
425
  		hctx->flags |= BLK_MQ_F_SYSFS_UP;
  		ret = blk_mq_register_hctx(hctx);
320ae51fe   Jens Axboe   blk-mq: new multi...
426
427
  		if (ret)
  			break;
320ae51fe   Jens Axboe   blk-mq: new multi...
428
429
430
431
432
433
434
435
436
  	}
  
  	if (ret) {
  		blk_mq_unregister_disk(disk);
  		return ret;
  	}
  
  	return 0;
  }
67aec14ce   Jens Axboe   blk-mq: make the ...
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
  
  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;
  }