From: Chengguang Xu Now overlayfs can only sync own dirty inodes during syncfs, so remove unnecessary sync_filesystem() on upper file system. Call ->sync_fs() and write the block device of the upper filesystem instead, which is what sync_filesystem() does after it has written the inodes. Do the same for a read-only remount. With many containers on one upper filesystem, stopping one of them no longer writes out the dirty data of all the others. Signed-off-by: Chengguang Xu [josef: everything after the first paragraph, no wait_sb_inodes() on the upper filesystem] Signed-off-by: Josef Bacik --- fs/overlayfs/params.c | 14 +++----------- fs/overlayfs/super.c | 28 ++++++++++++++++++++-------- 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/fs/overlayfs/params.c b/fs/overlayfs/params.c index 5a15e5478a6b..43fe0b1ef11f 100644 --- a/fs/overlayfs/params.c +++ b/fs/overlayfs/params.c @@ -764,22 +764,14 @@ static int ovl_reconfigure(struct fs_context *fc) { struct super_block *sb = fc->root->d_sb; struct ovl_fs *ofs = OVL_FS(sb); - struct super_block *upper_sb; - int ret = 0; if (!(fc->sb_flags & SB_RDONLY) && ovl_force_readonly(ofs)) return -EROFS; - if (fc->sb_flags & SB_RDONLY && !sb_rdonly(sb)) { - upper_sb = ovl_upper_mnt(ofs)->mnt_sb; - if (ovl_should_sync(ofs)) { - down_read(&upper_sb->s_umount); - ret = sync_filesystem(upper_sb); - up_read(&upper_sb->s_umount); - } - } + if (fc->sb_flags & SB_RDONLY && !sb_rdonly(sb) && ovl_should_sync(ofs)) + return sync_filesystem(sb); - return ret; + return 0; } static const struct fs_context_operations ovl_context_ops = { diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index 84258edb5530..361a3afa4ac8 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -271,18 +272,29 @@ static int ovl_sync_fs(struct super_block *sb, int wait) /* * Not called for sync(2) call or an emergency sync (SB_I_SKIP_SYNC). * All the super blocks will be iterated, including upper_sb. - * - * If this is a syncfs(2) call, then we do need to call - * sync_filesystem() on upper_sb, but enough if we do it when being - * called with wait == 1. */ - if (!wait) - return 0; - upper_sb = ovl_upper_mnt(ofs)->mnt_sb; + /* + * sync_filesystem() has already written the dirty inodes of this + * overlay through ovl_write_inode(), including the fake ones, see + * ovl_upper_modified(). What is left are the last two steps of + * sync_filesystem() on the upper filesystem. Do not write the inodes + * that others have dirtied there. + */ down_read(&upper_sb->s_umount); - ret = sync_filesystem(upper_sb); + /* Like sync_filesystem(), do not call ->sync_fs() on a read-only sb */ + ret = 0; + if (sb_rdonly(upper_sb)) + goto out; + + if (upper_sb->s_op->sync_fs) + ret = upper_sb->s_op->sync_fs(upper_sb, wait); + if (!ret && wait) + ret = sync_blockdev(upper_sb->s_bdev); + else if (!ret) + ret = sync_blockdev_nowait(upper_sb->s_bdev); +out: up_read(&upper_sb->s_umount); return ret; -- 2.55.0