Print this page
Backport fix from 

Make NFS4.x dbe related ops lockless with atomic
Evan's review

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/fs/nfs/nfs4_db.c
          +++ new/usr/src/uts/common/fs/nfs/nfs4_db.c
↓ open down ↓ 819 lines elided ↑ open up ↑
 820  820              (CE_NOTE, "Reaping %d entries older than %ld seconds in table %s",
 821  821              desired, cache_time, table->dbt_name));
 822  822  
 823  823          /* Walk the buckets looking for entries to release/destroy */
 824  824          for (i = 0; i < table->dbt_len; i++) {
 825  825                  bp = &buckets[i];
 826  826                  do {
 827  827                          found = FALSE;
 828  828                          rw_enter(bp->dbk_lock, RW_READER);
 829  829                          for (l = bp->dbk_head; l; l = l->next) {
      830 +                                uint32_t refcnt;
      831 +
 830  832                                  entry = l->entry;
 831  833                                  /*
 832  834                                   * Examine an entry.  Ref count of 1 means
 833  835                                   * that the only reference is for the hash
 834  836                                   * table reference.
 835  837                                   */
 836  838                                  if (entry->dbe_refcnt != 1)
 837  839                                          continue;
 838  840                                  mutex_enter(entry->dbe_lock);
      841 +                                /*
      842 +                                 * Recheck the ref. count with the lock,
      843 +                                 * and if non-zero, leave things alone.
      844 +                                 */
 839  845                                  if ((entry->dbe_refcnt == 1) &&
 840  846                                      (table->dbt_reaper_shutdown ||
 841  847                                      table->dbt_expiry == NULL ||
 842  848                                      (*table->dbt_expiry)(entry->dbe_data))) {
 843      -                                        entry->dbe_refcnt--;
 844      -                                        count++;
 845      -                                        found = TRUE;
      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 +                                        }
 846  860                                  }
 847  861                                  mutex_exit(entry->dbe_lock);
 848  862                          }
 849  863                          if (found) {
 850  864                                  if (!rw_tryupgrade(bp->dbk_lock)) {
 851  865                                          rw_exit(bp->dbk_lock);
 852  866                                          rw_enter(bp->dbk_lock, RW_WRITER);
 853  867                                  }
 854  868  
 855  869                                  l = bp->dbk_head;
↓ open down ↓ 96 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX