1 | /* |
2 | * JFFS2 -- Journalling Flash File System, Version 2. |
3 | * |
4 | * Copyright © 2007 Nokia Corporation. All rights reserved. |
5 | * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org> |
6 | * |
7 | * Created by Richard Purdie <rpurdie@openedhand.com> |
8 | * |
9 | * For licensing information, see the file 'LICENCE' in this directory. |
10 | * |
11 | */ |
12 | |
13 | #include <linux/kernel.h> |
14 | #include <linux/sched.h> |
15 | #include <linux/vmalloc.h> |
16 | #include <linux/init.h> |
17 | #include <linux/lzo.h> |
18 | #include "compr.h" |
19 | |
20 | static void *lzo_mem; |
21 | static void *lzo_compress_buf; |
22 | static DEFINE_MUTEX(deflate_mutex); /* for lzo_mem and lzo_compress_buf */ |
23 | |
24 | static void free_workspace(void) |
25 | { |
26 | vfree(addr: lzo_mem); |
27 | vfree(addr: lzo_compress_buf); |
28 | } |
29 | |
30 | static int __init alloc_workspace(void) |
31 | { |
32 | lzo_mem = vmalloc(LZO1X_MEM_COMPRESS); |
33 | lzo_compress_buf = vmalloc(lzo1x_worst_compress(PAGE_SIZE)); |
34 | |
35 | if (!lzo_mem || !lzo_compress_buf) { |
36 | free_workspace(); |
37 | return -ENOMEM; |
38 | } |
39 | |
40 | return 0; |
41 | } |
42 | |
43 | static int jffs2_lzo_compress(unsigned char *data_in, unsigned char *cpage_out, |
44 | uint32_t *sourcelen, uint32_t *dstlen) |
45 | { |
46 | size_t compress_size; |
47 | int ret; |
48 | |
49 | mutex_lock(&deflate_mutex); |
50 | ret = lzo1x_1_compress(src: data_in, src_len: *sourcelen, dst: lzo_compress_buf, dst_len: &compress_size, wrkmem: lzo_mem); |
51 | if (ret != LZO_E_OK) |
52 | goto fail; |
53 | |
54 | if (compress_size > *dstlen) |
55 | goto fail; |
56 | |
57 | memcpy(cpage_out, lzo_compress_buf, compress_size); |
58 | mutex_unlock(lock: &deflate_mutex); |
59 | |
60 | *dstlen = compress_size; |
61 | return 0; |
62 | |
63 | fail: |
64 | mutex_unlock(lock: &deflate_mutex); |
65 | return -1; |
66 | } |
67 | |
68 | static int jffs2_lzo_decompress(unsigned char *data_in, unsigned char *cpage_out, |
69 | uint32_t srclen, uint32_t destlen) |
70 | { |
71 | size_t dl = destlen; |
72 | int ret; |
73 | |
74 | ret = lzo1x_decompress_safe(src: data_in, src_len: srclen, dst: cpage_out, dst_len: &dl); |
75 | |
76 | if (ret != LZO_E_OK || dl != destlen) |
77 | return -1; |
78 | |
79 | return 0; |
80 | } |
81 | |
82 | static struct jffs2_compressor jffs2_lzo_comp = { |
83 | .priority = JFFS2_LZO_PRIORITY, |
84 | .name = "lzo" , |
85 | .compr = JFFS2_COMPR_LZO, |
86 | .compress = &jffs2_lzo_compress, |
87 | .decompress = &jffs2_lzo_decompress, |
88 | .disabled = 0, |
89 | }; |
90 | |
91 | int __init jffs2_lzo_init(void) |
92 | { |
93 | int ret; |
94 | |
95 | ret = alloc_workspace(); |
96 | if (ret < 0) |
97 | return ret; |
98 | |
99 | ret = jffs2_register_compressor(comp: &jffs2_lzo_comp); |
100 | if (ret) |
101 | free_workspace(); |
102 | |
103 | return ret; |
104 | } |
105 | |
106 | void jffs2_lzo_exit(void) |
107 | { |
108 | jffs2_unregister_compressor(comp: &jffs2_lzo_comp); |
109 | free_workspace(); |
110 | } |
111 | |