ANDROID: block: Add support for filesystem requests and small segments

Add support in the bio splitting code and also in the bio submission code
for bios with segments smaller than the page size.

Bug: 308663717
Bug: 319125789
Change-Id: I056659cf86c04fb095aa01cd3d274d29417782ac
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Signed-off-by: Juan Yescas <jyescas@google.com>
This commit is contained in:
Bart Van Assche 2023-06-12 13:33:12 -07:00 committed by Juan Yescas
parent 879eff2954
commit 8a2f432fcb
3 changed files with 13 additions and 8 deletions

View File

@ -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);

View File

@ -2951,6 +2951,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))

View File

@ -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;
}