From fd23720ae14dca926800ae70e6c8f4b4f82efc08 Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Wed, 8 Jan 2014 10:25:42 -0800 Subject: [PATCH] Drain iput taskq outside z_teardown_lock It's unsafe to drain the iput taskq while holding the z_teardown_lock as a writer. This is because when the last reference on an inode is dropped it may still have pages which need to be written to disk. This will be done through zpl_writepages which will acquire the z_teardown_lock as a reader in ZFS_ENTER. Therefore, if we're holding the lock as a writer in zfs_sb_teardown the unmount will deadlock. Signed-off-by: Brian Behlendorf Signed-off-by: Chris Dunlop Closes #1988 --- module/zfs/zfs_vfsops.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/module/zfs/zfs_vfsops.c b/module/zfs/zfs_vfsops.c index c64854d7b..f331a36ea 100644 --- a/module/zfs/zfs_vfsops.c +++ b/module/zfs/zfs_vfsops.c @@ -1091,6 +1091,14 @@ zfs_sb_teardown(zfs_sb_t *zsb, boolean_t unmounting) { znode_t *zp; + /* + * If someone has not already unmounted this file system, + * drain the iput_taskq to ensure all active references to the + * zfs_sb_t have been handled only then can it be safely destroyed. + */ + if (zsb->z_os) + taskq_wait(dsl_pool_iput_taskq(dmu_objset_pool(zsb->z_os))); + rrw_enter(&zsb->z_teardown_lock, RW_WRITER, FTAG); if (!unmounting) { @@ -1104,14 +1112,6 @@ zfs_sb_teardown(zfs_sb_t *zsb, boolean_t unmounting) shrink_dcache_sb(zsb->z_parent->z_sb); } - /* - * If someone has not already unmounted this file system, - * drain the iput_taskq to ensure all active references to the - * zfs_sb_t have been handled only then can it be safely destroyed. - */ - if (zsb->z_os) - taskq_wait(dsl_pool_iput_taskq(dmu_objset_pool(zsb->z_os))); - /* * Close the zil. NB: Can't close the zil while zfs_inactive * threads are blocked as zil_close can call zfs_inactive.