Re: [PATCH v2 09/17] ovl: decode indexed non-dir file handles

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

 



On Thu, Jan 4, 2018 at 6:20 PM, Amir Goldstein <amir73il@xxxxxxxxx> wrote:
> Decoding an indexed non-dir file handle is similar to decoding a lower
> non-dir file handle, but additionally, we lookup the file handle in index
> dir by name to find the real upper inode.
>
> Signed-off-by: Amir Goldstein <amir73il@xxxxxxxxx>
> ---
>  fs/overlayfs/export.c | 72 +++++++++++++++++++++++++++++++++------------------
>  1 file changed, 47 insertions(+), 25 deletions(-)
>
> diff --git a/fs/overlayfs/export.c b/fs/overlayfs/export.c
> index 6b359f968c01..602bada474ba 100644
> --- a/fs/overlayfs/export.c
> +++ b/fs/overlayfs/export.c
> @@ -168,22 +168,24 @@ static int ovl_encode_inode_fh(struct inode *inode, u32 *fid, int *max_len,
>  }
>
>  /*
> - * Find or instantiate an overlay dentry from real dentries.
> + * Find or instantiate an overlay dentry from real dentries and index.
>   */
>  static struct dentry *ovl_obtain_alias(struct super_block *sb,
> -                                      struct dentry *upper,
> -                                      struct ovl_path *lowerpath)
> +                                      struct dentry *upper_alias,
> +                                      struct ovl_path *lowerpath,
> +                                      struct dentry *index)
>  {
>         struct dentry *lower = lowerpath ? lowerpath->dentry : NULL;
> +       struct dentry *upper = upper_alias ?: index;
>         struct dentry *dentry;
>         struct inode *inode;
>         struct ovl_entry *oe;
>
> -       /* TODO: obtain an indexed non-dir upper with origin */
> -       if (lower && (upper || d_is_dir(lower)))
> +       /* We get overlay directory dentries with ovl_lookup_real() */
> +       if (d_is_dir(upper ?: lower))
>                 return ERR_PTR(-EIO);
>
> -       inode = ovl_get_inode(sb, dget(upper), lower, NULL, !!lower);
> +       inode = ovl_get_inode(sb, dget(upper), lower, index, !!lower);
>         if (IS_ERR(inode)) {
>                 dput(upper);
>                 return ERR_CAST(inode);
> @@ -200,13 +202,16 @@ static struct dentry *ovl_obtain_alias(struct super_block *sb,
>         }
>
>         dentry->d_fsdata = oe;
> -       if (upper)
> +       if (upper_alias)
>                 ovl_dentry_set_upper_alias(dentry);
>         if (lower) {
>                 oe->lowerstack->dentry = dget(lower);
>                 oe->lowerstack->layer = lowerpath->layer;
>         }
>
> +       if (index)
> +               ovl_set_flag(OVL_INDEX, inode);
> +
>         return dentry;
>  }
>
> @@ -321,30 +326,26 @@ static struct dentry *ovl_lookup_real(struct super_block *sb,
>  }
>
>  /*
> - * Get an overlay dentry from upper/lower real dentries.
> + * Get an overlay dentry from upper/lower real dentries and index.
>   */
>  static struct dentry *ovl_get_dentry(struct super_block *sb,
>                                      struct dentry *upper,
> -                                    struct ovl_path *lowerpath)
> +                                    struct ovl_path *lowerpath,
> +                                    struct dentry *index)
>  {
> +       struct dentry *real = upper ?: (index ?: lowerpath->dentry);
> +
>         /*
> -        * Obtain a disconnected overlay dentry from a disconnected non-dir
> -        * real lower dentry.
> +        * Obtain a disconnected overlay dentry from a non-dir real dentry
> +        * and index.
>          */
> -       if (!upper && !d_is_dir(lowerpath->dentry))
> -               return ovl_obtain_alias(sb, NULL, lowerpath);
> +       if (!d_is_dir(real))
> +               return ovl_obtain_alias(sb, upper, lowerpath, index);
>
>         /* TODO: lookup connected dir from real lower dir */
>         if (!upper)
>                 return ERR_PTR(-EACCES);
>
> -       /*
> -        * Obtain a disconnected overlay dentry from a non-dir real upper
> -        * dentry.
> -        */
> -       if (!d_is_dir(upper))
> -               return ovl_obtain_alias(sb, upper, NULL);
> -
>         /* Removed empty directory? */
>         if ((upper->d_flags & DCACHE_DISCONNECTED) || d_unhashed(upper))
>                 return ERR_PTR(-ENOENT);
> @@ -370,7 +371,7 @@ static struct dentry *ovl_upper_fh_to_d(struct super_block *sb,
>         if (IS_ERR_OR_NULL(upper))
>                 return upper;
>
> -       dentry = ovl_get_dentry(sb, upper, NULL);
> +       dentry = ovl_get_dentry(sb, upper, NULL, NULL);
>         dput(upper);
>
>         return dentry;
> @@ -383,17 +384,38 @@ static struct dentry *ovl_lower_fh_to_d(struct super_block *sb,
>         struct ovl_path origin = { };
>         struct ovl_path *stack = &origin;
>         struct dentry *dentry = NULL;
> +       struct dentry *index = NULL;
>         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);
> +
> +       /* Then lookup origin by fh */
>         err = ovl_check_origin_fh(fh, NULL, ofs->lower_layers, ofs->numlower,
>                                   &stack);
> -       if (err)
> -               return ERR_PTR(err);
> +       if (err) {
> +               goto out_err;
> +       } else if (!index && !origin.dentry) {

origin.dentry is not going to be NULL if ovl_check_origin_fh()
returns.  So checking for non-NULL is not needed here

> +               return NULL;
> +       } else if (index && origin.dentry) {

here, and following patch.

> +               err = ovl_verify_origin(index, origin.dentry, false, false);
> +               if (err)
> +                       goto out_err;
> +       }
>
> -       dentry = ovl_get_dentry(sb, NULL, &origin);
> -       dput(origin.dentry);
> +       dentry = ovl_get_dentry(sb, NULL, &origin, index);
>
> +out:
> +       dput(origin.dentry);
> +       dput(index);
>         return dentry;
> +
> +out_err:
> +       dentry = ERR_PTR(err);
> +       goto out;
>  }
>
>  static struct dentry *ovl_fh_to_dentry(struct super_block *sb, struct fid *fid,
> --
> 2.7.4
>
--
To unsubscribe from this list: send the line "unsubscribe linux-unionfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Filesystems Devel]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux