[PATCH 2/3] block: Refuse request/bio merges with gaps in the integrity payload
Sagi Grimberg
sagig at mellanox.com
Wed Jul 15 06:19:15 PDT 2015
If a driver turned on QUEUE_FLAG_SG_GAPS, 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 at mellanox.com>
---
block/blk-integrity.c | 32 +++++++++++++++++++++++++++-----
1 file changed, 27 insertions(+), 5 deletions(-)
diff --git a/block/blk-integrity.c b/block/blk-integrity.c
index 79ffb48..bb18e0a 100644
--- a/block/blk-integrity.c
+++ b/block/blk-integrity.c
@@ -189,20 +189,31 @@ EXPORT_SYMBOL(blk_integrity_compare);
bool blk_integrity_merge_rq(struct request_queue *q, struct request *req,
struct request *next)
{
+ struct bio_integrity_payload *bip = bio_integrity(req->bio);
+ struct bio_integrity_payload *bip_next = bio_integrity(next->bio);
+
if (blk_integrity_rq(req) == 0 && blk_integrity_rq(next) == 0)
return true;
if (blk_integrity_rq(req) == 0 || blk_integrity_rq(next) == 0)
return false;
- if (bio_integrity(req->bio)->bip_flags !=
- bio_integrity(next->bio)->bip_flags)
+ if (bip->bip_flags != bip_next->bip_flags)
return false;
if (req->nr_integrity_segments + next->nr_integrity_segments >
q->limits.max_integrity_segments)
return false;
+ if (q->queue_flags & (1 << QUEUE_FLAG_SG_GAPS)) {
+ struct bio_vec *iv, *iv_next;
+
+ iv = &bip->bip_vec[bip->bip_vcnt];
+ iv_next = &bip_next->bip_vec[0];
+ if (bvec_gap_to_prev(iv, iv_next->bv_offset))
+ return false;
+ }
+
return true;
}
EXPORT_SYMBOL(blk_integrity_merge_rq);
@@ -212,16 +223,27 @@ bool blk_integrity_merge_bio(struct request_queue *q, struct request *req,
{
int nr_integrity_segs;
struct bio *next = bio->bi_next;
+ struct bio_integrity_payload *bip = bio_integrity(req->bio);
+ struct bio_integrity_payload *bip_next = bio_integrity(bio);
- if (blk_integrity_rq(req) == 0 && bio_integrity(bio) == NULL)
+ if (blk_integrity_rq(req) == 0 && bip_next == NULL)
return true;
- if (blk_integrity_rq(req) == 0 || bio_integrity(bio) == NULL)
+ if (blk_integrity_rq(req) == 0 || bip_next == NULL)
return false;
- if (bio_integrity(req->bio)->bip_flags != bio_integrity(bio)->bip_flags)
+ if (bip->bip_flags != bip_next->bip_flags)
return false;
+ if (q->queue_flags & (1 << QUEUE_FLAG_SG_GAPS)) {
+ struct bio_vec *iv, *iv_next;
+
+ iv = &bip->bip_vec[bip->bip_vcnt - 1];
+ iv_next = &bip_next->bip_vec[bip_next->bip_vcnt];
+ if (bvec_gap_to_prev(iv, iv_next->bv_offset))
+ return false;
+ }
+
bio->bi_next = NULL;
nr_integrity_segs = blk_rq_count_integrity_sg(q, bio);
bio->bi_next = next;
--
1.8.4.3
More information about the Linux-nvme
mailing list