From a1c14c8eb367822431bea7b5c9eb66c7f30e7046 Mon Sep 17 00:00:00 2001 From: Chunwei Chen Date: Fri, 18 Dec 2015 11:39:41 -0800 Subject: [PATCH] Fix empty xattr dir causing lockup During zfs_rmnode on a xattr dir, if the system crash just after dmu_free_long_range, we would get empty xattr dir in delete queue. This would cause blkid=0 be passed into zap_get_leaf_byblk when doing zfs_purgedir during mount, and would try to do rw_enter on a wrong structure and cause system lockup. We fix this by checking the zap object size in zfs_purgedir, if it's zero, we just return immediately. Signed-off-by: Chunwei Chen --- module/zfs/zfs_dir.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/module/zfs/zfs_dir.c b/module/zfs/zfs_dir.c index 712cb4656430..729188c852a3 100644 --- a/module/zfs/zfs_dir.c +++ b/module/zfs/zfs_dir.c @@ -557,6 +557,18 @@ zfs_purgedir(znode_t *dzp) zfs_dirlock_t dl; int skipped = 0; int error; + dmu_object_info_t doi; + + /* + * If system crashed just after dmu_free_long_range in zfs_rmnode, we + * would be left with an empty object here. If that's the case, we + * should just return immediately. The underlying objects should + * already be freed, so this should be perfectly fine. + */ + dmu_object_info(zsb->z_os, dzp->z_id, &doi); + if (doi.doi_max_offset == 0) { + return (0); + } for (zap_cursor_init(&zc, zsb->z_os, dzp->z_id); (error = zap_cursor_retrieve(&zc, &zap)) == 0;