[Devel,rh7,2/2] fs: use original vfsmount for touch_atime

Submitted by Maxim Patlasov on Sept. 14, 2016, 12:55 a.m.


Message ID 147381453553.13199.6971839294430084925.stgit@maxim-thinkpad
State New
Series "overlayfs: fix handling MNT_NOATIME"
Headers show

Commit Message

Maxim Patlasov Sept. 14, 2016, 12:55 a.m.
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.


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 f1c3d5b..7b84d49 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -961,6 +961,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;
@@ -2095,7 +2096,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);