Signed-off-by: Jeff Layton <jlay...@redhat.com>
---
 fs/namei.c | 68 ++++++++++++++++++++++++++++++++++++--------------------------
 1 file changed, 40 insertions(+), 28 deletions(-)

diff --git a/fs/namei.c b/fs/namei.c
index 438ed67..6705757 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2963,44 +2963,56 @@ SYSCALL_DEFINE4(mknodat, int, dfd, const char __user *, 
filename, umode_t, mode,
        struct dentry *dentry;
        struct path path;
        int error;
+       char *name;
+       unsigned int try = 0;
 
        if (S_ISDIR(mode))
                return -EPERM;
 
-       dentry = user_path_create(dfd, filename, &path, 0);
-       if (IS_ERR(dentry))
-               return PTR_ERR(dentry);
+       name = getname(filename);
+       if (IS_ERR(name))
+               return PTR_ERR(name);
 
-       if (!IS_POSIXACL(path.dentry->d_inode))
-               mode &= ~current_umask();
-       error = may_mknod(mode);
-       if (error)
-               goto out_dput;
-       error = mnt_want_write(path.mnt);
-       if (error)
-               goto out_dput;
-       error = security_path_mknod(&path, dentry, mode, dev);
-       if (error)
-               goto out_drop_write;
-       switch (mode & S_IFMT) {
-               case 0: case S_IFREG:
-                       error = 
vfs_create(path.dentry->d_inode,dentry,mode,true);
+       do {
+               dentry = kern_path_create(dfd, name, &path, false, try);
+               if (IS_ERR(dentry))
+                       return PTR_ERR(dentry);
+
+               if (!IS_POSIXACL(path.dentry->d_inode))
+                       mode &= ~current_umask();
+               error = may_mknod(mode);
+               if (error)
+                       goto out_dput;
+               error = mnt_want_write(path.mnt);
+               if (error)
+                       goto out_dput;
+               error = security_path_mknod(&path, dentry, mode, dev);
+               if (error)
+                       goto out_drop_write;
+               switch (mode & S_IFMT) {
+               case 0:
+               case S_IFREG:
+                       error = vfs_create(path.dentry->d_inode, dentry,
+                                       mode, true);
                        break;
-               case S_IFCHR: case S_IFBLK:
-                       error = vfs_mknod(path.dentry->d_inode,dentry,mode,
+               case S_IFCHR:
+               case S_IFBLK:
+                       error = vfs_mknod(path.dentry->d_inode, dentry, mode,
                                        new_decode_dev(dev));
                        break;
-               case S_IFIFO: case S_IFSOCK:
-                       error = vfs_mknod(path.dentry->d_inode,dentry,mode,0);
-                       break;
-       }
+               case S_IFIFO:
+               case S_IFSOCK:
+                       error = vfs_mknod(path.dentry->d_inode, dentry,
+                                       mode, 0);
+               }
 out_drop_write:
-       mnt_drop_write(path.mnt);
+               mnt_drop_write(path.mnt);
 out_dput:
-       dput(dentry);
-       mutex_unlock(&path.dentry->d_inode->i_mutex);
-       path_put(&path);
-
+               dput(dentry);
+               mutex_unlock(&path.dentry->d_inode->i_mutex);
+               path_put(&path);
+       } while (retry_estale(error, try++));
+       putname(name);
        return error;
 }
 
-- 
1.7.11.2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to