Btrfs: cleanup the similar code of the fs root read
authorMiao Xie <miaox@cn.fujitsu.com>
Wed, 15 May 2013 07:48:19 +0000 (07:48 +0000)
committerJosef Bacik <jbacik@fusionio.com>
Fri, 14 Jun 2013 15:29:37 +0000 (11:29 -0400)
There are several functions whose code is similar, such as
  btrfs_find_last_root()
  btrfs_read_fs_root_no_radix()

Besides that, some functions are invoked twice, it is unnecessary,
for example, we are sure that all roots which is found in
  btrfs_find_orphan_roots()
have their orphan items, so it is unnecessary to check the orphan
item again.

So cleanup it.

Signed-off-by: Miao Xie <miaox@cn.fujitsu.com>
Signed-off-by: Josef Bacik <jbacik@fusionio.com>
fs/btrfs/ctree.h
fs/btrfs/disk-io.c
fs/btrfs/disk-io.h
fs/btrfs/extent-tree.c
fs/btrfs/relocation.c
fs/btrfs/root-tree.c
fs/btrfs/tree-log.c
fs/btrfs/volumes.c
fs/btrfs/volumes.h

index d9ff585aadba851052220cba837e705181af96a6..a84e59b7b00646b132827c709396d147a2542b04 100644 (file)
@@ -3376,9 +3376,9 @@ int __must_check btrfs_update_root(struct btrfs_trans_handle *trans,
                                   struct btrfs_root_item *item);
 void btrfs_read_root_item(struct extent_buffer *eb, int slot,
                          struct btrfs_root_item *item);
-int btrfs_find_last_root(struct btrfs_root *root, u64 objectid, struct
-                        btrfs_root_item *item, struct btrfs_key *key);
-int btrfs_find_dead_roots(struct btrfs_root *root, u64 objectid);
+int btrfs_find_root(struct btrfs_root *root, struct btrfs_key *search_key,
+                   struct btrfs_path *path, struct btrfs_root_item *root_item,
+                   struct btrfs_key *root_key);
 int btrfs_find_orphan_roots(struct btrfs_root *tree_root);
 void btrfs_set_root_node(struct btrfs_root_item *item,
                         struct extent_buffer *node);
index 8dbd908a3a9770d76ce69eb2b571db1d517a49a8..c65a5aac1e45de711fcd4e85ceba8ea196b767b3 100644 (file)
@@ -1234,39 +1234,6 @@ static void __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
        spin_lock_init(&root->root_item_lock);
 }
 
-static int __must_check find_and_setup_root(struct btrfs_root *tree_root,
-                                           struct btrfs_fs_info *fs_info,
-                                           u64 objectid,
-                                           struct btrfs_root *root)
-{
-       int ret;
-       u32 blocksize;
-       u64 generation;
-
-       __setup_root(tree_root->nodesize, tree_root->leafsize,
-                    tree_root->sectorsize, tree_root->stripesize,
-                    root, fs_info, objectid);
-       ret = btrfs_find_last_root(tree_root, objectid,
-                                  &root->root_item, &root->root_key);
-       if (ret > 0)
-               return -ENOENT;
-       else if (ret < 0)
-               return ret;
-
-       generation = btrfs_root_generation(&root->root_item);
-       blocksize = btrfs_level_size(root, btrfs_root_level(&root->root_item));
-       root->commit_root = NULL;
-       root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item),
-                                    blocksize, generation);
-       if (!root->node || !btrfs_buffer_uptodate(root->node, generation, 0)) {
-               free_extent_buffer(root->node);
-               root->node = NULL;
-               return -EIO;
-       }
-       root->commit_root = btrfs_root_node(root);
-       return 0;
-}
-
 static struct btrfs_root *btrfs_alloc_root(struct btrfs_fs_info *fs_info)
 {
        struct btrfs_root *root = kzalloc(sizeof(*root), GFP_NOFS);
@@ -1451,70 +1418,73 @@ int btrfs_add_log_tree(struct btrfs_trans_handle *trans,
        return 0;
 }
 
-struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_root *tree_root,
-                                              struct btrfs_key *location)
+struct btrfs_root *btrfs_read_tree_root(struct btrfs_root *tree_root,
+                                       struct btrfs_key *key)
 {
        struct btrfs_root *root;
        struct btrfs_fs_info *fs_info = tree_root->fs_info;
        struct btrfs_path *path;
-       struct extent_buffer *l;
        u64 generation;
        u32 blocksize;
-       int ret = 0;
-       int slot;
+       int ret;
 
-       root = btrfs_alloc_root(fs_info);
-       if (!root)
+       path = btrfs_alloc_path();
+       if (!path)
                return ERR_PTR(-ENOMEM);
-       if (location->offset == (u64)-1) {
-               ret = find_and_setup_root(tree_root, fs_info,
-                                         location->objectid, root);
-               if (ret) {
-                       kfree(root);
-                       return ERR_PTR(ret);
-               }
-               goto out;
+
+       root = btrfs_alloc_root(fs_info);
+       if (!root) {
+               ret = -ENOMEM;
+               goto alloc_fail;
        }
 
        __setup_root(tree_root->nodesize, tree_root->leafsize,
                     tree_root->sectorsize, tree_root->stripesize,
-                    root, fs_info, location->objectid);
+                    root, fs_info, key->objectid);
 
-       path = btrfs_alloc_path();
-       if (!path) {
-               kfree(root);
-               return ERR_PTR(-ENOMEM);
-       }
-       ret = btrfs_search_slot(NULL, tree_root, location, path, 0, 0);
-       if (ret == 0) {
-               l = path->nodes[0];
-               slot = path->slots[0];
-               btrfs_read_root_item(l, slot, &root->root_item);
-               memcpy(&root->root_key, location, sizeof(*location));
-       }
-       btrfs_free_path(path);
+       ret = btrfs_find_root(tree_root, key, path,
+                             &root->root_item, &root->root_key);
        if (ret) {
-               kfree(root);
                if (ret > 0)
                        ret = -ENOENT;
-               return ERR_PTR(ret);
+               goto find_fail;
        }
 
        generation = btrfs_root_generation(&root->root_item);
        blocksize = btrfs_level_size(root, btrfs_root_level(&root->root_item));
        root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item),
                                     blocksize, generation);
-       if (!root->node || !extent_buffer_uptodate(root->node)) {
-               ret = (!root->node) ? -ENOMEM : -EIO;
-
-               free_extent_buffer(root->node);
-               kfree(root);
-               return ERR_PTR(ret);
+       if (!root->node) {
+               ret = -ENOMEM;
+               goto find_fail;
+       } else if (!btrfs_buffer_uptodate(root->node, generation, 0)) {
+               ret = -EIO;
+               goto read_fail;
        }
-
        root->commit_root = btrfs_root_node(root);
 out:
-       if (location->objectid != BTRFS_TREE_LOG_OBJECTID) {
+       btrfs_free_path(path);
+       return root;
+
+read_fail:
+       free_extent_buffer(root->node);
+find_fail:
+       kfree(root);
+alloc_fail:
+       root = ERR_PTR(ret);
+       goto out;
+}
+
+struct btrfs_root *btrfs_read_fs_root(struct btrfs_root *tree_root,
+                                     struct btrfs_key *location)
+{
+       struct btrfs_root *root;
+
+       root = btrfs_read_tree_root(tree_root, location);
+       if (IS_ERR(root))
+               return root;
+
+       if (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID) {
                root->ref_cows = 1;
                btrfs_check_and_init_root_item(&root->root_item);
        }
@@ -1522,6 +1492,66 @@ out:
        return root;
 }
 
+int btrfs_init_fs_root(struct btrfs_root *root)
+{
+       int ret;
+
+       root->free_ino_ctl = kzalloc(sizeof(*root->free_ino_ctl), GFP_NOFS);
+       root->free_ino_pinned = kzalloc(sizeof(*root->free_ino_pinned),
+                                       GFP_NOFS);
+       if (!root->free_ino_pinned || !root->free_ino_ctl) {
+               ret = -ENOMEM;
+               goto fail;
+       }
+
+       btrfs_init_free_ino_ctl(root);
+       mutex_init(&root->fs_commit_mutex);
+       spin_lock_init(&root->cache_lock);
+       init_waitqueue_head(&root->cache_wait);
+
+       ret = get_anon_bdev(&root->anon_dev);
+       if (ret)
+               goto fail;
+       return 0;
+fail:
+       kfree(root->free_ino_ctl);
+       kfree(root->free_ino_pinned);
+       return ret;
+}
+
+struct btrfs_root *btrfs_lookup_fs_root(struct btrfs_fs_info *fs_info,
+                                       u64 root_id)
+{
+       struct btrfs_root *root;
+
+       spin_lock(&fs_info->fs_roots_radix_lock);
+       root = radix_tree_lookup(&fs_info->fs_roots_radix,
+                                (unsigned long)root_id);
+       spin_unlock(&fs_info->fs_roots_radix_lock);
+       return root;
+}
+
+int btrfs_insert_fs_root(struct btrfs_fs_info *fs_info,
+                        struct btrfs_root *root)
+{
+       int ret;
+
+       ret = radix_tree_preload(GFP_NOFS & ~__GFP_HIGHMEM);
+       if (ret)
+               return ret;
+
+       spin_lock(&fs_info->fs_roots_radix_lock);
+       ret = radix_tree_insert(&fs_info->fs_roots_radix,
+                               (unsigned long)root->root_key.objectid,
+                               root);
+       if (ret == 0)
+               root->in_radix = 1;
+       spin_unlock(&fs_info->fs_roots_radix_lock);
+       radix_tree_preload_end();
+
+       return ret;
+}
+
 struct btrfs_root *btrfs_read_fs_root_no_name(struct btrfs_fs_info *fs_info,
                                              struct btrfs_key *location)
 {
@@ -1542,58 +1572,30 @@ struct btrfs_root *btrfs_read_fs_root_no_name(struct btrfs_fs_info *fs_info,
                return fs_info->quota_root ? fs_info->quota_root :
                                             ERR_PTR(-ENOENT);
 again:
-       spin_lock(&fs_info->fs_roots_radix_lock);
-       root = radix_tree_lookup(&fs_info->fs_roots_radix,
-                                (unsigned long)location->objectid);
-       spin_unlock(&fs_info->fs_roots_radix_lock);
+       root = btrfs_lookup_fs_root(fs_info, location->objectid);
        if (root)
                return root;
 
-       root = btrfs_read_fs_root_no_radix(fs_info->tree_root, location);
+       root = btrfs_read_fs_root(fs_info->tree_root, location);
        if (IS_ERR(root))
                return root;
 
-       root->free_ino_ctl = kzalloc(sizeof(*root->free_ino_ctl), GFP_NOFS);
-       root->free_ino_pinned = kzalloc(sizeof(*root->free_ino_pinned),
-                                       GFP_NOFS);
-       if (!root->free_ino_pinned || !root->free_ino_ctl) {
-               ret = -ENOMEM;
+       if (btrfs_root_refs(&root->root_item) == 0) {
+               ret = -ENOENT;
                goto fail;
        }
 
-       btrfs_init_free_ino_ctl(root);
-       mutex_init(&root->fs_commit_mutex);
-       spin_lock_init(&root->cache_lock);
-       init_waitqueue_head(&root->cache_wait);
-
-       ret = get_anon_bdev(&root->anon_dev);
+       ret = btrfs_init_fs_root(root);
        if (ret)
                goto fail;
 
-       if (btrfs_root_refs(&root->root_item) == 0) {
-               ret = -ENOENT;
-               goto fail;
-       }
-
        ret = btrfs_find_orphan_item(fs_info->tree_root, location->objectid);
        if (ret < 0)
                goto fail;
        if (ret == 0)
                root->orphan_item_inserted = 1;
 
-       ret = radix_tree_preload(GFP_NOFS & ~__GFP_HIGHMEM);
-       if (ret)
-               goto fail;
-
-       spin_lock(&fs_info->fs_roots_radix_lock);
-       ret = radix_tree_insert(&fs_info->fs_roots_radix,
-                               (unsigned long)root->root_key.objectid,
-                               root);
-       if (ret == 0)
-               root->in_radix = 1;
-
-       spin_unlock(&fs_info->fs_roots_radix_lock);
-       radix_tree_preload_end();
+       ret = btrfs_insert_fs_root(fs_info, root);
        if (ret) {
                if (ret == -EEXIST) {
                        free_fs_root(root);
@@ -1601,10 +1603,6 @@ again:
                }
                goto fail;
        }
-
-       ret = btrfs_find_dead_roots(fs_info->tree_root,
-                                   root->root_key.objectid);
-       WARN_ON(ret);
        return root;
 fail:
        free_fs_root(root);
@@ -2050,7 +2048,7 @@ static void del_fs_roots(struct btrfs_fs_info *fs_info)
                list_del(&gang[0]->root_list);
 
                if (gang[0]->in_radix) {
-                       btrfs_free_fs_root(fs_info, gang[0]);
+                       btrfs_drop_and_free_fs_root(fs_info, gang[0]);
                } else {
                        free_extent_buffer(gang[0]->node);
                        free_extent_buffer(gang[0]->commit_root);
@@ -2065,7 +2063,7 @@ static void del_fs_roots(struct btrfs_fs_info *fs_info)
                if (!ret)
                        break;
                for (i = 0; i < ret; i++)
-                       btrfs_free_fs_root(fs_info, gang[i]);
+                       btrfs_drop_and_free_fs_root(fs_info, gang[i]);
        }
 }
 
@@ -2097,14 +2095,8 @@ int open_ctree(struct super_block *sb,
        int backup_index = 0;
 
        tree_root = fs_info->tree_root = btrfs_alloc_root(fs_info);
-       extent_root = fs_info->extent_root = btrfs_alloc_root(fs_info);
-       csum_root = fs_info->csum_root = btrfs_alloc_root(fs_info);
        chunk_root = fs_info->chunk_root = btrfs_alloc_root(fs_info);
-       dev_root = fs_info->dev_root = btrfs_alloc_root(fs_info);
-       quota_root = fs_info->quota_root = btrfs_alloc_root(fs_info);
-
-       if (!tree_root || !extent_root || !csum_root ||
-           !chunk_root || !dev_root || !quota_root) {
+       if (!tree_root || !chunk_root) {
                err = -ENOMEM;
                goto fail;
        }
@@ -2655,33 +2647,44 @@ retry_root_backup:
        btrfs_set_root_node(&tree_root->root_item, tree_root->node);
        tree_root->commit_root = btrfs_root_node(tree_root);
 
-       ret = find_and_setup_root(tree_root, fs_info,
-                                 BTRFS_EXTENT_TREE_OBJECTID, extent_root);
-       if (ret)
+       location.objectid = BTRFS_EXTENT_TREE_OBJECTID;
+       location.type = BTRFS_ROOT_ITEM_KEY;
+       location.offset = 0;
+
+       extent_root = btrfs_read_tree_root(tree_root, &location);
+       if (IS_ERR(extent_root)) {
+               ret = PTR_ERR(extent_root);
                goto recovery_tree_root;
+       }
        extent_root->track_dirty = 1;
+       fs_info->extent_root = extent_root;
 
-       ret = find_and_setup_root(tree_root, fs_info,
-                                 BTRFS_DEV_TREE_OBJECTID, dev_root);
-       if (ret)
+       location.objectid = BTRFS_DEV_TREE_OBJECTID;
+       dev_root = btrfs_read_tree_root(tree_root, &location);
+       if (IS_ERR(dev_root)) {
+               ret = PTR_ERR(dev_root);
                goto recovery_tree_root;
+       }
        dev_root->track_dirty = 1;
+       fs_info->dev_root = dev_root;
+       btrfs_init_devices_late(fs_info);
 
-       ret = find_and_setup_root(tree_root, fs_info,
-                                 BTRFS_CSUM_TREE_OBJECTID, csum_root);
-       if (ret)
+       location.objectid = BTRFS_CSUM_TREE_OBJECTID;
+       csum_root = btrfs_read_tree_root(tree_root, &location);
+       if (IS_ERR(csum_root)) {
+               ret = PTR_ERR(csum_root);
                goto recovery_tree_root;
+       }
        csum_root->track_dirty = 1;
+       fs_info->csum_root = csum_root;
 
-       ret = find_and_setup_root(tree_root, fs_info,
-                                 BTRFS_QUOTA_TREE_OBJECTID, quota_root);
-       if (ret) {
-               kfree(quota_root);
-               quota_root = fs_info->quota_root = NULL;
-       } else {
+       location.objectid = BTRFS_QUOTA_TREE_OBJECTID;
+       quota_root = btrfs_read_tree_root(tree_root, &location);
+       if (!IS_ERR(quota_root)) {
                quota_root->track_dirty = 1;
                fs_info->quota_enabled = 1;
                fs_info->pending_quota_state = 1;
+               fs_info->quota_root = quota_root;
        }
 
        fs_info->generation = generation;
@@ -2834,7 +2837,7 @@ retry_root_backup:
 
        location.objectid = BTRFS_FS_TREE_OBJECTID;
        location.type = BTRFS_ROOT_ITEM_KEY;
-       location.offset = (u64)-1;
+       location.offset = 0;
 
        fs_info->fs_root = btrfs_read_fs_root_no_name(fs_info, &location);
        if (IS_ERR(fs_info->fs_root)) {
@@ -3381,7 +3384,9 @@ int write_ctree_super(struct btrfs_trans_handle *trans,
        return ret;
 }
 
-void btrfs_free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root)
+/* Drop a fs root from the radix tree and free it. */
+void btrfs_drop_and_free_fs_root(struct btrfs_fs_info *fs_info,
+                                 struct btrfs_root *root)
 {
        spin_lock(&fs_info->fs_roots_radix_lock);
        radix_tree_delete(&fs_info->fs_roots_radix,
@@ -3415,6 +3420,11 @@ static void free_fs_root(struct btrfs_root *root)
        kfree(root);
 }
 
+void btrfs_free_fs_root(struct btrfs_root *root)
+{
+       free_fs_root(root);
+}
+
 int btrfs_cleanup_fs_roots(struct btrfs_fs_info *fs_info)
 {
        u64 root_objectid = 0;
index be69ce1b07a22ac83a2dedd808be0e6d20040333..534d583e609db9cbb4686461057d27412750d45f 100644 (file)
@@ -63,14 +63,19 @@ struct buffer_head *btrfs_read_dev_super(struct block_device *bdev);
 int btrfs_commit_super(struct btrfs_root *root);
 struct extent_buffer *btrfs_find_tree_block(struct btrfs_root *root,
                                            u64 bytenr, u32 blocksize);
-struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_root *tree_root,
-                                              struct btrfs_key *location);
+struct btrfs_root *btrfs_read_fs_root(struct btrfs_root *tree_root,
+                                     struct btrfs_key *location);
+int btrfs_init_fs_root(struct btrfs_root *root);
+int btrfs_insert_fs_root(struct btrfs_fs_info *fs_info,
+                        struct btrfs_root *root);
 struct btrfs_root *btrfs_read_fs_root_no_name(struct btrfs_fs_info *fs_info,
                                              struct btrfs_key *location);
 int btrfs_cleanup_fs_roots(struct btrfs_fs_info *fs_info);
 void btrfs_btree_balance_dirty(struct btrfs_root *root);
 void btrfs_btree_balance_dirty_nodelay(struct btrfs_root *root);
-void btrfs_free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root);
+void btrfs_drop_and_free_fs_root(struct btrfs_fs_info *fs_info,
+                                struct btrfs_root *root);
+void btrfs_free_fs_root(struct btrfs_root *root);
 void btrfs_mark_buffer_dirty(struct extent_buffer *buf);
 int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid,
                          int atomic);
index b55b5fb0eb29de067ca8b3c5a9a9a6928402e537..c989fe602fafb47aa8e15ca3ebb4c71104c3efb9 100644 (file)
@@ -7447,8 +7447,8 @@ int btrfs_drop_snapshot(struct btrfs_root *root,
        }
 
        if (root->root_key.objectid != BTRFS_TREE_RELOC_OBJECTID) {
-               ret = btrfs_find_last_root(tree_root, root->root_key.objectid,
-                                          NULL, NULL);
+               ret = btrfs_find_root(tree_root, &root->root_key, path,
+                                     NULL, NULL);
                if (ret < 0) {
                        btrfs_abort_transaction(trans, tree_root, ret);
                        err = ret;
@@ -7465,7 +7465,7 @@ int btrfs_drop_snapshot(struct btrfs_root *root,
        }
 
        if (root->in_radix) {
-               btrfs_free_fs_root(tree_root->fs_info, root);
+               btrfs_drop_and_free_fs_root(tree_root->fs_info, root);
        } else {
                free_extent_buffer(root->node);
                free_extent_buffer(root->commit_root);
index 4febca4fc2de7fe79fb9239a5e44f9ce3ad4eba0..f46b4cca4fa2ccd8e92ea3d4f788a5a1996e285a 100644 (file)
@@ -1355,8 +1355,7 @@ static struct btrfs_root *create_reloc_root(struct btrfs_trans_handle *trans,
        BUG_ON(ret);
        kfree(root_item);
 
-       reloc_root = btrfs_read_fs_root_no_radix(root->fs_info->tree_root,
-                                                &root_key);
+       reloc_root = btrfs_read_fs_root(root->fs_info->tree_root, &root_key);
        BUG_ON(IS_ERR(reloc_root));
        reloc_root->last_trans = trans->transid;
        return reloc_root;
@@ -4277,7 +4276,7 @@ int btrfs_recover_relocation(struct btrfs_root *root)
                    key.type != BTRFS_ROOT_ITEM_KEY)
                        break;
 
-               reloc_root = btrfs_read_fs_root_no_radix(root, &key);
+               reloc_root = btrfs_read_fs_root(root, &key);
                if (IS_ERR(reloc_root)) {
                        err = PTR_ERR(reloc_root);
                        goto out;
index 5bf1ed57f178ea60b7ca8e98aceb6710fc9f55c4..79e683273de5c94ae350859a0757973e95156dc2 100644 (file)
@@ -64,52 +64,59 @@ void btrfs_read_root_item(struct extent_buffer *eb, int slot,
 }
 
 /*
- * lookup the root with the highest offset for a given objectid.  The key we do
- * find is copied into 'key'.  If we find something return 0, otherwise 1, < 0
- * on error.
+ * btrfs_find_root - lookup the root by the key.
+ * root: the root of the root tree
+ * search_key: the key to search
+ * path: the path we search
+ * root_item: the root item of the tree we look for
+ * root_key: the reak key of the tree we look for
+ *
+ * If ->offset of 'seach_key' is -1ULL, it means we are not sure the offset
+ * of the search key, just lookup the root with the highest offset for a
+ * given objectid.
+ *
+ * If we find something return 0, otherwise > 0, < 0 on error.
  */
-int btrfs_find_last_root(struct btrfs_root *root, u64 objectid,
-                       struct btrfs_root_item *item, struct btrfs_key *key)
+int btrfs_find_root(struct btrfs_root *root, struct btrfs_key *search_key,
+                   struct btrfs_path *path, struct btrfs_root_item *root_item,
+                   struct btrfs_key *root_key)
 {
-       struct btrfs_path *path;
-       struct btrfs_key search_key;
        struct btrfs_key found_key;
        struct extent_buffer *l;
        int ret;
        int slot;
 
-       search_key.objectid = objectid;
-       search_key.type = BTRFS_ROOT_ITEM_KEY;
-       search_key.offset = (u64)-1;
-
-       path = btrfs_alloc_path();
-       if (!path)
-               return -ENOMEM;
-       ret = btrfs_search_slot(NULL, root, &search_key, path, 0, 0);
+       ret = btrfs_search_slot(NULL, root, search_key, path, 0, 0);
        if (ret < 0)
-               goto out;
+               return ret;
 
-       BUG_ON(ret == 0);
-       if (path->slots[0] == 0) {
-               ret = 1;
-               goto out;
+       if (search_key->offset != -1ULL) {      /* the search key is exact */
+               if (ret > 0)
+                       goto out;
+       } else {
+               BUG_ON(ret == 0);               /* Logical error */
+               if (path->slots[0] == 0)
+                       goto out;
+               path->slots[0]--;
+               ret = 0;
        }
+
        l = path->nodes[0];
-       slot = path->slots[0] - 1;
+       slot = path->slots[0];
+
        btrfs_item_key_to_cpu(l, &found_key, slot);
-       if (found_key.objectid != objectid ||
+       if (found_key.objectid != search_key->objectid ||
            found_key.type != BTRFS_ROOT_ITEM_KEY) {
                ret = 1;
                goto out;
        }
-       if (item)
-               btrfs_read_root_item(l, slot, item);
-       if (key)
-               memcpy(key, &found_key, sizeof(found_key));
 
-       ret = 0;
+       if (root_item)
+               btrfs_read_root_item(l, slot, root_item);
+       if (root_key)
+               memcpy(root_key, &found_key, sizeof(found_key));
 out:
-       btrfs_free_path(path);
+       btrfs_release_path(path);
        return ret;
 }
 
@@ -212,86 +219,6 @@ int btrfs_insert_root(struct btrfs_trans_handle *trans, struct btrfs_root *root,
        return btrfs_insert_item(trans, root, key, item, sizeof(*item));
 }
 
-/*
- * at mount time we want to find all the old transaction snapshots that were in
- * the process of being deleted if we crashed.  This is any root item with an
- * offset lower than the latest root.  They need to be queued for deletion to
- * finish what was happening when we crashed.
- */
-int btrfs_find_dead_roots(struct btrfs_root *root, u64 objectid)
-{
-       struct btrfs_root *dead_root;
-       struct btrfs_root_item *ri;
-       struct btrfs_key key;
-       struct btrfs_key found_key;
-       struct btrfs_path *path;
-       int ret;
-       u32 nritems;
-       struct extent_buffer *leaf;
-       int slot;
-
-       key.objectid = objectid;
-       btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY);
-       key.offset = 0;
-       path = btrfs_alloc_path();
-       if (!path)
-               return -ENOMEM;
-
-again:
-       ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
-       if (ret < 0)
-               goto err;
-       while (1) {
-               leaf = path->nodes[0];
-               nritems = btrfs_header_nritems(leaf);
-               slot = path->slots[0];
-               if (slot >= nritems) {
-                       ret = btrfs_next_leaf(root, path);
-                       if (ret)
-                               break;
-                       leaf = path->nodes[0];
-                       nritems = btrfs_header_nritems(leaf);
-                       slot = path->slots[0];
-               }
-               btrfs_item_key_to_cpu(leaf, &key, slot);
-               if (btrfs_key_type(&key) != BTRFS_ROOT_ITEM_KEY)
-                       goto next;
-
-               if (key.objectid < objectid)
-                       goto next;
-
-               if (key.objectid > objectid)
-                       break;
-
-               ri = btrfs_item_ptr(leaf, slot, struct btrfs_root_item);
-               if (btrfs_disk_root_refs(leaf, ri) != 0)
-                       goto next;
-
-               memcpy(&found_key, &key, sizeof(key));
-               key.offset++;
-               btrfs_release_path(path);
-               dead_root =
-                       btrfs_read_fs_root_no_radix(root->fs_info->tree_root,
-                                                   &found_key);
-               if (IS_ERR(dead_root)) {
-                       ret = PTR_ERR(dead_root);
-                       goto err;
-               }
-
-               ret = btrfs_add_dead_root(dead_root);
-               if (ret)
-                       goto err;
-               goto again;
-next:
-               slot++;
-               path->slots[0]++;
-       }
-       ret = 0;
-err:
-       btrfs_free_path(path);
-       return ret;
-}
-
 int btrfs_find_orphan_roots(struct btrfs_root *tree_root)
 {
        struct extent_buffer *leaf;
@@ -340,20 +267,29 @@ int btrfs_find_orphan_roots(struct btrfs_root *tree_root)
                root_key.objectid = key.offset;
                key.offset++;
 
-               root = btrfs_read_fs_root_no_name(tree_root->fs_info,
-                                                 &root_key);
-               if (!IS_ERR(root))
+               root = btrfs_read_fs_root(tree_root, &root_key);
+               if (IS_ERR(root)) {
+                       err = PTR_ERR(root);
+                       break;
+               }
+
+               if (btrfs_root_refs(&root->root_item) == 0) {
+                       btrfs_add_dead_root(root);
                        continue;
+               }
 
-               ret = PTR_ERR(root);
-               if (ret != -ENOENT) {
-                       err = ret;
+               err = btrfs_init_fs_root(root);
+               if (err) {
+                       btrfs_free_fs_root(root);
                        break;
                }
 
-               ret = btrfs_find_dead_roots(tree_root, root_key.objectid);
-               if (ret) {
-                       err = ret;
+               root->orphan_item_inserted = 1;
+
+               err = btrfs_insert_fs_root(root->fs_info, root);
+               if (err) {
+                       BUG_ON(err == -EEXIST);
+                       btrfs_free_fs_root(root);
                        break;
                }
        }
index c276ac9a0ec338c86973a752d74b9e93d22cc9a8..a59724e6c9f5788de946de5b82ebab9c3745e244 100644 (file)
@@ -4016,8 +4016,7 @@ again:
                if (found_key.objectid != BTRFS_TREE_LOG_OBJECTID)
                        break;
 
-               log = btrfs_read_fs_root_no_radix(log_root_tree,
-                                                 &found_key);
+               log = btrfs_read_fs_root(log_root_tree, &found_key);
                if (IS_ERR(log)) {
                        ret = PTR_ERR(log);
                        btrfs_error(fs_info, ret,
index 24940085cdac342be50083a3be8b505d57c67516..440de708f9eb522937e8a843048fb8040c15b905 100644 (file)
@@ -5367,7 +5367,6 @@ static struct btrfs_device *add_missing_dev(struct btrfs_root *root,
                return NULL;
        list_add(&device->dev_list,
                 &fs_devices->devices);
-       device->dev_root = root->fs_info->dev_root;
        device->devid = devid;
        device->work.func = pending_bios_fn;
        device->fs_devices = fs_devices;
@@ -5593,7 +5592,6 @@ static int read_one_dev(struct btrfs_root *root,
        }
 
        fill_device_from_item(leaf, dev_item, device);
-       device->dev_root = root->fs_info->dev_root;
        device->in_fs_metadata = 1;
        if (device->writeable && !device->is_tgtdev_for_dev_replace) {
                device->fs_devices->total_rw_bytes += device->total_bytes;
@@ -5751,6 +5749,17 @@ error:
        return ret;
 }
 
+void btrfs_init_devices_late(struct btrfs_fs_info *fs_info)
+{
+       struct btrfs_fs_devices *fs_devices = fs_info->fs_devices;
+       struct btrfs_device *device;
+
+       mutex_lock(&fs_devices->device_list_mutex);
+       list_for_each_entry(device, &fs_devices->devices, dev_list)
+               device->dev_root = fs_info->dev_root;
+       mutex_unlock(&fs_devices->device_list_mutex);
+}
+
 static void __btrfs_reset_dev_stats(struct btrfs_device *dev)
 {
        int i;
index f6247e2a47f7b643d8c88f2ee4c5b53f5c79f043..857acd34ccde6c6853a434cd1343ceb114031433 100644 (file)
@@ -321,6 +321,7 @@ int find_free_dev_extent(struct btrfs_device *device, u64 num_bytes,
 void btrfs_dev_stat_inc_and_print(struct btrfs_device *dev, int index);
 int btrfs_get_dev_stats(struct btrfs_root *root,
                        struct btrfs_ioctl_get_dev_stats *stats);
+void btrfs_init_devices_late(struct btrfs_fs_info *fs_info);
 int btrfs_init_dev_stats(struct btrfs_fs_info *fs_info);
 int btrfs_run_dev_stats(struct btrfs_trans_handle *trans,
                        struct btrfs_fs_info *fs_info);