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=15055 Signed-off-by: Zhong, Xin <xin.zhong@intel.com> Signed-off-by: Chris Mason <chris.mason@oracle.com>
This commit is contained in:
parent
13f2696f1d
commit
e15d054242
@ -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 = {
|
|||||||
{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)
|
|||||||
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)
|
|||||||
*/
|
*/
|
||||||
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,
|
|||||||
*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,
|
|||||||
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,
|
|||||||
|
|
||||||
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,
|
|||||||
s->s_flags |= MS_ACTIVE;
|
s->s_flags |= MS_ACTIVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
root = get_default_root(s, subvol_objectid);
|
|
||||||
if (IS_ERR(root)) {
|
|
||||||
error = PTR_ERR(root);
|
|
||||||
deactivate_locked_super(s);
|
|
||||||
goto error_free_subvol_name;
|
|
||||||
}
|
|
||||||
/* if they gave us a subvolume name bind mount into that */
|
/* if they gave us a subvolume name bind mount into that */
|
||||||
if (strcmp(subvol_name, ".")) {
|
if (strcmp(subvol_name, ".")) {
|
||||||
struct dentry *new_root;
|
struct dentry *new_root;
|
||||||
|
|
||||||
|
root = get_default_root(s, subvol_rootid);
|
||||||
|
if (IS_ERR(root)) {
|
||||||
|
error = PTR_ERR(root);
|
||||||
|
deactivate_locked_super(s);
|
||||||
|
goto error_free_subvol_name;
|
||||||
|
}
|
||||||
|
|
||||||
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,
|
|||||||
}
|
}
|
||||||
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);
|
||||||
|
Loading…
Reference in New Issue
Block a user