diff options
Diffstat (limited to 'block')
-rw-r--r-- | block/blk-barrier.c | 2 | ||||
-rw-r--r-- | block/blk-core.c | 12 | ||||
-rw-r--r-- | block/blk-merge.c | 27 | ||||
-rw-r--r-- | block/elevator.c | 12 | ||||
-rw-r--r-- | block/ioctl.c | 2 |
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 | ||
12 | void blk_recalc_rq_sectors(struct request *rq, int nsect) | 12 | void 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 | ||