ovl: ovl_obtain_alias(): don't call d_instantiate_anon() for old
authorAl Viro <viro@zeniv.linux.org.uk>
Thu, 24 Oct 2019 01:06:45 +0000 (02:06 +0100)
committerMiklos Szeredi <mszeredi@redhat.com>
Tue, 17 Mar 2020 14:04:23 +0000 (15:04 +0100)
The situation is the same as for __d_obtain_alias() (which is what that
thing is parallel to) - if we find a preexisting alias, we want to grab it,
drop the inode and return the alias we'd found.

The only thing d_instantiate_anon() does compared to that is spurious
security_d_instiate() that has already been done to that dentry with exact
same arguments.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
fs/overlayfs/export.c

index a58b3d9..475c61f 100644 (file)
@@ -308,31 +308,35 @@ static struct dentry *ovl_obtain_alias(struct super_block *sb,
                ovl_set_flag(OVL_UPPERDATA, inode);
 
        dentry = d_find_any_alias(inode);
-       if (!dentry) {
-               dentry = d_alloc_anon(inode->i_sb);
-               if (!dentry)
-                       goto nomem;
-               oe = ovl_alloc_entry(lower ? 1 : 0);
-               if (!oe)
-                       goto nomem;
-
-               if (lower) {
-                       oe->lowerstack->dentry = dget(lower);
-                       oe->lowerstack->layer = lowerpath->layer;
-               }
-               dentry->d_fsdata = oe;
-               if (upper_alias)
-                       ovl_dentry_set_upper_alias(dentry);
+       if (dentry)
+               goto out_iput;
+
+       dentry = d_alloc_anon(inode->i_sb);
+       if (unlikely(!dentry))
+               goto nomem;
+       oe = ovl_alloc_entry(lower ? 1 : 0);
+       if (!oe)
+               goto nomem;
+
+       if (lower) {
+               oe->lowerstack->dentry = dget(lower);
+               oe->lowerstack->layer = lowerpath->layer;
        }
+       dentry->d_fsdata = oe;
+       if (upper_alias)
+               ovl_dentry_set_upper_alias(dentry);
+
        ovl_dentry_update_reval(dentry, upper,
                        DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE);
 
        return d_instantiate_anon(dentry, inode);
 
 nomem:
-       iput(inode);
        dput(dentry);
-       return ERR_PTR(-ENOMEM);
+       dentry = ERR_PTR(-ENOMEM);
+out_iput:
+       iput(inode);
+       return dentry;
 }
 
 /* Get the upper or lower dentry in stach whose on layer @idx */