Blame view

block/blk-sysfs.c 11.9 KB
8324aa91d   Jens Axboe   block: split tag ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  /*
   * Functions related to sysfs handling
   */
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/bio.h>
  #include <linux/blkdev.h>
  #include <linux/blktrace_api.h>
  
  #include "blk.h"
  
  struct queue_sysfs_entry {
  	struct attribute attr;
  	ssize_t (*show)(struct request_queue *, char *);
  	ssize_t (*store)(struct request_queue *, const char *, size_t);
  };
  
  static ssize_t
9cb308ce8   Xiaotian Feng   block: sysfs fix ...
19
  queue_var_show(unsigned long var, char *page)
8324aa91d   Jens Axboe   block: split tag ...
20
  {
9cb308ce8   Xiaotian Feng   block: sysfs fix ...
21
22
  	return sprintf(page, "%lu
  ", var);
8324aa91d   Jens Axboe   block: split tag ...
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
  }
  
  static ssize_t
  queue_var_store(unsigned long *var, const char *page, size_t count)
  {
  	char *p = (char *) page;
  
  	*var = simple_strtoul(p, &p, 10);
  	return count;
  }
  
  static ssize_t queue_requests_show(struct request_queue *q, char *page)
  {
  	return queue_var_show(q->nr_requests, (page));
  }
  
  static ssize_t
  queue_requests_store(struct request_queue *q, const char *page, size_t count)
  {
  	struct request_list *rl = &q->rq;
  	unsigned long nr;
b8a9ae779   Jens Axboe   block: don't assu...
44
45
46
47
48
49
  	int ret;
  
  	if (!q->request_fn)
  		return -EINVAL;
  
  	ret = queue_var_store(&nr, page, count);
8324aa91d   Jens Axboe   block: split tag ...
50
51
52
53
54
55
  	if (nr < BLKDEV_MIN_RQ)
  		nr = BLKDEV_MIN_RQ;
  
  	spin_lock_irq(q->queue_lock);
  	q->nr_requests = nr;
  	blk_queue_congestion_threshold(q);
1faa16d22   Jens Axboe   block: change the...
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
  	if (rl->count[BLK_RW_SYNC] >= queue_congestion_on_threshold(q))
  		blk_set_queue_congested(q, BLK_RW_SYNC);
  	else if (rl->count[BLK_RW_SYNC] < queue_congestion_off_threshold(q))
  		blk_clear_queue_congested(q, BLK_RW_SYNC);
  
  	if (rl->count[BLK_RW_ASYNC] >= queue_congestion_on_threshold(q))
  		blk_set_queue_congested(q, BLK_RW_ASYNC);
  	else if (rl->count[BLK_RW_ASYNC] < queue_congestion_off_threshold(q))
  		blk_clear_queue_congested(q, BLK_RW_ASYNC);
  
  	if (rl->count[BLK_RW_SYNC] >= q->nr_requests) {
  		blk_set_queue_full(q, BLK_RW_SYNC);
  	} else if (rl->count[BLK_RW_SYNC]+1 <= q->nr_requests) {
  		blk_clear_queue_full(q, BLK_RW_SYNC);
  		wake_up(&rl->wait[BLK_RW_SYNC]);
8324aa91d   Jens Axboe   block: split tag ...
71
  	}
1faa16d22   Jens Axboe   block: change the...
72
73
74
75
76
  	if (rl->count[BLK_RW_ASYNC] >= q->nr_requests) {
  		blk_set_queue_full(q, BLK_RW_ASYNC);
  	} else if (rl->count[BLK_RW_ASYNC]+1 <= q->nr_requests) {
  		blk_clear_queue_full(q, BLK_RW_ASYNC);
  		wake_up(&rl->wait[BLK_RW_ASYNC]);
8324aa91d   Jens Axboe   block: split tag ...
77
78
79
80
81
82
83
  	}
  	spin_unlock_irq(q->queue_lock);
  	return ret;
  }
  
  static ssize_t queue_ra_show(struct request_queue *q, char *page)
  {
9cb308ce8   Xiaotian Feng   block: sysfs fix ...
84
85
  	unsigned long ra_kb = q->backing_dev_info.ra_pages <<
  					(PAGE_CACHE_SHIFT - 10);
8324aa91d   Jens Axboe   block: split tag ...
86
87
88
89
90
91
92
93
94
  
  	return queue_var_show(ra_kb, (page));
  }
  
  static ssize_t
  queue_ra_store(struct request_queue *q, const char *page, size_t count)
  {
  	unsigned long ra_kb;
  	ssize_t ret = queue_var_store(&ra_kb, page, count);
8324aa91d   Jens Axboe   block: split tag ...
95
  	q->backing_dev_info.ra_pages = ra_kb >> (PAGE_CACHE_SHIFT - 10);
8324aa91d   Jens Axboe   block: split tag ...
96
97
98
99
100
101
  
  	return ret;
  }
  
  static ssize_t queue_max_sectors_show(struct request_queue *q, char *page)
  {
ae03bf639   Martin K. Petersen   block: Use access...
102
  	int max_sectors_kb = queue_max_sectors(q) >> 1;
8324aa91d   Jens Axboe   block: split tag ...
103
104
105
  
  	return queue_var_show(max_sectors_kb, (page));
  }
e1defc4ff   Martin K. Petersen   block: Do away wi...
106
  static ssize_t queue_logical_block_size_show(struct request_queue *q, char *page)
e68b903c6   Martin K. Petersen   Expose hardware s...
107
  {
e1defc4ff   Martin K. Petersen   block: Do away wi...
108
  	return queue_var_show(queue_logical_block_size(q), page);
e68b903c6   Martin K. Petersen   Expose hardware s...
109
  }
c72758f33   Martin K. Petersen   block: Export I/O...
110
111
112
113
114
115
116
117
118
119
120
121
122
  static ssize_t queue_physical_block_size_show(struct request_queue *q, char *page)
  {
  	return queue_var_show(queue_physical_block_size(q), page);
  }
  
  static ssize_t queue_io_min_show(struct request_queue *q, char *page)
  {
  	return queue_var_show(queue_io_min(q), page);
  }
  
  static ssize_t queue_io_opt_show(struct request_queue *q, char *page)
  {
  	return queue_var_show(queue_io_opt(q), page);
e68b903c6   Martin K. Petersen   Expose hardware s...
123
  }
8324aa91d   Jens Axboe   block: split tag ...
124
125
126
127
  static ssize_t
  queue_max_sectors_store(struct request_queue *q, const char *page, size_t count)
  {
  	unsigned long max_sectors_kb,
ae03bf639   Martin K. Petersen   block: Use access...
128
  		max_hw_sectors_kb = queue_max_hw_sectors(q) >> 1,
8324aa91d   Jens Axboe   block: split tag ...
129
130
131
132
133
  			page_kb = 1 << (PAGE_CACHE_SHIFT - 10);
  	ssize_t ret = queue_var_store(&max_sectors_kb, page, count);
  
  	if (max_sectors_kb > max_hw_sectors_kb || max_sectors_kb < page_kb)
  		return -EINVAL;
7c239517d   Wu Fengguang   block: don't take...
134

8324aa91d   Jens Axboe   block: split tag ...
135
  	spin_lock_irq(q->queue_lock);
c295fc057   Nikanth Karthikesan   block: Allow chan...
136
  	q->limits.max_sectors = max_sectors_kb << 1;
8324aa91d   Jens Axboe   block: split tag ...
137
138
139
140
141
142
143
  	spin_unlock_irq(q->queue_lock);
  
  	return ret;
  }
  
  static ssize_t queue_max_hw_sectors_show(struct request_queue *q, char *page)
  {
ae03bf639   Martin K. Petersen   block: Use access...
144
  	int max_hw_sectors_kb = queue_max_hw_sectors(q) >> 1;
8324aa91d   Jens Axboe   block: split tag ...
145
146
147
  
  	return queue_var_show(max_hw_sectors_kb, (page));
  }
1308835ff   Bartlomiej Zolnierkiewicz   block: export SSD...
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
  static ssize_t queue_nonrot_show(struct request_queue *q, char *page)
  {
  	return queue_var_show(!blk_queue_nonrot(q), page);
  }
  
  static ssize_t queue_nonrot_store(struct request_queue *q, const char *page,
  				  size_t count)
  {
  	unsigned long nm;
  	ssize_t ret = queue_var_store(&nm, page, count);
  
  	spin_lock_irq(q->queue_lock);
  	if (nm)
  		queue_flag_clear(QUEUE_FLAG_NONROT, q);
  	else
  		queue_flag_set(QUEUE_FLAG_NONROT, q);
  	spin_unlock_irq(q->queue_lock);
  
  	return ret;
  }
ac9fafa12   Alan D. Brunelle   block: Skip I/O m...
168
169
170
171
172
173
174
175
176
177
  static ssize_t queue_nomerges_show(struct request_queue *q, char *page)
  {
  	return queue_var_show(blk_queue_nomerges(q), page);
  }
  
  static ssize_t queue_nomerges_store(struct request_queue *q, const char *page,
  				    size_t count)
  {
  	unsigned long nm;
  	ssize_t ret = queue_var_store(&nm, page, count);
bf0f97025   Jens Axboe   block: sysfs stor...
178
  	spin_lock_irq(q->queue_lock);
ac9fafa12   Alan D. Brunelle   block: Skip I/O m...
179
  	if (nm)
bf0f97025   Jens Axboe   block: sysfs stor...
180
  		queue_flag_set(QUEUE_FLAG_NOMERGES, q);
ac9fafa12   Alan D. Brunelle   block: Skip I/O m...
181
  	else
bf0f97025   Jens Axboe   block: sysfs stor...
182
  		queue_flag_clear(QUEUE_FLAG_NOMERGES, q);
bf0f97025   Jens Axboe   block: sysfs stor...
183
  	spin_unlock_irq(q->queue_lock);
1308835ff   Bartlomiej Zolnierkiewicz   block: export SSD...
184

ac9fafa12   Alan D. Brunelle   block: Skip I/O m...
185
186
  	return ret;
  }
c7c22e4d5   Jens Axboe   block: add suppor...
187
188
  static ssize_t queue_rq_affinity_show(struct request_queue *q, char *page)
  {
9cb308ce8   Xiaotian Feng   block: sysfs fix ...
189
  	bool set = test_bit(QUEUE_FLAG_SAME_COMP, &q->queue_flags);
c7c22e4d5   Jens Axboe   block: add suppor...
190

9cb308ce8   Xiaotian Feng   block: sysfs fix ...
191
  	return queue_var_show(set, page);
c7c22e4d5   Jens Axboe   block: add suppor...
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
  }
  
  static ssize_t
  queue_rq_affinity_store(struct request_queue *q, const char *page, size_t count)
  {
  	ssize_t ret = -EINVAL;
  #if defined(CONFIG_USE_GENERIC_SMP_HELPERS)
  	unsigned long val;
  
  	ret = queue_var_store(&val, page, count);
  	spin_lock_irq(q->queue_lock);
  	if (val)
  		queue_flag_set(QUEUE_FLAG_SAME_COMP, q);
  	else
  		queue_flag_clear(QUEUE_FLAG_SAME_COMP,  q);
  	spin_unlock_irq(q->queue_lock);
  #endif
  	return ret;
  }
8324aa91d   Jens Axboe   block: split tag ...
211

bc58ba946   Jens Axboe   block: add sysfs ...
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
  static ssize_t queue_iostats_show(struct request_queue *q, char *page)
  {
  	return queue_var_show(blk_queue_io_stat(q), page);
  }
  
  static ssize_t queue_iostats_store(struct request_queue *q, const char *page,
  				   size_t count)
  {
  	unsigned long stats;
  	ssize_t ret = queue_var_store(&stats, page, count);
  
  	spin_lock_irq(q->queue_lock);
  	if (stats)
  		queue_flag_set(QUEUE_FLAG_IO_STAT, q);
  	else
  		queue_flag_clear(QUEUE_FLAG_IO_STAT, q);
  	spin_unlock_irq(q->queue_lock);
  
  	return ret;
  }
8324aa91d   Jens Axboe   block: split tag ...
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
  static struct queue_sysfs_entry queue_requests_entry = {
  	.attr = {.name = "nr_requests", .mode = S_IRUGO | S_IWUSR },
  	.show = queue_requests_show,
  	.store = queue_requests_store,
  };
  
  static struct queue_sysfs_entry queue_ra_entry = {
  	.attr = {.name = "read_ahead_kb", .mode = S_IRUGO | S_IWUSR },
  	.show = queue_ra_show,
  	.store = queue_ra_store,
  };
  
  static struct queue_sysfs_entry queue_max_sectors_entry = {
  	.attr = {.name = "max_sectors_kb", .mode = S_IRUGO | S_IWUSR },
  	.show = queue_max_sectors_show,
  	.store = queue_max_sectors_store,
  };
  
  static struct queue_sysfs_entry queue_max_hw_sectors_entry = {
  	.attr = {.name = "max_hw_sectors_kb", .mode = S_IRUGO },
  	.show = queue_max_hw_sectors_show,
  };
  
  static struct queue_sysfs_entry queue_iosched_entry = {
  	.attr = {.name = "scheduler", .mode = S_IRUGO | S_IWUSR },
  	.show = elv_iosched_show,
  	.store = elv_iosched_store,
  };
e68b903c6   Martin K. Petersen   Expose hardware s...
260
261
  static struct queue_sysfs_entry queue_hw_sector_size_entry = {
  	.attr = {.name = "hw_sector_size", .mode = S_IRUGO },
e1defc4ff   Martin K. Petersen   block: Do away wi...
262
263
264
265
266
267
  	.show = queue_logical_block_size_show,
  };
  
  static struct queue_sysfs_entry queue_logical_block_size_entry = {
  	.attr = {.name = "logical_block_size", .mode = S_IRUGO },
  	.show = queue_logical_block_size_show,
e68b903c6   Martin K. Petersen   Expose hardware s...
268
  };
c72758f33   Martin K. Petersen   block: Export I/O...
269
270
271
272
273
274
275
276
277
278
279
280
281
  static struct queue_sysfs_entry queue_physical_block_size_entry = {
  	.attr = {.name = "physical_block_size", .mode = S_IRUGO },
  	.show = queue_physical_block_size_show,
  };
  
  static struct queue_sysfs_entry queue_io_min_entry = {
  	.attr = {.name = "minimum_io_size", .mode = S_IRUGO },
  	.show = queue_io_min_show,
  };
  
  static struct queue_sysfs_entry queue_io_opt_entry = {
  	.attr = {.name = "optimal_io_size", .mode = S_IRUGO },
  	.show = queue_io_opt_show,
e68b903c6   Martin K. Petersen   Expose hardware s...
282
  };
1308835ff   Bartlomiej Zolnierkiewicz   block: export SSD...
283
284
285
286
287
  static struct queue_sysfs_entry queue_nonrot_entry = {
  	.attr = {.name = "rotational", .mode = S_IRUGO | S_IWUSR },
  	.show = queue_nonrot_show,
  	.store = queue_nonrot_store,
  };
ac9fafa12   Alan D. Brunelle   block: Skip I/O m...
288
289
290
291
292
  static struct queue_sysfs_entry queue_nomerges_entry = {
  	.attr = {.name = "nomerges", .mode = S_IRUGO | S_IWUSR },
  	.show = queue_nomerges_show,
  	.store = queue_nomerges_store,
  };
c7c22e4d5   Jens Axboe   block: add suppor...
293
294
295
296
297
  static struct queue_sysfs_entry queue_rq_affinity_entry = {
  	.attr = {.name = "rq_affinity", .mode = S_IRUGO | S_IWUSR },
  	.show = queue_rq_affinity_show,
  	.store = queue_rq_affinity_store,
  };
bc58ba946   Jens Axboe   block: add sysfs ...
298
299
300
301
302
  static struct queue_sysfs_entry queue_iostats_entry = {
  	.attr = {.name = "iostats", .mode = S_IRUGO | S_IWUSR },
  	.show = queue_iostats_show,
  	.store = queue_iostats_store,
  };
8324aa91d   Jens Axboe   block: split tag ...
303
304
305
306
307
308
  static struct attribute *default_attrs[] = {
  	&queue_requests_entry.attr,
  	&queue_ra_entry.attr,
  	&queue_max_hw_sectors_entry.attr,
  	&queue_max_sectors_entry.attr,
  	&queue_iosched_entry.attr,
e68b903c6   Martin K. Petersen   Expose hardware s...
309
  	&queue_hw_sector_size_entry.attr,
e1defc4ff   Martin K. Petersen   block: Do away wi...
310
  	&queue_logical_block_size_entry.attr,
c72758f33   Martin K. Petersen   block: Export I/O...
311
312
313
  	&queue_physical_block_size_entry.attr,
  	&queue_io_min_entry.attr,
  	&queue_io_opt_entry.attr,
1308835ff   Bartlomiej Zolnierkiewicz   block: export SSD...
314
  	&queue_nonrot_entry.attr,
ac9fafa12   Alan D. Brunelle   block: Skip I/O m...
315
  	&queue_nomerges_entry.attr,
c7c22e4d5   Jens Axboe   block: add suppor...
316
  	&queue_rq_affinity_entry.attr,
bc58ba946   Jens Axboe   block: add sysfs ...
317
  	&queue_iostats_entry.attr,
8324aa91d   Jens Axboe   block: split tag ...
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
  	NULL,
  };
  
  #define to_queue(atr) container_of((atr), struct queue_sysfs_entry, attr)
  
  static ssize_t
  queue_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
  {
  	struct queue_sysfs_entry *entry = to_queue(attr);
  	struct request_queue *q =
  		container_of(kobj, struct request_queue, kobj);
  	ssize_t res;
  
  	if (!entry->show)
  		return -EIO;
  	mutex_lock(&q->sysfs_lock);
  	if (test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)) {
  		mutex_unlock(&q->sysfs_lock);
  		return -ENOENT;
  	}
  	res = entry->show(q, page);
  	mutex_unlock(&q->sysfs_lock);
  	return res;
  }
  
  static ssize_t
  queue_attr_store(struct kobject *kobj, struct attribute *attr,
  		    const char *page, size_t length)
  {
  	struct queue_sysfs_entry *entry = to_queue(attr);
6728cb0e6   Jens Axboe   block: make core ...
348
  	struct request_queue *q;
8324aa91d   Jens Axboe   block: split tag ...
349
350
351
352
  	ssize_t res;
  
  	if (!entry->store)
  		return -EIO;
6728cb0e6   Jens Axboe   block: make core ...
353
354
  
  	q = container_of(kobj, struct request_queue, kobj);
8324aa91d   Jens Axboe   block: split tag ...
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
  	mutex_lock(&q->sysfs_lock);
  	if (test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)) {
  		mutex_unlock(&q->sysfs_lock);
  		return -ENOENT;
  	}
  	res = entry->store(q, page, length);
  	mutex_unlock(&q->sysfs_lock);
  	return res;
  }
  
  /**
   * blk_cleanup_queue: - release a &struct request_queue when it is no longer needed
   * @kobj:    the kobj belonging of the request queue to be released
   *
   * Description:
   *     blk_cleanup_queue is the pair to blk_init_queue() or
   *     blk_queue_make_request().  It should be called when a request queue is
   *     being released; typically when a block device is being de-registered.
   *     Currently, its primary task it to free all the &struct request
   *     structures that were allocated to the queue and the queue itself.
   *
   * Caveat:
   *     Hopefully the low level driver will have finished any
   *     outstanding requests first...
   **/
  static void blk_release_queue(struct kobject *kobj)
  {
  	struct request_queue *q =
  		container_of(kobj, struct request_queue, kobj);
  	struct request_list *rl = &q->rq;
  
  	blk_sync_queue(q);
  
  	if (rl->rq_pool)
  		mempool_destroy(rl->rq_pool);
  
  	if (q->queue_tags)
  		__blk_queue_free_tags(q);
  
  	blk_trace_shutdown(q);
  
  	bdi_destroy(&q->backing_dev_info);
  	kmem_cache_free(blk_requestq_cachep, q);
  }
  
  static struct sysfs_ops queue_sysfs_ops = {
  	.show	= queue_attr_show,
  	.store	= queue_attr_store,
  };
  
  struct kobj_type blk_queue_ktype = {
  	.sysfs_ops	= &queue_sysfs_ops,
  	.default_attrs	= default_attrs,
  	.release	= blk_release_queue,
  };
  
  int blk_register_queue(struct gendisk *disk)
  {
  	int ret;
1d54ad6da   Li Zefan   blktrace: add tra...
414
  	struct device *dev = disk_to_dev(disk);
8324aa91d   Jens Axboe   block: split tag ...
415
416
  
  	struct request_queue *q = disk->queue;
fb1997463   Akinobu Mita   block: fix blk_re...
417
  	if (WARN_ON(!q))
8324aa91d   Jens Axboe   block: split tag ...
418
  		return -ENXIO;
1d54ad6da   Li Zefan   blktrace: add tra...
419
420
421
  	ret = blk_trace_init_sysfs(dev);
  	if (ret)
  		return ret;
c9059598e   Linus Torvalds   Merge branch 'for...
422
  	ret = kobject_add(&q->kobj, kobject_get(&dev->kobj), "%s", "queue");
8324aa91d   Jens Axboe   block: split tag ...
423
424
425
426
  	if (ret < 0)
  		return ret;
  
  	kobject_uevent(&q->kobj, KOBJ_ADD);
cd43e26f0   Martin K. Petersen   block: Expose sta...
427
428
  	if (!q->request_fn)
  		return 0;
8324aa91d   Jens Axboe   block: split tag ...
429
430
431
432
  	ret = elv_register_queue(q);
  	if (ret) {
  		kobject_uevent(&q->kobj, KOBJ_REMOVE);
  		kobject_del(&q->kobj);
48c0d4d4c   Zdenek Kabelac   Add missing blk_t...
433
  		blk_trace_remove_sysfs(disk_to_dev(disk));
8324aa91d   Jens Axboe   block: split tag ...
434
435
436
437
438
439
440
441
442
  		return ret;
  	}
  
  	return 0;
  }
  
  void blk_unregister_queue(struct gendisk *disk)
  {
  	struct request_queue *q = disk->queue;
fb1997463   Akinobu Mita   block: fix blk_re...
443
444
  	if (WARN_ON(!q))
  		return;
48c0d4d4c   Zdenek Kabelac   Add missing blk_t...
445
  	if (q->request_fn)
8324aa91d   Jens Axboe   block: split tag ...
446
  		elv_unregister_queue(q);
48c0d4d4c   Zdenek Kabelac   Add missing blk_t...
447
448
449
450
  	kobject_uevent(&q->kobj, KOBJ_REMOVE);
  	kobject_del(&q->kobj);
  	blk_trace_remove_sysfs(disk_to_dev(disk));
  	kobject_put(&disk_to_dev(disk)->kobj);
8324aa91d   Jens Axboe   block: split tag ...
451
  }