Commit 123005f3 authored by Andres Salomon's avatar Andres Salomon Committed by Artem Bityutskiy

jffs2: add compr=lzo and compr=zlib options

..to allow forcing of either compression scheme.  This will override
compiled-in defaults.  jffs2_compress is reworked a bit, as the lzo/zlib
override shares lots of code w/ the PRIORITY mode.

v2: update show_options accordingly.
Signed-off-by: default avatarAndres Salomon <dilinger@queued.net>
Signed-off-by: default avatarArtem Bityutskiy <artem.bityutskiy@intel.com>
parent 92abc475
...@@ -53,6 +53,78 @@ static int jffs2_is_best_compression(struct jffs2_compressor *this, ...@@ -53,6 +53,78 @@ static int jffs2_is_best_compression(struct jffs2_compressor *this,
return 0; 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: /* jffs2_compress:
* @data_in: Pointer to uncompressed data * @data_in: Pointer to uncompressed data
* @cpage_out: Pointer to returned pointer to buffer for compressed 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, ...@@ -91,37 +163,8 @@ uint16_t jffs2_compress(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
case JFFS2_COMPR_MODE_NONE: case JFFS2_COMPR_MODE_NONE:
break; break;
case JFFS2_COMPR_MODE_PRIORITY: case JFFS2_COMPR_MODE_PRIORITY:
output_buf = kmalloc(*cdatalen,GFP_KERNEL); ret = jffs2_selected_compress(0, data_in, cpage_out, datalen,
if (!output_buf) { cdatalen);
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);
break; break;
case JFFS2_COMPR_MODE_SIZE: case JFFS2_COMPR_MODE_SIZE:
case JFFS2_COMPR_MODE_FAVOURLZO: case JFFS2_COMPR_MODE_FAVOURLZO:
...@@ -179,22 +222,28 @@ uint16_t jffs2_compress(struct jffs2_sb_info *c, struct jffs2_inode_info *f, ...@@ -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_orig_size += best_slen;
best->stat_compr_new_size += best_dlen; best->stat_compr_new_size += best_dlen;
ret = best->compr; ret = best->compr;
*cpage_out = output_buf;
} }
spin_unlock(&jffs2_compressor_list_lock); spin_unlock(&jffs2_compressor_list_lock);
break; 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: default:
printk(KERN_ERR "JFFS2: unknown compression mode.\n"); printk(KERN_ERR "JFFS2: unknown compression mode.\n");
} }
out:
if (ret == JFFS2_COMPR_NONE) { if (ret == JFFS2_COMPR_NONE) {
*cpage_out = data_in; *cpage_out = data_in;
*datalen = *cdatalen; *datalen = *cdatalen;
none_stat_compr_blocks++; none_stat_compr_blocks++;
none_stat_compr_size += *datalen; none_stat_compr_size += *datalen;
} }
else {
*cpage_out = output_buf;
}
return ret; return ret;
} }
......
...@@ -40,6 +40,8 @@ ...@@ -40,6 +40,8 @@
#define JFFS2_COMPR_MODE_PRIORITY 1 #define JFFS2_COMPR_MODE_PRIORITY 1
#define JFFS2_COMPR_MODE_SIZE 2 #define JFFS2_COMPR_MODE_SIZE 2
#define JFFS2_COMPR_MODE_FAVOURLZO 3 #define JFFS2_COMPR_MODE_FAVOURLZO 3
#define JFFS2_COMPR_MODE_FORCELZO 4
#define JFFS2_COMPR_MODE_FORCEZLIB 5
#define FAVOUR_LZO_PERCENT 80 #define FAVOUR_LZO_PERCENT 80
......
...@@ -82,6 +82,14 @@ static const char *jffs2_compr_name(unsigned int compr) ...@@ -82,6 +82,14 @@ static const char *jffs2_compr_name(unsigned int compr)
switch (compr) { switch (compr) {
case JFFS2_COMPR_MODE_NONE: case JFFS2_COMPR_MODE_NONE:
return "none"; return "none";
#ifdef CONFIG_JFFS2_LZO
case JFFS2_COMPR_MODE_FORCELZO:
return "lzo";
#endif
#ifdef CONFIG_JFFS2_ZLIB
case JFFS2_COMPR_MODE_FORCEZLIB:
return "zlib";
#endif
default: default:
/* should never happen; programmer error */ /* should never happen; programmer error */
WARN_ON(1); WARN_ON(1);
...@@ -195,11 +203,25 @@ static int jffs2_parse_options(struct jffs2_sb_info *c, char *data) ...@@ -195,11 +203,25 @@ static int jffs2_parse_options(struct jffs2_sb_info *c, char *data)
if (!name) if (!name)
return -ENOMEM; return -ENOMEM;
if (!strcmp(name, "none")) { if (!strcmp(name, "none"))
c->mount_opts.compr = JFFS2_COMPR_MODE_NONE; c->mount_opts.compr = JFFS2_COMPR_MODE_NONE;
c->mount_opts.override_compr = true; #ifdef CONFIG_JFFS2_LZO
else if (!strcmp(name, "lzo"))
c->mount_opts.compr = JFFS2_COMPR_MODE_FORCELZO;
#endif
#ifdef CONFIG_JFFS2_ZLIB
else if (!strcmp(name, "zlib"))
c->mount_opts.compr =
JFFS2_COMPR_MODE_FORCEZLIB;
#endif
else {
printk(KERN_ERR "JFFS2 Error: unknown compressor \"%s\"",
name);
kfree(name);
return -EINVAL;
} }
kfree(name); kfree(name);
c->mount_opts.override_compr = true;
break; break;
default: default:
printk(KERN_ERR "JFFS2 Error: unrecognized mount option '%s' or missing value\n", printk(KERN_ERR "JFFS2 Error: unrecognized mount option '%s' or missing value\n",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment