diff options
-rw-r--r-- | fs/btrfs/disk-io.c | 38 |
1 files changed, 35 insertions, 3 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 349411c3cc..12f9579fcf 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)) |