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

Commit 1ba10681 authored by Al Viro's avatar Al Viro
Browse files

switch do_spufs_create() to user_path_create(), fix double-unlock



Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent dae6ad8f
Loading
Loading
Loading
Loading
+11 −18
Original line number Diff line number Diff line
@@ -611,15 +611,14 @@ static int spufs_create_gang(struct inode *inode,

static struct file_system_type spufs_type;

long spufs_create(struct nameidata *nd, unsigned int flags, mode_t mode,
							struct file *filp)
long spufs_create(struct path *path, struct dentry *dentry,
		unsigned int flags, mode_t mode, struct file *filp)
{
	struct dentry *dentry;
	int ret;

	ret = -EINVAL;
	/* check if we are on spufs */
	if (nd->path.dentry->d_sb->s_type != &spufs_type)
	if (path->dentry->d_sb->s_type != &spufs_type)
		goto out;

	/* don't accept undefined flags */
@@ -627,33 +626,27 @@ long spufs_create(struct nameidata *nd, unsigned int flags, mode_t mode,
		goto out;

	/* only threads can be underneath a gang */
	if (nd->path.dentry != nd->path.dentry->d_sb->s_root) {
	if (path->dentry != path->dentry->d_sb->s_root) {
		if ((flags & SPU_CREATE_GANG) ||
		    !SPUFS_I(nd->path.dentry->d_inode)->i_gang)
		    !SPUFS_I(path->dentry->d_inode)->i_gang)
			goto out;
	}

	dentry = lookup_create(nd, 1);
	ret = PTR_ERR(dentry);
	if (IS_ERR(dentry))
		goto out_dir;

	mode &= ~current_umask();

	if (flags & SPU_CREATE_GANG)
		ret = spufs_create_gang(nd->path.dentry->d_inode,
					 dentry, nd->path.mnt, mode);
		ret = spufs_create_gang(path->dentry->d_inode,
					 dentry, path->mnt, mode);
	else
		ret = spufs_create_context(nd->path.dentry->d_inode,
					    dentry, nd->path.mnt, flags, mode,
		ret = spufs_create_context(path->dentry->d_inode,
					    dentry, path->mnt, flags, mode,
					    filp);
	if (ret >= 0)
		fsnotify_mkdir(nd->path.dentry->d_inode, dentry);
		fsnotify_mkdir(path->dentry->d_inode, dentry);
	return ret;

out_dir:
	mutex_unlock(&nd->path.dentry->d_inode->i_mutex);
out:
	mutex_unlock(&path->dentry->d_inode->i_mutex);
	return ret;
}

+1 −1
Original line number Diff line number Diff line
@@ -248,7 +248,7 @@ extern const struct spufs_tree_descr spufs_dir_debug_contents[];
/* system call implementation */
extern struct spufs_calls spufs_calls;
long spufs_run_spu(struct spu_context *ctx, u32 *npc, u32 *status);
long spufs_create(struct nameidata *nd, unsigned int flags,
long spufs_create(struct path *nd, struct dentry *dentry, unsigned int flags,
			mode_t mode, struct file *filp);
/* ELF coredump callbacks for writing SPU ELF notes */
extern int spufs_coredump_extra_notes_size(void);
+9 −13
Original line number Diff line number Diff line
@@ -62,21 +62,17 @@ static long do_spu_run(struct file *filp,
static long do_spu_create(const char __user *pathname, unsigned int flags,
		mode_t mode, struct file *neighbor)
{
	char *tmp;
	struct path path;
	struct dentry *dentry;
	int ret;

	tmp = getname(pathname);
	ret = PTR_ERR(tmp);
	if (!IS_ERR(tmp)) {
		struct nameidata nd;

		ret = kern_path_parent(tmp, &nd);
		if (!ret) {
			nd.flags |= LOOKUP_OPEN | LOOKUP_CREATE;
			ret = spufs_create(&nd, flags, mode, neighbor);
			path_put(&nd.path);
		}
		putname(tmp);
	dentry = user_path_create(AT_FDCWD, pathname, &path, 1);
	ret = PTR_ERR(dentry);
	if (!IS_ERR(dentry)) {
		ret = spufs_create(&path, dentry, flags, mode, neighbor);
		mutex_unlock(&path.dentry->d_inode->i_mutex);
		dput(dentry);
		path_put(&path);
	}

	return ret;