aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Mason <clm@fb.com>2015-12-30 10:52:35 -0500
committerChris Mason <clm@fb.com>2015-12-30 10:52:35 -0500
commit511711af91f21d80b27f18b569352d6896562828 (patch)
tree105c99f81073dfe5ce3b15623491f65778bf2032
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>
-rw-r--r--fs/btrfs/ctree.h2
-rw-r--r--fs/btrfs/disk-io.c24
-rw-r--r--fs/btrfs/extent-tree.c3
-rw-r--r--fs/btrfs/free-space-tree.c15
4 files changed, 28 insertions, 16 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index d79ba0570c55..9a88d0c69be4 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -1856,6 +1856,8 @@ struct btrfs_fs_info {
1856 * and will be latter freed. Protected by fs_info->chunk_mutex. 1856 * and will be latter freed. Protected by fs_info->chunk_mutex.
1857 */ 1857 */
1858 struct list_head pinned_chunks; 1858 struct list_head pinned_chunks;
1859
1860 int creating_free_space_tree;
1859}; 1861};
1860 1862
1861struct btrfs_subvolume_writers { 1863struct btrfs_subvolume_writers {
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 823c1ce87e2e..dc6b73a95342 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -3065,6 +3065,18 @@ retry_root_backup:
3065 if (sb->s_flags & MS_RDONLY) 3065 if (sb->s_flags & MS_RDONLY)
3066 return 0; 3066 return 0;
3067 3067
3068 if (btrfs_test_opt(tree_root, FREE_SPACE_TREE) &&
3069 !btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE)) {
3070 pr_info("BTRFS: creating free space tree\n");
3071 ret = btrfs_create_free_space_tree(fs_info);
3072 if (ret) {
3073 pr_warn("BTRFS: failed to create free space tree %d\n",
3074 ret);
3075 close_ctree(tree_root);
3076 return ret;
3077 }
3078 }
3079
3068 down_read(&fs_info->cleanup_work_sem); 3080 down_read(&fs_info->cleanup_work_sem);
3069 if ((ret = btrfs_orphan_cleanup(fs_info->fs_root)) || 3081 if ((ret = btrfs_orphan_cleanup(fs_info->fs_root)) ||
3070 (ret = btrfs_orphan_cleanup(fs_info->tree_root))) { 3082 (ret = btrfs_orphan_cleanup(fs_info->tree_root))) {
@@ -3102,18 +3114,6 @@ retry_root_backup:
3102 } 3114 }
3103 } 3115 }
3104 3116
3105 if (btrfs_test_opt(tree_root, FREE_SPACE_TREE) &&
3106 !btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE)) {
3107 pr_info("BTRFS: creating free space tree\n");
3108 ret = btrfs_create_free_space_tree(fs_info);
3109 if (ret) {
3110 pr_warn("BTRFS: failed to create free space tree %d\n",
3111 ret);
3112 close_ctree(tree_root);
3113 return ret;
3114 }
3115 }
3116
3117 if (!fs_info->uuid_root) { 3117 if (!fs_info->uuid_root) {
3118 pr_info("BTRFS: creating UUID tree\n"); 3118 pr_info("BTRFS: creating UUID tree\n");
3119 ret = btrfs_create_uuid_tree(fs_info); 3119 ret = btrfs_create_uuid_tree(fs_info);
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 83fc61db0e45..add4af641cfa 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -2926,6 +2926,9 @@ int btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,
2926 if (trans->aborted) 2926 if (trans->aborted)
2927 return 0; 2927 return 0;
2928 2928
2929 if (root->fs_info->creating_free_space_tree)
2930 return 0;
2931
2929 if (root == root->fs_info->extent_root) 2932 if (root == root->fs_info->extent_root)
2930 root = root->fs_info->tree_root; 2933 root = root->fs_info->tree_root;
2931 2934
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,
1067 if (ret) 1067 if (ret)
1068 goto out; 1068 goto out;
1069 1069
1070 mutex_lock(&block_group->free_space_lock);
1071
1070 /* 1072 /*
1071 * Iterate through all of the extent and metadata items in this block 1073 * Iterate through all of the extent and metadata items in this block
1072 * group, adding the free space between them and the free space at the 1074 * 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,
1080 1082
1081 ret = btrfs_search_slot_for_read(extent_root, &key, path, 1, 0); 1083 ret = btrfs_search_slot_for_read(extent_root, &key, path, 1, 0);
1082 if (ret < 0) 1084 if (ret < 0)
1083 goto out; 1085 goto out_locked;
1084 ASSERT(ret == 0); 1086 ASSERT(ret == 0);
1085 1087
1086 start = block_group->key.objectid; 1088 start = block_group->key.objectid;
@@ -1100,7 +1102,7 @@ static int populate_free_space_tree(struct btrfs_trans_handle *trans,
1100 key.objectid - 1102 key.objectid -
1101 start); 1103 start);
1102 if (ret) 1104 if (ret)
1103 goto out; 1105 goto out_locked;
1104 } 1106 }
1105 start = key.objectid; 1107 start = key.objectid;
1106 if (key.type == BTRFS_METADATA_ITEM_KEY) 1108 if (key.type == BTRFS_METADATA_ITEM_KEY)
@@ -1114,7 +1116,7 @@ static int populate_free_space_tree(struct btrfs_trans_handle *trans,
1114 1116
1115 ret = btrfs_next_item(extent_root, path); 1117 ret = btrfs_next_item(extent_root, path);
1116 if (ret < 0) 1118 if (ret < 0)
1117 goto out; 1119 goto out_locked;
1118 if (ret) 1120 if (ret)
1119 break; 1121 break;
1120 } 1122 }
@@ -1122,10 +1124,12 @@ static int populate_free_space_tree(struct btrfs_trans_handle *trans,
1122 ret = __add_to_free_space_tree(trans, fs_info, block_group, 1124 ret = __add_to_free_space_tree(trans, fs_info, block_group,
1123 path2, start, end - start); 1125 path2, start, end - start);
1124 if (ret) 1126 if (ret)
1125 goto out; 1127 goto out_locked;
1126 } 1128 }
1127 1129
1128 ret = 0; 1130 ret = 0;
1131out_locked:
1132 mutex_unlock(&block_group->free_space_lock);
1129out: 1133out:
1130 btrfs_free_path(path2); 1134 btrfs_free_path(path2);
1131 btrfs_free_path(path); 1135 btrfs_free_path(path);
@@ -1145,6 +1149,7 @@ int btrfs_create_free_space_tree(struct btrfs_fs_info *fs_info)
1145 if (IS_ERR(trans)) 1149 if (IS_ERR(trans))
1146 return PTR_ERR(trans); 1150 return PTR_ERR(trans);
1147 1151
1152 fs_info->creating_free_space_tree = 1;
1148 free_space_root = btrfs_create_tree(trans, fs_info, 1153 free_space_root = btrfs_create_tree(trans, fs_info,
1149 BTRFS_FREE_SPACE_TREE_OBJECTID); 1154 BTRFS_FREE_SPACE_TREE_OBJECTID);
1150 if (IS_ERR(free_space_root)) { 1155 if (IS_ERR(free_space_root)) {
@@ -1164,6 +1169,7 @@ int btrfs_create_free_space_tree(struct btrfs_fs_info *fs_info)
1164 } 1169 }
1165 1170
1166 btrfs_set_fs_compat_ro(fs_info, FREE_SPACE_TREE); 1171 btrfs_set_fs_compat_ro(fs_info, FREE_SPACE_TREE);
1172 fs_info->creating_free_space_tree = 0;
1167 1173
1168 ret = btrfs_commit_transaction(trans, tree_root); 1174 ret = btrfs_commit_transaction(trans, tree_root);
1169 if (ret) 1175 if (ret)
@@ -1172,6 +1178,7 @@ int btrfs_create_free_space_tree(struct btrfs_fs_info *fs_info)
1172 return 0; 1178 return 0;
1173 1179
1174abort: 1180abort:
1181 fs_info->creating_free_space_tree = 0;
1175 btrfs_abort_transaction(trans, tree_root, ret); 1182 btrfs_abort_transaction(trans, tree_root, ret);
1176 btrfs_end_transaction(trans, tree_root); 1183 btrfs_end_transaction(trans, tree_root);
1177 return ret; 1184 return ret;