bool blk_integrity_merge_bio(struct request_queue *q, struct request *req, struct bio *bio) { int nr_integrity_segs; struct bio *next = bio->bi_next; if (blk_integrity_rq(req) == 0 && bio_integrity(bio) == NULL) return true; if (blk_integrity_rq(req) == 0 || bio_integrity(bio) == NULL) return false; if (bio_integrity(req->bio)->bip_flags != bio_integrity(bio)->bip_flags) return false; bio->bi_next = NULL; nr_integrity_segs = blk_rq_count_integrity_sg(q, bio); bio->bi_next = next; if (req->nr_integrity_segments + nr_integrity_segs > q->limits.max_integrity_segments) return false; req->nr_integrity_segments += nr_integrity_segs; return true; }
int blk_integrity_merge_rq(struct request_queue *q, struct request *req, struct request *next) { if (blk_integrity_rq(req) != blk_integrity_rq(next)) return -1; if (req->nr_integrity_segments + next->nr_integrity_segments > q->limits.max_integrity_segments) return -1; return 0; }
bool blk_integrity_merge_rq(struct request_queue *q, struct request *req, struct request *next) { 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) return false; if (req->nr_integrity_segments + next->nr_integrity_segments > q->limits.max_integrity_segments) return false; return true; }
static int ll_merge_requests_fn(struct request_queue *q, struct request *req, struct request *next) { int total_phys_segments; unsigned int seg_size = req->biotail->bi_seg_back_size + next->bio->bi_seg_front_size; /* * First check if the either of the requests are re-queued * requests. Can't merge them if they are. */ if (req_no_special_merge(req) || req_no_special_merge(next)) return 0; /* * Will it become too large? */ if ((blk_rq_sectors(req) + blk_rq_sectors(next)) > blk_rq_get_max_sectors(req)) return 0; total_phys_segments = req->nr_phys_segments + next->nr_phys_segments; if (blk_phys_contig_segment(q, req->biotail, next->bio)) { if (req->nr_phys_segments == 1) req->bio->bi_seg_front_size = seg_size; if (next->nr_phys_segments == 1) next->biotail->bi_seg_back_size = seg_size; total_phys_segments--; } if (total_phys_segments > queue_max_segments(q)) return 0; if (blk_integrity_rq(req) && blk_integrity_merge_rq(q, req, next)) return 0; /* Merge is OK... */ req->nr_phys_segments = total_phys_segments; return 1; }
bool blk_rq_merge_ok(struct request *rq, struct bio *bio) { struct request_queue *q = rq->q; if (!rq_mergeable(rq) || !bio_mergeable(bio)) return false; if (!blk_check_merge_flags(rq->cmd_flags, bio->bi_rw)) return false; /* different data direction or already started, don't merge */ if (bio_data_dir(bio) != rq_data_dir(rq)) return false; /* must be same device and not a special request */ if (rq->rq_disk != bio->bi_bdev->bd_disk || req_no_special_merge(rq)) return false; /* only merge integrity protected bio into ditto rq */ if (bio_integrity(bio) != blk_integrity_rq(rq)) return false; /* must be using the same buffer */ if (rq->cmd_flags & REQ_WRITE_SAME && !blk_write_same_mergeable(rq->bio, bio)) return false; if (q->queue_flags & (1 << QUEUE_FLAG_SG_GAPS)) { struct bio_vec *bprev; bprev = &rq->biotail->bi_io_vec[rq->biotail->bi_vcnt - 1]; if (bvec_gap_to_prev(bprev, bio->bi_io_vec[0].bv_offset)) return false; } return true; }