return to old errno choice in mkdir() et.al.
authorAl Viro <viro@zeniv.linux.org.uk>
Thu, 15 May 2008 08:49:12 +0000 (04:49 -0400)
committerGreg Kroah-Hartman <gregkh@suse.de>
Wed, 6 Aug 2008 17:10:56 +0000 (10:10 -0700)
commit e9baf6e59842285bcf9570f5094e4c27674a0f7c upstream

In case when both EEXIST and EROFS would apply we used to
return the former in mkdir(2) and friends.  Lest anyone suspects
us of being consistent, in the same situation knfsd gave clients
nfs_erofs...

ro-bind series had switched the syscall side of things to
returning -EROFS and immediately broke an application - namely,
mkdir -p.  Patch restores the original behaviour...

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Acked-by: Jan Blunck <jblunck@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
fs/namei.c

index 8cf9bb9c2fc0b0133d85f0f6ff0f3e35a9fb8e07..a16f1ae6081b46cc6b0cf6146df67b5c2f4f9d0e 100644 (file)
@@ -1904,18 +1904,22 @@ struct dentry *lookup_create(struct nameidata *nd, int is_dir)
        if (IS_ERR(dentry))
                goto fail;
 
+       if (dentry->d_inode)
+               goto eexist;
        /*
         * Special case - lookup gave negative, but... we had foo/bar/
         * From the vfs_mknod() POV we just have a negative dentry -
         * all is fine. Let's be bastards - you had / on the end, you've
         * been asking for (non-existent) directory. -ENOENT for you.
         */
-       if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode)
-               goto enoent;
+       if (unlikely(!is_dir && nd->last.name[nd->last.len])) {
+               dput(dentry);
+               dentry = ERR_PTR(-ENOENT);
+       }
        return dentry;
-enoent:
+eexist:
        dput(dentry);
-       dentry = ERR_PTR(-ENOENT);
+       dentry = ERR_PTR(-EEXIST);
 fail:
        return dentry;
 }