diff options
author | Chris Mason <clm@fb.com> | 2017-02-27 16:11:53 -0500 |
---|---|---|
committer | Chris Mason <clm@fb.com> | 2017-02-27 16:11:53 -0500 |
commit | ef6ebf324216eaea95ff30da5a8e78e2a4311eba (patch) | |
tree | 5357c0d811540028845a3e303a1bf2101b9a22a6 | |
parent | 6288d6eabc7505f42dda34a2c2962f91914be3a4 (diff) | |
parent | 263d3995c93c6020576f6c93506412a0b9d1e932 (diff) |
Merge branch 'for-chris-4.11' of git://git.kernel.org/pub/scm/linux/kernel/git/fdmanana/linux into for-linus-4.11
-rw-r--r-- | fs/btrfs/ctree.c | 7 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 15 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 9 | ||||
-rw-r--r-- | fs/btrfs/file-item.c | 28 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 29 | ||||
-rw-r--r-- | fs/btrfs/send.c | 125 | ||||
-rw-r--r-- | fs/btrfs/tree-log.c | 5 |
7 files changed, 188 insertions, 30 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 1192bc7d2ee7..1fb60ee77b4a 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
@@ -4159,6 +4159,9 @@ static noinline int push_for_double_split(struct btrfs_trans_handle *trans, | |||
4159 | 4159 | ||
4160 | /* try to push all the items before our slot into the next leaf */ | 4160 | /* try to push all the items before our slot into the next leaf */ |
4161 | slot = path->slots[0]; | 4161 | slot = path->slots[0]; |
4162 | space_needed = data_size; | ||
4163 | if (slot > 0) | ||
4164 | space_needed -= btrfs_leaf_free_space(fs_info, path->nodes[0]); | ||
4162 | ret = push_leaf_left(trans, root, path, 1, space_needed, 0, slot); | 4165 | ret = push_leaf_left(trans, root, path, 1, space_needed, 0, slot); |
4163 | if (ret < 0) | 4166 | if (ret < 0) |
4164 | return ret; | 4167 | return ret; |
@@ -4214,6 +4217,10 @@ static noinline int split_leaf(struct btrfs_trans_handle *trans, | |||
4214 | if (wret < 0) | 4217 | if (wret < 0) |
4215 | return wret; | 4218 | return wret; |
4216 | if (wret) { | 4219 | if (wret) { |
4220 | space_needed = data_size; | ||
4221 | if (slot > 0) | ||
4222 | space_needed -= btrfs_leaf_free_space(fs_info, | ||
4223 | l); | ||
4217 | wret = push_leaf_left(trans, root, path, space_needed, | 4224 | wret = push_leaf_left(trans, root, path, space_needed, |
4218 | space_needed, 0, (u32)-1); | 4225 | space_needed, 0, (u32)-1); |
4219 | if (wret < 0) | 4226 | if (wret < 0) |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 2b06f557c176..32a9ec11888d 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -2205,11 +2205,9 @@ static void btrfs_stop_all_workers(struct btrfs_fs_info *fs_info) | |||
2205 | btrfs_destroy_workqueue(fs_info->delalloc_workers); | 2205 | btrfs_destroy_workqueue(fs_info->delalloc_workers); |
2206 | btrfs_destroy_workqueue(fs_info->workers); | 2206 | btrfs_destroy_workqueue(fs_info->workers); |
2207 | btrfs_destroy_workqueue(fs_info->endio_workers); | 2207 | btrfs_destroy_workqueue(fs_info->endio_workers); |
2208 | btrfs_destroy_workqueue(fs_info->endio_meta_workers); | ||
2209 | btrfs_destroy_workqueue(fs_info->endio_raid56_workers); | 2208 | btrfs_destroy_workqueue(fs_info->endio_raid56_workers); |
2210 | btrfs_destroy_workqueue(fs_info->endio_repair_workers); | 2209 | btrfs_destroy_workqueue(fs_info->endio_repair_workers); |
2211 | btrfs_destroy_workqueue(fs_info->rmw_workers); | 2210 | btrfs_destroy_workqueue(fs_info->rmw_workers); |
2212 | btrfs_destroy_workqueue(fs_info->endio_meta_write_workers); | ||
2213 | btrfs_destroy_workqueue(fs_info->endio_write_workers); | 2211 | btrfs_destroy_workqueue(fs_info->endio_write_workers); |
2214 | btrfs_destroy_workqueue(fs_info->endio_freespace_worker); | 2212 | btrfs_destroy_workqueue(fs_info->endio_freespace_worker); |
2215 | btrfs_destroy_workqueue(fs_info->submit_workers); | 2213 | btrfs_destroy_workqueue(fs_info->submit_workers); |
@@ -2219,6 +2217,13 @@ static void btrfs_stop_all_workers(struct btrfs_fs_info *fs_info) | |||
2219 | btrfs_destroy_workqueue(fs_info->flush_workers); | 2217 | btrfs_destroy_workqueue(fs_info->flush_workers); |
2220 | btrfs_destroy_workqueue(fs_info->qgroup_rescan_workers); | 2218 | btrfs_destroy_workqueue(fs_info->qgroup_rescan_workers); |
2221 | btrfs_destroy_workqueue(fs_info->extent_workers); | 2219 | btrfs_destroy_workqueue(fs_info->extent_workers); |
2220 | /* | ||
2221 | * Now that all other work queues are destroyed, we can safely destroy | ||
2222 | * the queues used for metadata I/O, since tasks from those other work | ||
2223 | * queues can do metadata I/O operations. | ||
2224 | */ | ||
2225 | btrfs_destroy_workqueue(fs_info->endio_meta_workers); | ||
2226 | btrfs_destroy_workqueue(fs_info->endio_meta_write_workers); | ||
2222 | } | 2227 | } |
2223 | 2228 | ||
2224 | static void free_root_extent_buffers(struct btrfs_root *root) | 2229 | static void free_root_extent_buffers(struct btrfs_root *root) |
@@ -3261,7 +3266,6 @@ fail_fsdev_sysfs: | |||
3261 | 3266 | ||
3262 | fail_block_groups: | 3267 | fail_block_groups: |
3263 | btrfs_put_block_group_cache(fs_info); | 3268 | btrfs_put_block_group_cache(fs_info); |
3264 | btrfs_free_block_groups(fs_info); | ||
3265 | 3269 | ||
3266 | fail_tree_roots: | 3270 | fail_tree_roots: |
3267 | free_root_pointers(fs_info, 1); | 3271 | free_root_pointers(fs_info, 1); |
@@ -3269,6 +3273,7 @@ fail_tree_roots: | |||
3269 | 3273 | ||
3270 | fail_sb_buffer: | 3274 | fail_sb_buffer: |
3271 | btrfs_stop_all_workers(fs_info); | 3275 | btrfs_stop_all_workers(fs_info); |
3276 | btrfs_free_block_groups(fs_info); | ||
3272 | fail_alloc: | 3277 | fail_alloc: |
3273 | fail_iput: | 3278 | fail_iput: |
3274 | btrfs_mapping_tree_free(&fs_info->mapping_tree); | 3279 | btrfs_mapping_tree_free(&fs_info->mapping_tree); |
@@ -3977,8 +3982,6 @@ void close_ctree(struct btrfs_fs_info *fs_info) | |||
3977 | 3982 | ||
3978 | btrfs_put_block_group_cache(fs_info); | 3983 | btrfs_put_block_group_cache(fs_info); |
3979 | 3984 | ||
3980 | btrfs_free_block_groups(fs_info); | ||
3981 | |||
3982 | /* | 3985 | /* |
3983 | * we must make sure there is not any read request to | 3986 | * we must make sure there is not any read request to |
3984 | * submit after we stopping all workers. | 3987 | * submit after we stopping all workers. |
@@ -3986,6 +3989,8 @@ void close_ctree(struct btrfs_fs_info *fs_info) | |||
3986 | invalidate_inode_pages2(fs_info->btree_inode->i_mapping); | 3989 | invalidate_inode_pages2(fs_info->btree_inode->i_mapping); |
3987 | btrfs_stop_all_workers(fs_info); | 3990 | btrfs_stop_all_workers(fs_info); |
3988 | 3991 | ||
3992 | btrfs_free_block_groups(fs_info); | ||
3993 | |||
3989 | clear_bit(BTRFS_FS_OPEN, &fs_info->flags); | 3994 | clear_bit(BTRFS_FS_OPEN, &fs_info->flags); |
3990 | free_root_pointers(fs_info, 1); | 3995 | free_root_pointers(fs_info, 1); |
3991 | 3996 | ||
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index c35b96633554..438c7312de33 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -9740,6 +9740,11 @@ void btrfs_put_block_group_cache(struct btrfs_fs_info *info) | |||
9740 | } | 9740 | } |
9741 | } | 9741 | } |
9742 | 9742 | ||
9743 | /* | ||
9744 | * Must be called only after stopping all workers, since we could have block | ||
9745 | * group caching kthreads running, and therefore they could race with us if we | ||
9746 | * freed the block groups before stopping them. | ||
9747 | */ | ||
9743 | int btrfs_free_block_groups(struct btrfs_fs_info *info) | 9748 | int btrfs_free_block_groups(struct btrfs_fs_info *info) |
9744 | { | 9749 | { |
9745 | struct btrfs_block_group_cache *block_group; | 9750 | struct btrfs_block_group_cache *block_group; |
@@ -9779,9 +9784,6 @@ int btrfs_free_block_groups(struct btrfs_fs_info *info) | |||
9779 | list_del(&block_group->list); | 9784 | list_del(&block_group->list); |
9780 | up_write(&block_group->space_info->groups_sem); | 9785 | up_write(&block_group->space_info->groups_sem); |
9781 | 9786 | ||
9782 | if (block_group->cached == BTRFS_CACHE_STARTED) | ||
9783 | wait_block_group_cache_done(block_group); | ||
9784 | |||
9785 | /* | 9787 | /* |
9786 | * We haven't cached this block group, which means we could | 9788 | * We haven't cached this block group, which means we could |
9787 | * possibly have excluded extents on this block group. | 9789 | * possibly have excluded extents on this block group. |
@@ -9791,6 +9793,7 @@ int btrfs_free_block_groups(struct btrfs_fs_info *info) | |||
9791 | free_excluded_extents(info, block_group); | 9793 | free_excluded_extents(info, block_group); |
9792 | 9794 | ||
9793 | btrfs_remove_free_space_cache(block_group); | 9795 | btrfs_remove_free_space_cache(block_group); |
9796 | ASSERT(block_group->cached != BTRFS_CACHE_STARTED); | ||
9794 | ASSERT(list_empty(&block_group->dirty_list)); | 9797 | ASSERT(list_empty(&block_group->dirty_list)); |
9795 | ASSERT(list_empty(&block_group->io_list)); | 9798 | ASSERT(list_empty(&block_group->io_list)); |
9796 | ASSERT(list_empty(&block_group->bg_list)); | 9799 | ASSERT(list_empty(&block_group->bg_list)); |
diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c index f7b9a92ad56d..e35df48b4383 100644 --- a/fs/btrfs/file-item.c +++ b/fs/btrfs/file-item.c | |||
@@ -643,7 +643,33 @@ int btrfs_del_csums(struct btrfs_trans_handle *trans, | |||
643 | 643 | ||
644 | /* delete the entire item, it is inside our range */ | 644 | /* delete the entire item, it is inside our range */ |
645 | if (key.offset >= bytenr && csum_end <= end_byte) { | 645 | if (key.offset >= bytenr && csum_end <= end_byte) { |
646 | ret = btrfs_del_item(trans, root, path); | 646 | int del_nr = 1; |
647 | |||
648 | /* | ||
649 | * Check how many csum items preceding this one in this | ||
650 | * leaf correspond to our range and then delete them all | ||
651 | * at once. | ||
652 | */ | ||
653 | if (key.offset > bytenr && path->slots[0] > 0) { | ||
654 | int slot = path->slots[0] - 1; | ||
655 | |||
656 | while (slot >= 0) { | ||
657 | struct btrfs_key pk; | ||
658 | |||
659 | btrfs_item_key_to_cpu(leaf, &pk, slot); | ||
660 | if (pk.offset < bytenr || | ||
661 | pk.type != BTRFS_EXTENT_CSUM_KEY || | ||
662 | pk.objectid != | ||
663 | BTRFS_EXTENT_CSUM_OBJECTID) | ||
664 | break; | ||
665 | path->slots[0] = slot; | ||
666 | del_nr++; | ||
667 | key.offset = pk.offset; | ||
668 | slot--; | ||
669 | } | ||
670 | } | ||
671 | ret = btrfs_del_items(trans, root, path, | ||
672 | path->slots[0], del_nr); | ||
647 | if (ret) | 673 | if (ret) |
648 | goto out; | 674 | goto out; |
649 | if (key.offset == bytenr) | 675 | if (key.offset == bytenr) |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index c38391e948d9..70df45192424 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -1331,10 +1331,16 @@ next_slot: | |||
1331 | * either valid or do not exist. | 1331 | * either valid or do not exist. |
1332 | */ | 1332 | */ |
1333 | if (csum_exist_in_range(fs_info, disk_bytenr, | 1333 | if (csum_exist_in_range(fs_info, disk_bytenr, |
1334 | num_bytes)) | 1334 | num_bytes)) { |
1335 | if (!nolock) | ||
1336 | btrfs_end_write_no_snapshoting(root); | ||
1335 | goto out_check; | 1337 | goto out_check; |
1336 | if (!btrfs_inc_nocow_writers(fs_info, disk_bytenr)) | 1338 | } |
1339 | if (!btrfs_inc_nocow_writers(fs_info, disk_bytenr)) { | ||
1340 | if (!nolock) | ||
1341 | btrfs_end_write_no_snapshoting(root); | ||
1337 | goto out_check; | 1342 | goto out_check; |
1343 | } | ||
1338 | nocow = 1; | 1344 | nocow = 1; |
1339 | } else if (extent_type == BTRFS_FILE_EXTENT_INLINE) { | 1345 | } else if (extent_type == BTRFS_FILE_EXTENT_INLINE) { |
1340 | extent_end = found_key.offset + | 1346 | extent_end = found_key.offset + |
@@ -4412,19 +4418,8 @@ search_again: | |||
4412 | if (found_type > min_type) { | 4418 | if (found_type > min_type) { |
4413 | del_item = 1; | 4419 | del_item = 1; |
4414 | } else { | 4420 | } else { |
4415 | if (item_end < new_size) { | 4421 | if (item_end < new_size) |
4416 | /* | ||
4417 | * With NO_HOLES mode, for the following mapping | ||
4418 | * | ||
4419 | * [0-4k][hole][8k-12k] | ||
4420 | * | ||
4421 | * if truncating isize down to 6k, it ends up | ||
4422 | * isize being 8k. | ||
4423 | */ | ||
4424 | if (btrfs_fs_incompat(root->fs_info, NO_HOLES)) | ||
4425 | last_size = new_size; | ||
4426 | break; | 4422 | break; |
4427 | } | ||
4428 | if (found_key.offset >= new_size) | 4423 | if (found_key.offset >= new_size) |
4429 | del_item = 1; | 4424 | del_item = 1; |
4430 | else | 4425 | else |
@@ -4607,8 +4602,12 @@ out: | |||
4607 | btrfs_abort_transaction(trans, ret); | 4602 | btrfs_abort_transaction(trans, ret); |
4608 | } | 4603 | } |
4609 | error: | 4604 | error: |
4610 | if (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID) | 4605 | if (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID) { |
4606 | ASSERT(last_size >= new_size); | ||
4607 | if (!err && last_size > new_size) | ||
4608 | last_size = new_size; | ||
4611 | btrfs_ordered_update_i_size(inode, last_size, NULL); | 4609 | btrfs_ordered_update_i_size(inode, last_size, NULL); |
4610 | } | ||
4612 | 4611 | ||
4613 | btrfs_free_path(path); | 4612 | btrfs_free_path(path); |
4614 | 4613 | ||
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c index d145ce804620..456c8901489b 100644 --- a/fs/btrfs/send.c +++ b/fs/btrfs/send.c | |||
@@ -1681,6 +1681,9 @@ static int is_inode_existent(struct send_ctx *sctx, u64 ino, u64 gen) | |||
1681 | { | 1681 | { |
1682 | int ret; | 1682 | int ret; |
1683 | 1683 | ||
1684 | if (ino == BTRFS_FIRST_FREE_OBJECTID) | ||
1685 | return 1; | ||
1686 | |||
1684 | ret = get_cur_inode_state(sctx, ino, gen); | 1687 | ret = get_cur_inode_state(sctx, ino, gen); |
1685 | if (ret < 0) | 1688 | if (ret < 0) |
1686 | goto out; | 1689 | goto out; |
@@ -1866,7 +1869,7 @@ static int will_overwrite_ref(struct send_ctx *sctx, u64 dir, u64 dir_gen, | |||
1866 | * not deleted and then re-created, if it was then we have no overwrite | 1869 | * not deleted and then re-created, if it was then we have no overwrite |
1867 | * and we can just unlink this entry. | 1870 | * and we can just unlink this entry. |
1868 | */ | 1871 | */ |
1869 | if (sctx->parent_root) { | 1872 | if (sctx->parent_root && dir != BTRFS_FIRST_FREE_OBJECTID) { |
1870 | ret = get_inode_info(sctx->parent_root, dir, NULL, &gen, NULL, | 1873 | ret = get_inode_info(sctx->parent_root, dir, NULL, &gen, NULL, |
1871 | NULL, NULL, NULL); | 1874 | NULL, NULL, NULL); |
1872 | if (ret < 0 && ret != -ENOENT) | 1875 | if (ret < 0 && ret != -ENOENT) |
@@ -1934,6 +1937,19 @@ static int did_overwrite_ref(struct send_ctx *sctx, | |||
1934 | if (ret <= 0) | 1937 | if (ret <= 0) |
1935 | goto out; | 1938 | goto out; |
1936 | 1939 | ||
1940 | if (dir != BTRFS_FIRST_FREE_OBJECTID) { | ||
1941 | ret = get_inode_info(sctx->send_root, dir, NULL, &gen, NULL, | ||
1942 | NULL, NULL, NULL); | ||
1943 | if (ret < 0 && ret != -ENOENT) | ||
1944 | goto out; | ||
1945 | if (ret) { | ||
1946 | ret = 0; | ||
1947 | goto out; | ||
1948 | } | ||
1949 | if (gen != dir_gen) | ||
1950 | goto out; | ||
1951 | } | ||
1952 | |||
1937 | /* check if the ref was overwritten by another ref */ | 1953 | /* check if the ref was overwritten by another ref */ |
1938 | ret = lookup_dir_item_inode(sctx->send_root, dir, name, name_len, | 1954 | ret = lookup_dir_item_inode(sctx->send_root, dir, name, name_len, |
1939 | &ow_inode, &other_type); | 1955 | &ow_inode, &other_type); |
@@ -3556,6 +3572,7 @@ static int wait_for_parent_move(struct send_ctx *sctx, | |||
3556 | { | 3572 | { |
3557 | int ret = 0; | 3573 | int ret = 0; |
3558 | u64 ino = parent_ref->dir; | 3574 | u64 ino = parent_ref->dir; |
3575 | u64 ino_gen = parent_ref->dir_gen; | ||
3559 | u64 parent_ino_before, parent_ino_after; | 3576 | u64 parent_ino_before, parent_ino_after; |
3560 | struct fs_path *path_before = NULL; | 3577 | struct fs_path *path_before = NULL; |
3561 | struct fs_path *path_after = NULL; | 3578 | struct fs_path *path_after = NULL; |
@@ -3576,6 +3593,8 @@ static int wait_for_parent_move(struct send_ctx *sctx, | |||
3576 | * at get_cur_path()). | 3593 | * at get_cur_path()). |
3577 | */ | 3594 | */ |
3578 | while (ino > BTRFS_FIRST_FREE_OBJECTID) { | 3595 | while (ino > BTRFS_FIRST_FREE_OBJECTID) { |
3596 | u64 parent_ino_after_gen; | ||
3597 | |||
3579 | if (is_waiting_for_move(sctx, ino)) { | 3598 | if (is_waiting_for_move(sctx, ino)) { |
3580 | /* | 3599 | /* |
3581 | * If the current inode is an ancestor of ino in the | 3600 | * If the current inode is an ancestor of ino in the |
@@ -3598,7 +3617,7 @@ static int wait_for_parent_move(struct send_ctx *sctx, | |||
3598 | fs_path_reset(path_after); | 3617 | fs_path_reset(path_after); |
3599 | 3618 | ||
3600 | ret = get_first_ref(sctx->send_root, ino, &parent_ino_after, | 3619 | ret = get_first_ref(sctx->send_root, ino, &parent_ino_after, |
3601 | NULL, path_after); | 3620 | &parent_ino_after_gen, path_after); |
3602 | if (ret < 0) | 3621 | if (ret < 0) |
3603 | goto out; | 3622 | goto out; |
3604 | ret = get_first_ref(sctx->parent_root, ino, &parent_ino_before, | 3623 | ret = get_first_ref(sctx->parent_root, ino, &parent_ino_before, |
@@ -3615,10 +3634,20 @@ static int wait_for_parent_move(struct send_ctx *sctx, | |||
3615 | if (ino > sctx->cur_ino && | 3634 | if (ino > sctx->cur_ino && |
3616 | (parent_ino_before != parent_ino_after || len1 != len2 || | 3635 | (parent_ino_before != parent_ino_after || len1 != len2 || |
3617 | memcmp(path_before->start, path_after->start, len1))) { | 3636 | memcmp(path_before->start, path_after->start, len1))) { |
3618 | ret = 1; | 3637 | u64 parent_ino_gen; |
3619 | break; | 3638 | |
3639 | ret = get_inode_info(sctx->parent_root, ino, NULL, | ||
3640 | &parent_ino_gen, NULL, NULL, NULL, | ||
3641 | NULL); | ||
3642 | if (ret < 0) | ||
3643 | goto out; | ||
3644 | if (ino_gen == parent_ino_gen) { | ||
3645 | ret = 1; | ||
3646 | break; | ||
3647 | } | ||
3620 | } | 3648 | } |
3621 | ino = parent_ino_after; | 3649 | ino = parent_ino_after; |
3650 | ino_gen = parent_ino_after_gen; | ||
3622 | } | 3651 | } |
3623 | 3652 | ||
3624 | out: | 3653 | out: |
@@ -5277,6 +5306,81 @@ out: | |||
5277 | return ret; | 5306 | return ret; |
5278 | } | 5307 | } |
5279 | 5308 | ||
5309 | static int range_is_hole_in_parent(struct send_ctx *sctx, | ||
5310 | const u64 start, | ||
5311 | const u64 end) | ||
5312 | { | ||
5313 | struct btrfs_path *path; | ||
5314 | struct btrfs_key key; | ||
5315 | struct btrfs_root *root = sctx->parent_root; | ||
5316 | u64 search_start = start; | ||
5317 | int ret; | ||
5318 | |||
5319 | path = alloc_path_for_send(); | ||
5320 | if (!path) | ||
5321 | return -ENOMEM; | ||
5322 | |||
5323 | key.objectid = sctx->cur_ino; | ||
5324 | key.type = BTRFS_EXTENT_DATA_KEY; | ||
5325 | key.offset = search_start; | ||
5326 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); | ||
5327 | if (ret < 0) | ||
5328 | goto out; | ||
5329 | if (ret > 0 && path->slots[0] > 0) | ||
5330 | path->slots[0]--; | ||
5331 | |||
5332 | while (search_start < end) { | ||
5333 | struct extent_buffer *leaf = path->nodes[0]; | ||
5334 | int slot = path->slots[0]; | ||
5335 | struct btrfs_file_extent_item *fi; | ||
5336 | u64 extent_end; | ||
5337 | |||
5338 | if (slot >= btrfs_header_nritems(leaf)) { | ||
5339 | ret = btrfs_next_leaf(root, path); | ||
5340 | if (ret < 0) | ||
5341 | goto out; | ||
5342 | else if (ret > 0) | ||
5343 | break; | ||
5344 | continue; | ||
5345 | } | ||
5346 | |||
5347 | btrfs_item_key_to_cpu(leaf, &key, slot); | ||
5348 | if (key.objectid < sctx->cur_ino || | ||
5349 | key.type < BTRFS_EXTENT_DATA_KEY) | ||
5350 | goto next; | ||
5351 | if (key.objectid > sctx->cur_ino || | ||
5352 | key.type > BTRFS_EXTENT_DATA_KEY || | ||
5353 | key.offset >= end) | ||
5354 | break; | ||
5355 | |||
5356 | fi = btrfs_item_ptr(leaf, slot, struct btrfs_file_extent_item); | ||
5357 | if (btrfs_file_extent_type(leaf, fi) == | ||
5358 | BTRFS_FILE_EXTENT_INLINE) { | ||
5359 | u64 size = btrfs_file_extent_inline_len(leaf, slot, fi); | ||
5360 | |||
5361 | extent_end = ALIGN(key.offset + size, | ||
5362 | root->fs_info->sectorsize); | ||
5363 | } else { | ||
5364 | extent_end = key.offset + | ||
5365 | btrfs_file_extent_num_bytes(leaf, fi); | ||
5366 | } | ||
5367 | if (extent_end <= start) | ||
5368 | goto next; | ||
5369 | if (btrfs_file_extent_disk_bytenr(leaf, fi) == 0) { | ||
5370 | search_start = extent_end; | ||
5371 | goto next; | ||
5372 | } | ||
5373 | ret = 0; | ||
5374 | goto out; | ||
5375 | next: | ||
5376 | path->slots[0]++; | ||
5377 | } | ||
5378 | ret = 1; | ||
5379 | out: | ||
5380 | btrfs_free_path(path); | ||
5381 | return ret; | ||
5382 | } | ||
5383 | |||
5280 | static int maybe_send_hole(struct send_ctx *sctx, struct btrfs_path *path, | 5384 | static int maybe_send_hole(struct send_ctx *sctx, struct btrfs_path *path, |
5281 | struct btrfs_key *key) | 5385 | struct btrfs_key *key) |
5282 | { | 5386 | { |
@@ -5321,8 +5425,17 @@ static int maybe_send_hole(struct send_ctx *sctx, struct btrfs_path *path, | |||
5321 | return ret; | 5425 | return ret; |
5322 | } | 5426 | } |
5323 | 5427 | ||
5324 | if (sctx->cur_inode_last_extent < key->offset) | 5428 | if (sctx->cur_inode_last_extent < key->offset) { |
5325 | ret = send_hole(sctx, key->offset); | 5429 | ret = range_is_hole_in_parent(sctx, |
5430 | sctx->cur_inode_last_extent, | ||
5431 | key->offset); | ||
5432 | if (ret < 0) | ||
5433 | return ret; | ||
5434 | else if (ret == 0) | ||
5435 | ret = send_hole(sctx, key->offset); | ||
5436 | else | ||
5437 | ret = 0; | ||
5438 | } | ||
5326 | sctx->cur_inode_last_extent = extent_end; | 5439 | sctx->cur_inode_last_extent = extent_end; |
5327 | return ret; | 5440 | return ret; |
5328 | } | 5441 | } |
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 3806853cde08..3cc972330ab3 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c | |||
@@ -673,6 +673,10 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans, | |||
673 | unsigned long dest_offset; | 673 | unsigned long dest_offset; |
674 | struct btrfs_key ins; | 674 | struct btrfs_key ins; |
675 | 675 | ||
676 | if (btrfs_file_extent_disk_bytenr(eb, item) == 0 && | ||
677 | btrfs_fs_incompat(fs_info, NO_HOLES)) | ||
678 | goto update_inode; | ||
679 | |||
676 | ret = btrfs_insert_empty_item(trans, root, path, key, | 680 | ret = btrfs_insert_empty_item(trans, root, path, key, |
677 | sizeof(*item)); | 681 | sizeof(*item)); |
678 | if (ret) | 682 | if (ret) |
@@ -825,6 +829,7 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans, | |||
825 | } | 829 | } |
826 | 830 | ||
827 | inode_add_bytes(inode, nbytes); | 831 | inode_add_bytes(inode, nbytes); |
832 | update_inode: | ||
828 | ret = btrfs_update_inode(trans, root, inode); | 833 | ret = btrfs_update_inode(trans, root, inode); |
829 | out: | 834 | out: |
830 | if (inode) | 835 | if (inode) |