diff --git a/module/zfs/arc.c b/module/zfs/arc.c index 48950245e2..2b0a78d4be 100644 --- a/module/zfs/arc.c +++ b/module/zfs/arc.c @@ -6087,6 +6087,10 @@ arc_write(zio_t *pio, spa_t *spa, uint64_t txg, VERIFY3P(buf->b_data, !=, NULL); arc_hdr_set_compress(hdr, ZIO_COMPRESS_OFF); } + + if (!(zio_flags & ZIO_FLAG_RAW)) + arc_hdr_set_compress(hdr, ZIO_COMPRESS_OFF); + ASSERT(!arc_buf_is_shared(buf)); ASSERT3P(hdr->b_l1hdr.b_pabd, ==, NULL); diff --git a/module/zfs/dbuf.c b/module/zfs/dbuf.c index 62340469d3..68d6e01600 100644 --- a/module/zfs/dbuf.c +++ b/module/zfs/dbuf.c @@ -63,7 +63,6 @@ struct dbuf_hold_impl_data { blkptr_t *dh_bp; int dh_err; dbuf_dirty_record_t *dh_dr; - arc_buf_contents_t dh_type; int dh_depth; }; @@ -2628,6 +2627,36 @@ dbuf_prefetch(dnode_t *dn, int64_t level, uint64_t blkid, zio_priority_t prio, #define DBUF_HOLD_IMPL_MAX_DEPTH 20 +/* + * Helper function for __dbuf_hold_impl() to copy a buffer. Handles + * the case of compressed and uncompressed buffers by allocating the + * new buffer, respectively, with arc_alloc_raw_buf(), + * arc_alloc_compressed_buf() or arc_alloc_buf().* + * + * NOTE: Declared noinline to avoid stack bloat in __dbuf_hold_impl(). + */ +noinline static void +dbuf_hold_copy(struct dbuf_hold_impl_data *dh) +{ + dnode_t *dn = dh->dh_dn; + dmu_buf_impl_t *db = dh->dh_db; + dbuf_dirty_record_t *dr = dh->dh_dr; + arc_buf_t *data = dr->dt.dl.dr_data; + + enum zio_compress compress_type = arc_get_compression(data); + + if (compress_type != ZIO_COMPRESS_OFF) { + dbuf_set_data(db, arc_alloc_compressed_buf( + dn->dn_objset->os_spa, db, arc_buf_size(data), + arc_buf_lsize(data), compress_type)); + } else { + dbuf_set_data(db, arc_alloc_buf(dn->dn_objset->os_spa, db, + DBUF_GET_BUFC_TYPE(db), db->db.db_size)); + } + + bcopy(data->b_data, db->db.db_data, arc_buf_size(data)); +} + /* * Returns with db_holds incremented, and db_mtx not held. * Note: dn_struct_rwlock must be held. @@ -2693,16 +2722,8 @@ __dbuf_hold_impl(struct dbuf_hold_impl_data *dh) dh->dh_dn->dn_object != DMU_META_DNODE_OBJECT && dh->dh_db->db_state == DB_CACHED && dh->dh_db->db_data_pending) { dh->dh_dr = dh->dh_db->db_data_pending; - - if (dh->dh_dr->dt.dl.dr_data == dh->dh_db->db_buf) { - dh->dh_type = DBUF_GET_BUFC_TYPE(dh->dh_db); - - dbuf_set_data(dh->dh_db, - arc_alloc_buf(dh->dh_dn->dn_objset->os_spa, - dh->dh_db, dh->dh_type, dh->dh_db->db.db_size)); - bcopy(dh->dh_dr->dt.dl.dr_data->b_data, - dh->dh_db->db.db_data, dh->dh_db->db.db_size); - } + if (dh->dh_dr->dt.dl.dr_data == dh->dh_db->db_buf) + dbuf_hold_copy(dh); } if (multilist_link_active(&dh->dh_db->db_cache_link)) { @@ -2775,7 +2796,6 @@ __dbuf_hold_impl_init(struct dbuf_hold_impl_data *dh, dh->dh_bp = NULL; dh->dh_err = 0; dh->dh_dr = NULL; - dh->dh_type = 0; dh->dh_depth = depth; }