diff options
-rw-r--r-- | Documentation/block/queue-sysfs.txt | 9 | ||||
-rw-r--r-- | block/bio.c | 11 | ||||
-rw-r--r-- | block/blk-core.c | 5 | ||||
-rw-r--r-- | block/blk-lib.c | 178 | ||||
-rw-r--r-- | block/blk-mq-tag.c | 12 | ||||
-rw-r--r-- | block/blk-mq.c | 5 | ||||
-rw-r--r-- | block/blk-settings.c | 26 | ||||
-rw-r--r-- | block/blk-sysfs.c | 39 | ||||
-rw-r--r-- | block/blk-throttle.c | 5 | ||||
-rw-r--r-- | drivers/block/skd_main.c | 2 | ||||
-rw-r--r-- | drivers/scsi/sd.c | 2 | ||||
-rw-r--r-- | include/linux/bio.h | 11 | ||||
-rw-r--r-- | include/linux/blk-mq.h | 2 | ||||
-rw-r--r-- | include/linux/blk_types.h | 2 | ||||
-rw-r--r-- | include/linux/blkdev.h | 7 | ||||
-rw-r--r-- | include/linux/blktrace_api.h | 9 | ||||
-rw-r--r-- | kernel/trace/blktrace.c | 2 |
17 files changed, 190 insertions, 137 deletions
diff --git a/Documentation/block/queue-sysfs.txt b/Documentation/block/queue-sysfs.txt index e5d914845be6..dce25d848d92 100644 --- a/Documentation/block/queue-sysfs.txt +++ b/Documentation/block/queue-sysfs.txt | |||
@@ -141,6 +141,15 @@ control of this block device to that new IO scheduler. Note that writing | |||
141 | an IO scheduler name to this file will attempt to load that IO scheduler | 141 | an IO scheduler name to this file will attempt to load that IO scheduler |
142 | module, if it isn't already present in the system. | 142 | module, if it isn't already present in the system. |
143 | 143 | ||
144 | write_cache (RW) | ||
145 | ---------------- | ||
146 | When read, this file will display whether the device has write back | ||
147 | caching enabled or not. It will return "write back" for the former | ||
148 | case, and "write through" for the latter. Writing to this file can | ||
149 | change the kernels view of the device, but it doesn't alter the | ||
150 | device state. This means that it might not be safe to toggle the | ||
151 | setting from "write back" to "write through", since that will also | ||
152 | eliminate cache flushes issued by the kernel. | ||
144 | 153 | ||
145 | 154 | ||
146 | Jens Axboe <jens.axboe@oracle.com>, February 2009 | 155 | Jens Axboe <jens.axboe@oracle.com>, February 2009 |
diff --git a/block/bio.c b/block/bio.c index 807d25e466ec..0e4aa42bc30d 100644 --- a/block/bio.c +++ b/block/bio.c | |||
@@ -311,17 +311,6 @@ static void bio_chain_endio(struct bio *bio) | |||
311 | bio_endio(__bio_chain_endio(bio)); | 311 | bio_endio(__bio_chain_endio(bio)); |
312 | } | 312 | } |
313 | 313 | ||
314 | /* | ||
315 | * Increment chain count for the bio. Make sure the CHAIN flag update | ||
316 | * is visible before the raised count. | ||
317 | */ | ||
318 | static inline void bio_inc_remaining(struct bio *bio) | ||
319 | { | ||
320 | bio_set_flag(bio, BIO_CHAIN); | ||
321 | smp_mb__before_atomic(); | ||
322 | atomic_inc(&bio->__bi_remaining); | ||
323 | } | ||
324 | |||
325 | /** | 314 | /** |
326 | * bio_chain - chain bio completions | 315 | * bio_chain - chain bio completions |
327 | * @bio: the target bio | 316 | * @bio: the target bio |
diff --git a/block/blk-core.c b/block/blk-core.c index b60537b2c35b..c50227796a26 100644 --- a/block/blk-core.c +++ b/block/blk-core.c | |||
@@ -1523,6 +1523,7 @@ EXPORT_SYMBOL(blk_put_request); | |||
1523 | * blk_add_request_payload - add a payload to a request | 1523 | * blk_add_request_payload - add a payload to a request |
1524 | * @rq: request to update | 1524 | * @rq: request to update |
1525 | * @page: page backing the payload | 1525 | * @page: page backing the payload |
1526 | * @offset: offset in page | ||
1526 | * @len: length of the payload. | 1527 | * @len: length of the payload. |
1527 | * | 1528 | * |
1528 | * This allows to later add a payload to an already submitted request by | 1529 | * This allows to later add a payload to an already submitted request by |
@@ -1533,12 +1534,12 @@ EXPORT_SYMBOL(blk_put_request); | |||
1533 | * discard requests should ever use it. | 1534 | * discard requests should ever use it. |
1534 | */ | 1535 | */ |
1535 | void blk_add_request_payload(struct request *rq, struct page *page, | 1536 | void blk_add_request_payload(struct request *rq, struct page *page, |
1536 | unsigned int len) | 1537 | int offset, unsigned int len) |
1537 | { | 1538 | { |
1538 | struct bio *bio = rq->bio; | 1539 | struct bio *bio = rq->bio; |
1539 | 1540 | ||
1540 | bio->bi_io_vec->bv_page = page; | 1541 | bio->bi_io_vec->bv_page = page; |
1541 | bio->bi_io_vec->bv_offset = 0; | 1542 | bio->bi_io_vec->bv_offset = offset; |
1542 | bio->bi_io_vec->bv_len = len; | 1543 | bio->bi_io_vec->bv_len = len; |
1543 | 1544 | ||
1544 | bio->bi_iter.bi_size = len; | 1545 | bio->bi_iter.bi_size = len; |
diff --git a/block/blk-lib.c b/block/blk-lib.c index 9ebf65379556..23d7f301a196 100644 --- a/block/blk-lib.c +++ b/block/blk-lib.c | |||
@@ -9,82 +9,46 @@ | |||
9 | 9 | ||
10 | #include "blk.h" | 10 | #include "blk.h" |
11 | 11 | ||
12 | struct bio_batch { | 12 | static struct bio *next_bio(struct bio *bio, int rw, unsigned int nr_pages, |
13 | atomic_t done; | 13 | gfp_t gfp) |
14 | int error; | ||
15 | struct completion *wait; | ||
16 | }; | ||
17 | |||
18 | static void bio_batch_end_io(struct bio *bio) | ||
19 | { | 14 | { |
20 | struct bio_batch *bb = bio->bi_private; | 15 | struct bio *new = bio_alloc(gfp, nr_pages); |
16 | |||
17 | if (bio) { | ||
18 | bio_chain(bio, new); | ||
19 | submit_bio(rw, bio); | ||
20 | } | ||
21 | 21 | ||
22 | if (bio->bi_error && bio->bi_error != -EOPNOTSUPP) | 22 | return new; |
23 | bb->error = bio->bi_error; | ||
24 | if (atomic_dec_and_test(&bb->done)) | ||
25 | complete(bb->wait); | ||
26 | bio_put(bio); | ||
27 | } | 23 | } |
28 | 24 | ||
29 | /** | 25 | int __blkdev_issue_discard(struct block_device *bdev, sector_t sector, |
30 | * blkdev_issue_discard - queue a discard | 26 | sector_t nr_sects, gfp_t gfp_mask, int type, struct bio **biop) |
31 | * @bdev: blockdev to issue discard for | ||
32 | * @sector: start sector | ||
33 | * @nr_sects: number of sectors to discard | ||
34 | * @gfp_mask: memory allocation flags (for bio_alloc) | ||
35 | * @flags: BLKDEV_IFL_* flags to control behaviour | ||
36 | * | ||
37 | * Description: | ||
38 | * Issue a discard request for the sectors in question. | ||
39 | */ | ||
40 | int blkdev_issue_discard(struct block_device *bdev, sector_t sector, | ||
41 | sector_t nr_sects, gfp_t gfp_mask, unsigned long flags) | ||
42 | { | 27 | { |
43 | DECLARE_COMPLETION_ONSTACK(wait); | ||
44 | struct request_queue *q = bdev_get_queue(bdev); | 28 | struct request_queue *q = bdev_get_queue(bdev); |
45 | int type = REQ_WRITE | REQ_DISCARD; | 29 | struct bio *bio = *biop; |
46 | unsigned int granularity; | 30 | unsigned int granularity; |
47 | int alignment; | 31 | int alignment; |
48 | struct bio_batch bb; | ||
49 | struct bio *bio; | ||
50 | int ret = 0; | ||
51 | struct blk_plug plug; | ||
52 | 32 | ||
53 | if (!q) | 33 | if (!q) |
54 | return -ENXIO; | 34 | return -ENXIO; |
55 | |||
56 | if (!blk_queue_discard(q)) | 35 | if (!blk_queue_discard(q)) |
57 | return -EOPNOTSUPP; | 36 | return -EOPNOTSUPP; |
37 | if ((type & REQ_SECURE) && !blk_queue_secdiscard(q)) | ||
38 | return -EOPNOTSUPP; | ||
58 | 39 | ||
59 | /* Zero-sector (unknown) and one-sector granularities are the same. */ | 40 | /* Zero-sector (unknown) and one-sector granularities are the same. */ |
60 | granularity = max(q->limits.discard_granularity >> 9, 1U); | 41 | granularity = max(q->limits.discard_granularity >> 9, 1U); |
61 | alignment = (bdev_discard_alignment(bdev) >> 9) % granularity; | 42 | alignment = (bdev_discard_alignment(bdev) >> 9) % granularity; |
62 | 43 | ||
63 | if (flags & BLKDEV_DISCARD_SECURE) { | ||
64 | if (!blk_queue_secdiscard(q)) | ||
65 | return -EOPNOTSUPP; | ||
66 | type |= REQ_SECURE; | ||
67 | } | ||
68 | |||
69 | atomic_set(&bb.done, 1); | ||
70 | bb.error = 0; | ||
71 | bb.wait = &wait; | ||
72 | |||
73 | blk_start_plug(&plug); | ||
74 | while (nr_sects) { | 44 | while (nr_sects) { |
75 | unsigned int req_sects; | 45 | unsigned int req_sects; |
76 | sector_t end_sect, tmp; | 46 | sector_t end_sect, tmp; |
77 | 47 | ||
78 | bio = bio_alloc(gfp_mask, 1); | ||
79 | if (!bio) { | ||
80 | ret = -ENOMEM; | ||
81 | break; | ||
82 | } | ||
83 | |||
84 | /* Make sure bi_size doesn't overflow */ | 48 | /* Make sure bi_size doesn't overflow */ |
85 | req_sects = min_t(sector_t, nr_sects, UINT_MAX >> 9); | 49 | req_sects = min_t(sector_t, nr_sects, UINT_MAX >> 9); |
86 | 50 | ||
87 | /* | 51 | /** |
88 | * If splitting a request, and the next starting sector would be | 52 | * If splitting a request, and the next starting sector would be |
89 | * misaligned, stop the discard at the previous aligned sector. | 53 | * misaligned, stop the discard at the previous aligned sector. |
90 | */ | 54 | */ |
@@ -98,18 +62,14 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector, | |||
98 | req_sects = end_sect - sector; | 62 | req_sects = end_sect - sector; |
99 | } | 63 | } |
100 | 64 | ||
65 | bio = next_bio(bio, type, 1, gfp_mask); | ||
101 | bio->bi_iter.bi_sector = sector; | 66 | bio->bi_iter.bi_sector = sector; |
102 | bio->bi_end_io = bio_batch_end_io; | ||
103 | bio->bi_bdev = bdev; | 67 | bio->bi_bdev = bdev; |
104 | bio->bi_private = &bb; | ||
105 | 68 | ||
106 | bio->bi_iter.bi_size = req_sects << 9; | 69 | bio->bi_iter.bi_size = req_sects << 9; |
107 | nr_sects -= req_sects; | 70 | nr_sects -= req_sects; |
108 | sector = end_sect; | 71 | sector = end_sect; |
109 | 72 | ||
110 | atomic_inc(&bb.done); | ||
111 | submit_bio(type, bio); | ||
112 | |||
113 | /* | 73 | /* |
114 | * We can loop for a long time in here, if someone does | 74 | * We can loop for a long time in here, if someone does |
115 | * full device discards (like mkfs). Be nice and allow | 75 | * full device discards (like mkfs). Be nice and allow |
@@ -118,14 +78,44 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector, | |||
118 | */ | 78 | */ |
119 | cond_resched(); | 79 | cond_resched(); |
120 | } | 80 | } |
121 | blk_finish_plug(&plug); | ||
122 | 81 | ||
123 | /* Wait for bios in-flight */ | 82 | *biop = bio; |
124 | if (!atomic_dec_and_test(&bb.done)) | 83 | return 0; |
125 | wait_for_completion_io(&wait); | 84 | } |
85 | EXPORT_SYMBOL(__blkdev_issue_discard); | ||
86 | |||
87 | /** | ||
88 | * blkdev_issue_discard - queue a discard | ||
89 | * @bdev: blockdev to issue discard for | ||
90 | * @sector: start sector | ||
91 | * @nr_sects: number of sectors to discard | ||
92 | * @gfp_mask: memory allocation flags (for bio_alloc) | ||
93 | * @flags: BLKDEV_IFL_* flags to control behaviour | ||
94 | * | ||
95 | * Description: | ||
96 | * Issue a discard request for the sectors in question. | ||
97 | */ | ||
98 | int blkdev_issue_discard(struct block_device *bdev, sector_t sector, | ||
99 | sector_t nr_sects, gfp_t gfp_mask, unsigned long flags) | ||
100 | { | ||
101 | int type = REQ_WRITE | REQ_DISCARD; | ||
102 | struct bio *bio = NULL; | ||
103 | struct blk_plug plug; | ||
104 | int ret; | ||
105 | |||
106 | if (flags & BLKDEV_DISCARD_SECURE) | ||
107 | type |= REQ_SECURE; | ||
108 | |||
109 | blk_start_plug(&plug); | ||
110 | ret = __blkdev_issue_discard(bdev, sector, nr_sects, gfp_mask, type, | ||
111 | &bio); | ||
112 | if (!ret && bio) { | ||
113 | ret = submit_bio_wait(type, bio); | ||
114 | if (ret == -EOPNOTSUPP) | ||
115 | ret = 0; | ||
116 | } | ||
117 | blk_finish_plug(&plug); | ||
126 | 118 | ||
127 | if (bb.error) | ||
128 | return bb.error; | ||
129 | return ret; | 119 | return ret; |
130 | } | 120 | } |
131 | EXPORT_SYMBOL(blkdev_issue_discard); | 121 | EXPORT_SYMBOL(blkdev_issue_discard); |
@@ -145,11 +135,9 @@ int blkdev_issue_write_same(struct block_device *bdev, sector_t sector, | |||
145 | sector_t nr_sects, gfp_t gfp_mask, | 135 | sector_t nr_sects, gfp_t gfp_mask, |
146 | struct page *page) | 136 | struct page *page) |
147 | { | 137 | { |
148 | DECLARE_COMPLETION_ONSTACK(wait); | ||
149 | struct request_queue *q = bdev_get_queue(bdev); | 138 | struct request_queue *q = bdev_get_queue(bdev); |
150 | unsigned int max_write_same_sectors; | 139 | unsigned int max_write_same_sectors; |
151 | struct bio_batch bb; | 140 | struct bio *bio = NULL; |
152 | struct bio *bio; | ||
153 | int ret = 0; | 141 | int ret = 0; |
154 | 142 | ||
155 | if (!q) | 143 | if (!q) |
@@ -158,21 +146,10 @@ int blkdev_issue_write_same(struct block_device *bdev, sector_t sector, | |||
158 | /* Ensure that max_write_same_sectors doesn't overflow bi_size */ | 146 | /* Ensure that max_write_same_sectors doesn't overflow bi_size */ |
159 | max_write_same_sectors = UINT_MAX >> 9; | 147 | max_write_same_sectors = UINT_MAX >> 9; |
160 | 148 | ||
161 | atomic_set(&bb.done, 1); | ||
162 | bb.error = 0; | ||
163 | bb.wait = &wait; | ||
164 | |||
165 | while (nr_sects) { | 149 | while (nr_sects) { |
166 | bio = bio_alloc(gfp_mask, 1); | 150 | bio = next_bio(bio, REQ_WRITE | REQ_WRITE_SAME, 1, gfp_mask); |
167 | if (!bio) { | ||
168 | ret = -ENOMEM; | ||
169 | break; | ||
170 | } | ||
171 | |||
172 | bio->bi_iter.bi_sector = sector; | 151 | bio->bi_iter.bi_sector = sector; |
173 | bio->bi_end_io = bio_batch_end_io; | ||
174 | bio->bi_bdev = bdev; | 152 | bio->bi_bdev = bdev; |
175 | bio->bi_private = &bb; | ||
176 | bio->bi_vcnt = 1; | 153 | bio->bi_vcnt = 1; |
177 | bio->bi_io_vec->bv_page = page; | 154 | bio->bi_io_vec->bv_page = page; |
178 | bio->bi_io_vec->bv_offset = 0; | 155 | bio->bi_io_vec->bv_offset = 0; |
@@ -186,18 +163,11 @@ int blkdev_issue_write_same(struct block_device *bdev, sector_t sector, | |||
186 | bio->bi_iter.bi_size = nr_sects << 9; | 163 | bio->bi_iter.bi_size = nr_sects << 9; |
187 | nr_sects = 0; | 164 | nr_sects = 0; |
188 | } | 165 | } |
189 | |||
190 | atomic_inc(&bb.done); | ||
191 | submit_bio(REQ_WRITE | REQ_WRITE_SAME, bio); | ||
192 | } | 166 | } |
193 | 167 | ||
194 | /* Wait for bios in-flight */ | 168 | if (bio) |
195 | if (!atomic_dec_and_test(&bb.done)) | 169 | ret = submit_bio_wait(REQ_WRITE | REQ_WRITE_SAME, bio); |
196 | wait_for_completion_io(&wait); | 170 | return ret != -EOPNOTSUPP ? ret : 0; |
197 | |||
198 | if (bb.error) | ||
199 | return bb.error; | ||
200 | return ret; | ||
201 | } | 171 | } |
202 | EXPORT_SYMBOL(blkdev_issue_write_same); | 172 | EXPORT_SYMBOL(blkdev_issue_write_same); |
203 | 173 | ||
@@ -216,28 +186,15 @@ static int __blkdev_issue_zeroout(struct block_device *bdev, sector_t sector, | |||
216 | sector_t nr_sects, gfp_t gfp_mask) | 186 | sector_t nr_sects, gfp_t gfp_mask) |
217 | { | 187 | { |
218 | int ret; | 188 | int ret; |
219 | struct bio *bio; | 189 | struct bio *bio = NULL; |
220 | struct bio_batch bb; | ||
221 | unsigned int sz; | 190 | unsigned int sz; |
222 | DECLARE_COMPLETION_ONSTACK(wait); | ||
223 | |||
224 | atomic_set(&bb.done, 1); | ||
225 | bb.error = 0; | ||
226 | bb.wait = &wait; | ||
227 | 191 | ||
228 | ret = 0; | ||
229 | while (nr_sects != 0) { | 192 | while (nr_sects != 0) { |
230 | bio = bio_alloc(gfp_mask, | 193 | bio = next_bio(bio, WRITE, |
231 | min(nr_sects, (sector_t)BIO_MAX_PAGES)); | 194 | min(nr_sects, (sector_t)BIO_MAX_PAGES), |
232 | if (!bio) { | 195 | gfp_mask); |
233 | ret = -ENOMEM; | ||
234 | break; | ||
235 | } | ||
236 | |||
237 | bio->bi_iter.bi_sector = sector; | 196 | bio->bi_iter.bi_sector = sector; |
238 | bio->bi_bdev = bdev; | 197 | bio->bi_bdev = bdev; |
239 | bio->bi_end_io = bio_batch_end_io; | ||
240 | bio->bi_private = &bb; | ||
241 | 198 | ||
242 | while (nr_sects != 0) { | 199 | while (nr_sects != 0) { |
243 | sz = min((sector_t) PAGE_SIZE >> 9 , nr_sects); | 200 | sz = min((sector_t) PAGE_SIZE >> 9 , nr_sects); |
@@ -247,18 +204,11 @@ static int __blkdev_issue_zeroout(struct block_device *bdev, sector_t sector, | |||
247 | if (ret < (sz << 9)) | 204 | if (ret < (sz << 9)) |
248 | break; | 205 | break; |
249 | } | 206 | } |
250 | ret = 0; | ||
251 | atomic_inc(&bb.done); | ||
252 | submit_bio(WRITE, bio); | ||
253 | } | 207 | } |
254 | 208 | ||
255 | /* Wait for bios in-flight */ | 209 | if (bio) |
256 | if (!atomic_dec_and_test(&bb.done)) | 210 | return submit_bio_wait(WRITE, bio); |
257 | wait_for_completion_io(&wait); | 211 | return 0; |
258 | |||
259 | if (bb.error) | ||
260 | return bb.error; | ||
261 | return ret; | ||
262 | } | 212 | } |
263 | 213 | ||
264 | /** | 214 | /** |
diff --git a/block/blk-mq-tag.c b/block/blk-mq-tag.c index abdbb47405cb..2fd04286f103 100644 --- a/block/blk-mq-tag.c +++ b/block/blk-mq-tag.c | |||
@@ -474,6 +474,18 @@ void blk_mq_all_tag_busy_iter(struct blk_mq_tags *tags, busy_tag_iter_fn *fn, | |||
474 | } | 474 | } |
475 | EXPORT_SYMBOL(blk_mq_all_tag_busy_iter); | 475 | EXPORT_SYMBOL(blk_mq_all_tag_busy_iter); |
476 | 476 | ||
477 | void blk_mq_tagset_busy_iter(struct blk_mq_tag_set *tagset, | ||
478 | busy_tag_iter_fn *fn, void *priv) | ||
479 | { | ||
480 | int i; | ||
481 | |||
482 | for (i = 0; i < tagset->nr_hw_queues; i++) { | ||
483 | if (tagset->tags && tagset->tags[i]) | ||
484 | blk_mq_all_tag_busy_iter(tagset->tags[i], fn, priv); | ||
485 | } | ||
486 | } | ||
487 | EXPORT_SYMBOL(blk_mq_tagset_busy_iter); | ||
488 | |||
477 | void blk_mq_queue_tag_busy_iter(struct request_queue *q, busy_iter_fn *fn, | 489 | void blk_mq_queue_tag_busy_iter(struct request_queue *q, busy_iter_fn *fn, |
478 | void *priv) | 490 | void *priv) |
479 | { | 491 | { |
diff --git a/block/blk-mq.c b/block/blk-mq.c index 1699baf39b78..7df9c9263b21 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c | |||
@@ -1122,8 +1122,7 @@ static void blk_mq_bio_to_request(struct request *rq, struct bio *bio) | |||
1122 | { | 1122 | { |
1123 | init_request_from_bio(rq, bio); | 1123 | init_request_from_bio(rq, bio); |
1124 | 1124 | ||
1125 | if (blk_do_io_stat(rq)) | 1125 | blk_account_io_start(rq, 1); |
1126 | blk_account_io_start(rq, 1); | ||
1127 | } | 1126 | } |
1128 | 1127 | ||
1129 | static inline bool hctx_allow_merges(struct blk_mq_hw_ctx *hctx) | 1128 | static inline bool hctx_allow_merges(struct blk_mq_hw_ctx *hctx) |
@@ -1496,7 +1495,7 @@ static struct blk_mq_tags *blk_mq_init_rq_map(struct blk_mq_tag_set *set, | |||
1496 | int to_do; | 1495 | int to_do; |
1497 | void *p; | 1496 | void *p; |
1498 | 1497 | ||
1499 | while (left < order_to_size(this_order - 1) && this_order) | 1498 | while (this_order && left < order_to_size(this_order - 1)) |
1500 | this_order--; | 1499 | this_order--; |
1501 | 1500 | ||
1502 | do { | 1501 | do { |
diff --git a/block/blk-settings.c b/block/blk-settings.c index 331e4eee0dda..c903bee43cf8 100644 --- a/block/blk-settings.c +++ b/block/blk-settings.c | |||
@@ -846,6 +846,32 @@ void blk_queue_flush_queueable(struct request_queue *q, bool queueable) | |||
846 | } | 846 | } |
847 | EXPORT_SYMBOL_GPL(blk_queue_flush_queueable); | 847 | EXPORT_SYMBOL_GPL(blk_queue_flush_queueable); |
848 | 848 | ||
849 | /** | ||
850 | * blk_queue_write_cache - configure queue's write cache | ||
851 | * @q: the request queue for the device | ||
852 | * @wc: write back cache on or off | ||
853 | * @fua: device supports FUA writes, if true | ||
854 | * | ||
855 | * Tell the block layer about the write cache of @q. | ||
856 | */ | ||
857 | void blk_queue_write_cache(struct request_queue *q, bool wc, bool fua) | ||
858 | { | ||
859 | spin_lock_irq(q->queue_lock); | ||
860 | if (wc) { | ||
861 | queue_flag_set(QUEUE_FLAG_WC, q); | ||
862 | q->flush_flags = REQ_FLUSH; | ||
863 | } else | ||
864 | queue_flag_clear(QUEUE_FLAG_WC, q); | ||
865 | if (fua) { | ||
866 | if (wc) | ||
867 | q->flush_flags |= REQ_FUA; | ||
868 | queue_flag_set(QUEUE_FLAG_FUA, q); | ||
869 | } else | ||
870 | queue_flag_clear(QUEUE_FLAG_FUA, q); | ||
871 | spin_unlock_irq(q->queue_lock); | ||
872 | } | ||
873 | EXPORT_SYMBOL_GPL(blk_queue_write_cache); | ||
874 | |||
849 | static int __init blk_settings_init(void) | 875 | static int __init blk_settings_init(void) |
850 | { | 876 | { |
851 | blk_max_low_pfn = max_low_pfn - 1; | 877 | blk_max_low_pfn = max_low_pfn - 1; |
diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c index 995b58d46ed1..99205965f559 100644 --- a/block/blk-sysfs.c +++ b/block/blk-sysfs.c | |||
@@ -347,6 +347,38 @@ static ssize_t queue_poll_store(struct request_queue *q, const char *page, | |||
347 | return ret; | 347 | return ret; |
348 | } | 348 | } |
349 | 349 | ||
350 | static ssize_t queue_wc_show(struct request_queue *q, char *page) | ||
351 | { | ||
352 | if (test_bit(QUEUE_FLAG_WC, &q->queue_flags)) | ||
353 | return sprintf(page, "write back\n"); | ||
354 | |||
355 | return sprintf(page, "write through\n"); | ||
356 | } | ||
357 | |||
358 | static ssize_t queue_wc_store(struct request_queue *q, const char *page, | ||
359 | size_t count) | ||
360 | { | ||
361 | int set = -1; | ||
362 | |||
363 | if (!strncmp(page, "write back", 10)) | ||
364 | set = 1; | ||
365 | else if (!strncmp(page, "write through", 13) || | ||
366 | !strncmp(page, "none", 4)) | ||
367 | set = 0; | ||
368 | |||
369 | if (set == -1) | ||
370 | return -EINVAL; | ||
371 | |||
372 | spin_lock_irq(q->queue_lock); | ||
373 | if (set) | ||
374 | queue_flag_set(QUEUE_FLAG_WC, q); | ||
375 | else | ||
376 | queue_flag_clear(QUEUE_FLAG_WC, q); | ||
377 | spin_unlock_irq(q->queue_lock); | ||
378 | |||
379 | return count; | ||
380 | } | ||
381 | |||
350 | static struct queue_sysfs_entry queue_requests_entry = { | 382 | static struct queue_sysfs_entry queue_requests_entry = { |
351 | .attr = {.name = "nr_requests", .mode = S_IRUGO | S_IWUSR }, | 383 | .attr = {.name = "nr_requests", .mode = S_IRUGO | S_IWUSR }, |
352 | .show = queue_requests_show, | 384 | .show = queue_requests_show, |
@@ -478,6 +510,12 @@ static struct queue_sysfs_entry queue_poll_entry = { | |||
478 | .store = queue_poll_store, | 510 | .store = queue_poll_store, |
479 | }; | 511 | }; |
480 | 512 | ||
513 | static struct queue_sysfs_entry queue_wc_entry = { | ||
514 | .attr = {.name = "write_cache", .mode = S_IRUGO | S_IWUSR }, | ||
515 | .show = queue_wc_show, | ||
516 | .store = queue_wc_store, | ||
517 | }; | ||
518 | |||
481 | static struct attribute *default_attrs[] = { | 519 | static struct attribute *default_attrs[] = { |
482 | &queue_requests_entry.attr, | 520 | &queue_requests_entry.attr, |
483 | &queue_ra_entry.attr, | 521 | &queue_ra_entry.attr, |
@@ -503,6 +541,7 @@ static struct attribute *default_attrs[] = { | |||
503 | &queue_iostats_entry.attr, | 541 | &queue_iostats_entry.attr, |
504 | &queue_random_entry.attr, | 542 | &queue_random_entry.attr, |
505 | &queue_poll_entry.attr, | 543 | &queue_poll_entry.attr, |
544 | &queue_wc_entry.attr, | ||
506 | NULL, | 545 | NULL, |
507 | }; | 546 | }; |
508 | 547 | ||
diff --git a/block/blk-throttle.c b/block/blk-throttle.c index 2149a1ddbacf..47a3e540631a 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c | |||
@@ -211,15 +211,14 @@ static struct throtl_data *sq_to_td(struct throtl_service_queue *sq) | |||
211 | * | 211 | * |
212 | * The messages are prefixed with "throtl BLKG_NAME" if @sq belongs to a | 212 | * The messages are prefixed with "throtl BLKG_NAME" if @sq belongs to a |
213 | * throtl_grp; otherwise, just "throtl". | 213 | * throtl_grp; otherwise, just "throtl". |
214 | * | ||
215 | * TODO: this should be made a function and name formatting should happen | ||
216 | * after testing whether blktrace is enabled. | ||
217 | */ | 214 | */ |
218 | #define throtl_log(sq, fmt, args...) do { \ | 215 | #define throtl_log(sq, fmt, args...) do { \ |
219 | struct throtl_grp *__tg = sq_to_tg((sq)); \ | 216 | struct throtl_grp *__tg = sq_to_tg((sq)); \ |
220 | struct throtl_data *__td = sq_to_td((sq)); \ | 217 | struct throtl_data *__td = sq_to_td((sq)); \ |
221 | \ | 218 | \ |
222 | (void)__td; \ | 219 | (void)__td; \ |
220 | if (likely(!blk_trace_note_message_enabled(__td->queue))) \ | ||
221 | break; \ | ||
223 | if ((__tg)) { \ | 222 | if ((__tg)) { \ |
224 | char __pbuf[128]; \ | 223 | char __pbuf[128]; \ |
225 | \ | 224 | \ |
diff --git a/drivers/block/skd_main.c b/drivers/block/skd_main.c index 586f9168ffa4..9a9ec212fab8 100644 --- a/drivers/block/skd_main.c +++ b/drivers/block/skd_main.c | |||
@@ -562,7 +562,7 @@ skd_prep_discard_cdb(struct skd_scsi_request *scsi_req, | |||
562 | put_unaligned_be32(count, &buf[16]); | 562 | put_unaligned_be32(count, &buf[16]); |
563 | 563 | ||
564 | req = skreq->req; | 564 | req = skreq->req; |
565 | blk_add_request_payload(req, page, len); | 565 | blk_add_request_payload(req, page, 0, len); |
566 | } | 566 | } |
567 | 567 | ||
568 | static void skd_request_fn_not_online(struct request_queue *q); | 568 | static void skd_request_fn_not_online(struct request_queue *q); |
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index f52b74cf8d1e..69b0a4a7a15f 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c | |||
@@ -779,7 +779,7 @@ static int sd_setup_discard_cmnd(struct scsi_cmnd *cmd) | |||
779 | * discarded on disk. This allows us to report completion on the full | 779 | * discarded on disk. This allows us to report completion on the full |
780 | * amount of blocks described by the request. | 780 | * amount of blocks described by the request. |
781 | */ | 781 | */ |
782 | blk_add_request_payload(rq, page, len); | 782 | blk_add_request_payload(rq, page, 0, len); |
783 | ret = scsi_init_io(cmd); | 783 | ret = scsi_init_io(cmd); |
784 | rq->__data_len = nr_bytes; | 784 | rq->__data_len = nr_bytes; |
785 | 785 | ||
diff --git a/include/linux/bio.h b/include/linux/bio.h index 6b7481f62218..9faebf7f9a33 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h | |||
@@ -703,6 +703,17 @@ static inline struct bio *bio_list_get(struct bio_list *bl) | |||
703 | } | 703 | } |
704 | 704 | ||
705 | /* | 705 | /* |
706 | * Increment chain count for the bio. Make sure the CHAIN flag update | ||
707 | * is visible before the raised count. | ||
708 | */ | ||
709 | static inline void bio_inc_remaining(struct bio *bio) | ||
710 | { | ||
711 | bio_set_flag(bio, BIO_CHAIN); | ||
712 | smp_mb__before_atomic(); | ||
713 | atomic_inc(&bio->__bi_remaining); | ||
714 | } | ||
715 | |||
716 | /* | ||
706 | * bio_set is used to allow other portions of the IO system to | 717 | * bio_set is used to allow other portions of the IO system to |
707 | * allocate their own private memory pools for bio and iovec structures. | 718 | * allocate their own private memory pools for bio and iovec structures. |
708 | * These memory pools in turn all allocate from the bio_slab | 719 | * These memory pools in turn all allocate from the bio_slab |
diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h index 9ac9799b702b..c808fec1ce44 100644 --- a/include/linux/blk-mq.h +++ b/include/linux/blk-mq.h | |||
@@ -240,6 +240,8 @@ void blk_mq_run_hw_queues(struct request_queue *q, bool async); | |||
240 | void blk_mq_delay_queue(struct blk_mq_hw_ctx *hctx, unsigned long msecs); | 240 | void blk_mq_delay_queue(struct blk_mq_hw_ctx *hctx, unsigned long msecs); |
241 | void blk_mq_all_tag_busy_iter(struct blk_mq_tags *tags, busy_tag_iter_fn *fn, | 241 | void blk_mq_all_tag_busy_iter(struct blk_mq_tags *tags, busy_tag_iter_fn *fn, |
242 | void *priv); | 242 | void *priv); |
243 | void blk_mq_tagset_busy_iter(struct blk_mq_tag_set *tagset, | ||
244 | busy_tag_iter_fn *fn, void *priv); | ||
243 | void blk_mq_freeze_queue(struct request_queue *q); | 245 | void blk_mq_freeze_queue(struct request_queue *q); |
244 | void blk_mq_unfreeze_queue(struct request_queue *q); | 246 | void blk_mq_unfreeze_queue(struct request_queue *q); |
245 | void blk_mq_freeze_queue_start(struct request_queue *q); | 247 | void blk_mq_freeze_queue_start(struct request_queue *q); |
diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h index 86a38ea1823f..77e5d81f07aa 100644 --- a/include/linux/blk_types.h +++ b/include/linux/blk_types.h | |||
@@ -208,7 +208,7 @@ enum rq_flag_bits { | |||
208 | #define REQ_COMMON_MASK \ | 208 | #define REQ_COMMON_MASK \ |
209 | (REQ_WRITE | REQ_FAILFAST_MASK | REQ_SYNC | REQ_META | REQ_PRIO | \ | 209 | (REQ_WRITE | REQ_FAILFAST_MASK | REQ_SYNC | REQ_META | REQ_PRIO | \ |
210 | REQ_DISCARD | REQ_WRITE_SAME | REQ_NOIDLE | REQ_FLUSH | REQ_FUA | \ | 210 | REQ_DISCARD | REQ_WRITE_SAME | REQ_NOIDLE | REQ_FLUSH | REQ_FUA | \ |
211 | REQ_SECURE | REQ_INTEGRITY) | 211 | REQ_SECURE | REQ_INTEGRITY | REQ_NOMERGE) |
212 | #define REQ_CLONE_MASK REQ_COMMON_MASK | 212 | #define REQ_CLONE_MASK REQ_COMMON_MASK |
213 | 213 | ||
214 | #define BIO_NO_ADVANCE_ITER_MASK (REQ_DISCARD|REQ_WRITE_SAME) | 214 | #define BIO_NO_ADVANCE_ITER_MASK (REQ_DISCARD|REQ_WRITE_SAME) |
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 669e419d6234..b79131acf6c0 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h | |||
@@ -491,6 +491,8 @@ struct request_queue { | |||
491 | #define QUEUE_FLAG_INIT_DONE 20 /* queue is initialized */ | 491 | #define QUEUE_FLAG_INIT_DONE 20 /* queue is initialized */ |
492 | #define QUEUE_FLAG_NO_SG_MERGE 21 /* don't attempt to merge SG segments*/ | 492 | #define QUEUE_FLAG_NO_SG_MERGE 21 /* don't attempt to merge SG segments*/ |
493 | #define QUEUE_FLAG_POLL 22 /* IO polling enabled if set */ | 493 | #define QUEUE_FLAG_POLL 22 /* IO polling enabled if set */ |
494 | #define QUEUE_FLAG_WC 23 /* Write back caching */ | ||
495 | #define QUEUE_FLAG_FUA 24 /* device supports FUA writes */ | ||
494 | 496 | ||
495 | #define QUEUE_FLAG_DEFAULT ((1 << QUEUE_FLAG_IO_STAT) | \ | 497 | #define QUEUE_FLAG_DEFAULT ((1 << QUEUE_FLAG_IO_STAT) | \ |
496 | (1 << QUEUE_FLAG_STACKABLE) | \ | 498 | (1 << QUEUE_FLAG_STACKABLE) | \ |
@@ -779,7 +781,7 @@ extern struct request *blk_make_request(struct request_queue *, struct bio *, | |||
779 | extern void blk_rq_set_block_pc(struct request *); | 781 | extern void blk_rq_set_block_pc(struct request *); |
780 | extern void blk_requeue_request(struct request_queue *, struct request *); | 782 | extern void blk_requeue_request(struct request_queue *, struct request *); |
781 | extern void blk_add_request_payload(struct request *rq, struct page *page, | 783 | extern void blk_add_request_payload(struct request *rq, struct page *page, |
782 | unsigned int len); | 784 | int offset, unsigned int len); |
783 | extern int blk_lld_busy(struct request_queue *q); | 785 | extern int blk_lld_busy(struct request_queue *q); |
784 | extern int blk_rq_prep_clone(struct request *rq, struct request *rq_src, | 786 | extern int blk_rq_prep_clone(struct request *rq, struct request *rq_src, |
785 | struct bio_set *bs, gfp_t gfp_mask, | 787 | struct bio_set *bs, gfp_t gfp_mask, |
@@ -1009,6 +1011,7 @@ extern void blk_queue_rq_timed_out(struct request_queue *, rq_timed_out_fn *); | |||
1009 | extern void blk_queue_rq_timeout(struct request_queue *, unsigned int); | 1011 | extern void blk_queue_rq_timeout(struct request_queue *, unsigned int); |
1010 | extern void blk_queue_flush(struct request_queue *q, unsigned int flush); | 1012 | extern void blk_queue_flush(struct request_queue *q, unsigned int flush); |
1011 | extern void blk_queue_flush_queueable(struct request_queue *q, bool queueable); | 1013 | extern void blk_queue_flush_queueable(struct request_queue *q, bool queueable); |
1014 | extern void blk_queue_write_cache(struct request_queue *q, bool enabled, bool fua); | ||
1012 | extern struct backing_dev_info *blk_get_backing_dev_info(struct block_device *bdev); | 1015 | extern struct backing_dev_info *blk_get_backing_dev_info(struct block_device *bdev); |
1013 | 1016 | ||
1014 | extern int blk_rq_map_sg(struct request_queue *, struct request *, struct scatterlist *); | 1017 | extern int blk_rq_map_sg(struct request_queue *, struct request *, struct scatterlist *); |
@@ -1128,6 +1131,8 @@ static inline struct request *blk_map_queue_find_tag(struct blk_queue_tag *bqt, | |||
1128 | extern int blkdev_issue_flush(struct block_device *, gfp_t, sector_t *); | 1131 | extern int blkdev_issue_flush(struct block_device *, gfp_t, sector_t *); |
1129 | extern int blkdev_issue_discard(struct block_device *bdev, sector_t sector, | 1132 | extern int blkdev_issue_discard(struct block_device *bdev, sector_t sector, |
1130 | sector_t nr_sects, gfp_t gfp_mask, unsigned long flags); | 1133 | sector_t nr_sects, gfp_t gfp_mask, unsigned long flags); |
1134 | extern int __blkdev_issue_discard(struct block_device *bdev, sector_t sector, | ||
1135 | sector_t nr_sects, gfp_t gfp_mask, int type, struct bio **biop); | ||
1131 | extern int blkdev_issue_write_same(struct block_device *bdev, sector_t sector, | 1136 | extern int blkdev_issue_write_same(struct block_device *bdev, sector_t sector, |
1132 | sector_t nr_sects, gfp_t gfp_mask, struct page *page); | 1137 | sector_t nr_sects, gfp_t gfp_mask, struct page *page); |
1133 | extern int blkdev_issue_zeroout(struct block_device *bdev, sector_t sector, | 1138 | extern int blkdev_issue_zeroout(struct block_device *bdev, sector_t sector, |
diff --git a/include/linux/blktrace_api.h b/include/linux/blktrace_api.h index afc1343df3c7..0f3172b8b225 100644 --- a/include/linux/blktrace_api.h +++ b/include/linux/blktrace_api.h | |||
@@ -57,6 +57,14 @@ void __trace_note_message(struct blk_trace *, const char *fmt, ...); | |||
57 | } while (0) | 57 | } while (0) |
58 | #define BLK_TN_MAX_MSG 128 | 58 | #define BLK_TN_MAX_MSG 128 |
59 | 59 | ||
60 | static inline bool blk_trace_note_message_enabled(struct request_queue *q) | ||
61 | { | ||
62 | struct blk_trace *bt = q->blk_trace; | ||
63 | if (likely(!bt)) | ||
64 | return false; | ||
65 | return bt->act_mask & BLK_TC_NOTIFY; | ||
66 | } | ||
67 | |||
60 | extern void blk_add_driver_data(struct request_queue *q, struct request *rq, | 68 | extern void blk_add_driver_data(struct request_queue *q, struct request *rq, |
61 | void *data, size_t len); | 69 | void *data, size_t len); |
62 | extern int blk_trace_setup(struct request_queue *q, char *name, dev_t dev, | 70 | extern int blk_trace_setup(struct request_queue *q, char *name, dev_t dev, |
@@ -79,6 +87,7 @@ extern struct attribute_group blk_trace_attr_group; | |||
79 | # define blk_trace_remove(q) (-ENOTTY) | 87 | # define blk_trace_remove(q) (-ENOTTY) |
80 | # define blk_add_trace_msg(q, fmt, ...) do { } while (0) | 88 | # define blk_add_trace_msg(q, fmt, ...) do { } while (0) |
81 | # define blk_trace_remove_sysfs(dev) do { } while (0) | 89 | # define blk_trace_remove_sysfs(dev) do { } while (0) |
90 | # define blk_trace_note_message_enabled(q) (false) | ||
82 | static inline int blk_trace_init_sysfs(struct device *dev) | 91 | static inline int blk_trace_init_sysfs(struct device *dev) |
83 | { | 92 | { |
84 | return 0; | 93 | return 0; |
diff --git a/kernel/trace/blktrace.c b/kernel/trace/blktrace.c index f94e7a21f52d..9aef8654e90d 100644 --- a/kernel/trace/blktrace.c +++ b/kernel/trace/blktrace.c | |||
@@ -1349,6 +1349,7 @@ static enum print_line_t print_one_line(struct trace_iterator *iter, | |||
1349 | if (t->action == BLK_TN_MESSAGE) { | 1349 | if (t->action == BLK_TN_MESSAGE) { |
1350 | log_action(iter, long_act ? "message" : "m"); | 1350 | log_action(iter, long_act ? "message" : "m"); |
1351 | blk_log_msg(s, iter->ent); | 1351 | blk_log_msg(s, iter->ent); |
1352 | return trace_handle_return(s); | ||
1352 | } | 1353 | } |
1353 | 1354 | ||
1354 | if (unlikely(what == 0 || what >= ARRAY_SIZE(what2act))) | 1355 | if (unlikely(what == 0 || what >= ARRAY_SIZE(what2act))) |
@@ -1551,6 +1552,7 @@ static const struct { | |||
1551 | { BLK_TC_COMPLETE, "complete" }, | 1552 | { BLK_TC_COMPLETE, "complete" }, |
1552 | { BLK_TC_FS, "fs" }, | 1553 | { BLK_TC_FS, "fs" }, |
1553 | { BLK_TC_PC, "pc" }, | 1554 | { BLK_TC_PC, "pc" }, |
1555 | { BLK_TC_NOTIFY, "notify" }, | ||
1554 | { BLK_TC_AHEAD, "ahead" }, | 1556 | { BLK_TC_AHEAD, "ahead" }, |
1555 | { BLK_TC_META, "meta" }, | 1557 | { BLK_TC_META, "meta" }, |
1556 | { BLK_TC_DISCARD, "discard" }, | 1558 | { BLK_TC_DISCARD, "discard" }, |