aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/tree-log.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-10-11 08:03:52 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-10-11 08:03:52 -0400
commit90d0c376f5ee1927327b267faf15bf970476f09e (patch)
treeb4ed1266ac45a34133e0e93b739067d5f5b33703 /fs/btrfs/tree-log.c
parentac0c49396d5ed9a33f08ce661635ac1bff80bb4f (diff)
parenta43bb39b5c710e79e921fb76341bacc418cfde78 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs
Pull btrfs updates from Chris Mason: "The largest set of changes here come from Miao Xie. He's cleaning up and improving read recovery/repair for raid, and has a number of related fixes. I've merged another set of fsync fixes from Filipe, and he's also improved the way we handle metadata write errors to make sure we force the FS readonly if things go wrong. Otherwise we have a collection of fixes and cleanups. Dave Sterba gets a cookie for removing the most lines (thanks Dave)" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs: (139 commits) btrfs: Fix compile error when CONFIG_SECURITY is not set. Btrfs: fix compiles when CONFIG_BTRFS_FS_RUN_SANITY_TESTS is off btrfs: Make btrfs handle security mount options internally to avoid losing security label. Btrfs: send, don't delay dir move if there's a new parent inode btrfs: add more superblock checks Btrfs: fix race in WAIT_SYNC ioctl Btrfs: be aware of btree inode write errors to avoid fs corruption Btrfs: remove redundant btrfs_verify_qgroup_counts declaration. btrfs: fix shadow warning on cmp Btrfs: fix compilation errors under DEBUG Btrfs: fix crash of btrfs_release_extent_buffer_page Btrfs: add missing end_page_writeback on submit_extent_page failure btrfs: Fix the wrong condition judgment about subset extent map Btrfs: fix build_backref_tree issue with multiple shared blocks Btrfs: cleanup error handling in build_backref_tree btrfs: move checks for DUMMY_ROOT into a helper btrfs: new define for the inline extent data start btrfs: kill extent_buffer_page helper btrfs: drop constant param from btrfs_release_extent_buffer_page btrfs: hide typecast to definition of BTRFS_SEND_TRANS_STUB ...
Diffstat (limited to 'fs/btrfs/tree-log.c')
-rw-r--r--fs/btrfs/tree-log.c259
1 files changed, 150 insertions, 109 deletions
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index d0262ceb85e1..1475979e5718 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -97,7 +97,8 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans,
97 struct btrfs_root *root, struct inode *inode, 97 struct btrfs_root *root, struct inode *inode,
98 int inode_only, 98 int inode_only,
99 const loff_t start, 99 const loff_t start,
100 const loff_t end); 100 const loff_t end,
101 struct btrfs_log_ctx *ctx);
101static int link_to_fixup_dir(struct btrfs_trans_handle *trans, 102static int link_to_fixup_dir(struct btrfs_trans_handle *trans,
102 struct btrfs_root *root, 103 struct btrfs_root *root,
103 struct btrfs_path *path, u64 objectid); 104 struct btrfs_path *path, u64 objectid);
@@ -1498,7 +1499,7 @@ static noinline int link_to_fixup_dir(struct btrfs_trans_handle *trans,
1498 return -EIO; 1499 return -EIO;
1499 1500
1500 key.objectid = BTRFS_TREE_LOG_FIXUP_OBJECTID; 1501 key.objectid = BTRFS_TREE_LOG_FIXUP_OBJECTID;
1501 btrfs_set_key_type(&key, BTRFS_ORPHAN_ITEM_KEY); 1502 key.type = BTRFS_ORPHAN_ITEM_KEY;
1502 key.offset = objectid; 1503 key.offset = objectid;
1503 1504
1504 ret = btrfs_insert_empty_item(trans, root, path, &key, 0); 1505 ret = btrfs_insert_empty_item(trans, root, path, &key, 0);
@@ -1637,6 +1638,7 @@ static noinline int replay_one_name(struct btrfs_trans_handle *trans,
1637 found_key.type == log_key.type && 1638 found_key.type == log_key.type &&
1638 found_key.offset == log_key.offset && 1639 found_key.offset == log_key.offset &&
1639 btrfs_dir_type(path->nodes[0], dst_di) == log_type) { 1640 btrfs_dir_type(path->nodes[0], dst_di) == log_type) {
1641 update_size = false;
1640 goto out; 1642 goto out;
1641 } 1643 }
1642 1644
@@ -2157,7 +2159,7 @@ static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans,
2157 2159
2158 bytenr = btrfs_node_blockptr(cur, path->slots[*level]); 2160 bytenr = btrfs_node_blockptr(cur, path->slots[*level]);
2159 ptr_gen = btrfs_node_ptr_generation(cur, path->slots[*level]); 2161 ptr_gen = btrfs_node_ptr_generation(cur, path->slots[*level]);
2160 blocksize = btrfs_level_size(root, *level - 1); 2162 blocksize = root->nodesize;
2161 2163
2162 parent = path->nodes[*level]; 2164 parent = path->nodes[*level];
2163 root_owner = btrfs_header_owner(parent); 2165 root_owner = btrfs_header_owner(parent);
@@ -2983,8 +2985,6 @@ static noinline int log_dir_items(struct btrfs_trans_handle *trans,
2983 min_key.type = key_type; 2985 min_key.type = key_type;
2984 min_key.offset = min_offset; 2986 min_key.offset = min_offset;
2985 2987
2986 path->keep_locks = 1;
2987
2988 ret = btrfs_search_forward(root, &min_key, path, trans->transid); 2988 ret = btrfs_search_forward(root, &min_key, path, trans->transid);
2989 2989
2990 /* 2990 /*
@@ -3364,7 +3364,7 @@ static noinline int copy_items(struct btrfs_trans_handle *trans,
3364 * or deletes of this inode don't have to relog the inode 3364 * or deletes of this inode don't have to relog the inode
3365 * again 3365 * again
3366 */ 3366 */
3367 if (btrfs_key_type(ins_keys + i) == BTRFS_EXTENT_DATA_KEY && 3367 if (ins_keys[i].type == BTRFS_EXTENT_DATA_KEY &&
3368 !skip_csum) { 3368 !skip_csum) {
3369 int found_type; 3369 int found_type;
3370 extent = btrfs_item_ptr(src, start_slot + i, 3370 extent = btrfs_item_ptr(src, start_slot + i,
@@ -3573,107 +3573,33 @@ static int extent_cmp(void *priv, struct list_head *a, struct list_head *b)
3573 return 0; 3573 return 0;
3574} 3574}
3575 3575
3576static int log_one_extent(struct btrfs_trans_handle *trans, 3576static int wait_ordered_extents(struct btrfs_trans_handle *trans,
3577 struct inode *inode, struct btrfs_root *root, 3577 struct inode *inode,
3578 struct extent_map *em, struct btrfs_path *path, 3578 struct btrfs_root *root,
3579 struct list_head *logged_list) 3579 const struct extent_map *em,
3580 const struct list_head *logged_list,
3581 bool *ordered_io_error)
3580{ 3582{
3581 struct btrfs_root *log = root->log_root;
3582 struct btrfs_file_extent_item *fi;
3583 struct extent_buffer *leaf;
3584 struct btrfs_ordered_extent *ordered; 3583 struct btrfs_ordered_extent *ordered;
3585 struct list_head ordered_sums; 3584 struct btrfs_root *log = root->log_root;
3586 struct btrfs_map_token token;
3587 struct btrfs_key key;
3588 u64 mod_start = em->mod_start; 3585 u64 mod_start = em->mod_start;
3589 u64 mod_len = em->mod_len; 3586 u64 mod_len = em->mod_len;
3587 const bool skip_csum = BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM;
3590 u64 csum_offset; 3588 u64 csum_offset;
3591 u64 csum_len; 3589 u64 csum_len;
3592 u64 extent_offset = em->start - em->orig_start; 3590 LIST_HEAD(ordered_sums);
3593 u64 block_len; 3591 int ret = 0;
3594 int ret;
3595 bool skip_csum = BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM;
3596 int extent_inserted = 0;
3597
3598 INIT_LIST_HEAD(&ordered_sums);
3599 btrfs_init_map_token(&token);
3600
3601 ret = __btrfs_drop_extents(trans, log, inode, path, em->start,
3602 em->start + em->len, NULL, 0, 1,
3603 sizeof(*fi), &extent_inserted);
3604 if (ret)
3605 return ret;
3606
3607 if (!extent_inserted) {
3608 key.objectid = btrfs_ino(inode);
3609 key.type = BTRFS_EXTENT_DATA_KEY;
3610 key.offset = em->start;
3611
3612 ret = btrfs_insert_empty_item(trans, log, path, &key,
3613 sizeof(*fi));
3614 if (ret)
3615 return ret;
3616 }
3617 leaf = path->nodes[0];
3618 fi = btrfs_item_ptr(leaf, path->slots[0],
3619 struct btrfs_file_extent_item);
3620
3621 btrfs_set_token_file_extent_generation(leaf, fi, em->generation,
3622 &token);
3623 if (test_bit(EXTENT_FLAG_PREALLOC, &em->flags)) {
3624 skip_csum = true;
3625 btrfs_set_token_file_extent_type(leaf, fi,
3626 BTRFS_FILE_EXTENT_PREALLOC,
3627 &token);
3628 } else {
3629 btrfs_set_token_file_extent_type(leaf, fi,
3630 BTRFS_FILE_EXTENT_REG,
3631 &token);
3632 if (em->block_start == EXTENT_MAP_HOLE)
3633 skip_csum = true;
3634 }
3635
3636 block_len = max(em->block_len, em->orig_block_len);
3637 if (em->compress_type != BTRFS_COMPRESS_NONE) {
3638 btrfs_set_token_file_extent_disk_bytenr(leaf, fi,
3639 em->block_start,
3640 &token);
3641 btrfs_set_token_file_extent_disk_num_bytes(leaf, fi, block_len,
3642 &token);
3643 } else if (em->block_start < EXTENT_MAP_LAST_BYTE) {
3644 btrfs_set_token_file_extent_disk_bytenr(leaf, fi,
3645 em->block_start -
3646 extent_offset, &token);
3647 btrfs_set_token_file_extent_disk_num_bytes(leaf, fi, block_len,
3648 &token);
3649 } else {
3650 btrfs_set_token_file_extent_disk_bytenr(leaf, fi, 0, &token);
3651 btrfs_set_token_file_extent_disk_num_bytes(leaf, fi, 0,
3652 &token);
3653 }
3654
3655 btrfs_set_token_file_extent_offset(leaf, fi,
3656 em->start - em->orig_start,
3657 &token);
3658 btrfs_set_token_file_extent_num_bytes(leaf, fi, em->len, &token);
3659 btrfs_set_token_file_extent_ram_bytes(leaf, fi, em->ram_bytes, &token);
3660 btrfs_set_token_file_extent_compression(leaf, fi, em->compress_type,
3661 &token);
3662 btrfs_set_token_file_extent_encryption(leaf, fi, 0, &token);
3663 btrfs_set_token_file_extent_other_encoding(leaf, fi, 0, &token);
3664 btrfs_mark_buffer_dirty(leaf);
3665 3592
3666 btrfs_release_path(path); 3593 *ordered_io_error = false;
3667 if (ret) {
3668 return ret;
3669 }
3670 3594
3671 if (skip_csum) 3595 if (test_bit(EXTENT_FLAG_PREALLOC, &em->flags) ||
3596 em->block_start == EXTENT_MAP_HOLE)
3672 return 0; 3597 return 0;
3673 3598
3674 /* 3599 /*
3675 * First check and see if our csums are on our outstanding ordered 3600 * Wait far any ordered extent that covers our extent map. If it
3676 * extents. 3601 * finishes without an error, first check and see if our csums are on
3602 * our outstanding ordered extents.
3677 */ 3603 */
3678 list_for_each_entry(ordered, logged_list, log_list) { 3604 list_for_each_entry(ordered, logged_list, log_list) {
3679 struct btrfs_ordered_sum *sum; 3605 struct btrfs_ordered_sum *sum;
@@ -3685,6 +3611,24 @@ static int log_one_extent(struct btrfs_trans_handle *trans,
3685 mod_start + mod_len <= ordered->file_offset) 3611 mod_start + mod_len <= ordered->file_offset)
3686 continue; 3612 continue;
3687 3613
3614 if (!test_bit(BTRFS_ORDERED_IO_DONE, &ordered->flags) &&
3615 !test_bit(BTRFS_ORDERED_IOERR, &ordered->flags) &&
3616 !test_bit(BTRFS_ORDERED_DIRECT, &ordered->flags)) {
3617 const u64 start = ordered->file_offset;
3618 const u64 end = ordered->file_offset + ordered->len - 1;
3619
3620 WARN_ON(ordered->inode != inode);
3621 filemap_fdatawrite_range(inode->i_mapping, start, end);
3622 }
3623
3624 wait_event(ordered->wait,
3625 (test_bit(BTRFS_ORDERED_IO_DONE, &ordered->flags) ||
3626 test_bit(BTRFS_ORDERED_IOERR, &ordered->flags)));
3627
3628 if (test_bit(BTRFS_ORDERED_IOERR, &ordered->flags)) {
3629 *ordered_io_error = true;
3630 break;
3631 }
3688 /* 3632 /*
3689 * We are going to copy all the csums on this ordered extent, so 3633 * We are going to copy all the csums on this ordered extent, so
3690 * go ahead and adjust mod_start and mod_len in case this 3634 * go ahead and adjust mod_start and mod_len in case this
@@ -3716,6 +3660,9 @@ static int log_one_extent(struct btrfs_trans_handle *trans,
3716 } 3660 }
3717 } 3661 }
3718 3662
3663 if (skip_csum)
3664 continue;
3665
3719 /* 3666 /*
3720 * To keep us from looping for the above case of an ordered 3667 * To keep us from looping for the above case of an ordered
3721 * extent that falls inside of the logged extent. 3668 * extent that falls inside of the logged extent.
@@ -3733,18 +3680,16 @@ static int log_one_extent(struct btrfs_trans_handle *trans,
3733 list_for_each_entry(sum, &ordered->list, list) { 3680 list_for_each_entry(sum, &ordered->list, list) {
3734 ret = btrfs_csum_file_blocks(trans, log, sum); 3681 ret = btrfs_csum_file_blocks(trans, log, sum);
3735 if (ret) 3682 if (ret)
3736 goto unlocked; 3683 break;
3737 } 3684 }
3738
3739 } 3685 }
3740unlocked:
3741 3686
3742 if (!mod_len || ret) 3687 if (*ordered_io_error || !mod_len || ret || skip_csum)
3743 return ret; 3688 return ret;
3744 3689
3745 if (em->compress_type) { 3690 if (em->compress_type) {
3746 csum_offset = 0; 3691 csum_offset = 0;
3747 csum_len = block_len; 3692 csum_len = max(em->block_len, em->orig_block_len);
3748 } else { 3693 } else {
3749 csum_offset = mod_start - em->start; 3694 csum_offset = mod_start - em->start;
3750 csum_len = mod_len; 3695 csum_len = mod_len;
@@ -3771,11 +3716,106 @@ unlocked:
3771 return ret; 3716 return ret;
3772} 3717}
3773 3718
3719static int log_one_extent(struct btrfs_trans_handle *trans,
3720 struct inode *inode, struct btrfs_root *root,
3721 const struct extent_map *em,
3722 struct btrfs_path *path,
3723 const struct list_head *logged_list,
3724 struct btrfs_log_ctx *ctx)
3725{
3726 struct btrfs_root *log = root->log_root;
3727 struct btrfs_file_extent_item *fi;
3728 struct extent_buffer *leaf;
3729 struct btrfs_map_token token;
3730 struct btrfs_key key;
3731 u64 extent_offset = em->start - em->orig_start;
3732 u64 block_len;
3733 int ret;
3734 int extent_inserted = 0;
3735 bool ordered_io_err = false;
3736
3737 ret = wait_ordered_extents(trans, inode, root, em, logged_list,
3738 &ordered_io_err);
3739 if (ret)
3740 return ret;
3741
3742 if (ordered_io_err) {
3743 ctx->io_err = -EIO;
3744 return 0;
3745 }
3746
3747 btrfs_init_map_token(&token);
3748
3749 ret = __btrfs_drop_extents(trans, log, inode, path, em->start,
3750 em->start + em->len, NULL, 0, 1,
3751 sizeof(*fi), &extent_inserted);
3752 if (ret)
3753 return ret;
3754
3755 if (!extent_inserted) {
3756 key.objectid = btrfs_ino(inode);
3757 key.type = BTRFS_EXTENT_DATA_KEY;
3758 key.offset = em->start;
3759
3760 ret = btrfs_insert_empty_item(trans, log, path, &key,
3761 sizeof(*fi));
3762 if (ret)
3763 return ret;
3764 }
3765 leaf = path->nodes[0];
3766 fi = btrfs_item_ptr(leaf, path->slots[0],
3767 struct btrfs_file_extent_item);
3768
3769 btrfs_set_token_file_extent_generation(leaf, fi, em->generation,
3770 &token);
3771 if (test_bit(EXTENT_FLAG_PREALLOC, &em->flags))
3772 btrfs_set_token_file_extent_type(leaf, fi,
3773 BTRFS_FILE_EXTENT_PREALLOC,
3774 &token);
3775 else
3776 btrfs_set_token_file_extent_type(leaf, fi,
3777 BTRFS_FILE_EXTENT_REG,
3778 &token);
3779
3780 block_len = max(em->block_len, em->orig_block_len);
3781 if (em->compress_type != BTRFS_COMPRESS_NONE) {
3782 btrfs_set_token_file_extent_disk_bytenr(leaf, fi,
3783 em->block_start,
3784 &token);
3785 btrfs_set_token_file_extent_disk_num_bytes(leaf, fi, block_len,
3786 &token);
3787 } else if (em->block_start < EXTENT_MAP_LAST_BYTE) {
3788 btrfs_set_token_file_extent_disk_bytenr(leaf, fi,
3789 em->block_start -
3790 extent_offset, &token);
3791 btrfs_set_token_file_extent_disk_num_bytes(leaf, fi, block_len,
3792 &token);
3793 } else {
3794 btrfs_set_token_file_extent_disk_bytenr(leaf, fi, 0, &token);
3795 btrfs_set_token_file_extent_disk_num_bytes(leaf, fi, 0,
3796 &token);
3797 }
3798
3799 btrfs_set_token_file_extent_offset(leaf, fi, extent_offset, &token);
3800 btrfs_set_token_file_extent_num_bytes(leaf, fi, em->len, &token);
3801 btrfs_set_token_file_extent_ram_bytes(leaf, fi, em->ram_bytes, &token);
3802 btrfs_set_token_file_extent_compression(leaf, fi, em->compress_type,
3803 &token);
3804 btrfs_set_token_file_extent_encryption(leaf, fi, 0, &token);
3805 btrfs_set_token_file_extent_other_encoding(leaf, fi, 0, &token);
3806 btrfs_mark_buffer_dirty(leaf);
3807
3808 btrfs_release_path(path);
3809
3810 return ret;
3811}
3812
3774static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans, 3813static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans,
3775 struct btrfs_root *root, 3814 struct btrfs_root *root,
3776 struct inode *inode, 3815 struct inode *inode,
3777 struct btrfs_path *path, 3816 struct btrfs_path *path,
3778 struct list_head *logged_list) 3817 struct list_head *logged_list,
3818 struct btrfs_log_ctx *ctx)
3779{ 3819{
3780 struct extent_map *em, *n; 3820 struct extent_map *em, *n;
3781 struct list_head extents; 3821 struct list_head extents;
@@ -3833,7 +3873,8 @@ process:
3833 3873
3834 write_unlock(&tree->lock); 3874 write_unlock(&tree->lock);
3835 3875
3836 ret = log_one_extent(trans, inode, root, em, path, logged_list); 3876 ret = log_one_extent(trans, inode, root, em, path, logged_list,
3877 ctx);
3837 write_lock(&tree->lock); 3878 write_lock(&tree->lock);
3838 clear_em_logging(tree, em); 3879 clear_em_logging(tree, em);
3839 free_extent_map(em); 3880 free_extent_map(em);
@@ -3863,7 +3904,8 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans,
3863 struct btrfs_root *root, struct inode *inode, 3904 struct btrfs_root *root, struct inode *inode,
3864 int inode_only, 3905 int inode_only,
3865 const loff_t start, 3906 const loff_t start,
3866 const loff_t end) 3907 const loff_t end,
3908 struct btrfs_log_ctx *ctx)
3867{ 3909{
3868 struct btrfs_path *path; 3910 struct btrfs_path *path;
3869 struct btrfs_path *dst_path; 3911 struct btrfs_path *dst_path;
@@ -3964,7 +4006,6 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans,
3964 err = ret; 4006 err = ret;
3965 goto out_unlock; 4007 goto out_unlock;
3966 } 4008 }
3967 path->keep_locks = 1;
3968 4009
3969 while (1) { 4010 while (1) {
3970 ins_nr = 0; 4011 ins_nr = 0;
@@ -4049,7 +4090,7 @@ log_extents:
4049 btrfs_release_path(dst_path); 4090 btrfs_release_path(dst_path);
4050 if (fast_search) { 4091 if (fast_search) {
4051 ret = btrfs_log_changed_extents(trans, root, inode, dst_path, 4092 ret = btrfs_log_changed_extents(trans, root, inode, dst_path,
4052 &logged_list); 4093 &logged_list, ctx);
4053 if (ret) { 4094 if (ret) {
4054 err = ret; 4095 err = ret;
4055 goto out_unlock; 4096 goto out_unlock;
@@ -4239,7 +4280,7 @@ static int btrfs_log_inode_parent(struct btrfs_trans_handle *trans,
4239 if (ret) 4280 if (ret)
4240 goto end_no_trans; 4281 goto end_no_trans;
4241 4282
4242 ret = btrfs_log_inode(trans, root, inode, inode_only, start, end); 4283 ret = btrfs_log_inode(trans, root, inode, inode_only, start, end, ctx);
4243 if (ret) 4284 if (ret)
4244 goto end_trans; 4285 goto end_trans;
4245 4286
@@ -4268,7 +4309,7 @@ static int btrfs_log_inode_parent(struct btrfs_trans_handle *trans,
4268 if (BTRFS_I(inode)->generation > 4309 if (BTRFS_I(inode)->generation >
4269 root->fs_info->last_trans_committed) { 4310 root->fs_info->last_trans_committed) {
4270 ret = btrfs_log_inode(trans, root, inode, inode_only, 4311 ret = btrfs_log_inode(trans, root, inode, inode_only,
4271 0, LLONG_MAX); 4312 0, LLONG_MAX, ctx);
4272 if (ret) 4313 if (ret)
4273 goto end_trans; 4314 goto end_trans;
4274 } 4315 }
@@ -4360,7 +4401,7 @@ int btrfs_recover_log_trees(struct btrfs_root *log_root_tree)
4360again: 4401again:
4361 key.objectid = BTRFS_TREE_LOG_OBJECTID; 4402 key.objectid = BTRFS_TREE_LOG_OBJECTID;
4362 key.offset = (u64)-1; 4403 key.offset = (u64)-1;
4363 btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY); 4404 key.type = BTRFS_ROOT_ITEM_KEY;
4364 4405
4365 while (1) { 4406 while (1) {
4366 ret = btrfs_search_slot(NULL, log_root_tree, &key, path, 0, 0); 4407 ret = btrfs_search_slot(NULL, log_root_tree, &key, path, 0, 0);