On Wed, Nov 19, 2014 at 03:33:29PM -0500, Bob Peterson wrote:
> ----- Original Message -----
> > Signed-off-by: Al Viro <[email protected]>
> > ---
> >  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).

Reply via email to