Re: [PATCH v2 10/17] ovl: decode lower file handles of unlinked but open files

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, Jan 4, 2018 at 7:20 PM, Amir Goldstein <amir73il@xxxxxxxxx> wrote:
> Lookup overlay inode in cache by origin inode, so we can decode a file
> handle of an open file even if the index has a whiteout index entry to
> mark this overlay inode was unlinked.
>
> Signed-off-by: Amir Goldstein <amir73il@xxxxxxxxx>
> ---
>  fs/overlayfs/export.c    | 22 ++++++++++++++++++++--
>  fs/overlayfs/inode.c     | 16 ++++++++++++++++
>  fs/overlayfs/overlayfs.h |  1 +
>  3 files changed, 37 insertions(+), 2 deletions(-)
>
> diff --git a/fs/overlayfs/export.c b/fs/overlayfs/export.c
> index 602bada474ba..6ecb54d4b52c 100644
> --- a/fs/overlayfs/export.c
> +++ b/fs/overlayfs/export.c
> @@ -385,13 +385,21 @@ static struct dentry *ovl_lower_fh_to_d(struct super_block *sb,
>         struct ovl_path *stack = &origin;
>         struct dentry *dentry = NULL;
>         struct dentry *index = NULL;
> +       struct inode *inode = NULL;
> +       bool is_deleted = false;
>         int err;
>
>         /* First lookup indexed upper by fh */
>         index = ovl_get_index_fh(ofs, fh);
>         err = PTR_ERR(index);
> -       if (IS_ERR(index))
> -               return ERR_PTR(err);
> +       if (IS_ERR(index)) {
> +               if (err != -ESTALE)
> +                       return ERR_PTR(err);
> +
> +               /* Found a whiteout index - treat as deleted inode */
> +               is_deleted = true;
> +               index = NULL;

Ouch! it seems I was misleading you.
If we find a whiteout index for dir, we *do* decode+reconnect origin,
because we want to find out if this is an unlinked but open non-dir.
I guess there are 2 ways to avoid this unneeded decode:
1. mark a "directory index whiteout" differently than "non-dir index whiteout"
2. lookup icache by file handle

> +       }
>
>         /* Then lookup origin by fh */
>         err = ovl_check_origin_fh(fh, NULL, ofs->lower_layers, ofs->numlower,
> @@ -404,6 +412,15 @@ static struct dentry *ovl_lower_fh_to_d(struct super_block *sb,
>                 err = ovl_verify_origin(index, origin.dentry, false, false);
>                 if (err)
>                         goto out_err;
> +       } else if (is_deleted && origin.dentry && !d_is_dir(origin.dentry)) {
> +               /* Lookup deleted overlay inode by origin inode */
> +               inode = ovl_lookup_inode(sb, origin.dentry);
> +               err = -ESTALE;
> +               if (!inode || atomic_read(&inode->i_count) == 1)
> +                       goto out_err;
> +
> +               /* Deleted but still open? */
> +               index = dget(ovl_i_dentry_upper(inode));
>         }

And to top that up, we even try to lookup the origin dir path in overlay
instead of returning ESTALE right away.
Sheesh! that's embarrassing.

Thanks,
Amir.



[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]

  Powered by Linux