switch do_spufs_create() to user_path_create(), fix double-unlock
Al Viro [Sun, 26 Jun 2011 15:54:58 +0000 (11:54 -0400)]
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>

arch/powerpc/platforms/cell/spufs/inode.c
arch/powerpc/platforms/cell/spufs/spufs.h
arch/powerpc/platforms/cell/spufs/syscalls.c

index 856e9c3..e481f6b 100644 (file)
@@ -611,15 +611,14 @@ out:
 
 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;
 }
 
index c448bac..099245f 100644 (file)
@@ -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);
index a3d2ce5..609e016 100644 (file)
@@ -62,21 +62,17 @@ out:
 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;