* 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. */
| 370 | * Otherwise returns NULL. |
| 371 | */ |
| 372 | static dmu_buf_impl_t * |
| 373 | dbuf_hash_insert(dmu_buf_impl_t *db) |
| 374 | { |
| 375 | dbuf_hash_table_t *h = &dbuf_hash_table; |
| 376 | objset_t *os = db->db_objset; |
| 377 | uint64_t obj = db->db.db_object; |
| 378 | int level = db->db_level; |
| 379 | uint64_t blkid, hv, idx; |
| 380 | dmu_buf_impl_t *dbf; |
| 381 | uint32_t i; |
| 382 | |
| 383 | blkid = db->db_blkid; |
| 384 | hv = dbuf_hash(os, obj, level, blkid); |
| 385 | idx = hv & h->hash_table_mask; |
| 386 | |
| 387 | mutex_enter(DBUF_HASH_MUTEX(h, idx)); |
| 388 | for (dbf = h->hash_table[idx], i = 0; dbf != NULL; |
| 389 | dbf = dbf->db_hash_next, i++) { |
| 390 | if (DBUF_EQUAL(dbf, os, obj, level, blkid)) { |
| 391 | mutex_enter(&dbf->db_mtx); |
| 392 | if (dbf->db_state != DB_EVICTING) { |
| 393 | mutex_exit(DBUF_HASH_MUTEX(h, idx)); |
| 394 | return (dbf); |
| 395 | } |
| 396 | mutex_exit(&dbf->db_mtx); |
| 397 | } |
| 398 | } |
| 399 | |
| 400 | if (i > 0) { |
| 401 | DBUF_STAT_BUMP(hash_collisions); |
| 402 | if (i == 1) |
| 403 | DBUF_STAT_BUMP(hash_chains); |
| 404 | |
| 405 | DBUF_STAT_MAX(hash_chain_max, i); |
| 406 | } |
| 407 | |
| 408 | mutex_enter(&db->db_mtx); |
| 409 | db->db_hash_next = h->hash_table[idx]; |
| 410 | h->hash_table[idx] = db; |
| 411 | mutex_exit(DBUF_HASH_MUTEX(h, idx)); |
| 412 | atomic_inc_64(&dbuf_hash_count); |
| 413 | DBUF_STAT_MAX(hash_elements_max, dbuf_hash_count); |
| 414 | |
| 415 | return (NULL); |
| 416 | } |
| 417 | |
| 418 | /* |
| 419 | * This returns whether this dbuf should be stored in the metadata cache, which |
no test coverage detected