From a9c94bea9fb3bef7704d71cd9486fbcebbe6e9c8 Mon Sep 17 00:00:00 2001 From: Rob Norris Date: Fri, 5 Jul 2024 13:39:33 +1000 Subject: [PATCH] zio_compress_data: limit dest length to ABD size Some callers (eg `do_corrective_recv()`) pass in a dest buffer much smaller than the wanted 87.5% of the source buffer, because the incoming abd is larger than the source data and they "know" what the decompressed size with be. However, `abd_borrow_buf()` rightly asserts if we try to borrow more than is available, so these callers fail. Previously when all we had was a dest buffer, we didn't know how big it was, so we couldn't do anything. Now we have a dest abd, with a size, so we can clamp dest size to the abd size. Sponsored-by: Klara, Inc. Sponsored-by: Wasabi Technology, Inc. Signed-off-by: Rob Norris --- module/zfs/zio_compress.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/module/zfs/zio_compress.c b/module/zfs/zio_compress.c index faf4309720..9182917f75 100644 --- a/module/zfs/zio_compress.c +++ b/module/zfs/zio_compress.c @@ -135,13 +135,9 @@ zio_compress_data(enum zio_compress c, abd_t *src, abd_t **dst, size_t s_len, uint8_t complevel; zio_compress_info_t *ci = &zio_compress_table[c]; - ASSERT3U(c, <, ZIO_COMPRESS_FUNCTIONS); ASSERT3U(ci->ci_compress, !=, NULL); ASSERT3U(s_len, >, 0); - /* Compress at least 12.5% */ - d_len = s_len - (s_len >> 3); - complevel = ci->ci_level; if (c == ZIO_COMPRESS_ZSTD) { @@ -160,6 +156,9 @@ zio_compress_data(enum zio_compress c, abd_t *src, abd_t **dst, size_t s_len, if (*dst == NULL) *dst = abd_alloc_sametype(src, s_len); + /* Compress at least 12.5%, but limit to the size of the dest abd. */ + d_len = MIN(s_len - (s_len >> 3), abd_get_size(*dst)); + c_len = ci->ci_compress(src, *dst, s_len, d_len, complevel); if (c_len > d_len)