158 uint64_t hv = DBUF_HASH(os, obj, level, blkid);
159 uint64_t idx = hv & h->hash_table_mask;
160 dmu_buf_impl_t *dbf;
161
162 mutex_enter(DBUF_HASH_MUTEX(h, idx));
163 for (dbf = h->hash_table[idx]; dbf != NULL; dbf = dbf->db_hash_next) {
164 if (DBUF_EQUAL(dbf, os, obj, level, blkid)) {
165 mutex_enter(&dbf->db_mtx);
166 if (dbf->db_state != DB_EVICTING) {
167 mutex_exit(DBUF_HASH_MUTEX(h, idx));
168 return (dbf);
169 }
170 mutex_exit(&dbf->db_mtx);
171 }
172 }
173
174 mutex_enter(&db->db_mtx);
175 db->db_hash_next = h->hash_table[idx];
176 h->hash_table[idx] = db;
177 mutex_exit(DBUF_HASH_MUTEX(h, idx));
178 atomic_add_64(&dbuf_hash_count, 1);
179
180 return (NULL);
181 }
182
183 /*
184 * Remove an entry from the hash table. This operation will
185 * fail if there are any existing holds on the db.
186 */
187 static void
188 dbuf_hash_remove(dmu_buf_impl_t *db)
189 {
190 dbuf_hash_table_t *h = &dbuf_hash_table;
191 uint64_t hv = DBUF_HASH(db->db_objset, db->db.db_object,
192 db->db_level, db->db_blkid);
193 uint64_t idx = hv & h->hash_table_mask;
194 dmu_buf_impl_t *dbf, **dbp;
195
196 /*
197 * We musn't hold db_mtx to maintin lock ordering:
198 * DBUF_HASH_MUTEX > db_mtx.
199 */
200 ASSERT(refcount_is_zero(&db->db_holds));
201 ASSERT(db->db_state == DB_EVICTING);
202 ASSERT(!MUTEX_HELD(&db->db_mtx));
203
204 mutex_enter(DBUF_HASH_MUTEX(h, idx));
205 dbp = &h->hash_table[idx];
206 while ((dbf = *dbp) != db) {
207 dbp = &dbf->db_hash_next;
208 ASSERT(dbf != NULL);
209 }
210 *dbp = db->db_hash_next;
211 db->db_hash_next = NULL;
212 mutex_exit(DBUF_HASH_MUTEX(h, idx));
213 atomic_add_64(&dbuf_hash_count, -1);
214 }
215
216 static arc_evict_func_t dbuf_do_evict;
217
218 static void
219 dbuf_evict_user(dmu_buf_impl_t *db)
220 {
221 ASSERT(MUTEX_HELD(&db->db_mtx));
222
223 if (db->db_level != 0 || db->db_evict_func == NULL)
224 return;
225
226 if (db->db_user_data_ptr_ptr)
227 *db->db_user_data_ptr_ptr = db->db.db_data;
228 db->db_evict_func(&db->db, db->db_user_ptr);
229 db->db_user_ptr = NULL;
230 db->db_user_data_ptr_ptr = NULL;
231 db->db_evict_func = NULL;
232 }
233
|
158 uint64_t hv = DBUF_HASH(os, obj, level, blkid);
159 uint64_t idx = hv & h->hash_table_mask;
160 dmu_buf_impl_t *dbf;
161
162 mutex_enter(DBUF_HASH_MUTEX(h, idx));
163 for (dbf = h->hash_table[idx]; dbf != NULL; dbf = dbf->db_hash_next) {
164 if (DBUF_EQUAL(dbf, os, obj, level, blkid)) {
165 mutex_enter(&dbf->db_mtx);
166 if (dbf->db_state != DB_EVICTING) {
167 mutex_exit(DBUF_HASH_MUTEX(h, idx));
168 return (dbf);
169 }
170 mutex_exit(&dbf->db_mtx);
171 }
172 }
173
174 mutex_enter(&db->db_mtx);
175 db->db_hash_next = h->hash_table[idx];
176 h->hash_table[idx] = db;
177 mutex_exit(DBUF_HASH_MUTEX(h, idx));
178 atomic_inc_64(&dbuf_hash_count);
179
180 return (NULL);
181 }
182
183 /*
184 * Remove an entry from the hash table. This operation will
185 * fail if there are any existing holds on the db.
186 */
187 static void
188 dbuf_hash_remove(dmu_buf_impl_t *db)
189 {
190 dbuf_hash_table_t *h = &dbuf_hash_table;
191 uint64_t hv = DBUF_HASH(db->db_objset, db->db.db_object,
192 db->db_level, db->db_blkid);
193 uint64_t idx = hv & h->hash_table_mask;
194 dmu_buf_impl_t *dbf, **dbp;
195
196 /*
197 * We musn't hold db_mtx to maintin lock ordering:
198 * DBUF_HASH_MUTEX > db_mtx.
199 */
200 ASSERT(refcount_is_zero(&db->db_holds));
201 ASSERT(db->db_state == DB_EVICTING);
202 ASSERT(!MUTEX_HELD(&db->db_mtx));
203
204 mutex_enter(DBUF_HASH_MUTEX(h, idx));
205 dbp = &h->hash_table[idx];
206 while ((dbf = *dbp) != db) {
207 dbp = &dbf->db_hash_next;
208 ASSERT(dbf != NULL);
209 }
210 *dbp = db->db_hash_next;
211 db->db_hash_next = NULL;
212 mutex_exit(DBUF_HASH_MUTEX(h, idx));
213 atomic_dec_64(&dbuf_hash_count);
214 }
215
216 static arc_evict_func_t dbuf_do_evict;
217
218 static void
219 dbuf_evict_user(dmu_buf_impl_t *db)
220 {
221 ASSERT(MUTEX_HELD(&db->db_mtx));
222
223 if (db->db_level != 0 || db->db_evict_func == NULL)
224 return;
225
226 if (db->db_user_data_ptr_ptr)
227 *db->db_user_data_ptr_ptr = db->db.db_data;
228 db->db_evict_func(&db->db, db->db_user_ptr);
229 db->db_user_ptr = NULL;
230 db->db_user_data_ptr_ptr = NULL;
231 db->db_evict_func = NULL;
232 }
233
|