aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-12-14 17:42:53 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-12-14 17:42:53 -0500
commit7a02d089695a1217992434f03a78aa32bad85b5c (patch)
tree606288e042051e3c280275b1de7fa4be064420c6
parent980f3c344ff1cb4a8be9a169c6bde2dc74ca6288 (diff)
parent62421645bb702c077ee5a462815525106cb53bcf (diff)
Merge tag 'squashfs-updates' of git://git.kernel.org/pub/scm/linux/kernel/git/pkl/squashfs-next
Pull squashfs update from Phillip Lougher: "These patches optionally add LZ4 compression support to Squashfs. LZ4 is a lightweight compression algorithm which can be used on embedded systems to reduce CPU and memory overhead (in comparison to the standard zlib compression). These patches add the wrapper code to allow Squashfs to use the existing LZ4 decompression code, and the necessary configuration option" * tag 'squashfs-updates' of git://git.kernel.org/pub/scm/linux/kernel/git/pkl/squashfs-next: Squashfs: Add LZ4 compression configuration option Squashfs: add LZ4 compression support
-rw-r--r--Documentation/filesystems/squashfs.txt8
-rw-r--r--fs/squashfs/Kconfig15
-rw-r--r--fs/squashfs/Makefile1
-rw-r--r--fs/squashfs/decompressor.c7
-rw-r--r--fs/squashfs/decompressor.h4
-rw-r--r--fs/squashfs/lz4_wrapper.c142
-rw-r--r--fs/squashfs/squashfs_fs.h1
7 files changed, 174 insertions, 4 deletions
diff --git a/Documentation/filesystems/squashfs.txt b/Documentation/filesystems/squashfs.txt
index 403c090aca39..e5274f84dc56 100644
--- a/Documentation/filesystems/squashfs.txt
+++ b/Documentation/filesystems/squashfs.txt
@@ -2,10 +2,10 @@ SQUASHFS 4.0 FILESYSTEM
2======================= 2=======================
3 3
4Squashfs is a compressed read-only filesystem for Linux. 4Squashfs is a compressed read-only filesystem for Linux.
5It uses zlib/lzo/xz compression to compress files, inodes and directories. 5It uses zlib, lz4, lzo, or xz compression to compress files, inodes and
6Inodes in the system are very small and all blocks are packed to minimise 6directories. Inodes in the system are very small and all blocks are packed to
7data overhead. Block sizes greater than 4K are supported up to a maximum 7minimise data overhead. Block sizes greater than 4K are supported up to a
8of 1Mbytes (default block size 128K). 8maximum of 1Mbytes (default block size 128K).
9 9
10Squashfs is intended for general read-only filesystem use, for archival 10Squashfs is intended for general read-only filesystem use, for archival
11use (i.e. in cases where a .tar.gz file may be used), and in constrained 11use (i.e. in cases where a .tar.gz file may be used), and in constrained
diff --git a/fs/squashfs/Kconfig b/fs/squashfs/Kconfig
index b6fa8657dcbc..ffb093e72b6c 100644
--- a/fs/squashfs/Kconfig
+++ b/fs/squashfs/Kconfig
@@ -120,6 +120,21 @@ config SQUASHFS_ZLIB
120 120
121 If unsure, say Y. 121 If unsure, say Y.
122 122
123config SQUASHFS_LZ4
124 bool "Include support for LZ4 compressed file systems"
125 depends on SQUASHFS
126 select LZ4_DECOMPRESS
127 help
128 Saying Y here includes support for reading Squashfs file systems
129 compressed with LZ4 compression. LZ4 compression is mainly
130 aimed at embedded systems with slower CPUs where the overheads
131 of zlib are too high.
132
133 LZ4 is not the standard compression used in Squashfs and so most
134 file systems will be readable without selecting this option.
135
136 If unsure, say N.
137
123config SQUASHFS_LZO 138config SQUASHFS_LZO
124 bool "Include support for LZO compressed file systems" 139 bool "Include support for LZO compressed file systems"
125 depends on SQUASHFS 140 depends on SQUASHFS
diff --git a/fs/squashfs/Makefile b/fs/squashfs/Makefile
index 4132520b4ff2..246a6f329d89 100644
--- a/fs/squashfs/Makefile
+++ b/fs/squashfs/Makefile
@@ -11,6 +11,7 @@ squashfs-$(CONFIG_SQUASHFS_DECOMP_SINGLE) += decompressor_single.o
11squashfs-$(CONFIG_SQUASHFS_DECOMP_MULTI) += decompressor_multi.o 11squashfs-$(CONFIG_SQUASHFS_DECOMP_MULTI) += decompressor_multi.o
12squashfs-$(CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU) += decompressor_multi_percpu.o 12squashfs-$(CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU) += decompressor_multi_percpu.o
13squashfs-$(CONFIG_SQUASHFS_XATTR) += xattr.o xattr_id.o 13squashfs-$(CONFIG_SQUASHFS_XATTR) += xattr.o xattr_id.o
14squashfs-$(CONFIG_SQUASHFS_LZ4) += lz4_wrapper.o
14squashfs-$(CONFIG_SQUASHFS_LZO) += lzo_wrapper.o 15squashfs-$(CONFIG_SQUASHFS_LZO) += lzo_wrapper.o
15squashfs-$(CONFIG_SQUASHFS_XZ) += xz_wrapper.o 16squashfs-$(CONFIG_SQUASHFS_XZ) += xz_wrapper.o
16squashfs-$(CONFIG_SQUASHFS_ZLIB) += zlib_wrapper.o 17squashfs-$(CONFIG_SQUASHFS_ZLIB) += zlib_wrapper.o
diff --git a/fs/squashfs/decompressor.c b/fs/squashfs/decompressor.c
index ac22fe73b0ad..e9034bf6e5ae 100644
--- a/fs/squashfs/decompressor.c
+++ b/fs/squashfs/decompressor.c
@@ -41,6 +41,12 @@ static const struct squashfs_decompressor squashfs_lzma_unsupported_comp_ops = {
41 NULL, NULL, NULL, NULL, LZMA_COMPRESSION, "lzma", 0 41 NULL, NULL, NULL, NULL, LZMA_COMPRESSION, "lzma", 0
42}; 42};
43 43
44#ifndef CONFIG_SQUASHFS_LZ4
45static const struct squashfs_decompressor squashfs_lz4_comp_ops = {
46 NULL, NULL, NULL, NULL, LZ4_COMPRESSION, "lz4", 0
47};
48#endif
49
44#ifndef CONFIG_SQUASHFS_LZO 50#ifndef CONFIG_SQUASHFS_LZO
45static const struct squashfs_decompressor squashfs_lzo_comp_ops = { 51static const struct squashfs_decompressor squashfs_lzo_comp_ops = {
46 NULL, NULL, NULL, NULL, LZO_COMPRESSION, "lzo", 0 52 NULL, NULL, NULL, NULL, LZO_COMPRESSION, "lzo", 0
@@ -65,6 +71,7 @@ static const struct squashfs_decompressor squashfs_unknown_comp_ops = {
65 71
66static const struct squashfs_decompressor *decompressor[] = { 72static const struct squashfs_decompressor *decompressor[] = {
67 &squashfs_zlib_comp_ops, 73 &squashfs_zlib_comp_ops,
74 &squashfs_lz4_comp_ops,
68 &squashfs_lzo_comp_ops, 75 &squashfs_lzo_comp_ops,
69 &squashfs_xz_comp_ops, 76 &squashfs_xz_comp_ops,
70 &squashfs_lzma_unsupported_comp_ops, 77 &squashfs_lzma_unsupported_comp_ops,
diff --git a/fs/squashfs/decompressor.h b/fs/squashfs/decompressor.h
index af0985321808..a25713c031a5 100644
--- a/fs/squashfs/decompressor.h
+++ b/fs/squashfs/decompressor.h
@@ -46,6 +46,10 @@ static inline void *squashfs_comp_opts(struct squashfs_sb_info *msblk,
46extern const struct squashfs_decompressor squashfs_xz_comp_ops; 46extern const struct squashfs_decompressor squashfs_xz_comp_ops;
47#endif 47#endif
48 48
49#ifdef CONFIG_SQUASHFS_LZ4
50extern const struct squashfs_decompressor squashfs_lz4_comp_ops;
51#endif
52
49#ifdef CONFIG_SQUASHFS_LZO 53#ifdef CONFIG_SQUASHFS_LZO
50extern const struct squashfs_decompressor squashfs_lzo_comp_ops; 54extern const struct squashfs_decompressor squashfs_lzo_comp_ops;
51#endif 55#endif
diff --git a/fs/squashfs/lz4_wrapper.c b/fs/squashfs/lz4_wrapper.c
new file mode 100644
index 000000000000..c31e2bc9c081
--- /dev/null
+++ b/fs/squashfs/lz4_wrapper.c
@@ -0,0 +1,142 @@
1/*
2 * Copyright (c) 2013, 2014
3 * Phillip Lougher <phillip@squashfs.org.uk>
4 *
5 * This work is licensed under the terms of the GNU GPL, version 2. See
6 * the COPYING file in the top-level directory.
7 */
8
9#include <linux/buffer_head.h>
10#include <linux/mutex.h>
11#include <linux/slab.h>
12#include <linux/vmalloc.h>
13#include <linux/lz4.h>
14
15#include "squashfs_fs.h"
16#include "squashfs_fs_sb.h"
17#include "squashfs.h"
18#include "decompressor.h"
19#include "page_actor.h"
20
21#define LZ4_LEGACY 1
22
23struct lz4_comp_opts {
24 __le32 version;
25 __le32 flags;
26};
27
28struct squashfs_lz4 {
29 void *input;
30 void *output;
31};
32
33
34static void *lz4_comp_opts(struct squashfs_sb_info *msblk,
35 void *buff, int len)
36{
37 struct lz4_comp_opts *comp_opts = buff;
38
39 /* LZ4 compressed filesystems always have compression options */
40 if (comp_opts == NULL || len < sizeof(*comp_opts))
41 return ERR_PTR(-EIO);
42
43 if (le32_to_cpu(comp_opts->version) != LZ4_LEGACY) {
44 /* LZ4 format currently used by the kernel is the 'legacy'
45 * format */
46 ERROR("Unknown LZ4 version\n");
47 return ERR_PTR(-EINVAL);
48 }
49
50 return NULL;
51}
52
53
54static void *lz4_init(struct squashfs_sb_info *msblk, void *buff)
55{
56 int block_size = max_t(int, msblk->block_size, SQUASHFS_METADATA_SIZE);
57 struct squashfs_lz4 *stream;
58
59 stream = kzalloc(sizeof(*stream), GFP_KERNEL);
60 if (stream == NULL)
61 goto failed;
62 stream->input = vmalloc(block_size);
63 if (stream->input == NULL)
64 goto failed2;
65 stream->output = vmalloc(block_size);
66 if (stream->output == NULL)
67 goto failed3;
68
69 return stream;
70
71failed3:
72 vfree(stream->input);
73failed2:
74 kfree(stream);
75failed:
76 ERROR("Failed to initialise LZ4 decompressor\n");
77 return ERR_PTR(-ENOMEM);
78}
79
80
81static void lz4_free(void *strm)
82{
83 struct squashfs_lz4 *stream = strm;
84
85 if (stream) {
86 vfree(stream->input);
87 vfree(stream->output);
88 }
89 kfree(stream);
90}
91
92
93static int lz4_uncompress(struct squashfs_sb_info *msblk, void *strm,
94 struct buffer_head **bh, int b, int offset, int length,
95 struct squashfs_page_actor *output)
96{
97 struct squashfs_lz4 *stream = strm;
98 void *buff = stream->input, *data;
99 int avail, i, bytes = length, res;
100 size_t dest_len = output->length;
101
102 for (i = 0; i < b; i++) {
103 avail = min(bytes, msblk->devblksize - offset);
104 memcpy(buff, bh[i]->b_data + offset, avail);
105 buff += avail;
106 bytes -= avail;
107 offset = 0;
108 put_bh(bh[i]);
109 }
110
111 res = lz4_decompress_unknownoutputsize(stream->input, length,
112 stream->output, &dest_len);
113 if (res)
114 return -EIO;
115
116 bytes = dest_len;
117 data = squashfs_first_page(output);
118 buff = stream->output;
119 while (data) {
120 if (bytes <= PAGE_CACHE_SIZE) {
121 memcpy(data, buff, bytes);
122 break;
123 }
124 memcpy(data, buff, PAGE_CACHE_SIZE);
125 buff += PAGE_CACHE_SIZE;
126 bytes -= PAGE_CACHE_SIZE;
127 data = squashfs_next_page(output);
128 }
129 squashfs_finish_page(output);
130
131 return dest_len;
132}
133
134const struct squashfs_decompressor squashfs_lz4_comp_ops = {
135 .init = lz4_init,
136 .comp_opts = lz4_comp_opts,
137 .free = lz4_free,
138 .decompress = lz4_uncompress,
139 .id = LZ4_COMPRESSION,
140 .name = "lz4",
141 .supported = 1
142};
diff --git a/fs/squashfs/squashfs_fs.h b/fs/squashfs/squashfs_fs.h
index 4b2beda49498..506f4ba5b983 100644
--- a/fs/squashfs/squashfs_fs.h
+++ b/fs/squashfs/squashfs_fs.h
@@ -240,6 +240,7 @@ struct meta_index {
240#define LZMA_COMPRESSION 2 240#define LZMA_COMPRESSION 2
241#define LZO_COMPRESSION 3 241#define LZO_COMPRESSION 3
242#define XZ_COMPRESSION 4 242#define XZ_COMPRESSION 4
243#define LZ4_COMPRESSION 5
243 244
244struct squashfs_super_block { 245struct squashfs_super_block {
245 __le32 s_magic; 246 __le32 s_magic;