Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a7a16fd7 authored by Chris Mason's avatar Chris Mason
Browse files

Btrfs: Fix deadlock while searching for dead roots on mount



btrfs_find_dead_roots called btrfs_read_fs_root_no_radix, which
means we end up calling btrfs_search_slot with a path already held.

The fix is to remember the key inside btrfs_find_dead_roots and drop
the path.

Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
parent f9efa9c7
Loading
Loading
Loading
Loading
+9 −1
Original line number Original line Diff line number Diff line
@@ -154,6 +154,7 @@ int btrfs_find_dead_roots(struct btrfs_root *root, u64 objectid,
	struct btrfs_item *item;
	struct btrfs_item *item;
	struct btrfs_root_item *ri;
	struct btrfs_root_item *ri;
	struct btrfs_key key;
	struct btrfs_key key;
	struct btrfs_key found_key;
	struct btrfs_path *path;
	struct btrfs_path *path;
	int ret;
	int ret;
	u32 nritems;
	u32 nritems;
@@ -166,6 +167,8 @@ int btrfs_find_dead_roots(struct btrfs_root *root, u64 objectid,
	path = btrfs_alloc_path();
	path = btrfs_alloc_path();
	if (!path)
	if (!path)
		return -ENOMEM;
		return -ENOMEM;

again:
	ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
	ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
	if (ret < 0)
	if (ret < 0)
		goto err;
		goto err;
@@ -196,7 +199,11 @@ int btrfs_find_dead_roots(struct btrfs_root *root, u64 objectid,
		if (btrfs_disk_root_refs(leaf, ri) != 0)
		if (btrfs_disk_root_refs(leaf, ri) != 0)
			goto next;
			goto next;


		dead_root = btrfs_read_fs_root_no_radix(root->fs_info, &key);
		memcpy(&found_key, &key, sizeof(key));
		key.offset++;
		btrfs_release_path(root, path);
		dead_root = btrfs_read_fs_root_no_radix(root->fs_info,
							&found_key);
		if (IS_ERR(dead_root)) {
		if (IS_ERR(dead_root)) {
			ret = PTR_ERR(dead_root);
			ret = PTR_ERR(dead_root);
			goto err;
			goto err;
@@ -206,6 +213,7 @@ int btrfs_find_dead_roots(struct btrfs_root *root, u64 objectid,
					  &root->fs_info->dead_roots);
					  &root->fs_info->dead_roots);
		if (ret)
		if (ret)
			goto err;
			goto err;
		goto again;
next:
next:
		slot++;
		slot++;
		path->slots[0]++;
		path->slots[0]++;