267 dnode_t *dn;
268 dmu_buf_impl_t *db;
269 int error;
270
271 error = dnode_hold(os, object, FTAG, &dn);
272 if (error)
273 return (error);
274
275 rw_enter(&dn->dn_struct_rwlock, RW_READER);
276 if (dn->dn_bonus == NULL) {
277 rw_exit(&dn->dn_struct_rwlock);
278 rw_enter(&dn->dn_struct_rwlock, RW_WRITER);
279 if (dn->dn_bonus == NULL)
280 dbuf_create_bonus(dn);
281 }
282 db = dn->dn_bonus;
283
284 /* as long as the bonus buf is held, the dnode will be held */
285 if (refcount_add(&db->db_holds, tag) == 1) {
286 VERIFY(dnode_add_ref(dn, db));
287 (void) atomic_inc_32_nv(&dn->dn_dbufs_count);
288 }
289
290 /*
291 * Wait to drop dn_struct_rwlock until after adding the bonus dbuf's
292 * hold and incrementing the dbuf count to ensure that dnode_move() sees
293 * a dnode hold for every dbuf.
294 */
295 rw_exit(&dn->dn_struct_rwlock);
296
297 dnode_rele(dn, FTAG);
298
299 VERIFY(0 == dbuf_read(db, NULL, DB_RF_MUST_SUCCEED | DB_RF_NOPREFETCH));
300
301 *dbp = &db->db;
302 return (0);
303 }
304
305 /*
306 * returns ENOENT, EIO, or 0.
307 *
|
267 dnode_t *dn;
268 dmu_buf_impl_t *db;
269 int error;
270
271 error = dnode_hold(os, object, FTAG, &dn);
272 if (error)
273 return (error);
274
275 rw_enter(&dn->dn_struct_rwlock, RW_READER);
276 if (dn->dn_bonus == NULL) {
277 rw_exit(&dn->dn_struct_rwlock);
278 rw_enter(&dn->dn_struct_rwlock, RW_WRITER);
279 if (dn->dn_bonus == NULL)
280 dbuf_create_bonus(dn);
281 }
282 db = dn->dn_bonus;
283
284 /* as long as the bonus buf is held, the dnode will be held */
285 if (refcount_add(&db->db_holds, tag) == 1) {
286 VERIFY(dnode_add_ref(dn, db));
287 atomic_inc_32(&dn->dn_dbufs_count);
288 }
289
290 /*
291 * Wait to drop dn_struct_rwlock until after adding the bonus dbuf's
292 * hold and incrementing the dbuf count to ensure that dnode_move() sees
293 * a dnode hold for every dbuf.
294 */
295 rw_exit(&dn->dn_struct_rwlock);
296
297 dnode_rele(dn, FTAG);
298
299 VERIFY(0 == dbuf_read(db, NULL, DB_RF_MUST_SUCCEED | DB_RF_NOPREFETCH));
300
301 *dbp = &db->db;
302 return (0);
303 }
304
305 /*
306 * returns ENOENT, EIO, or 0.
307 *
|