* [PATCH] block: fix bio splitting on max sectors
@ 2016-01-22 18:29 Ming Lei
2016-01-22 18:43 ` Linus Torvalds
0 siblings, 1 reply; 5+ messages in thread
From: Ming Lei @ 2016-01-22 18:29 UTC (permalink / raw)
To: Jens Axboe, linux-kernel
Cc: linux-block, Linus Torvalds, Stefan Haberland, Keith Busch,
Ming Lei
After commit e36f62042880(block: split bios to maxpossible length),
bio can be splitted in the middle of a vector entry, then it
is easy to split out one bio which size isn't aligned with block
size, especially when the block size is bigger than 512.
This patch fixes the issue by making the max io size aligned
to logical block size.
Fixes: e36f62042880(block: split bios to maxpossible length)
Reported-by: Stefan Haberland <sth@linux.vnet.ibm.com>
Cc: Keith Busch <keith.busch@intel.com>
Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Ming Lei <tom.leiming@gmail.com>
---
block/blk-merge.c | 27 ++++++++++++++++++++-------
1 file changed, 20 insertions(+), 7 deletions(-)
diff --git a/block/blk-merge.c b/block/blk-merge.c
index 1699df5..ad22153 100644
--- a/block/blk-merge.c
+++ b/block/blk-merge.c
@@ -70,6 +70,18 @@ static struct bio *blk_bio_write_same_split(struct request_queue *q,
return bio_split(bio, q->limits.max_write_same_sectors, GFP_NOIO, bs);
}
+static inline unsigned get_max_io_size(struct request_queue *q,
+ struct bio *bio)
+{
+ unsigned sectors = blk_max_size_offset(q, bio->bi_iter.bi_sector);
+ unsigned mask = ~(queue_logical_block_size(q) - 1);
+
+ /* aligned to logical block size */
+ sectors = ((sectors << 9) & mask) >> 9;
+
+ return sectors;
+}
+
static struct bio *blk_bio_segment_split(struct request_queue *q,
struct bio *bio,
struct bio_set *bs,
@@ -81,6 +93,7 @@ static struct bio *blk_bio_segment_split(struct request_queue *q,
unsigned front_seg_size = bio->bi_seg_front_size;
bool do_split = true;
struct bio *new = NULL;
+ unsigned max_sectors;
bio_for_each_segment(bv, bio, iter) {
/*
@@ -90,20 +103,20 @@ static struct bio *blk_bio_segment_split(struct request_queue *q,
if (bvprvp && bvec_gap_to_prev(q, bvprvp, bv.bv_offset))
goto split;
- if (sectors + (bv.bv_len >> 9) >
- blk_max_size_offset(q, bio->bi_iter.bi_sector)) {
+ max_sectors = get_max_io_size(q, bio);
+ if (sectors + (bv.bv_len >> 9) > max_sectors) {
/*
* Consider this a new segment if we're splitting in
* the middle of this vector.
*/
if (nsegs < queue_max_segments(q) &&
- sectors < blk_max_size_offset(q,
- bio->bi_iter.bi_sector)) {
+ sectors < max_sectors) {
nsegs++;
- sectors = blk_max_size_offset(q,
- bio->bi_iter.bi_sector);
+ sectors = max_sectors;
}
- goto split;
+ if (sectors)
+ goto split;
+ /* Make this single bvec as the 1st segment */
}
if (bvprvp && blk_queue_cluster(q)) {
--
1.9.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH] block: fix bio splitting on max sectors
2016-01-22 18:29 [PATCH] block: fix bio splitting on max sectors Ming Lei
@ 2016-01-22 18:43 ` Linus Torvalds
2016-01-22 20:11 ` Keith Busch
0 siblings, 1 reply; 5+ messages in thread
From: Linus Torvalds @ 2016-01-22 18:43 UTC (permalink / raw)
To: Ming Lei
Cc: Jens Axboe, Linux Kernel Mailing List, linux-block,
Stefan Haberland, Keith Busch
On Fri, Jan 22, 2016 at 10:29 AM, Ming Lei <tom.leiming@gmail.com> wrote:
>
> This patch fixes the issue by making the max io size aligned
> to logical block size.
Looks better, thanks.
I'd suggest also moving the "max_sectors" variable into the
bio_for_each_segment() loop too just to keep variables with minimal
scope, but at least this is fairly legible.
Also:
> +static inline unsigned get_max_io_size(struct request_queue *q,
> + struct bio *bio)
> +{
> + unsigned sectors = blk_max_size_offset(q, bio->bi_iter.bi_sector);
> + unsigned mask = ~(queue_logical_block_size(q) - 1);
> +
> + /* aligned to logical block size */
> + sectors = ((sectors << 9) & mask) >> 9;
this could be written as
unsigned mask = queue_logical_block_size(q) - 1;
sectors = sectors & ~(mask >> 9);
avoiding the extra shift. That also avoids the possible overflow that
that extra left-shift introduces. Hmm?
Linus
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] block: fix bio splitting on max sectors
2016-01-22 18:43 ` Linus Torvalds
@ 2016-01-22 20:11 ` Keith Busch
[not found] ` <CA+55aFxkbTy13mPEQmoXY4L9gbakwz5NQCiLaEnjfhFtUXjtYg@mail.gmail.com>
0 siblings, 1 reply; 5+ messages in thread
From: Keith Busch @ 2016-01-22 20:11 UTC (permalink / raw)
To: Linus Torvalds
Cc: Ming Lei, Jens Axboe, Linux Kernel Mailing List, linux-block,
Stefan Haberland
On Fri, Jan 22, 2016 at 10:43:59AM -0800, Linus Torvalds wrote:
> On Fri, Jan 22, 2016 at 10:29 AM, Ming Lei <tom.leiming@gmail.com> wrote:
> >
> > This patch fixes the issue by making the max io size aligned
> > to logical block size.
>
> Looks better, thanks.
>
> I'd suggest also moving the "max_sectors" variable into the
> bio_for_each_segment() loop too just to keep variables with minimal
> scope, but at least this is fairly legible.
The value of max_sectors doesn't change in this function, so its
calculation could be done just once instead of with each segment
iteration.
Other than that, thanks Ming, the fix looks good to me. Third try's
a charm?
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] block: fix bio splitting on max sectors
[not found] ` <CA+55aFxkbTy13mPEQmoXY4L9gbakwz5NQCiLaEnjfhFtUXjtYg@mail.gmail.com>
@ 2016-01-22 20:32 ` Linus Torvalds
2016-01-22 20:33 ` Keith Busch
1 sibling, 0 replies; 5+ messages in thread
From: Linus Torvalds @ 2016-01-22 20:32 UTC (permalink / raw)
To: Keith Busch
Cc: Stefan Haberland, Jens Axboe, Linux Kernel Mailing List,
linux-block, Ming Lei
[ Grr. re-sending due to stupid html from android mobile app. ]
On Jan 22, 2016 12:11 PM, "Keith Busch" <keith.busch@intel.com> wrote:
>
> The value of max_sectors doesn't change in this function
Why do you say that? It depends on the offset, so it clearly *does* change.
Now, if the patch did what I suggested and made max_sector and the cluster
size thing be separate, then *those* would indeed be constant over the whole
function.
Linus
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] block: fix bio splitting on max sectors
[not found] ` <CA+55aFxkbTy13mPEQmoXY4L9gbakwz5NQCiLaEnjfhFtUXjtYg@mail.gmail.com>
2016-01-22 20:32 ` Linus Torvalds
@ 2016-01-22 20:33 ` Keith Busch
1 sibling, 0 replies; 5+ messages in thread
From: Keith Busch @ 2016-01-22 20:33 UTC (permalink / raw)
To: Linus Torvalds
Cc: Stefan Haberland, Jens Axboe, Linux Kernel Mailing List,
linux-block, Ming Lei
On Fri, Jan 22, 2016 at 12:22:18PM -0800, Linus Torvalds wrote:
>
> On Jan 22, 2016 12:11 PM, "Keith Busch" <keith.busch@intel.com> wrote:
> >
> > The value of max_sectors doesn't change in this function
>
> Why do you say that? It depends on the offset, so it clearly *does* change.
The only "offset" used is the bio's start sector, which doesn't change.
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2016-01-22 20:33 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-01-22 18:29 [PATCH] block: fix bio splitting on max sectors Ming Lei
2016-01-22 18:43 ` Linus Torvalds
2016-01-22 20:11 ` Keith Busch
[not found] ` <CA+55aFxkbTy13mPEQmoXY4L9gbakwz5NQCiLaEnjfhFtUXjtYg@mail.gmail.com>
2016-01-22 20:32 ` Linus Torvalds
2016-01-22 20:33 ` Keith Busch
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).