Skip to contentSkip to conversation

jffs2: Add LZO compression support to jffs2

PATCH In review Richard Purdie 3 participants 4 messages May 1, 2007 – May 4, 2007

Subsystems (4)
lore
Share & tools
lore
#0 lore raw

PATCH 2/5 jffs2: Add LZO compression support to jffs2

Add LZO1X compression/decompression support to jffs2.

LZO's interface doesn't entirely match that required by jffs2 so a buffer and memcpy is unavoidable.

---
 fs/Kconfig            |   10 ++++
 fs/jffs2/Makefile     |    1 +
 fs/jffs2/compr.c      |    6 +++
 fs/jffs2/compr.h      |    7 +++-
 fs/jffs2/compr_lzo.c  |  110 +++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/jffs2.h |    1 +
 6 files changed, 134 insertions(+), 1 deletions(-)
fs/Kconfig +10 -0
index a42f767..1645dfa 100644
@@ -1310,6 +1310,16 @@ config JFFS2_ZLIB
 
           Say 'Y' if unsure.
 
+config JFFS2_LZO
+	bool "JFFS2 LZO compression support" if JFFS2_COMPRESSION_OPTIONS
+	select LZO
+	depends on JFFS2_FS
+	default y
+        help
+          minilzo-based compression. Generally works better than Zlib.
+
+          Say 'Y' if unsure.
+
 config JFFS2_RTIME
 	bool "JFFS2 RTIME compression support" if JFFS2_COMPRESSION_OPTIONS
 	depends on JFFS2_FS
fs/jffs2/Makefile +1 -0
index c32b241..60e5d49 100644
@@ -17,4 +17,5 @@ jffs2-$(CONFIG_JFFS2_FS_POSIX_ACL)	+= acl.o
 jffs2-$(CONFIG_JFFS2_RUBIN)	+= compr_rubin.o
 jffs2-$(CONFIG_JFFS2_RTIME)	+= compr_rtime.o
 jffs2-$(CONFIG_JFFS2_ZLIB)	+= compr_zlib.o
+jffs2-$(CONFIG_JFFS2_LZO)	+= compr_lzo.o
 jffs2-$(CONFIG_JFFS2_SUMMARY)   += summary.o
fs/jffs2/compr.c +6 -0
index 485d065..6a23408 100644
@@ -285,6 +285,9 @@ int __init jffs2_compressors_init(void)
         jffs2_rubinmips_init();
         jffs2_dynrubin_init();
 #endif
+#ifdef CONFIG_JFFS2_LZO
+        jffs2_lzo_init();
+#endif
 /* Setting default compression mode */
 #ifdef CONFIG_JFFS2_CMODE_NONE
         jffs2_compression_mode = JFFS2_COMPR_MODE_NONE;
@@ -303,6 +306,9 @@ int __init jffs2_compressors_init(void)
 int jffs2_compressors_exit(void)
 {
 /* Unregistering compressors */
+#ifdef CONFIG_JFFS2_LZO
+        jffs2_lzo_exit();
+#endif
 #ifdef CONFIG_JFFS2_RUBIN
         jffs2_dynrubin_exit();
         jffs2_rubinmips_exit();
fs/jffs2/compr.h +6 -1
index 68cc701..8c6b2af 100644
@@ -27,9 +27,10 @@
 #define JFFS2_RUBINMIPS_PRIORITY 10
 #define JFFS2_DYNRUBIN_PRIORITY  20
 #define JFFS2_LZARI_PRIORITY     30
-#define JFFS2_LZO_PRIORITY       40
 #define JFFS2_RTIME_PRIORITY     50
 #define JFFS2_ZLIB_PRIORITY      60
+#define JFFS2_LZO_PRIORITY       80
+
 
 #define JFFS2_RUBINMIPS_DISABLED /* RUBINs will be used only */
 #define JFFS2_DYNRUBIN_DISABLED  /*        for decompression */
@@ -90,5 +91,9 @@ void jffs2_rtime_exit(void);
 int jffs2_zlib_init(void);
 void jffs2_zlib_exit(void);
 #endif
+#ifdef CONFIG_JFFS2_LZO
+int jffs2_lzo_init(void);
+void jffs2_lzo_exit(void);
+#endif
 
 #endif /* __JFFS2_COMPR_H__ */
fs/jffs2/compr_lzo.c new file +110 -0

110 lines not on this page · raw message

include/linux/jffs2.h +1 -0
index 840631f..6b563ca 100644
@@ -46,6 +46,7 @@
 #define JFFS2_COMPR_COPY	0x04
 #define JFFS2_COMPR_DYNRUBIN	0x05
 #define JFFS2_COMPR_ZLIB	0x06
+#define JFFS2_COMPR_LZO		0x07
 /* Compatibility flags. */
 #define JFFS2_COMPAT_MASK 0xc000      /* What do to if an unknown nodetype is found */
 #define JFFS2_NODE_ACCURATE 0x2000

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

#1 lore raw
Quoted 15 lines · On Tue, 01 May 2007 15:47:03 +0100 Richard Purdie wrote:

Add LZO1X compression/decompression support to jffs2.

LZO's interface doesn't entirely match that required by jffs2 so a buffer and memcpy is unavoidable.

---

fs/Kconfig +0 -0
index a42f767..1645dfa 100644
@@ -1310,6 +1310,16 @@ config JFFS2_ZLIB
 
           Say 'Y' if unsure.

fs/Kconfig config JFFS2_ZLIB · line 1321

Quoted 10 lines
fs/Kconfig +9 -0
 
+config JFFS2_LZO
+	bool "JFFS2 LZO compression support" if JFFS2_COMPRESSION_OPTIONS
+	select LZO
+	depends on JFFS2_FS
+	default y
+        help
+          minilzo-based compression. Generally works better than Zlib.
+
+          Say 'Y' if unsure.

Use <tab> on the "help" line (instead of spaces) and use <tab><space><space> on the help text lines.

fs/Kconfig config JFFS2_ZLIB · line 1325

Quoted 3 lines
fs/Kconfig +0 -0
 config JFFS2_RTIME
 	bool "JFFS2 RTIME compression support" if JFFS2_COMPRESSION_OPTIONS
 	depends on JFFS2_FS

---
~Randy
*** Remember to use Documentation/SubmitChecklist when testing your code ***

#2 lore raw
In reply to Richard Purdie

Hi Richard,

Quoted 33 lines · Richard Purdie

Add LZO1X compression/decompression support to jffs2.

LZO's interface doesn't entirely match that required by jffs2 so a buffer and memcpy is unavoidable.

---
[...]
+++ b/fs/jffs2/compr_lzo.c
[...]

fs/jffs2/compr_lzo.c new file +23 -0
+static void *lzo_mem;
+static void *lzo_compress_buf;
+static DEFINE_MUTEX(deflate_mutex);
+
+static void free_workspace(void)
+{
+       vfree(lzo_mem);
+       vfree(lzo_compress_buf);
+}
+
+static int __init alloc_workspace(void)
+{
+       lzo_mem = vmalloc(LZO1X_MEM_COMPRESS);
+       lzo_compress_buf = vmalloc(lzo1x_worst_compress(PAGE_SIZE));
+
+       if (!lzo_mem || !lzo_compress_buf) {
+               printk(KERN_WARNING "Failed to allocate lzo deflate workspace\n");
+               free_workspace();
+               return -ENOMEM;
+       }
+
+       return 0;
+}

fs/jffs2/compr_lzo.c line 54

Quoted 10 lines
fs/jffs2/compr_lzo.c new file +10 -0
+
+static int jffs2_lzo_compress(unsigned char *data_in, unsigned char *cpage_out,
+                             uint32_t *sourcelen, uint32_t *dstlen, void *model)
+{
+       unsigned long compress_size;
+       int ret;
+
+       mutex_lock(&deflate_mutex);
+       ret = lzo1x_1_compress(data_in, *sourcelen, lzo_compress_buf, &compress_size, lzo_mem);
+       mutex_unlock(&deflate_mutex);

Considering we do have to memcpy() the entire compressed result to the destination output buffer later anyway (note that fs/jffs2/compr_zlib.c doesn't need to do that), do we really gain much by avoiding vmalloc() and vfree() in jffs2_lzo_compress() itself and keeping the workspace buffers pre-allocated? I ask because I always found these global static workspace buffers ugly, and all the associated code + mutex could go away if we make them local to jffs2_lzo_compress() -- as long as it doesn't hurt performance terribly, of course.

Thanks,
Satyam

#3 lore raw
Quoted 38 lines · Satyam Sharma
Quoted 25 lines · Richard Purdie

+++ b/fs/jffs2/compr_lzo.c
[...]

fs/jffs2/compr_lzo.c new file +23 -0
+static void *lzo_mem;
+static void *lzo_compress_buf;
+static DEFINE_MUTEX(deflate_mutex);
+
+static void free_workspace(void)
+{
+       vfree(lzo_mem);
+       vfree(lzo_compress_buf);
+}
+
+static int __init alloc_workspace(void)
+{
+       lzo_mem = vmalloc(LZO1X_MEM_COMPRESS);
+       lzo_compress_buf = vmalloc(lzo1x_worst_compress(PAGE_SIZE));
+
+       if (!lzo_mem || !lzo_compress_buf) {
+               printk(KERN_WARNING "Failed to allocate lzo deflate workspace\n");
+               free_workspace();
+               return -ENOMEM;
+       }
+
+       return 0;
+}

fs/jffs2/compr_lzo.c line 54

Quoted 10 lines
fs/jffs2/compr_lzo.c new file +10 -0
+
+static int jffs2_lzo_compress(unsigned char *data_in, unsigned char *cpage_out,
+                             uint32_t *sourcelen, uint32_t *dstlen, void *model)
+{
+       unsigned long compress_size;
+       int ret;
+
+       mutex_lock(&deflate_mutex);
+       ret = lzo1x_1_compress(data_in, *sourcelen, lzo_compress_buf, &compress_size, lzo_mem);
+       mutex_unlock(&deflate_mutex);

Considering we do have to memcpy() the entire compressed result to the

Quoted 8 lines

destination output buffer later anyway (note that fs/jffs2/compr_zlib.c doesn't need to do that), do we really gain much by avoiding vmalloc() and vfree() in jffs2_lzo_compress() itself and keeping the workspace buffers pre-allocated? I ask because I always found these global static workspace buffers ugly, and all the associated code + mutex could go away if we make them local to jffs2_lzo_compress() -- as long as it doesn't hurt performance terribly, of course.

memcpy is relatively fast and I'd expect continually allocing and freeing buffers to have a significant overhead compared with that and impact performance. The current approach means you don't get ENOMEM errors in the uncompress/compress paths either.

Regards,

Richard