From: Alexander Larsson <alexl@redhat.com>
To: Amir Goldstein <amir73il@gmail.com>, Miklos Szeredi <miklos@szeredi.hu>
Cc: linux-unionfs@vger.kernel.org
Subject: Re: [PATCH 5/5] ovl: implement lazy lookup of lowerdata in data-only layers
Date: Tue, 18 Apr 2023 15:06:32 +0200 [thread overview]
Message-ID: <eca2fa9f586da7b69c992e5447593a6e681029b8.camel@redhat.com> (raw)
In-Reply-To: <20230412135412.1684197-6-amir73il@gmail.com>
On Wed, 2023-04-12 at 16:54 +0300, Amir Goldstein wrote:
> Defer lookup of lowerdata in the data-only layers to first data
> access
> or before copy up.
>
> We perform lowerdata lookup before copy up even if copy up is
> metadata
> only copy up. We can further optimize this lookup later if needed.
>
> Signed-off-by: Amir Goldstein <amir73il@gmail.com>
LGTM
Reviewed-by: Alexander Larsson <alexl@redhat.com>
> ---
> fs/overlayfs/copy_up.c | 9 +++++++
> fs/overlayfs/file.c | 18 ++++++++++---
> fs/overlayfs/namei.c | 56 +++++++++++++++++++++++++++++++++++---
> --
> fs/overlayfs/overlayfs.h | 2 ++
> fs/overlayfs/ovl_entry.h | 2 +-
> fs/overlayfs/util.c | 31 +++++++++++++++++++++-
> 6 files changed, 105 insertions(+), 13 deletions(-)
>
> diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c
> index 7bf101e756c8..eb266fb68730 100644
> --- a/fs/overlayfs/copy_up.c
> +++ b/fs/overlayfs/copy_up.c
> @@ -1074,6 +1074,15 @@ static int ovl_copy_up_flags(struct dentry
> *dentry, int flags)
> if (WARN_ON(disconnected && d_is_dir(dentry)))
> return -EIO;
>
> + /*
> + * We may not need lowerdata if we are only doing metacopy
> up, but it is
> + * not very important to optimize this case, so do lazy
> lowerdata lookup
> + * before any copy up, so we can do it before taking
> ovl_inode_lock().
> + */
> + err = ovl_maybe_lookup_lowerdata(dentry);
> + if (err)
> + return err;
> +
> old_cred = ovl_override_creds(dentry->d_sb);
> while (!err) {
> struct dentry *next;
> diff --git a/fs/overlayfs/file.c b/fs/overlayfs/file.c
> index 951683a66ff6..39737c2aaa84 100644
> --- a/fs/overlayfs/file.c
> +++ b/fs/overlayfs/file.c
> @@ -107,15 +107,21 @@ static int ovl_real_fdget_meta(const struct
> file *file, struct fd *real,
> {
> struct dentry *dentry = file_dentry(file);
> struct path realpath;
> + int err;
>
> real->flags = 0;
> real->file = file->private_data;
>
> - if (allow_meta)
> + if (allow_meta) {
> ovl_path_real(dentry, &realpath);
> - else
> + } else {
> + /* lazy lookup of lowerdata */
> + err = ovl_maybe_lookup_lowerdata(dentry);
> + if (err)
> + return err;
> +
> ovl_path_realdata(dentry, &realpath);
> - /* TODO: lazy lookup of lowerdata */
> + }
> if (!realpath.dentry)
> return -EIO;
>
> @@ -153,6 +159,11 @@ static int ovl_open(struct inode *inode, struct
> file *file)
> struct path realpath;
> int err;
>
> + /* lazy lookup of lowerdata */
> + err = ovl_maybe_lookup_lowerdata(dentry);
> + if (err)
> + return err;
> +
> err = ovl_maybe_copy_up(dentry, file->f_flags);
> if (err)
> return err;
> @@ -161,7 +172,6 @@ static int ovl_open(struct inode *inode, struct
> file *file)
> file->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
>
> ovl_path_realdata(dentry, &realpath);
> - /* TODO: lazy lookup of lowerdata */
> if (!realpath.dentry)
> return -EIO;
>
> diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c
> index 82e103e2308b..ba2b156162ca 100644
> --- a/fs/overlayfs/namei.c
> +++ b/fs/overlayfs/namei.c
> @@ -889,6 +889,52 @@ static int ovl_fix_origin(struct ovl_fs *ofs,
> struct dentry *dentry,
> return err;
> }
>
> +/* Lazy lookup of lowerdata */
> +int ovl_maybe_lookup_lowerdata(struct dentry *dentry)
> +{
> + struct inode *inode = d_inode(dentry);
> + const char *redirect = ovl_lowerdata_redirect(inode);
> + struct ovl_path datapath = {};
> + const struct cred *old_cred;
> + int err;
> +
> + if (!redirect || ovl_dentry_lowerdata(dentry))
> + return 0;
> +
> + if (redirect[0] != '/')
> + return -EIO;
> +
> + err = ovl_inode_lock_interruptible(inode);
> + if (err)
> + return err;
> +
> + err = 0;
> + /* Someone got here before us? */
> + if (ovl_dentry_lowerdata(dentry))
> + goto out;
> +
> + old_cred = ovl_override_creds(dentry->d_sb);
> + err = ovl_lookup_data_layers(dentry, redirect, &datapath);
> + revert_creds(old_cred);
> + if (err)
> + goto out_err;
> +
> + err = ovl_dentry_set_lowerdata(dentry, &datapath);
> + if (err)
> + goto out_err;
> +
> +out:
> + ovl_inode_unlock(inode);
> + dput(datapath.dentry);
> +
> + return err;
> +
> +out_err:
> + pr_warn_ratelimited("lazy lowerdata lookup failed (%pd2,
> err=%i)\n",
> + dentry, err);
> + goto out;
> +}
> +
> struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
> unsigned int flags)
> {
> @@ -1074,14 +1120,10 @@ struct dentry *ovl_lookup(struct inode *dir,
> struct dentry *dentry,
> }
> }
>
> - /* Lookup absolute redirect from lower metacopy in data-only
> layers */
> + /* Defer lookup of lowerdata in data-only layers to first
> access */
> if (d.metacopy && ctr && ofs->numdatalayer &&
> d.absolute_redirect) {
> - err = ovl_lookup_data_layers(dentry, d.redirect,
> - &stack[ctr]);
> - if (!err) {
> - d.metacopy = false;
> - ctr++;
> - }
> + d.metacopy = false;
> + ctr++;
> }
>
> /*
> diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
> index 011b7b466f70..4e327665c316 100644
> --- a/fs/overlayfs/overlayfs.h
> +++ b/fs/overlayfs/overlayfs.h
> @@ -400,6 +400,7 @@ enum ovl_path_type ovl_path_realdata(struct
> dentry *dentry, struct path *path);
> struct dentry *ovl_dentry_upper(struct dentry *dentry);
> struct dentry *ovl_dentry_lower(struct dentry *dentry);
> struct dentry *ovl_dentry_lowerdata(struct dentry *dentry);
> +int ovl_dentry_set_lowerdata(struct dentry *dentry, struct ovl_path
> *datapath);
> const struct ovl_layer *ovl_i_layer_lower(struct inode *inode);
> const struct ovl_layer *ovl_layer_lower(struct dentry *dentry);
> struct dentry *ovl_dentry_real(struct dentry *dentry);
> @@ -562,6 +563,7 @@ 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_maybe_lookup_lowerdata(struct dentry *dentry);
> struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
> unsigned int flags);
> bool ovl_lower_positive(struct dentry *dentry);
> diff --git a/fs/overlayfs/ovl_entry.h b/fs/overlayfs/ovl_entry.h
> index 25fabb3175cf..a7b1006c5321 100644
> --- a/fs/overlayfs/ovl_entry.h
> +++ b/fs/overlayfs/ovl_entry.h
> @@ -145,7 +145,7 @@ static inline struct dentry
> *ovl_lowerdata_dentry(struct ovl_entry *oe)
> {
> struct ovl_path *lowerdata = ovl_lowerdata(oe);
>
> - return lowerdata ? lowerdata->dentry : NULL;
> + return lowerdata ? READ_ONCE(lowerdata->dentry) : NULL;
> }
>
> /* private information held for every overlayfs dentry */
> diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c
> index 284b5ba4fcf6..9a042768013e 100644
> --- a/fs/overlayfs/util.c
> +++ b/fs/overlayfs/util.c
> @@ -250,7 +250,13 @@ void ovl_path_lowerdata(struct dentry *dentry,
> struct path *path)
>
> if (lowerdata_dentry) {
> path->dentry = lowerdata_dentry;
> - path->mnt = lowerdata->layer->mnt;
> + /*
> + * Pairs with smp_wmb() in
> ovl_dentry_set_lowerdata().
> + * Make sure that if lowerdata->dentry is visible,
> then
> + * datapath->layer is visible as well.
> + */
> + smp_rmb();
> + path->mnt = READ_ONCE(lowerdata->layer)->mnt;
> } else {
> *path = (struct path) { };
> }
> @@ -312,6 +318,29 @@ struct dentry *ovl_dentry_lowerdata(struct
> dentry *dentry)
> return ovl_lowerdata_dentry(OVL_E(dentry));
> }
>
> +int ovl_dentry_set_lowerdata(struct dentry *dentry, struct ovl_path
> *datapath)
> +{
> + struct ovl_entry *oe = OVL_E(dentry);
> + struct ovl_path *lowerdata = ovl_lowerdata(oe);
> + struct dentry *datadentry = datapath->dentry;
> +
> + if (WARN_ON_ONCE(ovl_numlower(oe) <= 1))
> + return -EIO;
> +
> + WRITE_ONCE(lowerdata->layer, datapath->layer);
> + /*
> + * Pairs with smp_rmb() in ovl_path_lowerdata().
> + * Make sure that if lowerdata->dentry is visible, then
> + * lowerdata->layer is visible as well.
> + */
> + smp_wmb();
> + WRITE_ONCE(lowerdata->dentry, dget(datadentry));
> +
> + ovl_dentry_update_reval(dentry, datadentry);
> +
> + return 0;
> +}
> +
> struct dentry *ovl_dentry_real(struct dentry *dentry)
> {
> return ovl_dentry_upper(dentry) ?: ovl_dentry_lower(dentry);
--
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
=-=-=
Alexander Larsson Red Hat,
Inc
alexl@redhat.com alexander.larsson@gmail.com
He's an unconventional arachnophobic ex-con fleeing from a secret
government programme. She's a strong-willed motormouth politician from
out of town. They fight crime!
prev parent reply other threads:[~2023-04-18 13:07 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-04-12 13:54 [PATCH 0/5] Overlayfs lazy lookup of lowerdata Amir Goldstein
2023-04-12 13:54 ` [PATCH 1/5] ovl: remove unneeded goto instructions Amir Goldstein
2023-04-18 11:37 ` Alexander Larsson
2023-04-12 13:54 ` [PATCH 2/5] ovl: introduce data-only lower layers Amir Goldstein
2023-04-18 12:02 ` Alexander Larsson
2023-04-18 13:33 ` Amir Goldstein
2023-04-18 14:20 ` Alexander Larsson
2023-04-18 15:29 ` Amir Goldstein
2023-04-12 13:54 ` [PATCH 3/5] ovl: implement lookup in data-only layers Amir Goldstein
2023-04-18 12:40 ` Alexander Larsson
2023-04-18 13:41 ` Amir Goldstein
2023-04-18 14:00 ` Alexander Larsson
2023-04-18 14:07 ` Amir Goldstein
2023-04-12 13:54 ` [PATCH 4/5] ovl: prepare for lazy lookup of lowerdata inode Amir Goldstein
2023-04-18 12:53 ` Alexander Larsson
2023-04-26 14:56 ` Miklos Szeredi
2023-04-27 11:12 ` Amir Goldstein
2023-04-27 11:43 ` Amir Goldstein
2023-04-12 13:54 ` [PATCH 5/5] ovl: implement lazy lookup of lowerdata in data-only layers Amir Goldstein
2023-04-18 13:06 ` Alexander Larsson [this message]
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=eca2fa9f586da7b69c992e5447593a6e681029b8.camel@redhat.com \
--to=alexl@redhat.com \
--cc=amir73il@gmail.com \
--cc=linux-unionfs@vger.kernel.org \
--cc=miklos@szeredi.hu \
/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