aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/relocation.c
diff options
context:
space:
mode:
authorJosef Bacik <josef@redhat.com>2010-06-21 14:48:16 -0400
committerJosef Bacik <josef@redhat.com>2010-10-28 15:59:09 -0400
commit0af3d00bad38d3bb9912a60928ad0669f17bdb76 (patch)
treeabbf4c773138a33dcde483ac60f016c4b5e55dcc /fs/btrfs/relocation.c
parentf6f94e2ab1b33f0082ac22d71f66385a60d8157f (diff)
Btrfs: create special free space cache inode
In order to save free space cache, we need an inode to hold the data, and we need a special item to point at the right inode for the right block group. So first, create a special item that will point to the right inode, and the number of extent entries we will have and the number of bitmaps we will have. We truncate and pre-allocate space everytime to make sure it's uptodate. This feature will be turned on as soon as you mount with -o space_cache, however it is safe to boot into old kernels, they will just generate the cache the old fashion way. When you boot back into a newer kernel we will notice that we modified and not the cache and automatically discard the cache. Signed-off-by: Josef Bacik <josef@redhat.com>
Diffstat (limited to 'fs/btrfs/relocation.c')
-rw-r--r--fs/btrfs/relocation.c91
1 files changed, 87 insertions, 4 deletions
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index b37d723b9d4a..af339eee55b8 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -29,6 +29,7 @@
29#include "locking.h" 29#include "locking.h"
30#include "btrfs_inode.h" 30#include "btrfs_inode.h"
31#include "async-thread.h" 31#include "async-thread.h"
32#include "free-space-cache.h"
32 33
33/* 34/*
34 * backref_node, mapping_node and tree_block start with this 35 * backref_node, mapping_node and tree_block start with this
@@ -3191,6 +3192,54 @@ static int block_use_full_backref(struct reloc_control *rc,
3191 return ret; 3192 return ret;
3192} 3193}
3193 3194
3195static int delete_block_group_cache(struct btrfs_fs_info *fs_info,
3196 struct inode *inode, u64 ino)
3197{
3198 struct btrfs_key key;
3199 struct btrfs_path *path;
3200 struct btrfs_root *root = fs_info->tree_root;
3201 struct btrfs_trans_handle *trans;
3202 unsigned long nr;
3203 int ret = 0;
3204
3205 if (inode)
3206 goto truncate;
3207
3208 key.objectid = ino;
3209 key.type = BTRFS_INODE_ITEM_KEY;
3210 key.offset = 0;
3211
3212 inode = btrfs_iget(fs_info->sb, &key, root, NULL);
3213 if (!inode || IS_ERR(inode) || is_bad_inode(inode)) {
3214 if (inode && !IS_ERR(inode))
3215 iput(inode);
3216 return -ENOENT;
3217 }
3218
3219truncate:
3220 path = btrfs_alloc_path();
3221 if (!path) {
3222 ret = -ENOMEM;
3223 goto out;
3224 }
3225
3226 trans = btrfs_join_transaction(root, 0);
3227 if (IS_ERR(trans)) {
3228 btrfs_free_path(path);
3229 goto out;
3230 }
3231
3232 ret = btrfs_truncate_free_space_cache(root, trans, path, inode);
3233
3234 btrfs_free_path(path);
3235 nr = trans->blocks_used;
3236 btrfs_end_transaction(trans, root);
3237 btrfs_btree_balance_dirty(root, nr);
3238out:
3239 iput(inode);
3240 return ret;
3241}
3242
3194/* 3243/*
3195 * helper to add tree blocks for backref of type BTRFS_EXTENT_DATA_REF_KEY 3244 * helper to add tree blocks for backref of type BTRFS_EXTENT_DATA_REF_KEY
3196 * this function scans fs tree to find blocks reference the data extent 3245 * this function scans fs tree to find blocks reference the data extent
@@ -3217,15 +3266,27 @@ static int find_data_references(struct reloc_control *rc,
3217 int counted; 3266 int counted;
3218 int ret; 3267 int ret;
3219 3268
3220 path = btrfs_alloc_path();
3221 if (!path)
3222 return -ENOMEM;
3223
3224 ref_root = btrfs_extent_data_ref_root(leaf, ref); 3269 ref_root = btrfs_extent_data_ref_root(leaf, ref);
3225 ref_objectid = btrfs_extent_data_ref_objectid(leaf, ref); 3270 ref_objectid = btrfs_extent_data_ref_objectid(leaf, ref);
3226 ref_offset = btrfs_extent_data_ref_offset(leaf, ref); 3271 ref_offset = btrfs_extent_data_ref_offset(leaf, ref);
3227 ref_count = btrfs_extent_data_ref_count(leaf, ref); 3272 ref_count = btrfs_extent_data_ref_count(leaf, ref);
3228 3273
3274 /*
3275 * This is an extent belonging to the free space cache, lets just delete
3276 * it and redo the search.
3277 */
3278 if (ref_root == BTRFS_ROOT_TREE_OBJECTID) {
3279 ret = delete_block_group_cache(rc->extent_root->fs_info,
3280 NULL, ref_objectid);
3281 if (ret != -ENOENT)
3282 return ret;
3283 ret = 0;
3284 }
3285
3286 path = btrfs_alloc_path();
3287 if (!path)
3288 return -ENOMEM;
3289
3229 root = read_fs_root(rc->extent_root->fs_info, ref_root); 3290 root = read_fs_root(rc->extent_root->fs_info, ref_root);
3230 if (IS_ERR(root)) { 3291 if (IS_ERR(root)) {
3231 err = PTR_ERR(root); 3292 err = PTR_ERR(root);
@@ -3860,6 +3921,8 @@ int btrfs_relocate_block_group(struct btrfs_root *extent_root, u64 group_start)
3860{ 3921{
3861 struct btrfs_fs_info *fs_info = extent_root->fs_info; 3922 struct btrfs_fs_info *fs_info = extent_root->fs_info;
3862 struct reloc_control *rc; 3923 struct reloc_control *rc;
3924 struct inode *inode;
3925 struct btrfs_path *path;
3863 int ret; 3926 int ret;
3864 int rw = 0; 3927 int rw = 0;
3865 int err = 0; 3928 int err = 0;
@@ -3882,6 +3945,26 @@ int btrfs_relocate_block_group(struct btrfs_root *extent_root, u64 group_start)
3882 rw = 1; 3945 rw = 1;
3883 } 3946 }
3884 3947
3948 path = btrfs_alloc_path();
3949 if (!path) {
3950 err = -ENOMEM;
3951 goto out;
3952 }
3953
3954 inode = lookup_free_space_inode(fs_info->tree_root, rc->block_group,
3955 path);
3956 btrfs_free_path(path);
3957
3958 if (!IS_ERR(inode))
3959 ret = delete_block_group_cache(fs_info, inode, 0);
3960 else
3961 ret = PTR_ERR(inode);
3962
3963 if (ret && ret != -ENOENT) {
3964 err = ret;
3965 goto out;
3966 }
3967
3885 rc->data_inode = create_reloc_inode(fs_info, rc->block_group); 3968 rc->data_inode = create_reloc_inode(fs_info, rc->block_group);
3886 if (IS_ERR(rc->data_inode)) { 3969 if (IS_ERR(rc->data_inode)) {
3887 err = PTR_ERR(rc->data_inode); 3970 err = PTR_ERR(rc->data_inode);