aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorAlasdair G Kergon <agk@redhat.com>2008-07-03 03:53:43 -0400
committerJens Axboe <jens.axboe@oracle.com>2008-07-03 07:21:15 -0400
commitcc371e66e340f35eed8dc4651c7c18e754c7fb26 (patch)
tree5a2d6727eb07a05999c531a90da43ab1c36b713e /fs
parentb24498d477a14680fc3bb3ad884fa9fa76a2d237 (diff)
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>
Diffstat (limited to 'fs')
-rw-r--r--fs/bio.c26
1 files changed, 21 insertions, 5 deletions
diff --git a/fs/bio.c b/fs/bio.c
index 7761c84c7032..88322b066acb 100644
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -325,10 +325,19 @@ static int __bio_add_page(struct request_queue *q, struct bio *bio, struct page
325 if (page == prev->bv_page && 325 if (page == prev->bv_page &&
326 offset == prev->bv_offset + prev->bv_len) { 326 offset == prev->bv_offset + prev->bv_len) {
327 prev->bv_len += len; 327 prev->bv_len += len;
328 if (q->merge_bvec_fn && 328
329 q->merge_bvec_fn(q, bio, prev) < len) { 329 if (q->merge_bvec_fn) {
330 prev->bv_len -= len; 330 struct bvec_merge_data bvm = {
331 return 0; 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 goto done; 343 goto done;
@@ -369,11 +378,18 @@ static int __bio_add_page(struct request_queue *q, struct bio *bio, struct page
369 * queue to get further control 378 * queue to get further control
370 */ 379 */
371 if (q->merge_bvec_fn) { 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 * merge_bvec_fn() returns number of bytes it can accept 389 * merge_bvec_fn() returns number of bytes it can accept
374 * at this offset 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 bvec->bv_page = NULL; 393 bvec->bv_page = NULL;
378 bvec->bv_len = 0; 394 bvec->bv_len = 0;
379 bvec->bv_offset = 0; 395 bvec->bv_offset = 0;