goto out;
 }
 
-static int btrfs_init_fs_root(struct btrfs_root *root)
+/*
+ * Initialize subvolume root in-memory structure
+ *
+ * @anon_dev:  anonymous device to attach to the root, if zero, allocate new
+ */
+static int btrfs_init_fs_root(struct btrfs_root *root, dev_t anon_dev)
 {
        int ret;
        unsigned int nofs_flag;
         */
        if (is_fstree(root->root_key.objectid) &&
            btrfs_root_refs(&root->root_item) > 0) {
-               ret = get_anon_bdev(&root->anon_dev);
-               if (ret)
-                       goto fail;
+               if (!anon_dev) {
+                       ret = get_anon_bdev(&root->anon_dev);
+                       if (ret)
+                               goto fail;
+               } else {
+                       root->anon_dev = anon_dev;
+               }
        }
 
        mutex_lock(&root->objectid_mutex);
 }
 
 
-struct btrfs_root *btrfs_get_fs_root(struct btrfs_fs_info *fs_info,
-                                    u64 objectid, bool check_ref)
+/*
+ * Get an in-memory reference of a root structure.
+ *
+ * For essential trees like root/extent tree, we grab it from fs_info directly.
+ * For subvolume trees, we check the cached filesystem roots first. If not
+ * found, then read it from disk and add it to cached fs roots.
+ *
+ * Caller should release the root by calling btrfs_put_root() after the usage.
+ *
+ * NOTE: Reloc and log trees can't be read by this function as they share the
+ *      same root objectid.
+ *
+ * @objectid:  root id
+ * @anon_dev:  preallocated anonymous block device number for new roots,
+ *             pass 0 for new allocation.
+ * @check_ref: whether to check root item references, If true, return -ENOENT
+ *             for orphan roots
+ */
+static struct btrfs_root *btrfs_get_root_ref(struct btrfs_fs_info *fs_info,
+                                            u64 objectid, dev_t anon_dev,
+                                            bool check_ref)
 {
        struct btrfs_root *root;
        struct btrfs_path *path;
 again:
        root = btrfs_lookup_fs_root(fs_info, objectid);
        if (root) {
+               /* Shouldn't get preallocated anon_dev for cached roots */
+               ASSERT(!anon_dev);
                if (check_ref && btrfs_root_refs(&root->root_item) == 0) {
                        btrfs_put_root(root);
                        return ERR_PTR(-ENOENT);
                goto fail;
        }
 
-       ret = btrfs_init_fs_root(root);
+       ret = btrfs_init_fs_root(root, anon_dev);
        if (ret)
                goto fail;
 
        return ERR_PTR(ret);
 }
 
+/*
+ * Get in-memory reference of a root structure
+ *
+ * @objectid:  tree objectid
+ * @check_ref: if set, verify that the tree exists and the item has at least
+ *             one reference
+ */
+struct btrfs_root *btrfs_get_fs_root(struct btrfs_fs_info *fs_info,
+                                    u64 objectid, bool check_ref)
+{
+       return btrfs_get_root_ref(fs_info, objectid, 0, check_ref);
+}
+
+/*
+ * Get in-memory reference of a root structure, created as new, optionally pass
+ * the anonymous block device id
+ *
+ * @objectid:  tree objectid
+ * @anon_dev:  if zero, allocate a new anonymous block device or use the
+ *             parameter value
+ */
+struct btrfs_root *btrfs_get_new_fs_root(struct btrfs_fs_info *fs_info,
+                                        u64 objectid, dev_t anon_dev)
+{
+       return btrfs_get_root_ref(fs_info, objectid, anon_dev, true);
+}
+
 static int btrfs_congested_fn(void *congested_data, int bdi_bits)
 {
        struct btrfs_fs_info *info = (struct btrfs_fs_info *)congested_data;
 
        struct inode *inode;
        int ret;
        int err;
+       dev_t anon_dev = 0;
        u64 objectid;
        u64 new_dirid = BTRFS_FIRST_FREE_OBJECTID;
        u64 index = 0;
        if (ret)
                goto fail_free;
 
+       ret = get_anon_bdev(&anon_dev);
+       if (ret < 0)
+               goto fail_free;
+
        /*
         * Don't create subvolume whose level is not zero. Or qgroup will be
         * screwed up since it assumes subvolume qgroup's level to be 0.
                goto fail;
 
        key.offset = (u64)-1;
-       new_root = btrfs_get_fs_root(fs_info, objectid, true);
+       new_root = btrfs_get_new_fs_root(fs_info, objectid, anon_dev);
        if (IS_ERR(new_root)) {
+               free_anon_bdev(anon_dev);
                ret = PTR_ERR(new_root);
                btrfs_abort_transaction(trans, ret);
                goto fail;
        }
+       /* Freeing will be done in btrfs_put_root() of new_root */
+       anon_dev = 0;
 
        btrfs_record_root_in_trans(trans, new_root);
 
        return ret;
 
 fail_free:
+       if (anon_dev)
+               free_anon_bdev(anon_dev);
        kfree(root_item);
        return ret;
 }
        if (!pending_snapshot)
                return -ENOMEM;
 
+       ret = get_anon_bdev(&pending_snapshot->anon_dev);
+       if (ret < 0)
+               goto free_pending;
        pending_snapshot->root_item = kzalloc(sizeof(struct btrfs_root_item),
                        GFP_KERNEL);
        pending_snapshot->path = btrfs_alloc_path();
 
        d_instantiate(dentry, inode);
        ret = 0;
+       pending_snapshot->anon_dev = 0;
 fail:
+       /* Prevent double freeing of anon_dev */
+       if (ret && pending_snapshot->snap)
+               pending_snapshot->snap->anon_dev = 0;
        btrfs_put_root(pending_snapshot->snap);
        btrfs_subvolume_release_metadata(fs_info, &pending_snapshot->block_rsv);
 free_pending:
+       if (pending_snapshot->anon_dev)
+               free_anon_bdev(pending_snapshot->anon_dev);
        kfree(pending_snapshot->root_item);
        btrfs_free_path(pending_snapshot->path);
        kfree(pending_snapshot);