aboutsummaryrefslogtreecommitdiffstats
path: root/fs/jffs2
diff options
context:
space:
mode:
Diffstat (limited to 'fs/jffs2')
-rw-r--r--fs/jffs2/compr.c119
-rw-r--r--fs/jffs2/compr.h2
-rw-r--r--fs/jffs2/super.c26
3 files changed, 110 insertions, 37 deletions
diff --git a/fs/jffs2/compr.c b/fs/jffs2/compr.c
index 97bc74db2c96..5b6c9d1a2fb9 100644
--- a/fs/jffs2/compr.c
+++ b/fs/jffs2/compr.c
@@ -53,6 +53,78 @@ static int jffs2_is_best_compression(struct jffs2_compressor *this,
53 return 0; 53 return 0;
54} 54}
55 55
56/*
57 * jffs2_selected_compress:
58 * @compr: Explicit compression type to use (ie, JFFS2_COMPR_ZLIB).
59 * If 0, just take the first available compression mode.
60 * @data_in: Pointer to uncompressed data
61 * @cpage_out: Pointer to returned pointer to buffer for compressed data
62 * @datalen: On entry, holds the amount of data available for compression.
63 * On exit, expected to hold the amount of data actually compressed.
64 * @cdatalen: On entry, holds the amount of space available for compressed
65 * data. On exit, expected to hold the actual size of the compressed
66 * data.
67 *
68 * Returns: the compression type used. Zero is used to show that the data
69 * could not be compressed; probably because we couldn't find the requested
70 * compression mode.
71 */
72static int jffs2_selected_compress(u8 compr, unsigned char *data_in,
73 unsigned char **cpage_out, u32 *datalen, u32 *cdatalen)
74{
75 struct jffs2_compressor *this;
76 int err, ret = JFFS2_COMPR_NONE;
77 uint32_t orig_slen, orig_dlen;
78 char *output_buf;
79
80 output_buf = kmalloc(*cdatalen, GFP_KERNEL);
81 if (!output_buf) {
82 printk(KERN_WARNING "JFFS2: No memory for compressor allocation. Compression failed.\n");
83 return ret;
84 }
85 orig_slen = *datalen;
86 orig_dlen = *cdatalen;
87 spin_lock(&jffs2_compressor_list_lock);
88 list_for_each_entry(this, &jffs2_compressor_list, list) {
89 /* Skip decompress-only and disabled modules */
90 if (!this->compress || this->disabled)
91 continue;
92
93 /* Skip if not the desired compression type */
94 if (compr && (compr != this->compr))
95 continue;
96
97 /*
98 * Either compression type was unspecified, or we found our
99 * compressor; either way, we're good to go.
100 */
101 this->usecount++;
102 spin_unlock(&jffs2_compressor_list_lock);
103
104 *datalen = orig_slen;
105 *cdatalen = orig_dlen;
106 err = this->compress(data_in, output_buf, datalen, cdatalen);
107
108 spin_lock(&jffs2_compressor_list_lock);
109 this->usecount--;
110 if (!err) {
111 /* Success */
112 ret = this->compr;
113 this->stat_compr_blocks++;
114 this->stat_compr_orig_size += *datalen;
115 this->stat_compr_new_size += *cdatalen;
116 break;
117 }
118 }
119 spin_unlock(&jffs2_compressor_list_lock);
120 if (ret == JFFS2_COMPR_NONE)
121 kfree(output_buf);
122 else
123 *cpage_out = output_buf;
124
125 return ret;
126}
127
56/* jffs2_compress: 128/* jffs2_compress:
57 * @data_in: Pointer to uncompressed data 129 * @data_in: Pointer to uncompressed data
58 * @cpage_out: Pointer to returned pointer to buffer for compressed data 130 * @cpage_out: Pointer to returned pointer to buffer for compressed data
@@ -91,37 +163,8 @@ uint16_t jffs2_compress(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
91 case JFFS2_COMPR_MODE_NONE: 163 case JFFS2_COMPR_MODE_NONE:
92 break; 164 break;
93 case JFFS2_COMPR_MODE_PRIORITY: 165 case JFFS2_COMPR_MODE_PRIORITY:
94 output_buf = kmalloc(*cdatalen,GFP_KERNEL); 166 ret = jffs2_selected_compress(0, data_in, cpage_out, datalen,
95 if (!output_buf) { 167 cdatalen);
96 printk(KERN_WARNING "JFFS2: No memory for compressor allocation. Compression failed.\n");
97 goto out;
98 }
99 orig_slen = *datalen;
100 orig_dlen = *cdatalen;
101 spin_lock(&jffs2_compressor_list_lock);
102 list_for_each_entry(this, &jffs2_compressor_list, list) {
103 /* Skip decompress-only backwards-compatibility and disabled modules */
104 if ((!this->compress)||(this->disabled))
105 continue;
106
107 this->usecount++;
108 spin_unlock(&jffs2_compressor_list_lock);
109 *datalen = orig_slen;
110 *cdatalen = orig_dlen;
111 compr_ret = this->compress(data_in, output_buf, datalen, cdatalen);
112 spin_lock(&jffs2_compressor_list_lock);
113 this->usecount--;
114 if (!compr_ret) {
115 ret = this->compr;
116 this->stat_compr_blocks++;
117 this->stat_compr_orig_size += *datalen;
118 this->stat_compr_new_size += *cdatalen;
119 break;
120 }
121 }
122 spin_unlock(&jffs2_compressor_list_lock);
123 if (ret == JFFS2_COMPR_NONE)
124 kfree(output_buf);
125 break; 168 break;
126 case JFFS2_COMPR_MODE_SIZE: 169 case JFFS2_COMPR_MODE_SIZE:
127 case JFFS2_COMPR_MODE_FAVOURLZO: 170 case JFFS2_COMPR_MODE_FAVOURLZO:
@@ -179,22 +222,28 @@ uint16_t jffs2_compress(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
179 best->stat_compr_orig_size += best_slen; 222 best->stat_compr_orig_size += best_slen;
180 best->stat_compr_new_size += best_dlen; 223 best->stat_compr_new_size += best_dlen;
181 ret = best->compr; 224 ret = best->compr;
225 *cpage_out = output_buf;
182 } 226 }
183 spin_unlock(&jffs2_compressor_list_lock); 227 spin_unlock(&jffs2_compressor_list_lock);
184 break; 228 break;
229 case JFFS2_COMPR_MODE_FORCELZO:
230 ret = jffs2_selected_compress(JFFS2_COMPR_LZO, data_in,
231 cpage_out, datalen, cdatalen);
232 break;
233 case JFFS2_COMPR_MODE_FORCEZLIB:
234 ret = jffs2_selected_compress(JFFS2_COMPR_ZLIB, data_in,
235 cpage_out, datalen, cdatalen);
236 break;
185 default: 237 default:
186 printk(KERN_ERR "JFFS2: unknown compression mode.\n"); 238 printk(KERN_ERR "JFFS2: unknown compression mode.\n");
187 } 239 }
188 out: 240
189 if (ret == JFFS2_COMPR_NONE) { 241 if (ret == JFFS2_COMPR_NONE) {
190 *cpage_out = data_in; 242 *cpage_out = data_in;
191 *datalen = *cdatalen; 243 *datalen = *cdatalen;
192 none_stat_compr_blocks++; 244 none_stat_compr_blocks++;
193 none_stat_compr_size += *datalen; 245 none_stat_compr_size += *datalen;
194 } 246 }
195 else {
196 *cpage_out = output_buf;
197 }
198 return ret; 247 return ret;
199} 248}
200 249
diff --git a/fs/jffs2/compr.h b/fs/jffs2/compr.h
index 13bb7597ab39..5e91d578f4ed 100644
--- a/fs/jffs2/compr.h
+++ b/fs/jffs2/compr.h
@@ -40,6 +40,8 @@
40#define JFFS2_COMPR_MODE_PRIORITY 1 40#define JFFS2_COMPR_MODE_PRIORITY 1
41#define JFFS2_COMPR_MODE_SIZE 2 41#define JFFS2_COMPR_MODE_SIZE 2
42#define JFFS2_COMPR_MODE_FAVOURLZO 3 42#define JFFS2_COMPR_MODE_FAVOURLZO 3
43#define JFFS2_COMPR_MODE_FORCELZO 4
44#define JFFS2_COMPR_MODE_FORCEZLIB 5
43 45
44#define FAVOUR_LZO_PERCENT 80 46#define FAVOUR_LZO_PERCENT 80
45 47
diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c
index 40f6e6385fd1..e7e974454115 100644
--- a/fs/jffs2/super.c
+++ b/fs/jffs2/super.c
@@ -82,6 +82,14 @@ static const char *jffs2_compr_name(unsigned int compr)
82 switch (compr) { 82 switch (compr) {
83 case JFFS2_COMPR_MODE_NONE: 83 case JFFS2_COMPR_MODE_NONE:
84 return "none"; 84 return "none";
85#ifdef CONFIG_JFFS2_LZO
86 case JFFS2_COMPR_MODE_FORCELZO:
87 return "lzo";
88#endif
89#ifdef CONFIG_JFFS2_ZLIB
90 case JFFS2_COMPR_MODE_FORCEZLIB:
91 return "zlib";
92#endif
85 default: 93 default:
86 /* should never happen; programmer error */ 94 /* should never happen; programmer error */
87 WARN_ON(1); 95 WARN_ON(1);
@@ -195,11 +203,25 @@ static int jffs2_parse_options(struct jffs2_sb_info *c, char *data)
195 203
196 if (!name) 204 if (!name)
197 return -ENOMEM; 205 return -ENOMEM;
198 if (!strcmp(name, "none")) { 206 if (!strcmp(name, "none"))
199 c->mount_opts.compr = JFFS2_COMPR_MODE_NONE; 207 c->mount_opts.compr = JFFS2_COMPR_MODE_NONE;
200 c->mount_opts.override_compr = true; 208#ifdef CONFIG_JFFS2_LZO
209 else if (!strcmp(name, "lzo"))
210 c->mount_opts.compr = JFFS2_COMPR_MODE_FORCELZO;
211#endif
212#ifdef CONFIG_JFFS2_ZLIB
213 else if (!strcmp(name, "zlib"))
214 c->mount_opts.compr =
215 JFFS2_COMPR_MODE_FORCEZLIB;
216#endif
217 else {
218 printk(KERN_ERR "JFFS2 Error: unknown compressor \"%s\"",
219 name);
220 kfree(name);
221 return -EINVAL;
201 } 222 }
202 kfree(name); 223 kfree(name);
224 c->mount_opts.override_compr = true;
203 break; 225 break;
204 default: 226 default:
205 printk(KERN_ERR "JFFS2 Error: unrecognized mount option '%s' or missing value\n", 227 printk(KERN_ERR "JFFS2 Error: unrecognized mount option '%s' or missing value\n",