OpenZFS 3746 - ZRLs are racy

Authored by: Will Andrews <will@freebsd.org>
Reviewed by: Boris Protopopov <bprotopopov@hotmail.com>
Reviewed by: Pavel Zakharov <pavel.zakha@gmail.com>
Reviewed by: Yuri Pankov <yuri.pankov@gmail.com>
Reviewed by: Justin T. Gibbs <gibbs@scsiguy.com>
Approved by: Matt Ahrens <mahrens@delphix.com>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Ported-by: George Melikov <mail@gmelikov.ru>

OpenZFS-issue: https://www.illumos.org/issues/3746
OpenZFS-commit: https://github.com/openzfs/openzfs/commit/260af64
Closes #5625
This commit is contained in:
George Melikov 2017-01-23 21:35:58 +03:00 committed by Brian Behlendorf
parent 911c41af2d
commit cffd6e1167

View File

@ -20,7 +20,8 @@
*/ */
/* /*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014 by Delphix. All rights reserved. * Copyright (c) 2014, 2015 by Delphix. All rights reserved.
* Copyright 2016 The MathWorks, Inc. All rights reserved.
*/ */
/* /*
@ -72,37 +73,32 @@ zrl_destroy(zrlock_t *zrl)
void void
zrl_add_impl(zrlock_t *zrl, const char *zc) zrl_add_impl(zrlock_t *zrl, const char *zc)
{ {
uint32_t n = (uint32_t)zrl->zr_refcount; for (;;) {
uint32_t n = (uint32_t)zrl->zr_refcount;
while (n != ZRL_LOCKED) { while (n != ZRL_LOCKED) {
uint32_t cas = atomic_cas_32( uint32_t cas = atomic_cas_32(
(uint32_t *)&zrl->zr_refcount, n, n + 1); (uint32_t *)&zrl->zr_refcount, n, n + 1);
if (cas == n) { if (cas == n) {
ASSERT3S((int32_t)n, >=, 0); ASSERT3S((int32_t)n, >=, 0);
#ifdef ZFS_DEBUG #ifdef ZFS_DEBUG
if (zrl->zr_owner == curthread) { if (zrl->zr_owner == curthread) {
DTRACE_PROBE2(zrlock__reentry, DTRACE_PROBE2(zrlock__reentry,
zrlock_t *, zrl, uint32_t, n); zrlock_t *, zrl, uint32_t, n);
}
zrl->zr_owner = curthread;
zrl->zr_caller = zc;
#endif
return;
} }
zrl->zr_owner = curthread; n = cas;
zrl->zr_caller = zc;
#endif
return;
} }
n = cas;
}
mutex_enter(&zrl->zr_mtx); mutex_enter(&zrl->zr_mtx);
while (zrl->zr_refcount == ZRL_LOCKED) { while (zrl->zr_refcount == ZRL_LOCKED) {
cv_wait(&zrl->zr_cv, &zrl->zr_mtx); cv_wait(&zrl->zr_cv, &zrl->zr_mtx);
}
mutex_exit(&zrl->zr_mtx);
} }
ASSERT3S(zrl->zr_refcount, >=, 0);
zrl->zr_refcount++;
#ifdef ZFS_DEBUG
zrl->zr_owner = curthread;
zrl->zr_caller = zc;
#endif
mutex_exit(&zrl->zr_mtx);
} }
void void