From 3aea149bf810cbb564e6ece4a1b5d1af1a037d37 Mon Sep 17 00:00:00 2001 From: Rob Norris Date: Thu, 4 May 2023 22:11:20 +1000 Subject: [PATCH] linux: reject syncing ops if the filesystem is unmounting The kernel can call these during unmount, so we have to handle them directly to prevent any further IO being issued. zfs_fsync reorganised slightly to not set up zfs_fsyncer_key until after the teardown lock is acquired, just in case we don't get it. Signed-off-by: Rob Norris (cherry picked from commit 900c26570ddcdd1d3ca135e6aee5df6456f6bfd6) --- module/os/linux/zfs/zfs_vfsops.c | 3 ++- module/os/linux/zfs/zfs_vnops_os.c | 2 +- module/zfs/zfs_vnops.c | 16 ++++++++++------ 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/module/os/linux/zfs/zfs_vfsops.c b/module/os/linux/zfs/zfs_vfsops.c index 08b98ed08d..58536890ea 100644 --- a/module/os/linux/zfs/zfs_vfsops.c +++ b/module/os/linux/zfs/zfs_vfsops.c @@ -275,7 +275,8 @@ zfs_sync(struct super_block *sb, int wait, cred_t *cr) */ dsl_pool_t *dp; - ZFS_ENTER(zfsvfs); + ZFS_ENTER_UNMOUNTOK(zfsvfs); + dp = dmu_objset_pool(zfsvfs->z_os); /* diff --git a/module/os/linux/zfs/zfs_vnops_os.c b/module/os/linux/zfs/zfs_vnops_os.c index 01f1a41a0e..8509d4342b 100644 --- a/module/os/linux/zfs/zfs_vnops_os.c +++ b/module/os/linux/zfs/zfs_vnops_os.c @@ -3665,7 +3665,7 @@ zfs_dirty_inode(struct inode *ip, int flags) if (zfs_is_readonly(zfsvfs) || dmu_objset_is_snapshot(zfsvfs->z_os)) return (0); - ZFS_ENTER(zfsvfs); + ZFS_ENTER_UNMOUNTOK(zfsvfs); ZFS_VERIFY_ZP(zp); #ifdef I_DIRTY_TIME diff --git a/module/zfs/zfs_vnops.c b/module/zfs/zfs_vnops.c index 1b32d38767..0519f68ed7 100644 --- a/module/zfs/zfs_vnops.c +++ b/module/zfs/zfs_vnops.c @@ -63,16 +63,20 @@ zfs_fsync(znode_t *zp, int syncflag, cred_t *cr) { zfsvfs_t *zfsvfs = ZTOZSB(zp); + if (zfsvfs->z_os->os_sync == ZFS_SYNC_DISABLED) + return (0); + + ZFS_ENTER_UNMOUNTOK(zfsvfs); + ZFS_VERIFY_ZP(zp); + (void) tsd_set(zfs_fsyncer_key, (void *)zfs_fsync_sync_cnt); - if (zfsvfs->z_os->os_sync != ZFS_SYNC_DISABLED) { - ZFS_ENTER(zfsvfs); - ZFS_VERIFY_ZP(zp); - zil_commit(zfsvfs->z_log, zp->z_id); - ZFS_EXIT(zfsvfs); - } + zil_commit(zfsvfs->z_log, zp->z_id); + tsd_set(zfs_fsyncer_key, NULL); + ZFS_EXIT(zfsvfs); + return (0); }