|
@@ -53,6 +53,78 @@ static int jffs2_is_best_compression(struct jffs2_compressor *this,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * jffs2_selected_compress:
|
|
|
+ * @compr: Explicit compression type to use (ie, JFFS2_COMPR_ZLIB).
|
|
|
+ * If 0, just take the first available compression mode.
|
|
|
+ * @data_in: Pointer to uncompressed data
|
|
|
+ * @cpage_out: Pointer to returned pointer to buffer for compressed data
|
|
|
+ * @datalen: On entry, holds the amount of data available for compression.
|
|
|
+ * On exit, expected to hold the amount of data actually compressed.
|
|
|
+ * @cdatalen: On entry, holds the amount of space available for compressed
|
|
|
+ * data. On exit, expected to hold the actual size of the compressed
|
|
|
+ * data.
|
|
|
+ *
|
|
|
+ * Returns: the compression type used. Zero is used to show that the data
|
|
|
+ * could not be compressed; probably because we couldn't find the requested
|
|
|
+ * compression mode.
|
|
|
+ */
|
|
|
+static int jffs2_selected_compress(u8 compr, unsigned char *data_in,
|
|
|
+ unsigned char **cpage_out, u32 *datalen, u32 *cdatalen)
|
|
|
+{
|
|
|
+ struct jffs2_compressor *this;
|
|
|
+ int err, ret = JFFS2_COMPR_NONE;
|
|
|
+ uint32_t orig_slen, orig_dlen;
|
|
|
+ char *output_buf;
|
|
|
+
|
|
|
+ output_buf = kmalloc(*cdatalen, GFP_KERNEL);
|
|
|
+ if (!output_buf) {
|
|
|
+ printk(KERN_WARNING "JFFS2: No memory for compressor allocation. Compression failed.\n");
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+ orig_slen = *datalen;
|
|
|
+ orig_dlen = *cdatalen;
|
|
|
+ spin_lock(&jffs2_compressor_list_lock);
|
|
|
+ list_for_each_entry(this, &jffs2_compressor_list, list) {
|
|
|
+ /* Skip decompress-only and disabled modules */
|
|
|
+ if (!this->compress || this->disabled)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ /* Skip if not the desired compression type */
|
|
|
+ if (compr && (compr != this->compr))
|
|
|
+ continue;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Either compression type was unspecified, or we found our
|
|
|
+ * compressor; either way, we're good to go.
|
|
|
+ */
|
|
|
+ this->usecount++;
|
|
|
+ spin_unlock(&jffs2_compressor_list_lock);
|
|
|
+
|
|
|
+ *datalen = orig_slen;
|
|
|
+ *cdatalen = orig_dlen;
|
|
|
+ err = this->compress(data_in, output_buf, datalen, cdatalen);
|
|
|
+
|
|
|
+ spin_lock(&jffs2_compressor_list_lock);
|
|
|
+ this->usecount--;
|
|
|
+ if (!err) {
|
|
|
+ /* Success */
|
|
|
+ ret = this->compr;
|
|
|
+ this->stat_compr_blocks++;
|
|
|
+ this->stat_compr_orig_size += *datalen;
|
|
|
+ this->stat_compr_new_size += *cdatalen;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ spin_unlock(&jffs2_compressor_list_lock);
|
|
|
+ if (ret == JFFS2_COMPR_NONE)
|
|
|
+ kfree(output_buf);
|
|
|
+ else
|
|
|
+ *cpage_out = output_buf;
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
/* jffs2_compress:
|
|
|
* @data_in: Pointer to uncompressed data
|
|
|
* @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,
|
|
|
case JFFS2_COMPR_MODE_NONE:
|
|
|
break;
|
|
|
case JFFS2_COMPR_MODE_PRIORITY:
|
|
|
- output_buf = kmalloc(*cdatalen,GFP_KERNEL);
|
|
|
- if (!output_buf) {
|
|
|
- printk(KERN_WARNING "JFFS2: No memory for compressor allocation. Compression failed.\n");
|
|
|
- goto out;
|
|
|
- }
|
|
|
- orig_slen = *datalen;
|
|
|
- orig_dlen = *cdatalen;
|
|
|
- spin_lock(&jffs2_compressor_list_lock);
|
|
|
- list_for_each_entry(this, &jffs2_compressor_list, list) {
|
|
|
- /* Skip decompress-only backwards-compatibility and disabled modules */
|
|
|
- if ((!this->compress)||(this->disabled))
|
|
|
- continue;
|
|
|
-
|
|
|
- this->usecount++;
|
|
|
- spin_unlock(&jffs2_compressor_list_lock);
|
|
|
- *datalen = orig_slen;
|
|
|
- *cdatalen = orig_dlen;
|
|
|
- compr_ret = this->compress(data_in, output_buf, datalen, cdatalen);
|
|
|
- spin_lock(&jffs2_compressor_list_lock);
|
|
|
- this->usecount--;
|
|
|
- if (!compr_ret) {
|
|
|
- ret = this->compr;
|
|
|
- this->stat_compr_blocks++;
|
|
|
- this->stat_compr_orig_size += *datalen;
|
|
|
- this->stat_compr_new_size += *cdatalen;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- spin_unlock(&jffs2_compressor_list_lock);
|
|
|
- if (ret == JFFS2_COMPR_NONE)
|
|
|
- kfree(output_buf);
|
|
|
+ ret = jffs2_selected_compress(0, data_in, cpage_out, datalen,
|
|
|
+ cdatalen);
|
|
|
break;
|
|
|
case JFFS2_COMPR_MODE_SIZE:
|
|
|
case JFFS2_COMPR_MODE_FAVOURLZO:
|
|
@@ -179,22 +222,28 @@ uint16_t jffs2_compress(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
|
|
|
best->stat_compr_orig_size += best_slen;
|
|
|
best->stat_compr_new_size += best_dlen;
|
|
|
ret = best->compr;
|
|
|
+ *cpage_out = output_buf;
|
|
|
}
|
|
|
spin_unlock(&jffs2_compressor_list_lock);
|
|
|
break;
|
|
|
+ case JFFS2_COMPR_MODE_FORCELZO:
|
|
|
+ ret = jffs2_selected_compress(JFFS2_COMPR_LZO, data_in,
|
|
|
+ cpage_out, datalen, cdatalen);
|
|
|
+ break;
|
|
|
+ case JFFS2_COMPR_MODE_FORCEZLIB:
|
|
|
+ ret = jffs2_selected_compress(JFFS2_COMPR_ZLIB, data_in,
|
|
|
+ cpage_out, datalen, cdatalen);
|
|
|
+ break;
|
|
|
default:
|
|
|
printk(KERN_ERR "JFFS2: unknown compression mode.\n");
|
|
|
}
|
|
|
- out:
|
|
|
+
|
|
|
if (ret == JFFS2_COMPR_NONE) {
|
|
|
*cpage_out = data_in;
|
|
|
*datalen = *cdatalen;
|
|
|
none_stat_compr_blocks++;
|
|
|
none_stat_compr_size += *datalen;
|
|
|
}
|
|
|
- else {
|
|
|
- *cpage_out = output_buf;
|
|
|
- }
|
|
|
return ret;
|
|
|
}
|
|
|
|