* Try to kick all the dnode's dbufs out of the cache... */
| 453 | * Try to kick all the dnode's dbufs out of the cache... |
| 454 | */ |
| 455 | void |
| 456 | dnode_evict_dbufs(dnode_t *dn) |
| 457 | { |
| 458 | dmu_buf_impl_t *db_marker; |
| 459 | dmu_buf_impl_t *db, *db_next; |
| 460 | |
| 461 | db_marker = kmem_alloc(sizeof (dmu_buf_impl_t), KM_SLEEP); |
| 462 | |
| 463 | mutex_enter(&dn->dn_dbufs_mtx); |
| 464 | for (db = avl_first(&dn->dn_dbufs); db != NULL; db = db_next) { |
| 465 | |
| 466 | #ifdef ZFS_DEBUG |
| 467 | DB_DNODE_ENTER(db); |
| 468 | ASSERT3P(DB_DNODE(db), ==, dn); |
| 469 | DB_DNODE_EXIT(db); |
| 470 | #endif /* DEBUG */ |
| 471 | |
| 472 | mutex_enter(&db->db_mtx); |
| 473 | if (db->db_state != DB_EVICTING && |
| 474 | zfs_refcount_is_zero(&db->db_holds)) { |
| 475 | db_marker->db_level = db->db_level; |
| 476 | db_marker->db_blkid = db->db_blkid; |
| 477 | db_marker->db_state = DB_SEARCH; |
| 478 | avl_insert_here(&dn->dn_dbufs, db_marker, db, |
| 479 | AVL_BEFORE); |
| 480 | |
| 481 | /* |
| 482 | * We need to use the "marker" dbuf rather than |
| 483 | * simply getting the next dbuf, because |
| 484 | * dbuf_destroy() may actually remove multiple dbufs. |
| 485 | * It can call itself recursively on the parent dbuf, |
| 486 | * which may also be removed from dn_dbufs. The code |
| 487 | * flow would look like: |
| 488 | * |
| 489 | * dbuf_destroy(): |
| 490 | * dnode_rele_and_unlock(parent_dbuf, evicting=TRUE): |
| 491 | * if (!cacheable || pending_evict) |
| 492 | * dbuf_destroy() |
| 493 | */ |
| 494 | dbuf_destroy(db); |
| 495 | |
| 496 | db_next = AVL_NEXT(&dn->dn_dbufs, db_marker); |
| 497 | avl_remove(&dn->dn_dbufs, db_marker); |
| 498 | } else { |
| 499 | db->db_pending_evict = TRUE; |
| 500 | mutex_exit(&db->db_mtx); |
| 501 | db_next = AVL_NEXT(&dn->dn_dbufs, db); |
| 502 | } |
| 503 | } |
| 504 | mutex_exit(&dn->dn_dbufs_mtx); |
| 505 | |
| 506 | kmem_free(db_marker, sizeof (dmu_buf_impl_t)); |
| 507 | |
| 508 | dnode_evict_bonus(dn); |
| 509 | } |
| 510 | |
| 511 | void |
| 512 | dnode_evict_bonus(dnode_t *dn) |
no test coverage detected