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