From: Amir Goldstein <amir73il@gmail.com>
To: Miklos Szeredi <miklos@szeredi.hu>
Cc: linux-unionfs@vger.kernel.org
Subject: [PATCH 7/7] ovl: follow decoded origin file handle of merge dir
Date: Tue, 17 Oct 2017 18:23:53 +0300 [thread overview]
Message-ID: <1508253833-9866-8-git-send-email-amir73il@gmail.com> (raw)
In-Reply-To: <1508253833-9866-1-git-send-email-amir73il@gmail.com>
When 'verify_dir' feature is enabled, if lower dir does not match the
origin fh stored in upper dir, or if no lower dir was found by name,
try to decode the stored origin fh and use the result as the merge dir
lower dentry.
When there is more than a single lower layer, a lower merge directory
followed from upper dir by origin fh is not followed down again to lower
layers by name.
This is going to be used for overlayfs snapshots and NFS export.
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
---
Documentation/filesystems/overlayfs.txt | 6 +++++-
fs/dcache.c | 1 +
fs/overlayfs/namei.c | 37 ++++++++++++++++++++++++++++++---
3 files changed, 40 insertions(+), 4 deletions(-)
diff --git a/Documentation/filesystems/overlayfs.txt b/Documentation/filesystems/overlayfs.txt
index 17a3c9196fd3..d89041baceb9 100644
--- a/Documentation/filesystems/overlayfs.txt
+++ b/Documentation/filesystems/overlayfs.txt
@@ -279,7 +279,11 @@ the "trusted.overlay.redirect" extended attribute, will verify that the
found lower directory file handle and lower filesystem UUID match the
origin file handle that was stored at copy_up time. If a found lower
directory does not match the stored origin, that directory will be not be
-merged with the upper directory.
+merged with the upper directory. If the stored origin file handle can be
+decoded to an existing lower directory, the decoded directory will be
+merged with the upper directory instead. The "verify_dir" feature,
+therefore, makes an overlay mount cope better with the situations of
+lower directory rename and delete.
Testsuite
---------
diff --git a/fs/dcache.c b/fs/dcache.c
index f90141387f01..f61e03a38a30 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -3529,6 +3529,7 @@ bool is_subdir(struct dentry *new_dentry, struct dentry *old_dentry)
return result;
}
+EXPORT_SYMBOL(is_subdir);
static enum d_walk_ret d_genocide_kill(void *data, struct dentry *dentry)
{
diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c
index 988cb5496474..5de7aa60a7a6 100644
--- a/fs/overlayfs/namei.c
+++ b/fs/overlayfs/namei.c
@@ -83,9 +83,21 @@ static int ovl_check_redirect(struct dentry *dentry, struct ovl_lookup_data *d,
goto err_free;
}
-static int ovl_acceptable(void *ctx, struct dentry *dentry)
+static int ovl_acceptable(void *mnt, struct dentry *dentry)
{
- return 1;
+ /*
+ * A non-dir origin may be disconnected, which is fine, because
+ * we only need it for its unique inode number.
+ */
+ if (!d_is_dir(dentry))
+ return 1;
+
+ /* Don't want to follow a deleted empty lower directory */
+ if (d_unhashed(dentry))
+ return 0;
+
+ /* Check if directory belongs to the layer mounted at mnt */
+ return is_subdir(dentry, ((struct vfsmount *)mnt)->mnt_root);
}
static struct ovl_fh *ovl_get_origin_fh(struct dentry *dentry)
@@ -160,7 +172,7 @@ static struct dentry *ovl_get_origin(struct dentry *dentry,
bytes = (fh->len - offsetof(struct ovl_fh, fid));
origin = exportfs_decode_fh(mnt, (struct fid *)fh->fid,
bytes >> 2, (int)fh->type,
- ovl_acceptable, NULL);
+ ovl_acceptable, mnt);
if (IS_ERR(origin)) {
/* Treat stale file handle as "origin unknown" */
if (origin == ERR_PTR(-ESTALE))
@@ -697,6 +709,25 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
}
}
+ /*
+ * If lower not found by name or couldn't verify origin fh, try to
+ * follow the decoded origin fh in upper to the first lower dir.
+ */
+ if (!d.stop && poe->numlower && upperdentry && !ctr &&
+ ovl_verify_dir(dentry->d_sb)) {
+ err = ovl_check_origin(upperdentry, roe->lowerstack,
+ roe->numlower, &stack, &ctr);
+ if (err)
+ goto out_put;
+ /*
+ * XXX: We do not continue layers lookup from decoded origin for
+ * more than a single lower layer. This would require setting
+ * d.redirect to decoded origin path and jump back to the
+ * lowerstack layers lookup loop with 'i' set to the root layer
+ * number where we found the decoded origin.
+ */
+ }
+
/* Lookup index by lower inode and verify it matches upper inode */
if (ctr && !d.is_dir && ovl_indexdir(dentry->d_sb)) {
struct dentry *origin = stack[0].dentry;
--
2.7.4
prev parent reply other threads:[~2017-10-17 15:23 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-10-17 15:23 [PATCH 0/7] Implement overlayfs verify_dir mount option Amir Goldstein
2017-10-17 15:23 ` [PATCH 1/7] ovl: fix rmdir problem on origin dir Amir Goldstein
2017-10-31 12:54 ` Miklos Szeredi
2017-10-17 15:23 ` [PATCH 2/7] ovl: no direct iteration for dir with copy up origin Amir Goldstein
2017-10-31 13:08 ` Miklos Szeredi
2017-10-17 15:23 ` [PATCH 3/7] ovl: remove unneeded arg from ovl_verify_origin() Amir Goldstein
2017-10-17 15:23 ` [PATCH 4/7] ovl: disable redirect_dir and index when no xattr support Amir Goldstein
2017-10-17 15:23 ` [PATCH 5/7] ovl: ignore redirect_dir and index when no upper layer Amir Goldstein
2017-10-17 15:23 ` [PATCH 6/7] ovl: add support for verify_dir mount option Amir Goldstein
2017-10-17 15:23 ` Amir Goldstein [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=1508253833-9866-8-git-send-email-amir73il@gmail.com \
--to=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;
as well as URLs for NNTP newsgroup(s).