Re: [PATCH 1/2] ovl: mark upper dir with type origin entries "impure"

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

 



On Thu, May 11, 2017 at 3:42 PM, Amir Goldstein <amir73il@xxxxxxxxx> wrote:
> When moving a merge dir or non-dir with copy up origin into
> a non-merge upper dir (a.k.a pure upper dir), we are marking
> the target parent dir "impure". ovl_iterate() iterates pure
> upper dirs directly, because there is no need to filter out
> whiteouts and merge dir content with lower dir. But for the
> case of an "impure" upper dir, ovl_iterate() will not be able
> to iterate the real upper dir directly, because it will need
> to lookup the origin inode and use it to fill d_ino.

Applied, thanks.

Miklos

>
> Signed-off-by: Amir Goldstein <amir73il@xxxxxxxxx>
> ---
>  fs/overlayfs/dir.c       | 41 ++++++++++++++++++++++++++++++++++++++++-
>  fs/overlayfs/namei.c     | 18 ++++++++++++++++--
>  fs/overlayfs/overlayfs.h |  3 +++
>  fs/overlayfs/ovl_entry.h |  1 +
>  fs/overlayfs/util.c      | 15 +++++++++++++++
>  5 files changed, 75 insertions(+), 3 deletions(-)
>
> diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c
> index 723b98b..205e491 100644
> --- a/fs/overlayfs/dir.c
> +++ b/fs/overlayfs/dir.c
> @@ -138,6 +138,17 @@ static int ovl_set_opaque(struct dentry *dentry, struct dentry *upperdentry)
>         return err;
>  }
>
> +static int ovl_set_impure(struct dentry *dentry, struct dentry *upperdentry)
> +{
> +       int err;
> +
> +       err = ovl_do_setxattr(upperdentry, OVL_XATTR_IMPURE, "y", 1, 0);
> +       if (!err)
> +               ovl_dentry_set_impure(dentry);
> +
> +       return err;
> +}
> +
>  /* Common operations required to be done after creation of file on upper */
>  static void ovl_instantiate(struct dentry *dentry, struct inode *inode,
>                             struct dentry *newdentry, bool hardlink)
> @@ -162,6 +173,11 @@ static bool ovl_type_merge(struct dentry *dentry)
>         return OVL_TYPE_MERGE(ovl_path_type(dentry));
>  }
>
> +static bool ovl_type_origin(struct dentry *dentry)
> +{
> +       return OVL_TYPE_ORIGIN(ovl_path_type(dentry));
> +}
> +
>  static int ovl_create_upper(struct dentry *dentry, struct inode *inode,
>                             struct cattr *attr, struct dentry *hardlink)
>  {
> @@ -943,6 +959,30 @@ static int ovl_rename(struct inode *olddir, struct dentry *old,
>         old_upperdir = ovl_dentry_upper(old->d_parent);
>         new_upperdir = ovl_dentry_upper(new->d_parent);
>
> +       if (ovl_same_sb(old->d_sb) && !samedir) {
> +               /*
> +                * When moving a merge dir or non-dir with copy up origin into
> +                * a non-merge upper dir (a.k.a pure upper dir), we are making
> +                * the target parent dir "impure". ovl_iterate() iterates pure
> +                * upper dirs directly, because there is no need to filter out
> +                * whiteouts and merge dir content with lower dir. But for the
> +                * case of an "impure" upper dir, ovl_iterate() cannot iterate
> +                * the real directory directly, because it looks for the inode
> +                * numbers to fill d_ino in the entries origin inode.
> +                */
> +               if (ovl_type_origin(old) && !ovl_type_merge(new->d_parent)) {
> +                       err = ovl_set_impure(new->d_parent, new_upperdir);
> +                       if (err)
> +                               goto out_dput;
> +               }
> +               if (!overwrite && ovl_type_origin(new) &&
> +                   !ovl_type_merge(old->d_parent)) {
> +                       err = ovl_set_impure(old->d_parent, old_upperdir);
> +                       if (err)
> +                               goto out_dput;
> +               }
> +       }
> +
>         trap = lock_rename(new_upperdir, old_upperdir);
>
>         olddentry = lookup_one_len(old->d_name.name, old_upperdir,
> @@ -1004,7 +1044,6 @@ static int ovl_rename(struct inode *olddir, struct dentry *old,
>                 if (err)
>                         goto out_dput;
>         }
> -
>         err = ovl_do_rename(old_upperdir->d_inode, olddentry,
>                             new_upperdir->d_inode, newdentry, flags);
>         if (err)
> diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c
> index bad0f66..0c72a59 100644
> --- a/fs/overlayfs/namei.c
> +++ b/fs/overlayfs/namei.c
> @@ -167,7 +167,7 @@ static struct dentry *ovl_get_origin(struct dentry *dentry,
>         goto out;
>  }
>
> -static bool ovl_is_opaquedir(struct dentry *dentry)
> +static bool ovl_check_dir_xattr(struct dentry *dentry, const char *name)
>  {
>         int res;
>         char val;
> @@ -175,13 +175,23 @@ static bool ovl_is_opaquedir(struct dentry *dentry)
>         if (!d_is_dir(dentry))
>                 return false;
>
> -       res = vfs_getxattr(dentry, OVL_XATTR_OPAQUE, &val, 1);
> +       res = vfs_getxattr(dentry, name, &val, 1);
>         if (res == 1 && val == 'y')
>                 return true;
>
>         return false;
>  }
>
> +static bool ovl_is_opaquedir(struct dentry *dentry)
> +{
> +       return ovl_check_dir_xattr(dentry, OVL_XATTR_OPAQUE);
> +}
> +
> +static bool ovl_is_impuredir(struct dentry *dentry)
> +{
> +       return ovl_check_dir_xattr(dentry, OVL_XATTR_IMPURE);
> +}
> +
>  static int ovl_lookup_single(struct dentry *base, struct ovl_lookup_data *d,
>                              const char *name, unsigned int namelen,
>                              size_t prelen, const char *post,
> @@ -351,6 +361,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
>         unsigned int ctr = 0;
>         struct inode *inode = NULL;
>         bool upperopaque = false;
> +       bool upperimpure = false;
>         char *upperredirect = NULL;
>         struct dentry *this;
>         unsigned int i;
> @@ -395,6 +406,8 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
>                                 poe = roe;
>                 }
>                 upperopaque = d.opaque;
> +               if (upperdentry && d.is_dir)
> +                       upperimpure = ovl_is_impuredir(upperdentry);
>         }
>
>         if (!d.stop && poe->numlower) {
> @@ -463,6 +476,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
>
>         revert_creds(old_cred);
>         oe->opaque = upperopaque;
> +       oe->impure = upperimpure;
>         oe->redirect = upperredirect;
>         oe->__upperdentry = upperdentry;
>         memcpy(oe->lowerstack, stack, sizeof(struct path) * ctr);
> diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
> index caa36cb..fae52f5 100644
> --- a/fs/overlayfs/overlayfs.h
> +++ b/fs/overlayfs/overlayfs.h
> @@ -24,6 +24,7 @@ enum ovl_path_type {
>  #define OVL_XATTR_OPAQUE OVL_XATTR_PREFIX "opaque"
>  #define OVL_XATTR_REDIRECT OVL_XATTR_PREFIX "redirect"
>  #define OVL_XATTR_ORIGIN OVL_XATTR_PREFIX "origin"
> +#define OVL_XATTR_IMPURE OVL_XATTR_PREFIX "impure"
>
>  /*
>   * The tuple (fh,uuid) is a universal unique identifier for a copy up origin,
> @@ -203,8 +204,10 @@ struct dentry *ovl_dentry_real(struct dentry *dentry);
>  struct ovl_dir_cache *ovl_dir_cache(struct dentry *dentry);
>  void ovl_set_dir_cache(struct dentry *dentry, struct ovl_dir_cache *cache);
>  bool ovl_dentry_is_opaque(struct dentry *dentry);
> +bool ovl_dentry_is_impure(struct dentry *dentry);
>  bool ovl_dentry_is_whiteout(struct dentry *dentry);
>  void ovl_dentry_set_opaque(struct dentry *dentry);
> +void ovl_dentry_set_impure(struct dentry *dentry);
>  bool ovl_redirect_dir(struct super_block *sb);
>  void ovl_clear_redirect_dir(struct super_block *sb);
>  const char *ovl_dentry_get_redirect(struct dentry *dentry);
> diff --git a/fs/overlayfs/ovl_entry.h b/fs/overlayfs/ovl_entry.h
> index b2023ddb..9b9361f 100644
> --- a/fs/overlayfs/ovl_entry.h
> +++ b/fs/overlayfs/ovl_entry.h
> @@ -42,6 +42,7 @@ struct ovl_entry {
>                         u64 version;
>                         const char *redirect;
>                         bool opaque;
> +                       bool impure;
>                         bool copying;
>                 };
>                 struct rcu_head rcu;
> diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c
> index cfdea47..b17a936 100644
> --- a/fs/overlayfs/util.c
> +++ b/fs/overlayfs/util.c
> @@ -172,9 +172,17 @@ void ovl_set_dir_cache(struct dentry *dentry, struct ovl_dir_cache *cache)
>  bool ovl_dentry_is_opaque(struct dentry *dentry)
>  {
>         struct ovl_entry *oe = dentry->d_fsdata;
> +
>         return oe->opaque;
>  }
>
> +bool ovl_dentry_is_impure(struct dentry *dentry)
> +{
> +       struct ovl_entry *oe = dentry->d_fsdata;
> +
> +       return oe->impure;
> +}
> +
>  bool ovl_dentry_is_whiteout(struct dentry *dentry)
>  {
>         return !dentry->d_inode && ovl_dentry_is_opaque(dentry);
> @@ -187,6 +195,13 @@ void ovl_dentry_set_opaque(struct dentry *dentry)
>         oe->opaque = true;
>  }
>
> +void ovl_dentry_set_impure(struct dentry *dentry)
> +{
> +       struct ovl_entry *oe = dentry->d_fsdata;
> +
> +       oe->impure = true;
> +}
> +
>  bool ovl_redirect_dir(struct super_block *sb)
>  {
>         struct ovl_fs *ofs = sb->s_fs_info;
> --
> 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