From: Amir Goldstein <amir73il@gmail.com>
To: Miklos Szeredi <miklos@szeredi.hu>
Cc: Vivek Goyal <vgoyal@redhat.com>, cgxu519 <cgxu519@gmx.com>,
linux-unionfs@vger.kernel.org
Subject: [RFC][PATCH v2 3/5] ovl: lazy copy up of data on first data access
Date: Tue, 22 Jan 2019 14:34:55 +0200 [thread overview]
Message-ID: <20190122123457.10600-4-amir73il@gmail.com> (raw)
In-Reply-To: <20190122123457.10600-1-amir73il@gmail.com>
When metacopy feature is enabled and filemap operations supported,
copy up only metadata when opening a file O_RDWR and defer copy up
of data until the first data access file operation.
Copy up on first page fault will be handled by a followup patch.
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
---
fs/overlayfs/copy_up.c | 5 +---
fs/overlayfs/file.c | 63 +++++++++++++++++++++++++++++++++++-----
fs/overlayfs/overlayfs.h | 10 ++++++-
fs/overlayfs/util.c | 4 +--
4 files changed, 68 insertions(+), 14 deletions(-)
diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c
index 05f853c7db0d..92a27ba65c78 100644
--- a/fs/overlayfs/copy_up.c
+++ b/fs/overlayfs/copy_up.c
@@ -731,10 +731,7 @@ static bool ovl_need_meta_copy_up(struct dentry *dentry, umode_t mode,
if (!S_ISREG(mode))
return false;
- if (flags && ((OPEN_FMODE(flags) & FMODE_WRITE) || (flags & O_TRUNC)))
- return false;
-
- return true;
+ return !ovl_open_flags_need_data_copy_up(flags);
}
/* Copy up data of an inode which was copied up metadata only in the past. */
diff --git a/fs/overlayfs/file.c b/fs/overlayfs/file.c
index 5f648979adbf..e02b61af9488 100644
--- a/fs/overlayfs/file.c
+++ b/fs/overlayfs/file.c
@@ -90,10 +90,24 @@ static int ovl_real_fdget_meta(const struct file *file, struct fd *real,
{
struct inode *inode = file_inode(file);
struct inode *realinode;
+ int err;
real->flags = 0;
real->file = file->private_data;
+ /*
+ * Lazy copy up caches the meta copy upper file on open O_RDWR.
+ * We need to promote upper inode to full data copy up before
+ * we allow access to real file data on a writable file, otherwise
+ * we may try to open a lower file O_RDWR or perform data operations
+ * (e.g. fallocate) on the metacopy inode.
+ */
+ if (!allow_meta) {
+ err = ovl_maybe_copy_up(file_dentry(file), file->f_flags);
+ if (err)
+ return err;
+ }
+
if (allow_meta)
realinode = ovl_inode_real(inode);
else
@@ -127,11 +141,34 @@ static bool ovl_filemap_support(struct file *file)
return ofs->upper_mnt && ovl_aops.writepage;
}
-static bool ovl_should_use_filemap(struct file *file)
+static bool ovl_should_use_filemap_meta(struct file *file, bool meta_only)
{
+ int err;
+
if (!ovl_filemap_support(file))
return false;
+ /*
+ * If file was opened O_RDWR with lazy copy up of data, the first
+ * data access file operation will trigger data copy up. If file was
+ * opened O_RDWR and @meta_only is true, we use overlay inode filemap
+ * operations, but defer data copy up further.
+ *
+ * For example, mmap() and fsync() are metadata only operations that
+ * do not trigger lazy copy up of data, but read() (on a file open for
+ * write) is a data access operation that does trigger data copy up.
+ */
+ if (!meta_only) {
+ err = ovl_maybe_copy_up(file_dentry(file), file->f_flags);
+ if (err) {
+ pr_warn_ratelimited("overlayfs: failed lazy copy up data (%pd2, err=%i)\n",
+ file_dentry(file), err);
+ return false;
+ }
+ } else if (file->f_mode & FMODE_WRITE) {
+ return true;
+ }
+
/*
* Use overlay inode page cache for all inodes that could be dirty,
* including pure upper inodes, so ovl_sync_fs() can sync all dirty
@@ -140,9 +177,14 @@ static bool ovl_should_use_filemap(struct file *file)
return ovl_has_upperdata(file_inode(file));
}
+static bool ovl_should_use_filemap(struct file *file)
+{
+ return ovl_should_use_filemap_meta(file, false);
+}
+
static int ovl_flush_filemap(struct file *file, loff_t offset, loff_t len)
{
- if (!ovl_should_use_filemap(file))
+ if (!ovl_should_use_filemap_meta(file, true))
return 0;
return filemap_write_and_wait_range(file_inode(file)->i_mapping,
@@ -152,16 +194,23 @@ static int ovl_flush_filemap(struct file *file, loff_t offset, loff_t len)
static int ovl_open(struct inode *inode, struct file *file)
{
struct file *realfile;
+ int metacopy = 0;
int err;
- err = ovl_maybe_copy_up(file_dentry(file), file->f_flags);
+ /* (O_RDWR | O_WRONLY) signals that we want meta copy up */
+ if (ovl_filemap_support(file) && (file->f_flags & O_ACCMODE) == O_RDWR)
+ metacopy = (O_RDWR | O_WRONLY);
+
+ /* Allow to copy up meta and defer copy up data to first data access */
+ err = ovl_maybe_copy_up(file_dentry(file), file->f_flags | metacopy);
if (err)
return err;
/* No longer need these flags, so don't pass them on to underlying fs */
file->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
- realfile = ovl_open_realfile(file, ovl_inode_realdata(inode));
+ realfile = ovl_open_realfile(file, metacopy ? ovl_inode_real(inode) :
+ ovl_inode_realdata(inode));
if (IS_ERR(realfile))
return PTR_ERR(realfile);
@@ -337,7 +386,7 @@ static int ovl_real_fsync(struct file *file, loff_t start, loff_t end,
static int ovl_fsync(struct file *file, loff_t start, loff_t end, int datasync)
{
- if (ovl_should_use_filemap(file))
+ if (ovl_should_use_filemap_meta(file, true))
return __generic_file_fsync(file, start, end, datasync);
return ovl_real_fsync(file, start, end, datasync);
@@ -381,7 +430,7 @@ static int ovl_real_mmap(struct file *file, struct vm_area_struct *vma)
static int ovl_mmap(struct file *file, struct vm_area_struct *vma)
{
- if (ovl_should_use_filemap(file))
+ if (ovl_should_use_filemap_meta(file, true))
generic_file_mmap(file, vma);
return ovl_real_mmap(file, vma);
@@ -441,7 +490,7 @@ extern int generic_fadvise(struct file *file, loff_t offset, loff_t len,
static int ovl_fadvise(struct file *file, loff_t offset, loff_t len, int advice)
{
- if (ovl_should_use_filemap(file))
+ if (ovl_should_use_filemap_meta(file, true))
return generic_fadvise(file, offset, len, advice);
/* XXX: Should we allow messing with lower shared page cache? */
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
index ab61c07e8583..6baa3460c173 100644
--- a/fs/overlayfs/overlayfs.h
+++ b/fs/overlayfs/overlayfs.h
@@ -195,14 +195,22 @@ static inline struct dentry *ovl_do_tmpfile(struct dentry *dentry, umode_t mode)
return ret;
}
-static inline bool ovl_open_flags_need_copy_up(int flags)
+static inline bool ovl_open_flags_need_data_copy_up(int flags)
{
if (!flags)
return false;
+ /* Either O_RDWR or O_WRONLY will trigger data copy up */
return ((OPEN_FMODE(flags) & FMODE_WRITE) || (flags & O_TRUNC));
}
+static inline bool ovl_open_flags_need_copy_up(int flags)
+{
+ /* O_RDWR|O_WRONLY together will trigger meta copy up */
+ return (flags & O_ACCMODE) == (O_RDWR | O_WRONLY) ||
+ ovl_open_flags_need_data_copy_up(flags);
+}
+
/* util.c */
int ovl_want_write(struct dentry *dentry);
void ovl_drop_write(struct dentry *dentry);
diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c
index 7c01327b1852..df6d13185f40 100644
--- a/fs/overlayfs/util.c
+++ b/fs/overlayfs/util.c
@@ -367,7 +367,7 @@ void ovl_set_upperdata(struct inode *inode)
/* Caller should hold ovl_inode->lock */
bool ovl_dentry_needs_data_copy_up_locked(struct dentry *dentry, int flags)
{
- if (!ovl_open_flags_need_copy_up(flags))
+ if (!ovl_open_flags_need_data_copy_up(flags))
return false;
return !ovl_test_flag(OVL_UPPERDATA, d_inode(dentry));
@@ -375,7 +375,7 @@ bool ovl_dentry_needs_data_copy_up_locked(struct dentry *dentry, int flags)
bool ovl_dentry_needs_data_copy_up(struct dentry *dentry, int flags)
{
- if (!ovl_open_flags_need_copy_up(flags))
+ if (!ovl_open_flags_need_data_copy_up(flags))
return false;
return !ovl_has_upperdata(d_inode(dentry));
--
2.17.1
next prev parent reply other threads:[~2019-01-22 12:34 UTC|newest]
Thread overview: 42+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-01-22 12:34 [RFC][PATCH v2 0/5] Experiments with overlayfs filemap Amir Goldstein
2019-01-22 12:34 ` [RFC][PATCH v2 1/5] ovl: reorder tests in ovl_open_need_copy_up() Amir Goldstein
2019-01-22 12:34 ` [RFC][PATCH v2 2/5] ovl: prepare for generic filemap file operations Amir Goldstein
2019-01-22 12:34 ` Amir Goldstein [this message]
2019-01-22 12:34 ` [RFC][PATCH v2 4/5] ovl: lazy copy up data on page fault Amir Goldstein
2019-01-22 12:34 ` [RFC][PATCH v2 5/5] ovl: noop aops to test filemap operations and lazy copy up Amir Goldstein
2019-01-24 17:18 ` [RFC][PATCH v2 0/5] Experiments with overlayfs filemap Amir Goldstein
2019-01-24 22:35 ` Amir Goldstein
2019-01-25 9:54 ` Miklos Szeredi
2019-01-25 11:24 ` Amir Goldstein
2019-01-25 12:21 ` Miklos Szeredi
2019-01-25 13:04 ` Amir Goldstein
2019-01-25 13:31 ` Miklos Szeredi
2019-01-25 15:56 ` Miklos Szeredi
2019-01-25 21:18 ` Amir Goldstein
2019-01-27 18:22 ` Amir Goldstein
2019-01-28 19:22 ` Vivek Goyal
2019-01-28 20:57 ` Amir Goldstein
2019-01-28 21:17 ` Miklos Szeredi
2019-01-28 21:22 ` Miklos Szeredi
2019-01-28 22:14 ` Amir Goldstein
2019-01-29 7:17 ` Miklos Szeredi
2019-01-29 8:54 ` Amir Goldstein
2019-01-29 8:58 ` Miklos Szeredi
2019-01-29 9:12 ` Amir Goldstein
2019-01-29 12:44 ` Miklos Szeredi
2019-01-29 16:47 ` Amir Goldstein
2019-01-31 16:23 ` Miklos Szeredi
2019-01-31 21:54 ` Amir Goldstein
2019-02-01 9:14 ` Miklos Szeredi
2019-02-01 13:22 ` Amir Goldstein
2019-02-01 16:29 ` Vivek Goyal
2019-02-01 13:25 ` Amir Goldstein
2019-02-01 16:24 ` Miklos Szeredi
2019-02-01 16:47 ` Vivek Goyal
2019-02-02 16:51 ` Amir Goldstein
2019-02-05 7:42 ` Amir Goldstein
2019-02-05 7:50 ` Miklos Szeredi
2019-02-05 13:03 ` Amir Goldstein
2019-02-06 15:36 ` Miklos Szeredi
2019-02-12 7:43 ` Amir Goldstein
2019-02-12 8:11 ` Miklos Szeredi
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=20190122123457.10600-4-amir73il@gmail.com \
--to=amir73il@gmail.com \
--cc=cgxu519@gmx.com \
--cc=linux-unionfs@vger.kernel.org \
--cc=miklos@szeredi.hu \
--cc=vgoyal@redhat.com \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.