Skip to contentSkip to conversation

AXFS: axfs_uncompress.c

PATCH In review Jared Hulbert 4 participants 8 messages Aug 21, 2008 – Aug 29, 2008 Memory technology devices (MTD)

lore
Share & tools
lore
#0 lore raw

PATCH 10/10 AXFS: axfs_uncompress.c

Handles the decompression for axfs, modeled after fs/cramfs/uncompress.c.

---

fs/axfs/axfs_uncompress.c new file +97 -0
new file mode 100644
index 0000000..b7a2060
@@ -0,0 +1,97 @@
+/*
+ * Advanced XIP File System for Linux - AXFS
+ *   Readonly, compressed, and XIP filesystem for Linux systems big and small
+ *
+ *   Modified in 2006 by Eric Anderson
+ *     from the cramfs sources fs/cramfs/uncompress.c
+ *
+ * (C) Copyright 1999 Linus Torvalds
+ *
+ * axfs_uncompress.c -
+ *  axfs interfaces to the uncompression library. There's really just
+ * three entrypoints:
+ *
+ *  - axfs_uncompress_init() - called to initialize the thing.
+ *  - axfs_uncompress_exit() - tell me when you're done
+ *  - axfs_uncompress_block() - uncompress a block.
+ *
+ * NOTE NOTE NOTE! The uncompression is entirely single-threaded. We
+ * only have one stream, and we'll initialize it only once even if it
+ * then is used by multiple filesystems.
+ *
+ */
+
+#include <linux/errno.h>
+#include <linux/vmalloc.h>
+#include <linux/zlib.h>
+#include <linux/mutex.h>
+
+static z_stream stream;
+static int initialized;
+static struct mutex axfs_uncmp_mutex;
+
+int axfs_uncompress_block(void *dst, int dstlen, void *src, int srclen)
+{
+	int err;
+	int out;
+
+	mutex_lock(&axfs_uncmp_mutex);
+
+	stream.next_in = src;
+	stream.avail_in = srclen;
+
+	stream.next_out = dst;
+	stream.avail_out = dstlen;
+
+	err = zlib_inflateReset(&stream);
+	if (err != Z_OK) {
+		printk(KERN_ERR "zlib_inflateReset error %d\n", err);
+		zlib_inflateEnd(&stream);
+		zlib_inflateInit(&stream);
+	}
+
+	err = zlib_inflate(&stream, Z_FINISH);
+	if (err != Z_STREAM_END)
+		goto err;
+
+	out = stream.total_out;
+
+	mutex_unlock(&axfs_uncmp_mutex);
+
+	return out;
+
+err:
+
+	mutex_unlock(&axfs_uncmp_mutex);
+
+	printk(KERN_ERR "Error %d while decompressing!\n", err);
+	printk(KERN_ERR "%p(%d)->%p(%d)\n", src, srclen, dst, dstlen);
+	return 0;
+}
+
+int axfs_uncompress_init(void)
+{
+	if (!initialized++) {
+
+		mutex_init(&axfs_uncmp_mutex);
+
+		stream.workspace = vmalloc(zlib_inflate_workspacesize());
+		if (!stream.workspace) {
+			initialized = 0;
+			return -ENOMEM;
+		}
+		stream.next_in = NULL;
+		stream.avail_in = 0;
+		zlib_inflateInit(&stream);
+	}
+	return 0;
+}
+
+int axfs_uncompress_exit(void)
+{
+	if (!--initialized) {
+		zlib_inflateEnd(&stream);
+		vfree(stream.workspace);
+	}
+	return 0;
+}
#1 lore raw
Quoted 31 lines · Jared Hulbert

Handles the decompression for axfs, modeled after fs/cramfs/uncompress.c.

---

fs/axfs/axfs_uncompress.c new file +21 -0
new file mode 100644
index 0000000..b7a2060
@@ -0,0 +1,97 @@
+/*
+ * Advanced XIP File System for Linux - AXFS
+ *   Readonly, compressed, and XIP filesystem for Linux systems big and small
+ *
+ *   Modified in 2006 by Eric Anderson
+ *     from the cramfs sources fs/cramfs/uncompress.c
+ *
+ * (C) Copyright 1999 Linus Torvalds
+ *
+ * axfs_uncompress.c -
+ *  axfs interfaces to the uncompression library. There's really just
+ * three entrypoints:
+ *
+ *  - axfs_uncompress_init() - called to initialize the thing.
+ *  - axfs_uncompress_exit() - tell me when you're done
+ *  - axfs_uncompress_block() - uncompress a block.
+ *
+ * NOTE NOTE NOTE! The uncompression is entirely single-threaded. We
+ * only have one stream, and we'll initialize it only once even if it
+ * then is used by multiple filesystems.
+ *

fs/axfs/axfs_uncompress.c line 31

Quoted 10 lines
fs/axfs/axfs_uncompress.c new file +10 -0
+ */
+
+#include <linux/errno.h>
+#include <linux/vmalloc.h>
+#include <linux/zlib.h>
+#include <linux/mutex.h>
+
+static z_stream stream;
+static int initialized;
+static struct mutex axfs_uncmp_mutex;

Use DEFINE_MUTEX and drop the mutex_init() down in the init function.

Quoted 56 lines
fs/axfs/axfs_uncompress.c new file +56 -0
+
+int axfs_uncompress_block(void *dst, int dstlen, void *src, int srclen)
+{
+	int err;
+	int out;
+
+	mutex_lock(&axfs_uncmp_mutex);
+
+	stream.next_in = src;
+	stream.avail_in = srclen;
+
+	stream.next_out = dst;
+	stream.avail_out = dstlen;
+
+	err = zlib_inflateReset(&stream);
+	if (err != Z_OK) {
+		printk(KERN_ERR "zlib_inflateReset error %d\n", err);
+		zlib_inflateEnd(&stream);
+		zlib_inflateInit(&stream);
+	}
+
+	err = zlib_inflate(&stream, Z_FINISH);
+	if (err != Z_STREAM_END)
+		goto err;
+
+	out = stream.total_out;
+
+	mutex_unlock(&axfs_uncmp_mutex);
+
+	return out;
+
+err:
+
+	mutex_unlock(&axfs_uncmp_mutex);
+
+	printk(KERN_ERR "Error %d while decompressing!\n", err);
+	printk(KERN_ERR "%p(%d)->%p(%d)\n", src, srclen, dst, dstlen);
+	return 0;
+}
+
+int axfs_uncompress_init(void)
+{
+	if (!initialized++) {
+
+		mutex_init(&axfs_uncmp_mutex);
+
+		stream.workspace = vmalloc(zlib_inflate_workspacesize());
+		if (!stream.workspace) {
+			initialized = 0;
+			return -ENOMEM;
+		}
+		stream.next_in = NULL;
+		stream.avail_in = 0;
+		zlib_inflateInit(&stream);
+	}
+	return 0;

fs/axfs/axfs_uncompress.c line 97

Quoted 10 lines
fs/axfs/axfs_uncompress.c new file +10 -0
+}
+
+int axfs_uncompress_exit(void)
+{
+	if (!--initialized) {
+		zlib_inflateEnd(&stream);
+		vfree(stream.workspace);
+	}
+	return 0;
+}

axfs_uncompress_init() and axfs_uncompress_exit() are only called during init and exit of the module, no need for the initialized variable and the functions can be annotated with __init and __exit.

#2 lore raw
Quoted 1 line

Use DEFINE_MUTEX and drop the mutex_init() down in the init function.

okay. by drop you mean delete?

Quoted 3 lines

axfs_uncompress_init() and axfs_uncompress_exit() are only called during init and exit of the module, no need for the initialized variable and the functions can be annotated with __init and __exit.

can be annotated or should be?

#3 lore raw
Quoted 3 lines · Jared Hulbert
Quoted 1 line

Use DEFINE_MUTEX and drop the mutex_init() down in the init function.

okay. by drop you mean delete?

Yes.

Quoted 5 lines
Quoted 3 lines

axfs_uncompress_init() and axfs_uncompress_exit() are only called during init and exit of the module, no need for the initialized variable and the functions can be annotated with __init and __exit.

can be annotated or should be?

Should be. We only need them once during init and cleanup. If you want to call axfs_uncompress_exit() from init_axfs_fs() to clean up in case of register_filesystem failing, you can't annotate axfs_uncompress_exit() with __exit.

Sven

#4 lore raw
In reply to Jared Hulbert

fs/axfs/axfs_uncompress.c line 51

Quoted 6 lines · Jared Hulbert
fs/axfs/axfs_uncompress.c new file +6 -0
+	err = zlib_inflateReset(&stream);
+	if (err != Z_OK) {
+		printk(KERN_ERR "zlib_inflateReset error %d\n", err);
+		zlib_inflateEnd(&stream);
+		zlib_inflateInit(&stream);
+	}

Jared,

just FYI, are you aware that LZO which is also present in the kernel is much faster on decompress than zlib, while its compression is only slightly worse?

I do not remember the digits, but last time I tested UBIFS, LZO decompression was about 3 times faster than zlib on OMAP3. This depends on architecture, etc of course. This may matter a lot if one is fighting for faster system boot-up. So you might consider supporting LZO as well.

Signature · 2 lines
Best regards,
Artem Bityutskiy (Битюцкий Артём)
#5 lore raw
Quoted 11 lines · Artem Bityutskiy

fs/axfs/axfs_uncompress.c line 51

Quoted 6 lines · Jared Hulbert
fs/axfs/axfs_uncompress.c new file +6 -0
+	err = zlib_inflateReset(&stream);
+	if (err != Z_OK) {
+		printk(KERN_ERR "zlib_inflateReset error %d\n", err);
+		zlib_inflateEnd(&stream);
+		zlib_inflateInit(&stream);
+	}

just FYI, are you aware that LZO which is also present in the kernel is much faster on decompress than zlib, while its compression is only slightly worse?

If you want support for multiple decompression algorithms, you can switch from using zlib_inflate*() directly to calling zlib through the crypto API. Then you can call crypto_alloc_comp() with the correct decompression algorithm name.

For squashfs, I had to modify only ca. 40 lines of code.

You do need a new zlib crypto module, as the existing deflate crypto module uses the raw deflate format instead of the zlib format, and has some parameters tuned for its use in IPSec.

I hope to have some patches ready next week...

With kind regards,

Geert Uytterhoeven
Software Architect

Sony Techsoft Centre Europe
The Corporate Village · Da Vincilaan 7-D1 · B-1935 Zaventem · Belgium

Phone:    +32 (0)2 700 8453
Fax:      +32 (0)2 700 8622
E-mail:   [email protected]
Internet: http://www.sony-europe.com/

A division of Sony Europe (Belgium) N.V.
VAT BE 0413.825.160 · RPR Brussels
Fortis · BIC GEBABEBB · IBAN BE41293037680010

#6 lore raw
Quoted 6 lines

If you want support for multiple decompression algorithms, you can switch from using zlib_inflate*() directly to calling zlib through the crypto API. Then you can call crypto_alloc_comp() with the correct decompression algorithm name.

For squashfs, I had to modify only ca. 40 lines of code.

I definately want to support multiple formats. I have a flag in the superblock all ready to go for that. One problem. I'm not sure how to do it. Can you point us to some reference code?

#7 lore raw

Hi Jared,

Quoted 10 lines · Jared Hulbert
Quoted 6 lines

If you want support for multiple decompression algorithms, you can switch from using zlib_inflate*() directly to calling zlib through the crypto API. Then you can call crypto_alloc_comp() with the correct decompression algorithm name.

For squashfs, I had to modify only ca. 40 lines of code.

I definately want to support multiple formats. I have a flag in the superblock all ready to go for that. One problem. I'm not sure how to do it. Can you point us to some reference code?

Please take a look at the email with subject

[patch 3/3] squashfs: Switch from zlib/inflate to "zlib" crypto module

With kind regards,

Geert Uytterhoeven
Software Architect

Sony Techsoft Centre Europe
The Corporate Village · Da Vincilaan 7-D1 · B-1935 Zaventem · Belgium

Phone:    +32 (0)2 700 8453
Fax:      +32 (0)2 700 8622
E-mail:   [email protected]
Internet: http://www.sony-europe.com/

A division of Sony Europe (Belgium) N.V. VAT BE 0413.825.160 · RPR Brussels Fortis · BIC GEBABEBB · IBAN BE41293037680010