linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Amir Goldstein <amir73il@gmail.com>
To: Miklos Szeredi <miklos@szeredi.hu>
Cc: Al Viro <viro@zeniv.linux.org.uk>,
	linux-unionfs@vger.kernel.org, linux-fsdevel@vger.kernel.org
Subject: [PATCH v2 23/23] ovl: copy up on read operations on indexed lower
Date: Thu,  8 Jun 2017 18:00:49 +0300	[thread overview]
Message-ID: <1496934049-11216-3-git-send-email-amir73il@gmail.com> (raw)
In-Reply-To: <1496934049-11216-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 accessing a lower hardlink for read, 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.

The following test demonstrates the upper/lower hardlinks inconsistency:

$ echo -n a > /lower/foo
$ ln /lower/foo /lower/bar
$ cd /mnt
$ tail foo bar # both aliases are ro lower
==> foo <==
a
==> bar <==
a

$ echo -n b >> foo
$ tail foo bar # foo is rw upper, bar is ro lower
==> foo <==
ab
==> bar <==
a

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

Signed-off-by: Amir Goldstein <amir73il@gmail.com>
---
 fs/overlayfs/copy_up.c   | 28 ++++++++++++++++++++++++++++
 fs/overlayfs/overlayfs.h |  1 +
 fs/overlayfs/super.c     |  4 +++-
 fs/overlayfs/util.c      | 12 +++++++++++-
 4 files changed, 43 insertions(+), 2 deletions(-)

diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c
index 8a297cfc33fb..27aabed25680 100644
--- a/fs/overlayfs/copy_up.c
+++ b/fs/overlayfs/copy_up.c
@@ -1023,3 +1023,31 @@ int ovl_open_maybe_copy_up(struct dentry *dentry, unsigned int file_flags)
 
 	return err;
 }
+
+/* Copy up on read ops of non-dir indexed lower */
+int ovl_maybe_ro_copy_up(struct dentry *dentry)
+{
+	enum ovl_path_type type = ovl_path_type(dentry);
+	int err;
+
+	if (WARN_ON(!d_inode(dentry)) || d_is_dir(dentry) ||
+	    OVL_TYPE_UPPER(type) || !OVL_TYPE_INDEX(type))
+		return 0;
+
+	err = ovl_want_write(dentry);
+	if (err)
+		goto fail;
+
+	err = ovl_copy_up(dentry);
+	ovl_drop_write(dentry);
+
+	if (err)
+		goto fail;
+
+	return 0;
+
+fail:
+	pr_warn_ratelimited("overlayfs: failed copy up on read (%pd2, err=%i)\n",
+			    dentry, err);
+	return err;
+}
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
index 434870f5bb4b..10df85d41546 100644
--- a/fs/overlayfs/overlayfs.h
+++ b/fs/overlayfs/overlayfs.h
@@ -305,6 +305,7 @@ void ovl_cleanup(struct inode *dir, struct dentry *dentry);
 /* copy_up.c */
 int ovl_copy_up(struct dentry *dentry);
 int ovl_open_maybe_copy_up(struct dentry *dentry, unsigned int file_flags);
+int ovl_maybe_ro_copy_up(struct dentry *dentry);
 int ovl_copy_xattr(struct dentry *old, struct dentry *new);
 int ovl_set_attr(struct dentry *upper, struct kstat *stat);
 struct ovl_fh *ovl_encode_fh(struct dentry *lower, bool is_upper);
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
index 4cf18850b4de..5ef9ce7489be 100644
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -76,6 +76,8 @@ static struct dentry *ovl_d_real(struct dentry *dentry,
 				 unsigned int open_flags)
 {
 	struct dentry *real;
+	/* Copy up on open for read of indexed lower */
+	bool rocopyup = !inode && ovl_indexdir(dentry->d_sb);
 	int err;
 
 	if (!d_is_reg(dentry)) {
@@ -87,7 +89,7 @@ static struct dentry *ovl_d_real(struct dentry *dentry,
 	if (d_is_negative(dentry))
 		return dentry;
 
-	if (open_flags) {
+	if (open_flags || rocopyup) {
 		err = ovl_open_maybe_copy_up(dentry, open_flags);
 		if (err)
 			return ERR_PTR(err);
diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c
index fa6c2ae4a747..bad3df557cc6 100644
--- a/fs/overlayfs/util.c
+++ b/fs/overlayfs/util.c
@@ -14,6 +14,7 @@
 #include <linux/xattr.h>
 #include <linux/exportfs.h>
 #include <linux/uuid.h>
+#include <linux/ratelimit.h>
 #include "overlayfs.h"
 #include "ovl_entry.h"
 
@@ -131,10 +132,15 @@ void ovl_path_lower(struct dentry *dentry, struct path *path)
 	*path = oe->numlower ? oe->lowerstack[0] : (struct path) { };
 }
 
+/* Caller must not hold ovl_want_write(dentry) */
 enum ovl_path_type ovl_path_real(struct dentry *dentry, struct path *path)
 {
-	enum ovl_path_type type = ovl_path_type(dentry);
+	enum ovl_path_type type;
 
+	/* best effort copy up indexed lower */
+	ovl_maybe_ro_copy_up(dentry);
+
+	type = ovl_path_type(dentry);
 	if (!OVL_TYPE_UPPER(type))
 		ovl_path_lower(dentry, path);
 	else
@@ -169,11 +175,15 @@ struct dentry *ovl_dentry_index(struct dentry *dentry)
 	return oe->indexdentry;
 }
 
+/* Caller must not hold ovl_want_write(dentry) */
 struct dentry *ovl_dentry_real(struct dentry *dentry)
 {
 	struct ovl_entry *oe = dentry->d_fsdata;
 	struct dentry *realdentry;
 
+	/* Best effort copy up of indexed lower */
+	ovl_maybe_ro_copy_up(dentry);
+
 	realdentry = ovl_upperdentry_dereference(oe);
 	if (!realdentry)
 		realdentry = __ovl_dentry_lower(oe);
-- 
2.7.4

  parent reply	other threads:[~2017-06-08 15:00 UTC|newest]

Thread overview: 41+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-06-07  7:51 [PATCH v2 00/20] Overlayfs inodes index Amir Goldstein
2017-06-07  7:51 ` [PATCH v2 01/20] vfs: introduce inode 'inuse' lock Amir Goldstein
2017-06-07  7:51 ` [PATCH v2 02/20] ovl: get exclusive ownership on upper/work dirs Amir Goldstein
2017-06-07  7:51 ` [PATCH v2 03/20] ovl: relax same fs constrain for ovl_check_origin() Amir Goldstein
2017-06-07  7:51 ` [PATCH v2 04/20] ovl: generalize ovl_create_workdir() Amir Goldstein
2017-06-07  7:51 ` [PATCH v2 05/20] ovl: introduce the inodes index dir feature Amir Goldstein
2017-06-07  7:51 ` [PATCH v2 06/20] ovl: verify upper root dir matches lower root dir Amir Goldstein
2017-06-07  7:51 ` [PATCH v2 07/20] ovl: verify index dir matches upper dir Amir Goldstein
2017-06-07  7:51 ` [PATCH v2 08/20] ovl: lookup index entry for non-dir Amir Goldstein
2017-06-08 12:11   ` Miklos Szeredi
2017-06-08 14:48     ` Amir Goldstein
2017-06-08 15:17       ` Miklos Szeredi
2017-06-08 16:09         ` Amir Goldstein
2017-06-09  8:43           ` Miklos Szeredi
2017-06-09  9:38             ` Amir Goldstein
2017-06-09 11:49               ` Miklos Szeredi
2017-06-09 13:14                 ` Miklos Szeredi
2017-06-09 13:24                   ` Amir Goldstein
2017-06-09 13:29                     ` Miklos Szeredi
2017-06-09 22:56                   ` Amir Goldstein
2017-06-07  7:51 ` [PATCH v2 09/20] ovl: move inode helpers to inode.c Amir Goldstein
2017-06-07  7:51 ` [PATCH v2 10/20] ovl: use ovl_inode_init() for initializing new inode Amir Goldstein
2017-06-07  7:51 ` [PATCH v2 11/20] ovl: hash overlay non-dir inodes by copy up origin inode Amir Goldstein
2017-06-07  7:51 ` [PATCH v2 12/20] ovl: fix nlink leak in ovl_rename() Amir Goldstein
2017-06-07  7:51 ` [PATCH v2 13/20] ovl: adjust overlay inode nlink for indexed inodes Amir Goldstein
2017-06-07  7:51 ` [PATCH v2 14/20] ovl: defer upper dir lock to tempfile link Amir Goldstein
2017-06-07  7:51 ` [PATCH v2 15/20] ovl: factor out ovl_copy_up_inode() helper Amir Goldstein
2017-06-07  7:51 ` [PATCH v2 16/20] ovl: generalize ovl_copy_up_locked() using actors Amir Goldstein
2017-06-07  7:51 ` [PATCH v2 17/20] ovl: generalize ovl_copy_up_one() " Amir Goldstein
2017-06-07  7:51 ` [PATCH v2 18/20] ovl: implement index dir copy up method Amir Goldstein
2017-06-07  7:51 ` [PATCH v2 19/20] ovl: handle race of concurrent lower hardlinks copy up Amir Goldstein
2017-06-07  7:51 ` [PATCH v2 20/20] ovl: constant inode number for hardlinks Amir Goldstein
2017-06-07  7:54 ` [PATCH v2 00/20] Overlayfs inodes index Miklos Szeredi
2017-06-07  7:58   ` Amir Goldstein
2017-06-07 14:58 ` Amir Goldstein
2017-06-08 15:00   ` [PATCH v2 21/23] ovl: use inodes index on readonly mount Amir Goldstein
2017-06-08 15:00     ` [PATCH v2 22/23] ovl: move copy up helpers to copy_up.c Amir Goldstein
2017-06-08 15:00     ` Amir Goldstein [this message]
2017-06-07 17:17 ` [PATCH v2 00/20] Overlayfs inodes index J. Bruce Fields
2017-06-07 18:36   ` Amir Goldstein
2017-06-07 18:59     ` J. Bruce Fields

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=1496934049-11216-3-git-send-email-amir73il@gmail.com \
    --to=amir73il@gmail.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-unionfs@vger.kernel.org \
    --cc=miklos@szeredi.hu \
    --cc=viro@zeniv.linux.org.uk \
    /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).