summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/overlayfs/dir.c1
-rw-r--r--fs/overlayfs/inode.c29
-rw-r--r--fs/overlayfs/overlayfs.h4
-rw-r--r--fs/overlayfs/super.c8
4 files changed, 37 insertions, 5 deletions
diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c
index 8beeed34dad6..b4eac8173f93 100644
--- a/fs/overlayfs/dir.c
+++ b/fs/overlayfs/dir.c
@@ -943,4 +943,5 @@ const struct inode_operations ovl_dir_inode_operations = {
.listxattr = ovl_listxattr,
.removexattr = ovl_removexattr,
.get_acl = ovl_get_acl,
+ .update_time = ovl_update_time,
};
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;
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
index e8d50da384d5..fb73c09a84e7 100644
--- a/fs/overlayfs/overlayfs.h
+++ b/fs/overlayfs/overlayfs.h
@@ -181,6 +181,7 @@ ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size);
int ovl_removexattr(struct dentry *dentry, const char *name);
struct posix_acl *ovl_get_acl(struct inode *inode, int type);
int ovl_open_maybe_copy_up(struct dentry *dentry, unsigned int file_flags);
+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);
@@ -189,6 +190,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_mode = from->i_mode;
+ 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 80598912a5d9..058103c60f54 100644
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -608,7 +608,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)
@@ -1075,6 +1075,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);
@@ -1122,7 +1126,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++;