aboutsummaryrefslogtreecommitdiffstats
path: root/block
diff options
context:
space:
mode:
Diffstat (limited to 'block')
-rw-r--r--block/blk-barrier.c2
-rw-r--r--block/blk-core.c12
-rw-r--r--block/blk-merge.c27
-rw-r--r--block/elevator.c12
-rw-r--r--block/ioctl.c2
5 files changed, 36 insertions, 19 deletions
diff --git a/block/blk-barrier.c b/block/blk-barrier.c
index e5448131d4f1..988b63479b2f 100644
--- a/block/blk-barrier.c
+++ b/block/blk-barrier.c
@@ -372,7 +372,7 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector,
372 nr_sects = 0; 372 nr_sects = 0;
373 } 373 }
374 bio_get(bio); 374 bio_get(bio);
375 submit_bio(WRITE_DISCARD, bio); 375 submit_bio(DISCARD_BARRIER, bio);
376 376
377 /* Check if it failed immediately */ 377 /* Check if it failed immediately */
378 if (bio_flagged(bio, BIO_EOPNOTSUPP)) 378 if (bio_flagged(bio, BIO_EOPNOTSUPP))
diff --git a/block/blk-core.c b/block/blk-core.c
index 1e143c4f9d34..1261516dd42a 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -1077,12 +1077,13 @@ void init_request_from_bio(struct request *req, struct bio *bio)
1077 /* 1077 /*
1078 * REQ_BARRIER implies no merging, but lets make it explicit 1078 * REQ_BARRIER implies no merging, but lets make it explicit
1079 */ 1079 */
1080 if (unlikely(bio_barrier(bio)))
1081 req->cmd_flags |= (REQ_HARDBARRIER | REQ_NOMERGE);
1082 if (unlikely(bio_discard(bio))) { 1080 if (unlikely(bio_discard(bio))) {
1083 req->cmd_flags |= (REQ_SOFTBARRIER | REQ_DISCARD); 1081 req->cmd_flags |= REQ_DISCARD;
1082 if (bio_barrier(bio))
1083 req->cmd_flags |= REQ_SOFTBARRIER;
1084 req->q->prepare_discard_fn(req->q, req); 1084 req->q->prepare_discard_fn(req->q, req);
1085 } 1085 } else if (unlikely(bio_barrier(bio)))
1086 req->cmd_flags |= (REQ_HARDBARRIER | REQ_NOMERGE);
1086 1087
1087 if (bio_sync(bio)) 1088 if (bio_sync(bio))
1088 req->cmd_flags |= REQ_RW_SYNC; 1089 req->cmd_flags |= REQ_RW_SYNC;
@@ -1114,7 +1115,8 @@ static int __make_request(struct request_queue *q, struct bio *bio)
1114 blk_queue_bounce(q, &bio); 1115 blk_queue_bounce(q, &bio);
1115 1116
1116 barrier = bio_barrier(bio); 1117 barrier = bio_barrier(bio);
1117 if (unlikely(barrier) && (q->next_ordered == QUEUE_ORDERED_NONE)) { 1118 if (unlikely(barrier) && bio_has_data(bio) &&
1119 (q->next_ordered == QUEUE_ORDERED_NONE)) {
1118 err = -EOPNOTSUPP; 1120 err = -EOPNOTSUPP;
1119 goto end_io; 1121 goto end_io;
1120 } 1122 }
diff --git a/block/blk-merge.c b/block/blk-merge.c
index 5efc9e7a68b7..6cf8f0c70a51 100644
--- a/block/blk-merge.c
+++ b/block/blk-merge.c
@@ -11,7 +11,7 @@
11 11
12void blk_recalc_rq_sectors(struct request *rq, int nsect) 12void blk_recalc_rq_sectors(struct request *rq, int nsect)
13{ 13{
14 if (blk_fs_request(rq)) { 14 if (blk_fs_request(rq) || blk_discard_rq(rq)) {
15 rq->hard_sector += nsect; 15 rq->hard_sector += nsect;
16 rq->hard_nr_sectors -= nsect; 16 rq->hard_nr_sectors -= nsect;
17 17
@@ -131,13 +131,17 @@ static int blk_phys_contig_segment(struct request_queue *q, struct bio *bio,
131 if (!test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags)) 131 if (!test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags))
132 return 0; 132 return 0;
133 133
134 if (!BIOVEC_PHYS_MERGEABLE(__BVEC_END(bio), __BVEC_START(nxt)))
135 return 0;
136 if (bio->bi_size + nxt->bi_size > q->max_segment_size) 134 if (bio->bi_size + nxt->bi_size > q->max_segment_size)
137 return 0; 135 return 0;
138 136
137 if (!bio_has_data(bio))
138 return 1;
139
140 if (!BIOVEC_PHYS_MERGEABLE(__BVEC_END(bio), __BVEC_START(nxt)))
141 return 0;
142
139 /* 143 /*
140 * bio and nxt are contigous in memory, check if the queue allows 144 * bio and nxt are contiguous in memory; check if the queue allows
141 * these two to be merged into one 145 * these two to be merged into one
142 */ 146 */
143 if (BIO_SEG_BOUNDARY(q, bio, nxt)) 147 if (BIO_SEG_BOUNDARY(q, bio, nxt))
@@ -153,8 +157,9 @@ static int blk_hw_contig_segment(struct request_queue *q, struct bio *bio,
153 blk_recount_segments(q, bio); 157 blk_recount_segments(q, bio);
154 if (!bio_flagged(nxt, BIO_SEG_VALID)) 158 if (!bio_flagged(nxt, BIO_SEG_VALID))
155 blk_recount_segments(q, nxt); 159 blk_recount_segments(q, nxt);
156 if (!BIOVEC_VIRT_MERGEABLE(__BVEC_END(bio), __BVEC_START(nxt)) || 160 if (bio_has_data(bio) &&
157 BIOVEC_VIRT_OVERSIZE(bio->bi_hw_back_size + nxt->bi_hw_front_size)) 161 (!BIOVEC_VIRT_MERGEABLE(__BVEC_END(bio), __BVEC_START(nxt)) ||
162 BIOVEC_VIRT_OVERSIZE(bio->bi_hw_back_size + nxt->bi_hw_front_size)))
158 return 0; 163 return 0;
159 if (bio->bi_hw_back_size + nxt->bi_hw_front_size > q->max_segment_size) 164 if (bio->bi_hw_back_size + nxt->bi_hw_front_size > q->max_segment_size)
160 return 0; 165 return 0;
@@ -317,8 +322,9 @@ int ll_back_merge_fn(struct request_queue *q, struct request *req,
317 if (!bio_flagged(bio, BIO_SEG_VALID)) 322 if (!bio_flagged(bio, BIO_SEG_VALID))
318 blk_recount_segments(q, bio); 323 blk_recount_segments(q, bio);
319 len = req->biotail->bi_hw_back_size + bio->bi_hw_front_size; 324 len = req->biotail->bi_hw_back_size + bio->bi_hw_front_size;
320 if (BIOVEC_VIRT_MERGEABLE(__BVEC_END(req->biotail), __BVEC_START(bio)) 325 if (!bio_has_data(bio) ||
321 && !BIOVEC_VIRT_OVERSIZE(len)) { 326 (BIOVEC_VIRT_MERGEABLE(__BVEC_END(req->biotail), __BVEC_START(bio))
327 && !BIOVEC_VIRT_OVERSIZE(len))) {
322 int mergeable = ll_new_mergeable(q, req, bio); 328 int mergeable = ll_new_mergeable(q, req, bio);
323 329
324 if (mergeable) { 330 if (mergeable) {
@@ -356,8 +362,9 @@ int ll_front_merge_fn(struct request_queue *q, struct request *req,
356 blk_recount_segments(q, bio); 362 blk_recount_segments(q, bio);
357 if (!bio_flagged(req->bio, BIO_SEG_VALID)) 363 if (!bio_flagged(req->bio, BIO_SEG_VALID))
358 blk_recount_segments(q, req->bio); 364 blk_recount_segments(q, req->bio);
359 if (BIOVEC_VIRT_MERGEABLE(__BVEC_END(bio), __BVEC_START(req->bio)) && 365 if (!bio_has_data(bio) ||
360 !BIOVEC_VIRT_OVERSIZE(len)) { 366 (BIOVEC_VIRT_MERGEABLE(__BVEC_END(bio), __BVEC_START(req->bio)) &&
367 !BIOVEC_VIRT_OVERSIZE(len))) {
361 int mergeable = ll_new_mergeable(q, req, bio); 368 int mergeable = ll_new_mergeable(q, req, bio);
362 369
363 if (mergeable) { 370 if (mergeable) {
diff --git a/block/elevator.c b/block/elevator.c
index ed6f8f32d27e..4f5127054e3f 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -75,6 +75,12 @@ int elv_rq_merge_ok(struct request *rq, struct bio *bio)
75 return 0; 75 return 0;
76 76
77 /* 77 /*
78 * Don't merge file system requests and discard requests
79 */
80 if (bio_discard(bio) != bio_discard(rq->bio))
81 return 0;
82
83 /*
78 * different data direction or already started, don't merge 84 * different data direction or already started, don't merge
79 */ 85 */
80 if (bio_data_dir(bio) != rq_data_dir(rq)) 86 if (bio_data_dir(bio) != rq_data_dir(rq))
@@ -438,6 +444,8 @@ void elv_dispatch_sort(struct request_queue *q, struct request *rq)
438 list_for_each_prev(entry, &q->queue_head) { 444 list_for_each_prev(entry, &q->queue_head) {
439 struct request *pos = list_entry_rq(entry); 445 struct request *pos = list_entry_rq(entry);
440 446
447 if (blk_discard_rq(rq) != blk_discard_rq(pos))
448 break;
441 if (rq_data_dir(rq) != rq_data_dir(pos)) 449 if (rq_data_dir(rq) != rq_data_dir(pos))
442 break; 450 break;
443 if (pos->cmd_flags & stop_flags) 451 if (pos->cmd_flags & stop_flags)
@@ -607,7 +615,7 @@ void elv_insert(struct request_queue *q, struct request *rq, int where)
607 break; 615 break;
608 616
609 case ELEVATOR_INSERT_SORT: 617 case ELEVATOR_INSERT_SORT:
610 BUG_ON(!blk_fs_request(rq)); 618 BUG_ON(!blk_fs_request(rq) && !blk_discard_rq(rq));
611 rq->cmd_flags |= REQ_SORTED; 619 rq->cmd_flags |= REQ_SORTED;
612 q->nr_sorted++; 620 q->nr_sorted++;
613 if (rq_mergeable(rq)) { 621 if (rq_mergeable(rq)) {
@@ -692,7 +700,7 @@ void __elv_add_request(struct request_queue *q, struct request *rq, int where,
692 * this request is scheduling boundary, update 700 * this request is scheduling boundary, update
693 * end_sector 701 * end_sector
694 */ 702 */
695 if (blk_fs_request(rq)) { 703 if (blk_fs_request(rq) || blk_discard_rq(rq)) {
696 q->end_sector = rq_end_sector(rq); 704 q->end_sector = rq_end_sector(rq);
697 q->boundary_rq = rq; 705 q->boundary_rq = rq;
698 } 706 }
diff --git a/block/ioctl.c b/block/ioctl.c
index 342298bb6080..375c57922b00 100644
--- a/block/ioctl.c
+++ b/block/ioctl.c
@@ -161,7 +161,7 @@ static int blk_ioctl_discard(struct block_device *bdev, uint64_t start,
161 bio->bi_size = len << 9; 161 bio->bi_size = len << 9;
162 len = 0; 162 len = 0;
163 } 163 }
164 submit_bio(WRITE_DISCARD, bio); 164 submit_bio(DISCARD_NOBARRIER, bio);
165 165
166 wait_for_completion(&wait); 166 wait_for_completion(&wait);
167 167