[PATCH v14 26/31] ovl: Allow ovl_open_realfile() to open metacopy inode

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Most of the time we need to open inode containing data (and not metacopy)
but when fsync happens, in that case we need to make sure upper metacopy
inode is fsynced too. In that case we need to open metacopy inode
temporarily.

Add a parameter to ovl_open_realfile() which specifies whether to open
data inode or metacopy inode. Later fsync patch will make use of this
functionality.

Signed-off-by: Vivek Goyal <vgoyal@xxxxxxxxxx>
---
 fs/overlayfs/file.c | 34 ++++++++++++++++++++++++++++------
 1 file changed, 28 insertions(+), 6 deletions(-)

diff --git a/fs/overlayfs/file.c b/fs/overlayfs/file.c
index 558a859b2658..08387639ba6e 100644
--- a/fs/overlayfs/file.c
+++ b/fs/overlayfs/file.c
@@ -14,7 +14,7 @@
 #include <linux/uio.h>
 #include "overlayfs.h"
 
-static struct file *ovl_open_realfile(const struct file *file)
+static struct file *ovl_open_realfile(const struct file *file, bool meta)
 {
 	struct inode *inode = file_inode(file);
 	struct inode *upperinode = ovl_inode_upper(inode);
@@ -28,7 +28,13 @@ static struct file *ovl_open_realfile(const struct file *file)
 
 	/* Always open file which contains data. Do not open metacopy. */
 	realinode = upperreal ? upperinode : ovl_inode_lowerdata(inode);
-
+	if (upperinode && (meta || ovl_has_upperdata(inode))) {
+		realinode = upperinode;
+		upperreal = true;
+	} else {
+		realinode = meta ? ovl_inode_lower(inode) :
+				 ovl_inode_lowerdata(inode);
+	}
 	old_cred = ovl_override_creds(inode->i_sb);
 	realfile = path_open(&file->f_path, file->f_flags | O_NOATIME,
 			     realinode, current_cred(), false);
@@ -80,17 +86,23 @@ static int ovl_change_flags(struct file *file, unsigned int flags)
 	return 0;
 }
 
-static int ovl_real_file(const struct file *file, struct fd *real)
+static int _ovl_real_file(const struct file *file, struct fd *real, bool meta)
 {
 	struct inode *inode = file_inode(file);
+	struct inode *real_inode;
 
 	real->flags = 0;
 	real->file = file->private_data;
 
+	if (meta)
+		real_inode = ovl_inode_real(inode);
+	else
+		real_inode = ovl_inode_real_data(inode);
+
 	/* Has it been copied up since we'd opened it? */
-	if (unlikely(file_inode(real->file) != ovl_inode_real_data(inode))) {
+	if (unlikely(file_inode(real->file) != real_inode)) {
 		real->flags = FDPUT_FPUT;
-		real->file = ovl_open_realfile(file);
+		real->file = ovl_open_realfile(file, meta);
 
 		return PTR_ERR_OR_ZERO(real->file);
 	}
@@ -102,6 +114,16 @@ static int ovl_real_file(const struct file *file, struct fd *real)
 	return 0;
 }
 
+static int ovl_real_file(const struct file *file, struct fd *real)
+{
+	return _ovl_real_file(file, real, false);
+}
+
+static int ovl_real_meta_file(const struct file *file, struct fd *real)
+{
+	return _ovl_real_file(file, real, true);
+}
+
 static int ovl_open(struct inode *inode, struct file *file)
 {
 	struct dentry *dentry = file_dentry(file);
@@ -115,7 +137,7 @@ static int ovl_open(struct inode *inode, struct file *file)
 	/* 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);
+	realfile = ovl_open_realfile(file, false);
 	if (IS_ERR(realfile))
 		return PTR_ERR(realfile);
 
-- 
2.13.6

--
To unsubscribe from this list: send the line "unsubscribe linux-unionfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Filesystems Devel]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux