diff options
Diffstat (limited to 'fs/btrfs/root-tree.c')
-rw-r--r-- | fs/btrfs/root-tree.c | 45 |
1 files changed, 24 insertions, 21 deletions
diff --git a/fs/btrfs/root-tree.c b/fs/btrfs/root-tree.c index 7fd7e1830cfe..edae751e870c 100644 --- a/fs/btrfs/root-tree.c +++ b/fs/btrfs/root-tree.c @@ -46,12 +46,7 @@ static void btrfs_read_root_item(struct extent_buffer *eb, int slot, != btrfs_root_generation_v2(item)) { if (btrfs_root_generation_v2(item) != 0) { btrfs_warn(eb->fs_info, - "mismatching " - "generation and generation_v2 " - "found in root item. This root " - "was probably mounted with an " - "older kernel. Resetting all " - "new fields."); + "mismatching generation and generation_v2 found in root item. This root was probably mounted with an older kernel. Resetting all new fields."); } need_reset = 1; } @@ -156,8 +151,9 @@ int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root if (ret != 0) { btrfs_print_leaf(root, path->nodes[0]); - btrfs_crit(root->fs_info, "unable to update root key %llu %u %llu", - key->objectid, key->type, key->offset); + btrfs_crit(root->fs_info, + "unable to update root key %llu %u %llu", + key->objectid, key->type, key->offset); BUG_ON(1); } @@ -272,6 +268,23 @@ int btrfs_find_orphan_roots(struct btrfs_root *tree_root) root_key.objectid = key.offset; key.offset++; + /* + * The root might have been inserted already, as before we look + * for orphan roots, log replay might have happened, which + * triggers a transaction commit and qgroup accounting, which + * in turn reads and inserts fs roots while doing backref + * walking. + */ + root = btrfs_lookup_fs_root(tree_root->fs_info, + root_key.objectid); + if (root) { + WARN_ON(!test_bit(BTRFS_ROOT_ORPHAN_ITEM_INSERTED, + &root->state)); + if (btrfs_root_refs(&root->root_item) == 0) + btrfs_add_dead_root(root); + continue; + } + root = btrfs_read_fs_root(tree_root, &root_key); err = PTR_ERR_OR_ZERO(root); if (err && err != -ENOENT) { @@ -285,8 +298,7 @@ int btrfs_find_orphan_roots(struct btrfs_root *tree_root) if (IS_ERR(trans)) { err = PTR_ERR(trans); btrfs_handle_fs_error(tree_root->fs_info, err, - "Failed to start trans to delete " - "orphan item"); + "Failed to start trans to delete orphan item"); break; } err = btrfs_del_orphan_item(trans, tree_root, @@ -294,8 +306,7 @@ int btrfs_find_orphan_roots(struct btrfs_root *tree_root) btrfs_end_transaction(trans, tree_root); if (err) { btrfs_handle_fs_error(tree_root->fs_info, err, - "Failed to delete root orphan " - "item"); + "Failed to delete root orphan item"); break; } continue; @@ -310,16 +321,8 @@ int btrfs_find_orphan_roots(struct btrfs_root *tree_root) set_bit(BTRFS_ROOT_ORPHAN_ITEM_INSERTED, &root->state); err = btrfs_insert_fs_root(root->fs_info, root); - /* - * The root might have been inserted already, as before we look - * for orphan roots, log replay might have happened, which - * triggers a transaction commit and qgroup accounting, which - * in turn reads and inserts fs roots while doing backref - * walking. - */ - if (err == -EEXIST) - err = 0; if (err) { + BUG_ON(err == -EEXIST); btrfs_free_fs_root(root); break; } |