From 3bcb39b086bf8d7c3cff013564f86162ec497d90 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 10 Feb 2021 22:13:03 -0500 Subject: [PATCH] cifs: have ->mkdir() handle race with another client sanely if we have mkdir request reported successful *and* simulating lookup gets us a non-directory (which is possible if another client has managed to get rmdir and create in between), the sane action is not to mangle ->i_mode of non-directory inode to S_IFDIR | mode, it's "report success and return with dentry negative unhashed" - that way the next lookup will do the right thing. Signed-off-by: Al Viro --- fs/cifs/inode.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index d46b36d..80c487f 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -1739,6 +1739,16 @@ cifs_mkdir_qinfo(struct inode *parent, struct dentry *dentry, umode_t mode, if (rc) return rc; + if (!S_ISDIR(inode->i_mode)) { + /* + * mkdir succeeded, but another client has managed to remove the + * sucker and replace it with non-directory. Return success, + * but don't leave the child in dcache. + */ + iput(inode); + d_drop(dentry); + return 0; + } /* * setting nlink not necessary except in cases where we failed to get it * from the server or was set bogus. Also, since this is a brand new @@ -1790,7 +1800,7 @@ cifs_mkdir_qinfo(struct inode *parent, struct dentry *dentry, umode_t mode, } } d_instantiate(dentry, inode); - return rc; + return 0; } static int -- 2.7.4