diff options
author | Chris Mason <chris.mason@oracle.com> | 2008-06-26 10:34:20 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:04:04 -0400 |
commit | a7a16fd772620605c76e8ac8bdbc8ccc9e3df1a0 (patch) | |
tree | 5dc173d7653ba4819ce1c853b9e84293422edf90 /fs/btrfs/root-tree.c | |
parent | f9efa9c784aa3b801feb367f72c6867d26fb348e (diff) |
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: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/root-tree.c')
-rw-r--r-- | fs/btrfs/root-tree.c | 10 |
1 files changed, 9 insertions, 1 deletions
diff --git a/fs/btrfs/root-tree.c b/fs/btrfs/root-tree.c index 8bf21ba0a43..a5c0e98b5ae 100644 --- a/fs/btrfs/root-tree.c +++ b/fs/btrfs/root-tree.c | |||
@@ -154,6 +154,7 @@ int btrfs_find_dead_roots(struct btrfs_root *root, u64 objectid, | |||
154 | struct btrfs_item *item; | 154 | struct btrfs_item *item; |
155 | struct btrfs_root_item *ri; | 155 | struct btrfs_root_item *ri; |
156 | struct btrfs_key key; | 156 | struct btrfs_key key; |
157 | struct btrfs_key found_key; | ||
157 | struct btrfs_path *path; | 158 | struct btrfs_path *path; |
158 | int ret; | 159 | int ret; |
159 | u32 nritems; | 160 | u32 nritems; |
@@ -166,6 +167,8 @@ int btrfs_find_dead_roots(struct btrfs_root *root, u64 objectid, | |||
166 | path = btrfs_alloc_path(); | 167 | path = btrfs_alloc_path(); |
167 | if (!path) | 168 | if (!path) |
168 | return -ENOMEM; | 169 | return -ENOMEM; |
170 | |||
171 | again: | ||
169 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); | 172 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); |
170 | if (ret < 0) | 173 | if (ret < 0) |
171 | goto err; | 174 | goto err; |
@@ -196,7 +199,11 @@ int btrfs_find_dead_roots(struct btrfs_root *root, u64 objectid, | |||
196 | if (btrfs_disk_root_refs(leaf, ri) != 0) | 199 | if (btrfs_disk_root_refs(leaf, ri) != 0) |
197 | goto next; | 200 | goto next; |
198 | 201 | ||
199 | dead_root = btrfs_read_fs_root_no_radix(root->fs_info, &key); | 202 | memcpy(&found_key, &key, sizeof(key)); |
203 | key.offset++; | ||
204 | btrfs_release_path(root, path); | ||
205 | dead_root = btrfs_read_fs_root_no_radix(root->fs_info, | ||
206 | &found_key); | ||
200 | if (IS_ERR(dead_root)) { | 207 | if (IS_ERR(dead_root)) { |
201 | ret = PTR_ERR(dead_root); | 208 | ret = PTR_ERR(dead_root); |
202 | goto err; | 209 | goto err; |
@@ -206,6 +213,7 @@ int btrfs_find_dead_roots(struct btrfs_root *root, u64 objectid, | |||
206 | &root->fs_info->dead_roots); | 213 | &root->fs_info->dead_roots); |
207 | if (ret) | 214 | if (ret) |
208 | goto err; | 215 | goto err; |
216 | goto again; | ||
209 | next: | 217 | next: |
210 | slot++; | 218 | slot++; |
211 | path->slots[0]++; | 219 | path->slots[0]++; |