Introduce a helper ovl_wait_wb_inodes() to wait until all target upper inodes finish writeback. Signed-off-by: Chengguang Xu <cgxu519@xxxxxxxxxxxx> --- fs/overlayfs/super.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index e5607a908d82..9a535fc11221 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c @@ -255,6 +255,36 @@ static void ovl_put_super(struct super_block *sb) ovl_free_fs(ofs); } +void ovl_wait_wb_inodes(struct ovl_fs *ofs) +{ + LIST_HEAD(tmp_list); + struct ovl_inode *oi; + struct inode *upper; + + spin_lock(&ofs->syncfs_wait_list_lock); + list_splice_init(&ofs->syncfs_wait_list, &tmp_list); + + while (!list_empty(&tmp_list)) { + oi = list_first_entry(&tmp_list, struct ovl_inode, wait_list); + list_del_init(&oi->wait_list); + ihold(&oi->vfs_inode); + spin_unlock(&ofs->syncfs_wait_list_lock); + + upper = ovl_inode_upper(&oi->vfs_inode); + if (!mapping_tagged(upper->i_mapping, PAGECACHE_TAG_WRITEBACK)) { + iput(&oi->vfs_inode); + goto wait_next; + } + + filemap_fdatawait_keep_errors(upper->i_mapping); + iput(&oi->vfs_inode); + cond_resched(); +wait_next: + spin_lock(&ofs->syncfs_wait_list_lock); + } + spin_unlock(&ofs->syncfs_wait_list_lock); +} + /* Sync real dirty inodes in upper filesystem (if it exists) */ static int ovl_sync_fs(struct super_block *sb, int wait) { -- 2.26.2