We'd occasionally merge requests with conflicting integrity flags. Introduce a merge helper which checks that the requests have compatible integrity payloads.
Unified · Split
| @@ -186,37 +186,53 @@ int blk_integrity_compare(struct gendisk *gd1, struct gendisk *gd2) · 185 unmodified lines | ||
| 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 | + | |
| 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 | 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 @@ static inline int ll_new_hw_segment(struct request_queue *q, · 312 unmodified lines | ||
| 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 @@ static int ll_merge_requests_fn(struct request_queue *q, struct request *req, · 90 unmodified lines | ||
| 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 @@ bool blk_rq_merge_ok(struct request *rq, struct bio *bio) · 173 unmodified lines | ||
| 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 */ |
| @@ -1497,10 +1497,10 @@ extern int blk_integrity_compare(struct gendisk *, struct gendisk *); · 1496 unmodified lines | ||
| 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) |
| @@ -1580,15 +1580,15 @@ static inline unsigned short queue_max_integrity_segments(struct request_queue * · 73 unmodified lines | ||
| 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 | } |