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 }
|