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 http://www.opensolaris.org/os/licensing. 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, 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 unsigned long zio_decompress_fail_fraction = 0; 48 49 /* 50 * Compression vectors. 51 */ 52 zio_compress_info_t zio_compress_table[ZIO_COMPRESS_FUNCTIONS] = { 53 {"inherit", 0, NULL, NULL, NULL}, 54 {"on", 0, NULL, NULL, NULL}, 55 {"uncompressed", 0, NULL, NULL, NULL}, 56 {"lzjb", 0, lzjb_compress, lzjb_decompress, NULL}, 57 {"empty", 0, NULL, NULL, NULL}, 58 {"gzip-1", 1, gzip_compress, gzip_decompress, NULL}, 59 {"gzip-2", 2, gzip_compress, gzip_decompress, NULL}, 60 {"gzip-3", 3, gzip_compress, gzip_decompress, NULL}, 61 {"gzip-4", 4, gzip_compress, gzip_decompress, NULL}, 62 {"gzip-5", 5, gzip_compress, gzip_decompress, NULL}, 63 {"gzip-6", 6, gzip_compress, gzip_decompress, NULL}, 64 {"gzip-7", 7, gzip_compress, gzip_decompress, NULL}, 65 {"gzip-8", 8, gzip_compress, gzip_decompress, NULL}, 66 {"gzip-9", 9, gzip_compress, gzip_decompress, NULL}, 67 {"zle", 64, zle_compress, zle_decompress, NULL}, 68 {"lz4", 0, lz4_compress_zfs, lz4_decompress_zfs, NULL}, 69 {"zstd", ZIO_ZSTD_LEVEL_DEFAULT, zfs_zstd_compress, 70 zfs_zstd_decompress, zfs_zstd_decompress_level}, 71 }; 72 73 uint8_t 74 zio_complevel_select(spa_t *spa, enum zio_compress compress, uint8_t child, 75 uint8_t parent) 76 { 77 uint8_t result; 78 79 if (!ZIO_COMPRESS_HASLEVEL(compress)) 80 return (0); 81 82 result = child; 83 if (result == ZIO_COMPLEVEL_INHERIT) 84 result = parent; 85 86 return (result); 87 } 88 89 enum zio_compress 90 zio_compress_select(spa_t *spa, enum zio_compress child, 91 enum zio_compress parent) 92 { 93 enum zio_compress result; 94 95 ASSERT(child < ZIO_COMPRESS_FUNCTIONS); 96 ASSERT(parent < ZIO_COMPRESS_FUNCTIONS); 97 ASSERT(parent != ZIO_COMPRESS_INHERIT); 98 99 result = child; 100 if (result == ZIO_COMPRESS_INHERIT) 101 result = parent; 102 103 if (result == ZIO_COMPRESS_ON) { 104 if (spa_feature_is_active(spa, SPA_FEATURE_LZ4_COMPRESS)) 105 result = ZIO_COMPRESS_LZ4_ON_VALUE; 106 else 107 result = ZIO_COMPRESS_LEGACY_ON_VALUE; 108 } 109 110 return (result); 111 } 112 113 /*ARGSUSED*/ 114 static int 115 zio_compress_zeroed_cb(void *data, size_t len, void *private) 116 { 117 uint64_t *end = (uint64_t *)((char *)data + len); 118 for (uint64_t *word = (uint64_t *)data; word < end; word++) 119 if (*word != 0) 120 return (1); 121 122 return (0); 123 } 124 125 size_t 126 zio_compress_data(enum zio_compress c, abd_t *src, void *dst, size_t s_len, 127 uint8_t level) 128 { 129 size_t c_len, d_len; 130 uint8_t complevel; 131 zio_compress_info_t *ci = &zio_compress_table[c]; 132 133 ASSERT((uint_t)c < ZIO_COMPRESS_FUNCTIONS); 134 ASSERT((uint_t)c == ZIO_COMPRESS_EMPTY || ci->ci_compress != NULL); 135 136 /* 137 * If the data is all zeroes, we don't even need to allocate 138 * a block for it. We indicate this by returning zero size. 139 */ 140 if (abd_iterate_func(src, 0, s_len, zio_compress_zeroed_cb, NULL) == 0) 141 return (0); 142 143 if (c == ZIO_COMPRESS_EMPTY) 144 return (s_len); 145 146 /* Compress at least 12.5% */ 147 d_len = s_len - (s_len >> 3); 148 149 complevel = ci->ci_level; 150 151 if (c == ZIO_COMPRESS_ZSTD) { 152 /* If we don't know the level, we can't compress it */ 153 if (level == ZIO_COMPLEVEL_INHERIT) 154 return (s_len); 155 156 if (level == ZIO_COMPLEVEL_DEFAULT) 157 complevel = ZIO_ZSTD_LEVEL_DEFAULT; 158 else 159 complevel = level; 160 161 ASSERT3U(complevel, !=, ZIO_COMPLEVEL_INHERIT); 162 } 163 164 /* No compression algorithms can read from ABDs directly */ 165 void *tmp = abd_borrow_buf_copy(src, s_len); 166 c_len = ci->ci_compress(tmp, dst, s_len, d_len, complevel); 167 abd_return_buf(src, tmp, s_len); 168 169 if (c_len > d_len) 170 return (s_len); 171 172 ASSERT3U(c_len, <=, d_len); 173 return (c_len); 174 } 175 176 int 177 zio_decompress_data_buf(enum zio_compress c, void *src, void *dst, 178 size_t s_len, size_t d_len, uint8_t *level) 179 { 180 zio_compress_info_t *ci = &zio_compress_table[c]; 181 if ((uint_t)c >= ZIO_COMPRESS_FUNCTIONS || ci->ci_decompress == NULL) 182 return (SET_ERROR(EINVAL)); 183 184 if (ci->ci_decompress_level != NULL && level != NULL) 185 return (ci->ci_decompress_level(src, dst, s_len, d_len, level)); 186 187 return (ci->ci_decompress(src, dst, s_len, d_len, ci->ci_level)); 188 } 189 190 int 191 zio_decompress_data(enum zio_compress c, abd_t *src, void *dst, 192 size_t s_len, size_t d_len, uint8_t *level) 193 { 194 void *tmp = abd_borrow_buf_copy(src, s_len); 195 int ret = zio_decompress_data_buf(c, tmp, dst, s_len, d_len, level); 196 abd_return_buf(src, tmp, s_len); 197 198 /* 199 * Decompression shouldn't fail, because we've already verified 200 * the checksum. However, for extra protection (e.g. against bitflips 201 * in non-ECC RAM), we handle this error (and test it). 202 */ 203 if (zio_decompress_fail_fraction != 0 && 204 random_in_range(zio_decompress_fail_fraction) == 0) 205 ret = SET_ERROR(EINVAL); 206 207 return (ret); 208 } 209 210 int 211 zio_compress_to_feature(enum zio_compress comp) 212 { 213 switch (comp) { 214 case ZIO_COMPRESS_ZSTD: 215 return (SPA_FEATURE_ZSTD_COMPRESS); 216 default: 217 /* fallthru */; 218 } 219 return (SPA_FEATURE_NONE); 220 } 221