提交 538f72cd 编写于 作者: W Wang Shilong 提交者: Chris Mason

Btrfs: fix protection between walking backrefs and root deletion

There is a race condition between resolving indirect ref and root deletion,
and we should gurantee that root can not be destroyed to avoid accessing
broken tree here.

Here we fix it by holding @subvol_srcu, and we will release it as soon
as we have held root node lock.
Signed-off-by: NWang Shilong <wangsl.fnst@cn.fujitsu.com>
Signed-off-by: NJosef Bacik <jbacik@fb.com>
Signed-off-by: NChris Mason <clm@fb.com>
上级 3c9665df
...@@ -301,23 +301,34 @@ static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info, ...@@ -301,23 +301,34 @@ static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info,
int ret = 0; int ret = 0;
int root_level; int root_level;
int level = ref->level; int level = ref->level;
int index;
root_key.objectid = ref->root_id; root_key.objectid = ref->root_id;
root_key.type = BTRFS_ROOT_ITEM_KEY; root_key.type = BTRFS_ROOT_ITEM_KEY;
root_key.offset = (u64)-1; root_key.offset = (u64)-1;
index = srcu_read_lock(&fs_info->subvol_srcu);
root = btrfs_read_fs_root_no_name(fs_info, &root_key); root = btrfs_read_fs_root_no_name(fs_info, &root_key);
if (IS_ERR(root)) { if (IS_ERR(root)) {
srcu_read_unlock(&fs_info->subvol_srcu, index);
ret = PTR_ERR(root); ret = PTR_ERR(root);
goto out; goto out;
} }
root_level = btrfs_old_root_level(root, time_seq); root_level = btrfs_old_root_level(root, time_seq);
if (root_level + 1 == level) if (root_level + 1 == level) {
srcu_read_unlock(&fs_info->subvol_srcu, index);
goto out; goto out;
}
path->lowest_level = level; path->lowest_level = level;
ret = btrfs_search_old_slot(root, &ref->key_for_search, path, time_seq); ret = btrfs_search_old_slot(root, &ref->key_for_search, path, time_seq);
/* root node has been locked, we can release @subvol_srcu safely here */
srcu_read_unlock(&fs_info->subvol_srcu, index);
pr_debug("search slot in root %llu (level %d, ref count %d) returned " pr_debug("search slot in root %llu (level %d, ref count %d) returned "
"%d for key (%llu %u %llu)\n", "%d for key (%llu %u %llu)\n",
ref->root_id, level, ref->count, ret, ref->root_id, level, ref->count, ret,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册