[Devel,RHEL7,COMMIT] fs: use original vfsmount for touch_atime

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

Details

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

Commit Message

Konstantin Khorenko Sept. 16, 2016, 2:35 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 a427c4dfb7514de4701ad5f51e4f9442a495131c
Author: Maxim Patlasov <mpatlasov@virtuozzo.com>
Date:   Fri Sep 16 18:35:14 2016 +0400

    fs: use original vfsmount for touch_atime
    
    In case of overlayfs, vfs_open is called recursively filling filp->f_path
    with pointers to real dentry and vfsmount (upper or lower). Hence, touch_atime
    has no access to mnt_flags of original (overlayfs) vfsmount. The patch fixes
    the problem by saving original path to a new field of struct file.
    
    The patch to be reverted when RHEL picks up 4bacc9c92 from mainline:
    
    >    Make file->f_path always point to the overlay dentry so that the path in
    >    /proc/pid/fd is correct and to ensure that label-based LSMs have access to the
    >    overlay as well as the underlay (path-based LSMs probably don't need it).
    
    Picking it now is premature because it introduced a lot of bugs (outside overlay)
    and the chances are high to overlook some related fixes in mainline.
    
    https://jira.sw.ru/browse/PSBM-51009
    
    Signed-off-by: Maxim Patlasov <mpatlasov@virtuozzo.com>
---
 fs/open.c          | 3 +++
 include/linux/fs.h | 4 +++-
 2 files changed, 6 insertions(+), 1 deletion(-)

Patch hide | download patch | download mbox

diff --git a/fs/open.c b/fs/open.c
index bc60c05..8c066b1 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -894,6 +894,9 @@  int vfs_open(const struct path *path, struct file *filp,
 	struct inode *inode = path->dentry->d_inode;
 	iop_dentry_open_t dentry_open = get_dentry_open_iop(inode);
 
+	if (!filp->f_original_path.mnt)
+		filp->f_original_path = *path;
+
 	if (dentry_open)
 		return dentry_open(path->dentry, filp, cred);
 	else {
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 7203dba..ed9519f 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -959,6 +959,7 @@  struct file {
 		struct rcu_head 	fu_rcuhead;
 	} f_u;
 	struct path		f_path;
+	struct path		f_original_path;
 #define f_dentry	f_path.dentry
 	struct inode		*f_inode;	/* cached value */
 	const struct file_operations	*f_op;
@@ -2093,7 +2094,8 @@  extern void touch_atime(struct path *);
 static inline void file_accessed(struct file *file)
 {
 	if (!(file->f_flags & O_NOATIME))
-		touch_atime(&file->f_path);
+		touch_atime(file->f_original_path.mnt ?
+			    &file->f_original_path : &file->f_path);
 }
 
 int sync_inode(struct inode *inode, struct writeback_control *wbc);