Print this page
Backport fix from 
 Make NFS4.x dbe related ops lockless with atomic
Evan's review


 810 {
 811         rfs4_index_t *idx = table->dbt_indices;
 812         rfs4_bucket_t *buckets = idx->dbi_buckets, *bp;
 813         rfs4_link_t *l, *t;
 814         rfs4_dbe_t *entry;
 815         bool_t found;
 816         int i;
 817         int count = 0;
 818 
 819         NFS4_DEBUG(table->dbt_debug & REAP_DEBUG,
 820             (CE_NOTE, "Reaping %d entries older than %ld seconds in table %s",
 821             desired, cache_time, table->dbt_name));
 822 
 823         /* Walk the buckets looking for entries to release/destroy */
 824         for (i = 0; i < table->dbt_len; i++) {
 825                 bp = &buckets[i];
 826                 do {
 827                         found = FALSE;
 828                         rw_enter(bp->dbk_lock, RW_READER);
 829                         for (l = bp->dbk_head; l; l = l->next) {


 830                                 entry = l->entry;
 831                                 /*
 832                                  * Examine an entry.  Ref count of 1 means
 833                                  * that the only reference is for the hash
 834                                  * table reference.
 835                                  */
 836                                 if (entry->dbe_refcnt != 1)
 837                                         continue;
 838                                 mutex_enter(entry->dbe_lock);




 839                                 if ((entry->dbe_refcnt == 1) &&
 840                                     (table->dbt_reaper_shutdown ||
 841                                     table->dbt_expiry == NULL ||
 842                                     (*table->dbt_expiry)(entry->dbe_data))) {
 843                                         entry->dbe_refcnt--;

 844                                         count++;
 845                                         found = TRUE;






 846                                 }

 847                                 mutex_exit(entry->dbe_lock);
 848                         }
 849                         if (found) {
 850                                 if (!rw_tryupgrade(bp->dbk_lock)) {
 851                                         rw_exit(bp->dbk_lock);
 852                                         rw_enter(bp->dbk_lock, RW_WRITER);
 853                                 }
 854 
 855                                 l = bp->dbk_head;
 856                                 while (l) {
 857                                         t = l;
 858                                         entry = t->entry;
 859                                         l = l->next;
 860                                         if (entry->dbe_refcnt == 0) {
 861                                                 DEQUEUE(bp->dbk_head, t);
 862                                                 t->next = NULL;
 863                                                 t->prev = NULL;
 864                                                 INVALIDATE_ADDR(t->entry);
 865                                                 rfs4_dbe_destroy(entry);
 866                                         }




 810 {
 811         rfs4_index_t *idx = table->dbt_indices;
 812         rfs4_bucket_t *buckets = idx->dbi_buckets, *bp;
 813         rfs4_link_t *l, *t;
 814         rfs4_dbe_t *entry;
 815         bool_t found;
 816         int i;
 817         int count = 0;
 818 
 819         NFS4_DEBUG(table->dbt_debug & REAP_DEBUG,
 820             (CE_NOTE, "Reaping %d entries older than %ld seconds in table %s",
 821             desired, cache_time, table->dbt_name));
 822 
 823         /* Walk the buckets looking for entries to release/destroy */
 824         for (i = 0; i < table->dbt_len; i++) {
 825                 bp = &buckets[i];
 826                 do {
 827                         found = FALSE;
 828                         rw_enter(bp->dbk_lock, RW_READER);
 829                         for (l = bp->dbk_head; l; l = l->next) {
 830                                 uint32_t refcnt;
 831 
 832                                 entry = l->entry;
 833                                 /*
 834                                  * Examine an entry.  Ref count of 1 means
 835                                  * that the only reference is for the hash
 836                                  * table reference.
 837                                  */
 838                                 if (entry->dbe_refcnt != 1)
 839                                         continue;
 840                                 mutex_enter(entry->dbe_lock);
 841                                 /*
 842                                  * Recheck the ref. count with the lock,
 843                                  * and if non-zero, leave things alone.
 844                                  */
 845                                 if ((entry->dbe_refcnt == 1) &&
 846                                     (table->dbt_reaper_shutdown ||
 847                                     table->dbt_expiry == NULL ||
 848                                     (*table->dbt_expiry)(entry->dbe_data))) {
 849                                         refcnt = atomic_dec_32_nv(&entry->dbe_refcnt);
 850                                         if (refcnt == 0) {
 851                                                 count++;
 852                                                 found = TRUE;
 853                                         } else {
 854                                                 /*
 855                                                  * Lost race w/ incr.
 856                                                  * Leave it as it was
 857                                                  */
 858                                                 atomic_inc_32(&entry->dbe_refcnt);
 859                                         }
 860                                 }
 861                                 mutex_exit(entry->dbe_lock);
 862                         }
 863                         if (found) {
 864                                 if (!rw_tryupgrade(bp->dbk_lock)) {
 865                                         rw_exit(bp->dbk_lock);
 866                                         rw_enter(bp->dbk_lock, RW_WRITER);
 867                                 }
 868 
 869                                 l = bp->dbk_head;
 870                                 while (l) {
 871                                         t = l;
 872                                         entry = t->entry;
 873                                         l = l->next;
 874                                         if (entry->dbe_refcnt == 0) {
 875                                                 DEQUEUE(bp->dbk_head, t);
 876                                                 t->next = NULL;
 877                                                 t->prev = NULL;
 878                                                 INVALIDATE_ADDR(t->entry);
 879                                                 rfs4_dbe_destroy(entry);
 880                                         }