static int blk_phys_contig_segment(struct request_queue *q, struct bio *bio, struct bio *nxt) { if (!blk_queue_cluster(q)) return 0; if (bio->bi_seg_back_size + nxt->bi_seg_front_size > queue_max_segment_size(q)) return 0; if (!bio_has_data(bio)) return 1; if (!BIOVEC_PHYS_MERGEABLE(__BVEC_END(bio), __BVEC_START(nxt))) return 0; /* * bio and nxt are contiguous in memory; check if the queue allows * these two to be merged into one */ if (BIO_SEG_BOUNDARY(q, bio, nxt)) return 1; return 0; }
static ssize_t queue_max_segment_size_show(struct request_queue *q, char *page) { if (blk_queue_cluster(q)) return queue_var_show(queue_max_segment_size(q), (page)); return queue_var_show(PAGE_CACHE_SIZE, (page)); }
static int blk_phys_contig_segment(struct request_queue *q, struct bio *bio, struct bio *nxt) { struct bio_vec end_bv = { NULL }, nxt_bv; struct bvec_iter iter; if (!blk_queue_cluster(q)) return 0; if (bio->bi_seg_back_size + nxt->bi_seg_front_size > queue_max_segment_size(q)) return 0; if (!bio_has_data(bio)) return 1; bio_for_each_segment(end_bv, bio, iter) if (end_bv.bv_len == iter.bi_size) break; nxt_bv = bio_iovec(nxt); if (!BIOVEC_PHYS_MERGEABLE(&end_bv, &nxt_bv)) return 0; /* * bio and nxt are contiguous in memory; check if the queue allows * these two to be merged into one */ if (BIOVEC_SEG_BOUNDARY(q, &end_bv, &nxt_bv)) return 1; return 0; }
static unsigned int __blk_recalc_rq_segments(struct request_queue *q, struct bio *bio) { struct bio_vec *bv, *bvprv = NULL; int cluster, i, high, highprv = 1; unsigned int seg_size, nr_phys_segs; struct bio *fbio, *bbio; if (!bio) return 0; fbio = bio; cluster = blk_queue_cluster(q); seg_size = 0; nr_phys_segs = 0; for_each_bio(bio) { bio_for_each_segment(bv, bio, i) { /* */ high = page_to_pfn(bv->bv_page) > queue_bounce_pfn(q); if (high || highprv) goto new_segment; if (cluster) { if (seg_size + bv->bv_len > queue_max_segment_size(q)) goto new_segment; if (!BIOVEC_PHYS_MERGEABLE(bvprv, bv)) goto new_segment; if (!BIOVEC_SEG_BOUNDARY(q, bvprv, bv)) goto new_segment; if ((bvprv->bv_page != bv->bv_page) && (bvprv->bv_page + 1) != bv->bv_page) goto new_segment; seg_size += bv->bv_len; bvprv = bv; continue; } new_segment: if (nr_phys_segs == 1 && seg_size > fbio->bi_seg_front_size) fbio->bi_seg_front_size = seg_size; nr_phys_segs++; bvprv = bv; seg_size = bv->bv_len; highprv = high; } bbio = bio; }
static unsigned int __blk_recalc_rq_segments(struct request_queue *q, struct bio *bio) { unsigned int phys_size; struct bio_vec *bv, *bvprv = NULL; int cluster, i, high, highprv = 1; unsigned int seg_size, nr_phys_segs; struct bio *fbio, *bbio; if (!bio) return 0; fbio = bio; cluster = blk_queue_cluster(q); seg_size = 0; phys_size = nr_phys_segs = 0; for_each_bio(bio) { bio_for_each_segment(bv, bio, i) { /* * the trick here is making sure that a high page is * never considered part of another segment, since that * might change with the bounce page. */ high = page_to_pfn(bv->bv_page) > queue_bounce_pfn(q); if (high || highprv) goto new_segment; if (cluster) { if (seg_size + bv->bv_len > queue_max_segment_size(q)) goto new_segment; if (!BIOVEC_PHYS_MERGEABLE(bvprv, bv)) goto new_segment; if (!BIOVEC_SEG_BOUNDARY(q, bvprv, bv)) goto new_segment; seg_size += bv->bv_len; bvprv = bv; continue; } new_segment: if (nr_phys_segs == 1 && seg_size > fbio->bi_seg_front_size) fbio->bi_seg_front_size = seg_size; nr_phys_segs++; bvprv = bv; seg_size = bv->bv_len; highprv = high; } bbio = bio; }
static unsigned int __blk_recalc_rq_segments(struct request_queue *q, struct bio *bio) { struct bio_vec *bv, *bvprv = NULL; int cluster, i, high, highprv = 1; unsigned int seg_size, nr_phys_segs; struct bio *fbio, *bbio; if (!bio) return 0; fbio = bio; cluster = blk_queue_cluster(q); seg_size = 0; nr_phys_segs = 0; for_each_bio(bio) { bio_for_each_segment(bv, bio, i) { /* * the trick here is making sure that a high page is * never considered part of another segment, since that * might change with the bounce page. */ high = page_to_pfn(bv->bv_page) > queue_bounce_pfn(q); if (high || highprv) goto new_segment; if (cluster) { if (seg_size + bv->bv_len > queue_max_segment_size(q)) goto new_segment; if (!BIOVEC_PHYS_MERGEABLE(bvprv, bv)) goto new_segment; if (!BIOVEC_SEG_BOUNDARY(q, bvprv, bv)) goto new_segment; <<<<<<< HEAD if ((bvprv->bv_page != bv->bv_page) && (bvprv->bv_page + 1) != bv->bv_page) goto new_segment; ======= <<<<<<< HEAD if ((bvprv->bv_page != bv->bv_page) && (bvprv->bv_page + 1) != bv->bv_page) goto new_segment; ======= >>>>>>> 58a75b6a81be54a8b491263ca1af243e9d8617b9 >>>>>>> ae1773bb70f3d7cf73324ce8fba787e01d8fa9f2
/* * map a request to scatterlist, return number of sg entries setup. Caller * must make sure sg can hold rq->nr_phys_segments entries */ int blk_rq_map_sg(struct request_queue *q, struct request *rq, struct scatterlist *sglist) { struct bio_vec *bvec, *bvprv; struct req_iterator iter; struct scatterlist *sg; int nsegs, cluster; nsegs = 0; cluster = blk_queue_cluster(q); /* * for each bio in rq */ bvprv = NULL; sg = NULL; rq_for_each_segment(bvec, rq, iter) { __blk_segment_map_sg(q, bvec, sglist, &bvprv, &sg, &nsegs, &cluster); } /* segments in rq */
static int __blk_bios_map_sg(struct request_queue *q, struct bio *bio, struct scatterlist *sglist, struct scatterlist **sg) { struct bio_vec bvec, bvprv = { NULL }; struct bvec_iter iter; int nsegs, cluster; nsegs = 0; cluster = blk_queue_cluster(q); if (bio->bi_rw & REQ_DISCARD) { /* * This is a hack - drivers should be neither modifying the * biovec, nor relying on bi_vcnt - but because of * blk_add_request_payload(), a discard bio may or may not have * a payload we need to set up here (thank you Christoph) and * bi_vcnt is really the only way of telling if we need to. */ if (bio->bi_vcnt) goto single_segment; return 0; } if (bio->bi_rw & REQ_WRITE_SAME) { single_segment: *sg = sglist; bvec = bio_iovec(bio); sg_set_page(*sg, bvec.bv_page, bvec.bv_len, bvec.bv_offset); return 1; } for_each_bio(bio) bio_for_each_segment(bvec, bio, iter) __blk_segment_map_sg(q, &bvec, sglist, &bvprv, sg, &nsegs, &cluster); return nsegs; }
static unsigned int __blk_recalc_rq_segments(struct request_queue *q, struct bio *bio, bool no_sg_merge) { struct bio_vec bv, bvprv = { NULL }; int cluster, high, highprv = 1; unsigned int seg_size, nr_phys_segs; struct bio *fbio, *bbio; struct bvec_iter iter; if (!bio) return 0; /* * This should probably be returning 0, but blk_add_request_payload() * (Christoph!!!!) */ if (bio->bi_rw & REQ_DISCARD) return 1; if (bio->bi_rw & REQ_WRITE_SAME) return 1; fbio = bio; cluster = blk_queue_cluster(q); seg_size = 0; nr_phys_segs = 0; high = 0; for_each_bio(bio) { bio_for_each_segment(bv, bio, iter) { /* * If SG merging is disabled, each bio vector is * a segment */ if (no_sg_merge) goto new_segment; /* * the trick here is making sure that a high page is * never considered part of another segment, since * that might change with the bounce page. */ high = page_to_pfn(bv.bv_page) > queue_bounce_pfn(q); if (!high && !highprv && cluster) { if (seg_size + bv.bv_len > queue_max_segment_size(q)) goto new_segment; if (!BIOVEC_PHYS_MERGEABLE(&bvprv, &bv)) goto new_segment; if (!BIOVEC_SEG_BOUNDARY(q, &bvprv, &bv)) goto new_segment; seg_size += bv.bv_len; bvprv = bv; continue; } new_segment: if (nr_phys_segs == 1 && seg_size > fbio->bi_seg_front_size) fbio->bi_seg_front_size = seg_size; nr_phys_segs++; bvprv = bv; seg_size = bv.bv_len; highprv = high; } bbio = bio; } if (nr_phys_segs == 1 && seg_size > fbio->bi_seg_front_size) fbio->bi_seg_front_size = seg_size; if (seg_size > bbio->bi_seg_back_size) bbio->bi_seg_back_size = seg_size; return nr_phys_segs; }