diff options
author | Rich Ercolani <[email protected]> | 2021-08-30 17:13:46 -0400 |
---|---|---|
committer | Tony Hutter <[email protected]> | 2021-09-14 15:05:55 -0700 |
commit | 72a989cf60b4c7b9a46dc5854c0bd2561ce6b576 (patch) | |
tree | 8133d7ee2002161fe3f3c20c7020d3d7c5b15e5c /module | |
parent | 6bb6410570e6aeb19ae82d9287922927432f8c74 (diff) |
Fix cross-endian interoperability of zstd
It turns out that layouts of union bitfields are a pain, and the
current code results in an inconsistent layout between BE and LE
systems, leading to zstd-active datasets on one erroring out on
the other.
Switch everyone over to the LE layout, and add compatibility code
to read both.
Reviewed-by: Brian Behlendorf <[email protected]>
Reviewed-by: Matthew Ahrens <[email protected]>
Signed-off-by: Rich Ercolani <[email protected]>
Closes #12008
Closes #12022
Diffstat (limited to 'module')
-rw-r--r-- | module/zstd/Makefile.in | 1 | ||||
-rw-r--r-- | module/zstd/include/sparc_compat.h | 4 | ||||
-rw-r--r-- | module/zstd/zfs_zstd.c | 14 | ||||
-rw-r--r-- | module/zstd/zstd_sparc.c | 11 |
4 files changed, 24 insertions, 6 deletions
diff --git a/module/zstd/Makefile.in b/module/zstd/Makefile.in index f67db710f..091f7cea3 100644 --- a/module/zstd/Makefile.in +++ b/module/zstd/Makefile.in @@ -33,6 +33,7 @@ $(obj)/zfs_zstd.o: c_flags += -include $(zstd_include)/zstd_compat_wrapper.h $(MODULE)-objs += zfs_zstd.o $(MODULE)-objs += lib/zstd.o +$(MODULE)-objs += zstd_sparc.o all: mkdir -p lib diff --git a/module/zstd/include/sparc_compat.h b/module/zstd/include/sparc_compat.h new file mode 100644 index 000000000..14c1bdde9 --- /dev/null +++ b/module/zstd/include/sparc_compat.h @@ -0,0 +1,4 @@ +#if defined(__sparc) +uint64_t __bswapdi2(uint64_t in); +uint32_t __bswapsi2(uint32_t in); +#endif diff --git a/module/zstd/zfs_zstd.c b/module/zstd/zfs_zstd.c index a91ed1be9..2c698716c 100644 --- a/module/zstd/zfs_zstd.c +++ b/module/zstd/zfs_zstd.c @@ -380,6 +380,7 @@ zstd_enum_to_level(enum zio_zstd_levels level, int16_t *zstd_level) return (1); } + /* Compress block using zstd */ size_t zfs_zstd_compress(void *s_start, void *d_start, size_t s_len, size_t d_len, @@ -477,8 +478,8 @@ zfs_zstd_compress(void *s_start, void *d_start, size_t s_len, size_t d_len, * As soon as such incompatibility occurs, handling code needs to be * added, differentiating between the versions. */ - hdr->version = ZSTD_VERSION_NUMBER; - hdr->level = level; + zfs_set_hdrversion(hdr, ZSTD_VERSION_NUMBER); + zfs_set_hdrlevel(hdr, level); hdr->raw_version_level = BE_32(hdr->raw_version_level); return (c_len + sizeof (*hdr)); @@ -504,6 +505,7 @@ zfs_zstd_decompress_level(void *s_start, void *d_start, size_t s_len, * not modify the original data that may be used again later. */ hdr_copy.raw_version_level = BE_32(hdr->raw_version_level); + uint8_t curlevel = zfs_get_hdrlevel(&hdr_copy); /* * NOTE: We ignore the ZSTD version for now. As soon as any @@ -516,13 +518,13 @@ zfs_zstd_decompress_level(void *s_start, void *d_start, size_t s_len, * An invalid level is a strong indicator for data corruption! In such * case return an error so the upper layers can try to fix it. */ - if (zstd_enum_to_level(hdr_copy.level, &zstd_level)) { + if (zstd_enum_to_level(curlevel, &zstd_level)) { ZSTDSTAT_BUMP(zstd_stat_dec_inval); return (1); } ASSERT3U(d_len, >=, s_len); - ASSERT3U(hdr_copy.level, !=, ZIO_COMPLEVEL_INHERIT); + ASSERT3U(curlevel, !=, ZIO_COMPLEVEL_INHERIT); /* Invalid compressed buffer size encoded at start */ if (c_len + sizeof (*hdr) > s_len) { @@ -553,7 +555,7 @@ zfs_zstd_decompress_level(void *s_start, void *d_start, size_t s_len, } if (level) { - *level = hdr_copy.level; + *level = curlevel; } return (0); @@ -783,7 +785,7 @@ module_exit(zstd_fini); ZFS_MODULE_DESCRIPTION("ZSTD Compression for ZFS"); ZFS_MODULE_LICENSE("Dual BSD/GPL"); -ZFS_MODULE_VERSION(ZSTD_VERSION_STRING); +ZFS_MODULE_VERSION(ZSTD_VERSION_STRING "a"); EXPORT_SYMBOL(zfs_zstd_compress); EXPORT_SYMBOL(zfs_zstd_decompress_level); diff --git a/module/zstd/zstd_sparc.c b/module/zstd/zstd_sparc.c new file mode 100644 index 000000000..463df99bd --- /dev/null +++ b/module/zstd/zstd_sparc.c @@ -0,0 +1,11 @@ +#ifdef __sparc__ +#include <stdint.h> +#include <sys/byteorder.h> +#include "include/sparc_compat.h" +uint64_t __bswapdi2(uint64_t in) { + return (BSWAP_64(in)); +} +uint32_t __bswapsi2(uint32_t in) { + return (BSWAP_32(in)); +} +#endif |