diff options
author | Yan Zheng <zheng.yan@oracle.com> | 2008-10-30 14:25:28 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-10-30 14:25:28 -0400 |
commit | d899e05215178fed903ad0e7fc1cb4d8e0cc0a88 (patch) | |
tree | 2969e3558f5c50ec0f9ac4201099c0d5d1d6e2c2 | |
parent | 80ff385665b7fca29fefe358a60ab0d09f9b8e87 (diff) |
Btrfs: Add fallocate support v2
This patch updates btrfs-progs for fallocate support.
fallocate is a little different in Btrfs because we need to tell the
COW system that a given preallocated extent doesn't need to be
cow'd as long as there are no snapshots of it. This leverages the
-o nodatacow checks.
Signed-off-by: Yan Zheng <zheng.yan@oracle.com>
-rw-r--r-- | fs/btrfs/ctree.h | 9 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 65 | ||||
-rw-r--r-- | fs/btrfs/extent_io.c | 12 | ||||
-rw-r--r-- | fs/btrfs/extent_map.h | 1 | ||||
-rw-r--r-- | fs/btrfs/file.c | 245 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 323 | ||||
-rw-r--r-- | fs/btrfs/ioctl.c | 3 | ||||
-rw-r--r-- | fs/btrfs/ordered-data.c | 5 | ||||
-rw-r--r-- | fs/btrfs/ordered-data.h | 4 | ||||
-rw-r--r-- | fs/btrfs/tree-log.c | 13 |
10 files changed, 563 insertions, 117 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 8bf6a085a730..d5ba3d1aaf9a 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -462,8 +462,9 @@ struct btrfs_root_item { | |||
462 | u8 level; | 462 | u8 level; |
463 | } __attribute__ ((__packed__)); | 463 | } __attribute__ ((__packed__)); |
464 | 464 | ||
465 | #define BTRFS_FILE_EXTENT_REG 0 | 465 | #define BTRFS_FILE_EXTENT_INLINE 0 |
466 | #define BTRFS_FILE_EXTENT_INLINE 1 | 466 | #define BTRFS_FILE_EXTENT_REG 1 |
467 | #define BTRFS_FILE_EXTENT_PREALLOC 2 | ||
467 | 468 | ||
468 | struct btrfs_file_extent_item { | 469 | struct btrfs_file_extent_item { |
469 | /* | 470 | /* |
@@ -868,6 +869,7 @@ struct btrfs_root { | |||
868 | #define BTRFS_INODE_NODATACOW (1 << 1) | 869 | #define BTRFS_INODE_NODATACOW (1 << 1) |
869 | #define BTRFS_INODE_READONLY (1 << 2) | 870 | #define BTRFS_INODE_READONLY (1 << 2) |
870 | #define BTRFS_INODE_NOCOMPRESS (1 << 3) | 871 | #define BTRFS_INODE_NOCOMPRESS (1 << 3) |
872 | #define BTRFS_INODE_PREALLOC (1 << 4) | ||
871 | #define btrfs_clear_flag(inode, flag) (BTRFS_I(inode)->flags &= \ | 873 | #define btrfs_clear_flag(inode, flag) (BTRFS_I(inode)->flags &= \ |
872 | ~BTRFS_INODE_##flag) | 874 | ~BTRFS_INODE_##flag) |
873 | #define btrfs_set_flag(inode, flag) (BTRFS_I(inode)->flags |= \ | 875 | #define btrfs_set_flag(inode, flag) (BTRFS_I(inode)->flags |= \ |
@@ -1924,6 +1926,9 @@ extern struct file_operations btrfs_file_operations; | |||
1924 | int btrfs_drop_extents(struct btrfs_trans_handle *trans, | 1926 | int btrfs_drop_extents(struct btrfs_trans_handle *trans, |
1925 | struct btrfs_root *root, struct inode *inode, | 1927 | struct btrfs_root *root, struct inode *inode, |
1926 | u64 start, u64 end, u64 inline_limit, u64 *hint_block); | 1928 | u64 start, u64 end, u64 inline_limit, u64 *hint_block); |
1929 | int btrfs_mark_extent_written(struct btrfs_trans_handle *trans, | ||
1930 | struct btrfs_root *root, | ||
1931 | struct inode *inode, u64 start, u64 end); | ||
1927 | int btrfs_release_file(struct inode *inode, struct file *file); | 1932 | int btrfs_release_file(struct inode *inode, struct file *file); |
1928 | 1933 | ||
1929 | /* tree-defrag.c */ | 1934 | /* tree-defrag.c */ |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 1eb69a91b727..8af39521eb71 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -2147,6 +2147,9 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans, | |||
2147 | total_needed += empty_size; | 2147 | total_needed += empty_size; |
2148 | 2148 | ||
2149 | block_group = btrfs_lookup_block_group(root->fs_info, search_start); | 2149 | block_group = btrfs_lookup_block_group(root->fs_info, search_start); |
2150 | if (!block_group) | ||
2151 | block_group = btrfs_lookup_first_block_group(root->fs_info, | ||
2152 | search_start); | ||
2150 | space_info = __find_space_info(root->fs_info, data); | 2153 | space_info = __find_space_info(root->fs_info, data); |
2151 | 2154 | ||
2152 | down_read(&space_info->groups_sem); | 2155 | down_read(&space_info->groups_sem); |
@@ -3426,9 +3429,7 @@ walk_down: | |||
3426 | next: | 3429 | next: |
3427 | level--; | 3430 | level--; |
3428 | btrfs_release_path(extent_root, path); | 3431 | btrfs_release_path(extent_root, path); |
3429 | if (need_resched()) { | 3432 | cond_resched(); |
3430 | cond_resched(); | ||
3431 | } | ||
3432 | } | 3433 | } |
3433 | /* reached lowest level */ | 3434 | /* reached lowest level */ |
3434 | ret = 1; | 3435 | ret = 1; |
@@ -3539,9 +3540,7 @@ found: | |||
3539 | } | 3540 | } |
3540 | 3541 | ||
3541 | btrfs_release_path(extent_root, path); | 3542 | btrfs_release_path(extent_root, path); |
3542 | if (need_resched()) { | 3543 | cond_resched(); |
3543 | cond_resched(); | ||
3544 | } | ||
3545 | } | 3544 | } |
3546 | /* reached max tree level, but no tree root found. */ | 3545 | /* reached max tree level, but no tree root found. */ |
3547 | BUG(); | 3546 | BUG(); |
@@ -3654,8 +3653,9 @@ static int noinline get_new_locations(struct inode *reloc_inode, | |||
3654 | exts[nr].encryption = btrfs_file_extent_encryption(leaf, fi); | 3653 | exts[nr].encryption = btrfs_file_extent_encryption(leaf, fi); |
3655 | exts[nr].other_encoding = btrfs_file_extent_other_encoding(leaf, | 3654 | exts[nr].other_encoding = btrfs_file_extent_other_encoding(leaf, |
3656 | fi); | 3655 | fi); |
3657 | WARN_ON(exts[nr].offset > 0); | 3656 | BUG_ON(exts[nr].offset > 0); |
3658 | WARN_ON(exts[nr].num_bytes != exts[nr].disk_num_bytes); | 3657 | BUG_ON(exts[nr].compression || exts[nr].encryption); |
3658 | BUG_ON(exts[nr].num_bytes != exts[nr].disk_num_bytes); | ||
3659 | 3659 | ||
3660 | cur_pos += exts[nr].num_bytes; | 3660 | cur_pos += exts[nr].num_bytes; |
3661 | nr++; | 3661 | nr++; |
@@ -3709,6 +3709,7 @@ static int noinline replace_one_extent(struct btrfs_trans_handle *trans, | |||
3709 | u32 nritems; | 3709 | u32 nritems; |
3710 | int nr_scaned = 0; | 3710 | int nr_scaned = 0; |
3711 | int extent_locked = 0; | 3711 | int extent_locked = 0; |
3712 | int extent_type; | ||
3712 | int ret; | 3713 | int ret; |
3713 | 3714 | ||
3714 | memcpy(&key, leaf_key, sizeof(key)); | 3715 | memcpy(&key, leaf_key, sizeof(key)); |
@@ -3781,8 +3782,9 @@ next: | |||
3781 | } | 3782 | } |
3782 | fi = btrfs_item_ptr(leaf, path->slots[0], | 3783 | fi = btrfs_item_ptr(leaf, path->slots[0], |
3783 | struct btrfs_file_extent_item); | 3784 | struct btrfs_file_extent_item); |
3784 | if ((btrfs_file_extent_type(leaf, fi) != | 3785 | extent_type = btrfs_file_extent_type(leaf, fi); |
3785 | BTRFS_FILE_EXTENT_REG) || | 3786 | if ((extent_type != BTRFS_FILE_EXTENT_REG && |
3787 | extent_type != BTRFS_FILE_EXTENT_PREALLOC) || | ||
3786 | (btrfs_file_extent_disk_bytenr(leaf, fi) != | 3788 | (btrfs_file_extent_disk_bytenr(leaf, fi) != |
3787 | extent_key->objectid)) { | 3789 | extent_key->objectid)) { |
3788 | path->slots[0]++; | 3790 | path->slots[0]++; |
@@ -3865,16 +3867,10 @@ next: | |||
3865 | 3867 | ||
3866 | if (nr_extents == 1) { | 3868 | if (nr_extents == 1) { |
3867 | /* update extent pointer in place */ | 3869 | /* update extent pointer in place */ |
3868 | btrfs_set_file_extent_generation(leaf, fi, | ||
3869 | trans->transid); | ||
3870 | btrfs_set_file_extent_disk_bytenr(leaf, fi, | 3870 | btrfs_set_file_extent_disk_bytenr(leaf, fi, |
3871 | new_extents[0].disk_bytenr); | 3871 | new_extents[0].disk_bytenr); |
3872 | btrfs_set_file_extent_disk_num_bytes(leaf, fi, | 3872 | btrfs_set_file_extent_disk_num_bytes(leaf, fi, |
3873 | new_extents[0].disk_num_bytes); | 3873 | new_extents[0].disk_num_bytes); |
3874 | btrfs_set_file_extent_ram_bytes(leaf, fi, | ||
3875 | new_extents[0].ram_bytes); | ||
3876 | ext_offset += new_extents[0].offset; | ||
3877 | btrfs_set_file_extent_offset(leaf, fi, ext_offset); | ||
3878 | btrfs_mark_buffer_dirty(leaf); | 3874 | btrfs_mark_buffer_dirty(leaf); |
3879 | 3875 | ||
3880 | btrfs_drop_extent_cache(inode, key.offset, | 3876 | btrfs_drop_extent_cache(inode, key.offset, |
@@ -3901,6 +3897,8 @@ next: | |||
3901 | btrfs_release_path(root, path); | 3897 | btrfs_release_path(root, path); |
3902 | key.offset += num_bytes; | 3898 | key.offset += num_bytes; |
3903 | } else { | 3899 | } else { |
3900 | BUG_ON(1); | ||
3901 | #if 0 | ||
3904 | u64 alloc_hint; | 3902 | u64 alloc_hint; |
3905 | u64 extent_len; | 3903 | u64 extent_len; |
3906 | int i; | 3904 | int i; |
@@ -3977,6 +3975,7 @@ next: | |||
3977 | break; | 3975 | break; |
3978 | } | 3976 | } |
3979 | BUG_ON(i >= nr_extents); | 3977 | BUG_ON(i >= nr_extents); |
3978 | #endif | ||
3980 | } | 3979 | } |
3981 | 3980 | ||
3982 | if (extent_locked) { | 3981 | if (extent_locked) { |
@@ -4156,15 +4155,10 @@ static int noinline replace_extents_in_leaf(struct btrfs_trans_handle *trans, | |||
4156 | ref->extents[ext_index].bytenr = new_extent->disk_bytenr; | 4155 | ref->extents[ext_index].bytenr = new_extent->disk_bytenr; |
4157 | ref->extents[ext_index].num_bytes = new_extent->disk_num_bytes; | 4156 | ref->extents[ext_index].num_bytes = new_extent->disk_num_bytes; |
4158 | 4157 | ||
4159 | btrfs_set_file_extent_generation(leaf, fi, trans->transid); | ||
4160 | btrfs_set_file_extent_ram_bytes(leaf, fi, | ||
4161 | new_extent->ram_bytes); | ||
4162 | btrfs_set_file_extent_disk_bytenr(leaf, fi, | 4158 | btrfs_set_file_extent_disk_bytenr(leaf, fi, |
4163 | new_extent->disk_bytenr); | 4159 | new_extent->disk_bytenr); |
4164 | btrfs_set_file_extent_disk_num_bytes(leaf, fi, | 4160 | btrfs_set_file_extent_disk_num_bytes(leaf, fi, |
4165 | new_extent->disk_num_bytes); | 4161 | new_extent->disk_num_bytes); |
4166 | new_extent->offset += btrfs_file_extent_offset(leaf, fi); | ||
4167 | btrfs_set_file_extent_offset(leaf, fi, new_extent->offset); | ||
4168 | btrfs_mark_buffer_dirty(leaf); | 4162 | btrfs_mark_buffer_dirty(leaf); |
4169 | 4163 | ||
4170 | ret = btrfs_inc_extent_ref(trans, root, | 4164 | ret = btrfs_inc_extent_ref(trans, root, |
@@ -4625,12 +4619,15 @@ static int noinline relocate_one_extent(struct btrfs_root *extent_root, | |||
4625 | */ | 4619 | */ |
4626 | if (!new_extents) { | 4620 | if (!new_extents) { |
4627 | u64 group_start = group->key.objectid; | 4621 | u64 group_start = group->key.objectid; |
4622 | new_extents = kmalloc(sizeof(*new_extents), | ||
4623 | GFP_NOFS); | ||
4624 | nr_extents = 1; | ||
4628 | ret = get_new_locations(reloc_inode, | 4625 | ret = get_new_locations(reloc_inode, |
4629 | extent_key, | 4626 | extent_key, |
4630 | group_start, 0, | 4627 | group_start, 1, |
4631 | &new_extents, | 4628 | &new_extents, |
4632 | &nr_extents); | 4629 | &nr_extents); |
4633 | if (ret < 0) | 4630 | if (ret) |
4634 | goto out; | 4631 | goto out; |
4635 | } | 4632 | } |
4636 | btrfs_record_root_in_trans(found_root); | 4633 | btrfs_record_root_in_trans(found_root); |
@@ -4762,7 +4759,8 @@ static int __insert_orphan_inode(struct btrfs_trans_handle *trans, | |||
4762 | btrfs_set_inode_generation(leaf, item, 1); | 4759 | btrfs_set_inode_generation(leaf, item, 1); |
4763 | btrfs_set_inode_size(leaf, item, size); | 4760 | btrfs_set_inode_size(leaf, item, size); |
4764 | btrfs_set_inode_mode(leaf, item, S_IFREG | 0600); | 4761 | btrfs_set_inode_mode(leaf, item, S_IFREG | 0600); |
4765 | btrfs_set_inode_flags(leaf, item, BTRFS_INODE_NODATASUM); | 4762 | btrfs_set_inode_flags(leaf, item, BTRFS_INODE_NODATASUM | |
4763 | BTRFS_INODE_NOCOMPRESS); | ||
4766 | btrfs_mark_buffer_dirty(leaf); | 4764 | btrfs_mark_buffer_dirty(leaf); |
4767 | btrfs_release_path(root, path); | 4765 | btrfs_release_path(root, path); |
4768 | out: | 4766 | out: |
@@ -4835,6 +4833,7 @@ int btrfs_relocate_block_group(struct btrfs_root *root, u64 group_start) | |||
4835 | struct inode *reloc_inode; | 4833 | struct inode *reloc_inode; |
4836 | struct btrfs_block_group_cache *block_group; | 4834 | struct btrfs_block_group_cache *block_group; |
4837 | struct btrfs_key key; | 4835 | struct btrfs_key key; |
4836 | u64 skipped; | ||
4838 | u64 cur_byte; | 4837 | u64 cur_byte; |
4839 | u64 total_found; | 4838 | u64 total_found; |
4840 | u32 nritems; | 4839 | u32 nritems; |
@@ -4864,6 +4863,7 @@ int btrfs_relocate_block_group(struct btrfs_root *root, u64 group_start) | |||
4864 | btrfs_start_delalloc_inodes(info->tree_root); | 4863 | btrfs_start_delalloc_inodes(info->tree_root); |
4865 | btrfs_wait_ordered_extents(info->tree_root, 0); | 4864 | btrfs_wait_ordered_extents(info->tree_root, 0); |
4866 | again: | 4865 | again: |
4866 | skipped = 0; | ||
4867 | total_found = 0; | 4867 | total_found = 0; |
4868 | progress = 0; | 4868 | progress = 0; |
4869 | key.objectid = block_group->key.objectid; | 4869 | key.objectid = block_group->key.objectid; |
@@ -4926,6 +4926,8 @@ next: | |||
4926 | ret = relocate_one_extent(root, path, &key, block_group, | 4926 | ret = relocate_one_extent(root, path, &key, block_group, |
4927 | reloc_inode, pass); | 4927 | reloc_inode, pass); |
4928 | BUG_ON(ret < 0); | 4928 | BUG_ON(ret < 0); |
4929 | if (ret > 0) | ||
4930 | skipped++; | ||
4929 | 4931 | ||
4930 | key.objectid = cur_byte; | 4932 | key.objectid = cur_byte; |
4931 | key.type = 0; | 4933 | key.type = 0; |
@@ -4944,6 +4946,11 @@ next: | |||
4944 | printk("btrfs found %llu extents in pass %d\n", | 4946 | printk("btrfs found %llu extents in pass %d\n", |
4945 | (unsigned long long)total_found, pass); | 4947 | (unsigned long long)total_found, pass); |
4946 | pass++; | 4948 | pass++; |
4949 | if (total_found == skipped && pass > 2) { | ||
4950 | iput(reloc_inode); | ||
4951 | reloc_inode = create_reloc_inode(info, block_group); | ||
4952 | pass = 0; | ||
4953 | } | ||
4947 | goto again; | 4954 | goto again; |
4948 | } | 4955 | } |
4949 | 4956 | ||
@@ -5011,17 +5018,17 @@ int btrfs_free_block_groups(struct btrfs_fs_info *info) | |||
5011 | while ((n = rb_last(&info->block_group_cache_tree)) != NULL) { | 5018 | while ((n = rb_last(&info->block_group_cache_tree)) != NULL) { |
5012 | block_group = rb_entry(n, struct btrfs_block_group_cache, | 5019 | block_group = rb_entry(n, struct btrfs_block_group_cache, |
5013 | cache_node); | 5020 | cache_node); |
5014 | |||
5015 | spin_unlock(&info->block_group_cache_lock); | ||
5016 | btrfs_remove_free_space_cache(block_group); | ||
5017 | spin_lock(&info->block_group_cache_lock); | ||
5018 | |||
5019 | rb_erase(&block_group->cache_node, | 5021 | rb_erase(&block_group->cache_node, |
5020 | &info->block_group_cache_tree); | 5022 | &info->block_group_cache_tree); |
5023 | spin_unlock(&info->block_group_cache_lock); | ||
5024 | |||
5025 | btrfs_remove_free_space_cache(block_group); | ||
5021 | down_write(&block_group->space_info->groups_sem); | 5026 | down_write(&block_group->space_info->groups_sem); |
5022 | list_del(&block_group->list); | 5027 | list_del(&block_group->list); |
5023 | up_write(&block_group->space_info->groups_sem); | 5028 | up_write(&block_group->space_info->groups_sem); |
5024 | kfree(block_group); | 5029 | kfree(block_group); |
5030 | |||
5031 | spin_lock(&info->block_group_cache_lock); | ||
5025 | } | 5032 | } |
5026 | spin_unlock(&info->block_group_cache_lock); | 5033 | spin_unlock(&info->block_group_cache_lock); |
5027 | return 0; | 5034 | return 0; |
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 65a0583027e9..eb3c12e7beaf 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c | |||
@@ -2015,6 +2015,8 @@ printk("2bad mapping end %Lu cur %Lu\n", end, cur); | |||
2015 | } | 2015 | } |
2016 | bdev = em->bdev; | 2016 | bdev = em->bdev; |
2017 | block_start = em->block_start; | 2017 | block_start = em->block_start; |
2018 | if (test_bit(EXTENT_FLAG_PREALLOC, &em->flags)) | ||
2019 | block_start = EXTENT_MAP_HOLE; | ||
2018 | free_extent_map(em); | 2020 | free_extent_map(em); |
2019 | em = NULL; | 2021 | em = NULL; |
2020 | 2022 | ||
@@ -2769,14 +2771,18 @@ sector_t extent_bmap(struct address_space *mapping, sector_t iblock, | |||
2769 | struct inode *inode = mapping->host; | 2771 | struct inode *inode = mapping->host; |
2770 | u64 start = iblock << inode->i_blkbits; | 2772 | u64 start = iblock << inode->i_blkbits; |
2771 | sector_t sector = 0; | 2773 | sector_t sector = 0; |
2774 | size_t blksize = (1 << inode->i_blkbits); | ||
2772 | struct extent_map *em; | 2775 | struct extent_map *em; |
2773 | 2776 | ||
2774 | em = get_extent(inode, NULL, 0, start, (1 << inode->i_blkbits), 0); | 2777 | lock_extent(&BTRFS_I(inode)->io_tree, start, start + blksize - 1, |
2778 | GFP_NOFS); | ||
2779 | em = get_extent(inode, NULL, 0, start, blksize, 0); | ||
2780 | unlock_extent(&BTRFS_I(inode)->io_tree, start, start + blksize - 1, | ||
2781 | GFP_NOFS); | ||
2775 | if (!em || IS_ERR(em)) | 2782 | if (!em || IS_ERR(em)) |
2776 | return 0; | 2783 | return 0; |
2777 | 2784 | ||
2778 | if (em->block_start == EXTENT_MAP_INLINE || | 2785 | if (em->block_start > EXTENT_MAP_LAST_BYTE) |
2779 | em->block_start == EXTENT_MAP_HOLE) | ||
2780 | goto out; | 2786 | goto out; |
2781 | 2787 | ||
2782 | sector = (em->block_start + start - em->start) >> inode->i_blkbits; | 2788 | sector = (em->block_start + start - em->start) >> inode->i_blkbits; |
diff --git a/fs/btrfs/extent_map.h b/fs/btrfs/extent_map.h index e693e1b4ac4a..accfedaeb513 100644 --- a/fs/btrfs/extent_map.h +++ b/fs/btrfs/extent_map.h | |||
@@ -12,6 +12,7 @@ | |||
12 | #define EXTENT_FLAG_PINNED 0 /* this entry not yet on disk, don't free it */ | 12 | #define EXTENT_FLAG_PINNED 0 /* this entry not yet on disk, don't free it */ |
13 | #define EXTENT_FLAG_COMPRESSED 1 | 13 | #define EXTENT_FLAG_COMPRESSED 1 |
14 | #define EXTENT_FLAG_VACANCY 2 /* no file extent item found */ | 14 | #define EXTENT_FLAG_VACANCY 2 /* no file extent item found */ |
15 | #define EXTENT_FLAG_PREALLOC 3 /* pre-allocated extent */ | ||
15 | 16 | ||
16 | struct extent_map { | 17 | struct extent_map { |
17 | struct rb_node rb_node; | 18 | struct rb_node rb_node; |
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 1a0510ad030c..238a8e215eb9 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
@@ -381,7 +381,7 @@ int noinline btrfs_drop_extents(struct btrfs_trans_handle *trans, | |||
381 | int keep; | 381 | int keep; |
382 | int slot; | 382 | int slot; |
383 | int bookend; | 383 | int bookend; |
384 | int found_type; | 384 | int found_type = 0; |
385 | int found_extent; | 385 | int found_extent; |
386 | int found_inline; | 386 | int found_inline; |
387 | int recow; | 387 | int recow; |
@@ -442,7 +442,8 @@ next_slot: | |||
442 | extent); | 442 | extent); |
443 | other_encoding = btrfs_file_extent_other_encoding(leaf, | 443 | other_encoding = btrfs_file_extent_other_encoding(leaf, |
444 | extent); | 444 | extent); |
445 | if (found_type == BTRFS_FILE_EXTENT_REG) { | 445 | if (found_type == BTRFS_FILE_EXTENT_REG || |
446 | found_type == BTRFS_FILE_EXTENT_PREALLOC) { | ||
446 | extent_end = | 447 | extent_end = |
447 | btrfs_file_extent_disk_bytenr(leaf, | 448 | btrfs_file_extent_disk_bytenr(leaf, |
448 | extent); | 449 | extent); |
@@ -609,8 +610,7 @@ next_slot: | |||
609 | */ | 610 | */ |
610 | btrfs_set_file_extent_ram_bytes(leaf, extent, | 611 | btrfs_set_file_extent_ram_bytes(leaf, extent, |
611 | ram_bytes); | 612 | ram_bytes); |
612 | btrfs_set_file_extent_type(leaf, extent, | 613 | btrfs_set_file_extent_type(leaf, extent, found_type); |
613 | BTRFS_FILE_EXTENT_REG); | ||
614 | 614 | ||
615 | btrfs_mark_buffer_dirty(path->nodes[0]); | 615 | btrfs_mark_buffer_dirty(path->nodes[0]); |
616 | 616 | ||
@@ -661,6 +661,243 @@ out: | |||
661 | return ret; | 661 | return ret; |
662 | } | 662 | } |
663 | 663 | ||
664 | static int extent_mergeable(struct extent_buffer *leaf, int slot, | ||
665 | u64 objectid, u64 bytenr, u64 *start, u64 *end) | ||
666 | { | ||
667 | struct btrfs_file_extent_item *fi; | ||
668 | struct btrfs_key key; | ||
669 | u64 extent_end; | ||
670 | |||
671 | if (slot < 0 || slot >= btrfs_header_nritems(leaf)) | ||
672 | return 0; | ||
673 | |||
674 | btrfs_item_key_to_cpu(leaf, &key, slot); | ||
675 | if (key.objectid != objectid || key.type != BTRFS_EXTENT_DATA_KEY) | ||
676 | return 0; | ||
677 | |||
678 | fi = btrfs_item_ptr(leaf, slot, struct btrfs_file_extent_item); | ||
679 | if (btrfs_file_extent_type(leaf, fi) != BTRFS_FILE_EXTENT_REG || | ||
680 | btrfs_file_extent_disk_bytenr(leaf, fi) != bytenr || | ||
681 | btrfs_file_extent_compression(leaf, fi) || | ||
682 | btrfs_file_extent_encryption(leaf, fi) || | ||
683 | btrfs_file_extent_other_encoding(leaf, fi)) | ||
684 | return 0; | ||
685 | |||
686 | extent_end = key.offset + btrfs_file_extent_num_bytes(leaf, fi); | ||
687 | if ((*start && *start != key.offset) || (*end && *end != extent_end)) | ||
688 | return 0; | ||
689 | |||
690 | *start = key.offset; | ||
691 | *end = extent_end; | ||
692 | return 1; | ||
693 | } | ||
694 | |||
695 | /* | ||
696 | * Mark extent in the range start - end as written. | ||
697 | * | ||
698 | * This changes extent type from 'pre-allocated' to 'regular'. If only | ||
699 | * part of extent is marked as written, the extent will be split into | ||
700 | * two or three. | ||
701 | */ | ||
702 | int btrfs_mark_extent_written(struct btrfs_trans_handle *trans, | ||
703 | struct btrfs_root *root, | ||
704 | struct inode *inode, u64 start, u64 end) | ||
705 | { | ||
706 | struct extent_buffer *leaf; | ||
707 | struct btrfs_path *path; | ||
708 | struct btrfs_file_extent_item *fi; | ||
709 | struct btrfs_key key; | ||
710 | u64 bytenr; | ||
711 | u64 num_bytes; | ||
712 | u64 extent_end; | ||
713 | u64 extent_offset; | ||
714 | u64 other_start; | ||
715 | u64 other_end; | ||
716 | u64 split = start; | ||
717 | u64 locked_end = end; | ||
718 | int extent_type; | ||
719 | int split_end = 1; | ||
720 | int ret; | ||
721 | |||
722 | btrfs_drop_extent_cache(inode, start, end - 1, 0); | ||
723 | |||
724 | path = btrfs_alloc_path(); | ||
725 | BUG_ON(!path); | ||
726 | again: | ||
727 | key.objectid = inode->i_ino; | ||
728 | key.type = BTRFS_EXTENT_DATA_KEY; | ||
729 | if (split == start) | ||
730 | key.offset = split; | ||
731 | else | ||
732 | key.offset = split - 1; | ||
733 | |||
734 | ret = btrfs_search_slot(trans, root, &key, path, -1, 1); | ||
735 | if (ret > 0 && path->slots[0] > 0) | ||
736 | path->slots[0]--; | ||
737 | |||
738 | leaf = path->nodes[0]; | ||
739 | btrfs_item_key_to_cpu(leaf, &key, path->slots[0]); | ||
740 | BUG_ON(key.objectid != inode->i_ino || | ||
741 | key.type != BTRFS_EXTENT_DATA_KEY); | ||
742 | fi = btrfs_item_ptr(leaf, path->slots[0], | ||
743 | struct btrfs_file_extent_item); | ||
744 | extent_type = btrfs_file_extent_type(leaf, fi); | ||
745 | BUG_ON(extent_type != BTRFS_FILE_EXTENT_PREALLOC); | ||
746 | extent_end = key.offset + btrfs_file_extent_num_bytes(leaf, fi); | ||
747 | BUG_ON(key.offset > start || extent_end < end); | ||
748 | |||
749 | bytenr = btrfs_file_extent_disk_bytenr(leaf, fi); | ||
750 | num_bytes = btrfs_file_extent_disk_num_bytes(leaf, fi); | ||
751 | extent_offset = btrfs_file_extent_offset(leaf, fi); | ||
752 | |||
753 | if (key.offset == start) | ||
754 | split = end; | ||
755 | |||
756 | if (key.offset == start && extent_end == end) { | ||
757 | int del_nr = 0; | ||
758 | int del_slot = 0; | ||
759 | u64 leaf_owner = btrfs_header_owner(leaf); | ||
760 | u64 leaf_gen = btrfs_header_generation(leaf); | ||
761 | other_start = end; | ||
762 | other_end = 0; | ||
763 | if (extent_mergeable(leaf, path->slots[0] + 1, inode->i_ino, | ||
764 | bytenr, &other_start, &other_end)) { | ||
765 | extent_end = other_end; | ||
766 | del_slot = path->slots[0] + 1; | ||
767 | del_nr++; | ||
768 | ret = btrfs_free_extent(trans, root, bytenr, num_bytes, | ||
769 | leaf->start, leaf_owner, | ||
770 | leaf_gen, inode->i_ino, 0); | ||
771 | BUG_ON(ret); | ||
772 | } | ||
773 | other_start = 0; | ||
774 | other_end = start; | ||
775 | if (extent_mergeable(leaf, path->slots[0] - 1, inode->i_ino, | ||
776 | bytenr, &other_start, &other_end)) { | ||
777 | key.offset = other_start; | ||
778 | del_slot = path->slots[0]; | ||
779 | del_nr++; | ||
780 | ret = btrfs_free_extent(trans, root, bytenr, num_bytes, | ||
781 | leaf->start, leaf_owner, | ||
782 | leaf_gen, inode->i_ino, 0); | ||
783 | BUG_ON(ret); | ||
784 | } | ||
785 | split_end = 0; | ||
786 | if (del_nr == 0) { | ||
787 | btrfs_set_file_extent_type(leaf, fi, | ||
788 | BTRFS_FILE_EXTENT_REG); | ||
789 | goto done; | ||
790 | } | ||
791 | |||
792 | fi = btrfs_item_ptr(leaf, del_slot - 1, | ||
793 | struct btrfs_file_extent_item); | ||
794 | btrfs_set_file_extent_type(leaf, fi, BTRFS_FILE_EXTENT_REG); | ||
795 | btrfs_set_file_extent_num_bytes(leaf, fi, | ||
796 | extent_end - key.offset); | ||
797 | btrfs_mark_buffer_dirty(leaf); | ||
798 | |||
799 | ret = btrfs_del_items(trans, root, path, del_slot, del_nr); | ||
800 | BUG_ON(ret); | ||
801 | goto done; | ||
802 | } else if (split == start) { | ||
803 | if (locked_end < extent_end) { | ||
804 | ret = try_lock_extent(&BTRFS_I(inode)->io_tree, | ||
805 | locked_end, extent_end - 1, GFP_NOFS); | ||
806 | if (!ret) { | ||
807 | btrfs_release_path(root, path); | ||
808 | lock_extent(&BTRFS_I(inode)->io_tree, | ||
809 | locked_end, extent_end - 1, GFP_NOFS); | ||
810 | locked_end = extent_end; | ||
811 | goto again; | ||
812 | } | ||
813 | locked_end = extent_end; | ||
814 | } | ||
815 | btrfs_set_file_extent_num_bytes(leaf, fi, split - key.offset); | ||
816 | extent_offset += split - key.offset; | ||
817 | } else { | ||
818 | BUG_ON(key.offset != start); | ||
819 | btrfs_set_file_extent_offset(leaf, fi, extent_offset + | ||
820 | split - key.offset); | ||
821 | btrfs_set_file_extent_num_bytes(leaf, fi, extent_end - split); | ||
822 | key.offset = split; | ||
823 | btrfs_set_item_key_safe(trans, root, path, &key); | ||
824 | extent_end = split; | ||
825 | } | ||
826 | |||
827 | if (extent_end == end) { | ||
828 | split_end = 0; | ||
829 | extent_type = BTRFS_FILE_EXTENT_REG; | ||
830 | } | ||
831 | if (extent_end == end && split == start) { | ||
832 | other_start = end; | ||
833 | other_end = 0; | ||
834 | if (extent_mergeable(leaf, path->slots[0] + 1, inode->i_ino, | ||
835 | bytenr, &other_start, &other_end)) { | ||
836 | path->slots[0]++; | ||
837 | fi = btrfs_item_ptr(leaf, path->slots[0], | ||
838 | struct btrfs_file_extent_item); | ||
839 | key.offset = split; | ||
840 | btrfs_set_item_key_safe(trans, root, path, &key); | ||
841 | btrfs_set_file_extent_offset(leaf, fi, extent_offset); | ||
842 | btrfs_set_file_extent_num_bytes(leaf, fi, | ||
843 | other_end - split); | ||
844 | goto done; | ||
845 | } | ||
846 | } | ||
847 | if (extent_end == end && split == end) { | ||
848 | other_start = 0; | ||
849 | other_end = start; | ||
850 | if (extent_mergeable(leaf, path->slots[0] - 1 , inode->i_ino, | ||
851 | bytenr, &other_start, &other_end)) { | ||
852 | path->slots[0]--; | ||
853 | fi = btrfs_item_ptr(leaf, path->slots[0], | ||
854 | struct btrfs_file_extent_item); | ||
855 | btrfs_set_file_extent_num_bytes(leaf, fi, extent_end - | ||
856 | other_start); | ||
857 | goto done; | ||
858 | } | ||
859 | } | ||
860 | |||
861 | btrfs_mark_buffer_dirty(leaf); | ||
862 | btrfs_release_path(root, path); | ||
863 | |||
864 | key.offset = start; | ||
865 | ret = btrfs_insert_empty_item(trans, root, path, &key, sizeof(*fi)); | ||
866 | BUG_ON(ret); | ||
867 | |||
868 | leaf = path->nodes[0]; | ||
869 | fi = btrfs_item_ptr(leaf, path->slots[0], | ||
870 | struct btrfs_file_extent_item); | ||
871 | btrfs_set_file_extent_generation(leaf, fi, trans->transid); | ||
872 | btrfs_set_file_extent_type(leaf, fi, extent_type); | ||
873 | btrfs_set_file_extent_disk_bytenr(leaf, fi, bytenr); | ||
874 | btrfs_set_file_extent_disk_num_bytes(leaf, fi, num_bytes); | ||
875 | btrfs_set_file_extent_offset(leaf, fi, extent_offset); | ||
876 | btrfs_set_file_extent_num_bytes(leaf, fi, extent_end - key.offset); | ||
877 | btrfs_set_file_extent_ram_bytes(leaf, fi, num_bytes); | ||
878 | btrfs_set_file_extent_compression(leaf, fi, 0); | ||
879 | btrfs_set_file_extent_encryption(leaf, fi, 0); | ||
880 | btrfs_set_file_extent_other_encoding(leaf, fi, 0); | ||
881 | |||
882 | ret = btrfs_inc_extent_ref(trans, root, bytenr, num_bytes, | ||
883 | leaf->start, root->root_key.objectid, | ||
884 | trans->transid, inode->i_ino); | ||
885 | BUG_ON(ret); | ||
886 | done: | ||
887 | btrfs_mark_buffer_dirty(leaf); | ||
888 | btrfs_release_path(root, path); | ||
889 | if (split_end && split == start) { | ||
890 | split = end; | ||
891 | goto again; | ||
892 | } | ||
893 | if (locked_end > end) { | ||
894 | unlock_extent(&BTRFS_I(inode)->io_tree, end, locked_end - 1, | ||
895 | GFP_NOFS); | ||
896 | } | ||
897 | btrfs_free_path(path); | ||
898 | return 0; | ||
899 | } | ||
900 | |||
664 | /* | 901 | /* |
665 | * this gets pages into the page cache and locks them down, it also properly | 902 | * this gets pages into the page cache and locks them down, it also properly |
666 | * waits for data=ordered extents to finish before allowing the pages to be | 903 | * waits for data=ordered extents to finish before allowing the pages to be |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 3e6f0568fdb4..789c376157f9 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <linux/version.h> | 37 | #include <linux/version.h> |
38 | #include <linux/xattr.h> | 38 | #include <linux/xattr.h> |
39 | #include <linux/posix_acl.h> | 39 | #include <linux/posix_acl.h> |
40 | #include <linux/falloc.h> | ||
40 | #include "ctree.h" | 41 | #include "ctree.h" |
41 | #include "disk-io.h" | 42 | #include "disk-io.h" |
42 | #include "transaction.h" | 43 | #include "transaction.h" |
@@ -587,7 +588,7 @@ free_pages_out: | |||
587 | * blocks on disk | 588 | * blocks on disk |
588 | */ | 589 | */ |
589 | static int run_delalloc_nocow(struct inode *inode, struct page *locked_page, | 590 | static int run_delalloc_nocow(struct inode *inode, struct page *locked_page, |
590 | u64 start, u64 end, int *page_started) | 591 | u64 start, u64 end, int *page_started, int force) |
591 | { | 592 | { |
592 | struct btrfs_root *root = BTRFS_I(inode)->root; | 593 | struct btrfs_root *root = BTRFS_I(inode)->root; |
593 | struct btrfs_trans_handle *trans; | 594 | struct btrfs_trans_handle *trans; |
@@ -602,6 +603,7 @@ static int run_delalloc_nocow(struct inode *inode, struct page *locked_page, | |||
602 | u64 num_bytes; | 603 | u64 num_bytes; |
603 | int extent_type; | 604 | int extent_type; |
604 | int ret; | 605 | int ret; |
606 | int type; | ||
605 | int nocow; | 607 | int nocow; |
606 | int check_prev = 1; | 608 | int check_prev = 1; |
607 | 609 | ||
@@ -654,7 +656,8 @@ next_slot: | |||
654 | struct btrfs_file_extent_item); | 656 | struct btrfs_file_extent_item); |
655 | extent_type = btrfs_file_extent_type(leaf, fi); | 657 | extent_type = btrfs_file_extent_type(leaf, fi); |
656 | 658 | ||
657 | if (extent_type == BTRFS_FILE_EXTENT_REG) { | 659 | if (extent_type == BTRFS_FILE_EXTENT_REG || |
660 | extent_type == BTRFS_FILE_EXTENT_PREALLOC) { | ||
658 | struct btrfs_block_group_cache *block_group; | 661 | struct btrfs_block_group_cache *block_group; |
659 | disk_bytenr = btrfs_file_extent_disk_bytenr(leaf, fi); | 662 | disk_bytenr = btrfs_file_extent_disk_bytenr(leaf, fi); |
660 | extent_end = found_key.offset + | 663 | extent_end = found_key.offset + |
@@ -669,6 +672,8 @@ next_slot: | |||
669 | goto out_check; | 672 | goto out_check; |
670 | if (disk_bytenr == 0) | 673 | if (disk_bytenr == 0) |
671 | goto out_check; | 674 | goto out_check; |
675 | if (extent_type == BTRFS_FILE_EXTENT_REG && !force) | ||
676 | goto out_check; | ||
672 | if (btrfs_cross_ref_exist(trans, root, disk_bytenr)) | 677 | if (btrfs_cross_ref_exist(trans, root, disk_bytenr)) |
673 | goto out_check; | 678 | goto out_check; |
674 | block_group = btrfs_lookup_block_group(root->fs_info, | 679 | block_group = btrfs_lookup_block_group(root->fs_info, |
@@ -709,10 +714,39 @@ out_check: | |||
709 | 714 | ||
710 | disk_bytenr += cur_offset - found_key.offset; | 715 | disk_bytenr += cur_offset - found_key.offset; |
711 | num_bytes = min(end + 1, extent_end) - cur_offset; | 716 | num_bytes = min(end + 1, extent_end) - cur_offset; |
717 | if (extent_type == BTRFS_FILE_EXTENT_PREALLOC) { | ||
718 | struct extent_map *em; | ||
719 | struct extent_map_tree *em_tree; | ||
720 | em_tree = &BTRFS_I(inode)->extent_tree; | ||
721 | em = alloc_extent_map(GFP_NOFS); | ||
722 | em->start = cur_offset; | ||
723 | em->len = num_bytes; | ||
724 | em->block_len = num_bytes; | ||
725 | em->block_start = disk_bytenr; | ||
726 | em->bdev = root->fs_info->fs_devices->latest_bdev; | ||
727 | set_bit(EXTENT_FLAG_PINNED, &em->flags); | ||
728 | while (1) { | ||
729 | spin_lock(&em_tree->lock); | ||
730 | ret = add_extent_mapping(em_tree, em); | ||
731 | spin_unlock(&em_tree->lock); | ||
732 | if (ret != -EEXIST) { | ||
733 | free_extent_map(em); | ||
734 | break; | ||
735 | } | ||
736 | btrfs_drop_extent_cache(inode, em->start, | ||
737 | em->start + em->len - 1, 0); | ||
738 | } | ||
739 | type = BTRFS_ORDERED_PREALLOC; | ||
740 | } else { | ||
741 | type = BTRFS_ORDERED_NOCOW; | ||
742 | } | ||
712 | 743 | ||
713 | ret = btrfs_add_ordered_extent(inode, cur_offset, disk_bytenr, | 744 | ret = btrfs_add_ordered_extent(inode, cur_offset, disk_bytenr, |
714 | num_bytes, num_bytes, | 745 | num_bytes, num_bytes, type); |
715 | BTRFS_ORDERED_NOCOW); | 746 | BUG_ON(ret); |
747 | extent_clear_unlock_delalloc(inode, &BTRFS_I(inode)->io_tree, | ||
748 | cur_offset, cur_offset + num_bytes - 1, | ||
749 | locked_page, 0, 0, 0); | ||
716 | cur_offset = extent_end; | 750 | cur_offset = extent_end; |
717 | if (cur_offset > end) | 751 | if (cur_offset > end) |
718 | break; | 752 | break; |
@@ -745,7 +779,10 @@ static int run_delalloc_range(struct inode *inode, struct page *locked_page, | |||
745 | if (btrfs_test_opt(root, NODATACOW) || | 779 | if (btrfs_test_opt(root, NODATACOW) || |
746 | btrfs_test_flag(inode, NODATACOW)) | 780 | btrfs_test_flag(inode, NODATACOW)) |
747 | ret = run_delalloc_nocow(inode, locked_page, start, end, | 781 | ret = run_delalloc_nocow(inode, locked_page, start, end, |
748 | page_started); | 782 | page_started, 0); |
783 | else if (btrfs_test_flag(inode, PREALLOC)) | ||
784 | ret = run_delalloc_nocow(inode, locked_page, start, end, | ||
785 | page_started, 1); | ||
749 | else | 786 | else |
750 | ret = cow_file_range(inode, locked_page, start, end, | 787 | ret = cow_file_range(inode, locked_page, start, end, |
751 | page_started); | 788 | page_started); |
@@ -1006,6 +1043,63 @@ int btrfs_writepage_start_hook(struct page *page, u64 start, u64 end) | |||
1006 | return -EAGAIN; | 1043 | return -EAGAIN; |
1007 | } | 1044 | } |
1008 | 1045 | ||
1046 | static int insert_reserved_file_extent(struct btrfs_trans_handle *trans, | ||
1047 | struct inode *inode, u64 file_pos, | ||
1048 | u64 disk_bytenr, u64 disk_num_bytes, | ||
1049 | u64 num_bytes, u64 ram_bytes, | ||
1050 | u8 compression, u8 encryption, | ||
1051 | u16 other_encoding, int extent_type) | ||
1052 | { | ||
1053 | struct btrfs_root *root = BTRFS_I(inode)->root; | ||
1054 | struct btrfs_file_extent_item *fi; | ||
1055 | struct btrfs_path *path; | ||
1056 | struct extent_buffer *leaf; | ||
1057 | struct btrfs_key ins; | ||
1058 | u64 hint; | ||
1059 | int ret; | ||
1060 | |||
1061 | path = btrfs_alloc_path(); | ||
1062 | BUG_ON(!path); | ||
1063 | |||
1064 | ret = btrfs_drop_extents(trans, root, inode, file_pos, | ||
1065 | file_pos + num_bytes, file_pos, &hint); | ||
1066 | BUG_ON(ret); | ||
1067 | |||
1068 | ins.objectid = inode->i_ino; | ||
1069 | ins.offset = file_pos; | ||
1070 | ins.type = BTRFS_EXTENT_DATA_KEY; | ||
1071 | ret = btrfs_insert_empty_item(trans, root, path, &ins, sizeof(*fi)); | ||
1072 | BUG_ON(ret); | ||
1073 | leaf = path->nodes[0]; | ||
1074 | fi = btrfs_item_ptr(leaf, path->slots[0], | ||
1075 | struct btrfs_file_extent_item); | ||
1076 | btrfs_set_file_extent_generation(leaf, fi, trans->transid); | ||
1077 | btrfs_set_file_extent_type(leaf, fi, extent_type); | ||
1078 | btrfs_set_file_extent_disk_bytenr(leaf, fi, disk_bytenr); | ||
1079 | btrfs_set_file_extent_disk_num_bytes(leaf, fi, disk_num_bytes); | ||
1080 | btrfs_set_file_extent_offset(leaf, fi, 0); | ||
1081 | btrfs_set_file_extent_num_bytes(leaf, fi, num_bytes); | ||
1082 | btrfs_set_file_extent_ram_bytes(leaf, fi, ram_bytes); | ||
1083 | btrfs_set_file_extent_compression(leaf, fi, compression); | ||
1084 | btrfs_set_file_extent_encryption(leaf, fi, encryption); | ||
1085 | btrfs_set_file_extent_other_encoding(leaf, fi, other_encoding); | ||
1086 | btrfs_mark_buffer_dirty(leaf); | ||
1087 | |||
1088 | inode_add_bytes(inode, num_bytes); | ||
1089 | btrfs_drop_extent_cache(inode, file_pos, file_pos + num_bytes - 1, 0); | ||
1090 | |||
1091 | ins.objectid = disk_bytenr; | ||
1092 | ins.offset = disk_num_bytes; | ||
1093 | ins.type = BTRFS_EXTENT_ITEM_KEY; | ||
1094 | ret = btrfs_alloc_reserved_extent(trans, root, leaf->start, | ||
1095 | root->root_key.objectid, | ||
1096 | trans->transid, inode->i_ino, &ins); | ||
1097 | BUG_ON(ret); | ||
1098 | |||
1099 | btrfs_free_path(path); | ||
1100 | return 0; | ||
1101 | } | ||
1102 | |||
1009 | /* as ordered data IO finishes, this gets called so we can finish | 1103 | /* as ordered data IO finishes, this gets called so we can finish |
1010 | * an ordered extent if the range of bytes in the file it covers are | 1104 | * an ordered extent if the range of bytes in the file it covers are |
1011 | * fully written. | 1105 | * fully written. |
@@ -1016,12 +1110,7 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end) | |||
1016 | struct btrfs_trans_handle *trans; | 1110 | struct btrfs_trans_handle *trans; |
1017 | struct btrfs_ordered_extent *ordered_extent; | 1111 | struct btrfs_ordered_extent *ordered_extent; |
1018 | struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree; | 1112 | struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree; |
1019 | struct btrfs_file_extent_item *extent_item; | 1113 | int compressed = 0; |
1020 | struct btrfs_path *path = NULL; | ||
1021 | struct extent_buffer *leaf; | ||
1022 | u64 alloc_hint = 0; | ||
1023 | struct list_head list; | ||
1024 | struct btrfs_key ins; | ||
1025 | int ret; | 1114 | int ret; |
1026 | 1115 | ||
1027 | ret = btrfs_dec_test_ordered_pending(inode, start, end - start + 1); | 1116 | ret = btrfs_dec_test_ordered_pending(inode, start, end - start + 1); |
@@ -1035,67 +1124,30 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end) | |||
1035 | if (test_bit(BTRFS_ORDERED_NOCOW, &ordered_extent->flags)) | 1124 | if (test_bit(BTRFS_ORDERED_NOCOW, &ordered_extent->flags)) |
1036 | goto nocow; | 1125 | goto nocow; |
1037 | 1126 | ||
1038 | path = btrfs_alloc_path(); | ||
1039 | BUG_ON(!path); | ||
1040 | |||
1041 | lock_extent(io_tree, ordered_extent->file_offset, | 1127 | lock_extent(io_tree, ordered_extent->file_offset, |
1042 | ordered_extent->file_offset + ordered_extent->len - 1, | 1128 | ordered_extent->file_offset + ordered_extent->len - 1, |
1043 | GFP_NOFS); | 1129 | GFP_NOFS); |
1044 | 1130 | ||
1045 | INIT_LIST_HEAD(&list); | ||
1046 | |||
1047 | ret = btrfs_drop_extents(trans, root, inode, | ||
1048 | ordered_extent->file_offset, | ||
1049 | ordered_extent->file_offset + | ||
1050 | ordered_extent->len, | ||
1051 | ordered_extent->file_offset, &alloc_hint); | ||
1052 | BUG_ON(ret); | ||
1053 | |||
1054 | ins.objectid = inode->i_ino; | ||
1055 | ins.offset = ordered_extent->file_offset; | ||
1056 | ins.type = BTRFS_EXTENT_DATA_KEY; | ||
1057 | ret = btrfs_insert_empty_item(trans, root, path, &ins, | ||
1058 | sizeof(*extent_item)); | ||
1059 | BUG_ON(ret); | ||
1060 | leaf = path->nodes[0]; | ||
1061 | extent_item = btrfs_item_ptr(leaf, path->slots[0], | ||
1062 | struct btrfs_file_extent_item); | ||
1063 | btrfs_set_file_extent_generation(leaf, extent_item, trans->transid); | ||
1064 | btrfs_set_file_extent_type(leaf, extent_item, BTRFS_FILE_EXTENT_REG); | ||
1065 | btrfs_set_file_extent_disk_bytenr(leaf, extent_item, | ||
1066 | ordered_extent->start); | ||
1067 | btrfs_set_file_extent_disk_num_bytes(leaf, extent_item, | ||
1068 | ordered_extent->disk_len); | ||
1069 | btrfs_set_file_extent_offset(leaf, extent_item, 0); | ||
1070 | |||
1071 | if (test_bit(BTRFS_ORDERED_COMPRESSED, &ordered_extent->flags)) | 1131 | if (test_bit(BTRFS_ORDERED_COMPRESSED, &ordered_extent->flags)) |
1072 | btrfs_set_file_extent_compression(leaf, extent_item, 1); | 1132 | compressed = 1; |
1073 | else | 1133 | if (test_bit(BTRFS_ORDERED_PREALLOC, &ordered_extent->flags)) { |
1074 | btrfs_set_file_extent_compression(leaf, extent_item, 0); | 1134 | BUG_ON(compressed); |
1075 | btrfs_set_file_extent_encryption(leaf, extent_item, 0); | 1135 | ret = btrfs_mark_extent_written(trans, root, inode, |
1076 | btrfs_set_file_extent_other_encoding(leaf, extent_item, 0); | 1136 | ordered_extent->file_offset, |
1077 | 1137 | ordered_extent->file_offset + | |
1078 | /* ram bytes = extent_num_bytes for now */ | 1138 | ordered_extent->len); |
1079 | btrfs_set_file_extent_num_bytes(leaf, extent_item, | 1139 | BUG_ON(ret); |
1080 | ordered_extent->len); | 1140 | } else { |
1081 | btrfs_set_file_extent_ram_bytes(leaf, extent_item, | 1141 | ret = insert_reserved_file_extent(trans, inode, |
1082 | ordered_extent->len); | 1142 | ordered_extent->file_offset, |
1083 | btrfs_mark_buffer_dirty(leaf); | 1143 | ordered_extent->start, |
1084 | 1144 | ordered_extent->disk_len, | |
1085 | btrfs_drop_extent_cache(inode, ordered_extent->file_offset, | 1145 | ordered_extent->len, |
1086 | ordered_extent->file_offset + | 1146 | ordered_extent->len, |
1087 | ordered_extent->len - 1, 0); | 1147 | compressed, 0, 0, |
1088 | 1148 | BTRFS_FILE_EXTENT_REG); | |
1089 | ins.objectid = ordered_extent->start; | 1149 | BUG_ON(ret); |
1090 | ins.offset = ordered_extent->disk_len; | 1150 | } |
1091 | ins.type = BTRFS_EXTENT_ITEM_KEY; | ||
1092 | ret = btrfs_alloc_reserved_extent(trans, root, leaf->start, | ||
1093 | root->root_key.objectid, | ||
1094 | trans->transid, inode->i_ino, &ins); | ||
1095 | BUG_ON(ret); | ||
1096 | btrfs_release_path(root, path); | ||
1097 | |||
1098 | inode_add_bytes(inode, ordered_extent->len); | ||
1099 | unlock_extent(io_tree, ordered_extent->file_offset, | 1151 | unlock_extent(io_tree, ordered_extent->file_offset, |
1100 | ordered_extent->file_offset + ordered_extent->len - 1, | 1152 | ordered_extent->file_offset + ordered_extent->len - 1, |
1101 | GFP_NOFS); | 1153 | GFP_NOFS); |
@@ -1115,8 +1167,6 @@ nocow: | |||
1115 | btrfs_put_ordered_extent(ordered_extent); | 1167 | btrfs_put_ordered_extent(ordered_extent); |
1116 | 1168 | ||
1117 | btrfs_end_transaction(trans, root); | 1169 | btrfs_end_transaction(trans, root); |
1118 | if (path) | ||
1119 | btrfs_free_path(path); | ||
1120 | return 0; | 1170 | return 0; |
1121 | } | 1171 | } |
1122 | 1172 | ||
@@ -3488,7 +3538,8 @@ again: | |||
3488 | found_type = btrfs_file_extent_type(leaf, item); | 3538 | found_type = btrfs_file_extent_type(leaf, item); |
3489 | extent_start = found_key.offset; | 3539 | extent_start = found_key.offset; |
3490 | compressed = btrfs_file_extent_compression(leaf, item); | 3540 | compressed = btrfs_file_extent_compression(leaf, item); |
3491 | if (found_type == BTRFS_FILE_EXTENT_REG) { | 3541 | if (found_type == BTRFS_FILE_EXTENT_REG || |
3542 | found_type == BTRFS_FILE_EXTENT_PREALLOC) { | ||
3492 | extent_end = extent_start + | 3543 | extent_end = extent_start + |
3493 | btrfs_file_extent_num_bytes(leaf, item); | 3544 | btrfs_file_extent_num_bytes(leaf, item); |
3494 | } else if (found_type == BTRFS_FILE_EXTENT_INLINE) { | 3545 | } else if (found_type == BTRFS_FILE_EXTENT_INLINE) { |
@@ -3521,7 +3572,8 @@ again: | |||
3521 | goto not_found_em; | 3572 | goto not_found_em; |
3522 | } | 3573 | } |
3523 | 3574 | ||
3524 | if (found_type == BTRFS_FILE_EXTENT_REG) { | 3575 | if (found_type == BTRFS_FILE_EXTENT_REG || |
3576 | found_type == BTRFS_FILE_EXTENT_PREALLOC) { | ||
3525 | em->start = extent_start; | 3577 | em->start = extent_start; |
3526 | em->len = extent_end - extent_start; | 3578 | em->len = extent_end - extent_start; |
3527 | bytenr = btrfs_file_extent_disk_bytenr(leaf, item); | 3579 | bytenr = btrfs_file_extent_disk_bytenr(leaf, item); |
@@ -3538,6 +3590,8 @@ again: | |||
3538 | bytenr += btrfs_file_extent_offset(leaf, item); | 3590 | bytenr += btrfs_file_extent_offset(leaf, item); |
3539 | em->block_start = bytenr; | 3591 | em->block_start = bytenr; |
3540 | em->block_len = em->len; | 3592 | em->block_len = em->len; |
3593 | if (found_type == BTRFS_FILE_EXTENT_PREALLOC) | ||
3594 | set_bit(EXTENT_FLAG_PREALLOC, &em->flags); | ||
3541 | } | 3595 | } |
3542 | goto insert; | 3596 | goto insert; |
3543 | } else if (found_type == BTRFS_FILE_EXTENT_INLINE) { | 3597 | } else if (found_type == BTRFS_FILE_EXTENT_INLINE) { |
@@ -3969,6 +4023,7 @@ int btrfs_create_subvol_root(struct btrfs_root *new_root, struct dentry *dentry, | |||
3969 | if (error) | 4023 | if (error) |
3970 | return error; | 4024 | return error; |
3971 | 4025 | ||
4026 | atomic_inc(&inode->i_count); | ||
3972 | d_instantiate(dentry, inode); | 4027 | d_instantiate(dentry, inode); |
3973 | return 0; | 4028 | return 0; |
3974 | } | 4029 | } |
@@ -4318,6 +4373,7 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry, | |||
4318 | inode->i_op = &btrfs_symlink_inode_operations; | 4373 | inode->i_op = &btrfs_symlink_inode_operations; |
4319 | inode->i_mapping->a_ops = &btrfs_symlink_aops; | 4374 | inode->i_mapping->a_ops = &btrfs_symlink_aops; |
4320 | inode->i_mapping->backing_dev_info = &root->fs_info->bdi; | 4375 | inode->i_mapping->backing_dev_info = &root->fs_info->bdi; |
4376 | inode_set_bytes(inode, name_len); | ||
4321 | btrfs_i_size_write(inode, name_len - 1); | 4377 | btrfs_i_size_write(inode, name_len - 1); |
4322 | err = btrfs_update_inode(trans, root, inode); | 4378 | err = btrfs_update_inode(trans, root, inode); |
4323 | if (err) | 4379 | if (err) |
@@ -4335,6 +4391,130 @@ out_fail: | |||
4335 | return err; | 4391 | return err; |
4336 | } | 4392 | } |
4337 | 4393 | ||
4394 | static int prealloc_file_range(struct inode *inode, u64 start, u64 end, | ||
4395 | u64 alloc_hint, int mode) | ||
4396 | { | ||
4397 | struct btrfs_trans_handle *trans; | ||
4398 | struct btrfs_root *root = BTRFS_I(inode)->root; | ||
4399 | struct btrfs_key ins; | ||
4400 | u64 alloc_size; | ||
4401 | u64 cur_offset = start; | ||
4402 | u64 num_bytes = end - start; | ||
4403 | int ret = 0; | ||
4404 | |||
4405 | trans = btrfs_join_transaction(root, 1); | ||
4406 | BUG_ON(!trans); | ||
4407 | btrfs_set_trans_block_group(trans, inode); | ||
4408 | |||
4409 | while (num_bytes > 0) { | ||
4410 | alloc_size = min(num_bytes, root->fs_info->max_extent); | ||
4411 | ret = btrfs_reserve_extent(trans, root, alloc_size, | ||
4412 | root->sectorsize, 0, alloc_hint, | ||
4413 | (u64)-1, &ins, 1); | ||
4414 | if (ret) { | ||
4415 | WARN_ON(1); | ||
4416 | goto out; | ||
4417 | } | ||
4418 | ret = insert_reserved_file_extent(trans, inode, | ||
4419 | cur_offset, ins.objectid, | ||
4420 | ins.offset, ins.offset, | ||
4421 | ins.offset, 0, 0, 0, | ||
4422 | BTRFS_FILE_EXTENT_PREALLOC); | ||
4423 | BUG_ON(ret); | ||
4424 | num_bytes -= ins.offset; | ||
4425 | cur_offset += ins.offset; | ||
4426 | alloc_hint = ins.objectid + ins.offset; | ||
4427 | } | ||
4428 | out: | ||
4429 | if (cur_offset > start) { | ||
4430 | inode->i_ctime = CURRENT_TIME; | ||
4431 | btrfs_set_flag(inode, PREALLOC); | ||
4432 | if (!(mode & FALLOC_FL_KEEP_SIZE) && | ||
4433 | cur_offset > i_size_read(inode)) | ||
4434 | btrfs_i_size_write(inode, cur_offset); | ||
4435 | ret = btrfs_update_inode(trans, root, inode); | ||
4436 | BUG_ON(ret); | ||
4437 | } | ||
4438 | |||
4439 | btrfs_end_transaction(trans, root); | ||
4440 | return ret; | ||
4441 | } | ||
4442 | |||
4443 | static long btrfs_fallocate(struct inode *inode, int mode, | ||
4444 | loff_t offset, loff_t len) | ||
4445 | { | ||
4446 | u64 cur_offset; | ||
4447 | u64 last_byte; | ||
4448 | u64 alloc_start; | ||
4449 | u64 alloc_end; | ||
4450 | u64 alloc_hint = 0; | ||
4451 | u64 mask = BTRFS_I(inode)->root->sectorsize - 1; | ||
4452 | struct extent_map *em; | ||
4453 | int ret; | ||
4454 | |||
4455 | alloc_start = offset & ~mask; | ||
4456 | alloc_end = (offset + len + mask) & ~mask; | ||
4457 | |||
4458 | mutex_lock(&inode->i_mutex); | ||
4459 | if (alloc_start > inode->i_size) { | ||
4460 | ret = btrfs_cont_expand(inode, alloc_start); | ||
4461 | if (ret) | ||
4462 | goto out; | ||
4463 | } | ||
4464 | |||
4465 | while (1) { | ||
4466 | struct btrfs_ordered_extent *ordered; | ||
4467 | lock_extent(&BTRFS_I(inode)->io_tree, alloc_start, | ||
4468 | alloc_end - 1, GFP_NOFS); | ||
4469 | ordered = btrfs_lookup_first_ordered_extent(inode, | ||
4470 | alloc_end - 1); | ||
4471 | if (ordered && | ||
4472 | ordered->file_offset + ordered->len > alloc_start && | ||
4473 | ordered->file_offset < alloc_end) { | ||
4474 | btrfs_put_ordered_extent(ordered); | ||
4475 | unlock_extent(&BTRFS_I(inode)->io_tree, | ||
4476 | alloc_start, alloc_end - 1, GFP_NOFS); | ||
4477 | btrfs_wait_ordered_range(inode, alloc_start, | ||
4478 | alloc_end - alloc_start); | ||
4479 | } else { | ||
4480 | if (ordered) | ||
4481 | btrfs_put_ordered_extent(ordered); | ||
4482 | break; | ||
4483 | } | ||
4484 | } | ||
4485 | |||
4486 | cur_offset = alloc_start; | ||
4487 | while (1) { | ||
4488 | em = btrfs_get_extent(inode, NULL, 0, cur_offset, | ||
4489 | alloc_end - cur_offset, 0); | ||
4490 | BUG_ON(IS_ERR(em) || !em); | ||
4491 | last_byte = min(extent_map_end(em), alloc_end); | ||
4492 | last_byte = (last_byte + mask) & ~mask; | ||
4493 | if (em->block_start == EXTENT_MAP_HOLE) { | ||
4494 | ret = prealloc_file_range(inode, cur_offset, | ||
4495 | last_byte, alloc_hint, mode); | ||
4496 | if (ret < 0) { | ||
4497 | free_extent_map(em); | ||
4498 | break; | ||
4499 | } | ||
4500 | } | ||
4501 | if (em->block_start <= EXTENT_MAP_LAST_BYTE) | ||
4502 | alloc_hint = em->block_start; | ||
4503 | free_extent_map(em); | ||
4504 | |||
4505 | cur_offset = last_byte; | ||
4506 | if (cur_offset >= alloc_end) { | ||
4507 | ret = 0; | ||
4508 | break; | ||
4509 | } | ||
4510 | } | ||
4511 | unlock_extent(&BTRFS_I(inode)->io_tree, alloc_start, alloc_end - 1, | ||
4512 | GFP_NOFS); | ||
4513 | out: | ||
4514 | mutex_unlock(&inode->i_mutex); | ||
4515 | return ret; | ||
4516 | } | ||
4517 | |||
4338 | static int btrfs_set_page_dirty(struct page *page) | 4518 | static int btrfs_set_page_dirty(struct page *page) |
4339 | { | 4519 | { |
4340 | return __set_page_dirty_nobuffers(page); | 4520 | return __set_page_dirty_nobuffers(page); |
@@ -4421,6 +4601,7 @@ static struct inode_operations btrfs_file_inode_operations = { | |||
4421 | .listxattr = btrfs_listxattr, | 4601 | .listxattr = btrfs_listxattr, |
4422 | .removexattr = btrfs_removexattr, | 4602 | .removexattr = btrfs_removexattr, |
4423 | .permission = btrfs_permission, | 4603 | .permission = btrfs_permission, |
4604 | .fallocate = btrfs_fallocate, | ||
4424 | }; | 4605 | }; |
4425 | static struct inode_operations btrfs_special_inode_operations = { | 4606 | static struct inode_operations btrfs_special_inode_operations = { |
4426 | .getattr = btrfs_getattr, | 4607 | .getattr = btrfs_getattr, |
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 7f915d478399..9ff2b4e0e922 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -724,7 +724,8 @@ long btrfs_ioctl_clone(struct file *file, unsigned long src_fd) | |||
724 | extent = btrfs_item_ptr(leaf, slot, | 724 | extent = btrfs_item_ptr(leaf, slot, |
725 | struct btrfs_file_extent_item); | 725 | struct btrfs_file_extent_item); |
726 | found_type = btrfs_file_extent_type(leaf, extent); | 726 | found_type = btrfs_file_extent_type(leaf, extent); |
727 | if (found_type == BTRFS_FILE_EXTENT_REG) { | 727 | if (found_type == BTRFS_FILE_EXTENT_REG || |
728 | found_type == BTRFS_FILE_EXTENT_PREALLOC) { | ||
728 | u64 ds = btrfs_file_extent_disk_bytenr(leaf, | 729 | u64 ds = btrfs_file_extent_disk_bytenr(leaf, |
729 | extent); | 730 | extent); |
730 | u64 dl = btrfs_file_extent_disk_num_bytes(leaf, | 731 | u64 dl = btrfs_file_extent_disk_num_bytes(leaf, |
diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c index e7317c8fda29..370bb4285597 100644 --- a/fs/btrfs/ordered-data.c +++ b/fs/btrfs/ordered-data.c | |||
@@ -182,7 +182,7 @@ int btrfs_add_ordered_extent(struct inode *inode, u64 file_offset, | |||
182 | entry->len = len; | 182 | entry->len = len; |
183 | entry->disk_len = disk_len; | 183 | entry->disk_len = disk_len; |
184 | entry->inode = inode; | 184 | entry->inode = inode; |
185 | if (type == BTRFS_ORDERED_NOCOW || type == BTRFS_ORDERED_COMPRESSED) | 185 | if (type != BTRFS_ORDERED_IO_DONE && type != BTRFS_ORDERED_COMPLETE) |
186 | set_bit(type, &entry->flags); | 186 | set_bit(type, &entry->flags); |
187 | 187 | ||
188 | /* one ref for the tree */ | 188 | /* one ref for the tree */ |
@@ -339,7 +339,8 @@ int btrfs_wait_ordered_extents(struct btrfs_root *root, int nocow_only) | |||
339 | ordered = list_entry(cur, struct btrfs_ordered_extent, | 339 | ordered = list_entry(cur, struct btrfs_ordered_extent, |
340 | root_extent_list); | 340 | root_extent_list); |
341 | if (nocow_only && | 341 | if (nocow_only && |
342 | !test_bit(BTRFS_ORDERED_NOCOW, &ordered->flags)) { | 342 | !test_bit(BTRFS_ORDERED_NOCOW, &ordered->flags) && |
343 | !test_bit(BTRFS_ORDERED_PREALLOC, &ordered->flags)) { | ||
343 | list_move(&ordered->root_extent_list, | 344 | list_move(&ordered->root_extent_list, |
344 | &root->fs_info->ordered_extents); | 345 | &root->fs_info->ordered_extents); |
345 | cond_resched_lock(&root->fs_info->ordered_extent_lock); | 346 | cond_resched_lock(&root->fs_info->ordered_extent_lock); |
diff --git a/fs/btrfs/ordered-data.h b/fs/btrfs/ordered-data.h index e6d9bc54c2b1..260bf95dfe0c 100644 --- a/fs/btrfs/ordered-data.h +++ b/fs/btrfs/ordered-data.h | |||
@@ -68,6 +68,8 @@ struct btrfs_ordered_sum { | |||
68 | 68 | ||
69 | #define BTRFS_ORDERED_COMPRESSED 3 /* writing a compressed extent */ | 69 | #define BTRFS_ORDERED_COMPRESSED 3 /* writing a compressed extent */ |
70 | 70 | ||
71 | #define BTRFS_ORDERED_PREALLOC 4 /* set when writing to prealloced extent */ | ||
72 | |||
71 | struct btrfs_ordered_extent { | 73 | struct btrfs_ordered_extent { |
72 | /* logical offset in the file */ | 74 | /* logical offset in the file */ |
73 | u64 file_offset; | 75 | u64 file_offset; |
@@ -132,7 +134,7 @@ int btrfs_remove_ordered_extent(struct inode *inode, | |||
132 | int btrfs_dec_test_ordered_pending(struct inode *inode, | 134 | int btrfs_dec_test_ordered_pending(struct inode *inode, |
133 | u64 file_offset, u64 io_size); | 135 | u64 file_offset, u64 io_size); |
134 | int btrfs_add_ordered_extent(struct inode *inode, u64 file_offset, | 136 | int btrfs_add_ordered_extent(struct inode *inode, u64 file_offset, |
135 | u64 start, u64 len, u64 disk_len, int type); | 137 | u64 start, u64 len, u64 disk_len, int tyep); |
136 | int btrfs_add_ordered_sum(struct inode *inode, | 138 | int btrfs_add_ordered_sum(struct inode *inode, |
137 | struct btrfs_ordered_extent *entry, | 139 | struct btrfs_ordered_extent *entry, |
138 | struct btrfs_ordered_sum *sum); | 140 | struct btrfs_ordered_sum *sum); |
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index e0201c3a7dc9..be4fc30a30e4 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c | |||
@@ -442,7 +442,8 @@ insert: | |||
442 | 442 | ||
443 | fi = (struct btrfs_file_extent_item *)dst_ptr; | 443 | fi = (struct btrfs_file_extent_item *)dst_ptr; |
444 | extent_type = btrfs_file_extent_type(path->nodes[0], fi); | 444 | extent_type = btrfs_file_extent_type(path->nodes[0], fi); |
445 | if (extent_type == BTRFS_FILE_EXTENT_REG) { | 445 | if (extent_type == BTRFS_FILE_EXTENT_REG || |
446 | extent_type == BTRFS_FILE_EXTENT_PREALLOC) { | ||
446 | struct btrfs_key ins; | 447 | struct btrfs_key ins; |
447 | ins.objectid = btrfs_file_extent_disk_bytenr( | 448 | ins.objectid = btrfs_file_extent_disk_bytenr( |
448 | path->nodes[0], fi); | 449 | path->nodes[0], fi); |
@@ -538,7 +539,8 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans, | |||
538 | item = btrfs_item_ptr(eb, slot, struct btrfs_file_extent_item); | 539 | item = btrfs_item_ptr(eb, slot, struct btrfs_file_extent_item); |
539 | found_type = btrfs_file_extent_type(eb, item); | 540 | found_type = btrfs_file_extent_type(eb, item); |
540 | 541 | ||
541 | if (found_type == BTRFS_FILE_EXTENT_REG) | 542 | if (found_type == BTRFS_FILE_EXTENT_REG || |
543 | found_type == BTRFS_FILE_EXTENT_PREALLOC) | ||
542 | extent_end = start + btrfs_file_extent_num_bytes(eb, item); | 544 | extent_end = start + btrfs_file_extent_num_bytes(eb, item); |
543 | else if (found_type == BTRFS_FILE_EXTENT_INLINE) { | 545 | else if (found_type == BTRFS_FILE_EXTENT_INLINE) { |
544 | size = btrfs_file_extent_inline_len(eb, item); | 546 | size = btrfs_file_extent_inline_len(eb, item); |
@@ -562,7 +564,9 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans, | |||
562 | ret = btrfs_lookup_file_extent(trans, root, path, inode->i_ino, | 564 | ret = btrfs_lookup_file_extent(trans, root, path, inode->i_ino, |
563 | start, 0); | 565 | start, 0); |
564 | 566 | ||
565 | if (ret == 0 && found_type == BTRFS_FILE_EXTENT_REG) { | 567 | if (ret == 0 && |
568 | (found_type == BTRFS_FILE_EXTENT_REG || | ||
569 | found_type == BTRFS_FILE_EXTENT_PREALLOC)) { | ||
566 | struct btrfs_file_extent_item cmp1; | 570 | struct btrfs_file_extent_item cmp1; |
567 | struct btrfs_file_extent_item cmp2; | 571 | struct btrfs_file_extent_item cmp2; |
568 | struct btrfs_file_extent_item *existing; | 572 | struct btrfs_file_extent_item *existing; |
@@ -2522,7 +2526,8 @@ static noinline int copy_items(struct btrfs_trans_handle *trans, | |||
2522 | struct btrfs_file_extent_item); | 2526 | struct btrfs_file_extent_item); |
2523 | 2527 | ||
2524 | found_type = btrfs_file_extent_type(src, extent); | 2528 | found_type = btrfs_file_extent_type(src, extent); |
2525 | if (found_type == BTRFS_FILE_EXTENT_REG) { | 2529 | if (found_type == BTRFS_FILE_EXTENT_REG || |
2530 | found_type == BTRFS_FILE_EXTENT_PREALLOC) { | ||
2526 | u64 ds = btrfs_file_extent_disk_bytenr(src, | 2531 | u64 ds = btrfs_file_extent_disk_bytenr(src, |
2527 | extent); | 2532 | extent); |
2528 | u64 dl = btrfs_file_extent_disk_num_bytes(src, | 2533 | u64 dl = btrfs_file_extent_disk_num_bytes(src, |