aboutsummaryrefslogtreecommitdiff
path: root/fs/btrfs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs')
-rw-r--r--fs/btrfs/disk-io.c38
1 files changed, 35 insertions, 3 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 349411c3ccd..12f9579fcf9 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -804,6 +804,30 @@ static int setup_root_or_create_block(struct btrfs_fs_info *fs_info,
return 0;
}
+static int get_default_subvolume(struct btrfs_fs_info *fs_info,
+ struct btrfs_key *key_ret)
+{
+ struct btrfs_root *root = fs_info->tree_root;
+ struct btrfs_dir_item *dir_item;
+ struct btrfs_path path;
+ int ret = 0;
+
+ btrfs_init_path(&path);
+
+ dir_item = btrfs_lookup_dir_item(NULL, root, &path,
+ BTRFS_ROOT_TREE_DIR_OBJECTID,
+ "default", 7, 0);
+ if (IS_ERR(dir_item)) {
+ ret = PTR_ERR(dir_item);
+ goto out;
+ }
+
+ btrfs_dir_item_key_to_cpu(path.nodes[0], dir_item, key_ret);
+out:
+ btrfs_release_path(&path);
+ return ret;
+}
+
int btrfs_setup_all_roots(struct btrfs_fs_info *fs_info)
{
struct btrfs_super_block *sb = fs_info->super_copy;
@@ -833,9 +857,17 @@ int btrfs_setup_all_roots(struct btrfs_fs_info *fs_info)
fs_info->last_trans_committed = generation;
- key.objectid = BTRFS_FS_TREE_OBJECTID;
- key.type = BTRFS_ROOT_ITEM_KEY;
- key.offset = (u64)-1;
+ ret = get_default_subvolume(fs_info, &key);
+ if (ret) {
+ /*
+ * The default dir item isn't there. Linux kernel behaviour is
+ * to silently use the top-level subvolume in this case.
+ */
+ key.objectid = BTRFS_FS_TREE_OBJECTID;
+ key.type = BTRFS_ROOT_ITEM_KEY;
+ key.offset = (u64)-1;
+ }
+
fs_info->fs_root = btrfs_read_fs_root(fs_info, &key);
if (IS_ERR(fs_info->fs_root))