1fa9e4066Sahrens /* 2fa9e4066Sahrens * CDDL HEADER START 3fa9e4066Sahrens * 4fa9e4066Sahrens * The contents of this file are subject to the terms of the 55ad82045Snd150628 * Common Development and Distribution License (the "License"). 65ad82045Snd150628 * You may not use this file except in compliance with the License. 7fa9e4066Sahrens * 8fa9e4066Sahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9fa9e4066Sahrens * or http://www.opensolaris.org/os/licensing. 10fa9e4066Sahrens * See the License for the specific language governing permissions 11fa9e4066Sahrens * and limitations under the License. 12fa9e4066Sahrens * 13fa9e4066Sahrens * When distributing Covered Code, include this CDDL HEADER in each 14fa9e4066Sahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15fa9e4066Sahrens * If applicable, add the following below this CDDL HEADER, with the 16fa9e4066Sahrens * fields enclosed by brackets "[]" replaced with your own identifying 17fa9e4066Sahrens * information: Portions Copyright [yyyy] [name of copyright owner] 18fa9e4066Sahrens * 19fa9e4066Sahrens * CDDL HEADER END 20fa9e4066Sahrens */ 21c9431fa1Sahl 22fa9e4066Sahrens /* 23b24ab676SJeff Bonwick * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24fa9e4066Sahrens * Use is subject to license terms. 25fa9e4066Sahrens */ 26a6f561b4SSašo Kiselkov /* 27a6f561b4SSašo Kiselkov * Copyright (c) 2013 by Saso Kiselkov. All rights reserved. 28a6f561b4SSašo Kiselkov */ 29fa9e4066Sahrens 30be6fd75aSMatthew Ahrens /* 31be6fd75aSMatthew Ahrens * Copyright (c) 2013 by Delphix. All rights reserved. 32be6fd75aSMatthew Ahrens */ 33be6fd75aSMatthew Ahrens 34fa9e4066Sahrens #include <sys/zfs_context.h> 35fa9e4066Sahrens #include <sys/compress.h> 36fa9e4066Sahrens #include <sys/spa.h> 37*db1741f5SJustin T. Gibbs #include <sys/zfeature.h> 38fa9e4066Sahrens #include <sys/zio.h> 39fa9e4066Sahrens #include <sys/zio_compress.h> 40fa9e4066Sahrens 41fa9e4066Sahrens /* 42fa9e4066Sahrens * Compression vectors. 43fa9e4066Sahrens */ 44fa9e4066Sahrens 45fa9e4066Sahrens zio_compress_info_t zio_compress_table[ZIO_COMPRESS_FUNCTIONS] = { 46c9431fa1Sahl {NULL, NULL, 0, "inherit"}, 47c9431fa1Sahl {NULL, NULL, 0, "on"}, 48c9431fa1Sahl {NULL, NULL, 0, "uncompressed"}, 49c9431fa1Sahl {lzjb_compress, lzjb_decompress, 0, "lzjb"}, 50c9431fa1Sahl {NULL, NULL, 0, "empty"}, 51c9431fa1Sahl {gzip_compress, gzip_decompress, 1, "gzip-1"}, 52c9431fa1Sahl {gzip_compress, gzip_decompress, 2, "gzip-2"}, 53c9431fa1Sahl {gzip_compress, gzip_decompress, 3, "gzip-3"}, 54c9431fa1Sahl {gzip_compress, gzip_decompress, 4, "gzip-4"}, 55c9431fa1Sahl {gzip_compress, gzip_decompress, 5, "gzip-5"}, 56c9431fa1Sahl {gzip_compress, gzip_decompress, 6, "gzip-6"}, 57c9431fa1Sahl {gzip_compress, gzip_decompress, 7, "gzip-7"}, 58c9431fa1Sahl {gzip_compress, gzip_decompress, 8, "gzip-8"}, 59c9431fa1Sahl {gzip_compress, gzip_decompress, 9, "gzip-9"}, 60b24ab676SJeff Bonwick {zle_compress, zle_decompress, 64, "zle"}, 61a6f561b4SSašo Kiselkov {lz4_compress, lz4_decompress, 0, "lz4"}, 62fa9e4066Sahrens }; 63fa9e4066Sahrens 64b24ab676SJeff Bonwick enum zio_compress 65*db1741f5SJustin T. Gibbs zio_compress_select(spa_t *spa, enum zio_compress child, 66*db1741f5SJustin T. Gibbs enum zio_compress parent) 67fa9e4066Sahrens { 68*db1741f5SJustin T. Gibbs enum zio_compress result; 69*db1741f5SJustin T. Gibbs 70fa9e4066Sahrens ASSERT(child < ZIO_COMPRESS_FUNCTIONS); 71fa9e4066Sahrens ASSERT(parent < ZIO_COMPRESS_FUNCTIONS); 72*db1741f5SJustin T. Gibbs ASSERT(parent != ZIO_COMPRESS_INHERIT); 73fa9e4066Sahrens 74*db1741f5SJustin T. Gibbs result = child; 75*db1741f5SJustin T. Gibbs if (result == ZIO_COMPRESS_INHERIT) 76*db1741f5SJustin T. Gibbs result = parent; 77fa9e4066Sahrens 78*db1741f5SJustin T. Gibbs if (result == ZIO_COMPRESS_ON) { 79*db1741f5SJustin T. Gibbs if (spa_feature_is_active(spa, SPA_FEATURE_LZ4_COMPRESS)) 80*db1741f5SJustin T. Gibbs result = ZIO_COMPRESS_LZ4_ON_VALUE; 81*db1741f5SJustin T. Gibbs else 82*db1741f5SJustin T. Gibbs result = ZIO_COMPRESS_LEGACY_ON_VALUE; 83*db1741f5SJustin T. Gibbs } 84fa9e4066Sahrens 85*db1741f5SJustin T. Gibbs return (result); 86fa9e4066Sahrens } 87fa9e4066Sahrens 88b24ab676SJeff Bonwick size_t 89b24ab676SJeff Bonwick zio_compress_data(enum zio_compress c, void *src, void *dst, size_t s_len) 90fa9e4066Sahrens { 91fa9e4066Sahrens uint64_t *word, *word_end; 925d7b4d43SMatthew Ahrens size_t c_len, d_len; 93b24ab676SJeff Bonwick zio_compress_info_t *ci = &zio_compress_table[c]; 94fa9e4066Sahrens 95b24ab676SJeff Bonwick ASSERT((uint_t)c < ZIO_COMPRESS_FUNCTIONS); 96b24ab676SJeff Bonwick ASSERT((uint_t)c == ZIO_COMPRESS_EMPTY || ci->ci_compress != NULL); 97fa9e4066Sahrens 98fa9e4066Sahrens /* 99fa9e4066Sahrens * If the data is all zeroes, we don't even need to allocate 100b24ab676SJeff Bonwick * a block for it. We indicate this by returning zero size. 101fa9e4066Sahrens */ 102b24ab676SJeff Bonwick word_end = (uint64_t *)((char *)src + s_len); 103b24ab676SJeff Bonwick for (word = src; word < word_end; word++) 104b24ab676SJeff Bonwick if (*word != 0) 105fa9e4066Sahrens break; 106fa9e4066Sahrens 107b24ab676SJeff Bonwick if (word == word_end) 108416e0cd8Sek110237 return (0); 109416e0cd8Sek110237 110b24ab676SJeff Bonwick if (c == ZIO_COMPRESS_EMPTY) 111b24ab676SJeff Bonwick return (s_len); 112b24ab676SJeff Bonwick 113fa9e4066Sahrens /* Compress at least 12.5% */ 1145d7b4d43SMatthew Ahrens d_len = s_len - (s_len >> 3); 115b24ab676SJeff Bonwick c_len = ci->ci_compress(src, dst, s_len, d_len, ci->ci_level); 116b24ab676SJeff Bonwick 117b24ab676SJeff Bonwick if (c_len > d_len) 118b24ab676SJeff Bonwick return (s_len); 119b24ab676SJeff Bonwick 120b24ab676SJeff Bonwick ASSERT3U(c_len, <=, d_len); 121b24ab676SJeff Bonwick return (c_len); 122fa9e4066Sahrens } 123fa9e4066Sahrens 124fa9e4066Sahrens int 125b24ab676SJeff Bonwick zio_decompress_data(enum zio_compress c, void *src, void *dst, 126b24ab676SJeff Bonwick size_t s_len, size_t d_len) 127fa9e4066Sahrens { 128b24ab676SJeff Bonwick zio_compress_info_t *ci = &zio_compress_table[c]; 129c9431fa1Sahl 130b24ab676SJeff Bonwick if ((uint_t)c >= ZIO_COMPRESS_FUNCTIONS || ci->ci_decompress == NULL) 131be6fd75aSMatthew Ahrens return (SET_ERROR(EINVAL)); 132fa9e4066Sahrens 133b24ab676SJeff Bonwick return (ci->ci_decompress(src, dst, s_len, d_len, ci->ci_level)); 134fa9e4066Sahrens } 135