* Evict (if its unreferenced) or clear (if its referenced) any level-0 * data blocks in the free range, so that any future readers will find * empty blocks. */
| 1785 | * empty blocks. |
| 1786 | */ |
| 1787 | void |
| 1788 | dbuf_free_range(dnode_t *dn, uint64_t start_blkid, uint64_t end_blkid, |
| 1789 | dmu_tx_t *tx) |
| 1790 | { |
| 1791 | dmu_buf_impl_t *db_search; |
| 1792 | dmu_buf_impl_t *db, *db_next; |
| 1793 | uint64_t txg = tx->tx_txg; |
| 1794 | avl_index_t where; |
| 1795 | dbuf_dirty_record_t *dr; |
| 1796 | |
| 1797 | if (end_blkid > dn->dn_maxblkid && |
| 1798 | !(start_blkid == DMU_SPILL_BLKID || end_blkid == DMU_SPILL_BLKID)) |
| 1799 | end_blkid = dn->dn_maxblkid; |
| 1800 | dprintf_dnode(dn, "start=%llu end=%llu\n", start_blkid, end_blkid); |
| 1801 | |
| 1802 | db_search = kmem_alloc(sizeof (dmu_buf_impl_t), KM_SLEEP); |
| 1803 | db_search->db_level = 0; |
| 1804 | db_search->db_blkid = start_blkid; |
| 1805 | db_search->db_state = DB_SEARCH; |
| 1806 | |
| 1807 | mutex_enter(&dn->dn_dbufs_mtx); |
| 1808 | db = avl_find(&dn->dn_dbufs, db_search, &where); |
| 1809 | ASSERT3P(db, ==, NULL); |
| 1810 | |
| 1811 | db = avl_nearest(&dn->dn_dbufs, where, AVL_AFTER); |
| 1812 | |
| 1813 | for (; db != NULL; db = db_next) { |
| 1814 | db_next = AVL_NEXT(&dn->dn_dbufs, db); |
| 1815 | ASSERT(db->db_blkid != DMU_BONUS_BLKID); |
| 1816 | |
| 1817 | if (db->db_level != 0 || db->db_blkid > end_blkid) { |
| 1818 | break; |
| 1819 | } |
| 1820 | ASSERT3U(db->db_blkid, >=, start_blkid); |
| 1821 | |
| 1822 | /* found a level 0 buffer in the range */ |
| 1823 | mutex_enter(&db->db_mtx); |
| 1824 | if (dbuf_undirty(db, tx)) { |
| 1825 | /* mutex has been dropped and dbuf destroyed */ |
| 1826 | continue; |
| 1827 | } |
| 1828 | |
| 1829 | if (db->db_state == DB_UNCACHED || |
| 1830 | db->db_state == DB_NOFILL || |
| 1831 | db->db_state == DB_EVICTING) { |
| 1832 | ASSERT(db->db.db_data == NULL); |
| 1833 | mutex_exit(&db->db_mtx); |
| 1834 | continue; |
| 1835 | } |
| 1836 | if (db->db_state == DB_READ || db->db_state == DB_FILL) { |
| 1837 | /* will be handled in dbuf_read_done or dbuf_rele */ |
| 1838 | db->db_freed_in_flight = TRUE; |
| 1839 | mutex_exit(&db->db_mtx); |
| 1840 | continue; |
| 1841 | } |
| 1842 | if (zfs_refcount_count(&db->db_holds) == 0) { |
| 1843 | ASSERT(db->db_buf); |
| 1844 | dbuf_destroy(db); |
no test coverage detected