|
@@ -11,13 +11,16 @@
|
|
|
|
|
|
static struct bio *blk_bio_discard_split(struct request_queue *q,
|
|
|
struct bio *bio,
|
|
|
- struct bio_set *bs)
|
|
|
+ struct bio_set *bs,
|
|
|
+ unsigned *nsegs)
|
|
|
{
|
|
|
unsigned int max_discard_sectors, granularity;
|
|
|
int alignment;
|
|
|
sector_t tmp;
|
|
|
unsigned split_sectors;
|
|
|
|
|
|
+ *nsegs = 1;
|
|
|
+
|
|
|
/* Zero-sector (unknown) and one-sector granularities are the same. */
|
|
|
granularity = max(q->limits.discard_granularity >> 9, 1U);
|
|
|
|
|
@@ -51,8 +54,11 @@ static struct bio *blk_bio_discard_split(struct request_queue *q,
|
|
|
|
|
|
static struct bio *blk_bio_write_same_split(struct request_queue *q,
|
|
|
struct bio *bio,
|
|
|
- struct bio_set *bs)
|
|
|
+ struct bio_set *bs,
|
|
|
+ unsigned *nsegs)
|
|
|
{
|
|
|
+ *nsegs = 1;
|
|
|
+
|
|
|
if (!q->limits.max_write_same_sectors)
|
|
|
return NULL;
|
|
|
|
|
@@ -64,7 +70,8 @@ static struct bio *blk_bio_write_same_split(struct request_queue *q,
|
|
|
|
|
|
static struct bio *blk_bio_segment_split(struct request_queue *q,
|
|
|
struct bio *bio,
|
|
|
- struct bio_set *bs)
|
|
|
+ struct bio_set *bs,
|
|
|
+ unsigned *segs)
|
|
|
{
|
|
|
struct bio_vec bv, bvprv, *bvprvp = NULL;
|
|
|
struct bvec_iter iter;
|
|
@@ -106,22 +113,30 @@ new_segment:
|
|
|
sectors += bv.bv_len >> 9;
|
|
|
}
|
|
|
|
|
|
+ *segs = nsegs;
|
|
|
return NULL;
|
|
|
split:
|
|
|
+ *segs = nsegs;
|
|
|
return bio_split(bio, sectors, GFP_NOIO, bs);
|
|
|
}
|
|
|
|
|
|
void blk_queue_split(struct request_queue *q, struct bio **bio,
|
|
|
struct bio_set *bs)
|
|
|
{
|
|
|
- struct bio *split;
|
|
|
+ struct bio *split, *res;
|
|
|
+ unsigned nsegs;
|
|
|
|
|
|
if ((*bio)->bi_rw & REQ_DISCARD)
|
|
|
- split = blk_bio_discard_split(q, *bio, bs);
|
|
|
+ split = blk_bio_discard_split(q, *bio, bs, &nsegs);
|
|
|
else if ((*bio)->bi_rw & REQ_WRITE_SAME)
|
|
|
- split = blk_bio_write_same_split(q, *bio, bs);
|
|
|
+ split = blk_bio_write_same_split(q, *bio, bs, &nsegs);
|
|
|
else
|
|
|
- split = blk_bio_segment_split(q, *bio, q->bio_split);
|
|
|
+ split = blk_bio_segment_split(q, *bio, q->bio_split, &nsegs);
|
|
|
+
|
|
|
+ /* physical segments can be figured out during splitting */
|
|
|
+ res = split ? split : *bio;
|
|
|
+ res->bi_phys_segments = nsegs;
|
|
|
+ bio_set_flag(res, BIO_SEG_VALID);
|
|
|
|
|
|
if (split) {
|
|
|
bio_chain(split, *bio);
|