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 size_t 115 zio_compress_data(enum zio_compress c, abd_t *src, void **dst, size_t s_len, 116 uint8_t level) 117 { 118 size_t c_len, d_len; 119 uint8_t complevel; 120 zio_compress_info_t *ci = &zio_compress_table[c]; 121 122 ASSERT3U(c, <, ZIO_COMPRESS_FUNCTIONS); 123 ASSERT3U(ci->ci_compress, !=, NULL); 124 ASSERT3U(s_len, >, 0); 125 126 /* Compress at least 12.5% */ 127 d_len = s_len - (s_len >> 3); 128 129 complevel = ci->ci_level; 130 131 if (c == ZIO_COMPRESS_ZSTD) { 132 /* If we don't know the level, we can't compress it */ 133 if (level == ZIO_COMPLEVEL_INHERIT) 134 return (s_len); 135 136 if (level == ZIO_COMPLEVEL_DEFAULT) 137 complevel = ZIO_ZSTD_LEVEL_DEFAULT; 138 else 139 complevel = level; 140 141 ASSERT3U(complevel, !=, ZIO_COMPLEVEL_INHERIT); 142 } 143 144 if (*dst == NULL) 145 *dst = zio_buf_alloc(s_len); 146 147 /* No compression algorithms can read from ABDs directly */ 148 void *tmp = abd_borrow_buf_copy(src, s_len); 149 c_len = ci->ci_compress(tmp, *dst, s_len, d_len, complevel); 150 abd_return_buf(src, tmp, s_len); 151 152 if (c_len > d_len) 153 return (s_len); 154 155 ASSERT3U(c_len, <=, d_len); 156 return (c_len); 157 } 158 159 int 160 zio_decompress_data_buf(enum zio_compress c, void *src, void *dst, 161 size_t s_len, size_t d_len, uint8_t *level) 162 { 163 zio_compress_info_t *ci = &zio_compress_table[c]; 164 if ((uint_t)c >= ZIO_COMPRESS_FUNCTIONS || ci->ci_decompress == NULL) 165 return (SET_ERROR(EINVAL)); 166 167 if (ci->ci_decompress_level != NULL && level != NULL) 168 return (ci->ci_decompress_level(src, dst, s_len, d_len, level)); 169 170 return (ci->ci_decompress(src, dst, s_len, d_len, ci->ci_level)); 171 } 172 173 int 174 zio_decompress_data(enum zio_compress c, abd_t *src, void *dst, 175 size_t s_len, size_t d_len, uint8_t *level) 176 { 177 void *tmp = abd_borrow_buf_copy(src, s_len); 178 int ret = zio_decompress_data_buf(c, tmp, dst, s_len, d_len, level); 179 abd_return_buf(src, tmp, s_len); 180 181 /* 182 * Decompression shouldn't fail, because we've already verified 183 * the checksum. However, for extra protection (e.g. against bitflips 184 * in non-ECC RAM), we handle this error (and test it). 185 */ 186 if (zio_decompress_fail_fraction != 0 && 187 random_in_range(zio_decompress_fail_fraction) == 0) 188 ret = SET_ERROR(EINVAL); 189 190 return (ret); 191 } 192 193 int 194 zio_compress_to_feature(enum zio_compress comp) 195 { 196 switch (comp) { 197 case ZIO_COMPRESS_ZSTD: 198 return (SPA_FEATURE_ZSTD_COMPRESS); 199 default: 200 break; 201 } 202 return (SPA_FEATURE_NONE); 203 } 204