Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+33 −28
Original line number Original line Diff line number Diff line
@@ -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,
	}
	}


	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);