LZF Cryptoapi support.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi again.

Here's another resend, this time adding an lzf cryptoapi module.

LZF is a very fast compressor which typically achieves approximately 50%
compression on a suspend image. The original author (Marc Alexander
Lehmann) donated it to Suspend2. I have converted it to cryptoapi with a
recent switch of Suspend2 to use cryptoapi.

Regards,

Nigel

 Kconfig  |    7 +
 Makefile |    1 
 lzf.c    |  425 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 433 insertions(+)
diff -ruNp 625-crypto-api-work.patch-old/crypto/Kconfig 625-crypto-api-work.patch-new/crypto/Kconfig
--- 625-crypto-api-work.patch-old/crypto/Kconfig	2005-06-20 11:46:49.000000000 +1000
+++ 625-crypto-api-work.patch-new/crypto/Kconfig	2005-07-06 11:51:06.000000000 +1000
@@ -262,6 +262,13 @@ config CRYPTO_DEFLATE
 	  
 	  You will most probably want this if using IPSec.
 
+config CRYPTO_LZF
+	tristate "LZF compression algorithm"
+	depends on CRYPTO
+	help
+	  This is the LZF algorithm. It is especially useful for Suspend2,
+	  because it achieves good compression quickly.
+
 config CRYPTO_MICHAEL_MIC
 	tristate "Michael MIC keyed digest algorithm"
 	depends on CRYPTO
diff -ruNp 625-crypto-api-work.patch-old/crypto/lzf.c 625-crypto-api-work.patch-new/crypto/lzf.c
--- 625-crypto-api-work.patch-old/crypto/lzf.c	1970-01-01 10:00:00.000000000 +1000
+++ 625-crypto-api-work.patch-new/crypto/lzf.c	2005-07-06 22:10:55.000000000 +1000
@@ -0,0 +1,425 @@
+/* 
+ * Cryptoapi LZF compression module.
+ *
+ * Copyright (c) 2004-2005 Nigel Cunningham <[email protected]>
+ *
+ * based on the deflate.c file:
+ * 
+ * Copyright (c) 2003 James Morris <[email protected]>
+ * 
+ * and upon the LZF compression module donated to the Suspend2 project with
+ * the following copyright:
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option) 
+ * any later version.
+ * Copyright (c) 2000-2003 Marc Alexander Lehmann <[email protected]>
+ * 
+ * Redistribution and use in source and binary forms, with or without modifica-
+ * tion, are permitted provided that the following conditions are met:
+ * 
+ *   1.  Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ * 
+ *   2.  Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ * 
+ *   3.  The name of the author may not be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
+ * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
+ * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-
+ * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * the GNU General Public License version 2 (the "GPL"), in which case the
+ * provisions of the GPL are applicable instead of the above. If you wish to
+ * allow the use of your version of this file only under the terms of the
+ * GPL and not to allow others to use your version of this file under the
+ * BSD license, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the GPL. If
+ * you do not delete the provisions above, a recipient may use your version
+ * of this file under either the BSD or the GPL.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/crypto.h>
+#include <linux/err.h>
+#include <linux/vmalloc.h>
+#include <asm/string.h>
+
+struct lzf_ctx {
+	void *hbuf;
+	char *local_buffer;
+	char *page_buffer;
+	unsigned int bufofs;
+	int first_call;
+};
+
+/*
+ * size of hashtable is (1 << HLOG) * sizeof (char *)
+ * decompression is independent of the hash table size
+ * the difference between 15 and 14 is very small
+ * for small blocks (and 14 is also faster).
+ * For a low-memory configuration, use HLOG == 13;
+ * For best compression, use 15 or 16.
+ */
+#define HLOG 14
+
+/*
+ * sacrifice some compression quality in favour of compression speed.
+ * (roughly 1-2% worse compression for large blocks and
+ * 9-10% for small, redundant, blocks and >>20% better speed in both cases)
+ * In short: enable this for binary data, disable this for text data.
+ */
+#define ULTRA_FAST 1
+
+#define STRICT_ALIGN 0
+#define USE_MEMCPY 1
+#define INIT_HTAB 0
+
+#define HSIZE (1 << (HLOG))
+
+/*
+ * don't play with this unless you benchmark!
+ * decompression is not dependent on the hash function
+ * the hashing function might seem strange, just believe me
+ * it works ;)
+ */
+#define FRST(p) (((p[0]) << 8) + p[1])
+#define NEXT(v,p) (((v) << 8) + p[2])
+#define IDX(h) ((((h ^ (h << 5)) >> (3*8 - HLOG)) + h*3) & (HSIZE - 1))
+/*
+ * IDX works because it is very similar to a multiplicative hash, e.g.
+ * (h * 57321 >> (3*8 - HLOG))
+ * the next one is also quite good, albeit slow ;)
+ * (int)(cos(h & 0xffffff) * 1e6)
+ */
+
+#if 0
+/* original lzv-like hash function */
+# define FRST(p) (p[0] << 5) ^ p[1]
+# define NEXT(v,p) ((v) << 5) ^ p[2]
+# define IDX(h) ((h) & (HSIZE - 1))
+#endif
+
+#define MAX_LIT (1 <<  5)
+#define MAX_OFF (1 << 13)
+#define MAX_REF ((1 <<  8) + (1 << 3))
+
+/*
+ * compressed format
+ *
+ * 000LLLLL <L+1>    ; literal
+ * LLLOOOOO oooooooo ; backref L
+ * 111OOOOO LLLLLLLL oooooooo ; backref L+7
+ *
+ */
+
+static void lzf_compress_exit(void *context)
+{
+	struct lzf_ctx *ctx = (struct lzf_ctx *)context;
+
+	if (ctx->local_buffer) {
+		free_page((unsigned long)ctx->local_buffer);
+		ctx->local_buffer = NULL;
+	}
+
+	if (ctx->page_buffer) {
+		free_page((unsigned long)ctx->page_buffer);
+		ctx->page_buffer = NULL;
+	}
+
+	if (ctx->hbuf) {
+		vfree(ctx->hbuf);
+		ctx->hbuf = NULL;
+	}
+
+	ctx->first_call = 0;
+}
+
+static int lzf_compress_init(void *context)
+{
+	struct lzf_ctx *ctx = (struct lzf_ctx *)context;
+
+	/* Get LZF ready to go */
+	ctx->hbuf = vmalloc_32((1 << HLOG) * sizeof(char *));
+	if (!ctx->hbuf) {
+		printk(KERN_WARNING
+		       "Failed to allocate %d bytes for lzf workspace\n",
+		       (1 << HLOG) * sizeof(char *));
+		return -ENOMEM;
+	}
+
+	/* Allocate local buffer */
+	ctx->local_buffer = (char *)get_zeroed_page(GFP_ATOMIC);
+
+	if (!ctx->local_buffer) {
+		lzf_compress_exit(ctx);
+		return -ENOMEM;
+	}
+
+	/* Allocate page buffer */
+	ctx->page_buffer = (char *)get_zeroed_page(GFP_ATOMIC);
+
+	if (!ctx->page_buffer) {
+		free_page((unsigned long)ctx->local_buffer);
+		lzf_compress_exit(ctx);
+		return -ENOMEM;
+	}
+
+	ctx->first_call = 1;
+
+	return 0;
+}
+
+static int lzf_compress(void *context, const u8 * in_data, unsigned int in_len,
+			u8 * out_data, unsigned int *out_len)
+{
+	struct lzf_ctx *ctx = (struct lzf_ctx *)context;
+	const u8 **htab = ctx->hbuf;
+	const u8 **hslot;
+	const u8 *ip = in_data;
+	u8 *op = out_data;
+	const u8 *in_end = ip + in_len;
+	u8 *out_end = op + *out_len - 3;
+	const u8 *ref;
+
+	unsigned int hval = FRST(ip);
+	unsigned long off;
+	int lit = 0;
+
+	if (ctx->first_call) {
+		ctx->first_call = 0;
+	}
+#if INIT_HTAB
+#if USE_MEMCPY
+	memset(htab, 0, sizeof(htab));
+#else
+	for (hslot = htab; hslot < htab + HSIZE; hslot++)
+		*hslot++ = ip;
+#endif
+#endif
+
+	for (;;) {
+		if (ip < in_end - 2) {
+			hval = NEXT(hval, ip);
+			hslot = htab + IDX(hval);
+			ref = *hslot;
+			*hslot = ip;
+
+			if (1
+#if INIT_HTAB && !USE_MEMCPY
+			    && ref < ip	/* the next test will actually take care of this, but this is faster */
+#endif
+			    && (off = ip - ref - 1) < MAX_OFF
+			    && ip + 4 < in_end && ref > in_data
+#if STRICT_ALIGN
+			    && ref[0] == ip[0]
+			    && ref[1] == ip[1]
+			    && ref[2] == ip[2]
+#else
+			    && *(u16 *) ref == *(u16 *) ip && ref[2] == ip[2]
+#endif
+			    ) {
+				/* match found at *ref++ */
+				unsigned int len = 2;
+				unsigned int maxlen = in_end - ip - len;
+				maxlen = maxlen > MAX_REF ? MAX_REF : maxlen;
+
+				do
+					len++;
+				while (len < maxlen && ref[len] == ip[len]);
+
+				if (op + lit + 1 + 3 >= out_end) {
+					*out_len = PAGE_SIZE;
+					return 0;
+				}
+
+				if (lit) {
+					*op++ = lit - 1;
+					lit = -lit;
+					do
+						*op++ = ip[lit];
+					while (++lit);
+				}
+
+				len -= 2;
+				ip++;
+
+				if (len < 7) {
+					*op++ = (off >> 8) + (len << 5);
+				} else {
+					*op++ = (off >> 8) + (7 << 5);
+					*op++ = len - 7;
+				}
+
+				*op++ = off;
+
+#if ULTRA_FAST
+				ip += len;
+				hval = FRST(ip);
+				hval = NEXT(hval, ip);
+				htab[IDX(hval)] = ip;
+				ip++;
+#else
+				do {
+					hval = NEXT(hval, ip);
+					htab[IDX(hval)] = ip;
+					ip++;
+				}
+				while (len--);
+#endif
+				continue;
+			}
+		} else if (ip == in_end)
+			break;
+
+		/* one more literal byte we must copy */
+		lit++;
+		ip++;
+
+		if (lit == MAX_LIT) {
+			if (op + 1 + MAX_LIT >= out_end) {
+				*out_len = PAGE_SIZE;
+				return 0;
+			}
+
+			*op++ = MAX_LIT - 1;
+#if USE_MEMCPY
+			memcpy(op, ip - MAX_LIT, MAX_LIT);
+			op += MAX_LIT;
+			lit = 0;
+#else
+			lit = -lit;
+			do
+				*op++ = ip[lit];
+			while (++lit);
+#endif
+		}
+	}
+
+	if (lit) {
+		if (op + lit + 1 >= out_end) {
+			*out_len = PAGE_SIZE;
+			return 0;
+		}
+
+		*op++ = lit - 1;
+		lit = -lit;
+		do
+			*op++ = ip[lit];
+		while (++lit);
+	}
+
+	*out_len = op - out_data;
+	return 0;
+}
+
+static int lzf_decompress(void *context, const u8 * src, unsigned int slen,
+			  u8 * dst, unsigned int *dlen)
+{
+	struct lzf_ctx *ctx = (struct lzf_ctx *)context;
+	u8 const *ip = src;
+	u8 *op = dst;
+	u8 const *const in_end = ip + slen;
+	u8 *const out_end = op + *dlen;
+
+	if (ctx->first_call) {
+		ctx->first_call = 0;
+	}
+	do {
+		unsigned int ctrl = *ip++;
+
+		if (ctrl < (1 << 5)) {	/* literal run */
+			ctrl++;
+
+			if (op + ctrl > out_end) {
+				*dlen = PAGE_SIZE;
+				return 0;
+			}
+#if USE_MEMCPY
+			memcpy(op, ip, ctrl);
+			op += ctrl;
+			ip += ctrl;
+#else
+			do
+				*op++ = *ip++;
+			while (--ctrl);
+#endif
+		} else {	/* back reference */
+
+			unsigned int len = ctrl >> 5;
+
+			u8 *ref = op - ((ctrl & 0x1f) << 8) - 1;
+
+			if (len == 7)
+				len += *ip++;
+
+			ref -= *ip++;
+
+			if (op + len + 2 > out_end) {
+				*dlen = PAGE_SIZE;
+				return 0;
+			}
+
+			if (ref < (u8 *) dst) {
+				*dlen = PAGE_SIZE;
+				return 0;
+			}
+
+			*op++ = *ref++;
+			*op++ = *ref++;
+
+			do
+				*op++ = *ref++;
+			while (--len);
+		}
+	}
+	while (op < out_end && ip < in_end);
+
+	*dlen = op - (u8 *) dst;
+	return 0;
+}
+
+static struct crypto_alg alg = {
+	.cra_name = "lzf",
+	.cra_flags = CRYPTO_ALG_TYPE_COMPRESS,
+	.cra_ctxsize = 0,
+	.cra_module = THIS_MODULE,
+	.cra_list = LIST_HEAD_INIT(alg.cra_list),
+	.cra_u = {.compress = {
+			       .coa_init = lzf_compress_init,
+			       .coa_exit = lzf_compress_exit,
+			       .coa_compress = lzf_compress,
+			       .coa_decompress = lzf_decompress}}
+};
+
+static int __init init(void)
+{
+	return crypto_register_alg(&alg);
+}
+
+static void __exit fini(void)
+{
+	crypto_unregister_alg(&alg);
+}
+
+module_init(init);
+module_exit(fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("LZF Compression Algorithm");
+MODULE_AUTHOR("Marc Alexander Lehmann & Nigel Cunningham");
diff -ruNp 625-crypto-api-work.patch-old/crypto/Makefile 625-crypto-api-work.patch-new/crypto/Makefile
--- 625-crypto-api-work.patch-old/crypto/Makefile	2005-06-20 11:46:49.000000000 +1000
+++ 625-crypto-api-work.patch-new/crypto/Makefile	2005-07-06 11:51:06.000000000 +1000
@@ -30,5 +30,6 @@ obj-$(CONFIG_CRYPTO_ANUBIS) += anubis.o
 obj-$(CONFIG_CRYPTO_DEFLATE) += deflate.o
 obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o
 obj-$(CONFIG_CRYPTO_CRC32C) += crc32c.o
+obj-$(CONFIG_CRYPTO_LZF) += lzf.o
 
 obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o

-- 
Evolution.
Enumerate the requirements.
Consider the interdependencies.
Calculate the probabilities.
Be amazed that people believe it happened. 

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]
  Powered by Linux