From mboxrd@z Thu Jan 1 00:00:00 1970 From: Al Viro Date: Wed, 19 Nov 2014 20:42:56 +0000 Subject: [Cluster-devel] [PATCH 1/3] gfs2: bugger off early if O_CREAT open finds a directory In-Reply-To: <1173544096.16629343.1416429209461.JavaMail.zimbra@redhat.com> References: <20141119193404.GY7996@ZenIV.linux.org.uk> <20141119193449.GZ7996@ZenIV.linux.org.uk> <1173544096.16629343.1416429209461.JavaMail.zimbra@redhat.com> Message-ID: <20141119204256.GC7996@ZenIV.linux.org.uk> List-Id: To: cluster-devel.redhat.com MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit On Wed, Nov 19, 2014 at 03:33:29PM -0500, Bob Peterson wrote: > ----- Original Message ----- > > Signed-off-by: Al Viro > > --- > > fs/gfs2/inode.c | 5 +++++ > > 1 file changed, 5 insertions(+) > > > > diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c > > index c4ed823..310e248 100644 > > --- a/fs/gfs2/inode.c > > +++ b/fs/gfs2/inode.c > > @@ -624,6 +624,11 @@ static int gfs2_create_inode(struct inode *dir, struct > > dentry *dentry, > > inode = gfs2_dir_search(dir, &dentry->d_name, !S_ISREG(mode) || excl); > > error = PTR_ERR(inode); > > if (!IS_ERR(inode)) { > > + if (S_ISDIR(inode->i_mode)) { > > + iput(inode); > > + inode = ERR_PTR(-EISDIR); > > + goto fail_gunlock; > > + } > > d = d_splice_alias(inode, dentry); > > error = PTR_ERR(d); > > if (IS_ERR(d)) { > Hm. Seems wrong that it should return 0 if the dirent exists (mkdir of a > directory that already exists) but it looks like it already behaves that way. > So I guess so. It may warrant further investigation. It doesn't. Note that !S_ISREG(mode) || excl in there - *anything* other than ->create() will treat existing entries with the same name as EEXIST. The only case when we can possibly get into that if (!IS_ERR(inode)) is ->create() hitting an existing file. And with this change it narrows to "->create() hitting an existing non-directory". That allows the next patch to use d_instantiate() instead of d_splice_alias() - for non-directories it's the same thing, since dentry is already hashed here and we don't need to avoid multiple aliases. Which kills one of the two places in the tree where d_splice_alias() is called for an already hashed dentry (another is d_add_ci() and that call also goes down - see vfs.git#for-next for that one).