* Directly assign a provided arc buf to a given dbuf if it's not referenced * by anybody except our caller. Otherwise copy arcbuf's contents to dbuf. */
| 2659 | * by anybody except our caller. Otherwise copy arcbuf's contents to dbuf. |
| 2660 | */ |
| 2661 | void |
| 2662 | dbuf_assign_arcbuf(dmu_buf_impl_t *db, arc_buf_t *buf, dmu_tx_t *tx) |
| 2663 | { |
| 2664 | ASSERT(!zfs_refcount_is_zero(&db->db_holds)); |
| 2665 | ASSERT(db->db_blkid != DMU_BONUS_BLKID); |
| 2666 | ASSERT(db->db_level == 0); |
| 2667 | ASSERT3U(dbuf_is_metadata(db), ==, arc_is_metadata(buf)); |
| 2668 | ASSERT(buf != NULL); |
| 2669 | ASSERT3U(arc_buf_lsize(buf), ==, db->db.db_size); |
| 2670 | ASSERT(tx->tx_txg != 0); |
| 2671 | |
| 2672 | arc_return_buf(buf, db); |
| 2673 | ASSERT(arc_released(buf)); |
| 2674 | |
| 2675 | mutex_enter(&db->db_mtx); |
| 2676 | |
| 2677 | while (db->db_state == DB_READ || db->db_state == DB_FILL) |
| 2678 | cv_wait(&db->db_changed, &db->db_mtx); |
| 2679 | |
| 2680 | ASSERT(db->db_state == DB_CACHED || db->db_state == DB_UNCACHED); |
| 2681 | |
| 2682 | if (db->db_state == DB_CACHED && |
| 2683 | zfs_refcount_count(&db->db_holds) - 1 > db->db_dirtycnt) { |
| 2684 | /* |
| 2685 | * In practice, we will never have a case where we have an |
| 2686 | * encrypted arc buffer while additional holds exist on the |
| 2687 | * dbuf. We don't handle this here so we simply assert that |
| 2688 | * fact instead. |
| 2689 | */ |
| 2690 | ASSERT(!arc_is_encrypted(buf)); |
| 2691 | mutex_exit(&db->db_mtx); |
| 2692 | (void) dbuf_dirty(db, tx); |
| 2693 | bcopy(buf->b_data, db->db.db_data, db->db.db_size); |
| 2694 | arc_buf_destroy(buf, db); |
| 2695 | return; |
| 2696 | } |
| 2697 | |
| 2698 | if (db->db_state == DB_CACHED) { |
| 2699 | dbuf_dirty_record_t *dr = list_head(&db->db_dirty_records); |
| 2700 | |
| 2701 | ASSERT(db->db_buf != NULL); |
| 2702 | if (dr != NULL && dr->dr_txg == tx->tx_txg) { |
| 2703 | ASSERT(dr->dt.dl.dr_data == db->db_buf); |
| 2704 | |
| 2705 | if (!arc_released(db->db_buf)) { |
| 2706 | ASSERT(dr->dt.dl.dr_override_state == |
| 2707 | DR_OVERRIDDEN); |
| 2708 | arc_release(db->db_buf, db); |
| 2709 | } |
| 2710 | dr->dt.dl.dr_data = buf; |
| 2711 | arc_buf_destroy(db->db_buf, db); |
| 2712 | } else if (dr == NULL || dr->dt.dl.dr_data != db->db_buf) { |
| 2713 | arc_release(db->db_buf, db); |
| 2714 | arc_buf_destroy(db->db_buf, db); |
| 2715 | } |
| 2716 | db->db_buf = NULL; |
| 2717 | } |
| 2718 | ASSERT(db->db_buf == NULL); |
no test coverage detected