diff options
| -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 8bf6a085a73..d5ba3d1aaf9 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 1eb69a91b72..8af39521eb7 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 65a0583027e..eb3c12e7bea 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 e693e1b4ac4..accfedaeb51 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 1a0510ad030..238a8e215eb 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 3e6f0568fdb..789c376157f 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 7f915d47839..9ff2b4e0e92 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 e7317c8fda2..370bb428559 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 e6d9bc54c2b..260bf95dfe0 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 e0201c3a7dc..be4fc30a30e 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, |
