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: David Sterba <dsterba@suse.cz>
Signed-off-by: Omar Sandoval <osandov@osandov.com>
Signed-off-by: Chris Mason <clm@fb.com>
This commit is contained in:
Omar Sandoval 2015-05-18 02:16:28 -07:00 committed by Chris Mason
parent e6e4dbe894
commit fa33065950

View File

@ -1171,55 +1171,61 @@ static struct dentry *mount_subvol(const char *subvol_name, int flags,
const char *device_name, char *data)
{
struct dentry *root;
struct vfsmount *mnt;
struct vfsmount *mnt = NULL;
char *newargs;
int ret;
newargs = setup_root_args(data);
if (!newargs)
return ERR_PTR(-ENOMEM);
mnt = vfs_kern_mount(&btrfs_fs_type, flags, device_name,
newargs);
if (!newargs) {
root = ERR_PTR(-ENOMEM);
goto out;
}
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) {
mnt = vfs_kern_mount(&btrfs_fs_type, flags & ~MS_RDONLY, device_name,
newargs);
mnt = vfs_kern_mount(&btrfs_fs_type, flags & ~MS_RDONLY,
device_name, newargs);
} else {
int r;
mnt = vfs_kern_mount(&btrfs_fs_type, flags | MS_RDONLY, device_name,
newargs);
mnt = vfs_kern_mount(&btrfs_fs_type, flags | MS_RDONLY,
device_name, newargs);
if (IS_ERR(mnt)) {
kfree(newargs);
return ERR_CAST(mnt);
root = ERR_CAST(mnt);
mnt = NULL;
goto out;
}
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);
if (r < 0) {
/* FIXME: release vfsmount mnt ??*/
kfree(newargs);
return ERR_PTR(r);
if (ret < 0) {
root = ERR_PTR(ret);
goto out;
}
}
}
kfree(newargs);
if (IS_ERR(mnt))
return ERR_CAST(mnt);
if (IS_ERR(mnt)) {
root = ERR_CAST(mnt);
mnt = NULL;
goto out;
}
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))) {
struct super_block *s = root->d_sb;
dput(root);
root = ERR_PTR(-EINVAL);
deactivate_locked_super(s);
printk(KERN_ERR "BTRFS: '%s' is not a valid subvolume\n",
subvol_name);
pr_err("BTRFS: '%s' is not a valid subvolume\n", subvol_name);
}
out:
mntput(mnt);
kfree(newargs);
kfree(subvol_name);
return root;
}
@ -1305,9 +1311,8 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
}
if (subvol_name) {
root = mount_subvol(subvol_name, flags, device_name, data);
kfree(subvol_name);
return root;
/* mount_subvol() will free subvol_name. */
return mount_subvol(subvol_name, flags, device_name, data);
}
security_init_mnt_opts(&new_sec_opts);