Commit 4eaf99beadcefbf126fa05e66fb40fca999e09fd

Authored by Martin K. Petersen
Committed by Jens Axboe
1 parent aae7df5019

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>

Showing 3 changed files with 39 additions and 23 deletions Side-by-side Diff

block/blk-integrity.c
... ... @@ -186,37 +186,53 @@
186 186 }
187 187 EXPORT_SYMBOL(blk_integrity_compare);
188 188  
189   -int blk_integrity_merge_rq(struct request_queue *q, struct request *req,
190   - struct request *next)
  189 +bool blk_integrity_merge_rq(struct request_queue *q, struct request *req,
  190 + struct request *next)
191 191 {
192   - if (blk_integrity_rq(req) != blk_integrity_rq(next))
193   - return -1;
  192 + if (blk_integrity_rq(req) == 0 && blk_integrity_rq(next) == 0)
  193 + return true;
194 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;
  201 +
195 202 if (req->nr_integrity_segments + next->nr_integrity_segments >
196 203 q->limits.max_integrity_segments)
197   - return -1;
  204 + return false;
198 205  
199   - return 0;
  206 + return true;
200 207 }
201 208 EXPORT_SYMBOL(blk_integrity_merge_rq);
202 209  
203   -int blk_integrity_merge_bio(struct request_queue *q, struct request *req,
204   - struct bio *bio)
  210 +bool blk_integrity_merge_bio(struct request_queue *q, struct request *req,
  211 + struct bio *bio)
205 212 {
206 213 int nr_integrity_segs;
207 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 225 bio->bi_next = NULL;
210 226 nr_integrity_segs = blk_rq_count_integrity_sg(q, bio);
211 227 bio->bi_next = next;
212 228  
213 229 if (req->nr_integrity_segments + nr_integrity_segs >
214 230 q->limits.max_integrity_segments)
215   - return -1;
  231 + return false;
216 232  
217 233 req->nr_integrity_segments += nr_integrity_segs;
218 234  
219   - return 0;
  235 + return true;
220 236 }
221 237 EXPORT_SYMBOL(blk_integrity_merge_bio);
222 238  
... ... @@ -313,7 +313,7 @@
313 313 if (req->nr_phys_segments + nr_phys_segs > queue_max_segments(q))
314 314 goto no_merge;
315 315  
316   - if (bio_integrity(bio) && blk_integrity_merge_bio(q, req, bio))
  316 + if (blk_integrity_merge_bio(q, req, bio) == false)
317 317 goto no_merge;
318 318  
319 319 /*
... ... @@ -410,7 +410,7 @@
410 410 if (total_phys_segments > queue_max_segments(q))
411 411 return 0;
412 412  
413   - if (blk_integrity_rq(req) && blk_integrity_merge_rq(q, req, next))
  413 + if (blk_integrity_merge_rq(q, req, next) == false)
414 414 return 0;
415 415  
416 416 /* Merge is OK... */
... ... @@ -590,7 +590,7 @@
590 590 return false;
591 591  
592 592 /* only merge integrity protected bio into ditto rq */
593   - if (bio_integrity(bio) != blk_integrity_rq(rq))
  593 + if (blk_integrity_merge_bio(rq->q, rq, bio) == false)
594 594 return false;
595 595  
596 596 /* must be using the same buffer */
include/linux/blkdev.h
... ... @@ -1497,10 +1497,10 @@
1497 1497 extern int blk_rq_map_integrity_sg(struct request_queue *, struct bio *,
1498 1498 struct scatterlist *);
1499 1499 extern int blk_rq_count_integrity_sg(struct request_queue *, struct bio *);
1500   -extern int blk_integrity_merge_rq(struct request_queue *, struct request *,
1501   - struct request *);
1502   -extern int blk_integrity_merge_bio(struct request_queue *, struct request *,
1503   - struct bio *);
  1500 +extern bool blk_integrity_merge_rq(struct request_queue *, struct request *,
  1501 + struct request *);
  1502 +extern bool blk_integrity_merge_bio(struct request_queue *, struct request *,
  1503 + struct bio *);
1504 1504  
1505 1505 static inline
1506 1506 struct blk_integrity *bdev_get_integrity(struct block_device *bdev)
1507 1507  
... ... @@ -1580,15 +1580,15 @@
1580 1580 {
1581 1581 return 0;
1582 1582 }
1583   -static inline int blk_integrity_merge_rq(struct request_queue *rq,
1584   - struct request *r1,
1585   - struct request *r2)
  1583 +static inline bool blk_integrity_merge_rq(struct request_queue *rq,
  1584 + struct request *r1,
  1585 + struct request *r2)
1586 1586 {
1587 1587 return 0;
1588 1588 }
1589   -static inline int blk_integrity_merge_bio(struct request_queue *rq,
1590   - struct request *r,
1591   - struct bio *b)
  1589 +static inline bool blk_integrity_merge_bio(struct request_queue *rq,
  1590 + struct request *r,
  1591 + struct bio *b)
1592 1592 {
1593 1593 return 0;
1594 1594 }