From a8821f3f32bea173c7f9546b3b025898f0e09f58 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Sun, 18 Jun 2017 14:38:58 +1000 Subject: block: Improvements to bounce-buffer handling Since commit 23688bf4f830 ("block: ensure to split after potentially bouncing a bio") blk_queue_bounce() is called *before* blk_queue_split(). This means that: 1/ the comments blk_queue_split() about bounce buffers are irrelevant, and 2/ a very large bio (more than BIO_MAX_PAGES) will no longer be split before it arrives at blk_queue_bounce(), leading to the possibility that bio_clone_bioset() will fail and a NULL will be dereferenced. Separately, blk_queue_bounce() shouldn't use fs_bio_set as the bio being copied could be from the same set, and this could lead to a deadlock. So: - allocate 2 private biosets for blk_queue_bounce, one for splitting enormous bios and one for cloning bios. - add code to split a bio that exceeds BIO_MAX_PAGES. - Fix up the comments in blk_queue_split() Credit-to: Ming Lei (suggested using single bio_for_each_segment loop) Reviewed-by: Ming Lei Reviewed-by: Christoph Hellwig Signed-off-by: NeilBrown Signed-off-by: Jens Axboe --- block/blk-merge.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) (limited to 'block/blk-merge.c') diff --git a/block/blk-merge.c b/block/blk-merge.c index d59074556703..51c84540d3bb 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -117,17 +117,11 @@ static struct bio *blk_bio_segment_split(struct request_queue *q, * each holds at most BIO_MAX_PAGES bvecs because * bio_clone() can fail to allocate big bvecs. * - * It should have been better to apply the limit per - * request queue in which bio_clone() is involved, - * instead of globally. The biggest blocker is the - * bio_clone() in bio bounce. + * Those drivers which will need to use bio_clone() + * should tell us in some way. For now, impose the + * BIO_MAX_PAGES limit on all queues. * - * If bio is splitted by this reason, we should have - * allowed to continue bios merging, but don't do - * that now for making the change simple. - * - * TODO: deal with bio bounce's bio_clone() gracefully - * and convert the global limit into per-queue limit. + * TODO: handle users of bio_clone() differently. */ if (bvecs++ >= BIO_MAX_PAGES) goto split; -- cgit v1.2.3