Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1315216 > unrolled thread
| Started by | Ming Lei <tom.leiming@gmail.com> |
|---|---|
| First post | 2016-01-22 19:40 +0100 |
| Last post | 2016-01-22 21:40 +0100 |
| Articles | 5 — 3 participants |
Back to article view | Back to linux.kernel
[PATCH] block: fix bio splitting on max sectors Ming Lei <tom.leiming@gmail.com> - 2016-01-22 19:40 +0100
Re: [PATCH] block: fix bio splitting on max sectors Linus Torvalds <torvalds@linux-foundation.org> - 2016-01-22 19:50 +0100
Re: [PATCH] block: fix bio splitting on max sectors Keith Busch <keith.busch@intel.com> - 2016-01-22 21:20 +0100
Re: [PATCH] block: fix bio splitting on max sectors Keith Busch <keith.busch@intel.com> - 2016-01-22 21:40 +0100
Re: [PATCH] block: fix bio splitting on max sectors Linus Torvalds <torvalds@linux-foundation.org> - 2016-01-22 21:40 +0100
| From | Ming Lei <tom.leiming@gmail.com> |
|---|---|
| Date | 2016-01-22 19:40 +0100 |
| Subject | [PATCH] block: fix bio splitting on max sectors |
| Message-ID | <qTOMN-7Ux-1@gated-at.bofh.it> |
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
[toc] | [next] | [standalone]
| From | Linus Torvalds <torvalds@linux-foundation.org> |
|---|---|
| Date | 2016-01-22 19:50 +0100 |
| Message-ID | <qTOWt-7Yf-9@gated-at.bofh.it> |
| In reply to | #1315216 |
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
[toc] | [prev] | [next] | [standalone]
| From | Keith Busch <keith.busch@intel.com> |
|---|---|
| Date | 2016-01-22 21:20 +0100 |
| Message-ID | <qTQlA-Ac-1@gated-at.bofh.it> |
| In reply to | #1315222 |
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?
[toc] | [prev] | [next] | [standalone]
| From | Keith Busch <keith.busch@intel.com> |
|---|---|
| Date | 2016-01-22 21:40 +0100 |
| Message-ID | <qTQEX-IC-11@gated-at.bofh.it> |
| In reply to | #1315249 |
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.
[toc] | [prev] | [next] | [standalone]
| From | Linus Torvalds <torvalds@linux-foundation.org> |
|---|---|
| Date | 2016-01-22 21:40 +0100 |
| Message-ID | <qTQEX-IC-19@gated-at.bofh.it> |
| In reply to | #1315249 |
[ 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
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web