summaryrefslogtreecommitdiffstats
path: root/src/compressor/zlib
diff options
context:
space:
mode:
Diffstat (limited to 'src/compressor/zlib')
-rw-r--r--src/compressor/zlib/CMakeLists.txt47
-rw-r--r--src/compressor/zlib/CompressionPluginZlib.cc38
-rw-r--r--src/compressor/zlib/CompressionPluginZlib.h54
-rw-r--r--src/compressor/zlib/ZlibCompressor.cc246
-rw-r--r--src/compressor/zlib/ZlibCompressor.h46
5 files changed, 431 insertions, 0 deletions
diff --git a/src/compressor/zlib/CMakeLists.txt b/src/compressor/zlib/CMakeLists.txt
new file mode 100644
index 00000000..51aba083
--- /dev/null
+++ b/src/compressor/zlib/CMakeLists.txt
@@ -0,0 +1,47 @@
+# zlib
+
+if(HAVE_INTEL_SSE4_1 AND HAVE_BETTER_YASM_ELF64 AND (NOT APPLE))
+ set(zlib_sources
+ CompressionPluginZlib.cc
+ ZlibCompressor.cc
+ ${CMAKE_SOURCE_DIR}/src/isa-l/igzip/crc32_gzip.asm
+ ${CMAKE_SOURCE_DIR}/src/isa-l/igzip/crc32_gzip_base.c
+ ${CMAKE_SOURCE_DIR}/src/isa-l/igzip/detect_repeated_char.asm
+ ${CMAKE_SOURCE_DIR}/src/isa-l/igzip/encode_df.c
+ ${CMAKE_SOURCE_DIR}/src/isa-l/igzip/encode_df_04.asm
+ ${CMAKE_SOURCE_DIR}/src/isa-l/igzip/flatten_ll.c
+ ${CMAKE_SOURCE_DIR}/src/isa-l/igzip/huff_codes.c
+ ${CMAKE_SOURCE_DIR}/src/isa-l/igzip/hufftables_c.c
+ ${CMAKE_SOURCE_DIR}/src/isa-l/igzip/igzip.c
+ ${CMAKE_SOURCE_DIR}/src/isa-l/igzip/igzip.c
+ ${CMAKE_SOURCE_DIR}/src/isa-l/igzip/igzip_base.c
+ ${CMAKE_SOURCE_DIR}/src/isa-l/igzip/igzip_body_01.asm
+ ${CMAKE_SOURCE_DIR}/src/isa-l/igzip/igzip_body_02.asm
+ ${CMAKE_SOURCE_DIR}/src/isa-l/igzip/igzip_body_04.asm
+ ${CMAKE_SOURCE_DIR}/src/isa-l/igzip/igzip_finish.asm
+ ${CMAKE_SOURCE_DIR}/src/isa-l/igzip/igzip_icf_base.c
+ ${CMAKE_SOURCE_DIR}/src/isa-l/igzip/igzip_icf_body_01.asm
+ ${CMAKE_SOURCE_DIR}/src/isa-l/igzip/igzip_icf_body_02.asm
+ ${CMAKE_SOURCE_DIR}/src/isa-l/igzip/igzip_icf_body_04.asm
+ ${CMAKE_SOURCE_DIR}/src/isa-l/igzip/igzip_icf_finish.asm
+ ${CMAKE_SOURCE_DIR}/src/isa-l/igzip/igzip_multibinary.asm
+ ${CMAKE_SOURCE_DIR}/src/isa-l/igzip/igzip_update_histogram_01.asm
+ ${CMAKE_SOURCE_DIR}/src/isa-l/igzip/igzip_update_histogram_04.asm
+ ${CMAKE_SOURCE_DIR}/src/isa-l/igzip/proc_heap.asm
+ ${CMAKE_SOURCE_DIR}/src/isa-l/igzip/rfc1951_lookup.asm
+ )
+else(HAVE_INTEL_SSE4_1 AND HAVE_BETTER_YASM_ELF64 AND (NOT APPLE))
+ set(zlib_sources
+ CompressionPluginZlib.cc
+ ZlibCompressor.cc
+ )
+endif(HAVE_INTEL_SSE4_1 AND HAVE_BETTER_YASM_ELF64 AND (NOT APPLE))
+
+add_library(ceph_zlib SHARED ${zlib_sources})
+target_link_libraries(ceph_zlib ZLIB::ZLIB)
+target_include_directories(ceph_zlib SYSTEM PRIVATE "${CMAKE_SOURCE_DIR}/src/isa-l/include")
+set_target_properties(ceph_zlib PROPERTIES
+ VERSION 2.0.0
+ SOVERSION 2
+ INSTALL_RPATH "")
+install(TARGETS ceph_zlib DESTINATION ${compressor_plugin_dir})
diff --git a/src/compressor/zlib/CompressionPluginZlib.cc b/src/compressor/zlib/CompressionPluginZlib.cc
new file mode 100644
index 00000000..2215b9a4
--- /dev/null
+++ b/src/compressor/zlib/CompressionPluginZlib.cc
@@ -0,0 +1,38 @@
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2015 Mirantis, Inc.
+ *
+ * Author: Alyona Kiseleva <akiselyova@mirantis.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ */
+
+
+// -----------------------------------------------------------------------------
+#include "acconfig.h"
+#include "ceph_ver.h"
+#include "common/ceph_context.h"
+#include "CompressionPluginZlib.h"
+
+// -----------------------------------------------------------------------------
+
+const char *__ceph_plugin_version()
+{
+ return CEPH_GIT_NICE_VER;
+}
+
+// -----------------------------------------------------------------------------
+
+int __ceph_plugin_init(CephContext *cct,
+ const std::string& type,
+ const std::string& name)
+{
+ PluginRegistry *instance = cct->get_plugin_registry();
+
+ return instance->add(type, name, new CompressionPluginZlib(cct));
+}
diff --git a/src/compressor/zlib/CompressionPluginZlib.h b/src/compressor/zlib/CompressionPluginZlib.h
new file mode 100644
index 00000000..38320c0c
--- /dev/null
+++ b/src/compressor/zlib/CompressionPluginZlib.h
@@ -0,0 +1,54 @@
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2015 Mirantis, Inc.
+ *
+ * Author: Alyona Kiseleva <akiselyova@mirantis.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ */
+
+#ifndef CEPH_COMPRESSION_PLUGIN_ZLIB_H
+#define CEPH_COMPRESSION_PLUGIN_ZLIB_H
+
+// -----------------------------------------------------------------------------
+#include "arch/probe.h"
+#include "arch/intel.h"
+#include "arch/arm.h"
+#include "compressor/CompressionPlugin.h"
+#include "ZlibCompressor.h"
+
+// -----------------------------------------------------------------------------
+
+class CompressionPluginZlib : public CompressionPlugin {
+public:
+ bool has_isal = false;
+
+ explicit CompressionPluginZlib(CephContext *cct) : CompressionPlugin(cct)
+ {}
+
+ int factory(CompressorRef *cs,
+ std::ostream *ss) override
+ {
+ bool isal = false;
+#if defined(__i386__) || defined(__x86_64__)
+ // other arches or lack of support result in isal = false
+ if (cct->_conf->compressor_zlib_isal) {
+ ceph_arch_probe();
+ isal = (ceph_arch_intel_pclmul && ceph_arch_intel_sse41);
+ }
+#endif
+ if (compressor == 0 || has_isal != isal) {
+ compressor = std::make_shared<ZlibCompressor>(cct, isal);
+ has_isal = isal;
+ }
+ *cs = compressor;
+ return 0;
+ }
+};
+
+#endif
diff --git a/src/compressor/zlib/ZlibCompressor.cc b/src/compressor/zlib/ZlibCompressor.cc
new file mode 100644
index 00000000..e3064d2a
--- /dev/null
+++ b/src/compressor/zlib/ZlibCompressor.cc
@@ -0,0 +1,246 @@
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2015 Mirantis, Inc.
+ *
+ * Author: Alyona Kiseleva <akiselyova@mirantis.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ */
+
+// -----------------------------------------------------------------------------
+#include "common/debug.h"
+#include "ZlibCompressor.h"
+#include "osd/osd_types.h"
+#include "isa-l/include/igzip_lib.h"
+// -----------------------------------------------------------------------------
+
+#include <zlib.h>
+
+// -----------------------------------------------------------------------------
+#define dout_context cct
+#define dout_subsys ceph_subsys_compressor
+#undef dout_prefix
+#define dout_prefix _prefix(_dout)
+// -----------------------------------------------------------------------------
+
+// -----------------------------------------------------------------------------
+
+static ostream&
+_prefix(std::ostream* _dout)
+{
+ return *_dout << "ZlibCompressor: ";
+}
+// -----------------------------------------------------------------------------
+
+#define MAX_LEN (CEPH_PAGE_SIZE)
+
+// default window size for Zlib 1.2.8, negated for raw deflate
+#define ZLIB_DEFAULT_WIN_SIZE -15
+
+// desired memory usage level. increasing to 9 doesn't speed things up
+// significantly (helps only on >=16K blocks) and sometimes degrades
+// compression ratio.
+#define ZLIB_MEMORY_LEVEL 8
+
+int ZlibCompressor::zlib_compress(const bufferlist &in, bufferlist &out)
+{
+ int ret;
+ unsigned have;
+ z_stream strm;
+ unsigned char* c_in;
+ int begin = 1;
+
+ /* allocate deflate state */
+ strm.zalloc = Z_NULL;
+ strm.zfree = Z_NULL;
+ strm.opaque = Z_NULL;
+ ret = deflateInit2(&strm, cct->_conf->compressor_zlib_level, Z_DEFLATED, ZLIB_DEFAULT_WIN_SIZE, ZLIB_MEMORY_LEVEL, Z_DEFAULT_STRATEGY);
+ if (ret != Z_OK) {
+ dout(1) << "Compression init error: init return "
+ << ret << " instead of Z_OK" << dendl;
+ return -1;
+ }
+
+ for (ceph::bufferlist::buffers_t::const_iterator i = in.buffers().begin();
+ i != in.buffers().end();) {
+
+ c_in = (unsigned char*) (*i).c_str();
+ long unsigned int len = (*i).length();
+ ++i;
+
+ strm.avail_in = len;
+ int flush = i != in.buffers().end() ? Z_NO_FLUSH : Z_FINISH;
+
+ strm.next_in = c_in;
+ do {
+ bufferptr ptr = buffer::create_page_aligned(MAX_LEN);
+ strm.next_out = (unsigned char*)ptr.c_str() + begin;
+ strm.avail_out = MAX_LEN - begin;
+ if (begin) {
+ // put a compressor variation mark in front of compressed stream, not used at the moment
+ ptr.c_str()[0] = 0;
+ begin = 0;
+ }
+ ret = deflate(&strm, flush); /* no bad return value */
+ if (ret == Z_STREAM_ERROR) {
+ dout(1) << "Compression error: compress return Z_STREAM_ERROR("
+ << ret << ")" << dendl;
+ deflateEnd(&strm);
+ return -1;
+ }
+ have = MAX_LEN - strm.avail_out;
+ out.append(ptr, 0, have);
+ } while (strm.avail_out == 0);
+ if (strm.avail_in != 0) {
+ dout(10) << "Compression error: unused input" << dendl;
+ deflateEnd(&strm);
+ return -1;
+ }
+ }
+
+ deflateEnd(&strm);
+ return 0;
+}
+
+#if __x86_64__ && defined(HAVE_BETTER_YASM_ELF64)
+int ZlibCompressor::isal_compress(const bufferlist &in, bufferlist &out)
+{
+ int ret;
+ unsigned have;
+ isal_zstream strm;
+ unsigned char* c_in;
+ int begin = 1;
+
+ /* allocate deflate state */
+ isal_deflate_init(&strm);
+ strm.end_of_stream = 0;
+
+ for (ceph::bufferlist::buffers_t::const_iterator i = in.buffers().begin();
+ i != in.buffers().end();) {
+
+ c_in = (unsigned char*) (*i).c_str();
+ long unsigned int len = (*i).length();
+ ++i;
+
+ strm.avail_in = len;
+ strm.end_of_stream = (i == in.buffers().end());
+ strm.flush = FINISH_FLUSH;
+
+ strm.next_in = c_in;
+
+ do {
+ bufferptr ptr = buffer::create_page_aligned(MAX_LEN);
+ strm.next_out = (unsigned char*)ptr.c_str() + begin;
+ strm.avail_out = MAX_LEN - begin;
+ if (begin) {
+ // put a compressor variation mark in front of compressed stream, not used at the moment
+ ptr.c_str()[0] = 1;
+ begin = 0;
+ }
+ ret = isal_deflate(&strm);
+ if (ret != COMP_OK) {
+ dout(1) << "Compression error: isal_deflate return error ("
+ << ret << ")" << dendl;
+ return -1;
+ }
+ have = MAX_LEN - strm.avail_out;
+ out.append(ptr, 0, have);
+ } while (strm.avail_out == 0);
+ if (strm.avail_in != 0) {
+ dout(10) << "Compression error: unused input" << dendl;
+ return -1;
+ }
+ }
+
+ return 0;
+}
+#endif
+
+int ZlibCompressor::compress(const bufferlist &in, bufferlist &out)
+{
+#ifdef HAVE_QATZIP
+ if (qat_enabled)
+ return qat_accel.compress(in, out);
+#endif
+#if __x86_64__ && defined(HAVE_BETTER_YASM_ELF64)
+ if (isal_enabled)
+ return isal_compress(in, out);
+ else
+ return zlib_compress(in, out);
+#else
+ return zlib_compress(in, out);
+#endif
+}
+
+int ZlibCompressor::decompress(bufferlist::const_iterator &p, size_t compressed_size, bufferlist &out)
+{
+#ifdef HAVE_QATZIP
+ if (qat_enabled)
+ return qat_accel.decompress(p, compressed_size, out);
+#endif
+
+ int ret;
+ unsigned have;
+ z_stream strm;
+ const char* c_in;
+ int begin = 1;
+
+ /* allocate inflate state */
+ strm.zalloc = Z_NULL;
+ strm.zfree = Z_NULL;
+ strm.opaque = Z_NULL;
+ strm.avail_in = 0;
+ strm.next_in = Z_NULL;
+
+ // choose the variation of compressor
+ ret = inflateInit2(&strm, ZLIB_DEFAULT_WIN_SIZE);
+ if (ret != Z_OK) {
+ dout(1) << "Decompression init error: init return "
+ << ret << " instead of Z_OK" << dendl;
+ return -1;
+ }
+
+ size_t remaining = std::min<size_t>(p.get_remaining(), compressed_size);
+
+ while(remaining) {
+ long unsigned int len = p.get_ptr_and_advance(remaining, &c_in);
+ remaining -= len;
+ strm.avail_in = len - begin;
+ strm.next_in = (unsigned char*)c_in + begin;
+ begin = 0;
+
+ do {
+ strm.avail_out = MAX_LEN;
+ bufferptr ptr = buffer::create_page_aligned(MAX_LEN);
+ strm.next_out = (unsigned char*)ptr.c_str();
+ ret = inflate(&strm, Z_NO_FLUSH);
+ if (ret != Z_OK && ret != Z_STREAM_END && ret != Z_BUF_ERROR) {
+ dout(1) << "Decompression error: decompress return "
+ << ret << dendl;
+ inflateEnd(&strm);
+ return -1;
+ }
+ have = MAX_LEN - strm.avail_out;
+ out.append(ptr, 0, have);
+ } while (strm.avail_out == 0);
+ }
+
+ /* clean up and return */
+ (void)inflateEnd(&strm);
+ return 0;
+}
+
+int ZlibCompressor::decompress(const bufferlist &in, bufferlist &out)
+{
+#ifdef HAVE_QATZIP
+ if (qat_enabled)
+ return qat_accel.decompress(in, out);
+#endif
+ auto i = std::cbegin(in);
+ return decompress(i, in.length(), out);
+}
diff --git a/src/compressor/zlib/ZlibCompressor.h b/src/compressor/zlib/ZlibCompressor.h
new file mode 100644
index 00000000..d770547a
--- /dev/null
+++ b/src/compressor/zlib/ZlibCompressor.h
@@ -0,0 +1,46 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2015 Mirantis, Inc.
+ *
+ * Author: Alyona Kiseleva <akiselyova@mirantis.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ */
+
+#ifndef CEPH_COMPRESSION_ZLIB_H
+#define CEPH_COMPRESSION_ZLIB_H
+
+#include "common/config.h"
+#include "compressor/Compressor.h"
+
+class ZlibCompressor : public Compressor {
+ bool isal_enabled;
+ CephContext *const cct;
+public:
+ ZlibCompressor(CephContext *cct, bool isal)
+ : Compressor(COMP_ALG_ZLIB, "zlib"), isal_enabled(isal), cct(cct) {
+#ifdef HAVE_QATZIP
+ if (cct->_conf->qat_compressor_enabled && qat_accel.init("zlib"))
+ qat_enabled = true;
+ else
+ qat_enabled = false;
+#endif
+ }
+
+ int compress(const bufferlist &in, bufferlist &out) override;
+ int decompress(const bufferlist &in, bufferlist &out) override;
+ int decompress(bufferlist::const_iterator &p, size_t compressed_len, bufferlist &out) override;
+private:
+ int zlib_compress(const bufferlist &in, bufferlist &out);
+ int isal_compress(const bufferlist &in, bufferlist &out);
+ };
+
+
+#endif