diff options
author | George Melikov <[email protected]> | 2017-01-23 21:35:58 +0300 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2017-01-23 10:35:58 -0800 |
commit | cffd6e116711640d070d9690480b95c5a6de7154 (patch) | |
tree | 2799b1a7d5baf2cb4ad64e01232b1ef9405cba37 | |
parent | 911c41af2d7642fd25b563315c8d9e79b2dd1511 (diff) |
OpenZFS 3746 - ZRLs are racy
Authored by: Will Andrews <[email protected]>
Reviewed by: Boris Protopopov <[email protected]>
Reviewed by: Pavel Zakharov <[email protected]>
Reviewed by: Yuri Pankov <[email protected]>
Reviewed by: Justin T. Gibbs <[email protected]>
Approved by: Matt Ahrens <[email protected]>
Reviewed-by: Brian Behlendorf <[email protected]>
Ported-by: George Melikov <[email protected]>
OpenZFS-issue: https://www.illumos.org/issues/3746
OpenZFS-commit: https://github.com/openzfs/openzfs/commit/260af64
Closes #5625
-rw-r--r-- | module/zfs/zrlock.c | 50 |
1 files changed, 23 insertions, 27 deletions
diff --git a/module/zfs/zrlock.c b/module/zfs/zrlock.c index 137875fe0..02795112f 100644 --- a/module/zfs/zrlock.c +++ b/module/zfs/zrlock.c @@ -20,7 +20,8 @@ */ /* * 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 zrl_add_impl(zrlock_t *zrl, const char *zc) { - uint32_t n = (uint32_t)zrl->zr_refcount; - - while (n != ZRL_LOCKED) { - uint32_t cas = atomic_cas_32( - (uint32_t *)&zrl->zr_refcount, n, n + 1); - if (cas == n) { - ASSERT3S((int32_t)n, >=, 0); + for (;;) { + uint32_t n = (uint32_t)zrl->zr_refcount; + while (n != ZRL_LOCKED) { + uint32_t cas = atomic_cas_32( + (uint32_t *)&zrl->zr_refcount, n, n + 1); + if (cas == n) { + ASSERT3S((int32_t)n, >=, 0); #ifdef ZFS_DEBUG - if (zrl->zr_owner == curthread) { - DTRACE_PROBE2(zrlock__reentry, - zrlock_t *, zrl, uint32_t, n); - } - zrl->zr_owner = curthread; - zrl->zr_caller = zc; + if (zrl->zr_owner == curthread) { + DTRACE_PROBE2(zrlock__reentry, + zrlock_t *, zrl, uint32_t, n); + } + zrl->zr_owner = curthread; + zrl->zr_caller = zc; #endif - return; + return; + } + n = cas; } - n = cas; - } - mutex_enter(&zrl->zr_mtx); - while (zrl->zr_refcount == ZRL_LOCKED) { - cv_wait(&zrl->zr_cv, &zrl->zr_mtx); + mutex_enter(&zrl->zr_mtx); + while (zrl->zr_refcount == ZRL_LOCKED) { + 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 |