From 24edb63b854ab73fa1bf86b4dde98cdb648cba35 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Mon, 12 Jun 2023 13:33:12 -0700 Subject: [PATCH] Reapply "ANDROID: block: Add support for filesystem requests and small segments" This reverts commit I764adf995cae6b485d4d98e410c78128a88647e0. Bug: 333812722 Bug: 308663717 Bug: 319125789 Change-Id: Ie7f03b9d1ab67a33ccbc4311ba26cd746e1aaa22 Signed-off-by: Bart Van Assche [jyescas@google.com: Call blk_segments() in blk_mq_submit_bio() for the case when request is defined or it is null] Signed-off-by: Juan Yescas --- block/blk-merge.c | 8 ++++++-- block/blk-mq.c | 4 ++++ block/blk.h | 11 +++++------ 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/block/blk-merge.c b/block/blk-merge.c index cc7f6a4a255c..0f62c68b455c 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -285,7 +285,8 @@ static struct bio *bio_split_rw(struct bio *bio, struct queue_limits *lim, if (nsegs < lim->max_segments && bytes + bv.bv_len <= max_bytes && bv.bv_offset + bv.bv_len <= PAGE_SIZE) { - nsegs++; + /* single-page bvec optimization */ + nsegs += blk_segments(lim, bv.bv_len); bytes += bv.bv_len; } else { if (bvec_split_segs(lim, &bv, &nsegs, &bytes, @@ -533,7 +534,10 @@ static int __blk_bios_map_sg(struct request_queue *q, struct bio *bio, __blk_segment_map_sg_merge(q, &bvec, &bvprv, sg)) goto next_bvec; - if (bvec.bv_offset + bvec.bv_len <= PAGE_SIZE) + if (bvec.bv_offset + bvec.bv_len <= PAGE_SIZE && + (!blk_queue_sub_page_limits(&q->limits) || + bvec.bv_len <= q->limits.max_segment_size)) + /* single-segment bvec optimization */ nsegs += __blk_bvec_map_sg(bvec, sglist, sg); else nsegs += blk_bvec_map_sg(q, &bvec, sglist, sg); diff --git a/block/blk-mq.c b/block/blk-mq.c index 0e56e3e73019..276b0a6eaec5 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -2956,6 +2956,8 @@ void blk_mq_submit_bio(struct bio *bio) bio = __bio_split_to_limits(bio, &q->limits, &nr_segs); if (!bio) return; + } else if (bio->bi_vcnt == 1) { + nr_segs = blk_segments(&q->limits, bio->bi_io_vec[0].bv_len); } if (!bio_integrity_prep(bio)) return; @@ -2971,6 +2973,8 @@ void blk_mq_submit_bio(struct bio *bio) bio = __bio_split_to_limits(bio, &q->limits, &nr_segs); if (!bio) goto fail; + } else if (bio->bi_vcnt == 1) { + nr_segs = blk_segments(&q->limits, bio->bi_io_vec[0].bv_len); } if (!bio_integrity_prep(bio)) goto fail; diff --git a/block/blk.h b/block/blk.h index f6e59cd7cfa1..82143bf38064 100644 --- a/block/blk.h +++ b/block/blk.h @@ -337,13 +337,12 @@ static inline bool bio_may_exceed_limits(struct bio *bio, } /* - * All drivers must accept single-segments bios that are <= PAGE_SIZE. - * This is a quick and dirty check that relies on the fact that - * bi_io_vec[0] is always valid if a bio has data. The check might - * lead to occasional false negatives when bios are cloned, but compared - * to the performance impact of cloned bios themselves the loop below - * doesn't matter anyway. + * Check whether bio splitting should be performed. This check may + * trigger the bio splitting code even if splitting is not necessary. */ + if (blk_queue_sub_page_limits(lim) && bio->bi_io_vec && + bio->bi_io_vec->bv_len > lim->max_segment_size) + return true; return lim->chunk_sectors || bio->bi_vcnt != 1 || bio->bi_io_vec->bv_len + bio->bi_io_vec->bv_offset > PAGE_SIZE; }