diff options
| -rw-r--r-- | fs/btrfs/disk-io.c | 23 | ||||
| -rw-r--r-- | fs/btrfs/disk-io.h | 2 | ||||
| -rw-r--r-- | fs/btrfs/extent_io.c | 2 | ||||
| -rw-r--r-- | fs/btrfs/extent_io.h | 2 | ||||
| -rw-r--r-- | fs/btrfs/inode.c | 40 |
5 files changed, 52 insertions, 17 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index a8772b5a9cb5..f3b287c22caf 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
| @@ -74,6 +74,11 @@ struct async_submit_bio { | |||
| 74 | int rw; | 74 | int rw; |
| 75 | int mirror_num; | 75 | int mirror_num; |
| 76 | unsigned long bio_flags; | 76 | unsigned long bio_flags; |
| 77 | /* | ||
| 78 | * bio_offset is optional, can be used if the pages in the bio | ||
| 79 | * can't tell us where in the file the bio should go | ||
| 80 | */ | ||
| 81 | u64 bio_offset; | ||
| 77 | struct btrfs_work work; | 82 | struct btrfs_work work; |
| 78 | }; | 83 | }; |
| 79 | 84 | ||
| @@ -534,7 +539,8 @@ static void run_one_async_start(struct btrfs_work *work) | |||
| 534 | async = container_of(work, struct async_submit_bio, work); | 539 | async = container_of(work, struct async_submit_bio, work); |
| 535 | fs_info = BTRFS_I(async->inode)->root->fs_info; | 540 | fs_info = BTRFS_I(async->inode)->root->fs_info; |
| 536 | async->submit_bio_start(async->inode, async->rw, async->bio, | 541 | async->submit_bio_start(async->inode, async->rw, async->bio, |
| 537 | async->mirror_num, async->bio_flags); | 542 | async->mirror_num, async->bio_flags, |
| 543 | async->bio_offset); | ||
| 538 | } | 544 | } |
| 539 | 545 | ||
| 540 | static void run_one_async_done(struct btrfs_work *work) | 546 | static void run_one_async_done(struct btrfs_work *work) |
| @@ -556,7 +562,8 @@ static void run_one_async_done(struct btrfs_work *work) | |||
| 556 | wake_up(&fs_info->async_submit_wait); | 562 | wake_up(&fs_info->async_submit_wait); |
| 557 | 563 | ||
| 558 | async->submit_bio_done(async->inode, async->rw, async->bio, | 564 | async->submit_bio_done(async->inode, async->rw, async->bio, |
| 559 | async->mirror_num, async->bio_flags); | 565 | async->mirror_num, async->bio_flags, |
| 566 | async->bio_offset); | ||
| 560 | } | 567 | } |
| 561 | 568 | ||
| 562 | static void run_one_async_free(struct btrfs_work *work) | 569 | static void run_one_async_free(struct btrfs_work *work) |
| @@ -570,6 +577,7 @@ static void run_one_async_free(struct btrfs_work *work) | |||
| 570 | int btrfs_wq_submit_bio(struct btrfs_fs_info *fs_info, struct inode *inode, | 577 | int btrfs_wq_submit_bio(struct btrfs_fs_info *fs_info, struct inode *inode, |
| 571 | int rw, struct bio *bio, int mirror_num, | 578 | int rw, struct bio *bio, int mirror_num, |
| 572 | unsigned long bio_flags, | 579 | unsigned long bio_flags, |
| 580 | u64 bio_offset, | ||
| 573 | extent_submit_bio_hook_t *submit_bio_start, | 581 | extent_submit_bio_hook_t *submit_bio_start, |
| 574 | extent_submit_bio_hook_t *submit_bio_done) | 582 | extent_submit_bio_hook_t *submit_bio_done) |
| 575 | { | 583 | { |
| @@ -592,6 +600,7 @@ int btrfs_wq_submit_bio(struct btrfs_fs_info *fs_info, struct inode *inode, | |||
| 592 | 600 | ||
| 593 | async->work.flags = 0; | 601 | async->work.flags = 0; |
| 594 | async->bio_flags = bio_flags; | 602 | async->bio_flags = bio_flags; |
| 603 | async->bio_offset = bio_offset; | ||
| 595 | 604 | ||
| 596 | atomic_inc(&fs_info->nr_async_submits); | 605 | atomic_inc(&fs_info->nr_async_submits); |
| 597 | 606 | ||
| @@ -627,7 +636,8 @@ static int btree_csum_one_bio(struct bio *bio) | |||
| 627 | 636 | ||
| 628 | static int __btree_submit_bio_start(struct inode *inode, int rw, | 637 | static int __btree_submit_bio_start(struct inode *inode, int rw, |
| 629 | struct bio *bio, int mirror_num, | 638 | struct bio *bio, int mirror_num, |
| 630 | unsigned long bio_flags) | 639 | unsigned long bio_flags, |
| 640 | u64 bio_offset) | ||
| 631 | { | 641 | { |
| 632 | /* | 642 | /* |
| 633 | * when we're called for a write, we're already in the async | 643 | * when we're called for a write, we're already in the async |
| @@ -638,7 +648,8 @@ static int __btree_submit_bio_start(struct inode *inode, int rw, | |||
| 638 | } | 648 | } |
| 639 | 649 | ||
| 640 | static int __btree_submit_bio_done(struct inode *inode, int rw, struct bio *bio, | 650 | static int __btree_submit_bio_done(struct inode *inode, int rw, struct bio *bio, |
| 641 | int mirror_num, unsigned long bio_flags) | 651 | int mirror_num, unsigned long bio_flags, |
| 652 | u64 bio_offset) | ||
| 642 | { | 653 | { |
| 643 | /* | 654 | /* |
| 644 | * when we're called for a write, we're already in the async | 655 | * when we're called for a write, we're already in the async |
| @@ -648,7 +659,8 @@ static int __btree_submit_bio_done(struct inode *inode, int rw, struct bio *bio, | |||
| 648 | } | 659 | } |
| 649 | 660 | ||
| 650 | static int btree_submit_bio_hook(struct inode *inode, int rw, struct bio *bio, | 661 | static int btree_submit_bio_hook(struct inode *inode, int rw, struct bio *bio, |
| 651 | int mirror_num, unsigned long bio_flags) | 662 | int mirror_num, unsigned long bio_flags, |
| 663 | u64 bio_offset) | ||
| 652 | { | 664 | { |
| 653 | int ret; | 665 | int ret; |
| 654 | 666 | ||
| @@ -671,6 +683,7 @@ static int btree_submit_bio_hook(struct inode *inode, int rw, struct bio *bio, | |||
| 671 | */ | 683 | */ |
| 672 | return btrfs_wq_submit_bio(BTRFS_I(inode)->root->fs_info, | 684 | return btrfs_wq_submit_bio(BTRFS_I(inode)->root->fs_info, |
| 673 | inode, rw, bio, mirror_num, 0, | 685 | inode, rw, bio, mirror_num, 0, |
| 686 | bio_offset, | ||
| 674 | __btree_submit_bio_start, | 687 | __btree_submit_bio_start, |
| 675 | __btree_submit_bio_done); | 688 | __btree_submit_bio_done); |
| 676 | } | 689 | } |
diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h index 2c064eba6f09..88e825a0bf21 100644 --- a/fs/btrfs/disk-io.h +++ b/fs/btrfs/disk-io.h | |||
| @@ -87,7 +87,7 @@ int btrfs_bio_wq_end_io(struct btrfs_fs_info *info, struct bio *bio, | |||
| 87 | int metadata); | 87 | int metadata); |
| 88 | int btrfs_wq_submit_bio(struct btrfs_fs_info *fs_info, struct inode *inode, | 88 | int btrfs_wq_submit_bio(struct btrfs_fs_info *fs_info, struct inode *inode, |
| 89 | int rw, struct bio *bio, int mirror_num, | 89 | int rw, struct bio *bio, int mirror_num, |
| 90 | unsigned long bio_flags, | 90 | unsigned long bio_flags, u64 bio_offset, |
| 91 | extent_submit_bio_hook_t *submit_bio_start, | 91 | extent_submit_bio_hook_t *submit_bio_start, |
| 92 | extent_submit_bio_hook_t *submit_bio_done); | 92 | extent_submit_bio_hook_t *submit_bio_done); |
| 93 | 93 | ||
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index a53aca338c7f..15392af21bfb 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c | |||
| @@ -1913,7 +1913,7 @@ static int submit_one_bio(int rw, struct bio *bio, int mirror_num, | |||
| 1913 | 1913 | ||
| 1914 | if (tree->ops && tree->ops->submit_bio_hook) | 1914 | if (tree->ops && tree->ops->submit_bio_hook) |
| 1915 | tree->ops->submit_bio_hook(page->mapping->host, rw, bio, | 1915 | tree->ops->submit_bio_hook(page->mapping->host, rw, bio, |
| 1916 | mirror_num, bio_flags); | 1916 | mirror_num, bio_flags, start); |
| 1917 | else | 1917 | else |
| 1918 | submit_bio(rw, bio); | 1918 | submit_bio(rw, bio); |
| 1919 | if (bio_flagged(bio, BIO_EOPNOTSUPP)) | 1919 | if (bio_flagged(bio, BIO_EOPNOTSUPP)) |
diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h index 86f10dc791d9..86c7b341d070 100644 --- a/fs/btrfs/extent_io.h +++ b/fs/btrfs/extent_io.h | |||
| @@ -49,7 +49,7 @@ struct extent_state; | |||
| 49 | 49 | ||
| 50 | typedef int (extent_submit_bio_hook_t)(struct inode *inode, int rw, | 50 | typedef int (extent_submit_bio_hook_t)(struct inode *inode, int rw, |
| 51 | struct bio *bio, int mirror_num, | 51 | struct bio *bio, int mirror_num, |
| 52 | unsigned long bio_flags); | 52 | unsigned long bio_flags, u64 bio_offset); |
| 53 | struct extent_io_ops { | 53 | struct extent_io_ops { |
| 54 | int (*fill_delalloc)(struct inode *inode, struct page *locked_page, | 54 | int (*fill_delalloc)(struct inode *inode, struct page *locked_page, |
| 55 | u64 start, u64 end, int *page_started, | 55 | u64 start, u64 end, int *page_started, |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 1695440a59a4..13a4aa222861 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
| @@ -1385,7 +1385,8 @@ int btrfs_merge_bio_hook(struct page *page, unsigned long offset, | |||
| 1385 | */ | 1385 | */ |
| 1386 | static int __btrfs_submit_bio_start(struct inode *inode, int rw, | 1386 | static int __btrfs_submit_bio_start(struct inode *inode, int rw, |
| 1387 | struct bio *bio, int mirror_num, | 1387 | struct bio *bio, int mirror_num, |
| 1388 | unsigned long bio_flags) | 1388 | unsigned long bio_flags, |
| 1389 | u64 bio_offset) | ||
| 1389 | { | 1390 | { |
| 1390 | struct btrfs_root *root = BTRFS_I(inode)->root; | 1391 | struct btrfs_root *root = BTRFS_I(inode)->root; |
| 1391 | int ret = 0; | 1392 | int ret = 0; |
| @@ -1404,7 +1405,8 @@ static int __btrfs_submit_bio_start(struct inode *inode, int rw, | |||
| 1404 | * are inserted into the btree | 1405 | * are inserted into the btree |
| 1405 | */ | 1406 | */ |
| 1406 | static int __btrfs_submit_bio_done(struct inode *inode, int rw, struct bio *bio, | 1407 | static int __btrfs_submit_bio_done(struct inode *inode, int rw, struct bio *bio, |
| 1407 | int mirror_num, unsigned long bio_flags) | 1408 | int mirror_num, unsigned long bio_flags, |
| 1409 | u64 bio_offset) | ||
| 1408 | { | 1410 | { |
| 1409 | struct btrfs_root *root = BTRFS_I(inode)->root; | 1411 | struct btrfs_root *root = BTRFS_I(inode)->root; |
| 1410 | return btrfs_map_bio(root, rw, bio, mirror_num, 1); | 1412 | return btrfs_map_bio(root, rw, bio, mirror_num, 1); |
| @@ -1415,7 +1417,8 @@ static int __btrfs_submit_bio_done(struct inode *inode, int rw, struct bio *bio, | |||
| 1415 | * on write, or reading the csums from the tree before a read | 1417 | * on write, or reading the csums from the tree before a read |
| 1416 | */ | 1418 | */ |
| 1417 | static int btrfs_submit_bio_hook(struct inode *inode, int rw, struct bio *bio, | 1419 | static int btrfs_submit_bio_hook(struct inode *inode, int rw, struct bio *bio, |
| 1418 | int mirror_num, unsigned long bio_flags) | 1420 | int mirror_num, unsigned long bio_flags, |
| 1421 | u64 bio_offset) | ||
| 1419 | { | 1422 | { |
| 1420 | struct btrfs_root *root = BTRFS_I(inode)->root; | 1423 | struct btrfs_root *root = BTRFS_I(inode)->root; |
| 1421 | int ret = 0; | 1424 | int ret = 0; |
| @@ -1440,7 +1443,8 @@ static int btrfs_submit_bio_hook(struct inode *inode, int rw, struct bio *bio, | |||
| 1440 | /* we're doing a write, do the async checksumming */ | 1443 | /* we're doing a write, do the async checksumming */ |
| 1441 | return btrfs_wq_submit_bio(BTRFS_I(inode)->root->fs_info, | 1444 | return btrfs_wq_submit_bio(BTRFS_I(inode)->root->fs_info, |
| 1442 | inode, rw, bio, mirror_num, | 1445 | inode, rw, bio, mirror_num, |
| 1443 | bio_flags, __btrfs_submit_bio_start, | 1446 | bio_flags, bio_offset, |
| 1447 | __btrfs_submit_bio_start, | ||
| 1444 | __btrfs_submit_bio_done); | 1448 | __btrfs_submit_bio_done); |
| 1445 | } | 1449 | } |
| 1446 | 1450 | ||
| @@ -1844,7 +1848,7 @@ static int btrfs_io_failed_hook(struct bio *failed_bio, | |||
| 1844 | 1848 | ||
| 1845 | BTRFS_I(inode)->io_tree.ops->submit_bio_hook(inode, rw, bio, | 1849 | BTRFS_I(inode)->io_tree.ops->submit_bio_hook(inode, rw, bio, |
| 1846 | failrec->last_mirror, | 1850 | failrec->last_mirror, |
| 1847 | failrec->bio_flags); | 1851 | failrec->bio_flags, 0); |
| 1848 | return 0; | 1852 | return 0; |
| 1849 | } | 1853 | } |
| 1850 | 1854 | ||
| @@ -5484,6 +5488,17 @@ out_done: | |||
| 5484 | dio_end_io(bio, err); | 5488 | dio_end_io(bio, err); |
| 5485 | } | 5489 | } |
| 5486 | 5490 | ||
| 5491 | static int __btrfs_submit_bio_start_direct_io(struct inode *inode, int rw, | ||
| 5492 | struct bio *bio, int mirror_num, | ||
| 5493 | unsigned long bio_flags, u64 offset) | ||
| 5494 | { | ||
| 5495 | int ret; | ||
| 5496 | struct btrfs_root *root = BTRFS_I(inode)->root; | ||
| 5497 | ret = btrfs_csum_one_bio(root, inode, bio, offset, 1); | ||
| 5498 | BUG_ON(ret); | ||
| 5499 | return 0; | ||
| 5500 | } | ||
| 5501 | |||
| 5487 | static void btrfs_submit_direct(int rw, struct bio *bio, struct inode *inode, | 5502 | static void btrfs_submit_direct(int rw, struct bio *bio, struct inode *inode, |
| 5488 | loff_t file_offset) | 5503 | loff_t file_offset) |
| 5489 | { | 5504 | { |
| @@ -5535,13 +5550,20 @@ static void btrfs_submit_direct(int rw, struct bio *bio, struct inode *inode, | |||
| 5535 | if (ret) | 5550 | if (ret) |
| 5536 | goto out_err; | 5551 | goto out_err; |
| 5537 | 5552 | ||
| 5538 | if (write && !skip_sum) | 5553 | if (write && !skip_sum) { |
| 5539 | btrfs_csum_one_bio(root, inode, bio, dip->logical_offset, 1); | 5554 | ret = btrfs_wq_submit_bio(BTRFS_I(inode)->root->fs_info, |
| 5540 | else if (!skip_sum) | 5555 | inode, rw, bio, 0, 0, |
| 5556 | dip->logical_offset, | ||
| 5557 | __btrfs_submit_bio_start_direct_io, | ||
| 5558 | __btrfs_submit_bio_done); | ||
| 5559 | if (ret) | ||
| 5560 | goto out_err; | ||
| 5561 | return; | ||
| 5562 | } else if (!skip_sum) | ||
| 5541 | btrfs_lookup_bio_sums_dio(root, inode, bio, | 5563 | btrfs_lookup_bio_sums_dio(root, inode, bio, |
| 5542 | dip->logical_offset, dip->csums); | 5564 | dip->logical_offset, dip->csums); |
| 5543 | 5565 | ||
| 5544 | ret = btrfs_map_bio(root, rw, bio, 0, 0); | 5566 | ret = btrfs_map_bio(root, rw, bio, 0, 1); |
| 5545 | if (ret) | 5567 | if (ret) |
| 5546 | goto out_err; | 5568 | goto out_err; |
| 5547 | return; | 5569 | return; |
