| 237 | } |
| 238 | |
| 239 | void |
| 240 | rrw_exit(rrwlock_t *rrl, void *tag) |
| 241 | { |
| 242 | mutex_enter(&rrl->rr_lock); |
| 243 | #if !defined(ZFS_DEBUG) && defined(_KERNEL) |
| 244 | if (!rrl->rr_writer && rrl->rr_linked_rcount.rc_count == 0) { |
| 245 | rrl->rr_anon_rcount.rc_count--; |
| 246 | if (rrl->rr_anon_rcount.rc_count == 0) |
| 247 | cv_broadcast(&rrl->rr_cv); |
| 248 | mutex_exit(&rrl->rr_lock); |
| 249 | return; |
| 250 | } |
| 251 | DTRACE_PROBE(zfs__rrwfastpath__exitmiss); |
| 252 | #endif |
| 253 | ASSERT(!zfs_refcount_is_zero(&rrl->rr_anon_rcount) || |
| 254 | !zfs_refcount_is_zero(&rrl->rr_linked_rcount) || |
| 255 | rrl->rr_writer != NULL); |
| 256 | |
| 257 | if (rrl->rr_writer == NULL) { |
| 258 | int64_t count; |
| 259 | if (rrn_find_and_remove(rrl, tag)) { |
| 260 | count = zfs_refcount_remove( |
| 261 | &rrl->rr_linked_rcount, tag); |
| 262 | } else { |
| 263 | ASSERT(!rrl->rr_track_all); |
| 264 | count = zfs_refcount_remove(&rrl->rr_anon_rcount, tag); |
| 265 | } |
| 266 | if (count == 0) |
| 267 | cv_broadcast(&rrl->rr_cv); |
| 268 | } else { |
| 269 | ASSERT(rrl->rr_writer == curthread); |
| 270 | ASSERT(zfs_refcount_is_zero(&rrl->rr_anon_rcount) && |
| 271 | zfs_refcount_is_zero(&rrl->rr_linked_rcount)); |
| 272 | rrl->rr_writer = NULL; |
| 273 | cv_broadcast(&rrl->rr_cv); |
| 274 | } |
| 275 | mutex_exit(&rrl->rr_lock); |
| 276 | } |
| 277 | |
| 278 | /* |
| 279 | * If the lock was created with track_all, rrw_held(RW_READER) will return |
no test coverage detected