diff options
author | Kent Overstreet <koverstreet@google.com> | 2013-04-22 14:44:24 -0700 |
---|---|---|
committer | Kent Overstreet <koverstreet@google.com> | 2013-04-22 14:44:24 -0700 |
commit | a09ded8edf9ed4009930713e101249084cbcea5c (patch) | |
tree | e0a451f20434c8a0bfc28a36421d1b025be6dad5 /drivers | |
parent | 1545f13730be43278ce12f4af7e51b4dee5066a8 (diff) |
bcache: Fix merge_bvec_fn usage for when it modifies the bvm
Stacked md devices reuse the bvm for the subordinate device, causing
problems...
Reported-by: Michael Balser <michael.balser@profitbricks.com>
Signed-off-by: Kent Overstreet <koverstreet@google.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/md/bcache/io.c | 17 |
1 files changed, 8 insertions, 9 deletions
diff --git a/drivers/md/bcache/io.c b/drivers/md/bcache/io.c index 5304eaab6cb..48efd4dea64 100644 --- a/drivers/md/bcache/io.c +++ b/drivers/md/bcache/io.c @@ -163,13 +163,6 @@ static unsigned bch_bio_max_sectors(struct bio *bio) struct bio_vec *bv, *end = bio_iovec(bio) + min_t(int, bio_segments(bio), max_segments); - struct bvec_merge_data bvm = { - .bi_bdev = bio->bi_bdev, - .bi_sector = bio->bi_sector, - .bi_size = 0, - .bi_rw = bio->bi_rw, - }; - if (bio->bi_rw & REQ_DISCARD) return min(ret, q->limits.max_discard_sectors); @@ -178,12 +171,18 @@ static unsigned bch_bio_max_sectors(struct bio *bio) ret = 0; for (bv = bio_iovec(bio); bv < end; bv++) { + struct bvec_merge_data bvm = { + .bi_bdev = bio->bi_bdev, + .bi_sector = bio->bi_sector, + .bi_size = ret << 9, + .bi_rw = bio->bi_rw, + }; + if (q->merge_bvec_fn && q->merge_bvec_fn(q, &bvm, bv) < (int) bv->bv_len) break; - ret += bv->bv_len >> 9; - bvm.bi_size += bv->bv_len; + ret += bv->bv_len >> 9; } } |