Commit fa330659 authored by Omar Sandoval's avatar Omar Sandoval Committed by Chris Mason

Btrfs: clean up error handling in mount_subvol()

In preparation for new functionality in mount_subvol(), give it
ownership of subvol_name and tidy up the error paths.
Reviewed-by: default avatarDavid Sterba <dsterba@suse.cz>
Signed-off-by: default avatarOmar Sandoval <osandov@osandov.com>
Signed-off-by: default avatarChris Mason <clm@fb.com>
parent e6e4dbe8
...@@ -1171,55 +1171,61 @@ static struct dentry *mount_subvol(const char *subvol_name, int flags, ...@@ -1171,55 +1171,61 @@ static struct dentry *mount_subvol(const char *subvol_name, int flags,
const char *device_name, char *data) const char *device_name, char *data)
{ {
struct dentry *root; struct dentry *root;
struct vfsmount *mnt; struct vfsmount *mnt = NULL;
char *newargs; char *newargs;
int ret;
newargs = setup_root_args(data); newargs = setup_root_args(data);
if (!newargs) if (!newargs) {
return ERR_PTR(-ENOMEM); root = ERR_PTR(-ENOMEM);
mnt = vfs_kern_mount(&btrfs_fs_type, flags, device_name, goto out;
newargs); }
if (PTR_RET(mnt) == -EBUSY) { mnt = vfs_kern_mount(&btrfs_fs_type, flags, device_name, newargs);
if (PTR_ERR_OR_ZERO(mnt) == -EBUSY) {
if (flags & MS_RDONLY) { if (flags & MS_RDONLY) {
mnt = vfs_kern_mount(&btrfs_fs_type, flags & ~MS_RDONLY, device_name, mnt = vfs_kern_mount(&btrfs_fs_type, flags & ~MS_RDONLY,
newargs); device_name, newargs);
} else { } else {
int r; mnt = vfs_kern_mount(&btrfs_fs_type, flags | MS_RDONLY,
mnt = vfs_kern_mount(&btrfs_fs_type, flags | MS_RDONLY, device_name, device_name, newargs);
newargs);
if (IS_ERR(mnt)) { if (IS_ERR(mnt)) {
kfree(newargs); root = ERR_CAST(mnt);
return ERR_CAST(mnt); mnt = NULL;
goto out;
} }
down_write(&mnt->mnt_sb->s_umount); down_write(&mnt->mnt_sb->s_umount);
r = btrfs_remount(mnt->mnt_sb, &flags, NULL); ret = btrfs_remount(mnt->mnt_sb, &flags, NULL);
up_write(&mnt->mnt_sb->s_umount); up_write(&mnt->mnt_sb->s_umount);
if (r < 0) { if (ret < 0) {
/* FIXME: release vfsmount mnt ??*/ root = ERR_PTR(ret);
kfree(newargs); goto out;
return ERR_PTR(r);
} }
} }
} }
if (IS_ERR(mnt)) {
kfree(newargs); root = ERR_CAST(mnt);
mnt = NULL;
if (IS_ERR(mnt)) goto out;
return ERR_CAST(mnt); }
root = mount_subtree(mnt, subvol_name); root = mount_subtree(mnt, subvol_name);
/* mount_subtree() drops our reference on the vfsmount. */
mnt = NULL;
if (!IS_ERR(root) && !is_subvolume_inode(d_inode(root))) { if (!IS_ERR(root) && !is_subvolume_inode(d_inode(root))) {
struct super_block *s = root->d_sb; struct super_block *s = root->d_sb;
dput(root); dput(root);
root = ERR_PTR(-EINVAL); root = ERR_PTR(-EINVAL);
deactivate_locked_super(s); deactivate_locked_super(s);
printk(KERN_ERR "BTRFS: '%s' is not a valid subvolume\n", pr_err("BTRFS: '%s' is not a valid subvolume\n", subvol_name);
subvol_name);
} }
out:
mntput(mnt);
kfree(newargs);
kfree(subvol_name);
return root; return root;
} }
...@@ -1305,9 +1311,8 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags, ...@@ -1305,9 +1311,8 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
} }
if (subvol_name) { if (subvol_name) {
root = mount_subvol(subvol_name, flags, device_name, data); /* mount_subvol() will free subvol_name. */
kfree(subvol_name); return mount_subvol(subvol_name, flags, device_name, data);
return root;
} }
security_init_mnt_opts(&new_sec_opts); security_init_mnt_opts(&new_sec_opts);
......
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