FreeBSD ZFS
The Zettabyte File System
|
00001 /* 00002 * CDDL HEADER START 00003 * 00004 * The contents of this file are subject to the terms of the 00005 * Common Development and Distribution License (the "License"). 00006 * You may not use this file except in compliance with the License. 00007 * 00008 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 00009 * or http://www.opensolaris.org/os/licensing. 00010 * See the License for the specific language governing permissions 00011 * and limitations under the License. 00012 * 00013 * When distributing Covered Code, include this CDDL HEADER in each 00014 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 00015 * If applicable, add the following below this CDDL HEADER, with the 00016 * fields enclosed by brackets "[]" replaced with your own identifying 00017 * information: Portions Copyright [yyyy] [name of copyright owner] 00018 * 00019 * CDDL HEADER END 00020 */ 00021 00022 /* 00023 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 00024 * Use is subject to license terms. 00025 */ 00026 00027 #include <sys/zfs_context.h> 00028 #include <sys/compress.h> 00029 #include <sys/spa.h> 00030 #include <sys/zio.h> 00031 #include <sys/zio_compress.h> 00032 00033 /* 00034 * Compression vectors. 00035 */ 00036 00037 zio_compress_info_t zio_compress_table[ZIO_COMPRESS_FUNCTIONS] = { 00038 {NULL, NULL, 0, "inherit"}, 00039 {NULL, NULL, 0, "on"}, 00040 {NULL, NULL, 0, "uncompressed"}, 00041 {lzjb_compress, lzjb_decompress, 0, "lzjb"}, 00042 {NULL, NULL, 0, "empty"}, 00043 {gzip_compress, gzip_decompress, 1, "gzip-1"}, 00044 {gzip_compress, gzip_decompress, 2, "gzip-2"}, 00045 {gzip_compress, gzip_decompress, 3, "gzip-3"}, 00046 {gzip_compress, gzip_decompress, 4, "gzip-4"}, 00047 {gzip_compress, gzip_decompress, 5, "gzip-5"}, 00048 {gzip_compress, gzip_decompress, 6, "gzip-6"}, 00049 {gzip_compress, gzip_decompress, 7, "gzip-7"}, 00050 {gzip_compress, gzip_decompress, 8, "gzip-8"}, 00051 {gzip_compress, gzip_decompress, 9, "gzip-9"}, 00052 {zle_compress, zle_decompress, 64, "zle"}, 00053 }; 00054 00055 enum zio_compress 00056 zio_compress_select(enum zio_compress child, enum zio_compress parent) 00057 { 00058 ASSERT(child < ZIO_COMPRESS_FUNCTIONS); 00059 ASSERT(parent < ZIO_COMPRESS_FUNCTIONS); 00060 ASSERT(parent != ZIO_COMPRESS_INHERIT && parent != ZIO_COMPRESS_ON); 00061 00062 if (child == ZIO_COMPRESS_INHERIT) 00063 return (parent); 00064 00065 if (child == ZIO_COMPRESS_ON) 00066 return (ZIO_COMPRESS_ON_VALUE); 00067 00068 return (child); 00069 } 00070 00071 size_t 00072 zio_compress_data(enum zio_compress c, void *src, void *dst, size_t s_len) 00073 { 00074 uint64_t *word, *word_end; 00075 size_t c_len, d_len, r_len; 00076 zio_compress_info_t *ci = &zio_compress_table[c]; 00077 00078 ASSERT((uint_t)c < ZIO_COMPRESS_FUNCTIONS); 00079 ASSERT((uint_t)c == ZIO_COMPRESS_EMPTY || ci->ci_compress != NULL); 00080 00081 /* 00082 * If the data is all zeroes, we don't even need to allocate 00083 * a block for it. We indicate this by returning zero size. 00084 */ 00085 word_end = (uint64_t *)((char *)src + s_len); 00086 for (word = src; word < word_end; word++) 00087 if (*word != 0) 00088 break; 00089 00090 if (word == word_end) 00091 return (0); 00092 00093 if (c == ZIO_COMPRESS_EMPTY) 00094 return (s_len); 00095 00096 /* Compress at least 12.5% */ 00097 d_len = P2ALIGN(s_len - (s_len >> 3), (size_t)SPA_MINBLOCKSIZE); 00098 if (d_len == 0) 00099 return (s_len); 00100 00101 c_len = ci->ci_compress(src, dst, s_len, d_len, ci->ci_level); 00102 00103 if (c_len > d_len) 00104 return (s_len); 00105 00106 /* 00107 * Cool. We compressed at least as much as we were hoping to. 00108 * For both security and repeatability, pad out the last sector. 00109 */ 00110 r_len = P2ROUNDUP(c_len, (size_t)SPA_MINBLOCKSIZE); 00111 if (r_len > c_len) { 00112 bzero((char *)dst + c_len, r_len - c_len); 00113 c_len = r_len; 00114 } 00115 00116 ASSERT3U(c_len, <=, d_len); 00117 ASSERT(P2PHASE(c_len, (size_t)SPA_MINBLOCKSIZE) == 0); 00118 00119 return (c_len); 00120 } 00121 00122 int 00123 zio_decompress_data(enum zio_compress c, void *src, void *dst, 00124 size_t s_len, size_t d_len) 00125 { 00126 zio_compress_info_t *ci = &zio_compress_table[c]; 00127 00128 if ((uint_t)c >= ZIO_COMPRESS_FUNCTIONS || ci->ci_decompress == NULL) 00129 return (EINVAL); 00130 00131 return (ci->ci_decompress(src, dst, s_len, d_len, ci->ci_level)); 00132 }