block: Refuse request/bio merges with gaps in the integrity payload

If a driver sets the block queue virtual boundary mask, it means that
it cannot handle gaps so we must not allow those in the integrity
payload as well.

Signed-off-by: Sagi Grimberg <sagig@mellanox.com>

Fixed up by me to have duplicate integrity merge functions, depending
on whether block integrity is enabled or not. Fixes a compilations
issue with CONFIG_BLK_DEV_INTEGRITY unset.

Signed-off-by: Jens Axboe <axboe@fb.com>

authored by Sagi Grimberg and committed by Jens Axboe 7f39add3 5e7c4274

+39
+3
block/blk-integrity.c
··· 204 204 q->limits.max_integrity_segments) 205 205 return false; 206 206 207 + if (integrity_req_gap_back_merge(req, next->bio)) 208 + return false; 209 + 207 210 return true; 208 211 } 209 212 EXPORT_SYMBOL(blk_integrity_merge_rq);
+6
block/blk-merge.c
··· 440 440 { 441 441 if (req_gap_back_merge(req, bio)) 442 442 return 0; 443 + if (blk_integrity_rq(req) && 444 + integrity_req_gap_back_merge(req, bio)) 445 + return 0; 443 446 if (blk_rq_sectors(req) + bio_sectors(bio) > 444 447 blk_rq_get_max_sectors(req)) { 445 448 req->cmd_flags |= REQ_NOMERGE; ··· 463 460 { 464 461 465 462 if (req_gap_front_merge(req, bio)) 463 + return 0; 464 + if (blk_integrity_rq(req) && 465 + integrity_req_gap_front_merge(req, bio)) 466 466 return 0; 467 467 if (blk_rq_sectors(req) + bio_sectors(bio) > 468 468 blk_rq_get_max_sectors(req)) {
+30
include/linux/blkdev.h
··· 1514 1514 return q->limits.max_integrity_segments; 1515 1515 } 1516 1516 1517 + static inline bool integrity_req_gap_back_merge(struct request *req, 1518 + struct bio *next) 1519 + { 1520 + struct bio_integrity_payload *bip = bio_integrity(req->bio); 1521 + struct bio_integrity_payload *bip_next = bio_integrity(next); 1522 + 1523 + return bvec_gap_to_prev(req->q, &bip->bip_vec[bip->bip_vcnt - 1], 1524 + bip_next->bip_vec[0].bv_offset); 1525 + } 1526 + 1527 + static inline bool integrity_req_gap_front_merge(struct request *req, 1528 + struct bio *bio) 1529 + { 1530 + struct bio_integrity_payload *bip = bio_integrity(bio); 1531 + struct bio_integrity_payload *bip_next = bio_integrity(req->bio); 1532 + 1533 + return bvec_gap_to_prev(req->q, &bip->bip_vec[bip->bip_vcnt - 1], 1534 + bip_next->bip_vec[0].bv_offset); 1535 + } 1536 + 1517 1537 #else /* CONFIG_BLK_DEV_INTEGRITY */ 1518 1538 1519 1539 struct bio; ··· 1599 1579 static inline bool blk_integrity_is_initialized(struct gendisk *g) 1600 1580 { 1601 1581 return 0; 1582 + } 1583 + static inline bool integrity_req_gap_back_merge(struct request *req, 1584 + struct bio *next) 1585 + { 1586 + return false; 1587 + } 1588 + static inline bool integrity_req_gap_front_merge(struct request *req, 1589 + struct bio *bio) 1590 + { 1591 + return false; 1602 1592 } 1603 1593 1604 1594 #endif /* CONFIG_BLK_DEV_INTEGRITY */