Index: Makefile.inc1 =================================================================== --- Makefile.inc1 +++ Makefile.inc1 @@ -2154,7 +2154,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 @@ -6,7 +6,7 @@ .PATH: ${SRCTOP}/cddl/contrib/opensolaris/lib/libzfs/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 @@ -54,8 +54,9 @@ CFLAGS+= -I${SRCTOP}/lib/libpthread/thread CFLAGS+= -I${SRCTOP}/lib/libpthread/sys CFLAGS+= -I${SRCTOP}/lib/libthr/arch/${MACHINE_CPUARCH}/include +CFLAGS+= -I${.CURDIR}/../../../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: contrib/zstd/lib/common/error_private.h =================================================================== --- contrib/zstd/lib/common/error_private.h +++ contrib/zstd/lib/common/error_private.h @@ -20,7 +20,11 @@ /* **************************************** * Dependencies ******************************************/ +#ifdef _KERNEL +#include /* size_t */ +#else #include /* size_t */ +#endif #include "zstd_errors.h" /* enum list */ Index: contrib/zstd/lib/common/fse.h =================================================================== --- contrib/zstd/lib/common/fse.h +++ contrib/zstd/lib/common/fse.h @@ -42,7 +42,11 @@ /*-***************************************** * Dependencies ******************************************/ +#ifdef _KERNEL +#include /* size_t, ptrdiff_t */ +#else #include /* size_t, ptrdiff_t */ +#endif /*-***************************************** Index: contrib/zstd/lib/common/fse_decompress.c =================================================================== --- contrib/zstd/lib/common/fse_decompress.c +++ contrib/zstd/lib/common/fse_decompress.c @@ -57,12 +57,20 @@ /* ************************************************************** * Includes ****************************************************************/ +#ifdef _KERNEL +#include /* memset */ +#else #include /* malloc, free, qsort */ #include /* memcpy, memset */ +#endif #include "bitstream.h" #define FSE_STATIC_LINKING_ONLY #include "fse.h" +#if defined(ZSTD_HEAPMODE) && (ZSTD_HEAPMODE==1) +#include "zstd_internal.h" /* defaultCustomMem */ +static ZSTD_customMem customMalloc = { ZSTD_defaultAllocFunction, ZSTD_defaultFreeFunction, NULL }; +#endif /* ************************************************************** * Error Management @@ -71,7 +79,7 @@ #define FSE_STATIC_ASSERT(c) { enum { FSE_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */ /* check and forward error code */ -#define CHECK_F(f) { size_t const e = f; if (FSE_isError(e)) return e; } +#define CHECK_FSE_F(f) { size_t const e = f; if (FSE_isError(e)) return e; } /* ************************************************************** @@ -98,9 +106,21 @@ /* Function templates */ +#if defined(ZSTD_HEAPMODE) && (ZSTD_HEAPMODE==1) FSE_DTable* FSE_createDTable (unsigned tableLog) { if (tableLog > FSE_TABLELOG_ABSOLUTE_MAX) tableLog = FSE_TABLELOG_ABSOLUTE_MAX; + return (FSE_DTable*)ZSTD_malloc( FSE_DTABLE_SIZE_U32(tableLog) * sizeof (U32), customMalloc ); +} + +void FSE_freeDTable (FSE_DTable* dt) +{ + ZSTD_free(dt, customMalloc); +} +#else +FSE_DTable* FSE_createDTable (unsigned tableLog) +{ + if (tableLog > FSE_TABLELOG_ABSOLUTE_MAX) tableLog = FSE_TABLELOG_ABSOLUTE_MAX; return (FSE_DTable*)malloc( FSE_DTABLE_SIZE_U32(tableLog) * sizeof (U32) ); } @@ -108,6 +128,7 @@ { free(dt); } +#endif size_t FSE_buildDTable(FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog) { @@ -231,7 +252,7 @@ FSE_DState_t state2; /* Init */ - CHECK_F(BIT_initDStream(&bitD, cSrc, cSrcSize)); + CHECK_FSE_F(BIT_initDStream(&bitD, cSrc, cSrcSize)); FSE_initDState(&state1, &bitD, dt); FSE_initDState(&state2, &bitD, dt); @@ -309,7 +330,7 @@ ip += NCountLength; cSrcSize -= NCountLength; - CHECK_F( FSE_buildDTable (workSpace, counting, maxSymbolValue, tableLog) ); + CHECK_FSE_F( FSE_buildDTable (workSpace, counting, maxSymbolValue, tableLog) ); return FSE_decompress_usingDTable (dst, dstCapacity, ip, cSrcSize, workSpace); /* always return, even if it is an error code */ } Index: contrib/zstd/lib/common/huf.h =================================================================== --- contrib/zstd/lib/common/huf.h +++ contrib/zstd/lib/common/huf.h @@ -40,7 +40,11 @@ /* *** Dependencies *** */ +#ifdef _KERNEL +#include /* size_t */ +#else #include /* size_t */ +#endif /* *** library symbols visibility *** */ Index: contrib/zstd/lib/common/mem.h =================================================================== --- contrib/zstd/lib/common/mem.h +++ contrib/zstd/lib/common/mem.h @@ -17,8 +17,13 @@ /*-**************************************** * Dependencies ******************************************/ +#ifdef _KERNEL +#include /* size_t */ +#include /* memcpy */ +#else #include /* size_t, ptrdiff_t */ #include /* memcpy */ +#endif /*-**************************************** @@ -47,7 +52,9 @@ * Basic Types *****************************************************************/ #if !defined (__VMS) && (defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) +#ifndef _KERNEL # include +#endif typedef uint8_t BYTE; typedef uint16_t U16; typedef int16_t S16; Index: contrib/zstd/lib/common/pool.h =================================================================== --- contrib/zstd/lib/common/pool.h +++ contrib/zstd/lib/common/pool.h @@ -14,7 +14,11 @@ #endif +#ifdef _KERNEL +#include +#else #include /* size_t */ +#endif typedef struct POOL_ctx_s POOL_ctx; Index: contrib/zstd/lib/common/pool.c =================================================================== --- contrib/zstd/lib/common/pool.c +++ contrib/zstd/lib/common/pool.c @@ -9,8 +9,13 @@ /* ====== Dependencies ======= */ +#ifdef _KERNEL +#include +#include +#else #include /* size_t */ #include /* malloc, calloc, free */ +#endif #include "pool.h" /* ====== Compiler specifics ====== */ Index: contrib/zstd/lib/common/xxhash.h =================================================================== --- contrib/zstd/lib/common/xxhash.h +++ contrib/zstd/lib/common/xxhash.h @@ -75,7 +75,11 @@ /* **************************** * Definitions ******************************/ +#ifdef _KERNEL +#include /* size_t */ +#else #include /* size_t */ +#endif typedef enum { XXH_OK=0, XXH_ERROR } XXH_errorcode; Index: contrib/zstd/lib/common/xxhash.c =================================================================== --- contrib/zstd/lib/common/xxhash.c +++ contrib/zstd/lib/common/xxhash.c @@ -97,11 +97,23 @@ ***************************************/ /* Modify the local functions below should you wish to use some other memory routines */ /* for malloc(), free() */ +#ifdef _KERNEL +#include +extern void *zstd_alloc(void *opaque, size_t size); +extern void zstd_free(void *opaque, void *ptr); +static void* XXH_malloc(size_t s) { return zstd_alloc("xxh", s); } +static void XXH_free (void* p) { zstd_free("xxh", p); } +#else #include static void* XXH_malloc(size_t s) { return malloc(s); } static void XXH_free (void* p) { free(p); } +#endif /* for memcpy() */ +#ifdef _KERNEL +#include +#else #include +#endif static void* XXH_memcpy(void* dest, const void* src, size_t size) { return memcpy(dest,src,size); } #ifndef XXH_STATIC_LINKING_ONLY @@ -135,7 +147,9 @@ #ifndef MEM_MODULE # define MEM_MODULE # if !defined (__VMS) && (defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) +#ifndef _KERNEL # include +#endif typedef uint8_t BYTE; typedef uint16_t U16; typedef uint32_t U32; Index: contrib/zstd/lib/common/zstd_common.c =================================================================== --- contrib/zstd/lib/common/zstd_common.c +++ contrib/zstd/lib/common/zstd_common.c @@ -12,7 +12,9 @@ /*-************************************* * Dependencies ***************************************/ +#ifndef _KERNEL #include /* malloc */ +#endif #include "error_private.h" #define ZSTD_STATIC_LINKING_ONLY #include "zstd.h" /* declaration of ZSTD_isError, ZSTD_getErrorName, ZSTD_getErrorCode, ZSTD_getErrorString, ZSTD_versionNumber */ @@ -50,15 +52,23 @@ /* default uses stdlib */ void* ZSTD_defaultAllocFunction(void* opaque, size_t size) { +#ifdef _KERNEL + void* address = zstd_alloc(opaque, size); +#else void* address = malloc(size); (void)opaque; +#endif return address; } void ZSTD_defaultFreeFunction(void* opaque, void* address) { +#ifdef _KERNEL + zstd_free(opaque, address); +#else (void)opaque; free(address); +#endif } void* ZSTD_malloc(size_t size, ZSTD_customMem customMem) Index: contrib/zstd/lib/common/zstd_errors.h =================================================================== --- contrib/zstd/lib/common/zstd_errors.h +++ contrib/zstd/lib/common/zstd_errors.h @@ -15,7 +15,11 @@ #endif /*===== dependency =====*/ +#ifdef _KERNEL +#include /* size_t */ +#else #include /* size_t */ +#endif /* ===== ZSTDERRORLIB_API : control library symbols visibility ===== */ Index: contrib/zstd/lib/compress/fse_compress.c =================================================================== --- contrib/zstd/lib/compress/fse_compress.c +++ contrib/zstd/lib/compress/fse_compress.c @@ -56,13 +56,21 @@ /* ************************************************************** * Includes ****************************************************************/ +#ifdef _KERNEL +#include /* memcpy, memset */ +#else #include /* malloc, free, qsort */ #include /* memcpy, memset */ #include /* printf (debug) */ +#endif #include "bitstream.h" #define FSE_STATIC_LINKING_ONLY #include "fse.h" +#if defined(ZSTD_HEAPMODE) && (ZSTD_HEAPMODE==1) +#include "zstd_internal.h" /* defaultCustomMem */ +static ZSTD_customMem customMalloc = { ZSTD_defaultAllocFunction, ZSTD_defaultFreeFunction, NULL }; +#endif /* ************************************************************** * Error Management @@ -468,10 +476,18 @@ size_t size; if (tableLog > FSE_TABLELOG_ABSOLUTE_MAX) tableLog = FSE_TABLELOG_ABSOLUTE_MAX; size = FSE_CTABLE_SIZE_U32 (tableLog, maxSymbolValue) * sizeof(U32); +#if defined(ZSTD_HEAPMODE) && (ZSTD_HEAPMODE==1) + return (FSE_CTable*)ZSTD_malloc(size, customMalloc); +#else return (FSE_CTable*)malloc(size); +#endif } +#if defined(ZSTD_HEAPMODE) && (ZSTD_HEAPMODE==1) +void FSE_freeCTable (FSE_CTable* ct) { ZSTD_free(ct, customMalloc); } +#else void FSE_freeCTable (FSE_CTable* ct) { free(ct); } +#endif /* provides the minimum logSize to safely represent a distribution */ static unsigned FSE_minTableLog(size_t srcSize, unsigned maxSymbolValue) @@ -782,7 +798,7 @@ size_t FSE_compressBound(size_t size) { return FSE_COMPRESSBOUND(size); } #define CHECK_V_F(e, f) size_t const e = f; if (ERR_isError(e)) return f -#define CHECK_F(f) { CHECK_V_F(_var_err__, f); } +#define CHECK_FSE_F(f) { CHECK_V_F(_var_err__, f); } /* FSE_compress_wksp() : * Same as FSE_compress2(), but using an externally allocated scratch buffer (`workSpace`). @@ -815,7 +831,7 @@ } tableLog = FSE_optimalTableLog(tableLog, srcSize, maxSymbolValue); - CHECK_F( FSE_normalizeCount(norm, tableLog, count, srcSize, maxSymbolValue) ); + CHECK_FSE_F( FSE_normalizeCount(norm, tableLog, count, srcSize, maxSymbolValue) ); /* Write table description header */ { CHECK_V_F(nc_err, FSE_writeNCount(op, oend-op, norm, maxSymbolValue, tableLog) ); @@ -823,7 +839,7 @@ } /* Compress */ - CHECK_F( FSE_buildCTable_wksp(CTable, norm, maxSymbolValue, tableLog, scratchBuffer, scratchBufferSize) ); + CHECK_FSE_F( FSE_buildCTable_wksp(CTable, norm, maxSymbolValue, tableLog, scratchBuffer, scratchBufferSize) ); { CHECK_V_F(cSize, FSE_compress_usingCTable(op, oend - op, src, srcSize, CTable) ); if (cSize == 0) return 0; /* not enough space for compressed data */ op += cSize; Index: contrib/zstd/lib/compress/huf_compress.c =================================================================== --- contrib/zstd/lib/compress/huf_compress.c +++ contrib/zstd/lib/compress/huf_compress.c @@ -43,21 +43,29 @@ /* ************************************************************** * Includes ****************************************************************/ +#ifdef _KERNEL +#include /* memcpy, memset */ +#else #include /* memcpy, memset */ #include /* printf (debug) */ +#endif #include "bitstream.h" #define FSE_STATIC_LINKING_ONLY /* FSE_optimalTableLog_internal */ #include "fse.h" /* header compression */ #define HUF_STATIC_LINKING_ONLY #include "huf.h" +#if defined(ZSTD_HEAPMODE) && (ZSTD_HEAPMODE==1) +#include "zstd_internal.h" /* defaultCustomMem */ +static ZSTD_customMem customMalloc = { ZSTD_defaultAllocFunction, ZSTD_defaultFreeFunction, NULL }; +#endif /* ************************************************************** * Error Management ****************************************************************/ #define HUF_STATIC_ASSERT(c) { enum { HUF_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */ #define CHECK_V_F(e, f) size_t const e = f; if (ERR_isError(e)) return f -#define CHECK_F(f) { CHECK_V_F(_var_err__, f); } +#define CHECK_HUF_F(f) { CHECK_V_F(_var_err__, f); } /* ************************************************************** @@ -103,7 +111,7 @@ } tableLog = FSE_optimalTableLog(tableLog, wtSize, maxSymbolValue); - CHECK_F( FSE_normalizeCount(norm, tableLog, count, wtSize, maxSymbolValue) ); + CHECK_HUF_F( FSE_normalizeCount(norm, tableLog, count, wtSize, maxSymbolValue) ); /* Write table description header */ { CHECK_V_F(hSize, FSE_writeNCount(op, oend-op, norm, maxSymbolValue, tableLog) ); @@ -111,7 +119,7 @@ } /* Compress */ - CHECK_F( FSE_buildCTable_wksp(CTable, norm, maxSymbolValue, tableLog, scratchBuffer, sizeof(scratchBuffer)) ); + CHECK_HUF_F( FSE_buildCTable_wksp(CTable, norm, maxSymbolValue, tableLog, scratchBuffer, sizeof(scratchBuffer)) ); { CHECK_V_F(cSize, FSE_compress_usingCTable(op, oend - op, weightTable, wtSize, CTable) ); if (cSize == 0) return 0; /* not enough space for compressed data */ op += cSize; Index: contrib/zstd/lib/compress/zstd_compress.c =================================================================== --- contrib/zstd/lib/compress/zstd_compress.c +++ contrib/zstd/lib/compress/zstd_compress.c @@ -11,7 +11,11 @@ /*-************************************* * Dependencies ***************************************/ +#ifdef _KERNEL +#include /* memcpy, memset */ +#else #include /* memset */ +#endif #include "mem.h" #define FSE_STATIC_LINKING_ONLY /* FSE_encodeSymbol */ #include "fse.h" Index: contrib/zstd/lib/decompress/huf_decompress.c =================================================================== --- contrib/zstd/lib/decompress/huf_decompress.c +++ contrib/zstd/lib/decompress/huf_decompress.c @@ -54,12 +54,20 @@ /* ************************************************************** * Dependencies ****************************************************************/ +#ifdef _KERNEL +#include /* memcpy, memset */ +#else #include /* memcpy, memset */ +#endif #include "bitstream.h" /* BIT_* */ #include "fse.h" /* header compression */ #define HUF_STATIC_LINKING_ONLY #include "huf.h" +#if defined(ZSTD_HEAPMODE) && (ZSTD_HEAPMODE==1) +#include "zstd_internal.h" /* defaultCustomMem */ +static ZSTD_customMem customMalloc = { ZSTD_defaultAllocFunction, ZSTD_defaultFreeFunction, NULL }; +#endif /* ************************************************************** * Error Management Index: contrib/zstd/lib/decompress/zstd_decompress.c =================================================================== --- contrib/zstd/lib/decompress/zstd_decompress.c +++ contrib/zstd/lib/decompress/zstd_decompress.c @@ -41,7 +41,11 @@ /*-******************************************************* * Dependencies *********************************************************/ +#ifdef _KERNEL +#include /* memcpy, memset */ +#else #include /* memcpy, memmove, memset */ +#endif #include "mem.h" /* low level memory routines */ #define FSE_STATIC_LINKING_ONLY #include "fse.h" Index: contrib/zstd/lib/zstd.h =================================================================== --- contrib/zstd/lib/zstd.h +++ contrib/zstd/lib/zstd.h @@ -15,7 +15,13 @@ #define ZSTD_H_235446 /* ====== Dependency ======*/ +#ifdef _KERNEL +#include /* size_t */ +extern void *zstd_alloc(void *opaque, size_t size); +extern void zstd_free(void *opaque, void *ptr); +#else #include /* size_t */ +#endif /* ===== ZSTDLIB_API : control library symbols visibility ===== */ Index: rescue/rescue/Makefile =================================================================== --- rescue/rescue/Makefile +++ rescue/rescue/Makefile @@ -129,7 +129,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 @@ -325,9 +325,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 .if ${MK_OFED} != "no" _DP_cxgb4= ibverbs pthread _DP_ibcm= ibverbs Index: sys/boot/zfs/zfsimpl.c =================================================================== --- sys/boot/zfs/zfsimpl.c +++ sys/boot/zfs/zfsimpl.c @@ -60,6 +60,7 @@ "org.open-zfs:large_blocks", "org.illumos:sha512", "org.illumos:skein", + "org.freebsd:zstd_compress", NULL }; 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,29 @@ { "gzip-9", ZIO_COMPRESS_GZIP_9 }, { "zle", ZIO_COMPRESS_ZLE }, { "lz4", ZIO_COMPRESS_LZ4 }, + { "zstd", ZIO_COMPRESS_ZSTD_3 }, /* zstd default */ + { "zstd-1", ZIO_COMPRESS_ZSTD_1 }, + { "zstd-2", ZIO_COMPRESS_ZSTD_2 }, + { "zstd-3", ZIO_COMPRESS_ZSTD_3 }, + { "zstd-4", ZIO_COMPRESS_ZSTD_4 }, + { "zstd-5", ZIO_COMPRESS_ZSTD_5 }, + { "zstd-6", ZIO_COMPRESS_ZSTD_6 }, + { "zstd-7", ZIO_COMPRESS_ZSTD_7 }, + { "zstd-8", ZIO_COMPRESS_ZSTD_8 }, + { "zstd-9", ZIO_COMPRESS_ZSTD_9 }, + { "zstd-10", ZIO_COMPRESS_ZSTD_10 }, + { "zstd-11", ZIO_COMPRESS_ZSTD_11 }, + { "zstd-12", ZIO_COMPRESS_ZSTD_12 }, + { "zstd-13", ZIO_COMPRESS_ZSTD_13 }, + { "zstd-14", ZIO_COMPRESS_ZSTD_14 }, + { "zstd-15", ZIO_COMPRESS_ZSTD_15 }, + { "zstd-16", ZIO_COMPRESS_ZSTD_16 }, + { "zstd-17", ZIO_COMPRESS_ZSTD_17 }, + { "zstd-18", ZIO_COMPRESS_ZSTD_18 }, + { "zstd-19", ZIO_COMPRESS_ZSTD_19 }, + { "zstd-20", ZIO_COMPRESS_ZSTD_20 }, + { "zstd-21", ZIO_COMPRESS_ZSTD_21 }, + { "zstd-22", ZIO_COMPRESS_ZSTD_22 }, { NULL } }; @@ -250,7 +273,7 @@ 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-22]", "COMPRESS", compress_table); zprop_register_index(ZFS_PROP_SNAPDIR, "snapdir", ZFS_SNAPDIR_HIDDEN, PROP_INHERIT, ZFS_TYPE_FILESYSTEM, 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 @@ -109,7 +109,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/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 @@ -52,6 +52,28 @@ ZIO_COMPRESS_GZIP_9, ZIO_COMPRESS_ZLE, ZIO_COMPRESS_LZ4, + ZIO_COMPRESS_ZSTD_1, + ZIO_COMPRESS_ZSTD_2, + ZIO_COMPRESS_ZSTD_3, + ZIO_COMPRESS_ZSTD_4, + ZIO_COMPRESS_ZSTD_5, + ZIO_COMPRESS_ZSTD_6, + ZIO_COMPRESS_ZSTD_7, + ZIO_COMPRESS_ZSTD_8, + ZIO_COMPRESS_ZSTD_9, + ZIO_COMPRESS_ZSTD_10, + ZIO_COMPRESS_ZSTD_11, + ZIO_COMPRESS_ZSTD_12, + ZIO_COMPRESS_ZSTD_13, + ZIO_COMPRESS_ZSTD_14, + ZIO_COMPRESS_ZSTD_15, + ZIO_COMPRESS_ZSTD_16, + ZIO_COMPRESS_ZSTD_17, + ZIO_COMPRESS_ZSTD_18, + ZIO_COMPRESS_ZSTD_19, + ZIO_COMPRESS_ZSTD_20, + ZIO_COMPRESS_ZSTD_21, + ZIO_COMPRESS_ZSTD_22, ZIO_COMPRESS_FUNCTIONS }; @@ -95,6 +117,14 @@ 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); +extern void *zstd_alloc(void *opaque, size_t size); +extern void zstd_free(void *opaque, void *ptr); /* * Compress and decompress data if necessary. 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 @@ -3973,6 +3973,21 @@ spa_close(spa, FTAG); } + if (intval >= ZIO_COMPRESS_ZSTD_1 && + intval <= ZIO_COMPRESS_ZSTD_22) { + 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)); + } + spa_close(spa, FTAG); + } + /* * If this is a bootable dataset then * verify that the compression algorithm 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 @@ -79,6 +79,28 @@ {gzip_compress, gzip_decompress, 9, "gzip-9"}, {zle_compress, zle_decompress, 64, "zle"}, {lz4_compress, lz4_decompress, 0, "lz4"}, + {zstd_compress, zstd_decompress, 1, "zstd-1"}, + {zstd_compress, zstd_decompress, 2, "zstd-2"}, + {zstd_compress, zstd_decompress, 3, "zstd-3"}, + {zstd_compress, zstd_decompress, 4, "zstd-4"}, + {zstd_compress, zstd_decompress, 5, "zstd-5"}, + {zstd_compress, zstd_decompress, 6, "zstd-6"}, + {zstd_compress, zstd_decompress, 7, "zstd-7"}, + {zstd_compress, zstd_decompress, 8, "zstd-8"}, + {zstd_compress, zstd_decompress, 9, "zstd-9"}, + {zstd_compress, zstd_decompress, 10, "zstd-10"}, + {zstd_compress, zstd_decompress, 11, "zstd-11"}, + {zstd_compress, zstd_decompress, 12, "zstd-12"}, + {zstd_compress, zstd_decompress, 13, "zstd-13"}, + {zstd_compress, zstd_decompress, 14, "zstd-14"}, + {zstd_compress, zstd_decompress, 15, "zstd-15"}, + {zstd_compress, zstd_decompress, 16, "zstd-16"}, + {zstd_compress, zstd_decompress, 17, "zstd-17"}, + {zstd_compress, zstd_decompress, 18, "zstd-18"}, + {zstd_compress, zstd_decompress, 19, "zstd-19"}, + {zstd_compress, zstd_decompress, 20, "zstd-20"}, + {zstd_compress, zstd_decompress, 21, "zstd-21"}, + {zstd_compress, zstd_decompress, 22, "zstd-22"}, }; enum zio_compress 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,217 @@ +/* + * 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 2016 ScaleEngine, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#include + +#define ZSTD_STATIC_LINKING_ONLY +#include + +/* FreeBSD: Use heap for all platforms for now */ +#define HEAPMODE 1 + +#define ZSTD_KMEM_MAGIC 0x20160831 + +/* + * XXX: TODO: Investigate using ZSTD_compressBlock for small blocks + * XXX: TODO: use kmem_cache like lz4.c does + */ + +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, + "zstd-kmod" +}; + +struct zstd_kmem { + uint_t kmem_magic; + uint_t kmem_size; +}; + +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)); +} + +/*ARGSUSED*/ +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) +{ +#if HEAPMODE + size_t result; + ZSTD_CCtx *cctx; + +//printf("ALLAN: compressing %p to %p i=%d o=%d level=%d\n", source, dest, isize, osize, level); + + 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); + +//printf("ALLAN: result of compression %d @ %d -> %zu\n", isize, level, result); + + ZSTD_freeCCtx(cctx); + return (result); +#else + ZSTD_CCtx ctx; + void *ctx; + + return (ZSTD_compressCCtx(&ctx, dest, osize, source, isize, level)); +#endif +} + + +static size_t +real_zstd_decompress(const char *source, char *dest, int isize, int maxosize) +{ +#if HEAPMODE + size_t result; + ZSTD_DCtx *dctx; + +//printf("ALLAN: decompressing %p to %p i=%d o=%d\n", source, dest, isize, maxosize); + + dctx = ZSTD_createDCtx_advanced(zstd_malloc); + /* + * out of kernel memory, gently fall through - this will disable + * compression in zio_compress_data + */ + if (dctx == NULL) + return (-1); + + result = ZSTD_decompressDCtx(dctx, dest, maxosize, source, isize); + + ZSTD_freeDCtx(dctx); + return (result); +#else + ZSTD_DCtx dctx; + + return (ZSTD_decompressDCtx(&dctx, dest, maxosize, source, isize)); +#endif +} + +extern void * +zstd_alloc(void *opaque, size_t size) +{ + size_t nbytes = sizeof(struct zstd_kmem) + size; + +if (opaque != NULL) { + //printf("ALLAN: zstd_alloc: opaque='%s'\n", opaque); +} + + struct zstd_kmem *z = kmem_zalloc(nbytes, KM_NOSLEEP); + +//printf("ALLAN: allocated %zu at %p(%p)\n", nbytes, z, (z + sizeof(struct zstd_kmem))); + + if (z == NULL) + return (NULL); + + z->kmem_magic = ZSTD_KMEM_MAGIC; + z->kmem_size = nbytes; + + return (z + sizeof(struct zstd_kmem)); +} + +extern void +zstd_free(void *opaque, void *ptr) +{ + struct zstd_kmem *z = ((struct zstd_kmem *)ptr) - sizeof(struct zstd_kmem); + +if (opaque != NULL) { + //printf("ALLAN: zstd_free: opaque='%s'\n", opaque); +} + + if (z->kmem_magic != ZSTD_KMEM_MAGIC) { + //panic("zstd_kmem region corrupt: hdr=%p ptr=%p header=%08x", (void *)z, ptr, z->kmem_magic); + printf("zstd_kmem region corrupt: hdr=%p ptr=%p magic=%08x size=%u\n", (void *)z, ptr, z->kmem_magic, z->kmem_size); + return; + } + +//printf("ALLAN: attempting to free %p(%p): %u bytes\n", z, ptr, z->kmem_size); + + kmem_free(z, z->kmem_size); +} Index: sys/conf/files =================================================================== --- sys/conf/files +++ sys/conf/files @@ -249,6 +249,7 @@ cddl/contrib/opensolaris/uts/common/fs/zfs/zio_inject.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/zle.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/zrlock.c optional zfs compile-with "${ZFS_C}" +cddl/contrib/opensolaris/uts/common/fs/zfs/zstd.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/os/callb.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/os/fm.c optional zfs compile-with "${ZFS_C}" Index: sys/modules/zfs/Makefile =================================================================== --- sys/modules/zfs/Makefile +++ sys/modules/zfs/Makefile @@ -72,6 +72,17 @@ .PATH: ${SYSDIR}/crypto/skein SRCS+= skein.c skein_block.c +.PATH: ${SYSDIR}/../contrib/zstd/lib +CFLAGS+=-DZSTD_HEAPMODE=1 +CFLAGS+=-I${SYSDIR}/../contrib/zstd/lib +.PATH: ${SYSDIR}/../contrib/zstd/lib/common +SRCS+= zstd_common.c xxhash.c fse_decompress.c entropy_common.c error_private.c +.PATH: ${SYSDIR}/../contrib/zstd/lib/compress +SRCS+= zstd_compress.c fse_compress.c huf_compress.c +.PATH: ${SYSDIR}/../contrib/zstd/lib/decompress +SRCS+= zstd_decompress.c huf_decompress.c +CFLAGS+=-I${SYSDIR}/../contrib/zstd/lib/common + .PATH: ${SUNW}/common/zfs .include "${SUNW}/uts/common/Makefile.files" .PATH: ${SUNW}/uts/common/fs/zfs