Commit cc371e66e340f35eed8dc4651c7c18e754c7fb26

Authored by Alasdair G Kergon
Committed by Jens Axboe
1 parent b24498d477

Add bvec_merge_data to handle stacked devices and ->merge_bvec()

When devices are stacked, one device's merge_bvec_fn may need to perform
the mapping and then call one or more functions for its underlying devices.

The following bio fields are used:
  bio->bi_sector
  bio->bi_bdev
  bio->bi_size
  bio->bi_rw  using bio_data_dir()

This patch creates a new struct bvec_merge_data holding a copy of those
fields to avoid having to change them directly in the struct bio when
going down the stack only to have to change them back again on the way
back up.  (And then when the bio gets mapped for real, the whole
exercise gets repeated, but that's a problem for another day...)

Signed-off-by: Alasdair G Kergon <agk@redhat.com>
Cc: Neil Brown <neilb@suse.de>
Cc: Milan Broz <mbroz@redhat.com>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>

Showing 7 changed files with 60 additions and 29 deletions Side-by-side Diff

drivers/block/pktcdvd.c
... ... @@ -2633,11 +2633,12 @@
2633 2633  
2634 2634  
2635 2635  
2636   -static int pkt_merge_bvec(struct request_queue *q, struct bio *bio, struct bio_vec *bvec)
  2636 +static int pkt_merge_bvec(struct request_queue *q, struct bvec_merge_data *bmd,
  2637 + struct bio_vec *bvec)
2637 2638 {
2638 2639 struct pktcdvd_device *pd = q->queuedata;
2639   - sector_t zone = ZONE(bio->bi_sector, pd);
2640   - int used = ((bio->bi_sector - zone) << 9) + bio->bi_size;
  2640 + sector_t zone = ZONE(bmd->bi_sector, pd);
  2641 + int used = ((bmd->bi_sector - zone) << 9) + bmd->bi_size;
2641 2642 int remaining = (pd->settings.size << 9) - used;
2642 2643 int remaining2;
2643 2644  
... ... @@ -2645,7 +2646,7 @@
2645 2646 * A bio <= PAGE_SIZE must be allowed. If it crosses a packet
2646 2647 * boundary, pkt_make_request() will split the bio.
2647 2648 */
2648   - remaining2 = PAGE_SIZE - bio->bi_size;
  2649 + remaining2 = PAGE_SIZE - bmd->bi_size;
2649 2650 remaining = max(remaining, remaining2);
2650 2651  
2651 2652 BUG_ON(remaining < 0);
... ... @@ -50,17 +50,19 @@
50 50 /**
51 51 * linear_mergeable_bvec -- tell bio layer if two requests can be merged
52 52 * @q: request queue
53   - * @bio: the buffer head that's been built up so far
  53 + * @bvm: properties of new bio
54 54 * @biovec: the request that could be merged to it.
55 55 *
56 56 * Return amount of bytes we can take at this offset
57 57 */
58   -static int linear_mergeable_bvec(struct request_queue *q, struct bio *bio, struct bio_vec *biovec)
  58 +static int linear_mergeable_bvec(struct request_queue *q,
  59 + struct bvec_merge_data *bvm,
  60 + struct bio_vec *biovec)
59 61 {
60 62 mddev_t *mddev = q->queuedata;
61 63 dev_info_t *dev0;
62   - unsigned long maxsectors, bio_sectors = bio->bi_size >> 9;
63   - sector_t sector = bio->bi_sector + get_start_sect(bio->bi_bdev);
  64 + unsigned long maxsectors, bio_sectors = bvm->bi_size >> 9;
  65 + sector_t sector = bvm->bi_sector + get_start_sect(bvm->bi_bdev);
64 66  
65 67 dev0 = which_dev(mddev, sector);
66 68 maxsectors = (dev0->size << 1) - (sector - (dev0->offset<<1));
... ... @@ -241,18 +241,20 @@
241 241 /**
242 242 * raid0_mergeable_bvec -- tell bio layer if a two requests can be merged
243 243 * @q: request queue
244   - * @bio: the buffer head that's been built up so far
  244 + * @bvm: properties of new bio
245 245 * @biovec: the request that could be merged to it.
246 246 *
247 247 * Return amount of bytes we can accept at this offset
248 248 */
249   -static int raid0_mergeable_bvec(struct request_queue *q, struct bio *bio, struct bio_vec *biovec)
  249 +static int raid0_mergeable_bvec(struct request_queue *q,
  250 + struct bvec_merge_data *bvm,
  251 + struct bio_vec *biovec)
250 252 {
251 253 mddev_t *mddev = q->queuedata;
252   - sector_t sector = bio->bi_sector + get_start_sect(bio->bi_bdev);
  254 + sector_t sector = bvm->bi_sector + get_start_sect(bvm->bi_bdev);
253 255 int max;
254 256 unsigned int chunk_sectors = mddev->chunk_size >> 9;
255   - unsigned int bio_sectors = bio->bi_size >> 9;
  257 + unsigned int bio_sectors = bvm->bi_size >> 9;
256 258  
257 259 max = (chunk_sectors - ((sector & (chunk_sectors - 1)) + bio_sectors)) << 9;
258 260 if (max < 0) max = 0; /* bio_add cannot handle a negative return */
... ... @@ -439,26 +439,27 @@
439 439 /**
440 440 * raid10_mergeable_bvec -- tell bio layer if a two requests can be merged
441 441 * @q: request queue
442   - * @bio: the buffer head that's been built up so far
  442 + * @bvm: properties of new bio
443 443 * @biovec: the request that could be merged to it.
444 444 *
445 445 * Return amount of bytes we can accept at this offset
446 446 * If near_copies == raid_disk, there are no striping issues,
447 447 * but in that case, the function isn't called at all.
448 448 */
449   -static int raid10_mergeable_bvec(struct request_queue *q, struct bio *bio,
450   - struct bio_vec *bio_vec)
  449 +static int raid10_mergeable_bvec(struct request_queue *q,
  450 + struct bvec_merge_data *bvm,
  451 + struct bio_vec *biovec)
451 452 {
452 453 mddev_t *mddev = q->queuedata;
453   - sector_t sector = bio->bi_sector + get_start_sect(bio->bi_bdev);
  454 + sector_t sector = bvm->bi_sector + get_start_sect(bvm->bi_bdev);
454 455 int max;
455 456 unsigned int chunk_sectors = mddev->chunk_size >> 9;
456   - unsigned int bio_sectors = bio->bi_size >> 9;
  457 + unsigned int bio_sectors = bvm->bi_size >> 9;
457 458  
458 459 max = (chunk_sectors - ((sector & (chunk_sectors - 1)) + bio_sectors)) << 9;
459 460 if (max < 0) max = 0; /* bio_add cannot handle a negative return */
460   - if (max <= bio_vec->bv_len && bio_sectors == 0)
461   - return bio_vec->bv_len;
  461 + if (max <= biovec->bv_len && bio_sectors == 0)
  462 + return biovec->bv_len;
462 463 else
463 464 return max;
464 465 }
... ... @@ -3319,15 +3319,17 @@
3319 3319 /* We want read requests to align with chunks where possible,
3320 3320 * but write requests don't need to.
3321 3321 */
3322   -static int raid5_mergeable_bvec(struct request_queue *q, struct bio *bio, struct bio_vec *biovec)
  3322 +static int raid5_mergeable_bvec(struct request_queue *q,
  3323 + struct bvec_merge_data *bvm,
  3324 + struct bio_vec *biovec)
3323 3325 {
3324 3326 mddev_t *mddev = q->queuedata;
3325   - sector_t sector = bio->bi_sector + get_start_sect(bio->bi_bdev);
  3327 + sector_t sector = bvm->bi_sector + get_start_sect(bvm->bi_bdev);
3326 3328 int max;
3327 3329 unsigned int chunk_sectors = mddev->chunk_size >> 9;
3328   - unsigned int bio_sectors = bio->bi_size >> 9;
  3330 + unsigned int bio_sectors = bvm->bi_size >> 9;
3329 3331  
3330   - if (bio_data_dir(bio) == WRITE)
  3332 + if ((bvm->bi_rw & 1) == WRITE)
3331 3333 return biovec->bv_len; /* always allow writes to be mergeable */
3332 3334  
3333 3335 max = (chunk_sectors - ((sector & (chunk_sectors - 1)) + bio_sectors)) << 9;
... ... @@ -325,10 +325,19 @@
325 325 if (page == prev->bv_page &&
326 326 offset == prev->bv_offset + prev->bv_len) {
327 327 prev->bv_len += len;
328   - if (q->merge_bvec_fn &&
329   - q->merge_bvec_fn(q, bio, prev) < len) {
330   - prev->bv_len -= len;
331   - return 0;
  328 +
  329 + if (q->merge_bvec_fn) {
  330 + struct bvec_merge_data bvm = {
  331 + .bi_bdev = bio->bi_bdev,
  332 + .bi_sector = bio->bi_sector,
  333 + .bi_size = bio->bi_size,
  334 + .bi_rw = bio->bi_rw,
  335 + };
  336 +
  337 + if (q->merge_bvec_fn(q, &bvm, prev) < len) {
  338 + prev->bv_len -= len;
  339 + return 0;
  340 + }
332 341 }
333 342  
334 343 goto done;
335 344  
... ... @@ -369,11 +378,18 @@
369 378 * queue to get further control
370 379 */
371 380 if (q->merge_bvec_fn) {
  381 + struct bvec_merge_data bvm = {
  382 + .bi_bdev = bio->bi_bdev,
  383 + .bi_sector = bio->bi_sector,
  384 + .bi_size = bio->bi_size,
  385 + .bi_rw = bio->bi_rw,
  386 + };
  387 +
372 388 /*
373 389 * merge_bvec_fn() returns number of bytes it can accept
374 390 * at this offset
375 391 */
376   - if (q->merge_bvec_fn(q, bio, bvec) < len) {
  392 + if (q->merge_bvec_fn(q, &bvm, bvec) < len) {
377 393 bvec->bv_page = NULL;
378 394 bvec->bv_len = 0;
379 395 bvec->bv_offset = 0;
include/linux/blkdev.h
... ... @@ -254,7 +254,14 @@
254 254 typedef void (unplug_fn) (struct request_queue *);
255 255  
256 256 struct bio_vec;
257   -typedef int (merge_bvec_fn) (struct request_queue *, struct bio *, struct bio_vec *);
  257 +struct bvec_merge_data {
  258 + struct block_device *bi_bdev;
  259 + sector_t bi_sector;
  260 + unsigned bi_size;
  261 + unsigned long bi_rw;
  262 +};
  263 +typedef int (merge_bvec_fn) (struct request_queue *, struct bvec_merge_data *,
  264 + struct bio_vec *);
258 265 typedef void (prepare_flush_fn) (struct request_queue *, struct request *);
259 266 typedef void (softirq_done_fn)(struct request *);
260 267 typedef int (dma_drain_needed_fn)(struct request *);