public inbox for linux-unionfs@vger.kernel.org
 help / color / mirror / Atom feed
From: Amir Goldstein <amir73il@gmail.com>
To: Miklos Szeredi <miklos@szeredi.hu>
Cc: linux-unionfs@vger.kernel.org
Subject: [PATCH v4 22/25] ovl: link up indexed lower hardlink on lookup
Date: Wed, 21 Jun 2017 15:28:53 +0300	[thread overview]
Message-ID: <1498048136-28218-23-git-send-email-amir73il@gmail.com> (raw)
In-Reply-To: <1498048136-28218-1-git-send-email-amir73il@gmail.com>

With inodes index feature, all lower and upper hardlinks point to
the same overlay inode. However, when a lower hardlink is accessed
for read operation, the real inode operated on is not the same inode
as the real inode for read operation on an upper hardlink.

When lookup finds a lower hardlink, which is already indexed by
an earlier upper hardlink copy up, call ovl_copy_up() to link the
indexed upper on top of the lower hardlink and then operate on the
upper real inode to avoid this inconsistency.

Invalidate a lower indexed dentry on dcache lookup, so ovl_lookup()
is called to perform the index link up.

The following test demonstrates the upper/lower hardlinks inconsistency:

$ echo -n a > /lower/foo
$ ln /lower/foo /lower/bar
$ cd /mnt
$ echo -n b >> foo
$ tail foo bar # foo is indexed upper, bar is indexed lower
==> foo <==
ab
==> bar <==
a

$ echo -n c >> bar
$ tail foo bar # both aliases are indexed upper
==> foo <==
abc
==> bar <==
abc

Signed-off-by: Amir Goldstein <amir73il@gmail.com>
---
 fs/overlayfs/namei.c | 20 ++++++++++++++++++--
 fs/overlayfs/super.c | 39 +++++++++++++++++++++++++++++++++------
 2 files changed, 51 insertions(+), 8 deletions(-)

diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c
index 08154dad725e..c6b986b68105 100644
--- a/fs/overlayfs/namei.c
+++ b/fs/overlayfs/namei.c
@@ -659,7 +659,14 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
 			goto out_put;
 
 		if (!upperdentry) {
-			/* TODO: handle lookup of lower indexed entries */
+			/*
+			 * At this point, if we find a positive index, we cannot
+			 * tell if the index entry has been created by a copy up
+			 * in progress, because we don't have the overlay inode
+			 * and we don't hold the overlay inode oi_lock. So we
+			 * will treat this entry as non-indexed lower and will
+			 * try to link it up before returning from lookup.
+			 */
 		} else if (index && d_inode(index)) {
 			/* Vertified indexed upper */
 			type |= __OVL_PATH_INDEX;
@@ -722,13 +729,22 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
 	oe->redirect = upperredirect;
 	oe->__upperdentry = upperdentry;
 	memcpy(oe->lowerstack, stack, sizeof(struct path) * ctr);
-	dput(index);
 	kfree(stack);
 	kfree(d.redirect);
 	dentry->d_fsdata = oe;
 	ovl_update_type(dentry, d.is_dir);
 	d_add(dentry, inode);
 
+	/* Link up indexed lower early for consistent overlay hardlinks */
+	if (index && d_inode(index) && !upperdentry) {
+		err = ovl_copy_up(dentry);
+		if (err) {
+			pr_warn_ratelimited("overlayfs: failed link up to index (%pd2, index=%pd2, err=%i)\n",
+					    dentry, index, err);
+		}
+	}
+	dput(index);
+
 	return NULL;
 
 out_free_oe:
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
index 144354b5fcf1..d6604bbe0a66 100644
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -117,11 +117,43 @@ static struct dentry *ovl_d_real(struct dentry *dentry,
 	return dentry;
 }
 
+static int ovl_dentry_indexed_revalidate(struct dentry *dentry,
+					 unsigned int flags)
+{
+	enum ovl_path_type type = ovl_path_type(dentry);
+	bool is_upper;
+
+	if (!ovl_indexdir(dentry->d_sb) ||
+	    d_is_dir(dentry) || d_is_negative(dentry))
+		return 1;
+
+	/*
+	 * Invalidate lower hardlink after it has been indexed by copy up
+	 * of another lower alias. ovl_lookup will trigger copy up of this
+	 * path and link the upper path to the upper index inode.
+	 */
+	ovl_inode_real(d_inode(dentry), &is_upper);
+	if (is_upper && !OVL_TYPE_UPPER(type))
+		return 0;
+
+	return 1;
+}
+
+static const struct dentry_operations ovl_dentry_operations = {
+	.d_release = ovl_dentry_release,
+	.d_real = ovl_d_real,
+	.d_revalidate = ovl_dentry_indexed_revalidate,
+};
+
 static int ovl_dentry_revalidate(struct dentry *dentry, unsigned int flags)
 {
 	struct ovl_entry *oe = dentry->d_fsdata;
 	unsigned int i;
-	int ret = 1;
+	int ret;
+
+	ret = ovl_dentry_indexed_revalidate(dentry, flags);
+	if (ret < 1)
+		return ret;
 
 	for (i = 0; i < oe->numlower; i++) {
 		struct dentry *d = oe->lowerstack[i].dentry;
@@ -158,11 +190,6 @@ static int ovl_dentry_weak_revalidate(struct dentry *dentry, unsigned int flags)
 	return ret;
 }
 
-static const struct dentry_operations ovl_dentry_operations = {
-	.d_release = ovl_dentry_release,
-	.d_real = ovl_d_real,
-};
-
 static const struct dentry_operations ovl_reval_dentry_operations = {
 	.d_release = ovl_dentry_release,
 	.d_real = ovl_d_real,
-- 
2.7.4

  parent reply	other threads:[~2017-06-21 12:29 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-06-21 12:28 [PATCH v4 00/25] Overlayfs inodes index Amir Goldstein
2017-06-21 12:28 ` [PATCH v4 01/25] vfs: introduce inode 'inuse' lock Amir Goldstein
2017-06-21 12:28 ` [PATCH v4 02/25] ovl: get exclusive ownership on upper/work dirs Amir Goldstein
2017-06-21 12:28 ` [PATCH v4 03/25] ovl: relax same fs constrain for ovl_check_origin() Amir Goldstein
2017-06-21 12:28 ` [PATCH v4 04/25] ovl: generalize ovl_create_workdir() Amir Goldstein
2017-06-21 12:28 ` [PATCH v4 05/25] ovl: introduce the inodes index dir feature Amir Goldstein
2017-06-21 12:28 ` [PATCH v4 06/25] ovl: verify upper root dir matches lower root dir Amir Goldstein
2017-06-21 12:28 ` [PATCH v4 07/25] ovl: verify index dir matches upper dir Amir Goldstein
2017-06-21 12:28 ` [PATCH v4 08/25] ovl: store path type in dentry Amir Goldstein
2017-06-21 12:28 ` [PATCH v4 09/25] ovl: cram dentry state booleans into type flags Amir Goldstein
2017-06-21 12:28 ` [PATCH v4 10/25] ovl: lookup index entry for copy up origin Amir Goldstein
2017-06-21 12:28 ` [PATCH v4 11/25] ovl: cleanup bad and stale index entries on mount Amir Goldstein
2017-06-21 12:28 ` [PATCH v4 12/25] ovl: allocate an ovl_inode struct Amir Goldstein
2017-06-21 12:28 ` [PATCH v4 13/25] ovl: store upper/lower real inode in ovl_inode_info Amir Goldstein
2017-06-21 12:28 ` [PATCH v4 14/25] ovl: use ovl_inode_init() for initializing new inode Amir Goldstein
2017-06-21 12:28 ` [PATCH v4 15/25] ovl: hash overlay non-dir inodes by copy up origin inode Amir Goldstein
2017-06-21 12:28 ` [PATCH v4 16/25] ovl: defer upper dir lock to tempfile link Amir Goldstein
2017-06-21 12:28 ` [PATCH v4 17/25] ovl: factor out ovl_copy_up_inode() helper Amir Goldstein
2017-06-21 12:28 ` [PATCH v4 18/25] ovl: generalize ovl_copy_up_locked() using actors Amir Goldstein
2017-06-21 12:28 ` [PATCH v4 19/25] ovl: generalize ovl_copy_up_one() " Amir Goldstein
2017-06-21 12:28 ` [PATCH v4 20/25] ovl: use ovl_inode mutex to synchronize concurrent copy up Amir Goldstein
2017-06-21 12:28 ` [PATCH v4 21/25] ovl: implement index dir copy up method Amir Goldstein
2017-06-21 12:28 ` Amir Goldstein [this message]
2017-06-21 12:28 ` [PATCH v4 23/25] ovl: fix nlink leak in ovl_rename() Amir Goldstein
2017-06-21 12:28 ` [PATCH v4 24/25] ovl: persistent overlay inode nlink for indexed inodes Amir Goldstein
2017-06-23 11:34   ` Amir Goldstein
2017-06-21 12:28 ` [PATCH v4 25/25] ovl: cleanup orphan index entries Amir Goldstein
2017-06-21 16:45   ` Amir Goldstein
2017-06-21 17:02 ` [PATCH v4 00/25] Overlayfs inodes index Amir Goldstein
2017-06-21 20:03   ` Amir Goldstein
2017-06-22 10:18 ` [PATCH v4 26/25] ovl: document copying layers restrictions with " 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=1498048136-28218-23-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