From 8fc424efe16eba31a850918e1e3baf1e0a1901ee Mon Sep 17 00:00:00 2001 From: Pavel Snajdr Date: Thu, 28 Nov 2024 23:02:36 +0100 Subject: [PATCH] Linux: syncfs(2) should sync all open files While debugging problem with data not being synced on umount, we've noticed that even syncfs(2) doesn't help to get the data written out. It is because it doesn't actually sync any of the live znodes. Signed-off-by: Pavel Snajdr --- module/os/linux/zfs/zfs_vfsops.c | 12 ++++++------ module/os/linux/zfs/zpl_super.c | 14 +++++++++++++- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/module/os/linux/zfs/zfs_vfsops.c b/module/os/linux/zfs/zfs_vfsops.c index e6f6eb172da9..b0ccf0080110 100644 --- a/module/os/linux/zfs/zfs_vfsops.c +++ b/module/os/linux/zfs/zfs_vfsops.c @@ -1551,12 +1551,12 @@ zfs_preumount(struct super_block *sb) /* zfsvfs is NULL when zfs_domount fails during mount */ if (zfsvfs) { /* - * Since we have to disable zpl_prune_sb when umounting, - * because the shrinker gets freed before zpl_kill_sb is - * ever called, the umount might be unable to sync open files. - * - * Let's do it here. - */ + * Since we have to disable zpl_prune_sb when umounting, + * because the shrinker gets freed before zpl_kill_sb is + * ever called, the umount might be unable to sync open files. + * + * Let's do it here. + */ mutex_enter(&zfsvfs->z_znodes_lock); list_for_each_entry(zp, &zfsvfs->z_all_znodes, z_link_node) { if (zp->z_sa_hdl) diff --git a/module/os/linux/zfs/zpl_super.c b/module/os/linux/zfs/zpl_super.c index b97b701b7460..4a18537a7f15 100644 --- a/module/os/linux/zfs/zpl_super.c +++ b/module/os/linux/zfs/zpl_super.c @@ -109,11 +109,23 @@ zpl_sync_fs(struct super_block *sb, int wait) { fstrans_cookie_t cookie; cred_t *cr = CRED(); + znode_t *zp; + zfsvfs_t *zfsvfs = sb->s_fs_info; int error; crhold(cr); cookie = spl_fstrans_mark(); - error = -zfs_sync(sb, wait, cr); + mutex_enter(&zfsvfs->z_znodes_lock); + for (zp = list_head(&zfsvfs->z_all_znodes); zp; + zp = list_next(&zfsvfs->z_all_znodes, zp)) { + if (zp->z_sa_hdl) + error = -zfs_fsync(zp, wait, cr); + if (error != 0) + break; + } + mutex_exit(&zfsvfs->z_znodes_lock); + if (error == 0) + error = -zfs_sync(sb, wait, cr); spl_fstrans_unmark(cookie); crfree(cr); ASSERT3S(error, <=, 0);