Skip to content

Commit

Permalink
Add zstd support to zfs
Browse files Browse the repository at this point in the history
Signed-off-by: Allan Jude <[email protected]>
Signed-off-by: Sebastian Gottschall <[email protected]>
Signed-off-by: Kjeld Schouten-Lebbing <[email protected]>
Signed-off-by: Michael Niewöhner <[email protected]>
  • Loading branch information
c0d3z3r0 committed Dec 15, 2019
1 parent 8eb164c commit f4e47e1
Show file tree
Hide file tree
Showing 26 changed files with 1,030 additions and 15 deletions.
2 changes: 1 addition & 1 deletion cmd/dbufstat/dbufstat
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
1 change: 1 addition & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,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
Expand Down
1 change: 1 addition & 0 deletions contrib/zstd/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.o.cmd
10 changes: 9 additions & 1 deletion copy-builtin
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ scripts/make_gitrev.sh || true
rm -rf "$KERNEL_DIR/include/zfs" "$KERNEL_DIR/fs/zfs"
cp --recursive include "$KERNEL_DIR/include/zfs"
cp --recursive module "$KERNEL_DIR/fs/zfs"
mkdir "$KERNEL_DIR/fs/zfs/contrib"
cp --recursive contrib/zstd "$KERNEL_DIR/fs/zfs/contrib"
cp zfs_config.h "$KERNEL_DIR/include/zfs/"

for MODULE in "${MODULES[@]}"
Expand Down Expand Up @@ -72,10 +74,16 @@ EOF
ZFS_MODULE_CFLAGS += -I$(srctree)/include/zfs/os/linux/zfs
ZFS_MODULE_CFLAGS += -I$(srctree)/include/zfs/os/linux/kernel
ZFS_MODULE_CFLAGS += -include $(srctree)/include/zfs/zfs_config.h
ZFS_MODULE_CFLAGS += -I$(srctree)/fs/zfs/contrib/zstd
ZFS_MODULE_CFLAGS += -I$(srctree)/fs/zfs/contrib/zstd/common
ZFS_MODULE_CFLAGS += -I$(srctree)/fs/zfs/contrib/zstd/compress
ZFS_MODULE_CFLAGS += -I$(srctree)/fs/zfs/contrib/zstd/decompress
ZFS_MODULE_CFLAGS += -I$(srctree)/include/zfs/sys/zstd
ZFS_MODULE_CFLAGS += -std=gnu99 -Wno-declaration-after-statement
ZFS_MODULE_CPPFLAGS = -D_KERNEL
ZFS_MODULE_CPPFLAGS += -UDEBUG -DNDEBUG
export ZFS_MODULE_CFLAGS ZFS_MODULE_CPPFLAGS
ZSTD_PATH = ../contrib/zstd
export ZFS_MODULE_CFLAGS ZFS_MODULE_CPPFLAGS ZSTD_PATH
obj-$(CONFIG_ZFS) :=
EOF
Expand Down
4 changes: 2 additions & 2 deletions include/sys/zfs_ioctl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)

/*
Expand All @@ -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))
Expand Down
1 change: 1 addition & 0 deletions include/sys/zio.h
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,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)

Expand Down
56 changes: 56 additions & 0 deletions include/sys/zio_compress.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
6 changes: 3 additions & 3 deletions include/sys/zio_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions include/sys/zstd/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ COMMON_H = \
$(top_srcdir)/include/sys/zstd/stdio.h \
$(top_srcdir)/include/sys/zstd/stdlib.h \
$(top_srcdir)/include/sys/zstd/string.h \
$(top_srcdir)/include/sys/zstd/zstd.h \
$(top_srcdir)/include/sys/zstd/zstd_kfreebsd.c \
$(top_srcdir)/include/sys/zstd/zstd_kfreebsd.h \
$(top_srcdir)/include/sys/zstd/zstd_kmalloc.c
Expand Down
53 changes: 53 additions & 0 deletions include/sys/zstd/zstd.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/

/*
* Copyright (c) 2016-2018, Klara Systems Inc. All rights reserved.
* Copyright (c) 2016-2018, Allan Jude. All rights reserved.
* Copyright (c) 2018-2019, Sebastian Gottschall. All rights reserved.
* Copyright (c) 2019, Michael Niewöhner. All rights reserved.
*/

#ifndef _ZFS_ZSTD_H
#define _ZFS_ZSTD_H

#ifdef __cplusplus
extern "C" {
#endif

/* (de)init for user space / kernel emulation */
int zstd_init(void);
void zstd_fini(void);

size_t zstd_compress(void *s_start, void *d_start, size_t s_len, size_t d_len,
int n);
int zstd_get_level(void *s_start, size_t s_len, uint8_t *level);
int zstd_decompress_level(void *s_start, void *d_start, size_t s_len,
size_t d_len, uint8_t *level);
int zstd_decompress(void *s_start, void *d_start, size_t s_len, size_t d_len,
int n);

#ifdef __cplusplus
}
#endif

#endif /* _ZFS_ZSTD_H */
1 change: 1 addition & 0 deletions include/zfeature_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,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,
Expand Down
2 changes: 2 additions & 0 deletions module/Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -18,6 +19,7 @@ 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_CPPFLAGS += -D_KERNEL
ZFS_MODULE_CPPFLAGS += @KERNEL_DEBUG_CPPFLAGS@

Expand Down
9 changes: 9 additions & 0 deletions module/zcommon/zfeature_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,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)
Expand Down
99 changes: 97 additions & 2 deletions module/zcommon/zfs_prop.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,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 }
};

Expand Down Expand Up @@ -323,8 +416,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);
Expand Down
7 changes: 7 additions & 0 deletions module/zfs/dmu_recv.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
Loading

0 comments on commit f4e47e1

Please sign in to comment.