aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/tree-log.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/tree-log.c')
-rw-r--r--fs/btrfs/tree-log.c262
1 files changed, 152 insertions, 110 deletions
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index 1d1ba083ca6e..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;
@@ -3994,7 +4035,8 @@ again:
3994 if (ret < 0) { 4035 if (ret < 0) {
3995 err = ret; 4036 err = ret;
3996 goto out_unlock; 4037 goto out_unlock;
3997 } if (ret) { 4038 }
4039 if (ret) {
3998 ins_nr = 0; 4040 ins_nr = 0;
3999 btrfs_release_path(path); 4041 btrfs_release_path(path);
4000 continue; 4042 continue;
@@ -4048,7 +4090,7 @@ log_extents:
4048 btrfs_release_path(dst_path); 4090 btrfs_release_path(dst_path);
4049 if (fast_search) { 4091 if (fast_search) {
4050 ret = btrfs_log_changed_extents(trans, root, inode, dst_path, 4092 ret = btrfs_log_changed_extents(trans, root, inode, dst_path,
4051 &logged_list); 4093 &logged_list, ctx);
4052 if (ret) { 4094 if (ret) {
4053 err = ret; 4095 err = ret;
4054 goto out_unlock; 4096 goto out_unlock;
@@ -4238,7 +4280,7 @@ static int btrfs_log_inode_parent(struct btrfs_trans_handle *trans,
4238 if (ret) 4280 if (ret)
4239 goto end_no_trans; 4281 goto end_no_trans;
4240 4282
4241 ret = btrfs_log_inode(trans, root, inode, inode_only, start, end); 4283 ret = btrfs_log_inode(trans, root, inode, inode_only, start, end, ctx);
4242 if (ret) 4284 if (ret)
4243 goto end_trans; 4285 goto end_trans;
4244 4286
@@ -4267,7 +4309,7 @@ static int btrfs_log_inode_parent(struct btrfs_trans_handle *trans,
4267 if (BTRFS_I(inode)->generation > 4309 if (BTRFS_I(inode)->generation >
4268 root->fs_info->last_trans_committed) { 4310 root->fs_info->last_trans_committed) {
4269 ret = btrfs_log_inode(trans, root, inode, inode_only, 4311 ret = btrfs_log_inode(trans, root, inode, inode_only,
4270 0, LLONG_MAX); 4312 0, LLONG_MAX, ctx);
4271 if (ret) 4313 if (ret)
4272 goto end_trans; 4314 goto end_trans;
4273 } 4315 }
@@ -4359,7 +4401,7 @@ int btrfs_recover_log_trees(struct btrfs_root *log_root_tree)
4359again: 4401again:
4360 key.objectid = BTRFS_TREE_LOG_OBJECTID; 4402 key.objectid = BTRFS_TREE_LOG_OBJECTID;
4361 key.offset = (u64)-1; 4403 key.offset = (u64)-1;
4362 btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY); 4404 key.type = BTRFS_ROOT_ITEM_KEY;
4363 4405
4364 while (1) { 4406 while (1) {
4365 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);