Skip to content

Commit 45ec975

Browse files
daverodgmantorvalds
authored andcommitted
lib/lzo: separate lzo-rle from lzo
To prevent any issues with persistent data, separate lzo-rle from lzo so that it is treated as a separate algorithm, and lzo is still available. Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Dave Rodgman <[email protected]> Cc: David S. Miller <[email protected]> Cc: Greg Kroah-Hartman <[email protected]> Cc: Herbert Xu <[email protected]> Cc: Markus F.X.J. Oberhumer <[email protected]> Cc: Matt Sealey <[email protected]> Cc: Minchan Kim <[email protected]> Cc: Nitin Gupta <[email protected]> Cc: Richard Purdie <[email protected]> Cc: Sergey Senozhatsky <[email protected]> Cc: Sonny Rao <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 5ee4014 commit 45ec975

File tree

8 files changed

+226
-17
lines changed

8 files changed

+226
-17
lines changed

Documentation/lzo.txt

+8-4
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,10 @@ length encoding. This improves speed for data with many zeros, which is a
8888
common case for zram. This modifies the bitstream in a backwards compatible way
8989
(v1 can correctly decompress v0 compressed data, but v0 cannot read v1 data).
9090

91+
For maximum compatibility, both versions are available under different names
92+
(lzo and lzo-rle). Differences in the encoding are noted in this document with
93+
e.g.: version 1 only.
94+
9195
Byte sequences
9296
==============
9397

@@ -99,8 +103,8 @@ Byte sequences
99103
invalid at this place.
100104

101105
17 : bitstream version. If the first byte is 17, the next byte
102-
gives the bitstream version. If the first byte is not 17,
103-
the bitstream version is 0.
106+
gives the bitstream version (version 1 only). If the first byte
107+
is not 17, the bitstream version is 0.
104108

105109
18..21 : copy 0..3 literals
106110
state = (byte - 17) = 0..3 [ copy <state> literals ]
@@ -154,8 +158,8 @@ Byte sequences
154158
state = S (copy S literals after this block)
155159
End of stream is reached if distance == 16384
156160

157-
In version 1, this instruction is also used to encode a run of zeros if
158-
distance = 0xbfff, i.e. H = 1 and the D bits are all 1.
161+
In version 1 only, this instruction is also used to encode a run of
162+
zeros if distance = 0xbfff, i.e. H = 1 and the D bits are all 1.
159163
In this case, it is followed by a fourth byte, X.
160164
run length = ((X << 3) | (0 0 0 0 0 L L L)) + 4.
161165

crypto/Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ obj-$(CONFIG_CRYPTO_CRC32C) += crc32c_generic.o
128128
obj-$(CONFIG_CRYPTO_CRC32) += crc32_generic.o
129129
obj-$(CONFIG_CRYPTO_CRCT10DIF) += crct10dif_common.o crct10dif_generic.o
130130
obj-$(CONFIG_CRYPTO_AUTHENC) += authenc.o authencesn.o
131-
obj-$(CONFIG_CRYPTO_LZO) += lzo.o
131+
obj-$(CONFIG_CRYPTO_LZO) += lzo.o lzo-rle.o
132132
obj-$(CONFIG_CRYPTO_LZ4) += lz4.o
133133
obj-$(CONFIG_CRYPTO_LZ4HC) += lz4hc.o
134134
obj-$(CONFIG_CRYPTO_842) += 842.o

crypto/lzo-rle.c

+175
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
/*
2+
* Cryptographic API.
3+
*
4+
* This program is free software; you can redistribute it and/or modify it
5+
* under the terms of the GNU General Public License version 2 as published by
6+
* the Free Software Foundation.
7+
*
8+
* This program is distributed in the hope that it will be useful, but WITHOUT
9+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11+
* more details.
12+
*
13+
* You should have received a copy of the GNU General Public License along with
14+
* this program; if not, write to the Free Software Foundation, Inc., 51
15+
* Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16+
*
17+
*/
18+
19+
#include <linux/init.h>
20+
#include <linux/module.h>
21+
#include <linux/crypto.h>
22+
#include <linux/vmalloc.h>
23+
#include <linux/mm.h>
24+
#include <linux/lzo.h>
25+
#include <crypto/internal/scompress.h>
26+
27+
struct lzorle_ctx {
28+
void *lzorle_comp_mem;
29+
};
30+
31+
static void *lzorle_alloc_ctx(struct crypto_scomp *tfm)
32+
{
33+
void *ctx;
34+
35+
ctx = kvmalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL);
36+
if (!ctx)
37+
return ERR_PTR(-ENOMEM);
38+
39+
return ctx;
40+
}
41+
42+
static int lzorle_init(struct crypto_tfm *tfm)
43+
{
44+
struct lzorle_ctx *ctx = crypto_tfm_ctx(tfm);
45+
46+
ctx->lzorle_comp_mem = lzorle_alloc_ctx(NULL);
47+
if (IS_ERR(ctx->lzorle_comp_mem))
48+
return -ENOMEM;
49+
50+
return 0;
51+
}
52+
53+
static void lzorle_free_ctx(struct crypto_scomp *tfm, void *ctx)
54+
{
55+
kvfree(ctx);
56+
}
57+
58+
static void lzorle_exit(struct crypto_tfm *tfm)
59+
{
60+
struct lzorle_ctx *ctx = crypto_tfm_ctx(tfm);
61+
62+
lzorle_free_ctx(NULL, ctx->lzorle_comp_mem);
63+
}
64+
65+
static int __lzorle_compress(const u8 *src, unsigned int slen,
66+
u8 *dst, unsigned int *dlen, void *ctx)
67+
{
68+
size_t tmp_len = *dlen; /* size_t(ulong) <-> uint on 64 bit */
69+
int err;
70+
71+
err = lzorle1x_1_compress(src, slen, dst, &tmp_len, ctx);
72+
73+
if (err != LZO_E_OK)
74+
return -EINVAL;
75+
76+
*dlen = tmp_len;
77+
return 0;
78+
}
79+
80+
static int lzorle_compress(struct crypto_tfm *tfm, const u8 *src,
81+
unsigned int slen, u8 *dst, unsigned int *dlen)
82+
{
83+
struct lzorle_ctx *ctx = crypto_tfm_ctx(tfm);
84+
85+
return __lzorle_compress(src, slen, dst, dlen, ctx->lzorle_comp_mem);
86+
}
87+
88+
static int lzorle_scompress(struct crypto_scomp *tfm, const u8 *src,
89+
unsigned int slen, u8 *dst, unsigned int *dlen,
90+
void *ctx)
91+
{
92+
return __lzorle_compress(src, slen, dst, dlen, ctx);
93+
}
94+
95+
static int __lzorle_decompress(const u8 *src, unsigned int slen,
96+
u8 *dst, unsigned int *dlen)
97+
{
98+
int err;
99+
size_t tmp_len = *dlen; /* size_t(ulong) <-> uint on 64 bit */
100+
101+
err = lzo1x_decompress_safe(src, slen, dst, &tmp_len);
102+
103+
if (err != LZO_E_OK)
104+
return -EINVAL;
105+
106+
*dlen = tmp_len;
107+
return 0;
108+
}
109+
110+
static int lzorle_decompress(struct crypto_tfm *tfm, const u8 *src,
111+
unsigned int slen, u8 *dst, unsigned int *dlen)
112+
{
113+
return __lzorle_decompress(src, slen, dst, dlen);
114+
}
115+
116+
static int lzorle_sdecompress(struct crypto_scomp *tfm, const u8 *src,
117+
unsigned int slen, u8 *dst, unsigned int *dlen,
118+
void *ctx)
119+
{
120+
return __lzorle_decompress(src, slen, dst, dlen);
121+
}
122+
123+
static struct crypto_alg alg = {
124+
.cra_name = "lzo-rle",
125+
.cra_flags = CRYPTO_ALG_TYPE_COMPRESS,
126+
.cra_ctxsize = sizeof(struct lzorle_ctx),
127+
.cra_module = THIS_MODULE,
128+
.cra_init = lzorle_init,
129+
.cra_exit = lzorle_exit,
130+
.cra_u = { .compress = {
131+
.coa_compress = lzorle_compress,
132+
.coa_decompress = lzorle_decompress } }
133+
};
134+
135+
static struct scomp_alg scomp = {
136+
.alloc_ctx = lzorle_alloc_ctx,
137+
.free_ctx = lzorle_free_ctx,
138+
.compress = lzorle_scompress,
139+
.decompress = lzorle_sdecompress,
140+
.base = {
141+
.cra_name = "lzo-rle",
142+
.cra_driver_name = "lzo-rle-scomp",
143+
.cra_module = THIS_MODULE,
144+
}
145+
};
146+
147+
static int __init lzorle_mod_init(void)
148+
{
149+
int ret;
150+
151+
ret = crypto_register_alg(&alg);
152+
if (ret)
153+
return ret;
154+
155+
ret = crypto_register_scomp(&scomp);
156+
if (ret) {
157+
crypto_unregister_alg(&alg);
158+
return ret;
159+
}
160+
161+
return ret;
162+
}
163+
164+
static void __exit lzorle_mod_fini(void)
165+
{
166+
crypto_unregister_alg(&alg);
167+
crypto_unregister_scomp(&scomp);
168+
}
169+
170+
module_init(lzorle_mod_init);
171+
module_exit(lzorle_mod_fini);
172+
173+
MODULE_LICENSE("GPL");
174+
MODULE_DESCRIPTION("LZO-RLE Compression Algorithm");
175+
MODULE_ALIAS_CRYPTO("lzo-rle");

crypto/tcrypt.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,8 @@ static char *check[] = {
7676
"cast6", "arc4", "michael_mic", "deflate", "crc32c", "tea", "xtea",
7777
"khazad", "wp512", "wp384", "wp256", "tnepres", "xeta", "fcrypt",
7878
"camellia", "seed", "salsa20", "rmd128", "rmd160", "rmd256", "rmd320",
79-
"lzo", "cts", "sha3-224", "sha3-256", "sha3-384", "sha3-512",
80-
"streebog256", "streebog512",
79+
"lzo", "lzo-rle", "cts", "sha3-224", "sha3-256", "sha3-384",
80+
"sha3-512", "streebog256", "streebog512",
8181
NULL
8282
};
8383

drivers/block/zram/zcomp.c

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
static const char * const backends[] = {
2222
"lzo",
23+
"lzo-rle",
2324
#if IS_ENABLED(CONFIG_CRYPTO_LZ4)
2425
"lz4",
2526
#endif

include/linux/lzo.h

+4
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@
2424
int lzo1x_1_compress(const unsigned char *src, size_t src_len,
2525
unsigned char *dst, size_t *dst_len, void *wrkmem);
2626

27+
/* This requires 'wrkmem' of size LZO1X_1_MEM_COMPRESS */
28+
int lzorle1x_1_compress(const unsigned char *src, size_t src_len,
29+
unsigned char *dst, size_t *dst_len, void *wrkmem);
30+
2731
/* safe decompression with overrun testing */
2832
int lzo1x_decompress_safe(const unsigned char *src, size_t src_len,
2933
unsigned char *dst, size_t *dst_len);

lib/lzo/lzo1x_compress.c

+33-9
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@
2020
static noinline size_t
2121
lzo1x_1_do_compress(const unsigned char *in, size_t in_len,
2222
unsigned char *out, size_t *out_len,
23-
size_t ti, void *wrkmem, signed char *state_offset)
23+
size_t ti, void *wrkmem, signed char *state_offset,
24+
const unsigned char bitstream_version)
2425
{
2526
const unsigned char *ip;
2627
unsigned char *op;
@@ -46,7 +47,7 @@ lzo1x_1_do_compress(const unsigned char *in, size_t in_len,
4647
break;
4748
dv = get_unaligned_le32(ip);
4849

49-
if (dv == 0) {
50+
if (dv == 0 && bitstream_version) {
5051
const unsigned char *ir = ip + 4;
5152
const unsigned char *limit = ip_end
5253
< (ip + MAX_ZERO_RUN_LENGTH + 1)
@@ -284,30 +285,36 @@ lzo1x_1_do_compress(const unsigned char *in, size_t in_len,
284285
return in_end - (ii - ti);
285286
}
286287

287-
int lzo1x_1_compress(const unsigned char *in, size_t in_len,
288+
int lzogeneric1x_1_compress(const unsigned char *in, size_t in_len,
288289
unsigned char *out, size_t *out_len,
289-
void *wrkmem)
290+
void *wrkmem, const unsigned char bitstream_version)
290291
{
291292
const unsigned char *ip = in;
292293
unsigned char *op = out;
293294
size_t l = in_len;
294295
size_t t = 0;
295296
signed char state_offset = -2;
297+
unsigned int m4_max_offset;
296298

297299
// LZO v0 will never write 17 as first byte,
298300
// so this is used to version the bitstream
299-
*op++ = 17;
300-
*op++ = LZO_VERSION;
301+
if (bitstream_version > 0) {
302+
*op++ = 17;
303+
*op++ = bitstream_version;
304+
m4_max_offset = M4_MAX_OFFSET_V1;
305+
} else {
306+
m4_max_offset = M4_MAX_OFFSET_V0;
307+
}
301308

302309
while (l > 20) {
303-
size_t ll = l <= (M4_MAX_OFFSET + 1) ? l : (M4_MAX_OFFSET + 1);
310+
size_t ll = l <= (m4_max_offset + 1) ? l : (m4_max_offset + 1);
304311
uintptr_t ll_end = (uintptr_t) ip + ll;
305312
if ((ll_end + ((t + ll) >> 5)) <= ll_end)
306313
break;
307314
BUILD_BUG_ON(D_SIZE * sizeof(lzo_dict_t) > LZO1X_1_MEM_COMPRESS);
308315
memset(wrkmem, 0, D_SIZE * sizeof(lzo_dict_t));
309-
t = lzo1x_1_do_compress(ip, ll, op, out_len,
310-
t, wrkmem, &state_offset);
316+
t = lzo1x_1_do_compress(ip, ll, op, out_len, t, wrkmem,
317+
&state_offset, bitstream_version);
311318
ip += ll;
312319
op += *out_len;
313320
l -= ll;
@@ -351,7 +358,24 @@ int lzo1x_1_compress(const unsigned char *in, size_t in_len,
351358
*out_len = op - out;
352359
return LZO_E_OK;
353360
}
361+
362+
int lzo1x_1_compress(const unsigned char *in, size_t in_len,
363+
unsigned char *out, size_t *out_len,
364+
void *wrkmem)
365+
{
366+
return lzogeneric1x_1_compress(in, in_len, out, out_len, wrkmem, 0);
367+
}
368+
369+
int lzorle1x_1_compress(const unsigned char *in, size_t in_len,
370+
unsigned char *out, size_t *out_len,
371+
void *wrkmem)
372+
{
373+
return lzogeneric1x_1_compress(in, in_len, out, out_len,
374+
wrkmem, LZO_VERSION);
375+
}
376+
354377
EXPORT_SYMBOL_GPL(lzo1x_1_compress);
378+
EXPORT_SYMBOL_GPL(lzorle1x_1_compress);
355379

356380
MODULE_LICENSE("GPL");
357381
MODULE_DESCRIPTION("LZO1X-1 Compressor");

lib/lzo/lzodefs.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@
4444
#define M1_MAX_OFFSET 0x0400
4545
#define M2_MAX_OFFSET 0x0800
4646
#define M3_MAX_OFFSET 0x4000
47-
#define M4_MAX_OFFSET 0xbffe
47+
#define M4_MAX_OFFSET_V0 0xbfff
48+
#define M4_MAX_OFFSET_V1 0xbffe
4849

4950
#define M1_MIN_LEN 2
5051
#define M1_MAX_LEN 2

0 commit comments

Comments
 (0)