Print this page
Backport fix from
Make NFS4.x dbe related ops lockless with atomic
Evan's review
@@ -825,27 +825,41 @@
bp = &buckets[i];
do {
found = FALSE;
rw_enter(bp->dbk_lock, RW_READER);
for (l = bp->dbk_head; l; l = l->next) {
+ uint32_t refcnt;
+
entry = l->entry;
/*
* Examine an entry. Ref count of 1 means
* that the only reference is for the hash
* table reference.
*/
if (entry->dbe_refcnt != 1)
continue;
mutex_enter(entry->dbe_lock);
+ /*
+ * Recheck the ref. count with the lock,
+ * and if non-zero, leave things alone.
+ */
if ((entry->dbe_refcnt == 1) &&
(table->dbt_reaper_shutdown ||
table->dbt_expiry == NULL ||
(*table->dbt_expiry)(entry->dbe_data))) {
- entry->dbe_refcnt--;
+ refcnt = atomic_dec_32_nv(&entry->dbe_refcnt);
+ if (refcnt == 0) {
count++;
found = TRUE;
+ } else {
+ /*
+ * Lost race w/ incr.
+ * Leave it as it was
+ */
+ atomic_inc_32(&entry->dbe_refcnt);
}
+ }
mutex_exit(entry->dbe_lock);
}
if (found) {
if (!rw_tryupgrade(bp->dbk_lock)) {
rw_exit(bp->dbk_lock);