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; |