[Devel,RHEL7,COMMIT] ms/ovl: update atime on upperovl: update atime on upper

Submitted by Konstantin Khorenko on Sept. 16, 2016, 2:34 p.m.

Details

Message ID 201609161434.u8GEYX5h027906@finist_cl7.x64_64.work.ct
State New
Series "overlayfs: fix handling MNT_NOATIME"
Headers show

Commit Message

Konstantin Khorenko Sept. 16, 2016, 2:34 p.m.
The commit is pushed to "branch-rh7-3.10.0-327.28.2.vz7.17.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-327.28.2.vz7.17.6
------>
commit 72814686c2596add559bba25d551af93193b0287
Author: Maxim Patlasov <mpatlasov@virtuozzo.com>
Date:   Fri Sep 16 18:34:33 2016 +0400

    ms/ovl: update atime on upperovl: update atime on upper
    
    Patchset description:
    
    overlayfs: fix handling MNT_NOATIME
    
    The series fix a bug revealed by generic/120 from xfstests: overlayfs ignores
    noatime mount option. It always uses options of underlying fs instead.
    
    The series fix it similarly to mainline. See per-patch descriptions
    for details.
    
    https://jira.sw.ru/browse/PSBM-51009
    
    Maxim Patlasov (2):
          ovl: update atime on upperovl: update atime on upper
          fs: use original vfsmount for touch_atime
    
    ======================
    This patch description:
    
    Backport d719e8f268 from mainline:
    
        ovl: update atime on upper
    
        Fix atime update logic in overlayfs.
    
        This patch adds an i_op->update_time() handler to overlayfs inodes.  This
        forwards atime updates to the upper layer only.  No atime updates are done
        on lower layers.
    
        Remove implicit atime updates to underlying files and directories with
        O_NOATIME.  Remove explicit atime update in ovl_readlink().
    
        Clear atime related mnt flags from cloned upper mount.  This means atime
        updates are controlled purely by overlayfs mount options.
    
        Reported-by: Konstantin Khlebnikov <koct9i@gmail.com>
        Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
    
    https://jira.sw.ru/browse/PSBM-51009
    
    Signed-off-by: Maxim Patlasov <mpatlasov@virtuozzo.com>
---
 fs/overlayfs/dir.c       |  1 +
 fs/overlayfs/inode.c     | 29 ++++++++++++++++++++++++++---
 fs/overlayfs/overlayfs.h |  4 ++++
 fs/overlayfs/super.c     |  8 ++++++--
 4 files changed, 37 insertions(+), 5 deletions(-)

Patch hide | download patch | download mbox

diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c
index 5402b9b..881987c 100644
--- a/fs/overlayfs/dir.c
+++ b/fs/overlayfs/dir.c
@@ -966,6 +966,7 @@  const struct inode_operations_wrapper ovl_dir_inode_operations = {
 	.getxattr	= ovl_getxattr,
 	.listxattr	= ovl_listxattr,
 	.removexattr	= ovl_removexattr,
+	.update_time	= ovl_update_time,
 	},
 	.rename2	= ovl_rename2,
 };
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c
index 5fe7acf..77f2da4 100644
--- a/fs/overlayfs/inode.c
+++ b/fs/overlayfs/inode.c
@@ -196,8 +196,6 @@  static int ovl_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
 	if (!realinode->i_op->readlink)
 		return -EINVAL;
 
-	touch_atime(&realpath);
-
 	return realinode->i_op->readlink(realpath.dentry, buf, bufsiz);
 }
 
@@ -383,6 +381,29 @@  struct inode *ovl_d_select_inode(struct dentry *dentry)
 	return d_backing_inode(realpath.dentry);
 }
 
+int ovl_update_time(struct inode *inode, struct timespec *ts, int flags)
+{
+	struct dentry *alias;
+	struct path upperpath;
+
+	if (!(flags & S_ATIME))
+		return 0;
+
+	alias = d_find_any_alias(inode);
+	if (!alias)
+		return 0;
+
+	ovl_path_upper(alias, &upperpath);
+	if (upperpath.dentry) {
+		touch_atime(&upperpath);
+		inode->i_atime = d_inode(upperpath.dentry)->i_atime;
+	}
+
+	dput(alias);
+
+	return 0;
+}
+
 static const struct inode_operations_wrapper ovl_file_inode_operations = {
 	.ops = {
 	.setattr	= ovl_setattr,
@@ -392,6 +413,7 @@  static const struct inode_operations_wrapper ovl_file_inode_operations = {
 	.getxattr	= ovl_getxattr,
 	.listxattr	= ovl_listxattr,
 	.removexattr	= ovl_removexattr,
+	.update_time	= ovl_update_time,
 	},
 	.dentry_open	= ovl_dentry_open,
 };
@@ -406,6 +428,7 @@  static const struct inode_operations ovl_symlink_inode_operations = {
 	.getxattr	= ovl_getxattr,
 	.listxattr	= ovl_listxattr,
 	.removexattr	= ovl_removexattr,
+	.update_time	= ovl_update_time,
 };
 
 struct inode *ovl_new_inode(struct super_block *sb, umode_t mode,
@@ -421,7 +444,7 @@  struct inode *ovl_new_inode(struct super_block *sb, umode_t mode,
 
 	inode->i_ino = get_next_ino();
 	inode->i_mode = mode;
-	inode->i_flags |= S_NOATIME | S_NOCMTIME;
+	inode->i_flags |= S_NOCMTIME;
 
 	switch (mode) {
 	case S_IFDIR:
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
index 8da9684..61ba0d5 100644
--- a/fs/overlayfs/overlayfs.h
+++ b/fs/overlayfs/overlayfs.h
@@ -174,6 +174,7 @@  ssize_t ovl_getxattr(struct dentry *dentry, const char *name,
 ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size);
 int ovl_removexattr(struct dentry *dentry, const char *name);
 struct inode *ovl_d_select_inode(struct dentry *dentry);
+int ovl_update_time(struct inode *inode, struct timespec *ts, int flags);
 
 struct inode *ovl_new_inode(struct super_block *sb, umode_t mode,
 			    struct ovl_entry *oe);
@@ -181,6 +182,9 @@  static inline void ovl_copyattr(struct inode *from, struct inode *to)
 {
 	to->i_uid = from->i_uid;
 	to->i_gid = from->i_gid;
+	to->i_atime = from->i_atime;
+	to->i_mtime = from->i_mtime;
+	to->i_ctime = from->i_ctime;
 }
 
 /* dir.c */
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
index 2935967..b46463a 100644
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -533,7 +533,7 @@  out:
 
 struct file *ovl_path_open(struct path *path, int flags)
 {
-	return dentry_open(path, flags, current_cred());
+	return dentry_open(path, flags | O_NOATIME, current_cred());
 }
 
 static void ovl_put_super(struct super_block *sb)
@@ -1013,6 +1013,10 @@  static int ovl_fill_super(struct super_block *sb, void *data, int silent)
 			pr_err("overlayfs: failed to clone upperpath\n");
 			goto out_put_lowerpath;
 		}
+		/* Don't inherit atime flags */
+		ufs->upper_mnt->mnt_flags &= ~(MNT_NOATIME | MNT_NODIRATIME | MNT_RELATIME);
+
+		sb->s_time_gran = ufs->upper_mnt->mnt_sb->s_time_gran;
 
 		ufs->workdir = ovl_workdir_create(ufs->upper_mnt, workpath.dentry);
 		err = PTR_ERR(ufs->workdir);
@@ -1040,7 +1044,7 @@  static int ovl_fill_super(struct super_block *sb, void *data, int silent)
 		 * Make lower_mnt R/O.  That way fchmod/fchown on lower file
 		 * will fail instead of modifying lower fs.
 		 */
-		mnt->mnt_flags |= MNT_READONLY;
+		mnt->mnt_flags |= MNT_READONLY | MNT_NOATIME;
 
 		ufs->lower_mnt[ufs->numlower] = mnt;
 		ufs->numlower++;