Skip memory allocation when compressing holes

Hole detection in the zio compression code allows us to
opportunistically skip compression on holes. We can go a step further
by not doing memory allocations on holes either.

Reviewed-by: Brian Atkinson <batkinson@lanl.gov>
Reviewed-by: Alexander Motin <mav@FreeBSD.org>
Signed-off-by: Richard Yao <richard.yao@klarasystems.com>
Sponsored-by: Wasabi Technology, Inc.
Closes #14500
This commit is contained in:
Richard Yao 2023-02-27 17:41:02 -05:00 committed by GitHub
parent f58e513f74
commit bff26b0220
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 23 additions and 16 deletions

View File

@ -183,7 +183,7 @@ extern int lz4_decompress_zfs(void *src, void *dst, size_t s_len, size_t d_len,
/* /*
* Compress and decompress data if necessary. * Compress and decompress data if necessary.
*/ */
extern size_t zio_compress_data(enum zio_compress c, abd_t *src, void *dst, extern size_t zio_compress_data(enum zio_compress c, abd_t *src, void **dst,
size_t s_len, uint8_t level); size_t s_len, uint8_t level);
extern int zio_decompress_data(enum zio_compress c, abd_t *src, void *dst, extern int zio_decompress_data(enum zio_compress c, abd_t *src, void *dst,
size_t s_len, size_t d_len, uint8_t *level); size_t s_len, size_t d_len, uint8_t *level);

View File

@ -1816,12 +1816,13 @@ arc_hdr_authenticate(arc_buf_hdr_t *hdr, spa_t *spa, uint64_t dsobj)
*/ */
if (HDR_GET_COMPRESS(hdr) != ZIO_COMPRESS_OFF && if (HDR_GET_COMPRESS(hdr) != ZIO_COMPRESS_OFF &&
!HDR_COMPRESSION_ENABLED(hdr)) { !HDR_COMPRESSION_ENABLED(hdr)) {
tmpbuf = zio_buf_alloc(lsize);
csize = zio_compress_data(HDR_GET_COMPRESS(hdr),
hdr->b_l1hdr.b_pabd, &tmpbuf, lsize, hdr->b_complevel);
ASSERT3P(tmpbuf, !=, NULL);
ASSERT3U(csize, <=, psize);
abd = abd_get_from_buf(tmpbuf, lsize); abd = abd_get_from_buf(tmpbuf, lsize);
abd_take_ownership_of_buf(abd, B_TRUE); abd_take_ownership_of_buf(abd, B_TRUE);
csize = zio_compress_data(HDR_GET_COMPRESS(hdr),
hdr->b_l1hdr.b_pabd, tmpbuf, lsize, hdr->b_complevel);
ASSERT3U(csize, <=, psize);
abd_zero_off(abd, csize, psize - csize); abd_zero_off(abd, csize, psize - csize);
} }
@ -9402,7 +9403,7 @@ l2arc_apply_transforms(spa_t *spa, arc_buf_hdr_t *hdr, uint64_t asize,
cabd = abd_alloc_for_io(size, ismd); cabd = abd_alloc_for_io(size, ismd);
tmp = abd_borrow_buf(cabd, size); tmp = abd_borrow_buf(cabd, size);
psize = zio_compress_data(compress, to_write, tmp, size, psize = zio_compress_data(compress, to_write, &tmp, size,
hdr->b_complevel); hdr->b_complevel);
if (psize >= asize) { if (psize >= asize) {
@ -10867,12 +10868,11 @@ l2arc_log_blk_commit(l2arc_dev_t *dev, zio_t *pio, l2arc_write_callback_t *cb)
uint64_t psize, asize; uint64_t psize, asize;
zio_t *wzio; zio_t *wzio;
l2arc_lb_abd_buf_t *abd_buf; l2arc_lb_abd_buf_t *abd_buf;
uint8_t *tmpbuf; uint8_t *tmpbuf = NULL;
l2arc_lb_ptr_buf_t *lb_ptr_buf; l2arc_lb_ptr_buf_t *lb_ptr_buf;
VERIFY3S(dev->l2ad_log_ent_idx, ==, dev->l2ad_log_entries); VERIFY3S(dev->l2ad_log_ent_idx, ==, dev->l2ad_log_entries);
tmpbuf = zio_buf_alloc(sizeof (*lb));
abd_buf = zio_buf_alloc(sizeof (*abd_buf)); abd_buf = zio_buf_alloc(sizeof (*abd_buf));
abd_buf->abd = abd_get_from_buf(lb, sizeof (*lb)); abd_buf->abd = abd_get_from_buf(lb, sizeof (*lb));
lb_ptr_buf = kmem_zalloc(sizeof (l2arc_lb_ptr_buf_t), KM_SLEEP); lb_ptr_buf = kmem_zalloc(sizeof (l2arc_lb_ptr_buf_t), KM_SLEEP);
@ -10891,7 +10891,7 @@ l2arc_log_blk_commit(l2arc_dev_t *dev, zio_t *pio, l2arc_write_callback_t *cb)
/* try to compress the buffer */ /* try to compress the buffer */
psize = zio_compress_data(ZIO_COMPRESS_LZ4, psize = zio_compress_data(ZIO_COMPRESS_LZ4,
abd_buf->abd, tmpbuf, sizeof (*lb), 0); abd_buf->abd, (void **) &tmpbuf, sizeof (*lb), 0);
/* a log block is never entirely zero */ /* a log block is never entirely zero */
ASSERT(psize != 0); ASSERT(psize != 0);

View File

@ -1398,8 +1398,9 @@ do_corrective_recv(struct receive_writer_arg *rwa, struct drr_write *drrw,
/* Recompress the data */ /* Recompress the data */
abd_t *cabd = abd_alloc_linear(BP_GET_PSIZE(bp), abd_t *cabd = abd_alloc_linear(BP_GET_PSIZE(bp),
B_FALSE); B_FALSE);
void *buf = abd_to_buf(cabd);
uint64_t csize = zio_compress_data(BP_GET_COMPRESS(bp), uint64_t csize = zio_compress_data(BP_GET_COMPRESS(bp),
abd, abd_to_buf(cabd), abd_get_size(abd), abd, &buf, abd_get_size(abd),
rwa->os->os_complevel); rwa->os->os_complevel);
abd_zero_off(cabd, csize, BP_GET_PSIZE(bp) - csize); abd_zero_off(cabd, csize, BP_GET_PSIZE(bp) - csize);
/* Swap in newly compressed data into the abd */ /* Swap in newly compressed data into the abd */

View File

@ -1704,12 +1704,15 @@ zio_write_compress(zio_t *zio)
/* If it's a compressed write that is not raw, compress the buffer. */ /* If it's a compressed write that is not raw, compress the buffer. */
if (compress != ZIO_COMPRESS_OFF && if (compress != ZIO_COMPRESS_OFF &&
!(zio->io_flags & ZIO_FLAG_RAW_COMPRESS)) { !(zio->io_flags & ZIO_FLAG_RAW_COMPRESS)) {
void *cbuf = zio_buf_alloc(lsize); void *cbuf = NULL;
psize = zio_compress_data(compress, zio->io_abd, cbuf, lsize, psize = zio_compress_data(compress, zio->io_abd, &cbuf, lsize,
zp->zp_complevel); zp->zp_complevel);
if (psize == 0 || psize >= lsize) { if (psize == 0) {
compress = ZIO_COMPRESS_OFF; compress = ZIO_COMPRESS_OFF;
zio_buf_free(cbuf, lsize); } else if (psize >= lsize) {
compress = ZIO_COMPRESS_OFF;
if (cbuf != NULL)
zio_buf_free(cbuf, lsize);
} else if (!zp->zp_dedup && !zp->zp_encrypt && } else if (!zp->zp_dedup && !zp->zp_encrypt &&
psize <= BPE_PAYLOAD_SIZE && psize <= BPE_PAYLOAD_SIZE &&
zp->zp_level == 0 && !DMU_OT_HAS_FILL(zp->zp_type) && zp->zp_level == 0 && !DMU_OT_HAS_FILL(zp->zp_type) &&

View File

@ -125,7 +125,7 @@ zio_compress_zeroed_cb(void *data, size_t len, void *private)
} }
size_t size_t
zio_compress_data(enum zio_compress c, abd_t *src, void *dst, size_t s_len, zio_compress_data(enum zio_compress c, abd_t *src, void **dst, size_t s_len,
uint8_t level) uint8_t level)
{ {
size_t c_len, d_len; size_t c_len, d_len;
@ -163,9 +163,12 @@ zio_compress_data(enum zio_compress c, abd_t *src, void *dst, size_t s_len,
ASSERT3U(complevel, !=, ZIO_COMPLEVEL_INHERIT); ASSERT3U(complevel, !=, ZIO_COMPLEVEL_INHERIT);
} }
if (*dst == NULL)
*dst = zio_buf_alloc(s_len);
/* No compression algorithms can read from ABDs directly */ /* No compression algorithms can read from ABDs directly */
void *tmp = abd_borrow_buf_copy(src, s_len); void *tmp = abd_borrow_buf_copy(src, s_len);
c_len = ci->ci_compress(tmp, dst, s_len, d_len, complevel); c_len = ci->ci_compress(tmp, *dst, s_len, d_len, complevel);
abd_return_buf(src, tmp, s_len); abd_return_buf(src, tmp, s_len);
if (c_len > d_len) if (c_len > d_len)