L2ARC: Cleanup buffer re-compression

When compressed ARC is disabled, we may have to re-compress when
writing into L2ARC.  If doing so we can't fit it into the original
physical size, we should just fail immediately, since even if it
may still fit into allocation size, its checksum will never match.

While there, refactor the code similar to other compression places
without using abd_return_buf_copy().

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by:	Alexander Motin <mav@FreeBSD.org>
Sponsored by:	iXsystems, Inc.
Closes #16038
This commit is contained in:
Alexander Motin 2024-04-23 12:06:00 -04:00 committed by GitHub
parent 87d81d1d13
commit 1f940de072
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 20 additions and 39 deletions

View File

@ -8902,7 +8902,6 @@ l2arc_apply_transforms(spa_t *spa, arc_buf_hdr_t *hdr, uint64_t asize,
abd_t **abd_out) abd_t **abd_out)
{ {
int ret; int ret;
void *tmp = NULL;
abd_t *cabd = NULL, *eabd = NULL, *to_write = hdr->b_l1hdr.b_pabd; abd_t *cabd = NULL, *eabd = NULL, *to_write = hdr->b_l1hdr.b_pabd;
enum zio_compress compress = HDR_GET_COMPRESS(hdr); enum zio_compress compress = HDR_GET_COMPRESS(hdr);
uint64_t psize = HDR_GET_PSIZE(hdr); uint64_t psize = HDR_GET_PSIZE(hdr);
@ -8923,12 +8922,11 @@ l2arc_apply_transforms(spa_t *spa, arc_buf_hdr_t *hdr, uint64_t asize,
* and copy the data. This may be done to eliminate a dependency on a * and copy the data. This may be done to eliminate a dependency on a
* shared buffer or to reallocate the buffer to match asize. * shared buffer or to reallocate the buffer to match asize.
*/ */
if (HDR_HAS_RABD(hdr) && asize != psize) { if (HDR_HAS_RABD(hdr)) {
ASSERT3U(asize, >=, psize); ASSERT3U(asize, >, psize);
to_write = abd_alloc_for_io(asize, ismd); to_write = abd_alloc_for_io(asize, ismd);
abd_copy(to_write, hdr->b_crypt_hdr.b_rabd, psize); abd_copy(to_write, hdr->b_crypt_hdr.b_rabd, psize);
if (psize != asize) abd_zero_off(to_write, psize, asize - psize);
abd_zero_off(to_write, psize, asize - psize);
goto out; goto out;
} }
@ -8937,48 +8935,31 @@ l2arc_apply_transforms(spa_t *spa, arc_buf_hdr_t *hdr, uint64_t asize,
ASSERT3U(size, ==, psize); ASSERT3U(size, ==, psize);
to_write = abd_alloc_for_io(asize, ismd); to_write = abd_alloc_for_io(asize, ismd);
abd_copy(to_write, hdr->b_l1hdr.b_pabd, size); abd_copy(to_write, hdr->b_l1hdr.b_pabd, size);
if (size != asize) if (asize > size)
abd_zero_off(to_write, size, asize - size); abd_zero_off(to_write, size, asize - size);
goto out; goto out;
} }
if (compress != ZIO_COMPRESS_OFF && !HDR_COMPRESSION_ENABLED(hdr)) { if (compress != ZIO_COMPRESS_OFF && !HDR_COMPRESSION_ENABLED(hdr)) {
/* size_t bufsize = MAX(size, asize);
* In some cases, we can wind up with size > asize, so void *buf = zio_buf_alloc(bufsize);
* we need to opt for the larger allocation option here. uint64_t csize = zio_compress_data(compress, to_write, &buf,
* size, hdr->b_complevel);
* (We also need abd_return_buf_copy in all cases because if (csize > psize) {
* it's an ASSERT() to modify the buffer before returning it /*
* with arc_return_buf(), and all the compressors * We can't re-compress the block into the original
* write things before deciding to fail compression in nearly * psize. Even if it fits into asize, it does not
* every case.) * matter, since checksum will never match on read.
*/ */
uint64_t bufsize = MAX(size, asize); zio_buf_free(buf, bufsize);
cabd = abd_alloc_for_io(bufsize, ismd); return (SET_ERROR(EIO));
tmp = abd_borrow_buf(cabd, bufsize);
psize = zio_compress_data(compress, to_write, &tmp, size,
hdr->b_complevel);
if (psize >= asize) {
psize = HDR_GET_PSIZE(hdr);
abd_return_buf_copy(cabd, tmp, bufsize);
HDR_SET_COMPRESS(hdr, ZIO_COMPRESS_OFF);
to_write = cabd;
abd_copy(to_write, hdr->b_l1hdr.b_pabd, psize);
if (psize != asize)
abd_zero_off(to_write, psize, asize - psize);
goto encrypt;
} }
ASSERT3U(psize, <=, HDR_GET_PSIZE(hdr)); if (asize > csize)
if (psize < asize) memset((char *)buf + csize, 0, asize - csize);
memset((char *)tmp + psize, 0, bufsize - psize); to_write = cabd = abd_get_from_buf(buf, bufsize);
psize = HDR_GET_PSIZE(hdr); abd_take_ownership_of_buf(cabd, B_TRUE);
abd_return_buf_copy(cabd, tmp, bufsize);
to_write = cabd;
} }
encrypt:
if (HDR_ENCRYPTED(hdr)) { if (HDR_ENCRYPTED(hdr)) {
eabd = abd_alloc_for_io(asize, ismd); eabd = abd_alloc_for_io(asize, ismd);