Corrected edge case in uncompressed ARC->L2ARC handling
I genuinely don't know why this didn't come up before, but adding the LZ4 early abort pointed out this flaw, in which we're allocating a buffer of one size, and then telling the compressor that we're handing it buffers of a different size, which may be Very Different - say, allocating 512b and then telling it the inputs are 128k. Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Reviewed-by: George Amanakis <gamanakis@gmail.com> Signed-off-by: Rich Ercolani <rincebrain@gmail.com> Closes #13375
This commit is contained in:
parent
81b8b2d004
commit
7bf06f7262
|
@ -9337,26 +9337,37 @@ l2arc_apply_transforms(spa_t *spa, arc_buf_hdr_t *hdr, uint64_t asize,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (compress != ZIO_COMPRESS_OFF && !HDR_COMPRESSION_ENABLED(hdr)) {
|
if (compress != ZIO_COMPRESS_OFF && !HDR_COMPRESSION_ENABLED(hdr)) {
|
||||||
cabd = abd_alloc_for_io(asize, ismd);
|
/*
|
||||||
tmp = abd_borrow_buf(cabd, asize);
|
* In some cases, we can wind up with size > asize, so
|
||||||
|
* we need to opt for the larger allocation option here.
|
||||||
|
*
|
||||||
|
* (We also need abd_return_buf_copy in all cases because
|
||||||
|
* it's an ASSERT() to modify the buffer before returning it
|
||||||
|
* with arc_return_buf(), and all the compressors
|
||||||
|
* write things before deciding to fail compression in nearly
|
||||||
|
* every case.)
|
||||||
|
*/
|
||||||
|
cabd = abd_alloc_for_io(size, ismd);
|
||||||
|
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 >= size) {
|
if (psize >= asize) {
|
||||||
abd_return_buf(cabd, tmp, asize);
|
psize = HDR_GET_PSIZE(hdr);
|
||||||
|
abd_return_buf_copy(cabd, tmp, size);
|
||||||
HDR_SET_COMPRESS(hdr, ZIO_COMPRESS_OFF);
|
HDR_SET_COMPRESS(hdr, ZIO_COMPRESS_OFF);
|
||||||
to_write = cabd;
|
to_write = cabd;
|
||||||
abd_copy(to_write, hdr->b_l1hdr.b_pabd, size);
|
abd_copy(to_write, hdr->b_l1hdr.b_pabd, psize);
|
||||||
if (size != asize)
|
if (psize != asize)
|
||||||
abd_zero_off(to_write, size, asize - size);
|
abd_zero_off(to_write, psize, asize - psize);
|
||||||
goto encrypt;
|
goto encrypt;
|
||||||
}
|
}
|
||||||
ASSERT3U(psize, <=, HDR_GET_PSIZE(hdr));
|
ASSERT3U(psize, <=, HDR_GET_PSIZE(hdr));
|
||||||
if (psize < asize)
|
if (psize < asize)
|
||||||
memset((char *)tmp + psize, 0, asize - psize);
|
memset((char *)tmp + psize, 0, asize - psize);
|
||||||
psize = HDR_GET_PSIZE(hdr);
|
psize = HDR_GET_PSIZE(hdr);
|
||||||
abd_return_buf_copy(cabd, tmp, asize);
|
abd_return_buf_copy(cabd, tmp, size);
|
||||||
to_write = cabd;
|
to_write = cabd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue