summaryrefslogtreecommitdiffstats
path: root/fs/btrfs/root-tree.c
diff options
context:
space:
mode:
authorJeff Mahoney <jeffm@suse.com>2016-08-17 21:58:33 -0400
committerChris Mason <clm@fb.com>2016-08-25 06:58:29 -0400
commit35bbb97fc898aeb874cb7c8b746f091caa359994 (patch)
tree4ff7e4a0ac701e26985efb0d24c0ea3665791ffc /fs/btrfs/root-tree.c
parent187ee58c62c1d0d238d3dc4835869d33e1869906 (diff)
btrfs: don't create or leak aliased root while cleaning up orphans
commit 909c3a22da3 (Btrfs: fix loading of orphan roots leading to BUG_ON) avoids the BUG_ON but can add an aliased root to the dead_roots list or leak the root. Since we've already been loading roots into the radix tree, we should use it before looking the root up on disk. Cc: <stable@vger.kernel.org> # 4.5 Signed-off-by: Jeff Mahoney <jeffm@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com> Signed-off-by: Chris Mason <clm@fb.com>
Diffstat (limited to 'fs/btrfs/root-tree.c')
-rw-r--r--fs/btrfs/root-tree.c27
1 files changed, 18 insertions, 9 deletions
diff --git a/fs/btrfs/root-tree.c b/fs/btrfs/root-tree.c
index 7fd7e1830cfe..091296062456 100644
--- a/fs/btrfs/root-tree.c
+++ b/fs/btrfs/root-tree.c
@@ -272,6 +272,23 @@ int btrfs_find_orphan_roots(struct btrfs_root *tree_root)
272 root_key.objectid = key.offset; 272 root_key.objectid = key.offset;
273 key.offset++; 273 key.offset++;
274 274
275 /*
276 * The root might have been inserted already, as before we look
277 * for orphan roots, log replay might have happened, which
278 * triggers a transaction commit and qgroup accounting, which
279 * in turn reads and inserts fs roots while doing backref
280 * walking.
281 */
282 root = btrfs_lookup_fs_root(tree_root->fs_info,
283 root_key.objectid);
284 if (root) {
285 WARN_ON(!test_bit(BTRFS_ROOT_ORPHAN_ITEM_INSERTED,
286 &root->state));
287 if (btrfs_root_refs(&root->root_item) == 0)
288 btrfs_add_dead_root(root);
289 continue;
290 }
291
275 root = btrfs_read_fs_root(tree_root, &root_key); 292 root = btrfs_read_fs_root(tree_root, &root_key);
276 err = PTR_ERR_OR_ZERO(root); 293 err = PTR_ERR_OR_ZERO(root);
277 if (err && err != -ENOENT) { 294 if (err && err != -ENOENT) {
@@ -310,16 +327,8 @@ int btrfs_find_orphan_roots(struct btrfs_root *tree_root)
310 set_bit(BTRFS_ROOT_ORPHAN_ITEM_INSERTED, &root->state); 327 set_bit(BTRFS_ROOT_ORPHAN_ITEM_INSERTED, &root->state);
311 328
312 err = btrfs_insert_fs_root(root->fs_info, root); 329 err = btrfs_insert_fs_root(root->fs_info, root);
313 /*
314 * The root might have been inserted already, as before we look
315 * for orphan roots, log replay might have happened, which
316 * triggers a transaction commit and qgroup accounting, which
317 * in turn reads and inserts fs roots while doing backref
318 * walking.
319 */
320 if (err == -EEXIST)
321 err = 0;
322 if (err) { 330 if (err) {
331 BUG_ON(err == -EEXIST);
323 btrfs_free_fs_root(root); 332 btrfs_free_fs_root(root);
324 break; 333 break;
325 } 334 }