summaryrefslogtreecommitdiffstats
path: root/fs/overlayfs/inode.c
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@redhat.com>2016-07-29 12:05:23 +0200
committerMiklos Szeredi <mszeredi@redhat.com>2016-07-29 12:05:23 +0200
commitd719e8f268fa4f9944b24b60814da9017dfb7787 (patch)
tree0840f4bffc0abe65fb60286732bdc2ac1846dc7b /fs/overlayfs/inode.c
parentovl: fix sgid on directory (diff)
downloadlinux-d719e8f268fa4f9944b24b60814da9017dfb7787.tar.xz
linux-d719e8f268fa4f9944b24b60814da9017dfb7787.zip
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>
Diffstat (limited to 'fs/overlayfs/inode.c')
-rw-r--r--fs/overlayfs/inode.c29
1 files changed, 26 insertions, 3 deletions
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c
index 66f42f5cf705..041db9c6621c 100644
--- a/fs/overlayfs/inode.c
+++ b/fs/overlayfs/inode.c
@@ -185,8 +185,6 @@ static int ovl_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
if (!realinode->i_op->readlink)
return -EINVAL;
- touch_atime(&realpath);
-
old_cred = ovl_override_creds(dentry->d_sb);
err = realinode->i_op->readlink(realpath.dentry, buf, bufsiz);
revert_creds(old_cred);
@@ -367,6 +365,29 @@ int ovl_open_maybe_copy_up(struct dentry *dentry, unsigned int file_flags)
return err;
}
+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 ovl_file_inode_operations = {
.setattr = ovl_setattr,
.permission = ovl_permission,
@@ -376,6 +397,7 @@ static const struct inode_operations ovl_file_inode_operations = {
.listxattr = ovl_listxattr,
.removexattr = ovl_removexattr,
.get_acl = ovl_get_acl,
+ .update_time = ovl_update_time,
};
static const struct inode_operations ovl_symlink_inode_operations = {
@@ -387,6 +409,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,
@@ -400,7 +423,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;
inode->i_private = oe;
mode &= S_IFMT;