xref: /linux/block/blk-sysfs.c (revision 320ae51feed5c2f13664aa05a76bec198967e04d)
18324aa91SJens Axboe /*
28324aa91SJens Axboe  * Functions related to sysfs handling
38324aa91SJens Axboe  */
48324aa91SJens Axboe #include <linux/kernel.h>
55a0e3ad6STejun Heo #include <linux/slab.h>
68324aa91SJens Axboe #include <linux/module.h>
78324aa91SJens Axboe #include <linux/bio.h>
88324aa91SJens Axboe #include <linux/blkdev.h>
98324aa91SJens Axboe #include <linux/blktrace_api.h>
10*320ae51fSJens Axboe #include <linux/blk-mq.h>
118324aa91SJens Axboe 
128324aa91SJens Axboe #include "blk.h"
135efd6113STejun Heo #include "blk-cgroup.h"
148324aa91SJens Axboe 
158324aa91SJens Axboe struct queue_sysfs_entry {
168324aa91SJens Axboe 	struct attribute attr;
178324aa91SJens Axboe 	ssize_t (*show)(struct request_queue *, char *);
188324aa91SJens Axboe 	ssize_t (*store)(struct request_queue *, const char *, size_t);
198324aa91SJens Axboe };
208324aa91SJens Axboe 
218324aa91SJens Axboe static ssize_t
229cb308ceSXiaotian Feng queue_var_show(unsigned long var, char *page)
238324aa91SJens Axboe {
249cb308ceSXiaotian Feng 	return sprintf(page, "%lu\n", var);
258324aa91SJens Axboe }
268324aa91SJens Axboe 
278324aa91SJens Axboe static ssize_t
288324aa91SJens Axboe queue_var_store(unsigned long *var, const char *page, size_t count)
298324aa91SJens Axboe {
30b1f3b64dSDave Reisner 	int err;
31b1f3b64dSDave Reisner 	unsigned long v;
328324aa91SJens Axboe 
33ed751e68SJingoo Han 	err = kstrtoul(page, 10, &v);
34b1f3b64dSDave Reisner 	if (err || v > UINT_MAX)
35b1f3b64dSDave Reisner 		return -EINVAL;
36b1f3b64dSDave Reisner 
37b1f3b64dSDave Reisner 	*var = v;
38b1f3b64dSDave Reisner 
398324aa91SJens Axboe 	return count;
408324aa91SJens Axboe }
418324aa91SJens Axboe 
428324aa91SJens Axboe static ssize_t queue_requests_show(struct request_queue *q, char *page)
438324aa91SJens Axboe {
448324aa91SJens Axboe 	return queue_var_show(q->nr_requests, (page));
458324aa91SJens Axboe }
468324aa91SJens Axboe 
478324aa91SJens Axboe static ssize_t
488324aa91SJens Axboe queue_requests_store(struct request_queue *q, const char *page, size_t count)
498324aa91SJens Axboe {
50a051661cSTejun Heo 	struct request_list *rl;
518324aa91SJens Axboe 	unsigned long nr;
52b8a9ae77SJens Axboe 	int ret;
53b8a9ae77SJens Axboe 
54b8a9ae77SJens Axboe 	if (!q->request_fn)
55b8a9ae77SJens Axboe 		return -EINVAL;
56b8a9ae77SJens Axboe 
57b8a9ae77SJens Axboe 	ret = queue_var_store(&nr, page, count);
58b1f3b64dSDave Reisner 	if (ret < 0)
59b1f3b64dSDave Reisner 		return ret;
60b1f3b64dSDave Reisner 
618324aa91SJens Axboe 	if (nr < BLKDEV_MIN_RQ)
628324aa91SJens Axboe 		nr = BLKDEV_MIN_RQ;
638324aa91SJens Axboe 
648324aa91SJens Axboe 	spin_lock_irq(q->queue_lock);
658324aa91SJens Axboe 	q->nr_requests = nr;
668324aa91SJens Axboe 	blk_queue_congestion_threshold(q);
678324aa91SJens Axboe 
68a051661cSTejun Heo 	/* congestion isn't cgroup aware and follows root blkcg for now */
69a051661cSTejun Heo 	rl = &q->root_rl;
70a051661cSTejun Heo 
711faa16d2SJens Axboe 	if (rl->count[BLK_RW_SYNC] >= queue_congestion_on_threshold(q))
721faa16d2SJens Axboe 		blk_set_queue_congested(q, BLK_RW_SYNC);
731faa16d2SJens Axboe 	else if (rl->count[BLK_RW_SYNC] < queue_congestion_off_threshold(q))
741faa16d2SJens Axboe 		blk_clear_queue_congested(q, BLK_RW_SYNC);
758324aa91SJens Axboe 
761faa16d2SJens Axboe 	if (rl->count[BLK_RW_ASYNC] >= queue_congestion_on_threshold(q))
771faa16d2SJens Axboe 		blk_set_queue_congested(q, BLK_RW_ASYNC);
781faa16d2SJens Axboe 	else if (rl->count[BLK_RW_ASYNC] < queue_congestion_off_threshold(q))
791faa16d2SJens Axboe 		blk_clear_queue_congested(q, BLK_RW_ASYNC);
808324aa91SJens Axboe 
81a051661cSTejun Heo 	blk_queue_for_each_rl(rl, q) {
821faa16d2SJens Axboe 		if (rl->count[BLK_RW_SYNC] >= q->nr_requests) {
835b788ce3STejun Heo 			blk_set_rl_full(rl, BLK_RW_SYNC);
8460735b63STao Ma 		} else {
855b788ce3STejun Heo 			blk_clear_rl_full(rl, BLK_RW_SYNC);
861faa16d2SJens Axboe 			wake_up(&rl->wait[BLK_RW_SYNC]);
878324aa91SJens Axboe 		}
888324aa91SJens Axboe 
891faa16d2SJens Axboe 		if (rl->count[BLK_RW_ASYNC] >= q->nr_requests) {
905b788ce3STejun Heo 			blk_set_rl_full(rl, BLK_RW_ASYNC);
9160735b63STao Ma 		} else {
925b788ce3STejun Heo 			blk_clear_rl_full(rl, BLK_RW_ASYNC);
931faa16d2SJens Axboe 			wake_up(&rl->wait[BLK_RW_ASYNC]);
948324aa91SJens Axboe 		}
95a051661cSTejun Heo 	}
96a051661cSTejun Heo 
978324aa91SJens Axboe 	spin_unlock_irq(q->queue_lock);
988324aa91SJens Axboe 	return ret;
998324aa91SJens Axboe }
1008324aa91SJens Axboe 
1018324aa91SJens Axboe static ssize_t queue_ra_show(struct request_queue *q, char *page)
1028324aa91SJens Axboe {
1039cb308ceSXiaotian Feng 	unsigned long ra_kb = q->backing_dev_info.ra_pages <<
1049cb308ceSXiaotian Feng 					(PAGE_CACHE_SHIFT - 10);
1058324aa91SJens Axboe 
1068324aa91SJens Axboe 	return queue_var_show(ra_kb, (page));
1078324aa91SJens Axboe }
1088324aa91SJens Axboe 
1098324aa91SJens Axboe static ssize_t
1108324aa91SJens Axboe queue_ra_store(struct request_queue *q, const char *page, size_t count)
1118324aa91SJens Axboe {
1128324aa91SJens Axboe 	unsigned long ra_kb;
1138324aa91SJens Axboe 	ssize_t ret = queue_var_store(&ra_kb, page, count);
1148324aa91SJens Axboe 
115b1f3b64dSDave Reisner 	if (ret < 0)
116b1f3b64dSDave Reisner 		return ret;
117b1f3b64dSDave Reisner 
1188324aa91SJens Axboe 	q->backing_dev_info.ra_pages = ra_kb >> (PAGE_CACHE_SHIFT - 10);
1198324aa91SJens Axboe 
1208324aa91SJens Axboe 	return ret;
1218324aa91SJens Axboe }
1228324aa91SJens Axboe 
1238324aa91SJens Axboe static ssize_t queue_max_sectors_show(struct request_queue *q, char *page)
1248324aa91SJens Axboe {
125ae03bf63SMartin K. Petersen 	int max_sectors_kb = queue_max_sectors(q) >> 1;
1268324aa91SJens Axboe 
1278324aa91SJens Axboe 	return queue_var_show(max_sectors_kb, (page));
1288324aa91SJens Axboe }
1298324aa91SJens Axboe 
130c77a5710SMartin K. Petersen static ssize_t queue_max_segments_show(struct request_queue *q, char *page)
131c77a5710SMartin K. Petersen {
132c77a5710SMartin K. Petersen 	return queue_var_show(queue_max_segments(q), (page));
133c77a5710SMartin K. Petersen }
134c77a5710SMartin K. Petersen 
13513f05c8dSMartin K. Petersen static ssize_t queue_max_integrity_segments_show(struct request_queue *q, char *page)
13613f05c8dSMartin K. Petersen {
13713f05c8dSMartin K. Petersen 	return queue_var_show(q->limits.max_integrity_segments, (page));
13813f05c8dSMartin K. Petersen }
13913f05c8dSMartin K. Petersen 
140c77a5710SMartin K. Petersen static ssize_t queue_max_segment_size_show(struct request_queue *q, char *page)
141c77a5710SMartin K. Petersen {
142e692cb66SMartin K. Petersen 	if (blk_queue_cluster(q))
143c77a5710SMartin K. Petersen 		return queue_var_show(queue_max_segment_size(q), (page));
144c77a5710SMartin K. Petersen 
145c77a5710SMartin K. Petersen 	return queue_var_show(PAGE_CACHE_SIZE, (page));
146c77a5710SMartin K. Petersen }
147c77a5710SMartin K. Petersen 
148e1defc4fSMartin K. Petersen static ssize_t queue_logical_block_size_show(struct request_queue *q, char *page)
149e68b903cSMartin K. Petersen {
150e1defc4fSMartin K. Petersen 	return queue_var_show(queue_logical_block_size(q), page);
151e68b903cSMartin K. Petersen }
152e68b903cSMartin K. Petersen 
153c72758f3SMartin K. Petersen static ssize_t queue_physical_block_size_show(struct request_queue *q, char *page)
154c72758f3SMartin K. Petersen {
155c72758f3SMartin K. Petersen 	return queue_var_show(queue_physical_block_size(q), page);
156c72758f3SMartin K. Petersen }
157c72758f3SMartin K. Petersen 
158c72758f3SMartin K. Petersen static ssize_t queue_io_min_show(struct request_queue *q, char *page)
159c72758f3SMartin K. Petersen {
160c72758f3SMartin K. Petersen 	return queue_var_show(queue_io_min(q), page);
161c72758f3SMartin K. Petersen }
162c72758f3SMartin K. Petersen 
163c72758f3SMartin K. Petersen static ssize_t queue_io_opt_show(struct request_queue *q, char *page)
164c72758f3SMartin K. Petersen {
165c72758f3SMartin K. Petersen 	return queue_var_show(queue_io_opt(q), page);
1668324aa91SJens Axboe }
1678324aa91SJens Axboe 
16886b37281SMartin K. Petersen static ssize_t queue_discard_granularity_show(struct request_queue *q, char *page)
16986b37281SMartin K. Petersen {
17086b37281SMartin K. Petersen 	return queue_var_show(q->limits.discard_granularity, page);
17186b37281SMartin K. Petersen }
17286b37281SMartin K. Petersen 
17386b37281SMartin K. Petersen static ssize_t queue_discard_max_show(struct request_queue *q, char *page)
17486b37281SMartin K. Petersen {
175a934a00aSMartin K. Petersen 	return sprintf(page, "%llu\n",
176a934a00aSMartin K. Petersen 		       (unsigned long long)q->limits.max_discard_sectors << 9);
17786b37281SMartin K. Petersen }
17886b37281SMartin K. Petersen 
17998262f27SMartin K. Petersen static ssize_t queue_discard_zeroes_data_show(struct request_queue *q, char *page)
18098262f27SMartin K. Petersen {
18198262f27SMartin K. Petersen 	return queue_var_show(queue_discard_zeroes_data(q), page);
18298262f27SMartin K. Petersen }
18398262f27SMartin K. Petersen 
1844363ac7cSMartin K. Petersen static ssize_t queue_write_same_max_show(struct request_queue *q, char *page)
1854363ac7cSMartin K. Petersen {
1864363ac7cSMartin K. Petersen 	return sprintf(page, "%llu\n",
1874363ac7cSMartin K. Petersen 		(unsigned long long)q->limits.max_write_same_sectors << 9);
1884363ac7cSMartin K. Petersen }
1894363ac7cSMartin K. Petersen 
1904363ac7cSMartin K. Petersen 
1918324aa91SJens Axboe static ssize_t
1928324aa91SJens Axboe queue_max_sectors_store(struct request_queue *q, const char *page, size_t count)
1938324aa91SJens Axboe {
1948324aa91SJens Axboe 	unsigned long max_sectors_kb,
195ae03bf63SMartin K. Petersen 		max_hw_sectors_kb = queue_max_hw_sectors(q) >> 1,
1968324aa91SJens Axboe 			page_kb = 1 << (PAGE_CACHE_SHIFT - 10);
1978324aa91SJens Axboe 	ssize_t ret = queue_var_store(&max_sectors_kb, page, count);
1988324aa91SJens Axboe 
199b1f3b64dSDave Reisner 	if (ret < 0)
200b1f3b64dSDave Reisner 		return ret;
201b1f3b64dSDave Reisner 
2028324aa91SJens Axboe 	if (max_sectors_kb > max_hw_sectors_kb || max_sectors_kb < page_kb)
2038324aa91SJens Axboe 		return -EINVAL;
2047c239517SWu Fengguang 
2058324aa91SJens Axboe 	spin_lock_irq(q->queue_lock);
206c295fc05SNikanth Karthikesan 	q->limits.max_sectors = max_sectors_kb << 1;
2078324aa91SJens Axboe 	spin_unlock_irq(q->queue_lock);
2088324aa91SJens Axboe 
2098324aa91SJens Axboe 	return ret;
2108324aa91SJens Axboe }
2118324aa91SJens Axboe 
2128324aa91SJens Axboe static ssize_t queue_max_hw_sectors_show(struct request_queue *q, char *page)
2138324aa91SJens Axboe {
214ae03bf63SMartin K. Petersen 	int max_hw_sectors_kb = queue_max_hw_sectors(q) >> 1;
2158324aa91SJens Axboe 
2168324aa91SJens Axboe 	return queue_var_show(max_hw_sectors_kb, (page));
2178324aa91SJens Axboe }
2188324aa91SJens Axboe 
219956bcb7cSJens Axboe #define QUEUE_SYSFS_BIT_FNS(name, flag, neg)				\
220956bcb7cSJens Axboe static ssize_t								\
221956bcb7cSJens Axboe queue_show_##name(struct request_queue *q, char *page)			\
222956bcb7cSJens Axboe {									\
223956bcb7cSJens Axboe 	int bit;							\
224956bcb7cSJens Axboe 	bit = test_bit(QUEUE_FLAG_##flag, &q->queue_flags);		\
225956bcb7cSJens Axboe 	return queue_var_show(neg ? !bit : bit, page);			\
226956bcb7cSJens Axboe }									\
227956bcb7cSJens Axboe static ssize_t								\
228956bcb7cSJens Axboe queue_store_##name(struct request_queue *q, const char *page, size_t count) \
229956bcb7cSJens Axboe {									\
230956bcb7cSJens Axboe 	unsigned long val;						\
231956bcb7cSJens Axboe 	ssize_t ret;							\
232956bcb7cSJens Axboe 	ret = queue_var_store(&val, page, count);			\
233c678ef52SArnd Bergmann 	if (ret < 0)							\
234c678ef52SArnd Bergmann 		 return ret;						\
235956bcb7cSJens Axboe 	if (neg)							\
236956bcb7cSJens Axboe 		val = !val;						\
237956bcb7cSJens Axboe 									\
238956bcb7cSJens Axboe 	spin_lock_irq(q->queue_lock);					\
239956bcb7cSJens Axboe 	if (val)							\
240956bcb7cSJens Axboe 		queue_flag_set(QUEUE_FLAG_##flag, q);			\
241956bcb7cSJens Axboe 	else								\
242956bcb7cSJens Axboe 		queue_flag_clear(QUEUE_FLAG_##flag, q);			\
243956bcb7cSJens Axboe 	spin_unlock_irq(q->queue_lock);					\
244956bcb7cSJens Axboe 	return ret;							\
2451308835fSBartlomiej Zolnierkiewicz }
2461308835fSBartlomiej Zolnierkiewicz 
247956bcb7cSJens Axboe QUEUE_SYSFS_BIT_FNS(nonrot, NONROT, 1);
248956bcb7cSJens Axboe QUEUE_SYSFS_BIT_FNS(random, ADD_RANDOM, 0);
249956bcb7cSJens Axboe QUEUE_SYSFS_BIT_FNS(iostats, IO_STAT, 0);
250956bcb7cSJens Axboe #undef QUEUE_SYSFS_BIT_FNS
2511308835fSBartlomiej Zolnierkiewicz 
252ac9fafa1SAlan D. Brunelle static ssize_t queue_nomerges_show(struct request_queue *q, char *page)
253ac9fafa1SAlan D. Brunelle {
254488991e2SAlan D. Brunelle 	return queue_var_show((blk_queue_nomerges(q) << 1) |
255488991e2SAlan D. Brunelle 			       blk_queue_noxmerges(q), page);
256ac9fafa1SAlan D. Brunelle }
257ac9fafa1SAlan D. Brunelle 
258ac9fafa1SAlan D. Brunelle static ssize_t queue_nomerges_store(struct request_queue *q, const char *page,
259ac9fafa1SAlan D. Brunelle 				    size_t count)
260ac9fafa1SAlan D. Brunelle {
261ac9fafa1SAlan D. Brunelle 	unsigned long nm;
262ac9fafa1SAlan D. Brunelle 	ssize_t ret = queue_var_store(&nm, page, count);
263ac9fafa1SAlan D. Brunelle 
264b1f3b64dSDave Reisner 	if (ret < 0)
265b1f3b64dSDave Reisner 		return ret;
266b1f3b64dSDave Reisner 
267bf0f9702SJens Axboe 	spin_lock_irq(q->queue_lock);
268bf0f9702SJens Axboe 	queue_flag_clear(QUEUE_FLAG_NOMERGES, q);
269488991e2SAlan D. Brunelle 	queue_flag_clear(QUEUE_FLAG_NOXMERGES, q);
270488991e2SAlan D. Brunelle 	if (nm == 2)
271488991e2SAlan D. Brunelle 		queue_flag_set(QUEUE_FLAG_NOMERGES, q);
272488991e2SAlan D. Brunelle 	else if (nm)
273488991e2SAlan D. Brunelle 		queue_flag_set(QUEUE_FLAG_NOXMERGES, q);
274bf0f9702SJens Axboe 	spin_unlock_irq(q->queue_lock);
2751308835fSBartlomiej Zolnierkiewicz 
276ac9fafa1SAlan D. Brunelle 	return ret;
277ac9fafa1SAlan D. Brunelle }
278ac9fafa1SAlan D. Brunelle 
279c7c22e4dSJens Axboe static ssize_t queue_rq_affinity_show(struct request_queue *q, char *page)
280c7c22e4dSJens Axboe {
2819cb308ceSXiaotian Feng 	bool set = test_bit(QUEUE_FLAG_SAME_COMP, &q->queue_flags);
2825757a6d7SDan Williams 	bool force = test_bit(QUEUE_FLAG_SAME_FORCE, &q->queue_flags);
283c7c22e4dSJens Axboe 
2845757a6d7SDan Williams 	return queue_var_show(set << force, page);
285c7c22e4dSJens Axboe }
286c7c22e4dSJens Axboe 
287c7c22e4dSJens Axboe static ssize_t
288c7c22e4dSJens Axboe queue_rq_affinity_store(struct request_queue *q, const char *page, size_t count)
289c7c22e4dSJens Axboe {
290c7c22e4dSJens Axboe 	ssize_t ret = -EINVAL;
291c7c22e4dSJens Axboe #if defined(CONFIG_USE_GENERIC_SMP_HELPERS)
292c7c22e4dSJens Axboe 	unsigned long val;
293c7c22e4dSJens Axboe 
294c7c22e4dSJens Axboe 	ret = queue_var_store(&val, page, count);
295b1f3b64dSDave Reisner 	if (ret < 0)
296b1f3b64dSDave Reisner 		return ret;
297b1f3b64dSDave Reisner 
298c7c22e4dSJens Axboe 	spin_lock_irq(q->queue_lock);
299e8037d49SEric Seppanen 	if (val == 2) {
300c7c22e4dSJens Axboe 		queue_flag_set(QUEUE_FLAG_SAME_COMP, q);
3015757a6d7SDan Williams 		queue_flag_set(QUEUE_FLAG_SAME_FORCE, q);
302e8037d49SEric Seppanen 	} else if (val == 1) {
303e8037d49SEric Seppanen 		queue_flag_set(QUEUE_FLAG_SAME_COMP, q);
304e8037d49SEric Seppanen 		queue_flag_clear(QUEUE_FLAG_SAME_FORCE, q);
305e8037d49SEric Seppanen 	} else if (val == 0) {
306c7c22e4dSJens Axboe 		queue_flag_clear(QUEUE_FLAG_SAME_COMP, q);
3075757a6d7SDan Williams 		queue_flag_clear(QUEUE_FLAG_SAME_FORCE, q);
3085757a6d7SDan Williams 	}
309c7c22e4dSJens Axboe 	spin_unlock_irq(q->queue_lock);
310c7c22e4dSJens Axboe #endif
311c7c22e4dSJens Axboe 	return ret;
312c7c22e4dSJens Axboe }
3138324aa91SJens Axboe 
3148324aa91SJens Axboe static struct queue_sysfs_entry queue_requests_entry = {
3158324aa91SJens Axboe 	.attr = {.name = "nr_requests", .mode = S_IRUGO | S_IWUSR },
3168324aa91SJens Axboe 	.show = queue_requests_show,
3178324aa91SJens Axboe 	.store = queue_requests_store,
3188324aa91SJens Axboe };
3198324aa91SJens Axboe 
3208324aa91SJens Axboe static struct queue_sysfs_entry queue_ra_entry = {
3218324aa91SJens Axboe 	.attr = {.name = "read_ahead_kb", .mode = S_IRUGO | S_IWUSR },
3228324aa91SJens Axboe 	.show = queue_ra_show,
3238324aa91SJens Axboe 	.store = queue_ra_store,
3248324aa91SJens Axboe };
3258324aa91SJens Axboe 
3268324aa91SJens Axboe static struct queue_sysfs_entry queue_max_sectors_entry = {
3278324aa91SJens Axboe 	.attr = {.name = "max_sectors_kb", .mode = S_IRUGO | S_IWUSR },
3288324aa91SJens Axboe 	.show = queue_max_sectors_show,
3298324aa91SJens Axboe 	.store = queue_max_sectors_store,
3308324aa91SJens Axboe };
3318324aa91SJens Axboe 
3328324aa91SJens Axboe static struct queue_sysfs_entry queue_max_hw_sectors_entry = {
3338324aa91SJens Axboe 	.attr = {.name = "max_hw_sectors_kb", .mode = S_IRUGO },
3348324aa91SJens Axboe 	.show = queue_max_hw_sectors_show,
3358324aa91SJens Axboe };
3368324aa91SJens Axboe 
337c77a5710SMartin K. Petersen static struct queue_sysfs_entry queue_max_segments_entry = {
338c77a5710SMartin K. Petersen 	.attr = {.name = "max_segments", .mode = S_IRUGO },
339c77a5710SMartin K. Petersen 	.show = queue_max_segments_show,
340c77a5710SMartin K. Petersen };
341c77a5710SMartin K. Petersen 
34213f05c8dSMartin K. Petersen static struct queue_sysfs_entry queue_max_integrity_segments_entry = {
34313f05c8dSMartin K. Petersen 	.attr = {.name = "max_integrity_segments", .mode = S_IRUGO },
34413f05c8dSMartin K. Petersen 	.show = queue_max_integrity_segments_show,
34513f05c8dSMartin K. Petersen };
34613f05c8dSMartin K. Petersen 
347c77a5710SMartin K. Petersen static struct queue_sysfs_entry queue_max_segment_size_entry = {
348c77a5710SMartin K. Petersen 	.attr = {.name = "max_segment_size", .mode = S_IRUGO },
349c77a5710SMartin K. Petersen 	.show = queue_max_segment_size_show,
350c77a5710SMartin K. Petersen };
351c77a5710SMartin K. Petersen 
3528324aa91SJens Axboe static struct queue_sysfs_entry queue_iosched_entry = {
3538324aa91SJens Axboe 	.attr = {.name = "scheduler", .mode = S_IRUGO | S_IWUSR },
3548324aa91SJens Axboe 	.show = elv_iosched_show,
3558324aa91SJens Axboe 	.store = elv_iosched_store,
3568324aa91SJens Axboe };
3578324aa91SJens Axboe 
358e68b903cSMartin K. Petersen static struct queue_sysfs_entry queue_hw_sector_size_entry = {
359e68b903cSMartin K. Petersen 	.attr = {.name = "hw_sector_size", .mode = S_IRUGO },
360e1defc4fSMartin K. Petersen 	.show = queue_logical_block_size_show,
361e1defc4fSMartin K. Petersen };
362e1defc4fSMartin K. Petersen 
363e1defc4fSMartin K. Petersen static struct queue_sysfs_entry queue_logical_block_size_entry = {
364e1defc4fSMartin K. Petersen 	.attr = {.name = "logical_block_size", .mode = S_IRUGO },
365e1defc4fSMartin K. Petersen 	.show = queue_logical_block_size_show,
366e68b903cSMartin K. Petersen };
367e68b903cSMartin K. Petersen 
368c72758f3SMartin K. Petersen static struct queue_sysfs_entry queue_physical_block_size_entry = {
369c72758f3SMartin K. Petersen 	.attr = {.name = "physical_block_size", .mode = S_IRUGO },
370c72758f3SMartin K. Petersen 	.show = queue_physical_block_size_show,
371c72758f3SMartin K. Petersen };
372c72758f3SMartin K. Petersen 
373c72758f3SMartin K. Petersen static struct queue_sysfs_entry queue_io_min_entry = {
374c72758f3SMartin K. Petersen 	.attr = {.name = "minimum_io_size", .mode = S_IRUGO },
375c72758f3SMartin K. Petersen 	.show = queue_io_min_show,
376c72758f3SMartin K. Petersen };
377c72758f3SMartin K. Petersen 
378c72758f3SMartin K. Petersen static struct queue_sysfs_entry queue_io_opt_entry = {
379c72758f3SMartin K. Petersen 	.attr = {.name = "optimal_io_size", .mode = S_IRUGO },
380c72758f3SMartin K. Petersen 	.show = queue_io_opt_show,
3818324aa91SJens Axboe };
3828324aa91SJens Axboe 
38386b37281SMartin K. Petersen static struct queue_sysfs_entry queue_discard_granularity_entry = {
38486b37281SMartin K. Petersen 	.attr = {.name = "discard_granularity", .mode = S_IRUGO },
38586b37281SMartin K. Petersen 	.show = queue_discard_granularity_show,
38686b37281SMartin K. Petersen };
38786b37281SMartin K. Petersen 
38886b37281SMartin K. Petersen static struct queue_sysfs_entry queue_discard_max_entry = {
38986b37281SMartin K. Petersen 	.attr = {.name = "discard_max_bytes", .mode = S_IRUGO },
39086b37281SMartin K. Petersen 	.show = queue_discard_max_show,
39186b37281SMartin K. Petersen };
39286b37281SMartin K. Petersen 
39398262f27SMartin K. Petersen static struct queue_sysfs_entry queue_discard_zeroes_data_entry = {
39498262f27SMartin K. Petersen 	.attr = {.name = "discard_zeroes_data", .mode = S_IRUGO },
39598262f27SMartin K. Petersen 	.show = queue_discard_zeroes_data_show,
39698262f27SMartin K. Petersen };
39798262f27SMartin K. Petersen 
3984363ac7cSMartin K. Petersen static struct queue_sysfs_entry queue_write_same_max_entry = {
3994363ac7cSMartin K. Petersen 	.attr = {.name = "write_same_max_bytes", .mode = S_IRUGO },
4004363ac7cSMartin K. Petersen 	.show = queue_write_same_max_show,
4014363ac7cSMartin K. Petersen };
4024363ac7cSMartin K. Petersen 
4031308835fSBartlomiej Zolnierkiewicz static struct queue_sysfs_entry queue_nonrot_entry = {
4041308835fSBartlomiej Zolnierkiewicz 	.attr = {.name = "rotational", .mode = S_IRUGO | S_IWUSR },
405956bcb7cSJens Axboe 	.show = queue_show_nonrot,
406956bcb7cSJens Axboe 	.store = queue_store_nonrot,
4071308835fSBartlomiej Zolnierkiewicz };
4081308835fSBartlomiej Zolnierkiewicz 
409ac9fafa1SAlan D. Brunelle static struct queue_sysfs_entry queue_nomerges_entry = {
410ac9fafa1SAlan D. Brunelle 	.attr = {.name = "nomerges", .mode = S_IRUGO | S_IWUSR },
411ac9fafa1SAlan D. Brunelle 	.show = queue_nomerges_show,
412ac9fafa1SAlan D. Brunelle 	.store = queue_nomerges_store,
413ac9fafa1SAlan D. Brunelle };
414ac9fafa1SAlan D. Brunelle 
415c7c22e4dSJens Axboe static struct queue_sysfs_entry queue_rq_affinity_entry = {
416c7c22e4dSJens Axboe 	.attr = {.name = "rq_affinity", .mode = S_IRUGO | S_IWUSR },
417c7c22e4dSJens Axboe 	.show = queue_rq_affinity_show,
418c7c22e4dSJens Axboe 	.store = queue_rq_affinity_store,
419c7c22e4dSJens Axboe };
420c7c22e4dSJens Axboe 
421bc58ba94SJens Axboe static struct queue_sysfs_entry queue_iostats_entry = {
422bc58ba94SJens Axboe 	.attr = {.name = "iostats", .mode = S_IRUGO | S_IWUSR },
423956bcb7cSJens Axboe 	.show = queue_show_iostats,
424956bcb7cSJens Axboe 	.store = queue_store_iostats,
425bc58ba94SJens Axboe };
426bc58ba94SJens Axboe 
427e2e1a148SJens Axboe static struct queue_sysfs_entry queue_random_entry = {
428e2e1a148SJens Axboe 	.attr = {.name = "add_random", .mode = S_IRUGO | S_IWUSR },
429956bcb7cSJens Axboe 	.show = queue_show_random,
430956bcb7cSJens Axboe 	.store = queue_store_random,
431e2e1a148SJens Axboe };
432e2e1a148SJens Axboe 
4338324aa91SJens Axboe static struct attribute *default_attrs[] = {
4348324aa91SJens Axboe 	&queue_requests_entry.attr,
4358324aa91SJens Axboe 	&queue_ra_entry.attr,
4368324aa91SJens Axboe 	&queue_max_hw_sectors_entry.attr,
4378324aa91SJens Axboe 	&queue_max_sectors_entry.attr,
438c77a5710SMartin K. Petersen 	&queue_max_segments_entry.attr,
43913f05c8dSMartin K. Petersen 	&queue_max_integrity_segments_entry.attr,
440c77a5710SMartin K. Petersen 	&queue_max_segment_size_entry.attr,
4418324aa91SJens Axboe 	&queue_iosched_entry.attr,
442e68b903cSMartin K. Petersen 	&queue_hw_sector_size_entry.attr,
443e1defc4fSMartin K. Petersen 	&queue_logical_block_size_entry.attr,
444c72758f3SMartin K. Petersen 	&queue_physical_block_size_entry.attr,
445c72758f3SMartin K. Petersen 	&queue_io_min_entry.attr,
446c72758f3SMartin K. Petersen 	&queue_io_opt_entry.attr,
44786b37281SMartin K. Petersen 	&queue_discard_granularity_entry.attr,
44886b37281SMartin K. Petersen 	&queue_discard_max_entry.attr,
44998262f27SMartin K. Petersen 	&queue_discard_zeroes_data_entry.attr,
4504363ac7cSMartin K. Petersen 	&queue_write_same_max_entry.attr,
4511308835fSBartlomiej Zolnierkiewicz 	&queue_nonrot_entry.attr,
452ac9fafa1SAlan D. Brunelle 	&queue_nomerges_entry.attr,
453c7c22e4dSJens Axboe 	&queue_rq_affinity_entry.attr,
454bc58ba94SJens Axboe 	&queue_iostats_entry.attr,
455e2e1a148SJens Axboe 	&queue_random_entry.attr,
4568324aa91SJens Axboe 	NULL,
4578324aa91SJens Axboe };
4588324aa91SJens Axboe 
4598324aa91SJens Axboe #define to_queue(atr) container_of((atr), struct queue_sysfs_entry, attr)
4608324aa91SJens Axboe 
4618324aa91SJens Axboe static ssize_t
4628324aa91SJens Axboe queue_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
4638324aa91SJens Axboe {
4648324aa91SJens Axboe 	struct queue_sysfs_entry *entry = to_queue(attr);
4658324aa91SJens Axboe 	struct request_queue *q =
4668324aa91SJens Axboe 		container_of(kobj, struct request_queue, kobj);
4678324aa91SJens Axboe 	ssize_t res;
4688324aa91SJens Axboe 
4698324aa91SJens Axboe 	if (!entry->show)
4708324aa91SJens Axboe 		return -EIO;
4718324aa91SJens Axboe 	mutex_lock(&q->sysfs_lock);
4723f3299d5SBart Van Assche 	if (blk_queue_dying(q)) {
4738324aa91SJens Axboe 		mutex_unlock(&q->sysfs_lock);
4748324aa91SJens Axboe 		return -ENOENT;
4758324aa91SJens Axboe 	}
4768324aa91SJens Axboe 	res = entry->show(q, page);
4778324aa91SJens Axboe 	mutex_unlock(&q->sysfs_lock);
4788324aa91SJens Axboe 	return res;
4798324aa91SJens Axboe }
4808324aa91SJens Axboe 
4818324aa91SJens Axboe static ssize_t
4828324aa91SJens Axboe queue_attr_store(struct kobject *kobj, struct attribute *attr,
4838324aa91SJens Axboe 		    const char *page, size_t length)
4848324aa91SJens Axboe {
4858324aa91SJens Axboe 	struct queue_sysfs_entry *entry = to_queue(attr);
4866728cb0eSJens Axboe 	struct request_queue *q;
4878324aa91SJens Axboe 	ssize_t res;
4888324aa91SJens Axboe 
4898324aa91SJens Axboe 	if (!entry->store)
4908324aa91SJens Axboe 		return -EIO;
4916728cb0eSJens Axboe 
4926728cb0eSJens Axboe 	q = container_of(kobj, struct request_queue, kobj);
4938324aa91SJens Axboe 	mutex_lock(&q->sysfs_lock);
4943f3299d5SBart Van Assche 	if (blk_queue_dying(q)) {
4958324aa91SJens Axboe 		mutex_unlock(&q->sysfs_lock);
4968324aa91SJens Axboe 		return -ENOENT;
4978324aa91SJens Axboe 	}
4988324aa91SJens Axboe 	res = entry->store(q, page, length);
4998324aa91SJens Axboe 	mutex_unlock(&q->sysfs_lock);
5008324aa91SJens Axboe 	return res;
5018324aa91SJens Axboe }
5028324aa91SJens Axboe 
503548bc8e1STejun Heo static void blk_free_queue_rcu(struct rcu_head *rcu_head)
504548bc8e1STejun Heo {
505548bc8e1STejun Heo 	struct request_queue *q = container_of(rcu_head, struct request_queue,
506548bc8e1STejun Heo 					       rcu_head);
507548bc8e1STejun Heo 	kmem_cache_free(blk_requestq_cachep, q);
508548bc8e1STejun Heo }
509548bc8e1STejun Heo 
5108324aa91SJens Axboe /**
511499337bbSAndrew Morton  * blk_release_queue: - release a &struct request_queue when it is no longer needed
512499337bbSAndrew Morton  * @kobj:    the kobj belonging to the request queue to be released
5138324aa91SJens Axboe  *
5148324aa91SJens Axboe  * Description:
515499337bbSAndrew Morton  *     blk_release_queue is the pair to blk_init_queue() or
5168324aa91SJens Axboe  *     blk_queue_make_request().  It should be called when a request queue is
5178324aa91SJens Axboe  *     being released; typically when a block device is being de-registered.
5188324aa91SJens Axboe  *     Currently, its primary task it to free all the &struct request
5198324aa91SJens Axboe  *     structures that were allocated to the queue and the queue itself.
5208324aa91SJens Axboe  *
5218324aa91SJens Axboe  * Caveat:
5228324aa91SJens Axboe  *     Hopefully the low level driver will have finished any
5238324aa91SJens Axboe  *     outstanding requests first...
5248324aa91SJens Axboe  **/
5258324aa91SJens Axboe static void blk_release_queue(struct kobject *kobj)
5268324aa91SJens Axboe {
5278324aa91SJens Axboe 	struct request_queue *q =
5288324aa91SJens Axboe 		container_of(kobj, struct request_queue, kobj);
5298324aa91SJens Axboe 
5308324aa91SJens Axboe 	blk_sync_queue(q);
5318324aa91SJens Axboe 
532e8989faeSTejun Heo 	blkcg_exit_queue(q);
533e8989faeSTejun Heo 
5347e5a8794STejun Heo 	if (q->elevator) {
5357e5a8794STejun Heo 		spin_lock_irq(q->queue_lock);
5367e5a8794STejun Heo 		ioc_clear_queue(q);
5377e5a8794STejun Heo 		spin_unlock_irq(q->queue_lock);
538777eb1bfSHannes Reinecke 		elevator_exit(q->elevator);
5397e5a8794STejun Heo 	}
540777eb1bfSHannes Reinecke 
541a051661cSTejun Heo 	blk_exit_rl(&q->root_rl);
5428324aa91SJens Axboe 
5438324aa91SJens Axboe 	if (q->queue_tags)
5448324aa91SJens Axboe 		__blk_queue_free_tags(q);
5458324aa91SJens Axboe 
546*320ae51fSJens Axboe 	percpu_counter_destroy(&q->mq_usage_counter);
547*320ae51fSJens Axboe 
548*320ae51fSJens Axboe 	if (q->mq_ops)
549*320ae51fSJens Axboe 		blk_mq_free_queue(q);
550*320ae51fSJens Axboe 
5518324aa91SJens Axboe 	blk_trace_shutdown(q);
5528324aa91SJens Axboe 
5538324aa91SJens Axboe 	bdi_destroy(&q->backing_dev_info);
554a73f730dSTejun Heo 
555a73f730dSTejun Heo 	ida_simple_remove(&blk_queue_ida, q->id);
556548bc8e1STejun Heo 	call_rcu(&q->rcu_head, blk_free_queue_rcu);
5578324aa91SJens Axboe }
5588324aa91SJens Axboe 
55952cf25d0SEmese Revfy static const struct sysfs_ops queue_sysfs_ops = {
5608324aa91SJens Axboe 	.show	= queue_attr_show,
5618324aa91SJens Axboe 	.store	= queue_attr_store,
5628324aa91SJens Axboe };
5638324aa91SJens Axboe 
5648324aa91SJens Axboe struct kobj_type blk_queue_ktype = {
5658324aa91SJens Axboe 	.sysfs_ops	= &queue_sysfs_ops,
5668324aa91SJens Axboe 	.default_attrs	= default_attrs,
5678324aa91SJens Axboe 	.release	= blk_release_queue,
5688324aa91SJens Axboe };
5698324aa91SJens Axboe 
5708324aa91SJens Axboe int blk_register_queue(struct gendisk *disk)
5718324aa91SJens Axboe {
5728324aa91SJens Axboe 	int ret;
5731d54ad6dSLi Zefan 	struct device *dev = disk_to_dev(disk);
5748324aa91SJens Axboe 	struct request_queue *q = disk->queue;
5758324aa91SJens Axboe 
576fb199746SAkinobu Mita 	if (WARN_ON(!q))
5778324aa91SJens Axboe 		return -ENXIO;
5788324aa91SJens Axboe 
579749fefe6STejun Heo 	/*
580749fefe6STejun Heo 	 * Initialization must be complete by now.  Finish the initial
581749fefe6STejun Heo 	 * bypass from queue allocation.
582749fefe6STejun Heo 	 */
583749fefe6STejun Heo 	blk_queue_bypass_end(q);
584*320ae51fSJens Axboe 	queue_flag_set_unlocked(QUEUE_FLAG_INIT_DONE, q);
585749fefe6STejun Heo 
5861d54ad6dSLi Zefan 	ret = blk_trace_init_sysfs(dev);
5871d54ad6dSLi Zefan 	if (ret)
5881d54ad6dSLi Zefan 		return ret;
5891d54ad6dSLi Zefan 
590c9059598SLinus Torvalds 	ret = kobject_add(&q->kobj, kobject_get(&dev->kobj), "%s", "queue");
591ed5302d3SLiu Yuan 	if (ret < 0) {
592ed5302d3SLiu Yuan 		blk_trace_remove_sysfs(dev);
5938324aa91SJens Axboe 		return ret;
594ed5302d3SLiu Yuan 	}
5958324aa91SJens Axboe 
5968324aa91SJens Axboe 	kobject_uevent(&q->kobj, KOBJ_ADD);
5978324aa91SJens Axboe 
598*320ae51fSJens Axboe 	if (q->mq_ops)
599*320ae51fSJens Axboe 		blk_mq_register_disk(disk);
600*320ae51fSJens Axboe 
601cd43e26fSMartin K. Petersen 	if (!q->request_fn)
602cd43e26fSMartin K. Petersen 		return 0;
603cd43e26fSMartin K. Petersen 
6048324aa91SJens Axboe 	ret = elv_register_queue(q);
6058324aa91SJens Axboe 	if (ret) {
6068324aa91SJens Axboe 		kobject_uevent(&q->kobj, KOBJ_REMOVE);
6078324aa91SJens Axboe 		kobject_del(&q->kobj);
60880656b67SLiu Yuan 		blk_trace_remove_sysfs(dev);
609c87ffbb8SXiaotian Feng 		kobject_put(&dev->kobj);
6108324aa91SJens Axboe 		return ret;
6118324aa91SJens Axboe 	}
6128324aa91SJens Axboe 
6138324aa91SJens Axboe 	return 0;
6148324aa91SJens Axboe }
6158324aa91SJens Axboe 
6168324aa91SJens Axboe void blk_unregister_queue(struct gendisk *disk)
6178324aa91SJens Axboe {
6188324aa91SJens Axboe 	struct request_queue *q = disk->queue;
6198324aa91SJens Axboe 
620fb199746SAkinobu Mita 	if (WARN_ON(!q))
621fb199746SAkinobu Mita 		return;
622fb199746SAkinobu Mita 
623*320ae51fSJens Axboe 	if (q->mq_ops)
624*320ae51fSJens Axboe 		blk_mq_unregister_disk(disk);
625*320ae51fSJens Axboe 
62648c0d4d4SZdenek Kabelac 	if (q->request_fn)
6278324aa91SJens Axboe 		elv_unregister_queue(q);
6288324aa91SJens Axboe 
6298324aa91SJens Axboe 	kobject_uevent(&q->kobj, KOBJ_REMOVE);
6308324aa91SJens Axboe 	kobject_del(&q->kobj);
63148c0d4d4SZdenek Kabelac 	blk_trace_remove_sysfs(disk_to_dev(disk));
632ed9e1982STejun Heo 	kobject_put(&disk_to_dev(disk)->kobj);
6338324aa91SJens Axboe }
634