linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Alexander Larsson <alexl@redhat.com>
To: Amir Goldstein <amir73il@gmail.com>,
	Miklos Szeredi <mszeredi@redhat.com>
Cc: linux-unionfs@vger.kernel.org, linux-fsdevel@vger.kernel.org,
	 stable@vger.kernel.org
Subject: Re: [PATCH v2] ovl: require xwhiteout feature flag on layer roots
Date: Fri, 19 Jan 2024 13:29:19 +0100	[thread overview]
Message-ID: <b50d431b154bdc64462e561d9da8f04e53f1603c.camel@redhat.com> (raw)
In-Reply-To: <CAOQ4uxiWtdgCQ+kBJemAYbwNR46ogP7DhjD29cqAw0qqLvQn4A@mail.gmail.com>

On Fri, 2024-01-19 at 13:08 +0200, Amir Goldstein wrote:
> On Fri, Jan 19, 2024 at 12:14 PM Miklos Szeredi <mszeredi@redhat.com>
> wrote:
> > 
> > Add a check on each lower layer for the xwhiteout feature.  This
> > prevents
> > unnecessary checking the overlay.whiteouts xattr when reading a
> > directory
> > if this feature is not enabled, i.e. most of the time.
> > 
> > Share the same xattr for the per-directory and the per-layer flag,
> > which
> > has the effect that if this is enabled for a layer, then the
> > optimization
> > to bypass checking of individual entries does not work on the root
> > of the
> > layer.  This was deemed better, than having a separate xattr for
> > the layer
> > and the directory.
> > 
> > Fixes: bc8df7a3dc03 ("ovl: Add an alternative type of whiteout")
> > Cc: <stable@vger.kernel.org> # v6.7
> > Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
> > ---
> > v2:
> >  - use overlay.whiteouts instead of overlay.feature_xwhiteout
> >  - move initialization to ovl_get_layers()
> >  - xwhiteouts can only be enabled on lower layer
> > 
> >  fs/overlayfs/namei.c     | 10 +++++++---
> >  fs/overlayfs/overlayfs.h |  7 +++++--
> >  fs/overlayfs/ovl_entry.h |  2 ++
> >  fs/overlayfs/readdir.c   | 11 ++++++++---
> >  fs/overlayfs/super.c     | 13 +++++++++++++
> >  fs/overlayfs/util.c      |  7 ++++++-
> >  6 files changed, 41 insertions(+), 9 deletions(-)
> > 
> > diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c
> > index 03bc8d5dfa31..583cf56df66e 100644
> > --- a/fs/overlayfs/namei.c
> > +++ b/fs/overlayfs/namei.c
> > @@ -863,7 +863,8 @@ struct dentry *ovl_lookup_index(struct ovl_fs
> > *ofs, struct dentry *upper,
> >   * Returns next layer in stack starting from top.
> >   * Returns -1 if this is the last layer.
> >   */
> > -int ovl_path_next(int idx, struct dentry *dentry, struct path
> > *path)
> > +int ovl_path_next(int idx, struct dentry *dentry, struct path
> > *path,
> > +                 const struct ovl_layer **layer)
> >  {
> >         struct ovl_entry *oe = OVL_E(dentry);
> >         struct ovl_path *lowerstack = ovl_lowerstack(oe);
> > @@ -871,13 +872,16 @@ int ovl_path_next(int idx, struct dentry
> > *dentry, struct path *path)
> >         BUG_ON(idx < 0);
> >         if (idx == 0) {
> >                 ovl_path_upper(dentry, path);
> > -               if (path->dentry)
> > +               if (path->dentry) {
> > +                       *layer = &OVL_FS(dentry->d_sb)->layers[0];
> >                         return ovl_numlower(oe) ? 1 : -1;
> > +               }
> >                 idx++;
> >         }
> >         BUG_ON(idx > ovl_numlower(oe));
> >         path->dentry = lowerstack[idx - 1].dentry;
> > -       path->mnt = lowerstack[idx - 1].layer->mnt;
> > +       *layer = lowerstack[idx - 1].layer;
> > +       path->mnt = (*layer)->mnt;
> > 
> >         return (idx < ovl_numlower(oe)) ? idx + 1 : -1;
> >  }
> > diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
> > index 05c3dd597fa8..6359cf5c66ff 100644
> > --- a/fs/overlayfs/overlayfs.h
> > +++ b/fs/overlayfs/overlayfs.h
> > @@ -492,7 +492,9 @@ bool ovl_path_check_dir_xattr(struct ovl_fs
> > *ofs, const struct path *path,
> >                               enum ovl_xattr ox);
> >  bool ovl_path_check_origin_xattr(struct ovl_fs *ofs, const struct
> > path *path);
> >  bool ovl_path_check_xwhiteout_xattr(struct ovl_fs *ofs, const
> > struct path *path);
> > -bool ovl_path_check_xwhiteouts_xattr(struct ovl_fs *ofs, const
> > struct path *path);
> > +bool ovl_path_check_xwhiteouts_xattr(struct ovl_fs *ofs,
> > +                                    const struct ovl_layer *layer,
> > +                                    const struct path *path);
> >  bool ovl_init_uuid_xattr(struct super_block *sb, struct ovl_fs
> > *ofs,
> >                          const struct path *upperpath);
> > 
> > @@ -674,7 +676,8 @@ int ovl_get_index_name(struct ovl_fs *ofs,
> > struct dentry *origin,
> >  struct dentry *ovl_get_index_fh(struct ovl_fs *ofs, struct ovl_fh
> > *fh);
> >  struct dentry *ovl_lookup_index(struct ovl_fs *ofs, struct dentry
> > *upper,
> >                                 struct dentry *origin, bool
> > verify);
> > -int ovl_path_next(int idx, struct dentry *dentry, struct path
> > *path);
> > +int ovl_path_next(int idx, struct dentry *dentry, struct path
> > *path,
> > +                 const struct ovl_layer **layer);
> >  int ovl_verify_lowerdata(struct dentry *dentry);
> >  struct dentry *ovl_lookup(struct inode *dir, struct dentry
> > *dentry,
> >                           unsigned int flags);
> > diff --git a/fs/overlayfs/ovl_entry.h b/fs/overlayfs/ovl_entry.h
> > index d82d2a043da2..33fcd3d3af30 100644
> > --- a/fs/overlayfs/ovl_entry.h
> > +++ b/fs/overlayfs/ovl_entry.h
> > @@ -40,6 +40,8 @@ struct ovl_layer {
> >         int idx;
> >         /* One fsid per unique underlying sb (upper fsid == 0) */
> >         int fsid;
> > +       /* xwhiteouts are enabled on this layer*/
> > +       bool xwhiteouts;
> >  };
> > 
> >  struct ovl_path {
> > diff --git a/fs/overlayfs/readdir.c b/fs/overlayfs/readdir.c
> > index a490fc47c3e7..c2597075e3f8 100644
> > --- a/fs/overlayfs/readdir.c
> > +++ b/fs/overlayfs/readdir.c
> > @@ -305,8 +305,6 @@ static inline int ovl_dir_read(const struct
> > path *realpath,
> >         if (IS_ERR(realfile))
> >                 return PTR_ERR(realfile);
> > 
> > -       rdd->in_xwhiteouts_dir = rdd->dentry &&
> > -               ovl_path_check_xwhiteouts_xattr(OVL_FS(rdd->dentry-
> > >d_sb), realpath);
> >         rdd->first_maybe_whiteout = NULL;
> >         rdd->ctx.pos = 0;
> >         do {
> > @@ -359,10 +357,14 @@ static int ovl_dir_read_merged(struct dentry
> > *dentry, struct list_head *list,
> >                 .is_lowest = false,
> >         };
> >         int idx, next;
> > +       struct ovl_fs *ofs = OVL_FS(dentry->d_sb);
> > +       const struct ovl_layer *layer;
> > 
> >         for (idx = 0; idx != -1; idx = next) {
> > -               next = ovl_path_next(idx, dentry, &realpath);
> > +               next = ovl_path_next(idx, dentry, &realpath,
> > &layer);
> >                 rdd.is_upper = ovl_dentry_upper(dentry) ==
> > realpath.dentry;
> > +               if (ovl_path_check_xwhiteouts_xattr(ofs, layer,
> > &realpath))
> > +                       rdd.in_xwhiteouts_dir = true;
> > 
> >                 if (next != -1) {
> >                         err = ovl_dir_read(&realpath, &rdd);
> > @@ -568,6 +570,7 @@ static int ovl_dir_read_impure(const struct
> > path *path,  struct list_head *list,
> >         int err;
> >         struct path realpath;
> >         struct ovl_cache_entry *p, *n;
> > +       struct ovl_fs *ofs = OVL_FS(path->dentry->d_sb);
> >         struct ovl_readdir_data rdd = {
> >                 .ctx.actor = ovl_fill_plain,
> >                 .list = list,
> > @@ -577,6 +580,8 @@ static int ovl_dir_read_impure(const struct
> > path *path,  struct list_head *list,
> >         INIT_LIST_HEAD(list);
> >         *root = RB_ROOT;
> >         ovl_path_upper(path->dentry, &realpath);
> > +       if (ovl_path_check_xwhiteouts_xattr(ofs, &ofs->layers[0],
> > &realpath))
> > +               rdd.in_xwhiteouts_dir = true;
> 
> Not needed since we do not support xwhiteouts on upper.
> 
> > 
> >         err = ovl_dir_read(&realpath, &rdd);
> >         if (err)
> > diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
> > index a0967bb25003..04588721eb2a 100644
> > --- a/fs/overlayfs/super.c
> > +++ b/fs/overlayfs/super.c
> > @@ -1027,6 +1027,7 @@ static int ovl_get_layers(struct super_block
> > *sb, struct ovl_fs *ofs,
> >                 struct ovl_fs_context_layer *l = &ctx->lower[i];
> >                 struct vfsmount *mnt;
> >                 struct inode *trap;
> > +               struct path root;
> >                 int fsid;
> > 
> >                 if (i < nr_merged_lower)
> > @@ -1069,6 +1070,16 @@ static int ovl_get_layers(struct super_block
> > *sb, struct ovl_fs *ofs,
> >                  */
> >                 mnt->mnt_flags |= MNT_READONLY | MNT_NOATIME;
> > 
> > +               /*
> > +                * Check if xwhiteout (xattr whiteout) support is
> > enabled on
> > +                * this layer.
> > +                */
> > +               root.mnt = mnt;
> > +               root.dentry = mnt->mnt_root;
> > +               err = ovl_path_getxattr(ofs, &root,
> > OVL_XATTR_XWHITEOUTS, NULL, 0);
> > +               if (err >= 0)
> > +                       layers[ofs->numlayer].xwhiteouts = true;
> > +
> >                 layers[ofs->numlayer].trap = trap;
> >                 layers[ofs->numlayer].mnt = mnt;
> >                 layers[ofs->numlayer].idx = ofs->numlayer;
> > @@ -1079,6 +1090,8 @@ static int ovl_get_layers(struct super_block
> > *sb, struct ovl_fs *ofs,
> >                 l->name = NULL;
> >                 ofs->numlayer++;
> >                 ofs->fs[fsid].is_lower = true;
> > +
> > +
> 
> extra spaces.
> 
> >         }
> > 
> >         /*
> > diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c
> > index c3f020ca13a8..6c6e6f5893ea 100644
> > --- a/fs/overlayfs/util.c
> > +++ b/fs/overlayfs/util.c
> > @@ -739,11 +739,16 @@ bool ovl_path_check_xwhiteout_xattr(struct
> > ovl_fs *ofs, const struct path *path)
> >         return res >= 0;
> >  }
> > 
> > -bool ovl_path_check_xwhiteouts_xattr(struct ovl_fs *ofs, const
> > struct path *path)
> > +bool ovl_path_check_xwhiteouts_xattr(struct ovl_fs *ofs,
> > +                                    const struct ovl_layer *layer,
> > +                                    const struct path *path)
> >  {
> >         struct dentry *dentry = path->dentry;
> >         int res;
> > 
> > +       if (!layer->xwhiteouts)
> > +               return false;
> > +
> >         /* xattr.whiteouts must be a directory */
> >         if (!d_is_dir(dentry))
> >                 return false;
> > --
> > 2.43.0
> > 
> 
> Do you want me to fix/test and send this to Linus?
> 
> Alex, can we add your RVB to v2?
> 

Yeah, other that your comments this looks good to me (and I tested it
here too).

Reviewed-By: Alexander Larsson <alex@redhat.com>

I'll have a look at doing the required changes in composefs.

-- 
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
=-=-=
 Alexander Larsson                                            Red Hat,
Inc 
       alexl@redhat.com            alexander.larsson@gmail.com 
He's a Nobel prize-winning voodoo matador haunted by memories of 'Nam. 
She's an orphaned gypsy bodyguard on the trail of a serial killer. They
fight crime! 

  parent reply	other threads:[~2024-01-19 12:29 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-01-19 10:14 [PATCH v2] ovl: require xwhiteout feature flag on layer roots Miklos Szeredi
2024-01-19 11:08 ` Amir Goldstein
2024-01-19 11:20   ` Miklos Szeredi
2024-01-19 12:19     ` Amir Goldstein
2024-01-19 12:29   ` Alexander Larsson [this message]
2024-01-19 14:12     ` Amir Goldstein
2024-01-19 16:35   ` Alexander Larsson
2024-01-19 19:06     ` Amir Goldstein
2024-01-19 20:29       ` Miklos Szeredi
2024-01-20 10:32         ` Amir Goldstein
2024-01-22 10:01           ` Alexander Larsson
2024-01-22  8:38     ` Amir Goldstein
2024-01-22 10:44       ` Alexander Larsson
2024-01-22 11:30         ` Amir Goldstein

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=b50d431b154bdc64462e561d9da8f04e53f1603c.camel@redhat.com \
    --to=alexl@redhat.com \
    --cc=amir73il@gmail.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-unionfs@vger.kernel.org \
    --cc=mszeredi@redhat.com \
    --cc=stable@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).