407 #ifdef DEBUG
408 DB_DNODE_ENTER(db);
409 ASSERT3P(DB_DNODE(db), ==, dn);
410 DB_DNODE_EXIT(db);
411 #endif /* DEBUG */
412
413 mutex_enter(&db->db_mtx);
414 if (db->db_state != DB_EVICTING &&
415 refcount_is_zero(&db->db_holds)) {
416 db_marker.db_level = db->db_level;
417 db_marker.db_blkid = db->db_blkid;
418 db_marker.db_state = DB_SEARCH;
419 avl_insert_here(&dn->dn_dbufs, &db_marker, db,
420 AVL_BEFORE);
421
422 dbuf_clear(db);
423
424 db_next = AVL_NEXT(&dn->dn_dbufs, &db_marker);
425 avl_remove(&dn->dn_dbufs, &db_marker);
426 } else {
427 mutex_exit(&db->db_mtx);
428 db_next = AVL_NEXT(&dn->dn_dbufs, db);
429 }
430 }
431 mutex_exit(&dn->dn_dbufs_mtx);
432
433 dnode_evict_bonus(dn);
434 }
435
436 void
437 dnode_evict_bonus(dnode_t *dn)
438 {
439 rw_enter(&dn->dn_struct_rwlock, RW_WRITER);
440 if (dn->dn_bonus && refcount_is_zero(&dn->dn_bonus->db_holds)) {
441 mutex_enter(&dn->dn_bonus->db_mtx);
442 dbuf_evict(dn->dn_bonus);
443 dn->dn_bonus = NULL;
444 }
445 rw_exit(&dn->dn_struct_rwlock);
446 }
447
448 static void
449 dnode_undirty_dbufs(list_t *list)
450 {
451 dbuf_dirty_record_t *dr;
452
453 while (dr = list_head(list)) {
454 dmu_buf_impl_t *db = dr->dr_dbuf;
455 uint64_t txg = dr->dr_txg;
456
457 if (db->db_level != 0)
458 dnode_undirty_dbufs(&dr->dt.di.dr_children);
459
460 mutex_enter(&db->db_mtx);
461 /* XXX - use dbuf_undirty()? */
462 list_remove(list, dr);
463 ASSERT(db->db_last_dirty == dr);
464 db->db_last_dirty = NULL;
475 dbuf_rele_and_unlock(db, (void *)(uintptr_t)txg);
476 }
477 }
478
479 static void
480 dnode_sync_free(dnode_t *dn, dmu_tx_t *tx)
481 {
482 int txgoff = tx->tx_txg & TXG_MASK;
483
484 ASSERT(dmu_tx_is_syncing(tx));
485
486 /*
487 * Our contents should have been freed in dnode_sync() by the
488 * free range record inserted by the caller of dnode_free().
489 */
490 ASSERT0(DN_USED_BYTES(dn->dn_phys));
491 ASSERT(BP_IS_HOLE(dn->dn_phys->dn_blkptr));
492
493 dnode_undirty_dbufs(&dn->dn_dirty_records[txgoff]);
494 dnode_evict_dbufs(dn);
495 ASSERT(avl_is_empty(&dn->dn_dbufs));
496
497 /*
498 * XXX - It would be nice to assert this, but we may still
499 * have residual holds from async evictions from the arc...
500 *
501 * zfs_obj_to_path() also depends on this being
502 * commented out.
503 *
504 * ASSERT3U(refcount_count(&dn->dn_holds), ==, 1);
505 */
506
507 /* Undirty next bits */
508 dn->dn_next_nlevels[txgoff] = 0;
509 dn->dn_next_indblkshift[txgoff] = 0;
510 dn->dn_next_blksz[txgoff] = 0;
511
512 /* ASSERT(blkptrs are zero); */
513 ASSERT(dn->dn_phys->dn_type != DMU_OT_NONE);
514 ASSERT(dn->dn_type != DMU_OT_NONE);
515
|
407 #ifdef DEBUG
408 DB_DNODE_ENTER(db);
409 ASSERT3P(DB_DNODE(db), ==, dn);
410 DB_DNODE_EXIT(db);
411 #endif /* DEBUG */
412
413 mutex_enter(&db->db_mtx);
414 if (db->db_state != DB_EVICTING &&
415 refcount_is_zero(&db->db_holds)) {
416 db_marker.db_level = db->db_level;
417 db_marker.db_blkid = db->db_blkid;
418 db_marker.db_state = DB_SEARCH;
419 avl_insert_here(&dn->dn_dbufs, &db_marker, db,
420 AVL_BEFORE);
421
422 dbuf_clear(db);
423
424 db_next = AVL_NEXT(&dn->dn_dbufs, &db_marker);
425 avl_remove(&dn->dn_dbufs, &db_marker);
426 } else {
427 db->db_pending_evict = TRUE;
428 mutex_exit(&db->db_mtx);
429 db_next = AVL_NEXT(&dn->dn_dbufs, db);
430 }
431 }
432 mutex_exit(&dn->dn_dbufs_mtx);
433
434 dnode_evict_bonus(dn);
435 }
436
437 void
438 dnode_evict_bonus(dnode_t *dn)
439 {
440 rw_enter(&dn->dn_struct_rwlock, RW_WRITER);
441 if (dn->dn_bonus != NULL) {
442 if (refcount_is_zero(&dn->dn_bonus->db_holds)) {
443 mutex_enter(&dn->dn_bonus->db_mtx);
444 dbuf_evict(dn->dn_bonus);
445 dn->dn_bonus = NULL;
446 } else {
447 dn->dn_bonus->db_pending_evict = TRUE;
448 }
449 }
450 rw_exit(&dn->dn_struct_rwlock);
451 }
452
453 static void
454 dnode_undirty_dbufs(list_t *list)
455 {
456 dbuf_dirty_record_t *dr;
457
458 while (dr = list_head(list)) {
459 dmu_buf_impl_t *db = dr->dr_dbuf;
460 uint64_t txg = dr->dr_txg;
461
462 if (db->db_level != 0)
463 dnode_undirty_dbufs(&dr->dt.di.dr_children);
464
465 mutex_enter(&db->db_mtx);
466 /* XXX - use dbuf_undirty()? */
467 list_remove(list, dr);
468 ASSERT(db->db_last_dirty == dr);
469 db->db_last_dirty = NULL;
480 dbuf_rele_and_unlock(db, (void *)(uintptr_t)txg);
481 }
482 }
483
484 static void
485 dnode_sync_free(dnode_t *dn, dmu_tx_t *tx)
486 {
487 int txgoff = tx->tx_txg & TXG_MASK;
488
489 ASSERT(dmu_tx_is_syncing(tx));
490
491 /*
492 * Our contents should have been freed in dnode_sync() by the
493 * free range record inserted by the caller of dnode_free().
494 */
495 ASSERT0(DN_USED_BYTES(dn->dn_phys));
496 ASSERT(BP_IS_HOLE(dn->dn_phys->dn_blkptr));
497
498 dnode_undirty_dbufs(&dn->dn_dirty_records[txgoff]);
499 dnode_evict_dbufs(dn);
500
501 /*
502 * XXX - It would be nice to assert this, but we may still
503 * have residual holds from async evictions from the arc...
504 *
505 * zfs_obj_to_path() also depends on this being
506 * commented out.
507 *
508 * ASSERT3U(refcount_count(&dn->dn_holds), ==, 1);
509 */
510
511 /* Undirty next bits */
512 dn->dn_next_nlevels[txgoff] = 0;
513 dn->dn_next_indblkshift[txgoff] = 0;
514 dn->dn_next_blksz[txgoff] = 0;
515
516 /* ASSERT(blkptrs are zero); */
517 ASSERT(dn->dn_phys->dn_type != DMU_OT_NONE);
518 ASSERT(dn->dn_type != DMU_OT_NONE);
519
|