Compressed receive with different ashift can result in incorrect PSIZE on disk

We round up the psize to the nearest multiple of the asize or to the
lsize, whichever is smaller. Once that's done, we allocate a new
buffer of the appropriate size, zero the tail, and copy the data
into it. This adds a small performance cost to these kinds of writes,
but fixes the bookkeeping problems.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: Matthew Ahrens <mahrens@delphix.com>
Co-authored-by: Matthew Ahrens <matthew.ahrens@delphix.com>
Signed-off-by: Paul Dagnelie <pcd@delphix.com>
Closes #12522
Closes #8462
This commit is contained in:
Paul Dagnelie 2021-09-08 13:52:28 -07:00 committed by Tony Hutter
parent 7bf68e9806
commit fd92825445
1 changed files with 12 additions and 0 deletions

View File

@ -1771,6 +1771,18 @@ zio_write_compress(zio_t *zio)
zio->io_abd, NULL, lsize, zp->zp_complevel); zio->io_abd, NULL, lsize, zp->zp_complevel);
if (psize == 0 || psize >= lsize) if (psize == 0 || psize >= lsize)
compress = ZIO_COMPRESS_OFF; compress = ZIO_COMPRESS_OFF;
} else if (zio->io_flags & ZIO_FLAG_RAW_COMPRESS) {
size_t rounded = MIN((size_t)roundup(psize,
spa->spa_min_alloc), lsize);
if (rounded != psize) {
abd_t *cdata = abd_alloc_linear(rounded, B_TRUE);
abd_zero_off(cdata, psize, rounded - psize);
abd_copy_off(cdata, zio->io_abd, 0, 0, psize);
psize = rounded;
zio_push_transform(zio, cdata,
psize, rounded, NULL);
}
} else { } else {
ASSERT3U(psize, !=, 0); ASSERT3U(psize, !=, 0);
} }