diff --git a/module/zfs/lz4_zfs.c b/module/zfs/lz4_zfs.c index e28215cf3501..820556effb8b 100644 --- a/module/zfs/lz4_zfs.c +++ b/module/zfs/lz4_zfs.c @@ -50,7 +50,8 @@ static int LZ4_compress64kCtx(void *ctx, const char *source, char *dest, int LZ4_uncompress_unknownOutputSize(const char *source, char *dest, int isize, int maxOutputSize); -static kmem_cache_t *lz4_cache; +static void *lz4_alloc(int flags); +static void lz4_free(void *ctx); size_t lz4_compress_zfs(void *s_start, void *d_start, size_t s_len, @@ -842,8 +843,7 @@ real_LZ4_compress(const char *source, char *dest, int isize, int osize) void *ctx; int result; - ASSERT(lz4_cache != NULL); - ctx = kmem_cache_alloc(lz4_cache, KM_SLEEP); + ctx = lz4_alloc(KM_SLEEP); /* * out of kernel memory, gently fall through - this will disable @@ -859,10 +859,29 @@ real_LZ4_compress(const char *source, char *dest, int isize, int osize) else result = LZ4_compressCtx(ctx, source, dest, isize, osize); - kmem_cache_free(lz4_cache, ctx); + lz4_free(ctx); return (result); } +#ifdef __FreeBSD__ +/* + * FreeBSD has 4, 8 and 16 KB malloc zones which can be used here. + * Should struct refTables get resized this may need to be revisited, hence + * compiler-time asserts. + */ +_Static_assert(sizeof(struct refTables) <= 16384, + "refTables too big for malloc"); +_Static_assert((sizeof(struct refTables) % 4096) == 0, + "refTables not a multiple of page size"); +#else +#define ZFS_LZ4_USE_CACHE +#endif + +#ifdef ZFS_LZ4_USE_CACHE +static kmem_cache_t *lz4_cache; +#endif + +#ifdef ZFS_LZ4_USE_CACHE void lz4_init(void) { @@ -878,3 +897,39 @@ lz4_fini(void) lz4_cache = NULL; } } + +static void * +lz4_alloc(int flags) +{ + ASSERT(lz4_cache != NULL); + return (kmem_cache_alloc(lz4_cache, flags)); +} + +static void +lz4_free(void *ctx) +{ + kmem_cache_free(lz4_cache, ctx); +} +#else +void +lz4_init(void) +{ +} + +void +lz4_fini(void) +{ +} + +static void * +lz4_alloc(int flags) +{ + return (kmem_alloc(sizeof (struct refTables), flags)); +} + +static void +lz4_free(void *ctx) +{ + kmem_free(ctx, sizeof (struct refTables)); +} +#endif