With lazytime on the upper filesystem the flusher leaves timestamps in memory for up to 12 hours. The overlay inode must not be clean during that time, or syncfs() would miss them. It cannot stay dirty either, because the flusher would visit it on every pass and it could not be reclaimed. When deferred timestamps are all that is left to write, set I_DIRTY_TIME on the overlay inode, like the VFS does on the upper inode. Implement ->sync_lazytime() to pass the request on to the upper inode. The VFS writes deferred timestamps on the last iput(). The upper inode does not see that while the overlay inode holds it, so the last iput() of the overlay inode stands in for it. Signed-off-by: Josef Bacik --- fs/overlayfs/dir.c | 1 + fs/overlayfs/inode.c | 19 +++++++++++++++++++ fs/overlayfs/overlayfs.h | 1 + fs/overlayfs/super.c | 27 +++++++++++++++++++++++++++ 4 files changed, 48 insertions(+) diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c index 1194ccf981c3..fc47beffa67e 100644 --- a/fs/overlayfs/dir.c +++ b/fs/overlayfs/dir.c @@ -1489,6 +1489,7 @@ const struct inode_operations ovl_dir_inode_operations = { .get_acl = ovl_get_acl, .set_acl = ovl_set_acl, .update_time = ovl_update_time, + .sync_lazytime = ovl_sync_lazytime, .fileattr_get = ovl_fileattr_get, .fileattr_set = ovl_fileattr_set, .tmpfile = ovl_tmpfile, diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c index 9a4bf7c2502b..5895ee5aa771 100644 --- a/fs/overlayfs/inode.c +++ b/fs/overlayfs/inode.c @@ -743,6 +743,22 @@ int ovl_fileattr_get(struct dentry *dentry, struct file_kattr *fa) return err; } +/* + * The overlay inode has I_DIRTY_TIME set because the upper inode has deferred + * timestamps, see ovl_park_inode(). The VFS calls this when the timestamps + * have to be written. Mark the upper inode dirty, which hands the timestamps + * to the upper filesystem, and mark the overlay inode dirty, so that + * ovl_write_inode() writes the upper inode. + */ +void ovl_sync_lazytime(struct inode *inode) +{ + struct inode *upper = ovl_inode_upper(inode); + + if (upper && (inode_state_read_once(upper) & I_DIRTY_TIME)) + mark_inode_dirty_sync(upper); + ovl_mark_inode_dirty(inode); +} + static const struct inode_operations ovl_file_inode_operations = { .setattr = ovl_setattr, .permission = ovl_permission, @@ -752,6 +768,7 @@ static const struct inode_operations ovl_file_inode_operations = { .get_acl = ovl_get_acl, .set_acl = ovl_set_acl, .update_time = ovl_update_time, + .sync_lazytime = ovl_sync_lazytime, .fiemap = ovl_fiemap, .fileattr_get = ovl_fileattr_get, .fileattr_set = ovl_fileattr_set, @@ -763,6 +780,7 @@ static const struct inode_operations ovl_symlink_inode_operations = { .getattr = ovl_getattr, .listxattr = ovl_listxattr, .update_time = ovl_update_time, + .sync_lazytime = ovl_sync_lazytime, }; static const struct inode_operations ovl_special_inode_operations = { @@ -774,6 +792,7 @@ static const struct inode_operations ovl_special_inode_operations = { .get_acl = ovl_get_acl, .set_acl = ovl_set_acl, .update_time = ovl_update_time, + .sync_lazytime = ovl_sync_lazytime, }; static const struct address_space_operations ovl_aops = { diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h index 1cc682f28cc3..2ef4b4b23990 100644 --- a/fs/overlayfs/overlayfs.h +++ b/fs/overlayfs/overlayfs.h @@ -891,6 +891,7 @@ static inline struct posix_acl *ovl_get_acl_path(const struct path *path, int ovl_update_time(struct inode *inode, enum fs_update_time type, unsigned int flags); +void ovl_sync_lazytime(struct inode *inode); bool ovl_is_private_xattr(struct super_block *sb, const char *name); struct ovl_inode_params { diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index 87773b73f228..27e30d0ace80 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c @@ -364,6 +364,31 @@ static enum ovl_write_mode ovl_write_mode(struct inode *inode, return OVL_WRITE_COMMIT; } +/* + * All that is left to write for @inode are timestamps that lazytime has + * deferred on the upper inode. The flusher leaves those alone for up to 12 + * hours. Set I_DIRTY_TIME on the overlay inode, like the VFS did on the upper + * inode. This takes the overlay inode off the list that the flusher walks, + * syncfs() still finds it, and the VFS calls ovl_sync_lazytime() when the + * timestamps have to be written. + * + * One of those occasions is when the last reference to an inode goes away. The + * upper inode never loses its last reference while the overlay inode exists, so + * the overlay inode has to stand in for it. The last reference to the overlay + * inode may already be gone at this point. iput() checks for I_DIRTY_TIME + * under i_lock before it drops the last reference, so either iput() sees the + * flag, or the reference count is zero here. + */ +static void ovl_park_inode(struct inode *inode) +{ + if (!ovl_tracks_dirty(OVL_FS(inode->i_sb))) + return; + + __mark_inode_dirty(inode, I_DIRTY_TIME); + if (!icount_read_once(inode)) + mark_inode_dirty_sync(inode); +} + static int ovl_write_inode(struct inode *inode, struct writeback_control *wbc) { struct inode *upper = ovl_inode_upper(inode); @@ -384,6 +409,8 @@ static int ovl_write_inode(struct inode *inode, struct writeback_control *wbc) if (ovl_upper_unfinished(upper)) ovl_mark_inode_dirty(inode); + else if (inode_state_read_once(upper) & I_DIRTY_TIME) + ovl_park_inode(inode); return ret; } -- 2.55.0