* Insert an entry into the hash table. If there is already an element * equal to elem in the hash table, then the already existing element * will be returned and the new element will not be inserted. * Otherwise returns NULL. * If lockp == NULL, the caller is assumed to already hold the hash lock. */
| 1049 | * If lockp == NULL, the caller is assumed to already hold the hash lock. |
| 1050 | */ |
| 1051 | static arc_buf_hdr_t * |
| 1052 | buf_hash_insert(arc_buf_hdr_t *hdr, kmutex_t **lockp) |
| 1053 | { |
| 1054 | uint64_t idx = BUF_HASH_INDEX(hdr->b_spa, &hdr->b_dva, hdr->b_birth); |
| 1055 | kmutex_t *hash_lock = BUF_HASH_LOCK(idx); |
| 1056 | arc_buf_hdr_t *fhdr; |
| 1057 | uint32_t i; |
| 1058 | |
| 1059 | ASSERT(!DVA_IS_EMPTY(&hdr->b_dva)); |
| 1060 | ASSERT(hdr->b_birth != 0); |
| 1061 | ASSERT(!HDR_IN_HASH_TABLE(hdr)); |
| 1062 | |
| 1063 | if (lockp != NULL) { |
| 1064 | *lockp = hash_lock; |
| 1065 | mutex_enter(hash_lock); |
| 1066 | } else { |
| 1067 | ASSERT(MUTEX_HELD(hash_lock)); |
| 1068 | } |
| 1069 | |
| 1070 | for (fhdr = buf_hash_table.ht_table[idx], i = 0; fhdr != NULL; |
| 1071 | fhdr = fhdr->b_hash_next, i++) { |
| 1072 | if (HDR_EQUAL(hdr->b_spa, &hdr->b_dva, hdr->b_birth, fhdr)) |
| 1073 | return (fhdr); |
| 1074 | } |
| 1075 | |
| 1076 | hdr->b_hash_next = buf_hash_table.ht_table[idx]; |
| 1077 | buf_hash_table.ht_table[idx] = hdr; |
| 1078 | arc_hdr_set_flags(hdr, ARC_FLAG_IN_HASH_TABLE); |
| 1079 | |
| 1080 | /* collect some hash table performance data */ |
| 1081 | if (i > 0) { |
| 1082 | ARCSTAT_BUMP(arcstat_hash_collisions); |
| 1083 | if (i == 1) |
| 1084 | ARCSTAT_BUMP(arcstat_hash_chains); |
| 1085 | |
| 1086 | ARCSTAT_MAX(arcstat_hash_chain_max, i); |
| 1087 | } |
| 1088 | |
| 1089 | ARCSTAT_BUMP(arcstat_hash_elements); |
| 1090 | ARCSTAT_MAXSTAT(arcstat_hash_elements); |
| 1091 | |
| 1092 | return (NULL); |
| 1093 | } |
| 1094 | |
| 1095 | static void |
| 1096 | buf_hash_remove(arc_buf_hdr_t *hdr) |
no test coverage detected