diff options
Diffstat (limited to 'fs/jffs2/compr.c')
-rw-r--r-- | fs/jffs2/compr.c | 119 |
1 files changed, 84 insertions, 35 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 | */ | ||
72 | static 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 | ||