Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

zio_compress: introduce max_size threshold #9416

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion cmd/zstream/zstream_recompress.c
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,8 @@ zstream_do_recompress(int argc, char *argv[])
abd_t *pabd =
abd_get_from_buf_struct(&abd, buf, bufsz);
size_t csize = zio_compress_data(ctype, &dabd,
&pabd, drrw->drr_logical_size, level);
&pabd, drrw->drr_logical_size,
drrw->drr_logical_size, level);
size_t rounded =
P2ROUNDUP(csize, SPA_MINBLOCKSIZE);
if (rounded >= drrw->drr_logical_size) {
Expand Down
3 changes: 3 additions & 0 deletions include/sys/zio.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
* Copyright (c) 2019, Allan Jude
* Copyright (c) 2019, 2023, 2024, Klara Inc.
* Copyright (c) 2019-2020, Michael Niewöhner
* Copyright (c) 2024 by George Melikov. All rights reserved.
*/

#ifndef _ZIO_H
Expand Down Expand Up @@ -603,6 +604,8 @@ extern int zio_alloc_zil(spa_t *spa, objset_t *os, uint64_t txg,
extern void zio_flush(zio_t *zio, vdev_t *vd);
extern void zio_shrink(zio_t *zio, uint64_t size);

extern size_t zio_get_compression_max_size(enum zio_compress compress,
uint64_t gcd_alloc, uint64_t min_alloc, size_t s_len);
extern int zio_wait(zio_t *zio);
extern void zio_nowait(zio_t *zio);
extern void zio_execute(void *zio);
Expand Down
3 changes: 2 additions & 1 deletion include/sys/zio_compress.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
* Copyright (c) 2019, 2024, Klara, Inc.
* Use is subject to license terms.
* Copyright (c) 2015, 2016 by Delphix. All rights reserved.
* Copyright (c) 2021, 2024 by George Melikov. All rights reserved.
*/

#ifndef _SYS_ZIO_COMPRESS_H
Expand Down Expand Up @@ -174,7 +175,7 @@ extern int zfs_lz4_decompress(abd_t *src, abd_t *dst, size_t s_len,
* Compress and decompress data if necessary.
*/
extern size_t zio_compress_data(enum zio_compress c, abd_t *src, abd_t **dst,
size_t s_len, uint8_t level);
size_t s_len, size_t d_len, uint8_t level);
extern int zio_decompress_data(enum zio_compress c, abd_t *src, abd_t *abd,
size_t s_len, size_t d_len, uint8_t *level);
extern int zio_compress_to_feature(enum zio_compress comp);
Expand Down
26 changes: 18 additions & 8 deletions man/man7/zfsprops.7
Original file line number Diff line number Diff line change
Expand Up @@ -917,14 +917,24 @@ zeroes (the NUL byte).
When a zero-filled block is detected, it is stored as
a hole and not compressed using the indicated compression algorithm.
.Pp
Any block being compressed must be no larger than 7/8 of its original size
after compression, otherwise the compression will not be considered worthwhile
and the block saved uncompressed.
Note that when the logical block is less than
8 times the disk sector size this effectively reduces the necessary compression
ratio; for example, 8 KiB blocks on disks with 4 KiB disk sectors must compress
to 1/2
or less of their original size.
All blocks are allocated as a whole number of sectors
.Pq chunks of 2^ Ns Sy ashift No bytes , e.g . Sy 512B No or Sy 4KB .
Compression may result in a non-sector-aligned size, which will be rounded up
to a whole number of sectors.
If compression saves less than one whole sector,
the block will be stored uncompressed.
Therefore, blocks whose logical size is a small number of sectors will
experience less compression
(e.g. for
.Sy recordsize Ns = Ns Sy 16K
with
.Sy 4K
sectors, which have 4 sectors per block,
compression needs to save at least 25% to actually save space on disk).
.Pp
There is
.Sy 12.5%
default compression threshold in addition to sector rounding.
.It Xo
.Sy context Ns = Ns Sy none Ns | Ns
.Ar SELinux-User : Ns Ar SELinux-Role : Ns Ar SELinux-Type : Ns Ar Sensitivity-Level
Expand Down
20 changes: 14 additions & 6 deletions module/zfs/arc.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
* Copyright (c) 2019, 2023, Klara Inc.
* Copyright (c) 2019, Allan Jude
* Copyright (c) 2020, The FreeBSD Foundation [1]
* Copyright (c) 2021, 2024 by George Melikov. All rights reserved.
*
* [1] Portions of this software were developed by Allan Jude
* under sponsorship from the FreeBSD Foundation.
Expand Down Expand Up @@ -1786,9 +1787,13 @@ arc_hdr_authenticate(arc_buf_hdr_t *hdr, spa_t *spa, uint64_t dsobj)
!HDR_COMPRESSION_ENABLED(hdr)) {
abd = NULL;
csize = zio_compress_data(HDR_GET_COMPRESS(hdr),
hdr->b_l1hdr.b_pabd, &abd, lsize, hdr->b_complevel);
hdr->b_l1hdr.b_pabd, &abd, lsize, MIN(lsize, psize),
hdr->b_complevel);
if (csize >= lsize || csize > psize) {
ret = SET_ERROR(EIO);
return (ret);
}
ASSERT3P(abd, !=, NULL);
ASSERT3U(csize, <=, psize);
abd_zero_off(abd, csize, psize - csize);
free_abd = B_TRUE;
}
Expand Down Expand Up @@ -9029,8 +9034,8 @@ l2arc_apply_transforms(spa_t *spa, arc_buf_hdr_t *hdr, uint64_t asize,
if (compress != ZIO_COMPRESS_OFF && !HDR_COMPRESSION_ENABLED(hdr)) {
cabd = abd_alloc_for_io(MAX(size, asize), ismd);
uint64_t csize = zio_compress_data(compress, to_write, &cabd,
size, hdr->b_complevel);
if (csize > psize) {
size, MIN(size, psize), hdr->b_complevel);
if (csize >= size || csize > psize) {
/*
* We can't re-compress the block into the original
* psize. Even if it fits into asize, it does not
Expand Down Expand Up @@ -10521,9 +10526,12 @@ l2arc_log_blk_commit(l2arc_dev_t *dev, zio_t *pio, l2arc_write_callback_t *cb)
*/
list_insert_tail(&cb->l2wcb_abd_list, abd_buf);

/* try to compress the buffer */
/* try to compress the buffer, at least one sector to save */
psize = zio_compress_data(ZIO_COMPRESS_LZ4,
abd_buf->abd, &abd, sizeof (*lb), 0);
abd_buf->abd, &abd, sizeof (*lb),
zio_get_compression_max_size(ZIO_COMPRESS_LZ4,
dev->l2ad_vdev->vdev_ashift,
dev->l2ad_vdev->vdev_ashift, sizeof (*lb)), 0);

/* a log block is never entirely zero */
ASSERT(psize != 0);
Expand Down
2 changes: 1 addition & 1 deletion module/zfs/dmu_recv.c
Original file line number Diff line number Diff line change
Expand Up @@ -1408,7 +1408,7 @@ do_corrective_recv(struct receive_writer_arg *rwa, struct drr_write *drrw,
abd_t *cabd = abd_alloc_linear(BP_GET_PSIZE(bp),
B_FALSE);
uint64_t csize = zio_compress_data(BP_GET_COMPRESS(bp),
abd, &cabd, abd_get_size(abd),
abd, &cabd, abd_get_size(abd), BP_GET_PSIZE(bp),
rwa->os->os_complevel);
abd_zero_off(cabd, csize, BP_GET_PSIZE(bp) - csize);
/* Swap in newly compressed data into the abd */
Expand Down
26 changes: 25 additions & 1 deletion module/zfs/zio.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
* Copyright (c) 2019, 2023, 2024, Klara Inc.
* Copyright (c) 2019, Allan Jude
* Copyright (c) 2021, Datto, Inc.
* Copyright (c) 2021, 2024 by George Melikov. All rights reserved.
*/

#include <sys/sysmacros.h>
Expand Down Expand Up @@ -1704,6 +1705,26 @@ zio_roundup_alloc_size(spa_t *spa, uint64_t size)
return (spa->spa_min_alloc);
}

size_t
zio_get_compression_max_size(enum zio_compress compress, uint64_t gcd_alloc,
uint64_t min_alloc, size_t s_len)
{
size_t d_len;

/* minimum 12.5% must be saved (legacy value, may be changed later) */
d_len = s_len - (s_len >> 3);

/* ZLE can't use exactly d_len bytes, it needs more, so ignore it */
if (compress == ZIO_COMPRESS_ZLE)
return (d_len);

d_len = d_len - d_len % gcd_alloc;

if (d_len < min_alloc)
return (BPE_PAYLOAD_SIZE);
return (d_len);
}

/*
* ==========================================================================
* Prepare to read and write logical blocks
Expand Down Expand Up @@ -1885,7 +1906,10 @@ zio_write_compress(zio_t *zio)
psize = lsize;
else
psize = zio_compress_data(compress, zio->io_abd, &cabd,
lsize, zp->zp_complevel);
lsize,
zio_get_compression_max_size(compress,
spa->spa_gcd_alloc, spa->spa_min_alloc, lsize),
zp->zp_complevel);
if (psize == 0) {
compress = ZIO_COMPRESS_OFF;
} else if (psize >= lsize) {
Expand Down
14 changes: 3 additions & 11 deletions module/zfs/zio_compress.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,11 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
*/

/*
* Copyright (c) 2013, 2018 by Delphix. All rights reserved.
* Copyright (c) 2019, 2024, Klara, Inc.
* Copyright (c) 2019, Allan Jude
* Copyright (c) 2021, 2024 by George Melikov. All rights reserved.
*/

#include <sys/zfs_context.h>
Expand Down Expand Up @@ -129,9 +125,9 @@ zio_compress_select(spa_t *spa, enum zio_compress child,

size_t
gmelikov marked this conversation as resolved.
Show resolved Hide resolved
zio_compress_data(enum zio_compress c, abd_t *src, abd_t **dst, size_t s_len,
uint8_t level)
size_t d_len, uint8_t level)
{
size_t c_len, d_len;
size_t c_len;
uint8_t complevel;
zio_compress_info_t *ci = &zio_compress_table[c];

Expand All @@ -156,15 +152,11 @@ 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)
return (s_len);

ASSERT3U(c_len, <=, d_len);
return (c_len);
}

Expand Down
Loading