Skip to content

Commit 35bbb97

Browse files
jeffmahoneymasoncl
authored andcommitted
btrfs: don't create or leak aliased root while cleaning up orphans
commit 909c3a2 (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: <[email protected]> # 4.5 Signed-off-by: Jeff Mahoney <[email protected]> Reviewed-by: David Sterba <[email protected]> Signed-off-by: David Sterba <[email protected]> Signed-off-by: Chris Mason <[email protected]>
1 parent 187ee58 commit 35bbb97

File tree

3 files changed

+22
-11
lines changed

3 files changed

+22
-11
lines changed

fs/btrfs/disk-io.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1624,8 +1624,8 @@ int btrfs_init_fs_root(struct btrfs_root *root)
16241624
return ret;
16251625
}
16261626

1627-
static struct btrfs_root *btrfs_lookup_fs_root(struct btrfs_fs_info *fs_info,
1628-
u64 root_id)
1627+
struct btrfs_root *btrfs_lookup_fs_root(struct btrfs_fs_info *fs_info,
1628+
u64 root_id)
16291629
{
16301630
struct btrfs_root *root;
16311631

fs/btrfs/disk-io.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ struct extent_buffer *btrfs_find_tree_block(struct btrfs_fs_info *fs_info,
6868
struct btrfs_root *btrfs_read_fs_root(struct btrfs_root *tree_root,
6969
struct btrfs_key *location);
7070
int btrfs_init_fs_root(struct btrfs_root *root);
71+
struct btrfs_root *btrfs_lookup_fs_root(struct btrfs_fs_info *fs_info,
72+
u64 root_id);
7173
int btrfs_insert_fs_root(struct btrfs_fs_info *fs_info,
7274
struct btrfs_root *root);
7375
void btrfs_free_fs_roots(struct btrfs_fs_info *fs_info);

fs/btrfs/root-tree.c

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,23 @@ int btrfs_find_orphan_roots(struct btrfs_root *tree_root)
272272
root_key.objectid = key.offset;
273273
key.offset++;
274274

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+
275292
root = btrfs_read_fs_root(tree_root, &root_key);
276293
err = PTR_ERR_OR_ZERO(root);
277294
if (err && err != -ENOENT) {
@@ -310,16 +327,8 @@ int btrfs_find_orphan_roots(struct btrfs_root *tree_root)
310327
set_bit(BTRFS_ROOT_ORPHAN_ITEM_INSERTED, &root->state);
311328

312329
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;
322330
if (err) {
331+
BUG_ON(err == -EEXIST);
323332
btrfs_free_fs_root(root);
324333
break;
325334
}

0 commit comments

Comments
 (0)