Message ID | 20210313043824.1283821-10-viro@zeniv.linux.org.uk (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [v2,01/15] new helper: inode_wrong_type() | expand |
On Sat, 2021-03-13 at 04:38 +0000, Al Viro wrote: > 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 <viro@zeniv.linux.org.uk> > --- > 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 d46b36d52211..80c487fcf10e 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 Reviewed-by: Jeff Layton <jlayton@kernel.org>
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index d46b36d52211..80c487fcf10e 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
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 <viro@zeniv.linux.org.uk> --- fs/cifs/inode.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)