summaryrefslogtreecommitdiffstats
path: root/include/sys/dnode.h
diff options
context:
space:
mode:
authorJohn Poduska <[email protected]>2020-03-12 13:25:56 -0400
committerGitHub <[email protected]>2020-03-12 10:25:56 -0700
commite6b28efccc4853b4f2715c2d37ab05cead2e1c3e (patch)
tree106de4649fcdb96798b03a92309b1e9ffa9540ef /include/sys/dnode.h
parent1e9231ada893d43bdbfa8ef3a11f1e423296981d (diff)
Prevent race condition in dnode_dest (#10101)
dnode_special_close() waits for the refcount of dn_holds to go to zero without holding the dn_mtx. dnode_rele_and_unlock() does the final remove to dn_holds with dn_mtx being held: refs = zfs_refcount_remove(&dn->dn_holds, tag); mutex_exit(&dn->dn_mtx); So, there is a race condition after the remove until dn_mtx is dropped. During that time, dnode_destroy() can get called, which ends up in dnode_dest() calling mutex_destroy() and a panic since the lock is still held. This change adds a condvar to wait for the final dnode_rele_and_unlock() to release the dn_mtx before calling dnode_destroy(). Reviewed-by: Paul Dagnelie <[email protected]> Reviewed-by: Brian Behlendorf <[email protected]> Reviewed-by: Matthew Ahrens <[email protected]> Signed-off-by: John Poduska <[email protected]> Closes #7814 Closes #10101
Diffstat (limited to 'include/sys/dnode.h')
-rw-r--r--include/sys/dnode.h1
1 files changed, 1 insertions, 0 deletions
diff --git a/include/sys/dnode.h b/include/sys/dnode.h
index 3ea7aeb7f..14821bab2 100644
--- a/include/sys/dnode.h
+++ b/include/sys/dnode.h
@@ -332,6 +332,7 @@ struct dnode {
uint64_t dn_assigned_txg;
uint64_t dn_dirty_txg; /* txg dnode was last dirtied */
kcondvar_t dn_notxholds;
+ kcondvar_t dn_nodnholds;
enum dnode_dirtycontext dn_dirtyctx;
void *dn_dirtyctx_firstset; /* dbg: contents meaningless */