rev |
line source |
gokhlayeh@9257
|
1 From: Phillip Lougher <phillip@lougher.demon.co.uk>
|
gokhlayeh@9257
|
2 Date: Thu, 9 Dec 2010 02:02:29 +0000 (+0000)
|
gokhlayeh@9257
|
3 Subject: Squashfs: add XZ compression support
|
gokhlayeh@9257
|
4 X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fpkl%2Fsquashfs-xz.git;a=commitdiff_plain;h=d3e6969b9ff1f3a3c6bf3da71433c77046aa80e4
|
gokhlayeh@9257
|
5
|
gokhlayeh@9257
|
6 Squashfs: add XZ compression support
|
gokhlayeh@9257
|
7
|
gokhlayeh@9257
|
8 Add XZ decompressor wrapper code.
|
gokhlayeh@9257
|
9
|
gokhlayeh@9257
|
10 Signed-off-by: Phillip Lougher <phillip@lougher.demon.co.uk>
|
gokhlayeh@9257
|
11 ---
|
gokhlayeh@9257
|
12
|
gokhlayeh@9257
|
13 diff --git a/fs/squashfs/squashfs_fs.h b/fs/squashfs/squashfs_fs.h
|
gokhlayeh@9257
|
14 index c5137fc..39533fe 100644
|
gokhlayeh@9257
|
15 --- a/fs/squashfs/squashfs_fs.h
|
gokhlayeh@9257
|
16 +++ b/fs/squashfs/squashfs_fs.h
|
gokhlayeh@9257
|
17 @@ -238,6 +238,7 @@ struct meta_index {
|
gokhlayeh@9257
|
18 #define ZLIB_COMPRESSION 1
|
gokhlayeh@9257
|
19 #define LZMA_COMPRESSION 2
|
gokhlayeh@9257
|
20 #define LZO_COMPRESSION 3
|
gokhlayeh@9257
|
21 +#define XZ_COMPRESSION 4
|
gokhlayeh@9257
|
22
|
gokhlayeh@9257
|
23 struct squashfs_super_block {
|
gokhlayeh@9257
|
24 __le32 s_magic;
|
gokhlayeh@9257
|
25 diff --git a/fs/squashfs/xz_wrapper.c b/fs/squashfs/xz_wrapper.c
|
gokhlayeh@9257
|
26 new file mode 100644
|
gokhlayeh@9257
|
27 index 0000000..053fe35
|
gokhlayeh@9257
|
28 --- /dev/null
|
gokhlayeh@9257
|
29 +++ b/fs/squashfs/xz_wrapper.c
|
gokhlayeh@9257
|
30 @@ -0,0 +1,153 @@
|
gokhlayeh@9257
|
31 +/*
|
gokhlayeh@9257
|
32 + * Squashfs - a compressed read only filesystem for Linux
|
gokhlayeh@9257
|
33 + *
|
gokhlayeh@9257
|
34 + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
|
gokhlayeh@9257
|
35 + * Phillip Lougher <phillip@lougher.demon.co.uk>
|
gokhlayeh@9257
|
36 + *
|
gokhlayeh@9257
|
37 + * This program is free software; you can redistribute it and/or
|
gokhlayeh@9257
|
38 + * modify it under the terms of the GNU General Public License
|
gokhlayeh@9257
|
39 + * as published by the Free Software Foundation; either version 2,
|
gokhlayeh@9257
|
40 + * or (at your option) any later version.
|
gokhlayeh@9257
|
41 + *
|
gokhlayeh@9257
|
42 + * This program is distributed in the hope that it will be useful,
|
gokhlayeh@9257
|
43 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
gokhlayeh@9257
|
44 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
gokhlayeh@9257
|
45 + * GNU General Public License for more details.
|
gokhlayeh@9257
|
46 + *
|
gokhlayeh@9257
|
47 + * You should have received a copy of the GNU General Public License
|
gokhlayeh@9257
|
48 + * along with this program; if not, write to the Free Software
|
gokhlayeh@9257
|
49 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
gokhlayeh@9257
|
50 + *
|
gokhlayeh@9257
|
51 + * xz_wrapper.c
|
gokhlayeh@9257
|
52 + */
|
gokhlayeh@9257
|
53 +
|
gokhlayeh@9257
|
54 +
|
gokhlayeh@9257
|
55 +#include <linux/mutex.h>
|
gokhlayeh@9257
|
56 +#include <linux/buffer_head.h>
|
gokhlayeh@9257
|
57 +#include <linux/slab.h>
|
gokhlayeh@9257
|
58 +#include <linux/xz.h>
|
gokhlayeh@9257
|
59 +
|
gokhlayeh@9257
|
60 +#include "squashfs_fs.h"
|
gokhlayeh@9257
|
61 +#include "squashfs_fs_sb.h"
|
gokhlayeh@9257
|
62 +#include "squashfs_fs_i.h"
|
gokhlayeh@9257
|
63 +#include "squashfs.h"
|
gokhlayeh@9257
|
64 +#include "decompressor.h"
|
gokhlayeh@9257
|
65 +
|
gokhlayeh@9257
|
66 +struct squashfs_xz {
|
gokhlayeh@9257
|
67 + struct xz_dec *state;
|
gokhlayeh@9257
|
68 + struct xz_buf buf;
|
gokhlayeh@9257
|
69 +};
|
gokhlayeh@9257
|
70 +
|
gokhlayeh@9257
|
71 +static void *squashfs_xz_init(struct squashfs_sb_info *msblk)
|
gokhlayeh@9257
|
72 +{
|
gokhlayeh@9257
|
73 + int block_size = max_t(int, msblk->block_size, SQUASHFS_METADATA_SIZE);
|
gokhlayeh@9257
|
74 +
|
gokhlayeh@9257
|
75 + struct squashfs_xz *stream = kmalloc(sizeof(*stream), GFP_KERNEL);
|
gokhlayeh@9257
|
76 + if (stream == NULL)
|
gokhlayeh@9257
|
77 + goto failed;
|
gokhlayeh@9257
|
78 + stream->state = xz_dec_init(XZ_PREALLOC, block_size);
|
gokhlayeh@9257
|
79 + if (stream->state == NULL)
|
gokhlayeh@9257
|
80 + goto failed;
|
gokhlayeh@9257
|
81 +
|
gokhlayeh@9257
|
82 + return stream;
|
gokhlayeh@9257
|
83 +
|
gokhlayeh@9257
|
84 +failed:
|
gokhlayeh@9257
|
85 + ERROR("Failed to allocate xz workspace\n");
|
gokhlayeh@9257
|
86 + kfree(stream);
|
gokhlayeh@9257
|
87 + return NULL;
|
gokhlayeh@9257
|
88 +}
|
gokhlayeh@9257
|
89 +
|
gokhlayeh@9257
|
90 +
|
gokhlayeh@9257
|
91 +static void squashfs_xz_free(void *strm)
|
gokhlayeh@9257
|
92 +{
|
gokhlayeh@9257
|
93 + struct squashfs_xz *stream = strm;
|
gokhlayeh@9257
|
94 +
|
gokhlayeh@9257
|
95 + if (stream) {
|
gokhlayeh@9257
|
96 + xz_dec_end(stream->state);
|
gokhlayeh@9257
|
97 + kfree(stream);
|
gokhlayeh@9257
|
98 + }
|
gokhlayeh@9257
|
99 +}
|
gokhlayeh@9257
|
100 +
|
gokhlayeh@9257
|
101 +
|
gokhlayeh@9257
|
102 +static int squashfs_xz_uncompress(struct squashfs_sb_info *msblk, void **buffer,
|
gokhlayeh@9257
|
103 + struct buffer_head **bh, int b, int offset, int length, int srclength,
|
gokhlayeh@9257
|
104 + int pages)
|
gokhlayeh@9257
|
105 +{
|
gokhlayeh@9257
|
106 + enum xz_ret xz_err;
|
gokhlayeh@9257
|
107 + int avail, total = 0, k = 0, page = 0;
|
gokhlayeh@9257
|
108 + struct squashfs_xz *stream = msblk->stream;
|
gokhlayeh@9257
|
109 +
|
gokhlayeh@9257
|
110 + mutex_lock(&msblk->read_data_mutex);
|
gokhlayeh@9257
|
111 +
|
gokhlayeh@9257
|
112 + xz_dec_reset(stream->state);
|
gokhlayeh@9257
|
113 + stream->buf.in_pos = 0;
|
gokhlayeh@9257
|
114 + stream->buf.in_size = 0;
|
gokhlayeh@9257
|
115 + stream->buf.out_pos = 0;
|
gokhlayeh@9257
|
116 + stream->buf.out_size = PAGE_CACHE_SIZE;
|
gokhlayeh@9257
|
117 + stream->buf.out = buffer[page++];
|
gokhlayeh@9257
|
118 +
|
gokhlayeh@9257
|
119 + do {
|
gokhlayeh@9257
|
120 + if (stream->buf.in_pos == stream->buf.in_size && k < b) {
|
gokhlayeh@9257
|
121 + avail = min(length, msblk->devblksize - offset);
|
gokhlayeh@9257
|
122 + length -= avail;
|
gokhlayeh@9257
|
123 + wait_on_buffer(bh[k]);
|
gokhlayeh@9257
|
124 + if (!buffer_uptodate(bh[k]))
|
gokhlayeh@9257
|
125 + goto release_mutex;
|
gokhlayeh@9257
|
126 +
|
gokhlayeh@9257
|
127 + if (avail == 0) {
|
gokhlayeh@9257
|
128 + offset = 0;
|
gokhlayeh@9257
|
129 + put_bh(bh[k++]);
|
gokhlayeh@9257
|
130 + continue;
|
gokhlayeh@9257
|
131 + }
|
gokhlayeh@9257
|
132 +
|
gokhlayeh@9257
|
133 + stream->buf.in = bh[k]->b_data + offset;
|
gokhlayeh@9257
|
134 + stream->buf.in_size = avail;
|
gokhlayeh@9257
|
135 + stream->buf.in_pos = 0;
|
gokhlayeh@9257
|
136 + offset = 0;
|
gokhlayeh@9257
|
137 + }
|
gokhlayeh@9257
|
138 +
|
gokhlayeh@9257
|
139 + if (stream->buf.out_pos == stream->buf.out_size
|
gokhlayeh@9257
|
140 + && page < pages) {
|
gokhlayeh@9257
|
141 + stream->buf.out = buffer[page++];
|
gokhlayeh@9257
|
142 + stream->buf.out_pos = 0;
|
gokhlayeh@9257
|
143 + total += PAGE_CACHE_SIZE;
|
gokhlayeh@9257
|
144 + }
|
gokhlayeh@9257
|
145 +
|
gokhlayeh@9257
|
146 + xz_err = xz_dec_run(stream->state, &stream->buf);
|
gokhlayeh@9257
|
147 +
|
gokhlayeh@9257
|
148 + if (stream->buf.in_pos == stream->buf.in_size && k < b)
|
gokhlayeh@9257
|
149 + put_bh(bh[k++]);
|
gokhlayeh@9257
|
150 + } while (xz_err == XZ_OK);
|
gokhlayeh@9257
|
151 +
|
gokhlayeh@9257
|
152 + if (xz_err != XZ_STREAM_END) {
|
gokhlayeh@9257
|
153 + ERROR("xz_dec_run error, data probably corrupt\n");
|
gokhlayeh@9257
|
154 + goto release_mutex;
|
gokhlayeh@9257
|
155 + }
|
gokhlayeh@9257
|
156 +
|
gokhlayeh@9257
|
157 + if (k < b) {
|
gokhlayeh@9257
|
158 + ERROR("xz_uncompress error, input remaining\n");
|
gokhlayeh@9257
|
159 + goto release_mutex;
|
gokhlayeh@9257
|
160 + }
|
gokhlayeh@9257
|
161 +
|
gokhlayeh@9257
|
162 + total += stream->buf.out_pos;
|
gokhlayeh@9257
|
163 + mutex_unlock(&msblk->read_data_mutex);
|
gokhlayeh@9257
|
164 + return total;
|
gokhlayeh@9257
|
165 +
|
gokhlayeh@9257
|
166 +release_mutex:
|
gokhlayeh@9257
|
167 + mutex_unlock(&msblk->read_data_mutex);
|
gokhlayeh@9257
|
168 +
|
gokhlayeh@9257
|
169 + for (; k < b; k++)
|
gokhlayeh@9257
|
170 + put_bh(bh[k]);
|
gokhlayeh@9257
|
171 +
|
gokhlayeh@9257
|
172 + return -EIO;
|
gokhlayeh@9257
|
173 +}
|
gokhlayeh@9257
|
174 +
|
gokhlayeh@9257
|
175 +const struct squashfs_decompressor squashfs_xz_comp_ops = {
|
gokhlayeh@9257
|
176 + .init = squashfs_xz_init,
|
gokhlayeh@9257
|
177 + .free = squashfs_xz_free,
|
gokhlayeh@9257
|
178 + .decompress = squashfs_xz_uncompress,
|
gokhlayeh@9257
|
179 + .id = XZ_COMPRESSION,
|
gokhlayeh@9257
|
180 + .name = "xz",
|
gokhlayeh@9257
|
181 + .supported = 1
|
gokhlayeh@9257
|
182 +};
|
gokhlayeh@9257
|
183 +
|