summaryrefslogtreecommitdiff
path: root/fs/btrfs/free-space-tree.c
diff options
context:
space:
mode:
authorChris Mason <clm@fb.com>2015-12-30 07:52:35 -0800
committerChris Mason <clm@fb.com>2015-12-30 07:52:35 -0800
commit511711af91f21d80b27f18b569352d6896562828 (patch)
tree105c99f81073dfe5ce3b15623491f65778bf2032 /fs/btrfs/free-space-tree.c
parentb4570aa994b8fdb3a9c04ed80a6cac69072d4d42 (diff)
btrfs: don't run delayed references while we are creating the free space tree
This is a short term solution to make sure btrfs_run_delayed_refs() doesn't change the extent tree while we are scanning it to create the free space tree. Longer term we need to synchronize scanning the block groups one by one, similar to what happens during a balance. Signed-off-by: Chris Mason <clm@fb.com>
Diffstat (limited to 'fs/btrfs/free-space-tree.c')
-rw-r--r--fs/btrfs/free-space-tree.c15
1 files changed, 11 insertions, 4 deletions
diff --git a/fs/btrfs/free-space-tree.c b/fs/btrfs/free-space-tree.c
index cbe36dd0d97b..393e36bd5845 100644
--- a/fs/btrfs/free-space-tree.c
+++ b/fs/btrfs/free-space-tree.c
@@ -1067,6 +1067,8 @@ static int populate_free_space_tree(struct btrfs_trans_handle *trans,
if (ret)
goto out;
+ mutex_lock(&block_group->free_space_lock);
+
/*
* Iterate through all of the extent and metadata items in this block
* group, adding the free space between them and the free space at the
@@ -1080,7 +1082,7 @@ static int populate_free_space_tree(struct btrfs_trans_handle *trans,
ret = btrfs_search_slot_for_read(extent_root, &key, path, 1, 0);
if (ret < 0)
- goto out;
+ goto out_locked;
ASSERT(ret == 0);
start = block_group->key.objectid;
@@ -1100,7 +1102,7 @@ static int populate_free_space_tree(struct btrfs_trans_handle *trans,
key.objectid -
start);
if (ret)
- goto out;
+ goto out_locked;
}
start = key.objectid;
if (key.type == BTRFS_METADATA_ITEM_KEY)
@@ -1114,7 +1116,7 @@ static int populate_free_space_tree(struct btrfs_trans_handle *trans,
ret = btrfs_next_item(extent_root, path);
if (ret < 0)
- goto out;
+ goto out_locked;
if (ret)
break;
}
@@ -1122,10 +1124,12 @@ static int populate_free_space_tree(struct btrfs_trans_handle *trans,
ret = __add_to_free_space_tree(trans, fs_info, block_group,
path2, start, end - start);
if (ret)
- goto out;
+ goto out_locked;
}
ret = 0;
+out_locked:
+ mutex_unlock(&block_group->free_space_lock);
out:
btrfs_free_path(path2);
btrfs_free_path(path);
@@ -1145,6 +1149,7 @@ int btrfs_create_free_space_tree(struct btrfs_fs_info *fs_info)
if (IS_ERR(trans))
return PTR_ERR(trans);
+ fs_info->creating_free_space_tree = 1;
free_space_root = btrfs_create_tree(trans, fs_info,
BTRFS_FREE_SPACE_TREE_OBJECTID);
if (IS_ERR(free_space_root)) {
@@ -1164,6 +1169,7 @@ int btrfs_create_free_space_tree(struct btrfs_fs_info *fs_info)
}
btrfs_set_fs_compat_ro(fs_info, FREE_SPACE_TREE);
+ fs_info->creating_free_space_tree = 0;
ret = btrfs_commit_transaction(trans, tree_root);
if (ret)
@@ -1172,6 +1178,7 @@ int btrfs_create_free_space_tree(struct btrfs_fs_info *fs_info)
return 0;
abort:
+ fs_info->creating_free_space_tree = 0;
btrfs_abort_transaction(trans, tree_root, ret);
btrfs_end_transaction(trans, tree_root);
return ret;