Commit e15d0542 authored by Xin Zhong's avatar Xin Zhong Committed by Chris Mason

Btrfs: fix subvolume mount by name problem when default mount subvolume is set

We create two subvolumes (meego_root and meego_home) in
btrfs root directory. And set meego_root as default mount
subvolume. After we remount btrfs, meego_root is mounted
to top directory by default. Then when we try to mount
meego_home (subvol=meego_home) to a subdirectory, it failed.
The problem is when default mount subvolume is set to
meego_root, we search meego_home in meego_root but can not find
it. So the solution is to add a new mount option (subvolrootid)
to specify subvol id of root and search subvol name in it. For
our case, now we can use "-o subvolrootid=0,subvol=meego_home)
to mount meego_home.

Detail information can be found in meego bugzilla:
https://bugs.meego.com/show_bug.cgi?id=15055Signed-off-by: default avatarZhong, Xin <xin.zhong@intel.com>
Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
parent 13f2696f
...@@ -159,7 +159,7 @@ enum { ...@@ -159,7 +159,7 @@ enum {
Opt_compress_type, Opt_compress_force, Opt_compress_force_type, Opt_compress_type, Opt_compress_force, Opt_compress_force_type,
Opt_notreelog, Opt_ratio, Opt_flushoncommit, Opt_discard, Opt_notreelog, Opt_ratio, Opt_flushoncommit, Opt_discard,
Opt_space_cache, Opt_clear_cache, Opt_user_subvol_rm_allowed, Opt_space_cache, Opt_clear_cache, Opt_user_subvol_rm_allowed,
Opt_enospc_debug, Opt_err, Opt_enospc_debug, Opt_subvolrootid, Opt_err,
}; };
static match_table_t tokens = { static match_table_t tokens = {
...@@ -189,6 +189,7 @@ static match_table_t tokens = { ...@@ -189,6 +189,7 @@ static match_table_t tokens = {
{Opt_clear_cache, "clear_cache"}, {Opt_clear_cache, "clear_cache"},
{Opt_user_subvol_rm_allowed, "user_subvol_rm_allowed"}, {Opt_user_subvol_rm_allowed, "user_subvol_rm_allowed"},
{Opt_enospc_debug, "enospc_debug"}, {Opt_enospc_debug, "enospc_debug"},
{Opt_subvolrootid, "subvolrootid=%d"},
{Opt_err, NULL}, {Opt_err, NULL},
}; };
...@@ -232,6 +233,7 @@ int btrfs_parse_options(struct btrfs_root *root, char *options) ...@@ -232,6 +233,7 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
break; break;
case Opt_subvol: case Opt_subvol:
case Opt_subvolid: case Opt_subvolid:
case Opt_subvolrootid:
case Opt_device: case Opt_device:
/* /*
* These are parsed by btrfs_parse_early_options * These are parsed by btrfs_parse_early_options
...@@ -388,7 +390,7 @@ int btrfs_parse_options(struct btrfs_root *root, char *options) ...@@ -388,7 +390,7 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
*/ */
static int btrfs_parse_early_options(const char *options, fmode_t flags, static int btrfs_parse_early_options(const char *options, fmode_t flags,
void *holder, char **subvol_name, u64 *subvol_objectid, void *holder, char **subvol_name, u64 *subvol_objectid,
struct btrfs_fs_devices **fs_devices) u64 *subvol_rootid, struct btrfs_fs_devices **fs_devices)
{ {
substring_t args[MAX_OPT_ARGS]; substring_t args[MAX_OPT_ARGS];
char *opts, *orig, *p; char *opts, *orig, *p;
...@@ -429,6 +431,18 @@ static int btrfs_parse_early_options(const char *options, fmode_t flags, ...@@ -429,6 +431,18 @@ static int btrfs_parse_early_options(const char *options, fmode_t flags,
*subvol_objectid = intarg; *subvol_objectid = intarg;
} }
break; break;
case Opt_subvolrootid:
intarg = 0;
error = match_int(&args[0], &intarg);
if (!error) {
/* we want the original fs_tree */
if (!intarg)
*subvol_rootid =
BTRFS_FS_TREE_OBJECTID;
else
*subvol_rootid = intarg;
}
break;
case Opt_device: case Opt_device:
error = btrfs_scan_one_device(match_strdup(&args[0]), error = btrfs_scan_one_device(match_strdup(&args[0]),
flags, holder, fs_devices); flags, holder, fs_devices);
...@@ -736,6 +750,7 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags, ...@@ -736,6 +750,7 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
fmode_t mode = FMODE_READ; fmode_t mode = FMODE_READ;
char *subvol_name = NULL; char *subvol_name = NULL;
u64 subvol_objectid = 0; u64 subvol_objectid = 0;
u64 subvol_rootid = 0;
int error = 0; int error = 0;
if (!(flags & MS_RDONLY)) if (!(flags & MS_RDONLY))
...@@ -743,7 +758,7 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags, ...@@ -743,7 +758,7 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
error = btrfs_parse_early_options(data, mode, fs_type, error = btrfs_parse_early_options(data, mode, fs_type,
&subvol_name, &subvol_objectid, &subvol_name, &subvol_objectid,
&fs_devices); &subvol_rootid, &fs_devices);
if (error) if (error)
return ERR_PTR(error); return ERR_PTR(error);
...@@ -807,15 +822,17 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags, ...@@ -807,15 +822,17 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
s->s_flags |= MS_ACTIVE; s->s_flags |= MS_ACTIVE;
} }
root = get_default_root(s, subvol_objectid); /* if they gave us a subvolume name bind mount into that */
if (strcmp(subvol_name, ".")) {
struct dentry *new_root;
root = get_default_root(s, subvol_rootid);
if (IS_ERR(root)) { if (IS_ERR(root)) {
error = PTR_ERR(root); error = PTR_ERR(root);
deactivate_locked_super(s); deactivate_locked_super(s);
goto error_free_subvol_name; goto error_free_subvol_name;
} }
/* if they gave us a subvolume name bind mount into that */
if (strcmp(subvol_name, ".")) {
struct dentry *new_root;
mutex_lock(&root->d_inode->i_mutex); mutex_lock(&root->d_inode->i_mutex);
new_root = lookup_one_len(subvol_name, root, new_root = lookup_one_len(subvol_name, root,
strlen(subvol_name)); strlen(subvol_name));
...@@ -836,6 +853,13 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags, ...@@ -836,6 +853,13 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
} }
dput(root); dput(root);
root = new_root; root = new_root;
} else {
root = get_default_root(s, subvol_objectid);
if (IS_ERR(root)) {
error = PTR_ERR(root);
deactivate_locked_super(s);
goto error_free_subvol_name;
}
} }
kfree(subvol_name); kfree(subvol_name);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment