aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorAndriy Gapon <avg@FreeBSD.org>2019-08-12 10:30:00 +0000
committerAndriy Gapon <avg@FreeBSD.org>2019-08-12 10:30:00 +0000
commitcfe94339f2697b31c946b42620534ad81de5eeb3 (patch)
treeec0a320c1d13294e9e09f168881669fa16f7b9e5 /sys
parentf62615062eb0387feeb7fc009f689346202e6ad6 (diff)
downloadsrc-cfe94339f2697b31c946b42620534ad81de5eeb3.tar.gz
src-cfe94339f2697b31c946b42620534ad81de5eeb3.zip
a stop gap fix for a race between dnode_hold and dnode_sync_free
The race was introduced in r337669, the large dnode feature import from ZoL. The problem was debugged by ZoL developers and then, independently, on FreeBSD. The fix is an early proposal by Brian Behlendorf: https://github.com/behlendorf/zfs/commit/50f32ed74e42aa28522e9681fb8ae55239fa33a7 This fix never went into ZoL. A larger change that was committed later included a different solution because of the re-worked code. Ideally, we want to revert this fix and re-synchronize FreeBSD large dnode code with that in illumos (or newer ZoL). illumos has a later import of the feature from ZoL that does not have the bug. PR: 236480 Obtained from: Brian Behlendorf <behlendorf1@llnl.gov> Submitted by: ncrogers@gmail.com (patch adaptation) Reported by: ncrogers@gmail.com Tested by: ncrogers@gmail.com, Dennis Noordsij <dennis.noordsij@alumni.helsinki.fi>, Julien Cigar <julien@perdition.city> MFC after: 10 days
Notes
Notes: svn path=/head/; revision=350894
Diffstat (limited to 'sys')
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode.c4
1 files changed, 3 insertions, 1 deletions
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode.c
index 0c3b09446ae7..91b3a0414834 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode.c
@@ -1324,7 +1324,9 @@ dnode_hold_impl(objset_t *os, uint64_t object, int flag, int slots,
mutex_enter(&dn->dn_mtx);
type = dn->dn_type;
if (dn->dn_free_txg ||
- ((flag & DNODE_MUST_BE_FREE) && !refcount_is_zero(&dn->dn_holds))) {
+ ((flag & DNODE_MUST_BE_ALLOCATED) && type == DMU_OT_NONE) ||
+ ((flag & DNODE_MUST_BE_FREE) &&
+ (type != DMU_OT_NONE || !refcount_is_zero(&dn->dn_holds)))) {
mutex_exit(&dn->dn_mtx);
zrl_remove(&dnh->dnh_zrlock);
dbuf_rele(db, FTAG);