diff options
author | Chunwei Chen <[email protected]> | 2019-08-28 10:42:02 -0700 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2019-08-28 10:42:02 -0700 |
commit | 035e96118bc9a7cbf435dd17dda507b870fcf6e6 (patch) | |
tree | 71cb2c19bd850251f28966a37e7ce148a65a513b /include | |
parent | 9c9dcd6e04ae7a868efafe4447bdbe67ae25a6da (diff) |
Fix zil replay panic when TX_REMOVE followed by TX_CREATE
If TX_REMOVE is followed by TX_CREATE on the same object id, we need to
make sure the object removal is completely finished before creation. The
current implementation relies on dnode_hold_impl with
DNODE_MUST_BE_ALLOCATED returning ENOENT. While this check seems to work
fine before, in current version it does not guarantee the object removal
is completed.
We fix this by checking if DNODE_MUST_BE_FREE returns successful
instead. Also add test and remove dead code in dnode_hold_impl.
Reviewed-by: Brian Behlendorf <[email protected]>
Reviewed-by: Tom Caputi <[email protected]>
Signed-off-by: Chunwei Chen <[email protected]>
Closes #7151
Closes #8910
Closes #9123
Closes #9145
Diffstat (limited to 'include')
-rw-r--r-- | include/sys/dnode.h | 7 |
1 files changed, 2 insertions, 5 deletions
diff --git a/include/sys/dnode.h b/include/sys/dnode.h index f18b5dd5c..5e9d070e2 100644 --- a/include/sys/dnode.h +++ b/include/sys/dnode.h @@ -46,6 +46,7 @@ extern "C" { */ #define DNODE_MUST_BE_ALLOCATED 1 #define DNODE_MUST_BE_FREE 2 +#define DNODE_DRY_RUN 4 /* * dnode_next_offset() flags. @@ -415,6 +416,7 @@ int dnode_hold_impl(struct objset *dd, uint64_t object, int flag, int dn_slots, boolean_t dnode_add_ref(dnode_t *dn, void *ref); void dnode_rele(dnode_t *dn, void *ref); void dnode_rele_and_unlock(dnode_t *dn, void *tag, boolean_t evicting); +int dnode_try_claim(objset_t *os, uint64_t object, int slots); void dnode_setdirty(dnode_t *dn, dmu_tx_t *tx); void dnode_sync(dnode_t *dn, dmu_tx_t *tx); void dnode_allocate(dnode_t *dn, dmu_object_type_t ot, int blocksize, int ibs, @@ -532,11 +534,6 @@ typedef struct dnode_stats { */ kstat_named_t dnode_hold_free_overflow; /* - * Number of times a dnode_hold(...) was attempted on a dnode - * which had already been unlinked in an earlier txg. - */ - kstat_named_t dnode_hold_free_txg; - /* * Number of times dnode_free_interior_slots() needed to retry * acquiring a slot zrl lock due to contention. */ |