mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2024-12-26 19:19:32 +03:00
32dce2da0c
Currently, when ZFS wants to accelerate compression with QAT, it passes a destination buffer of the same size as the source buffer. Unfortunately, if the data is incompressible, QAT can actually "compress" the data to be larger than the source buffer. When this happens, the QAT driver will return a FAILED error code and print warnings to dmesg. This patch fixes these issues by providing the QAT driver with an additional buffer to work with so that even completely incompressible source data will not cause an overflow. This patch also resolves an error handling issue where incompressible data attempts compression twice: once by QAT and once in software. To fix this issue, a new (and fake) error code CPA_STATUS_INOMPRESSIBLE has been added so that the calling code can correctly account for the difference between a hardware failure and data that simply cannot be compressed. Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Reviewed-by: Weigang Li <weigang.li@intel.com> Signed-off-by: Tom Caputi <tcaputi@datto.com> Closes #7338
109 lines
2.6 KiB
C
109 lines
2.6 KiB
C
/*
|
|
* CDDL HEADER START
|
|
*
|
|
* The contents of this file are subject to the terms of the
|
|
* Common Development and Distribution License (the "License").
|
|
* You may not use this file except in compliance with the License.
|
|
*
|
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
|
* or http://www.opensolaris.org/os/licensing.
|
|
* See the License for the specific language governing permissions
|
|
* and limitations under the License.
|
|
*
|
|
* When distributing Covered Code, include this CDDL HEADER in each
|
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
|
* If applicable, add the following below this CDDL HEADER, with the
|
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
|
*
|
|
* CDDL HEADER END
|
|
*/
|
|
|
|
/*
|
|
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
|
|
* Use is subject to license terms.
|
|
*/
|
|
|
|
|
|
|
|
#include <sys/debug.h>
|
|
#include <sys/types.h>
|
|
#include "qat.h"
|
|
|
|
#ifdef _KERNEL
|
|
|
|
#include <sys/systm.h>
|
|
#include <sys/zmod.h>
|
|
|
|
typedef size_t zlen_t;
|
|
#define compress_func z_compress_level
|
|
#define uncompress_func z_uncompress
|
|
|
|
#else /* _KERNEL */
|
|
|
|
#include <strings.h>
|
|
#include <zlib.h>
|
|
|
|
typedef uLongf zlen_t;
|
|
#define compress_func compress2
|
|
#define uncompress_func uncompress
|
|
|
|
#endif
|
|
|
|
size_t
|
|
gzip_compress(void *s_start, void *d_start, size_t s_len, size_t d_len, int n)
|
|
{
|
|
int ret;
|
|
zlen_t dstlen = d_len;
|
|
|
|
ASSERT(d_len <= s_len);
|
|
|
|
/* check if hardware accelerator can be used */
|
|
if (qat_dc_use_accel(s_len)) {
|
|
ret = qat_compress(QAT_COMPRESS, s_start, s_len, d_start,
|
|
d_len, &dstlen);
|
|
if (ret == CPA_STATUS_SUCCESS) {
|
|
return ((size_t)dstlen);
|
|
} else if (ret == CPA_STATUS_INCOMPRESSIBLE) {
|
|
if (d_len != s_len)
|
|
return (s_len);
|
|
|
|
bcopy(s_start, d_start, s_len);
|
|
return (s_len);
|
|
}
|
|
/* if hardware compression fails, do it again with software */
|
|
}
|
|
|
|
if (compress_func(d_start, &dstlen, s_start, s_len, n) != Z_OK) {
|
|
if (d_len != s_len)
|
|
return (s_len);
|
|
|
|
bcopy(s_start, d_start, s_len);
|
|
return (s_len);
|
|
}
|
|
|
|
return ((size_t)dstlen);
|
|
}
|
|
|
|
/*ARGSUSED*/
|
|
int
|
|
gzip_decompress(void *s_start, void *d_start, size_t s_len, size_t d_len, int n)
|
|
{
|
|
zlen_t dstlen = d_len;
|
|
|
|
ASSERT(d_len >= s_len);
|
|
|
|
/* check if hardware accelerator can be used */
|
|
if (qat_dc_use_accel(d_len)) {
|
|
if (qat_compress(QAT_DECOMPRESS, s_start, s_len,
|
|
d_start, d_len, &dstlen) == CPA_STATUS_SUCCESS)
|
|
return (0);
|
|
/* if hardware de-compress fail, do it again with software */
|
|
}
|
|
|
|
if (uncompress_func(d_start, &dstlen, s_start, s_len) != Z_OK)
|
|
return (-1);
|
|
|
|
return (0);
|
|
}
|