--- ddt.c 2010-06-25 15:30:21.084712659 +0200 +++ ddt.c.new 2010-06-25 15:30:16.980712010 +0200 @@ -964,10 +964,11 @@ ddt_repair_table(ddt_t *ddt, zio_t *rio) avl_tree_t *t = &ddt->ddt_repair_tree; blkptr_t blk; + ASSERT(MUTEX_HELD(&ddt->ddt_lock)); + if (spa_sync_pass(spa) > 1) return; - ddt_enter(ddt); for (rdde = avl_first(t); rdde != NULL; rdde = rdde_next) { rdde_next = AVL_NEXT(t, rdde); avl_remove(&ddt->ddt_repair_tree, rdde); @@ -978,7 +979,6 @@ ddt_repair_table(ddt_t *ddt, zio_t *rio) ddt_repair_done(ddt, dde); ddt_enter(ddt); } - ddt_exit(ddt); } static void @@ -1053,7 +1053,8 @@ ddt_sync_table(ddt_t *ddt, dmu_tx_t *tx, { spa_t *spa = ddt->ddt_spa; ddt_entry_t *dde; - void *cookie = NULL; + + ASSERT(MUTEX_HELD(&ddt->ddt_lock)); if (avl_numnodes(&ddt->ddt_tree) == 0) return; @@ -1068,7 +1069,18 @@ ddt_sync_table(ddt_t *ddt, dmu_tx_t *tx, &spa->spa_ddt_stat_object, tx) == 0); } - while ((dde = avl_destroy_nodes(&ddt->ddt_tree, &cookie)) != NULL) { + while ((dde = avl_first(&ddt->ddt_tree)) != NULL) { + if (dde->dde_loading) { + /* + * If the entry is being loaded, wait for it. + * Because we drop the ddt_lock during the wait, + * we have to start over, as the entry might + * have been removed in the meantime. + */ + cv_wait(&dde->dde_cv, &ddt->ddt_lock); + continue; + } + avl_remove(&ddt->ddt_tree, dde); ddt_sync_entry(ddt, dde, tx, txg); ddt_free(dde); } @@ -1106,8 +1118,10 @@ ddt_sync(spa_t *spa, uint64_t txg) ddt_t *ddt = spa->spa_ddt[c]; if (ddt == NULL) continue; + ddt_enter(ddt); ddt_sync_table(ddt, tx, txg); ddt_repair_table(ddt, rio); + ddt_exit(ddt); } (void) zio_wait(rio);