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 <rob.norris@klarasystems.com>
This commit is contained in:
Rob Norris 2024-07-05 13:39:33 +10:00 committed by Tony Hutter
parent f62e6e1f98
commit a9c94bea9f

View File

@ -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)