Page MenuHomeFreeBSD

D11124.id36221.diff
No OneTemporary

D11124.id36221.diff

Index: Makefile.inc1
===================================================================
--- Makefile.inc1
+++ Makefile.inc1
@@ -2381,7 +2381,7 @@
${_cddl_lib_libctf} \
lib/libutil lib/libpjdlog ${_lib_libypclnt} lib/libz lib/msun \
${_secure_lib_libcrypto} ${_lib_libldns} \
- ${_secure_lib_libssh} ${_secure_lib_libssl}
+ ${_secure_lib_libssh} ${_secure_lib_libssl} lib/libzstd
.if ${MK_GNUCXX} != "no"
_prebuild_libs+= gnu/lib/libstdc++ gnu/lib/libsupc++
Index: cddl/lib/libzfs/Makefile
===================================================================
--- cddl/lib/libzfs/Makefile
+++ cddl/lib/libzfs/Makefile
@@ -7,7 +7,7 @@
.PATH: ${SRCTOP}/cddl/contrib/opensolaris/lib/libcmdutils/common
LIB= zfs
-LIBADD= md pthread umem util uutil m avl bsdxml geom nvpair z zfs_core
+LIBADD= md pthread umem util uutil m avl bsdxml geom nvpair z zfs_core zstd
SRCS= deviceid.c \
fsshare.c \
mkdirp.c \
Index: cddl/lib/libzpool/Makefile
===================================================================
--- cddl/lib/libzpool/Makefile
+++ cddl/lib/libzpool/Makefile
@@ -62,8 +62,9 @@
CFLAGS+= -I${SRCTOP}/lib/libpthread/thread
CFLAGS+= -I${SRCTOP}/lib/libpthread/sys
CFLAGS+= -I${SRCTOP}/lib/libthr/arch/${MACHINE_CPUARCH}/include
+CFLAGS+= -I${SRCTOP}/sys/contrib/zstd/lib
-LIBADD= md pthread z nvpair avl umem
+LIBADD= md pthread z nvpair avl umem zstd
# atomic.S doesn't like profiling.
MK_PROFILE= no
Index: rescue/rescue/Makefile
===================================================================
--- rescue/rescue/Makefile
+++ rescue/rescue/Makefile
@@ -126,7 +126,7 @@
CRUNCH_LIBS+= -l80211 -lalias -lcam -lncursesw -ldevstat -lipsec -llzma
.if ${MK_ZFS} != "no"
-CRUNCH_LIBS+= -lavl -lzpool -lzfs_core -lzfs -lnvpair -lpthread -luutil -lumem
+CRUNCH_LIBS+= -lavl -lzpool -lzfs_core -lzfs -lnvpair -lpthread -luutil -lumem -lprivatezstd
.else
# liblzma needs pthread
CRUNCH_LIBS+= -lpthread
Index: share/mk/src.libnames.mk
===================================================================
--- share/mk/src.libnames.mk
+++ share/mk/src.libnames.mk
@@ -327,9 +327,9 @@
_DP_fifolog= z
_DP_ipf= kvm
_DP_zfs= md pthread umem util uutil m nvpair avl bsdxml geom nvpair z \
- zfs_core
+ zfs_core zstd
_DP_zfs_core= nvpair
-_DP_zpool= md pthread z nvpair avl umem
+_DP_zpool= md pthread z nvpair avl umem zstd
# OFED support
.if ${MK_OFED} != "no"
Index: stand/efi/boot1/Makefile
===================================================================
--- stand/efi/boot1/Makefile
+++ stand/efi/boot1/Makefile
@@ -33,6 +33,7 @@
SRCS+= zfs_module.c
CFLAGS+= -I${ZFSSRC}
CFLAGS+= -I${SYSDIR}/cddl/boot/zfs
+CFLAGS+= -I${SYSDIR}/contrib/zstd/lib
CFLAGS+= -DEFI_ZFS_BOOT
LIBZFSBOOT= ${BOOTOBJ}/zfs/libzfsboot.a
.endif
Index: stand/efi/boot1/boot1.c
===================================================================
--- stand/efi/boot1/boot1.c
+++ stand/efi/boot1/boot1.c
@@ -73,6 +73,18 @@
return (NULL);
}
+void *
+Calloc(size_t number, size_t len, const char *file __unused, int line __unused)
+{
+ uintptr_t bytes = (uintptr_t)number * (uintptr_t)len;
+ void *out;
+
+ if ((out = Malloc(bytes, file, line)) != NULL)
+ bzero(out, bytes);
+
+ return(out);
+}
+
void
Free(void *buf, const char *file __unused, int line __unused)
{
Index: stand/i386/gptzfsboot/Makefile
===================================================================
--- stand/i386/gptzfsboot/Makefile
+++ stand/i386/gptzfsboot/Makefile
@@ -31,6 +31,7 @@
-I${BOOTSRC}/i386/common \
-I${ZFSSRC} \
-I${SYSDIR}/cddl/boot/zfs \
+ -I${SYSDIR}/contrib/zstd/lib \
-I${BOOTSRC}/i386/btx/lib \
-I${BOOTSRC}/i386/boot2 \
-Wall -Waggregate-return -Wbad-function-cast \
Index: stand/i386/zfsboot/Makefile
===================================================================
--- stand/i386/zfsboot/Makefile
+++ stand/i386/zfsboot/Makefile
@@ -30,6 +30,7 @@
-I${BOOTSRC}/i386 \
-I${ZFSSRC} \
-I${SYSDIR}/cddl/boot/zfs \
+ -I${SYSDIR}/contrib/zstd/lib \
-I${BTXLIB} \
-I${BOOTSRC}/i386/boot2 \
-Wall -Waggregate-return -Wbad-function-cast -Wno-cast-align \
Index: stand/libsa/Makefile
===================================================================
--- stand/libsa/Makefile
+++ stand/libsa/Makefile
@@ -81,6 +81,31 @@
.PATH: ${SASRC}/${LIBSA_CPUARCH}
SRCS+= _setjmp.S
+# decompression functionality from libzstd
+.PATH: ${SRCTOP}/sys/contrib/zstd/lib
+CFLAGS+= -I${SRCTOP}/sys/contrib/zstd/lib
+.PATH: ${SRCTOP}/sys/contrib/zstd/lib/common
+CFLAGS+= -I${SRCTOP}/sys/contrib/zstd/lib/common
+.PATH: ${SRCTOP}/sys/contrib/zstd/lib/compress
+CFLAGS+= -I${SRCTOP}/sys/contrib/zstd/lib/compress
+.PATH: ${SRCTOP}/sys/contrib/zstd/lib/decompress
+CFLAGS+= -I${SRCTOP}/sys/contrib/zstd/lib/decompress
+.for file in zstd_common.c fse_decompress.c entropy_common.c error_private.c \
+ xxhash.c zstd_compress.c fse_compress.c huf_compress.c \
+ zstd_double_fast.c zstd_fast.c zstd_lazy.c zstd_ldm.c zstd_opt.c \
+ zstd_decompress.c huf_decompress.c
+SRCS+= _${file}
+CLEANFILES+= _${file}
+
+_${file}: ${file}
+ sed -e 's|<stddef.h>|"stand.h"|' \
+ -e 's|<string.h>|"stand.h"|' \
+ -e 's|<stdio.h>|"stand.h"|' \
+ -e 's|<stdlib.h>|"stand.h"|' \
+ -e 's|<stdint.h>|"stand.h"|' \
+ ${.ALLSRC} > ${.TARGET}
+.endfor
+
# decompression functionality from libbz2
# NOTE: to actually test this functionality after libbz2 upgrade compile
# loader(8) with LOADER_BZIP2_SUPPORT defined
Index: stand/zfs/Makefile
===================================================================
--- stand/zfs/Makefile
+++ stand/zfs/Makefile
@@ -14,6 +14,7 @@
CFLAGS+= -DBOOTPROG=\"zfsloader\"
CFLAGS+= -I${LDRSRC}
CFLAGS+= -I${SYSDIR}/cddl/boot/zfs
+CFLAGS+= -I${SYSDIR}/contrib/zstd/lib
CFLAGS+= -I${SYSDIR}/crypto/skein
CFLAGS+= -Wformat -Wall
Index: sys/cddl/boot/zfs/zfsimpl.h
===================================================================
--- sys/cddl/boot/zfs/zfsimpl.h
+++ sys/cddl/boot/zfs/zfsimpl.h
@@ -561,6 +561,7 @@
ZIO_COMPRESS_GZIP_9,
ZIO_COMPRESS_ZLE,
ZIO_COMPRESS_LZ4,
+ ZIO_COMPRESS_ZSTD,
ZIO_COMPRESS_FUNCTIONS
};
Index: sys/cddl/boot/zfs/zfssubr.c
===================================================================
--- sys/cddl/boot/zfs/zfssubr.c
+++ sys/cddl/boot/zfs/zfssubr.c
@@ -162,6 +162,7 @@
#include "lzjb.c"
#include "zle.c"
#include "lz4.c"
+#include "zstd.c"
/*
* Compression vectors.
@@ -183,6 +184,7 @@
{NULL, NULL, 9, "gzip-9"},
{NULL, zle_decompress, 64, "zle"},
{NULL, lz4_decompress, 0, "lz4"},
+ {NULL, zstd_decompress, 0, "zstd"},
};
static void
Index: sys/cddl/boot/zfs/zstd.c
===================================================================
--- /dev/null
+++ sys/cddl/boot/zfs/zstd.c
@@ -0,0 +1,83 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (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-2017 by ScaleEngine Inc. All rights reserved.
+ * Copyright (c) 2017 Allan Jude <allanjude@freebsd.org>. All rights reserved.
+ */
+
+#include <netinet/in.h>
+
+#define ZSTD_STATIC_LINKING_ONLY
+#include <zstd.h>
+
+/* Allocate just one decompression context and reuse it */
+static char *dctxbuf = NULL;
+static size_t dctxsize;
+
+static int
+zstd_decompress(void *s_start, void *d_start, size_t s_len, size_t d_len, int n)
+{
+ const char *src = s_start;
+ uint32_t bufsiz = htonl(*(uint32_t *)src);
+ size_t result;
+
+ ASSERT(d_len >= s_len);
+
+ /* invalid compressed buffer size encoded at start */
+ if (bufsiz + sizeof (bufsiz) > s_len) {
+ printf("ZFS: Failed to decode decompression header\n");
+ return (1);
+ }
+
+ /*
+ * Returns 0 on success (decompression function returned non-negative)
+ * and non-zero on failure (decompression function returned negative.
+ */
+ ZSTD_DCtx *dctx;
+
+ if (dctxbuf == NULL) {
+ dctxsize = ZSTD_estimateDCtxSize();
+ dctxbuf = malloc(dctxsize + 8);
+ if (dctxbuf == NULL) {
+ printf("ZFS: memory allocation failure\n");
+ return (-1);
+ }
+ /* Pointer must be 8 byte aligned */
+ dctxbuf = (char *)roundup2((uintptr_t)dctxbuf, 8);
+ }
+
+ dctx = ZSTD_initStaticDCtx(dctxbuf, dctxsize);
+ if (dctx == NULL) {
+ printf("ZFS: failed to initialize decompression context\n");
+ return (-1);
+ }
+
+ result = ZSTD_decompressDCtx(dctx, d_start, d_len,
+ &src[sizeof (bufsiz)], bufsiz);
+ if (ZSTD_isError(result)) {
+ printf("ZFS: Failed to decompress block: %s\n",
+ ZSTD_getErrorName(result));
+ return (-1);
+ }
+
+ return (0);
+}
Index: sys/cddl/contrib/opensolaris/common/zfs/zfeature_common.h
===================================================================
--- sys/cddl/contrib/opensolaris/common/zfs/zfeature_common.h
+++ sys/cddl/contrib/opensolaris/common/zfs/zfeature_common.h
@@ -57,6 +57,7 @@
#ifdef illumos
SPA_FEATURE_EDONR,
#endif
+ SPA_FEATURE_ZSTD_COMPRESS,
SPA_FEATURES
} spa_feature_t;
Index: sys/cddl/contrib/opensolaris/common/zfs/zfeature_common.c
===================================================================
--- sys/cddl/contrib/opensolaris/common/zfs/zfeature_common.c
+++ sys/cddl/contrib/opensolaris/common/zfs/zfeature_common.c
@@ -247,4 +247,10 @@
"Edon-R hash algorithm.",
ZFEATURE_FLAG_PER_DATASET, NULL);
#endif
+
+ zfeature_register(SPA_FEATURE_ZSTD_COMPRESS,
+ "org.freebsd:zstd_compress", "zstd_compress",
+ "zstd compression algorithm support.",
+ ZFEATURE_FLAG_PER_DATASET, NULL);
+
}
Index: sys/cddl/contrib/opensolaris/common/zfs/zfs_prop.c
===================================================================
--- sys/cddl/contrib/opensolaris/common/zfs/zfs_prop.c
+++ sys/cddl/contrib/opensolaris/common/zfs/zfs_prop.c
@@ -116,6 +116,52 @@
{ "gzip-9", ZIO_COMPRESS_GZIP_9 },
{ "zle", ZIO_COMPRESS_ZLE },
{ "lz4", ZIO_COMPRESS_LZ4 },
+ { "zstd", ZIO_COMPRESS_ZSTD },
+ /*
+ * 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) },
{ NULL }
};
@@ -250,7 +296,8 @@
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",
+ "on | off | lzjb | gzip | gzip-[1-9] | zle | lz4"
+ " | zstd | zstd-[1-19]",
"COMPRESS", compress_table);
zprop_register_index(ZFS_PROP_SNAPDIR, "snapdir", ZFS_SNAPDIR_HIDDEN,
PROP_INHERIT, ZFS_TYPE_FILESYSTEM,
@@ -460,6 +507,9 @@
PROP_READONLY, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, "PREVSNAP");
/* oddball properties */
+ zprop_register_impl(ZFS_PROP_ZSTD_LEVEL, "zstd_compress_level",
+ PROP_TYPE_NUMBER, ZIO_ZSTDLVL_DEFAULT, NULL, PROP_INHERIT,
+ ZFS_TYPE_DATASET, "[1-19]", "ZSTDLEVEL", B_TRUE, B_TRUE, NULL);
zprop_register_impl(ZFS_PROP_CREATION, "creation", PROP_TYPE_NUMBER, 0,
NULL, PROP_READONLY, ZFS_TYPE_DATASET | ZFS_TYPE_BOOKMARK,
"<date>", "CREATION", B_FALSE, B_TRUE, NULL);
Index: sys/cddl/contrib/opensolaris/uts/common/Makefile.files
===================================================================
--- sys/cddl/contrib/opensolaris/uts/common/Makefile.files
+++ sys/cddl/contrib/opensolaris/uts/common/Makefile.files
@@ -144,7 +144,8 @@
zio_compress.o \
zio_inject.o \
zle.o \
- zrlock.o
+ zrlock.o \
+ zstd.o
ZFS_SHARED_OBJS += \
zfeature_common.o \
Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c
===================================================================
--- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c
+++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c
@@ -1858,7 +1858,8 @@
uint64_t csize;
void *cbuf = zio_buf_alloc(HDR_GET_PSIZE(hdr));
- csize = zio_compress_data(compress, zio->io_abd, cbuf, lsize);
+ csize = zio_compress_data(compress, zio->io_abd, cbuf, lsize,
+ &zio->io_prop);
ASSERT3U(csize, <=, HDR_GET_PSIZE(hdr));
if (csize < HDR_GET_PSIZE(hdr)) {
Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c
===================================================================
--- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c
+++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c
@@ -2012,6 +2012,7 @@
(wp & WP_SPILL));
enum zio_checksum checksum = os->os_checksum;
enum zio_compress compress = os->os_compress;
+ enum zio_zstd_levels zstd_level = os->os_zstd_level;
enum zio_checksum dedup_checksum = os->os_dedup_checksum;
boolean_t dedup = B_FALSE;
boolean_t nopwrite = B_FALSE;
@@ -2106,6 +2107,8 @@
zp->zp_checksum = checksum;
zp->zp_compress = compress;
ASSERT3U(zp->zp_compress, !=, ZIO_COMPRESS_INHERIT);
+ zp->zp_zstd_level = zstd_level;
+ ASSERT3U(zp->zp_zstd_level, !=, ZIO_ZSTDLVL_INHERIT);
zp->zp_type = (wp & WP_SPILL) ? dn->dn_bonustype : type;
zp->zp_level = level;
Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_objset.c
===================================================================
--- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_objset.c
+++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_objset.c
@@ -178,6 +178,20 @@
}
static void
+zstd_level_changed_cb(void *arg, uint64_t newval)
+{
+ objset_t *os = arg;
+
+ /*
+ * Inheritance and range checking should have been done by now.
+ */
+ ASSERT(newval != ZIO_ZSTDLVL_INHERIT);
+
+ os->os_zstd_level = zio_zstd_level_select(os->os_spa, newval,
+ ZIO_ZSTDLVL_DEFAULT);
+}
+
+static void
copies_changed_cb(void *arg, uint64_t newval)
{
objset_t *os = arg;
@@ -435,6 +449,11 @@
}
if (err == 0) {
err = dsl_prop_register(ds,
+ zfs_prop_to_name(ZFS_PROP_ZSTD_LEVEL),
+ zstd_level_changed_cb, os);
+ }
+ if (err == 0) {
+ err = dsl_prop_register(ds,
zfs_prop_to_name(ZFS_PROP_COPIES),
copies_changed_cb, os);
}
@@ -476,6 +495,7 @@
/* It's the meta-objset. */
os->os_checksum = ZIO_CHECKSUM_FLETCHER_4;
os->os_compress = ZIO_COMPRESS_ON;
+ os->os_zstd_level = ZIO_ZSTDLVL_DEFAULT;
os->os_copies = spa_max_replication(spa);
os->os_dedup_checksum = ZIO_CHECKSUM_OFF;
os->os_dedup_verify = B_FALSE;
Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_misc.c
===================================================================
--- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_misc.c
+++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_misc.c
@@ -2019,6 +2019,7 @@
metaslab_alloc_trace_init();
zio_init();
lz4_init();
+ zstd_init();
dmu_init();
zil_init();
vdev_cache_stat_init();
@@ -2047,6 +2048,7 @@
zil_fini();
dmu_fini();
lz4_fini();
+ zstd_fini();
zio_fini();
metaslab_alloc_trace_fini();
range_tree_fini();
Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu_objset.h
===================================================================
--- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu_objset.h
+++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu_objset.h
@@ -91,6 +91,7 @@
/* can change, under dsl_dir's locks: */
enum zio_checksum os_checksum;
enum zio_compress os_compress;
+ enum zio_zstd_levels os_zstd_level;
uint8_t os_copies;
enum zio_checksum os_dedup_checksum;
boolean_t os_dedup_verify;
Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa.h
===================================================================
--- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa.h
+++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa.h
@@ -152,6 +152,7 @@
#define SPA_ASIZEBITS 24 /* ASIZE up to 64 times larger */
#define SPA_COMPRESSBITS 7
+#define SPA_COMPRESSMASK ((1U<<SPA_COMPRESSBITS)-1)
/*
* All SPA data is represented by 128-bit data virtual addresses (DVAs).
Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio.h
===================================================================
--- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio.h
+++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio.h
@@ -124,6 +124,7 @@
#define BOOTFS_COMPRESS_VALID(compress) \
((compress) == ZIO_COMPRESS_LZJB || \
(compress) == ZIO_COMPRESS_LZ4 || \
+ (compress) == ZIO_COMPRESS_ZSTD || \
(compress) == ZIO_COMPRESS_ON || \
(compress) == ZIO_COMPRESS_OFF)
@@ -284,6 +285,7 @@
typedef struct zio_prop {
enum zio_checksum zp_checksum;
enum zio_compress zp_compress;
+ enum zio_zstd_levels zp_zstd_level;
dmu_object_type_t zp_type;
uint8_t zp_level;
uint8_t zp_copies;
@@ -592,6 +594,8 @@
enum zio_checksum child, enum zio_checksum parent);
extern enum zio_compress zio_compress_select(spa_t *spa,
enum zio_compress child, enum zio_compress parent);
+extern enum zio_zstd_levels zio_zstd_level_select(spa_t *spa,
+ enum zio_zstd_levels child, enum zio_zstd_levels parent);
extern void zio_cancel(zio_t *zio);
extern void zio_suspend(spa_t *spa, zio_t *zio);
Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio_compress.h
===================================================================
--- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio_compress.h
+++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio_compress.h
@@ -54,9 +54,43 @@
ZIO_COMPRESS_GZIP_9,
ZIO_COMPRESS_ZLE,
ZIO_COMPRESS_LZ4,
+ ZIO_COMPRESS_ZSTD,
ZIO_COMPRESS_FUNCTIONS
};
+#define ZIO_ZSTD_LEVEL_MIN 1
+#define ZIO_ZSTD_LEVEL_DEFAULT 3
+#define ZIO_ZSTD_LEVEL_MAX 19
+
+enum zio_zstd_levels {
+ ZIO_ZSTDLVL_INHERIT = 0,
+ ZIO_ZSTDLVL_1,
+ ZIO_ZSTDLVL_2,
+ 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,
+ ZIO_ZSTDLVL_DEFAULT = 30, /* Allow the default level to change */
+ ZIO_ZSTDLVL_AUTO = 31, /* Reserved for future use */
+ ZIO_ZSTDLVL_LEVELS
+};
+
+/* Forward Declaration to avoid visibility problems */
+struct zio_prop;
+
/* Common signature for all zio compress functions. */
typedef size_t zio_compress_func_t(void *src, void *dst,
size_t s_len, size_t d_len, int);
@@ -104,12 +138,18 @@
int level);
extern int lz4_decompress(void *src, void *dst, size_t s_len, size_t d_len,
int level);
+extern void zstd_init(void);
+extern void zstd_fini(void);
+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);
/*
* Compress and decompress data if necessary.
*/
extern size_t zio_compress_data(enum zio_compress c, abd_t *src, void *dst,
- size_t s_len);
+ size_t s_len, struct zio_prop *zp);
extern int zio_decompress_data(enum zio_compress c, abd_t *src, void *dst,
size_t s_len, size_t d_len);
extern int zio_decompress_data_buf(enum zio_compress c, void *src, void *dst,
Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio_impl.h
===================================================================
--- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio_impl.h
+++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio_impl.h
@@ -76,9 +76,9 @@
* 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
Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
===================================================================
--- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
+++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
@@ -2160,6 +2160,34 @@
}
static int
+get_prop_uint64(nvlist_t *nv, const char *prop, nvlist_t **nvp,
+ uint64_t *val)
+{
+ int err = 0;
+ nvlist_t *subnv;
+ nvpair_t *pair;
+ nvpair_t *propval;
+
+ if (nvlist_lookup_nvpair(nv, prop, &pair) != 0)
+ return (EINVAL);
+
+ /* decode the property value */
+ propval = pair;
+ if (nvpair_type(pair) == DATA_TYPE_NVLIST) {
+ subnv = fnvpair_value_nvlist(pair);
+ if (nvp != NULL)
+ *nvp = subnv;
+ if (nvlist_lookup_nvpair(subnv, ZPROP_VALUE, &propval) != 0)
+ err = EINVAL;
+ }
+ if (nvpair_type(propval) == DATA_TYPE_UINT64) {
+ *val = fnvpair_value_uint64(propval);
+ }
+
+ return (err);
+}
+
+static int
zfs_ioc_objset_stats_impl(zfs_cmd_t *zc, objset_t *os)
{
int error = 0;
@@ -2184,6 +2212,28 @@
return (error);
VERIFY0(error);
}
+ /*
+ * ZSTD stores the compression level in a separate hidden
+ * property to avoid using up a large chunk of space in the
+ * on-disk compression algorithm enum. We need to swap things
+ * back around when the property is read.
+ */
+ nvlist_t *cnv;
+ uint64_t compval, levelval;
+
+ if (get_prop_uint64(nv, "compression", &cnv, &compval) != 0)
+ error = EINVAL;
+
+ if (error == 0 && compval == ZIO_COMPRESS_ZSTD &&
+ get_prop_uint64(nv, "zstd_compress_level", NULL,
+ &levelval) == 0) {
+ if (levelval == ZIO_ZSTDLVL_DEFAULT)
+ levelval = 0;
+ fnvlist_remove(cnv, ZPROP_VALUE);
+ fnvlist_add_uint64(cnv, ZPROP_VALUE,
+ compval | (levelval << SPA_COMPRESSBITS));
+ }
+
error = put_nvlist(zc, nv);
nvlist_free(nv);
}
@@ -2583,6 +2633,32 @@
}
break;
}
+ case ZFS_PROP_COMPRESSION:
+ /* Special handling is only required for ZSTD */
+ if (intval & SPA_COMPRESSMASK != ZIO_COMPRESS_ZSTD) {
+ err = -1;
+ break;
+ }
+ /*
+ * Store the ZSTD compression level separate from the compress
+ * property in its own hidden property.
+ */
+ uint64_t levelval;
+
+ if (intval == ZIO_COMPRESS_ZSTD) {
+ levelval = ZIO_ZSTDLVL_DEFAULT;
+ } else {
+ levelval = (intval & ~SPA_COMPRESSMASK)
+ >> SPA_COMPRESSBITS;
+ }
+ err = dsl_prop_set_int(dsname, "zstd_compress_level", source,
+ levelval);
+ if (err == 0) {
+ /* Store the compression algorithm normally */
+ err = dsl_prop_set_int(dsname, propname, source,
+ intval & SPA_COMPRESSMASK);
+ }
+ break;
default:
err = -1;
}
@@ -4036,6 +4112,20 @@
if (!spa_feature_is_enabled(spa,
SPA_FEATURE_LZ4_COMPRESS)) {
+ spa_close(spa, FTAG);
+ return (SET_ERROR(ENOTSUP));
+ }
+ spa_close(spa, FTAG);
+ }
+
+ if (intval == ZIO_COMPRESS_ZSTD) {
+ spa_t *spa;
+
+ if ((err = spa_open(dsname, &spa, FTAG)) != 0)
+ return (err);
+
+ if (!spa_feature_is_enabled(spa,
+ SPA_FEATURE_ZSTD_COMPRESS)) {
spa_close(spa, FTAG);
return (SET_ERROR(ENOTSUP));
}
Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c
===================================================================
--- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c
+++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c
@@ -1377,7 +1377,8 @@
/* If it's a compressed write that is not raw, compress the buffer. */
if (compress != ZIO_COMPRESS_OFF && psize == lsize) {
void *cbuf = zio_buf_alloc(lsize);
- psize = zio_compress_data(compress, zio->io_abd, cbuf, lsize);
+ psize = zio_compress_data(compress, zio->io_abd, cbuf, lsize,
+ zp);
if (psize == 0 || psize == lsize) {
compress = ZIO_COMPRESS_OFF;
zio_buf_free(cbuf, lsize);
@@ -2337,6 +2338,7 @@
zp.zp_checksum = gio->io_prop.zp_checksum;
zp.zp_compress = ZIO_COMPRESS_OFF;
+ zp.zp_zstd_level = ZIO_ZSTDLVL_DEFAULT;
zp.zp_type = DMU_OT_NONE;
zp.zp_level = 0;
zp.zp_copies = gio->io_prop.zp_copies;
Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio_compress.c
===================================================================
--- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio_compress.c
+++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio_compress.c
@@ -74,9 +74,27 @@
{"gzip-8", 8, gzip_compress, gzip_decompress},
{"gzip-9", 9, gzip_compress, gzip_decompress},
{"zle", 64, zle_compress, zle_decompress},
- {"lz4", 0, lz4_compress, lz4_decompress}
+ {"lz4", 0, lz4_compress, lz4_decompress},
+ {"zstd", 0, zstd_compress, zstd_decompress},
};
+enum zio_zstd_levels
+zio_zstd_level_select(spa_t *spa, enum zio_zstd_levels child,
+ enum zio_zstd_levels parent)
+{
+ enum zio_zstd_levels result;
+
+ ASSERT(child < ZIO_ZSTDLVL_LEVELS);
+ ASSERT(parent < ZIO_ZSTDLVL_LEVELS);
+ ASSERT(parent != ZIO_ZSTDLVL_INHERIT);
+
+ result = child;
+ if (result == ZIO_ZSTDLVL_INHERIT)
+ result = parent;
+
+ return (result);
+}
+
enum zio_compress
zio_compress_select(spa_t *spa, enum zio_compress child,
enum zio_compress parent)
@@ -114,9 +132,11 @@
}
size_t
-zio_compress_data(enum zio_compress c, abd_t *src, void *dst, size_t s_len)
+zio_compress_data(enum zio_compress c, abd_t *src, void *dst, size_t s_len,
+ zio_prop_t *zp)
{
size_t c_len, d_len;
+ int level;
zio_compress_info_t *ci = &zio_compress_table[c];
ASSERT((uint_t)c < ZIO_COMPRESS_FUNCTIONS);
@@ -139,9 +159,18 @@
/* Compress at least 12.5% */
d_len = s_len - (s_len >> 3);
+ level = ci->ci_level;
+
+ if (c == ZIO_COMPRESS_ZSTD) {
+ if (zp->zp_zstd_level == ZIO_ZSTDLVL_DEFAULT)
+ level = ZIO_ZSTD_LEVEL_DEFAULT;
+ else
+ level = zp->zp_zstd_level;
+ }
+
/* No compression algorithms can read from ABDs directly */
void *tmp = abd_borrow_buf_copy(src, s_len);
- c_len = ci->ci_compress(tmp, dst, s_len, d_len, ci->ci_level);
+ c_len = ci->ci_compress(tmp, dst, s_len, d_len, level);
abd_return_buf(src, tmp, s_len);
if (c_len > d_len) {
Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zstd.c
===================================================================
--- /dev/null
+++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zstd.c
@@ -0,0 +1,331 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (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-2017 by ScaleEngine Inc. All rights reserved.
+ * Copyright (c) 2017 Allan Jude <allanjude@freebsd.org>. All rights reserved.
+ */
+
+#include <sys/param.h>
+#include <sys/zfs_context.h>
+#include <sys/zio_compress.h>
+#include <sys/spa.h>
+#include <sys/malloc.h>
+
+#define ZSTD_STATIC_LINKING_ONLY
+#include <zstd.h>
+
+#define ZSTD_KMEM_MAGIC 0x20160831
+
+/*
+ * XXX: TODO: Investigate using ZSTD_compressBlock for small blocks
+ */
+
+static size_t real_zstd_compress(const char *source, char *dest, int isize,
+ int osize, int level);
+static size_t real_zstd_decompress(const char *source, char *dest, int isize,
+ int maxosize);
+
+void *zstd_alloc(void *opaque, size_t size);
+void zstd_free(void *opaque, void *ptr);
+
+static const ZSTD_customMem zstd_malloc = {
+ zstd_alloc,
+ zstd_free,
+ NULL,
+};
+
+enum zstd_kmem_type {
+ ZSTD_KMEM_UNKNOWN = 0,
+ ZSTD_KMEM_CCTX,
+ ZSTD_KMEM_WRKSPC_4K_MIN,
+ ZSTD_KMEM_WRKSPC_4K_DEF,
+ ZSTD_KMEM_WRKSPC_4K_MAX,
+ ZSTD_KMEM_WRKSPC_16K_MIN,
+ ZSTD_KMEM_WRKSPC_16K_DEF,
+ ZSTD_KMEM_WRKSPC_16K_MAX,
+ ZSTD_KMEM_WRKSPC_128K_MIN,
+ ZSTD_KMEM_WRKSPC_128K_DEF,
+ ZSTD_KMEM_WRKSPC_128K_MAX,
+ /* zfs_max_recordsize */
+ ZSTD_KMEM_WRKSPC_MRS_MIN,
+ ZSTD_KMEM_WRKSPC_MRS_DEF,
+ ZSTD_KMEM_WRKSPC_MRS_MAX,
+ /* SPA_MAXBLOCKSIZE */
+ ZSTD_KMEM_WRKSPC_MBS_MIN,
+ ZSTD_KMEM_WRKSPC_MBS_DEF,
+ ZSTD_KMEM_WRKSPC_MBS_MAX,
+ ZSTD_KMEM_DCTX,
+ ZSTD_KMEM_COUNT,
+};
+
+struct zstd_kmem {
+ uint_t kmem_magic;
+ enum zstd_kmem_type kmem_type;
+ size_t kmem_size;
+};
+
+struct zstd_kmem_config {
+ size_t block_size;
+ int compress_level;
+ char* cache_name;
+};
+
+static kmem_cache_t *zstd_kmem_cache[ZSTD_KMEM_COUNT] = { NULL };
+static struct zstd_kmem zstd_cache_size[ZSTD_KMEM_COUNT] = {
+ { ZSTD_KMEM_MAGIC, 0, 0 } };
+static struct zstd_kmem_config zstd_cache_config[ZSTD_KMEM_COUNT] = {
+ { 0, 0, "zstd_unknown" },
+ { 0, 0, "zstd_cctx" },
+ { 4096, ZIO_ZSTD_LEVEL_MIN, "zstd_wrkspc_4k_min" },
+ { 4096, ZIO_ZSTD_LEVEL_DEFAULT, "zstd_wrkspc_4k_def" },
+ { 4096, ZIO_ZSTD_LEVEL_MAX, "zstd_wrkspc_4k_max" },
+ { 16384, ZIO_ZSTD_LEVEL_MIN, "zstd_wrkspc_16k_min" },
+ { 16384, ZIO_ZSTD_LEVEL_DEFAULT, "zstd_wrkspc_16k_def" },
+ { 16384, ZIO_ZSTD_LEVEL_MAX, "zstd_wrkspc_16k_max" },
+ { SPA_OLD_MAXBLOCKSIZE, ZIO_ZSTD_LEVEL_MIN, "zstd_wrkspc_128k_min" },
+ { SPA_OLD_MAXBLOCKSIZE, ZIO_ZSTD_LEVEL_DEFAULT,
+ "zstd_wrkspc_128k_def" },
+ { SPA_OLD_MAXBLOCKSIZE, ZIO_ZSTD_LEVEL_MAX, "zstd_wrkspc_128k_max" },
+ { SPA_MAXBLOCKSIZE, ZIO_ZSTD_LEVEL_MIN, "zstd_wrkspc_mbs_min" },
+ { SPA_MAXBLOCKSIZE, ZIO_ZSTD_LEVEL_DEFAULT, "zstd_wrkspc_mbs_def" },
+ { SPA_MAXBLOCKSIZE, ZIO_ZSTD_LEVEL_MAX, "zstd_wrkspc_mbs_max" },
+ { 0, 0, "zstd_dctx" },
+ };
+
+static int
+zstd_compare(const void *a, const void *b)
+{
+ struct zstd_kmem *x, *y;
+
+ x = (struct zstd_kmem*)a;
+ y = (struct zstd_kmem*)b;
+
+ ASSERT(x->kmem_magic == ZSTD_KMEM_MAGIC);
+ ASSERT(y->kmem_magic == ZSTD_KMEM_MAGIC);
+
+ if (x->kmem_size > y->kmem_size) {
+ return (1);
+ } else if (x->kmem_size == y->kmem_size) {
+ return (0);
+ } else {
+ return (-1);
+ }
+}
+
+size_t
+zstd_compress(void *s_start, void *d_start, size_t s_len, size_t d_len, int n)
+{
+ uint32_t bufsiz;
+ char *dest = d_start;
+
+ ASSERT(d_len >= sizeof (bufsiz));
+ ASSERT(d_len <= s_len);
+
+ /* XXX: this could overflow, but we never have blocks that big */
+ bufsiz = real_zstd_compress(s_start, &dest[sizeof (bufsiz)], s_len,
+ d_len - sizeof (bufsiz), n);
+
+ /* Signal an error if the compression routine returned an error. */
+ if (ZSTD_isError(bufsiz))
+ return (s_len);
+
+ /*
+ * Encode the compresed buffer size at the start. We'll need this in
+ * decompression to counter the effects of padding which might be
+ * added to the compressed buffer and which, if unhandled, would
+ * confuse the hell out of our decompression function.
+ */
+ *(uint32_t *)dest = BE_32(bufsiz);
+
+ return (bufsiz + sizeof (bufsiz));
+}
+
+int
+zstd_decompress(void *s_start, void *d_start, size_t s_len, size_t d_len, int n)
+{
+ const char *src = s_start;
+ uint32_t bufsiz = BE_IN32(src);
+
+ ASSERT(d_len >= s_len);
+
+ /* invalid compressed buffer size encoded at start */
+ if (bufsiz + sizeof (bufsiz) > s_len)
+ return (1);
+
+ /*
+ * Returns 0 on success (decompression function returned non-negative)
+ * and non-zero on failure (decompression function returned negative.
+ */
+ if (ZSTD_isError(real_zstd_decompress(&src[sizeof (bufsiz)], d_start,
+ bufsiz, d_len)))
+ return (-1);
+
+ return (0);
+}
+
+static size_t
+real_zstd_compress(const char *source, char *dest, int isize, int osize,
+ int level)
+{
+ size_t result;
+ ZSTD_CCtx *cctx;
+
+ if (level == 0 || level == ZIO_ZSTDLVL_DEFAULT)
+ level = ZIO_ZSTD_LEVEL_DEFAULT;
+
+ /* XXX: In ZSTD 1.3+ consider using ZSTD_initStaticCCtx() instead */
+ cctx = ZSTD_createCCtx_advanced(zstd_malloc);
+ /*
+ * out of kernel memory, gently fall through - this will disable
+ * compression in zio_compress_data
+ */
+ if (cctx == NULL)
+ return (-1);
+
+ result = ZSTD_compressCCtx(cctx, dest, osize, source, isize, level);
+
+ ZSTD_freeCCtx(cctx);
+ return (result);
+}
+
+
+static size_t
+real_zstd_decompress(const char *source, char *dest, int isize, int maxosize)
+{
+ size_t result;
+ ZSTD_DCtx *dctx;
+
+ dctx = ZSTD_createDCtx_advanced(zstd_malloc);
+ if (dctx == NULL)
+ return (-1);
+
+ result = ZSTD_decompressDCtx(dctx, dest, maxosize, source, isize);
+
+ ZSTD_freeDCtx(dctx);
+ return (result);
+}
+
+extern void *
+zstd_alloc(void *opaque __unused, size_t size)
+{
+ size_t nbytes = sizeof(struct zstd_kmem) + size;
+ struct zstd_kmem *z;
+ enum zstd_kmem_type type;
+ int i;
+
+ type = ZSTD_KMEM_UNKNOWN;
+ for (i = 0; i < ZSTD_KMEM_COUNT; i++) {
+ if (nbytes <= zstd_cache_size[i].kmem_size) {
+ type = zstd_cache_size[i].kmem_type;
+ z = kmem_cache_alloc(zstd_kmem_cache[type],
+ KM_NOSLEEP | M_ZERO);
+ break;
+ }
+ }
+ /* No matching cache */
+ if (type == ZSTD_KMEM_UNKNOWN) {
+ z = kmem_alloc(nbytes, KM_NOSLEEP | M_ZERO);
+ }
+ if (z == NULL) {
+ return (NULL);
+ }
+
+ z->kmem_magic = ZSTD_KMEM_MAGIC;
+ z->kmem_type = type;
+ z->kmem_size = nbytes;
+
+ return ((void*)z + (sizeof(struct zstd_kmem)));
+}
+
+extern void
+zstd_free(void *opaque __unused, void *ptr)
+{
+ struct zstd_kmem *z = ptr - sizeof(struct zstd_kmem);
+
+ ASSERT(z->kmem_magic == ZSTD_KMEM_MAGIC);
+ ASSERT(z->kmem_type < ZSTD_KMEM_COUNT);
+ ASSERT(z->kmem_type >= ZSTD_KMEM_UNKNOWN);
+
+ if (z->kmem_type == ZSTD_KMEM_UNKNOWN) {
+ kmem_free(z, z->kmem_size);
+ } else {
+ kmem_cache_free(zstd_kmem_cache[z->kmem_type], z);
+ }
+}
+
+extern void
+zstd_init(void)
+{
+ int i;
+
+ /* There is no estimate function for the CCtx */
+ zstd_cache_size[1].kmem_magic = ZSTD_KMEM_MAGIC;
+ zstd_cache_size[1].kmem_type = 1;
+ zstd_cache_size[1].kmem_size = roundup2(zstd_cache_config[1].block_size
+ + sizeof(struct zstd_kmem), PAGE_SIZE);
+ zstd_kmem_cache[1] = kmem_cache_create(
+ zstd_cache_config[1].cache_name, zstd_cache_size[1].kmem_size,
+ 0, NULL, NULL, NULL, NULL, NULL, 0);
+
+ /*
+ * Estimate the size of the ZSTD CCtx workspace required for each record
+ * size at each compression level.
+ */
+ for (i = 2; i < ZSTD_KMEM_DCTX; i++) {
+ zstd_cache_size[i].kmem_magic = ZSTD_KMEM_MAGIC;
+ zstd_cache_size[i].kmem_type = i;
+ zstd_cache_size[i].kmem_size = roundup2(
+ ZSTD_estimateCCtxSize_usingCParams(
+ ZSTD_getCParams(zstd_cache_config[i].compress_level,
+ zstd_cache_config[i].block_size, 0)) +
+ sizeof(struct zstd_kmem), PAGE_SIZE);
+ zstd_kmem_cache[i] = kmem_cache_create(
+ zstd_cache_config[i].cache_name,
+ zstd_cache_size[i].kmem_size,
+ 0, NULL, NULL, NULL, NULL, NULL, 0);
+ }
+ /* Estimate the size of the decompression context */
+ zstd_cache_size[i].kmem_magic = ZSTD_KMEM_MAGIC;
+ zstd_cache_size[i].kmem_type = i;
+ zstd_cache_size[i].kmem_size = roundup2(ZSTD_estimateDCtxSize() +
+ sizeof(struct zstd_kmem), PAGE_SIZE);
+ zstd_kmem_cache[i] = kmem_cache_create(zstd_cache_config[i].cache_name,
+ zstd_cache_size[i].kmem_size, 0, NULL, NULL, NULL, NULL, NULL, 0);
+
+ /* Sort the kmem caches for later searching */
+ qsort(zstd_cache_size, ZSTD_KMEM_COUNT, sizeof(struct zstd_kmem),
+ zstd_compare);
+
+}
+
+extern void
+zstd_fini(void)
+{
+ int i, type;
+
+ for (i = 0; i < ZSTD_KMEM_COUNT; i++) {
+ type = zstd_cache_size[i].kmem_type;
+ if (zstd_kmem_cache[type] != NULL) {
+ kmem_cache_destroy(zstd_kmem_cache[type]);
+ }
+ }
+}
Index: sys/cddl/contrib/opensolaris/uts/common/sys/fs/zfs.h
===================================================================
--- sys/cddl/contrib/opensolaris/uts/common/sys/fs/zfs.h
+++ sys/cddl/contrib/opensolaris/uts/common/sys/fs/zfs.h
@@ -163,6 +163,7 @@
ZFS_PROP_REDUNDANT_METADATA,
ZFS_PROP_PREV_SNAP,
ZFS_PROP_RECEIVE_RESUME_TOKEN,
+ ZFS_PROP_ZSTD_LEVEL,
ZFS_NUM_PROPS
} zfs_prop_t;
Index: sys/contrib/zstd/lib/freebsd/stddef.h
===================================================================
--- /dev/null
+++ sys/contrib/zstd/lib/freebsd/stddef.h
@@ -0,0 +1,2 @@
+#include "zstd_kfreebsd.h"
+
Index: sys/contrib/zstd/lib/freebsd/stdint.h
===================================================================
--- /dev/null
+++ sys/contrib/zstd/lib/freebsd/stdint.h
@@ -0,0 +1,2 @@
+#include "zstd_kfreebsd.h"
+
Index: sys/contrib/zstd/lib/freebsd/stdio.h
===================================================================
--- /dev/null
+++ sys/contrib/zstd/lib/freebsd/stdio.h
@@ -0,0 +1,2 @@
+#include "zstd_kfreebsd.h"
+
Index: sys/contrib/zstd/lib/freebsd/stdlib.h
===================================================================
--- /dev/null
+++ sys/contrib/zstd/lib/freebsd/stdlib.h
@@ -0,0 +1,2 @@
+#include "zstd_kfreebsd.h"
+
Index: sys/contrib/zstd/lib/freebsd/string.h
===================================================================
--- /dev/null
+++ sys/contrib/zstd/lib/freebsd/string.h
@@ -0,0 +1,2 @@
+#include "zstd_kfreebsd.h"
+
Index: sys/contrib/zstd/lib/freebsd/zstd_kfreebsd.h
===================================================================
--- /dev/null
+++ sys/contrib/zstd/lib/freebsd/zstd_kfreebsd.h
@@ -0,0 +1,56 @@
+/*-
+ * Copyright (c) 2014-2015 Allan Jude <allanjude@freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef ZSTD_KFREEBSD_H
+#define ZSTD_KFREEBSD_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef _KERNEL
+#include <sys/param.h> /* size_t */
+#include <sys/systm.h> /* memcpy, memset */
+#ifndef BUILDING_ZFS
+#include <sys/stddef.h> /* ptrdiff_t */
+#endif
+#include <sys/malloc.h>
+
+MALLOC_DECLARE(M_ZSTD);
+
+#define malloc(x) (malloc)((x), M_ZSTD, M_WAITOK)
+#define free(x) (free)((x), M_ZSTD)
+/* in zstd's use of calloc, a is always 1 */
+#define calloc(a,b) (malloc)((a)*(b), M_ZSTD, M_WAITOK | M_ZERO)
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZSTD_KFREEBSD_H */
Index: sys/contrib/zstd/lib/freebsd/zstd_kmalloc.c
===================================================================
--- /dev/null
+++ sys/contrib/zstd/lib/freebsd/zstd_kmalloc.c
@@ -0,0 +1,33 @@
+/*-
+ * Copyright (c) 2016-2017 Allan Jude <allanjude@freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+
+MALLOC_DEFINE(M_ZSTD, "zstd", "ZSTD Compressor");
Index: sys/modules/zfs/Makefile
===================================================================
--- sys/modules/zfs/Makefile
+++ sys/modules/zfs/Makefile
@@ -72,6 +72,11 @@
.PATH: ${SYSDIR}/crypto/skein
SRCS+= skein.c skein_block.c
+.PATH: ${SYSDIR}/contrib/zstd/lib
+CFLAGS+=-I${SYSDIR}/contrib/zstd/lib
+CFLAGS+=-I${SYSDIR}/contrib/zstd/lib/freebsd
+CFLAGS+=-I${SYSDIR}/contrib/zstd/lib/common
+
.PATH: ${SUNW}/common/zfs
.include "${SUNW}/uts/common/Makefile.files"
.PATH: ${SUNW}/uts/common/fs/zfs

File Metadata

Mime Type
text/plain
Expires
Wed, Jan 21, 4:22 PM (2 h, 43 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
27813407
Default Alt Text
D11124.id36221.diff (42 KB)

Event Timeline