diff options
-rw-r--r-- | fs/overlayfs/dir.c | 1 | ||||
-rw-r--r-- | fs/overlayfs/inode.c | 29 | ||||
-rw-r--r-- | fs/overlayfs/overlayfs.h | 4 | ||||
-rw-r--r-- | fs/overlayfs/super.c | 8 |
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++; |