1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or https://opensource.org/licenses/CDDL-1.0. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 /* 27 * Copyright (c) 2013 by Saso Kiselkov. All rights reserved. 28 */ 29 30 /* 31 * Copyright (c) 2013, 2018 by Delphix. All rights reserved. 32 * Copyright (c) 2019, 2024, Klara, Inc. 33 * Copyright (c) 2019, Allan Jude 34 */ 35 36 #include <sys/zfs_context.h> 37 #include <sys/spa.h> 38 #include <sys/zfeature.h> 39 #include <sys/zio.h> 40 #include <sys/zio_compress.h> 41 #include <sys/zstd/zstd.h> 42 43 /* 44 * If nonzero, every 1/X decompression attempts will fail, simulating 45 * an undetected memory error. 46 */ 47 static unsigned long zio_decompress_fail_fraction = 0; 48 49 /* 50 * Compression vectors. 51 * 52 * NOTE: DO NOT CHANGE THE NAMES OF THESE COMPRESSION FUNCTIONS. 53 * THEY ARE USED AS ZAP KEY NAMES BY FAST DEDUP AND THEREFORE 54 * PART OF THE ON-DISK FORMAT. 55 */ 56 zio_compress_info_t zio_compress_table[ZIO_COMPRESS_FUNCTIONS] = { 57 {"inherit", 0, NULL, NULL, NULL}, 58 {"on", 0, NULL, NULL, NULL}, 59 {"uncompressed", 0, NULL, NULL, NULL}, 60 {"lzjb", 0, 61 zfs_lzjb_compress, zfs_lzjb_decompress, NULL}, 62 {"empty", 0, NULL, NULL, NULL}, 63 {"gzip-1", 1, 64 zfs_gzip_compress, zfs_gzip_decompress, NULL}, 65 {"gzip-2", 2, 66 zfs_gzip_compress, zfs_gzip_decompress, NULL}, 67 {"gzip-3", 3, 68 zfs_gzip_compress, zfs_gzip_decompress, NULL}, 69 {"gzip-4", 4, 70 zfs_gzip_compress, zfs_gzip_decompress, NULL}, 71 {"gzip-5", 5, 72 zfs_gzip_compress, zfs_gzip_decompress, NULL}, 73 {"gzip-6", 6, 74 zfs_gzip_compress, zfs_gzip_decompress, NULL}, 75 {"gzip-7", 7, 76 zfs_gzip_compress, zfs_gzip_decompress, NULL}, 77 {"gzip-8", 8, 78 zfs_gzip_compress, zfs_gzip_decompress, NULL}, 79 {"gzip-9", 9, 80 zfs_gzip_compress, zfs_gzip_decompress, NULL}, 81 {"zle", 64, 82 zfs_zle_compress, zfs_zle_decompress, NULL}, 83 {"lz4", 0, 84 zfs_lz4_compress, zfs_lz4_decompress, NULL}, 85 {"zstd", ZIO_ZSTD_LEVEL_DEFAULT, 86 zfs_zstd_compress, zfs_zstd_decompress, zfs_zstd_decompress_level}, 87 }; 88 89 uint8_t 90 zio_complevel_select(spa_t *spa, enum zio_compress compress, uint8_t child, 91 uint8_t parent) 92 { 93 (void) spa; 94 uint8_t result; 95 96 if (!ZIO_COMPRESS_HASLEVEL(compress)) 97 return (0); 98 99 result = child; 100 if (result == ZIO_COMPLEVEL_INHERIT) 101 result = parent; 102 103 return (result); 104 } 105 106 enum zio_compress 107 zio_compress_select(spa_t *spa, enum zio_compress child, 108 enum zio_compress parent) 109 { 110 enum zio_compress result; 111 112 ASSERT(child < ZIO_COMPRESS_FUNCTIONS); 113 ASSERT(parent < ZIO_COMPRESS_FUNCTIONS); 114 ASSERT(parent != ZIO_COMPRESS_INHERIT); 115 116 result = child; 117 if (result == ZIO_COMPRESS_INHERIT) 118 result = parent; 119 120 if (result == ZIO_COMPRESS_ON) { 121 if (spa_feature_is_active(spa, SPA_FEATURE_LZ4_COMPRESS)) 122 result = ZIO_COMPRESS_LZ4_ON_VALUE; 123 else 124 result = ZIO_COMPRESS_LEGACY_ON_VALUE; 125 } 126 127 return (result); 128 } 129 130 size_t 131 zio_compress_data(enum zio_compress c, abd_t *src, abd_t **dst, size_t s_len, 132 uint8_t level) 133 { 134 size_t c_len, d_len; 135 uint8_t complevel; 136 zio_compress_info_t *ci = &zio_compress_table[c]; 137 138 ASSERT3U(ci->ci_compress, !=, NULL); 139 ASSERT3U(s_len, >, 0); 140 141 complevel = ci->ci_level; 142 143 if (c == ZIO_COMPRESS_ZSTD) { 144 /* If we don't know the level, we can't compress it */ 145 if (level == ZIO_COMPLEVEL_INHERIT) 146 return (s_len); 147 148 if (level == ZIO_COMPLEVEL_DEFAULT) 149 complevel = ZIO_ZSTD_LEVEL_DEFAULT; 150 else 151 complevel = level; 152 153 ASSERT3U(complevel, !=, ZIO_COMPLEVEL_INHERIT); 154 } 155 156 if (*dst == NULL) 157 *dst = abd_alloc_sametype(src, s_len); 158 159 /* Compress at least 12.5%, but limit to the size of the dest abd. */ 160 d_len = MIN(s_len - (s_len >> 3), abd_get_size(*dst)); 161 162 c_len = ci->ci_compress(src, *dst, s_len, d_len, complevel); 163 164 if (c_len > d_len) 165 return (s_len); 166 167 ASSERT3U(c_len, <=, d_len); 168 return (c_len); 169 } 170 171 int 172 zio_decompress_data(enum zio_compress c, abd_t *src, abd_t *dst, 173 size_t s_len, size_t d_len, uint8_t *level) 174 { 175 zio_compress_info_t *ci = &zio_compress_table[c]; 176 if ((uint_t)c >= ZIO_COMPRESS_FUNCTIONS || ci->ci_decompress == NULL) 177 return (SET_ERROR(EINVAL)); 178 179 int err; 180 if (ci->ci_decompress_level != NULL && level != NULL) 181 err = ci->ci_decompress_level(src, dst, s_len, d_len, level); 182 else 183 err = ci->ci_decompress(src, dst, s_len, d_len, ci->ci_level); 184 185 /* 186 * Decompression shouldn't fail, because we've already verified 187 * the checksum. However, for extra protection (e.g. against bitflips 188 * in non-ECC RAM), we handle this error (and test it). 189 */ 190 if (zio_decompress_fail_fraction != 0 && 191 random_in_range(zio_decompress_fail_fraction) == 0) 192 err = SET_ERROR(EINVAL); 193 194 return (err); 195 } 196 197 int 198 zio_compress_to_feature(enum zio_compress comp) 199 { 200 switch (comp) { 201 case ZIO_COMPRESS_ZSTD: 202 return (SPA_FEATURE_ZSTD_COMPRESS); 203 default: 204 break; 205 } 206 return (SPA_FEATURE_NONE); 207 } 208