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