diff options
author | Martin K. Petersen <martin.petersen@oracle.com> | 2014-09-26 19:20:06 -0400 |
---|---|---|
committer | Jens Axboe <axboe@fb.com> | 2014-09-27 11:14:57 -0400 |
commit | 4eaf99beadcefbf126fa05e66fb40fca999e09fd (patch) | |
tree | e91203868eb48cdf06dd575e7d3f3569d6b6bfc9 /block/blk-integrity.c | |
parent | aae7df50190a640e51bfe11c93f94741ac82ff0b (diff) |
block: Don't merge requests if integrity flags differ
We'd occasionally merge requests with conflicting integrity flags.
Introduce a merge helper which checks that the requests have compatible
integrity payloads.
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Sagi Grimberg <sagig@mellanox.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
Diffstat (limited to 'block/blk-integrity.c')
-rw-r--r-- | block/blk-integrity.c | 36 |
1 files changed, 26 insertions, 10 deletions
diff --git a/block/blk-integrity.c b/block/blk-integrity.c index 1c6ba442cd91..79ffb4855af0 100644 --- a/block/blk-integrity.c +++ b/block/blk-integrity.c | |||
@@ -186,37 +186,53 @@ int blk_integrity_compare(struct gendisk *gd1, struct gendisk *gd2) | |||
186 | } | 186 | } |
187 | EXPORT_SYMBOL(blk_integrity_compare); | 187 | EXPORT_SYMBOL(blk_integrity_compare); |
188 | 188 | ||
189 | int blk_integrity_merge_rq(struct request_queue *q, struct request *req, | 189 | bool blk_integrity_merge_rq(struct request_queue *q, struct request *req, |
190 | struct request *next) | 190 | struct request *next) |
191 | { | 191 | { |
192 | if (blk_integrity_rq(req) != blk_integrity_rq(next)) | 192 | if (blk_integrity_rq(req) == 0 && blk_integrity_rq(next) == 0) |
193 | return -1; | 193 | return true; |
194 | |||
195 | if (blk_integrity_rq(req) == 0 || blk_integrity_rq(next) == 0) | ||
196 | return false; | ||
197 | |||
198 | if (bio_integrity(req->bio)->bip_flags != | ||
199 | bio_integrity(next->bio)->bip_flags) | ||
200 | return false; | ||
194 | 201 | ||
195 | if (req->nr_integrity_segments + next->nr_integrity_segments > | 202 | if (req->nr_integrity_segments + next->nr_integrity_segments > |
196 | q->limits.max_integrity_segments) | 203 | q->limits.max_integrity_segments) |
197 | return -1; | 204 | return false; |
198 | 205 | ||
199 | return 0; | 206 | return true; |
200 | } | 207 | } |
201 | EXPORT_SYMBOL(blk_integrity_merge_rq); | 208 | EXPORT_SYMBOL(blk_integrity_merge_rq); |
202 | 209 | ||
203 | int blk_integrity_merge_bio(struct request_queue *q, struct request *req, | 210 | bool blk_integrity_merge_bio(struct request_queue *q, struct request *req, |
204 | struct bio *bio) | 211 | struct bio *bio) |
205 | { | 212 | { |
206 | int nr_integrity_segs; | 213 | int nr_integrity_segs; |
207 | struct bio *next = bio->bi_next; | 214 | struct bio *next = bio->bi_next; |
208 | 215 | ||
216 | if (blk_integrity_rq(req) == 0 && bio_integrity(bio) == NULL) | ||
217 | return true; | ||
218 | |||
219 | if (blk_integrity_rq(req) == 0 || bio_integrity(bio) == NULL) | ||
220 | return false; | ||
221 | |||
222 | if (bio_integrity(req->bio)->bip_flags != bio_integrity(bio)->bip_flags) | ||
223 | return false; | ||
224 | |||
209 | bio->bi_next = NULL; | 225 | bio->bi_next = NULL; |
210 | nr_integrity_segs = blk_rq_count_integrity_sg(q, bio); | 226 | nr_integrity_segs = blk_rq_count_integrity_sg(q, bio); |
211 | bio->bi_next = next; | 227 | bio->bi_next = next; |
212 | 228 | ||
213 | if (req->nr_integrity_segments + nr_integrity_segs > | 229 | if (req->nr_integrity_segments + nr_integrity_segs > |
214 | q->limits.max_integrity_segments) | 230 | q->limits.max_integrity_segments) |
215 | return -1; | 231 | return false; |
216 | 232 | ||
217 | req->nr_integrity_segments += nr_integrity_segs; | 233 | req->nr_integrity_segments += nr_integrity_segs; |
218 | 234 | ||
219 | return 0; | 235 | return true; |
220 | } | 236 | } |
221 | EXPORT_SYMBOL(blk_integrity_merge_bio); | 237 | EXPORT_SYMBOL(blk_integrity_merge_bio); |
222 | 238 | ||