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 /fs/btrfs/extent-tree.c | |
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>
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r-- | fs/btrfs/extent-tree.c | 65 |
1 files changed, 36 insertions, 29 deletions
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; |