From fbeddd60b79690b6a6ececc9b00b6014d21405aa Mon Sep 17 00:00:00 2001 From: Matthew Ahrens Date: Thu, 5 Jun 2014 13:20:08 -0800 Subject: Illumos 4390 - I/O errors can corrupt space map when deleting fs/vol 4390 i/o errors when deleting filesystem/zvol can lead to space map corruption Reviewed by: George Wilson Reviewed by: Christopher Siden Reviewed by: Adam Leventhal Reviewed by: Dan McDonald Reviewed by: Saso Kiselkov Approved by: Dan McDonald References: https://www.illumos.org/issues/4390 https://github.com/illumos/illumos-gate/commit/7fd05ac Porting notes: Previous stack-reduction efforts in traverse_visitb() caused a fair number of un-mergable pieces of code. This patch should reduce its stack footprint a bit more. The new local bptree_entry_phys_t in bptree_add() is dynamically-allocated using kmem_zalloc() for the purpose of stack reduction. The new global zfs_free_leak_on_eio has been defined as an integer rather than a boolean_t as was the case with the related zfs_recover global. Also, zfs_free_leak_on_eio's definition has been inserted into zfs_debug.c for consistency with the existing definition of zfs_recover. Illumos placed it in spa_misc.c. Ported by: Tim Chase Signed-off-by: Brian Behlendorf Closes #2545 --- module/zfs/dsl_pool.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'module/zfs/dsl_pool.c') diff --git a/module/zfs/dsl_pool.c b/module/zfs/dsl_pool.c index 91476cc0b..f1ab29c62 100644 --- a/module/zfs/dsl_pool.c +++ b/module/zfs/dsl_pool.c @@ -245,6 +245,13 @@ dsl_pool_open(dsl_pool_t *dp) dp->dp_meta_objset, obj)); } + /* + * Note: errors ignored, because the leak dir will not exist if we + * have not encountered a leak yet. + */ + (void) dsl_pool_open_special_dir(dp, LEAK_DIR_NAME, + &dp->dp_leak_dir); + if (spa_feature_is_active(dp->dp_spa, SPA_FEATURE_ASYNC_DESTROY)) { err = zap_lookup(dp->dp_meta_objset, DMU_POOL_DIRECTORY_OBJECT, DMU_POOL_BPTREE_OBJ, sizeof (uint64_t), 1, @@ -292,6 +299,8 @@ dsl_pool_close(dsl_pool_t *dp) dsl_dir_rele(dp->dp_mos_dir, dp); if (dp->dp_free_dir) dsl_dir_rele(dp->dp_free_dir, dp); + if (dp->dp_leak_dir) + dsl_dir_rele(dp->dp_leak_dir, dp); if (dp->dp_root_dir) dsl_dir_rele(dp->dp_root_dir, dp); -- cgit v1.2.3