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

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

Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent dae6ad8f
...@@ -611,15 +611,14 @@ static int spufs_create_gang(struct inode *inode, ...@@ -611,15 +611,14 @@ static int spufs_create_gang(struct inode *inode,
static struct file_system_type spufs_type; static struct file_system_type spufs_type;
long spufs_create(struct nameidata *nd, unsigned int flags, mode_t mode, long spufs_create(struct path *path, struct dentry *dentry,
struct file *filp) unsigned int flags, mode_t mode, struct file *filp)
{ {
struct dentry *dentry;
int ret; int ret;
ret = -EINVAL; ret = -EINVAL;
/* check if we are on spufs */ /* 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; goto out;
/* don't accept undefined flags */ /* don't accept undefined flags */
...@@ -627,33 +626,27 @@ long spufs_create(struct nameidata *nd, unsigned int flags, mode_t mode, ...@@ -627,33 +626,27 @@ long spufs_create(struct nameidata *nd, unsigned int flags, mode_t mode,
goto out; goto out;
/* only threads can be underneath a gang */ /* 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) || if ((flags & SPU_CREATE_GANG) ||
!SPUFS_I(nd->path.dentry->d_inode)->i_gang) !SPUFS_I(path->dentry->d_inode)->i_gang)
goto out; goto out;
} }
dentry = lookup_create(nd, 1);
ret = PTR_ERR(dentry);
if (IS_ERR(dentry))
goto out_dir;
mode &= ~current_umask(); mode &= ~current_umask();
if (flags & SPU_CREATE_GANG) if (flags & SPU_CREATE_GANG)
ret = spufs_create_gang(nd->path.dentry->d_inode, ret = spufs_create_gang(path->dentry->d_inode,
dentry, nd->path.mnt, mode); dentry, path->mnt, mode);
else else
ret = spufs_create_context(nd->path.dentry->d_inode, ret = spufs_create_context(path->dentry->d_inode,
dentry, nd->path.mnt, flags, mode, dentry, path->mnt, flags, mode,
filp); filp);
if (ret >= 0) if (ret >= 0)
fsnotify_mkdir(nd->path.dentry->d_inode, dentry); fsnotify_mkdir(path->dentry->d_inode, dentry);
return ret; return ret;
out_dir:
mutex_unlock(&nd->path.dentry->d_inode->i_mutex);
out: out:
mutex_unlock(&path->dentry->d_inode->i_mutex);
return ret; return ret;
} }
......
...@@ -248,7 +248,7 @@ extern const struct spufs_tree_descr spufs_dir_debug_contents[]; ...@@ -248,7 +248,7 @@ extern const struct spufs_tree_descr spufs_dir_debug_contents[];
/* system call implementation */ /* system call implementation */
extern struct spufs_calls spufs_calls; extern struct spufs_calls spufs_calls;
long spufs_run_spu(struct spu_context *ctx, u32 *npc, u32 *status); 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); mode_t mode, struct file *filp);
/* ELF coredump callbacks for writing SPU ELF notes */ /* ELF coredump callbacks for writing SPU ELF notes */
extern int spufs_coredump_extra_notes_size(void); extern int spufs_coredump_extra_notes_size(void);
......
...@@ -62,21 +62,17 @@ static long do_spu_run(struct file *filp, ...@@ -62,21 +62,17 @@ static long do_spu_run(struct file *filp,
static long do_spu_create(const char __user *pathname, unsigned int flags, static long do_spu_create(const char __user *pathname, unsigned int flags,
mode_t mode, struct file *neighbor) mode_t mode, struct file *neighbor)
{ {
char *tmp; struct path path;
struct dentry *dentry;
int ret; int ret;
tmp = getname(pathname); dentry = user_path_create(AT_FDCWD, pathname, &path, 1);
ret = PTR_ERR(tmp); ret = PTR_ERR(dentry);
if (!IS_ERR(tmp)) { if (!IS_ERR(dentry)) {
struct nameidata nd; ret = spufs_create(&path, dentry, flags, mode, neighbor);
mutex_unlock(&path.dentry->d_inode->i_mutex);
ret = kern_path_parent(tmp, &nd); dput(dentry);
if (!ret) { path_put(&path);
nd.flags |= LOOKUP_OPEN | LOOKUP_CREATE;
ret = spufs_create(&nd, flags, mode, neighbor);
path_put(&nd.path);
}
putname(tmp);
} }
return ret; return ret;
......
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