Root/target/linux/generic/patches-2.6.30/003-squashfs_add_decompressor_framework.patch

1From 327fbf47a419befc6bff74f3ca42d2b6f0841903 Mon Sep 17 00:00:00 2001
2From: Phillip Lougher <phillip@lougher.demon.co.uk>
3Date: Tue, 6 Oct 2009 04:04:15 +0100
4Subject: [PATCH] Squashfs: add a decompressor framework
5
6This adds a decompressor framework which allows multiple compression
7algorithms to be cleanly supported.
8
9Also update zlib wrapper and other code to use the new framework.
10
11Signed-off-by: Phillip Lougher <phillip@lougher.demon.co.uk>
12---
13 fs/squashfs/Makefile | 2 +-
14 fs/squashfs/block.c | 6 ++--
15 fs/squashfs/decompressor.c | 58 ++++++++++++++++++++++++++++++++++++++++++
16 fs/squashfs/decompressor.h | 55 +++++++++++++++++++++++++++++++++++++++
17 fs/squashfs/squashfs.h | 14 +++++-----
18 fs/squashfs/squashfs_fs_sb.h | 41 +++++++++++++++--------------
19 fs/squashfs/super.c | 45 ++++++++++++++++++-------------
20 fs/squashfs/zlib_wrapper.c | 17 ++++++++++--
21 8 files changed, 185 insertions(+), 53 deletions(-)
22 create mode 100644 fs/squashfs/decompressor.c
23 create mode 100644 fs/squashfs/decompressor.h
24
25--- a/fs/squashfs/Makefile
26+++ b/fs/squashfs/Makefile
27@@ -4,4 +4,4 @@
28 
29 obj-$(CONFIG_SQUASHFS) += squashfs.o
30 squashfs-y += block.o cache.o dir.o export.o file.o fragment.o id.o inode.o
31-squashfs-y += namei.o super.o symlink.o zlib_wrapper.o
32+squashfs-y += namei.o super.o symlink.o zlib_wrapper.o decompressor.o
33--- a/fs/squashfs/block.c
34+++ b/fs/squashfs/block.c
35@@ -36,7 +36,7 @@
36 #include "squashfs_fs_sb.h"
37 #include "squashfs_fs_i.h"
38 #include "squashfs.h"
39-
40+#include "decompressor.h"
41 /*
42  * Read the metadata block length, this is stored in the first two
43  * bytes of the metadata block.
44@@ -151,8 +151,8 @@ int squashfs_read_data(struct super_bloc
45     }
46 
47     if (compressed) {
48- length = zlib_uncompress(msblk, buffer, bh, b, offset, length,
49- srclength, pages);
50+ length = squashfs_decompress(msblk, buffer, bh, b, offset,
51+ length, srclength, pages);
52         if (length < 0)
53             goto read_failure;
54     } else {
55--- /dev/null
56+++ b/fs/squashfs/decompressor.c
57@@ -0,0 +1,58 @@
58+/*
59+ * Squashfs - a compressed read only filesystem for Linux
60+ *
61+ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
62+ * Phillip Lougher <phillip@lougher.demon.co.uk>
63+ *
64+ * This program is free software; you can redistribute it and/or
65+ * modify it under the terms of the GNU General Public License
66+ * as published by the Free Software Foundation; either version 2,
67+ * or (at your option) any later version.
68+ *
69+ * This program is distributed in the hope that it will be useful,
70+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
71+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
72+ * GNU General Public License for more details.
73+ *
74+ * You should have received a copy of the GNU General Public License
75+ * along with this program; if not, write to the Free Software
76+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
77+ *
78+ * decompressor.c
79+ */
80+
81+#include <linux/types.h>
82+#include <linux/mutex.h>
83+#include <linux/buffer_head.h>
84+
85+#include "squashfs_fs.h"
86+#include "squashfs_fs_sb.h"
87+#include "squashfs_fs_i.h"
88+#include "decompressor.h"
89+#include "squashfs.h"
90+
91+/*
92+ * This file (and decompressor.h) implements a decompressor framework for
93+ * Squashfs, allowing multiple decompressors to be easily supported
94+ */
95+
96+static const struct squashfs_decompressor squashfs_unknown_comp_ops = {
97+ NULL, NULL, NULL, 0, "unknown", 0
98+};
99+
100+static const struct squashfs_decompressor *decompressor[] = {
101+ &squashfs_zlib_comp_ops,
102+ &squashfs_unknown_comp_ops
103+};
104+
105+
106+const struct squashfs_decompressor *squashfs_lookup_decompressor(int id)
107+{
108+ int i;
109+
110+ for (i = 0; decompressor[i]->id; i++)
111+ if (id == decompressor[i]->id)
112+ break;
113+
114+ return decompressor[i];
115+}
116--- /dev/null
117+++ b/fs/squashfs/decompressor.h
118@@ -0,0 +1,55 @@
119+#ifndef DECOMPRESSOR_H
120+#define DECOMPRESSOR_H
121+/*
122+ * Squashfs - a compressed read only filesystem for Linux
123+ *
124+ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
125+ * Phillip Lougher <phillip@lougher.demon.co.uk>
126+ *
127+ * This program is free software; you can redistribute it and/or
128+ * modify it under the terms of the GNU General Public License
129+ * as published by the Free Software Foundation; either version 2,
130+ * or (at your option) any later version.
131+ *
132+ * This program is distributed in the hope that it will be useful,
133+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
134+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
135+ * GNU General Public License for more details.
136+ *
137+ * You should have received a copy of the GNU General Public License
138+ * along with this program; if not, write to the Free Software
139+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
140+ *
141+ * decompressor.h
142+ */
143+
144+struct squashfs_decompressor {
145+ void *(*init)(void);
146+ void (*free)(void *);
147+ int (*decompress)(struct squashfs_sb_info *, void **,
148+ struct buffer_head **, int, int, int, int, int);
149+ int id;
150+ char *name;
151+ int supported;
152+};
153+
154+static inline void *squashfs_decompressor_init(struct squashfs_sb_info *msblk)
155+{
156+ return msblk->decompressor->init();
157+}
158+
159+static inline void squashfs_decompressor_free(struct squashfs_sb_info *msblk,
160+ void *s)
161+{
162+ if (msblk->decompressor)
163+ msblk->decompressor->free(s);
164+}
165+
166+static inline int squashfs_decompress(struct squashfs_sb_info *msblk,
167+ void **buffer, struct buffer_head **bh, int b, int offset, int length,
168+ int srclength, int pages)
169+{
170+ return msblk->decompressor->decompress(msblk, buffer, bh, b, offset,
171+ length, srclength, pages);
172+}
173+#endif
174--- a/fs/squashfs/squashfs.h
175+++ b/fs/squashfs/squashfs.h
176@@ -51,6 +51,9 @@ extern struct squashfs_cache_entry *squa
177                 u64, int);
178 extern int squashfs_read_table(struct super_block *, void *, u64, int);
179 
180+/* decompressor.c */
181+extern const struct squashfs_decompressor *squashfs_lookup_decompressor(int);
182+
183 /* export.c */
184 extern __le64 *squashfs_read_inode_lookup_table(struct super_block *, u64,
185                 unsigned int);
186@@ -70,14 +73,8 @@ extern struct inode *squashfs_iget(struc
187                 unsigned int);
188 extern int squashfs_read_inode(struct inode *, long long);
189 
190-/* zlib_wrapper.c */
191-extern void *zlib_init(void);
192-extern void zlib_free(void *);
193-extern int zlib_uncompress(struct squashfs_sb_info *, void **,
194- struct buffer_head **, int, int, int, int, int);
195-
196 /*
197- * Inodes and files operations
198+ * Inodes, files and decompressor operations
199  */
200 
201 /* dir.c */
202@@ -94,3 +91,6 @@ extern const struct inode_operations squ
203 
204 /* symlink.c */
205 extern const struct address_space_operations squashfs_symlink_aops;
206+
207+/* zlib_wrapper.c */
208+extern const struct squashfs_decompressor squashfs_zlib_comp_ops;
209--- a/fs/squashfs/squashfs_fs_sb.h
210+++ b/fs/squashfs/squashfs_fs_sb.h
211@@ -52,25 +52,26 @@ struct squashfs_cache_entry {
212 };
213 
214 struct squashfs_sb_info {
215- int devblksize;
216- int devblksize_log2;
217- struct squashfs_cache *block_cache;
218- struct squashfs_cache *fragment_cache;
219- struct squashfs_cache *read_page;
220- int next_meta_index;
221- __le64 *id_table;
222- __le64 *fragment_index;
223- unsigned int *fragment_index_2;
224- struct mutex read_data_mutex;
225- struct mutex meta_index_mutex;
226- struct meta_index *meta_index;
227- void *stream;
228- __le64 *inode_lookup_table;
229- u64 inode_table;
230- u64 directory_table;
231- unsigned int block_size;
232- unsigned short block_log;
233- long long bytes_used;
234- unsigned int inodes;
235+ const struct squashfs_decompressor *decompressor;
236+ int devblksize;
237+ int devblksize_log2;
238+ struct squashfs_cache *block_cache;
239+ struct squashfs_cache *fragment_cache;
240+ struct squashfs_cache *read_page;
241+ int next_meta_index;
242+ __le64 *id_table;
243+ __le64 *fragment_index;
244+ unsigned int *fragment_index_2;
245+ struct mutex read_data_mutex;
246+ struct mutex meta_index_mutex;
247+ struct meta_index *meta_index;
248+ void *stream;
249+ __le64 *inode_lookup_table;
250+ u64 inode_table;
251+ u64 directory_table;
252+ unsigned int block_size;
253+ unsigned short block_log;
254+ long long bytes_used;
255+ unsigned int inodes;
256 };
257 #endif
258--- a/fs/squashfs/super.c
259+++ b/fs/squashfs/super.c
260@@ -40,27 +40,35 @@
261 #include "squashfs_fs_sb.h"
262 #include "squashfs_fs_i.h"
263 #include "squashfs.h"
264+#include "decompressor.h"
265 
266 static struct file_system_type squashfs_fs_type;
267 static struct super_operations squashfs_super_ops;
268 
269-static int supported_squashfs_filesystem(short major, short minor, short comp)
270+static const struct squashfs_decompressor *supported_squashfs_filesystem(short
271+ major, short minor, short id)
272 {
273+ const struct squashfs_decompressor *decompressor;
274+
275     if (major < SQUASHFS_MAJOR) {
276         ERROR("Major/Minor mismatch, older Squashfs %d.%d "
277             "filesystems are unsupported\n", major, minor);
278- return -EINVAL;
279+ return NULL;
280     } else if (major > SQUASHFS_MAJOR || minor > SQUASHFS_MINOR) {
281         ERROR("Major/Minor mismatch, trying to mount newer "
282             "%d.%d filesystem\n", major, minor);
283         ERROR("Please update your kernel\n");
284- return -EINVAL;
285+ return NULL;
286     }
287 
288- if (comp != ZLIB_COMPRESSION)
289- return -EINVAL;
290+ decompressor = squashfs_lookup_decompressor(id);
291+ if (!decompressor->supported) {
292+ ERROR("Filesystem uses \"%s\" compression. This is not "
293+ "supported\n", decompressor->name);
294+ return NULL;
295+ }
296 
297- return 0;
298+ return decompressor;
299 }
300 
301 
302@@ -85,10 +93,6 @@ static int squashfs_fill_super(struct su
303     }
304     msblk = sb->s_fs_info;
305 
306- msblk->stream = zlib_init();
307- if (msblk->stream == NULL)
308- goto failure;
309-
310     sblk = kzalloc(sizeof(*sblk), GFP_KERNEL);
311     if (sblk == NULL) {
312         ERROR("Failed to allocate squashfs_super_block\n");
313@@ -115,25 +119,25 @@ static int squashfs_fill_super(struct su
314         goto failed_mount;
315     }
316 
317+ err = -EINVAL;
318+
319     /* Check it is a SQUASHFS superblock */
320     sb->s_magic = le32_to_cpu(sblk->s_magic);
321     if (sb->s_magic != SQUASHFS_MAGIC) {
322         if (!silent)
323             ERROR("Can't find a SQUASHFS superblock on %s\n",
324                         bdevname(sb->s_bdev, b));
325- err = -EINVAL;
326         goto failed_mount;
327     }
328 
329- /* Check the MAJOR & MINOR versions and compression type */
330- err = supported_squashfs_filesystem(le16_to_cpu(sblk->s_major),
331+ /* Check the MAJOR & MINOR versions and lookup compression type */
332+ msblk->decompressor = supported_squashfs_filesystem(
333+ le16_to_cpu(sblk->s_major),
334             le16_to_cpu(sblk->s_minor),
335             le16_to_cpu(sblk->compression));
336- if (err < 0)
337+ if (msblk->decompressor == NULL)
338         goto failed_mount;
339 
340- err = -EINVAL;
341-
342     /*
343      * Check if there's xattrs in the filesystem. These are not
344      * supported in this version, so warn that they will be ignored.
345@@ -200,6 +204,10 @@ static int squashfs_fill_super(struct su
346 
347     err = -ENOMEM;
348 
349+ msblk->stream = squashfs_decompressor_init(msblk);
350+ if (msblk->stream == NULL)
351+ goto failed_mount;
352+
353     msblk->block_cache = squashfs_cache_init("metadata",
354             SQUASHFS_CACHED_BLKS, SQUASHFS_METADATA_SIZE);
355     if (msblk->block_cache == NULL)
356@@ -287,7 +295,7 @@ failed_mount:
357     squashfs_cache_delete(msblk->block_cache);
358     squashfs_cache_delete(msblk->fragment_cache);
359     squashfs_cache_delete(msblk->read_page);
360- zlib_free(msblk->stream);
361+ squashfs_decompressor_free(msblk, msblk->stream);
362     kfree(msblk->inode_lookup_table);
363     kfree(msblk->fragment_index);
364     kfree(msblk->id_table);
365@@ -297,7 +305,6 @@ failed_mount:
366     return err;
367 
368 failure:
369- zlib_free(msblk->stream);
370     kfree(sb->s_fs_info);
371     sb->s_fs_info = NULL;
372     return -ENOMEM;
373@@ -339,7 +346,7 @@ static void squashfs_put_super(struct su
374         squashfs_cache_delete(sbi->block_cache);
375         squashfs_cache_delete(sbi->fragment_cache);
376         squashfs_cache_delete(sbi->read_page);
377- zlib_free(sbi->stream);
378+ squashfs_decompressor_free(sbi, sbi->stream);
379         kfree(sbi->id_table);
380         kfree(sbi->fragment_index);
381         kfree(sbi->meta_index);
382--- a/fs/squashfs/zlib_wrapper.c
383+++ b/fs/squashfs/zlib_wrapper.c
384@@ -30,8 +30,9 @@
385 #include "squashfs_fs_sb.h"
386 #include "squashfs_fs_i.h"
387 #include "squashfs.h"
388+#include "decompressor.h"
389 
390-void *zlib_init()
391+static void *zlib_init(void)
392 {
393     z_stream *stream = kmalloc(sizeof(z_stream), GFP_KERNEL);
394     if (stream == NULL)
395@@ -50,7 +51,7 @@ failed:
396 }
397 
398 
399-void zlib_free(void *strm)
400+static void zlib_free(void *strm)
401 {
402     z_stream *stream = strm;
403 
404@@ -60,7 +61,7 @@ void zlib_free(void *strm)
405 }
406 
407 
408-int zlib_uncompress(struct squashfs_sb_info *msblk, void **buffer,
409+static int zlib_uncompress(struct squashfs_sb_info *msblk, void **buffer,
410     struct buffer_head **bh, int b, int offset, int length, int srclength,
411     int pages)
412 {
413@@ -137,3 +138,13 @@ release_mutex:
414 
415     return -EIO;
416 }
417+
418+const struct squashfs_decompressor squashfs_zlib_comp_ops = {
419+ .init = zlib_init,
420+ .free = zlib_free,
421+ .decompress = zlib_uncompress,
422+ .id = ZLIB_COMPRESSION,
423+ .name = "zlib",
424+ .supported = 1
425+};
426+
427

Archive Download this file



interactive