Skip to content
Permalink
Browse files

Add zstd support to zfs

Signed-off-by: Allan Jude <allanjude@freebsd.org>
Signed-off-by: Sebastian Gottschall <s.gottschall@dd-wrt.com>
Signed-off-by: Kjeld Schouten-Lebbing <kjeld@schouten-lebbing.nl>
Signed-off-by: Michael Niewöhner <foss@mniewoehner.de>
  • Loading branch information...
c0d3z3r0 committed Dec 1, 2019
1 parent 9bf5127 commit d1ad340e2bedc804a1201bc78513b0e6e732dbe4
@@ -343,7 +343,7 @@ def get_compstring(c):
"ZIO_COMPRESS_GZIP_6", "ZIO_COMPRESS_GZIP_7",
"ZIO_COMPRESS_GZIP_8", "ZIO_COMPRESS_GZIP_9",
"ZIO_COMPRESS_ZLE", "ZIO_COMPRESS_LZ4",
"ZIO_COMPRESS_FUNCTION"]
"ZIO_COMPRESS_ZSTD", "ZIO_COMPRESS_FUNCTION"]

# If "-rr" option is used, don't convert to string representation
if raw > 1:
@@ -175,6 +175,7 @@ AC_CONFIG_FILES([
module/unicode/Makefile
module/zcommon/Makefile
module/zfs/Makefile
module/zstd/Makefile
rpm/Makefile
rpm/generic/Makefile
rpm/generic/zfs-dkms.spec
@@ -105,7 +105,7 @@ typedef enum drr_headertype {
#define DMU_BACKUP_FEATURE_COMPRESSED (1 << 22)
#define DMU_BACKUP_FEATURE_LARGE_DNODE (1 << 23)
#define DMU_BACKUP_FEATURE_RAW (1 << 24)
/* flag #25 is reserved for the ZSTD compression feature */
#define DMU_BACKUP_FEATURE_ZSTD (1 << 25)
#define DMU_BACKUP_FEATURE_HOLDS (1 << 26)

/*
@@ -117,7 +117,7 @@ typedef enum drr_headertype {
DMU_BACKUP_FEATURE_RESUMING | DMU_BACKUP_FEATURE_LARGE_BLOCKS | \
DMU_BACKUP_FEATURE_COMPRESSED | DMU_BACKUP_FEATURE_LARGE_DNODE | \
DMU_BACKUP_FEATURE_RAW | DMU_BACKUP_FEATURE_HOLDS | \
DMU_BACKUP_FEATURE_REDACTED)
DMU_BACKUP_FEATURE_REDACTED | DMU_BACKUP_FEATURE_ZSTD)

/* Are all features in the given flag word currently supported? */
#define DMU_STREAM_SUPPORTED(x) (!((x) & ~DMU_BACKUP_FEATURE_MASK))
@@ -154,6 +154,7 @@ enum zio_encrypt {
(compress) == ZIO_COMPRESS_GZIP_8 || \
(compress) == ZIO_COMPRESS_GZIP_9 || \
(compress) == ZIO_COMPRESS_ZLE || \
(compress) == ZIO_COMPRESS_ZSTD || \
(compress) == ZIO_COMPRESS_ON || \
(compress) == ZIO_COMPRESS_OFF)

@@ -51,12 +51,68 @@ enum zio_compress {
ZIO_COMPRESS_GZIP_9,
ZIO_COMPRESS_ZLE,
ZIO_COMPRESS_LZ4,
ZIO_COMPRESS_ZSTD,
ZIO_COMPRESS_FUNCTIONS
};

#define ZIO_COMPLEVEL_INHERIT 0
#define ZIO_COMPLEVEL_DEFAULT 255

enum zio_zstd_levels {
ZIO_ZSTDLVL_INHERIT = 0,
ZIO_ZSTDLVL_1,
#define ZIO_ZSTD_LEVEL_MIN ZIO_ZSTDLVL_1
ZIO_ZSTDLVL_2,
ZIO_ZSTDLVL_3,
#define ZIO_ZSTD_LEVEL_DEFAULT ZIO_ZSTDLVL_3
ZIO_ZSTDLVL_4,
ZIO_ZSTDLVL_5,
ZIO_ZSTDLVL_6,
ZIO_ZSTDLVL_7,
ZIO_ZSTDLVL_8,
ZIO_ZSTDLVL_9,
ZIO_ZSTDLVL_10,
ZIO_ZSTDLVL_11,
ZIO_ZSTDLVL_12,
ZIO_ZSTDLVL_13,
ZIO_ZSTDLVL_14,
ZIO_ZSTDLVL_15,
ZIO_ZSTDLVL_16,
ZIO_ZSTDLVL_17,
ZIO_ZSTDLVL_18,
ZIO_ZSTDLVL_19,
#define ZIO_ZSTD_LEVEL_MAX ZIO_ZSTDLVL_19
#define ZIO_ZSTDLVL_MAX ZIO_ZSTDLVL_19
ZIO_ZSTDLVL_RESERVE = 101, /* Leave room for new positive levels */
ZIO_ZSTDLVL_FAST, /* Fast levels are negative */
ZIO_ZSTDLVL_FAST_1,
#define ZIO_ZSTD_FAST_LEVEL_DEFAULT ZIO_ZSTDLVL_FAST_1
ZIO_ZSTDLVL_FAST_2,
ZIO_ZSTDLVL_FAST_3,
ZIO_ZSTDLVL_FAST_4,
ZIO_ZSTDLVL_FAST_5,
ZIO_ZSTDLVL_FAST_6,
ZIO_ZSTDLVL_FAST_7,
ZIO_ZSTDLVL_FAST_8,
ZIO_ZSTDLVL_FAST_9,
ZIO_ZSTDLVL_FAST_10,
ZIO_ZSTDLVL_FAST_20,
ZIO_ZSTDLVL_FAST_30,
ZIO_ZSTDLVL_FAST_40,
ZIO_ZSTDLVL_FAST_50,
ZIO_ZSTDLVL_FAST_60,
ZIO_ZSTDLVL_FAST_70,
ZIO_ZSTDLVL_FAST_80,
ZIO_ZSTDLVL_FAST_90,
ZIO_ZSTDLVL_FAST_100,
ZIO_ZSTDLVL_FAST_500,
ZIO_ZSTDLVL_FAST_1000,
#define ZIO_ZSTDLVL_FAST_MAX ZIO_ZSTDLVL_FAST_1000
ZIO_ZSTDLVL_DEFAULT = 250, /* Allow the default level to change */
ZIO_ZSTDLVL_AUTO = 251, /* Reserved for future use */
ZIO_ZSTDLVL_LEVELS
};

/* Forward Declaration to avoid visibility problems */
struct zio_prop;

@@ -100,6 +156,12 @@ extern zio_compress_info_t zio_compress_table[ZIO_COMPRESS_FUNCTIONS];
extern void lz4_init(void);
extern void lz4_fini(void);

/*
* specific to zstd user space implementation only
*/
extern void zstd_fini(void);
extern int zstd_init(void);

/*
* Compression routines.
*/
@@ -119,6 +181,13 @@ extern size_t lz4_compress_zfs(void *src, void *dst, size_t s_len, size_t d_len,
int level);
extern int lz4_decompress_zfs(void *src, void *dst, size_t s_len, size_t d_len,
int level);
extern size_t zstd_compress(void *src, void *dst, size_t s_len, size_t d_len,
int level);
extern int zstd_decompress(void *src, void *dst, size_t s_len, size_t d_len,
int level);
extern int zstd_decompress_level(void *src, void *dst, size_t s_len,
size_t d_len, uint8_t *level);
extern int zstd_get_level(void *src, size_t s_len, uint8_t *level);

/*
* Compress and decompress data if necessary.
@@ -73,9 +73,9 @@ extern "C" {
* the supported transformations:
*
* Compression:
* ZFS supports three different flavors of compression -- gzip, lzjb, and
* zle. Compression occurs as part of the write pipeline and is performed
* in the ZIO_STAGE_WRITE_BP_INIT stage.
* ZFS supports five different flavors of compression -- gzip, lzjb, lz4, zle,
* and zstd. Compression occurs as part of the write pipeline and is
* performed in the ZIO_STAGE_WRITE_BP_INIT stage.
*
* Dedup:
* Dedup reads are handled by the ZIO_STAGE_DDT_READ_START and
@@ -66,6 +66,7 @@ typedef enum spa_feature {
SPA_FEATURE_SPACEMAP_V2,
SPA_FEATURE_ALLOCATION_CLASSES,
SPA_FEATURE_RESILVER_DEFER,
SPA_FEATURE_ZSTD_COMPRESS,
SPA_FEATURE_BOOKMARK_V2,
SPA_FEATURE_REDACTION_BOOKMARKS,
SPA_FEATURE_REDACTED_DATASETS,
@@ -5,6 +5,10 @@ VPATH = \
$(top_srcdir)/module/zcommon \
$(top_srcdir)/module/lua \
$(top_srcdir)/module/os/linux/zfs \
$(top_srcdir)/contrib/zstd/zstd-1.4.4/lib/common \
$(top_srcdir)/contrib/zstd/zstd-1.4.4/lib/compress \
$(top_srcdir)/contrib/zstd/zstd-1.4.4/lib/decompress \
$(top_srcdir)/module/zstd \
$(top_srcdir)/lib/libzpool

# Suppress unused but set variable warnings often due to ASSERTs
@@ -13,7 +17,15 @@ AM_CFLAGS += $(NO_UNUSED_BUT_SET_VARIABLE)
# Includes kernel code generate warnings for large stack frames
AM_CFLAGS += $(FRAME_LARGER_THAN)

AM_CFLAGS += -DLIB_ZPOOL_BUILD
AM_CFLAGS += -DLIB_ZPOOL_BUILD -Wframe-larger-than=20480

DEFAULT_INCLUDES += \
-I$(top_srcdir)/include \
-I$(top_srcdir)/lib/libspl/include \
-I$(top_srcdir)/contrib/zstd/zstd-1.4.4/lib \
-I$(top_srcdir)/contrib/zstd/zstd-1.4.4/lib/common \
-I$(top_srcdir)/contrib/zstd/zstd-1.4.4/lib/compress \
-I$(top_srcdir)/contrib/zstd/zstd-1.4.4/lib/decompress

lib_LTLIBRARIES = libzpool.la

@@ -161,6 +173,29 @@ KERNEL_C = \
zrlock.c \
zthr.c

ZSTD_C = \
zstd_common.c \
fse_decompress.c \
entropy_common.c \
xxhash.c \
hist.c \
error_private.c \
zstd_compress.c \
zstd_compress_literals.c \
zstd_compress_sequences.c \
fse_compress.c \
huf_compress.c \
zstd_double_fast.c \
zstd_fast.c \
zstd_lazy.c \
zstd_ldm.c \
zstd_opt.c \
zstd_ddict.c \
zstd_decompress.c \
zstd_decompress_block.c \
huf_decompress.c \
zstd.c

LUA_C = \
lapi.c \
lauxlib.c \
@@ -190,7 +225,8 @@ LUA_C = \
nodist_libzpool_la_SOURCES = \
$(USER_C) \
$(KERNEL_C) \
$(LUA_C)
$(LUA_C) \
$(ZSTD_C)

libzpool_la_LIBADD = \
$(top_builddir)/lib/libicp/libicp.la \
@@ -8,6 +8,7 @@ obj-m += unicode/
obj-m += zcommon/
obj-m += zfs/
obj-m += os/linux/zfs/
obj-m += zstd/

INSTALL_MOD_DIR ?= extra

@@ -18,6 +19,12 @@ ZFS_MODULE_CFLAGS += -I@abs_top_srcdir@/include/os/linux/kernel
ZFS_MODULE_CFLAGS += -I@abs_top_srcdir@/include/os/linux/spl
ZFS_MODULE_CFLAGS += -I@abs_top_srcdir@/include/os/linux/zfs
ZFS_MODULE_CFLAGS += -I@abs_top_srcdir@/include
ZFS_MODULE_CFLAGS += -I@abs_top_srcdir@/contrib/zstd/zstd-1.4.4/lib
ZFS_MODULE_CFLAGS += -I@abs_top_srcdir@/contrib/zstd/zstd-1.4.4/lib/common
ZFS_MODULE_CFLAGS += -I@abs_top_srcdir@/contrib/zstd/zstd-1.4.4/lib/compress
ZFS_MODULE_CFLAGS += -I@abs_top_srcdir@/contrib/zstd/zstd-1.4.4/lib/decompress
ZFS_MODULE_CFLAGS += -I@abs_top_srcdir@/include/sys/zstd

ZFS_MODULE_CPPFLAGS += -D_KERNEL
ZFS_MODULE_CPPFLAGS += @KERNEL_DEBUG_CPPFLAGS@

@@ -553,6 +553,15 @@ zpool_feature_init(void)
"com.datto:resilver_defer", "resilver_defer",
"Support for deferring new resilvers when one is already running.",
ZFEATURE_FLAG_READONLY_COMPAT, ZFEATURE_TYPE_BOOLEAN, NULL);

static const spa_feature_t zstd_deps[] = {
SPA_FEATURE_EXTENSIBLE_DATASET,
SPA_FEATURE_NONE
};
zfeature_register(SPA_FEATURE_ZSTD_COMPRESS,
"org.freebsd:zstd_compress", "zstd_compress",
"zstd compression algorithm support.",
ZFEATURE_FLAG_PER_DATASET, ZFEATURE_TYPE_BOOLEAN, zstd_deps);
}

#if defined(_KERNEL)
@@ -120,6 +120,99 @@ zfs_prop_init(void)
{ "gzip-9", ZIO_COMPRESS_GZIP_9 },
{ "zle", ZIO_COMPRESS_ZLE },
{ "lz4", ZIO_COMPRESS_LZ4 },
{ "zstd", ZIO_COMPRESS_ZSTD },
{ "zstd-fast", ZIO_COMPRESS_ZSTD |
(ZIO_ZSTDLVL_FAST_1 << SPA_COMPRESSBITS) },
/*
* ZSTD 1-19 are synthetic. We store the compression level in a
* separate hidden property to avoid wasting a large amount of
* space in the ZIO_COMPRESS enum. We do not need to know the
* compression level at decompress time, so it does not need
* to be stored on disk in the block pointer.
*/
{ "zstd-1", ZIO_COMPRESS_ZSTD |
(ZIO_ZSTDLVL_1 << SPA_COMPRESSBITS) },
{ "zstd-2", ZIO_COMPRESS_ZSTD |
(ZIO_ZSTDLVL_2 << SPA_COMPRESSBITS) },
{ "zstd-3", ZIO_COMPRESS_ZSTD |
(ZIO_ZSTDLVL_3 << SPA_COMPRESSBITS) },
{ "zstd-4", ZIO_COMPRESS_ZSTD |
(ZIO_ZSTDLVL_4 << SPA_COMPRESSBITS) },
{ "zstd-5", ZIO_COMPRESS_ZSTD |
(ZIO_ZSTDLVL_5 << SPA_COMPRESSBITS) },
{ "zstd-6", ZIO_COMPRESS_ZSTD |
(ZIO_ZSTDLVL_6 << SPA_COMPRESSBITS) },
{ "zstd-7", ZIO_COMPRESS_ZSTD |
(ZIO_ZSTDLVL_7 << SPA_COMPRESSBITS) },
{ "zstd-8", ZIO_COMPRESS_ZSTD |
(ZIO_ZSTDLVL_8 << SPA_COMPRESSBITS) },
{ "zstd-9", ZIO_COMPRESS_ZSTD |
(ZIO_ZSTDLVL_9 << SPA_COMPRESSBITS) },
{ "zstd-10", ZIO_COMPRESS_ZSTD |
(ZIO_ZSTDLVL_10 << SPA_COMPRESSBITS) },
{ "zstd-11", ZIO_COMPRESS_ZSTD |
(ZIO_ZSTDLVL_11 << SPA_COMPRESSBITS) },
{ "zstd-12", ZIO_COMPRESS_ZSTD |
(ZIO_ZSTDLVL_12 << SPA_COMPRESSBITS) },
{ "zstd-13", ZIO_COMPRESS_ZSTD |
(ZIO_ZSTDLVL_13 << SPA_COMPRESSBITS) },
{ "zstd-14", ZIO_COMPRESS_ZSTD |
(ZIO_ZSTDLVL_14 << SPA_COMPRESSBITS) },
{ "zstd-15", ZIO_COMPRESS_ZSTD |
(ZIO_ZSTDLVL_15 << SPA_COMPRESSBITS) },
{ "zstd-16", ZIO_COMPRESS_ZSTD |
(ZIO_ZSTDLVL_16 << SPA_COMPRESSBITS) },
{ "zstd-17", ZIO_COMPRESS_ZSTD |
(ZIO_ZSTDLVL_17 << SPA_COMPRESSBITS) },
{ "zstd-18", ZIO_COMPRESS_ZSTD |
(ZIO_ZSTDLVL_18 << SPA_COMPRESSBITS) },
{ "zstd-19", ZIO_COMPRESS_ZSTD |
(ZIO_ZSTDLVL_19 << SPA_COMPRESSBITS) },
/*
* The ZSTD-Fast levels are also synthetic.
*/
{ "zstd-fast-1", ZIO_COMPRESS_ZSTD |
(ZIO_ZSTDLVL_FAST_1 << SPA_COMPRESSBITS) },
{ "zstd-fast-2", ZIO_COMPRESS_ZSTD |
(ZIO_ZSTDLVL_FAST_2 << SPA_COMPRESSBITS) },
{ "zstd-fast-3", ZIO_COMPRESS_ZSTD |
(ZIO_ZSTDLVL_FAST_3 << SPA_COMPRESSBITS) },
{ "zstd-fast-4", ZIO_COMPRESS_ZSTD |
(ZIO_ZSTDLVL_FAST_4 << SPA_COMPRESSBITS) },
{ "zstd-fast-5", ZIO_COMPRESS_ZSTD |
(ZIO_ZSTDLVL_FAST_5 << SPA_COMPRESSBITS) },
{ "zstd-fast-6", ZIO_COMPRESS_ZSTD |
(ZIO_ZSTDLVL_FAST_6 << SPA_COMPRESSBITS) },
{ "zstd-fast-7", ZIO_COMPRESS_ZSTD |
(ZIO_ZSTDLVL_FAST_7 << SPA_COMPRESSBITS) },
{ "zstd-fast-8", ZIO_COMPRESS_ZSTD |
(ZIO_ZSTDLVL_FAST_8 << SPA_COMPRESSBITS) },
{ "zstd-fast-9", ZIO_COMPRESS_ZSTD |
(ZIO_ZSTDLVL_FAST_9 << SPA_COMPRESSBITS) },
{ "zstd-fast-10", ZIO_COMPRESS_ZSTD |
(ZIO_ZSTDLVL_FAST_10 << SPA_COMPRESSBITS) },
{ "zstd-fast-20", ZIO_COMPRESS_ZSTD |
(ZIO_ZSTDLVL_FAST_20 << SPA_COMPRESSBITS) },
{ "zstd-fast-30", ZIO_COMPRESS_ZSTD |
(ZIO_ZSTDLVL_FAST_30 << SPA_COMPRESSBITS) },
{ "zstd-fast-40", ZIO_COMPRESS_ZSTD |
(ZIO_ZSTDLVL_FAST_40 << SPA_COMPRESSBITS) },
{ "zstd-fast-50", ZIO_COMPRESS_ZSTD |
(ZIO_ZSTDLVL_FAST_50 << SPA_COMPRESSBITS) },
{ "zstd-fast-60", ZIO_COMPRESS_ZSTD |
(ZIO_ZSTDLVL_FAST_60 << SPA_COMPRESSBITS) },
{ "zstd-fast-70", ZIO_COMPRESS_ZSTD |
(ZIO_ZSTDLVL_FAST_70 << SPA_COMPRESSBITS) },
{ "zstd-fast-80", ZIO_COMPRESS_ZSTD |
(ZIO_ZSTDLVL_FAST_80 << SPA_COMPRESSBITS) },
{ "zstd-fast-90", ZIO_COMPRESS_ZSTD |
(ZIO_ZSTDLVL_FAST_90 << SPA_COMPRESSBITS) },
{ "zstd-fast-100", ZIO_COMPRESS_ZSTD |
(ZIO_ZSTDLVL_FAST_100 << SPA_COMPRESSBITS) },
{ "zstd-fast-500", ZIO_COMPRESS_ZSTD |
(ZIO_ZSTDLVL_FAST_500 << SPA_COMPRESSBITS) },
{ "zstd-fast-1000", ZIO_COMPRESS_ZSTD |
(ZIO_ZSTDLVL_FAST_1000 << SPA_COMPRESSBITS) },
{ NULL }
};

@@ -307,8 +400,10 @@ zfs_prop_init(void)
zprop_register_index(ZFS_PROP_COMPRESSION, "compression",
ZIO_COMPRESS_DEFAULT, PROP_INHERIT,
ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME,
"on | off | lzjb | gzip | gzip-[1-9] | zle | lz4", "COMPRESS",
compress_table);
"on | off | lzjb | gzip | gzip-[1-9] | zle | lz4 | "
"zstd | zstd-[1-19] | "
"zstd-fast-[1-10,20,30,40,50,60,70,80,90,100,500,1000]",
"COMPRESS", compress_table);
zprop_register_index(ZFS_PROP_SNAPDIR, "snapdir", ZFS_SNAPDIR_HIDDEN,
PROP_INHERIT, ZFS_TYPE_FILESYSTEM,
"hidden | visible", "SNAPDIR", snapdir_table);
@@ -591,6 +591,13 @@ dmu_recv_begin_check(void *arg, dmu_tx_t *tx)
dsflags |= DS_HOLD_FLAG_DECRYPT;
}

if ((featureflags & DMU_BACKUP_FEATURE_ZSTD) &&
!spa_feature_is_enabled(dp->dp_spa, SPA_FEATURE_ZSTD_COMPRESS))
return (SET_ERROR(ENOTSUP));

if (!(DMU_STREAM_SUPPORTED(featureflags)))
return (SET_ERROR(ENOTSUP));

error = dsl_dataset_hold_flags(dp, tofs, dsflags, FTAG, &ds);
if (error == 0) {
/* target fs already exists; recv into temp clone */

0 comments on commit d1ad340

Please sign in to comment.
You can’t perform that action at this time.