diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-03-05 13:46:04 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-03-05 13:46:04 -0500 |
| commit | b24bc1e61cec2174faf5dfa632da16b6ca17144f (patch) | |
| tree | 33abe2345c70d4bce31cda8fe2e562a8a9a24dfc | |
| parent | 64ba9926759792cf7b95f823402e2781edd1b5d4 (diff) | |
| parent | 06862f884d9c2453daaf0c1d070c69cf444f10b1 (diff) | |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/pkl/squashfs-linus
* git://git.kernel.org/pub/scm/linux/kernel/git/pkl/squashfs-linus:
Squashfs: get rid of obsolete definition in header file
Squashfs: get rid of obsolete variable in struct squashfs_sb_info
Squashfs: add decompressor entries for lzma and lzo
Squashfs: add a decompressor framework
Squashfs: factor out remaining zlib dependencies into separate wrapper file
Squashfs: move zlib decompression wrapper code into a separate file
| -rw-r--r-- | fs/squashfs/Makefile | 2 | ||||
| -rw-r--r-- | fs/squashfs/block.c | 76 | ||||
| -rw-r--r-- | fs/squashfs/cache.c | 1 | ||||
| -rw-r--r-- | fs/squashfs/decompressor.c | 68 | ||||
| -rw-r--r-- | fs/squashfs/decompressor.h | 55 | ||||
| -rw-r--r-- | fs/squashfs/dir.c | 1 | ||||
| -rw-r--r-- | fs/squashfs/export.c | 1 | ||||
| -rw-r--r-- | fs/squashfs/file.c | 1 | ||||
| -rw-r--r-- | fs/squashfs/fragment.c | 1 | ||||
| -rw-r--r-- | fs/squashfs/id.c | 1 | ||||
| -rw-r--r-- | fs/squashfs/inode.c | 1 | ||||
| -rw-r--r-- | fs/squashfs/namei.c | 1 | ||||
| -rw-r--r-- | fs/squashfs/squashfs.h | 8 | ||||
| -rw-r--r-- | fs/squashfs/squashfs_fs.h | 6 | ||||
| -rw-r--r-- | fs/squashfs/squashfs_fs_sb.h | 40 | ||||
| -rw-r--r-- | fs/squashfs/super.c | 49 | ||||
| -rw-r--r-- | fs/squashfs/symlink.c | 1 | ||||
| -rw-r--r-- | fs/squashfs/zlib_wrapper.c | 150 |
18 files changed, 335 insertions, 128 deletions
diff --git a/fs/squashfs/Makefile b/fs/squashfs/Makefile index 70e3244fa30f..df8a19ef870d 100644 --- a/fs/squashfs/Makefile +++ b/fs/squashfs/Makefile | |||
| @@ -4,4 +4,4 @@ | |||
| 4 | 4 | ||
| 5 | obj-$(CONFIG_SQUASHFS) += squashfs.o | 5 | obj-$(CONFIG_SQUASHFS) += squashfs.o |
| 6 | squashfs-y += block.o cache.o dir.o export.o file.o fragment.o id.o inode.o | 6 | squashfs-y += block.o cache.o dir.o export.o file.o fragment.o id.o inode.o |
| 7 | squashfs-y += namei.o super.o symlink.o | 7 | squashfs-y += namei.o super.o symlink.o zlib_wrapper.o decompressor.o |
diff --git a/fs/squashfs/block.c b/fs/squashfs/block.c index 2a7960310349..1cb0d81b164b 100644 --- a/fs/squashfs/block.c +++ b/fs/squashfs/block.c | |||
| @@ -29,15 +29,14 @@ | |||
| 29 | #include <linux/fs.h> | 29 | #include <linux/fs.h> |
| 30 | #include <linux/vfs.h> | 30 | #include <linux/vfs.h> |
| 31 | #include <linux/slab.h> | 31 | #include <linux/slab.h> |
| 32 | #include <linux/mutex.h> | ||
| 33 | #include <linux/string.h> | 32 | #include <linux/string.h> |
| 34 | #include <linux/buffer_head.h> | 33 | #include <linux/buffer_head.h> |
| 35 | #include <linux/zlib.h> | ||
| 36 | 34 | ||
| 37 | #include "squashfs_fs.h" | 35 | #include "squashfs_fs.h" |
| 38 | #include "squashfs_fs_sb.h" | 36 | #include "squashfs_fs_sb.h" |
| 39 | #include "squashfs_fs_i.h" | 37 | #include "squashfs_fs_i.h" |
| 40 | #include "squashfs.h" | 38 | #include "squashfs.h" |
| 39 | #include "decompressor.h" | ||
| 41 | 40 | ||
| 42 | /* | 41 | /* |
| 43 | * Read the metadata block length, this is stored in the first two | 42 | * Read the metadata block length, this is stored in the first two |
| @@ -153,72 +152,10 @@ int squashfs_read_data(struct super_block *sb, void **buffer, u64 index, | |||
| 153 | } | 152 | } |
| 154 | 153 | ||
| 155 | if (compressed) { | 154 | if (compressed) { |
| 156 | int zlib_err = 0, zlib_init = 0; | 155 | length = squashfs_decompress(msblk, buffer, bh, b, offset, |
| 157 | 156 | length, srclength, pages); | |
| 158 | /* | 157 | if (length < 0) |
| 159 | * Uncompress block. | 158 | goto read_failure; |
| 160 | */ | ||
| 161 | |||
| 162 | mutex_lock(&msblk->read_data_mutex); | ||
| 163 | |||
| 164 | msblk->stream.avail_out = 0; | ||
| 165 | msblk->stream.avail_in = 0; | ||
| 166 | |||
| 167 | bytes = length; | ||
| 168 | do { | ||
| 169 | if (msblk->stream.avail_in == 0 && k < b) { | ||
| 170 | avail = min(bytes, msblk->devblksize - offset); | ||
| 171 | bytes -= avail; | ||
| 172 | wait_on_buffer(bh[k]); | ||
| 173 | if (!buffer_uptodate(bh[k])) | ||
| 174 | goto release_mutex; | ||
| 175 | |||
| 176 | if (avail == 0) { | ||
| 177 | offset = 0; | ||
| 178 | put_bh(bh[k++]); | ||
| 179 | continue; | ||
| 180 | } | ||
| 181 | |||
| 182 | msblk->stream.next_in = bh[k]->b_data + offset; | ||
| 183 | msblk->stream.avail_in = avail; | ||
| 184 | offset = 0; | ||
| 185 | } | ||
| 186 | |||
| 187 | if (msblk->stream.avail_out == 0 && page < pages) { | ||
| 188 | msblk->stream.next_out = buffer[page++]; | ||
| 189 | msblk->stream.avail_out = PAGE_CACHE_SIZE; | ||
| 190 | } | ||
| 191 | |||
| 192 | if (!zlib_init) { | ||
| 193 | zlib_err = zlib_inflateInit(&msblk->stream); | ||
| 194 | if (zlib_err != Z_OK) { | ||
| 195 | ERROR("zlib_inflateInit returned" | ||
| 196 | " unexpected result 0x%x," | ||
| 197 | " srclength %d\n", zlib_err, | ||
| 198 | srclength); | ||
| 199 | goto release_mutex; | ||
| 200 | } | ||
| 201 | zlib_init = 1; | ||
| 202 | } | ||
| 203 | |||
| 204 | zlib_err = zlib_inflate(&msblk->stream, Z_SYNC_FLUSH); | ||
| 205 | |||
| 206 | if (msblk->stream.avail_in == 0 && k < b) | ||
| 207 | put_bh(bh[k++]); | ||
| 208 | } while (zlib_err == Z_OK); | ||
| 209 | |||
| 210 | if (zlib_err != Z_STREAM_END) { | ||
| 211 | ERROR("zlib_inflate error, data probably corrupt\n"); | ||
| 212 | goto release_mutex; | ||
| 213 | } | ||
| 214 | |||
| 215 | zlib_err = zlib_inflateEnd(&msblk->stream); | ||
| 216 | if (zlib_err != Z_OK) { | ||
| 217 | ERROR("zlib_inflate error, data probably corrupt\n"); | ||
| 218 | goto release_mutex; | ||
| 219 | } | ||
| 220 | length = msblk->stream.total_out; | ||
| 221 | mutex_unlock(&msblk->read_data_mutex); | ||
| 222 | } else { | 159 | } else { |
| 223 | /* | 160 | /* |
| 224 | * Block is uncompressed. | 161 | * Block is uncompressed. |
| @@ -255,9 +192,6 @@ int squashfs_read_data(struct super_block *sb, void **buffer, u64 index, | |||
| 255 | kfree(bh); | 192 | kfree(bh); |
| 256 | return length; | 193 | return length; |
| 257 | 194 | ||
| 258 | release_mutex: | ||
| 259 | mutex_unlock(&msblk->read_data_mutex); | ||
| 260 | |||
| 261 | block_release: | 195 | block_release: |
| 262 | for (; k < b; k++) | 196 | for (; k < b; k++) |
| 263 | put_bh(bh[k]); | 197 | put_bh(bh[k]); |
diff --git a/fs/squashfs/cache.c b/fs/squashfs/cache.c index 40c98fa6b5d6..57314bee9059 100644 --- a/fs/squashfs/cache.c +++ b/fs/squashfs/cache.c | |||
| @@ -51,7 +51,6 @@ | |||
| 51 | #include <linux/sched.h> | 51 | #include <linux/sched.h> |
| 52 | #include <linux/spinlock.h> | 52 | #include <linux/spinlock.h> |
| 53 | #include <linux/wait.h> | 53 | #include <linux/wait.h> |
| 54 | #include <linux/zlib.h> | ||
| 55 | #include <linux/pagemap.h> | 54 | #include <linux/pagemap.h> |
| 56 | 55 | ||
| 57 | #include "squashfs_fs.h" | 56 | #include "squashfs_fs.h" |
diff --git a/fs/squashfs/decompressor.c b/fs/squashfs/decompressor.c new file mode 100644 index 000000000000..157478da6ac9 --- /dev/null +++ b/fs/squashfs/decompressor.c | |||
| @@ -0,0 +1,68 @@ | |||
| 1 | /* | ||
| 2 | * Squashfs - a compressed read only filesystem for Linux | ||
| 3 | * | ||
| 4 | * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 | ||
| 5 | * Phillip Lougher <phillip@lougher.demon.co.uk> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or | ||
| 8 | * modify it under the terms of the GNU General Public License | ||
| 9 | * as published by the Free Software Foundation; either version 2, | ||
| 10 | * or (at your option) any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
| 20 | * | ||
| 21 | * decompressor.c | ||
| 22 | */ | ||
| 23 | |||
| 24 | #include <linux/types.h> | ||
| 25 | #include <linux/mutex.h> | ||
| 26 | #include <linux/buffer_head.h> | ||
| 27 | |||
| 28 | #include "squashfs_fs.h" | ||
| 29 | #include "squashfs_fs_sb.h" | ||
| 30 | #include "squashfs_fs_i.h" | ||
| 31 | #include "decompressor.h" | ||
| 32 | #include "squashfs.h" | ||
| 33 | |||
| 34 | /* | ||
| 35 | * This file (and decompressor.h) implements a decompressor framework for | ||
| 36 | * Squashfs, allowing multiple decompressors to be easily supported | ||
| 37 | */ | ||
| 38 | |||
| 39 | static const struct squashfs_decompressor squashfs_lzma_unsupported_comp_ops = { | ||
| 40 | NULL, NULL, NULL, LZMA_COMPRESSION, "lzma", 0 | ||
| 41 | }; | ||
| 42 | |||
| 43 | static const struct squashfs_decompressor squashfs_lzo_unsupported_comp_ops = { | ||
| 44 | NULL, NULL, NULL, LZO_COMPRESSION, "lzo", 0 | ||
| 45 | }; | ||
| 46 | |||
| 47 | static const struct squashfs_decompressor squashfs_unknown_comp_ops = { | ||
| 48 | NULL, NULL, NULL, 0, "unknown", 0 | ||
| 49 | }; | ||
| 50 | |||
| 51 | static const struct squashfs_decompressor *decompressor[] = { | ||
| 52 | &squashfs_zlib_comp_ops, | ||
| 53 | &squashfs_lzma_unsupported_comp_ops, | ||
| 54 | &squashfs_lzo_unsupported_comp_ops, | ||
| 55 | &squashfs_unknown_comp_ops | ||
| 56 | }; | ||
| 57 | |||
| 58 | |||
| 59 | const struct squashfs_decompressor *squashfs_lookup_decompressor(int id) | ||
| 60 | { | ||
| 61 | int i; | ||
| 62 | |||
| 63 | for (i = 0; decompressor[i]->id; i++) | ||
| 64 | if (id == decompressor[i]->id) | ||
| 65 | break; | ||
| 66 | |||
| 67 | return decompressor[i]; | ||
| 68 | } | ||
diff --git a/fs/squashfs/decompressor.h b/fs/squashfs/decompressor.h new file mode 100644 index 000000000000..7425f80783f6 --- /dev/null +++ b/fs/squashfs/decompressor.h | |||
| @@ -0,0 +1,55 @@ | |||
| 1 | #ifndef DECOMPRESSOR_H | ||
| 2 | #define DECOMPRESSOR_H | ||
| 3 | /* | ||
| 4 | * Squashfs - a compressed read only filesystem for Linux | ||
| 5 | * | ||
| 6 | * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 | ||
| 7 | * Phillip Lougher <phillip@lougher.demon.co.uk> | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or | ||
| 10 | * modify it under the terms of the GNU General Public License | ||
| 11 | * as published by the Free Software Foundation; either version 2, | ||
| 12 | * or (at your option) any later version. | ||
| 13 | * | ||
| 14 | * This program is distributed in the hope that it will be useful, | ||
| 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | * GNU General Public License for more details. | ||
| 18 | * | ||
| 19 | * You should have received a copy of the GNU General Public License | ||
| 20 | * along with this program; if not, write to the Free Software | ||
| 21 | * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
| 22 | * | ||
| 23 | * decompressor.h | ||
| 24 | */ | ||
| 25 | |||
| 26 | struct squashfs_decompressor { | ||
| 27 | void *(*init)(struct squashfs_sb_info *); | ||
| 28 | void (*free)(void *); | ||
| 29 | int (*decompress)(struct squashfs_sb_info *, void **, | ||
| 30 | struct buffer_head **, int, int, int, int, int); | ||
| 31 | int id; | ||
| 32 | char *name; | ||
| 33 | int supported; | ||
| 34 | }; | ||
| 35 | |||
| 36 | static inline void *squashfs_decompressor_init(struct squashfs_sb_info *msblk) | ||
| 37 | { | ||
| 38 | return msblk->decompressor->init(msblk); | ||
| 39 | } | ||
| 40 | |||
| 41 | static inline void squashfs_decompressor_free(struct squashfs_sb_info *msblk, | ||
| 42 | void *s) | ||
| 43 | { | ||
| 44 | if (msblk->decompressor) | ||
| 45 | msblk->decompressor->free(s); | ||
| 46 | } | ||
| 47 | |||
| 48 | static inline int squashfs_decompress(struct squashfs_sb_info *msblk, | ||
| 49 | void **buffer, struct buffer_head **bh, int b, int offset, int length, | ||
| 50 | int srclength, int pages) | ||
| 51 | { | ||
| 52 | return msblk->decompressor->decompress(msblk, buffer, bh, b, offset, | ||
| 53 | length, srclength, pages); | ||
| 54 | } | ||
| 55 | #endif | ||
diff --git a/fs/squashfs/dir.c b/fs/squashfs/dir.c index 566b0eaed868..12b933ac6585 100644 --- a/fs/squashfs/dir.c +++ b/fs/squashfs/dir.c | |||
| @@ -30,7 +30,6 @@ | |||
| 30 | #include <linux/fs.h> | 30 | #include <linux/fs.h> |
| 31 | #include <linux/vfs.h> | 31 | #include <linux/vfs.h> |
| 32 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
| 33 | #include <linux/zlib.h> | ||
| 34 | 33 | ||
| 35 | #include "squashfs_fs.h" | 34 | #include "squashfs_fs.h" |
| 36 | #include "squashfs_fs_sb.h" | 35 | #include "squashfs_fs_sb.h" |
diff --git a/fs/squashfs/export.c b/fs/squashfs/export.c index 2b1b8fe5e037..7f93d5a9ee05 100644 --- a/fs/squashfs/export.c +++ b/fs/squashfs/export.c | |||
| @@ -39,7 +39,6 @@ | |||
| 39 | #include <linux/vfs.h> | 39 | #include <linux/vfs.h> |
| 40 | #include <linux/dcache.h> | 40 | #include <linux/dcache.h> |
| 41 | #include <linux/exportfs.h> | 41 | #include <linux/exportfs.h> |
| 42 | #include <linux/zlib.h> | ||
| 43 | #include <linux/slab.h> | 42 | #include <linux/slab.h> |
| 44 | 43 | ||
| 45 | #include "squashfs_fs.h" | 44 | #include "squashfs_fs.h" |
diff --git a/fs/squashfs/file.c b/fs/squashfs/file.c index 717767d831df..a25c5060bdcb 100644 --- a/fs/squashfs/file.c +++ b/fs/squashfs/file.c | |||
| @@ -47,7 +47,6 @@ | |||
| 47 | #include <linux/string.h> | 47 | #include <linux/string.h> |
| 48 | #include <linux/pagemap.h> | 48 | #include <linux/pagemap.h> |
| 49 | #include <linux/mutex.h> | 49 | #include <linux/mutex.h> |
| 50 | #include <linux/zlib.h> | ||
| 51 | 50 | ||
| 52 | #include "squashfs_fs.h" | 51 | #include "squashfs_fs.h" |
| 53 | #include "squashfs_fs_sb.h" | 52 | #include "squashfs_fs_sb.h" |
diff --git a/fs/squashfs/fragment.c b/fs/squashfs/fragment.c index b5a2c15bbbc7..7c90bbd6879d 100644 --- a/fs/squashfs/fragment.c +++ b/fs/squashfs/fragment.c | |||
| @@ -36,7 +36,6 @@ | |||
| 36 | #include <linux/fs.h> | 36 | #include <linux/fs.h> |
| 37 | #include <linux/vfs.h> | 37 | #include <linux/vfs.h> |
| 38 | #include <linux/slab.h> | 38 | #include <linux/slab.h> |
| 39 | #include <linux/zlib.h> | ||
| 40 | 39 | ||
| 41 | #include "squashfs_fs.h" | 40 | #include "squashfs_fs.h" |
| 42 | #include "squashfs_fs_sb.h" | 41 | #include "squashfs_fs_sb.h" |
diff --git a/fs/squashfs/id.c b/fs/squashfs/id.c index 3795b837ba28..b7f64bcd2b70 100644 --- a/fs/squashfs/id.c +++ b/fs/squashfs/id.c | |||
| @@ -34,7 +34,6 @@ | |||
| 34 | #include <linux/fs.h> | 34 | #include <linux/fs.h> |
| 35 | #include <linux/vfs.h> | 35 | #include <linux/vfs.h> |
| 36 | #include <linux/slab.h> | 36 | #include <linux/slab.h> |
| 37 | #include <linux/zlib.h> | ||
| 38 | 37 | ||
| 39 | #include "squashfs_fs.h" | 38 | #include "squashfs_fs.h" |
| 40 | #include "squashfs_fs_sb.h" | 39 | #include "squashfs_fs_sb.h" |
diff --git a/fs/squashfs/inode.c b/fs/squashfs/inode.c index 9101dbde39ec..49daaf669e41 100644 --- a/fs/squashfs/inode.c +++ b/fs/squashfs/inode.c | |||
| @@ -40,7 +40,6 @@ | |||
| 40 | 40 | ||
| 41 | #include <linux/fs.h> | 41 | #include <linux/fs.h> |
| 42 | #include <linux/vfs.h> | 42 | #include <linux/vfs.h> |
| 43 | #include <linux/zlib.h> | ||
| 44 | 43 | ||
| 45 | #include "squashfs_fs.h" | 44 | #include "squashfs_fs.h" |
| 46 | #include "squashfs_fs_sb.h" | 45 | #include "squashfs_fs_sb.h" |
diff --git a/fs/squashfs/namei.c b/fs/squashfs/namei.c index 9e398653b22b..5266bd8ad932 100644 --- a/fs/squashfs/namei.c +++ b/fs/squashfs/namei.c | |||
| @@ -57,7 +57,6 @@ | |||
| 57 | #include <linux/slab.h> | 57 | #include <linux/slab.h> |
| 58 | #include <linux/string.h> | 58 | #include <linux/string.h> |
| 59 | #include <linux/dcache.h> | 59 | #include <linux/dcache.h> |
| 60 | #include <linux/zlib.h> | ||
| 61 | 60 | ||
| 62 | #include "squashfs_fs.h" | 61 | #include "squashfs_fs.h" |
| 63 | #include "squashfs_fs_sb.h" | 62 | #include "squashfs_fs_sb.h" |
diff --git a/fs/squashfs/squashfs.h b/fs/squashfs/squashfs.h index 0e9feb6adf7e..fe2587af5512 100644 --- a/fs/squashfs/squashfs.h +++ b/fs/squashfs/squashfs.h | |||
| @@ -51,6 +51,9 @@ extern struct squashfs_cache_entry *squashfs_get_datablock(struct super_block *, | |||
| 51 | u64, int); | 51 | u64, int); |
| 52 | extern int squashfs_read_table(struct super_block *, void *, u64, int); | 52 | extern int squashfs_read_table(struct super_block *, void *, u64, int); |
| 53 | 53 | ||
| 54 | /* decompressor.c */ | ||
| 55 | extern const struct squashfs_decompressor *squashfs_lookup_decompressor(int); | ||
| 56 | |||
| 54 | /* export.c */ | 57 | /* export.c */ |
| 55 | extern __le64 *squashfs_read_inode_lookup_table(struct super_block *, u64, | 58 | extern __le64 *squashfs_read_inode_lookup_table(struct super_block *, u64, |
| 56 | unsigned int); | 59 | unsigned int); |
| @@ -71,7 +74,7 @@ extern struct inode *squashfs_iget(struct super_block *, long long, | |||
| 71 | extern int squashfs_read_inode(struct inode *, long long); | 74 | extern int squashfs_read_inode(struct inode *, long long); |
| 72 | 75 | ||
| 73 | /* | 76 | /* |
| 74 | * Inodes and files operations | 77 | * Inodes, files and decompressor operations |
| 75 | */ | 78 | */ |
| 76 | 79 | ||
| 77 | /* dir.c */ | 80 | /* dir.c */ |
| @@ -88,3 +91,6 @@ extern const struct inode_operations squashfs_dir_inode_ops; | |||
| 88 | 91 | ||
| 89 | /* symlink.c */ | 92 | /* symlink.c */ |
| 90 | extern const struct address_space_operations squashfs_symlink_aops; | 93 | extern const struct address_space_operations squashfs_symlink_aops; |
| 94 | |||
| 95 | /* zlib_wrapper.c */ | ||
| 96 | extern const struct squashfs_decompressor squashfs_zlib_comp_ops; | ||
diff --git a/fs/squashfs/squashfs_fs.h b/fs/squashfs/squashfs_fs.h index 283daafc568e..79024245ea00 100644 --- a/fs/squashfs/squashfs_fs.h +++ b/fs/squashfs/squashfs_fs.h | |||
| @@ -183,8 +183,6 @@ | |||
| 183 | #define SQUASHFS_MAX_FILE_SIZE (1LL << \ | 183 | #define SQUASHFS_MAX_FILE_SIZE (1LL << \ |
| 184 | (SQUASHFS_MAX_FILE_SIZE_LOG - 2)) | 184 | (SQUASHFS_MAX_FILE_SIZE_LOG - 2)) |
| 185 | 185 | ||
| 186 | #define SQUASHFS_MARKER_BYTE 0xff | ||
| 187 | |||
| 188 | /* meta index cache */ | 186 | /* meta index cache */ |
| 189 | #define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int)) | 187 | #define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int)) |
| 190 | #define SQUASHFS_META_ENTRIES 127 | 188 | #define SQUASHFS_META_ENTRIES 127 |
| @@ -211,7 +209,9 @@ struct meta_index { | |||
| 211 | /* | 209 | /* |
| 212 | * definitions for structures on disk | 210 | * definitions for structures on disk |
| 213 | */ | 211 | */ |
| 214 | #define ZLIB_COMPRESSION 1 | 212 | #define ZLIB_COMPRESSION 1 |
| 213 | #define LZMA_COMPRESSION 2 | ||
| 214 | #define LZO_COMPRESSION 3 | ||
| 215 | 215 | ||
| 216 | struct squashfs_super_block { | 216 | struct squashfs_super_block { |
| 217 | __le32 s_magic; | 217 | __le32 s_magic; |
diff --git a/fs/squashfs/squashfs_fs_sb.h b/fs/squashfs/squashfs_fs_sb.h index c8c65614dd1c..2e77dc547e25 100644 --- a/fs/squashfs/squashfs_fs_sb.h +++ b/fs/squashfs/squashfs_fs_sb.h | |||
| @@ -52,25 +52,25 @@ struct squashfs_cache_entry { | |||
| 52 | }; | 52 | }; |
| 53 | 53 | ||
| 54 | struct squashfs_sb_info { | 54 | struct squashfs_sb_info { |
| 55 | int devblksize; | 55 | const struct squashfs_decompressor *decompressor; |
| 56 | int devblksize_log2; | 56 | int devblksize; |
| 57 | struct squashfs_cache *block_cache; | 57 | int devblksize_log2; |
| 58 | struct squashfs_cache *fragment_cache; | 58 | struct squashfs_cache *block_cache; |
| 59 | struct squashfs_cache *read_page; | 59 | struct squashfs_cache *fragment_cache; |
| 60 | int next_meta_index; | 60 | struct squashfs_cache *read_page; |
| 61 | __le64 *id_table; | 61 | int next_meta_index; |
| 62 | __le64 *fragment_index; | 62 | __le64 *id_table; |
| 63 | unsigned int *fragment_index_2; | 63 | __le64 *fragment_index; |
| 64 | struct mutex read_data_mutex; | 64 | struct mutex read_data_mutex; |
| 65 | struct mutex meta_index_mutex; | 65 | struct mutex meta_index_mutex; |
| 66 | struct meta_index *meta_index; | 66 | struct meta_index *meta_index; |
| 67 | z_stream stream; | 67 | void *stream; |
| 68 | __le64 *inode_lookup_table; | 68 | __le64 *inode_lookup_table; |
| 69 | u64 inode_table; | 69 | u64 inode_table; |
| 70 | u64 directory_table; | 70 | u64 directory_table; |
| 71 | unsigned int block_size; | 71 | unsigned int block_size; |
| 72 | unsigned short block_log; | 72 | unsigned short block_log; |
| 73 | long long bytes_used; | 73 | long long bytes_used; |
| 74 | unsigned int inodes; | 74 | unsigned int inodes; |
| 75 | }; | 75 | }; |
| 76 | #endif | 76 | #endif |
diff --git a/fs/squashfs/super.c b/fs/squashfs/super.c index 6c197ef53add..3550aec2f655 100644 --- a/fs/squashfs/super.c +++ b/fs/squashfs/super.c | |||
| @@ -35,34 +35,41 @@ | |||
| 35 | #include <linux/pagemap.h> | 35 | #include <linux/pagemap.h> |
| 36 | #include <linux/init.h> | 36 | #include <linux/init.h> |
| 37 | #include <linux/module.h> | 37 | #include <linux/module.h> |
| 38 | #include <linux/zlib.h> | ||
| 39 | #include <linux/magic.h> | 38 | #include <linux/magic.h> |
| 40 | 39 | ||
| 41 | #include "squashfs_fs.h" | 40 | #include "squashfs_fs.h" |
| 42 | #include "squashfs_fs_sb.h" | 41 | #include "squashfs_fs_sb.h" |
| 43 | #include "squashfs_fs_i.h" | 42 | #include "squashfs_fs_i.h" |
| 44 | #include "squashfs.h" | 43 | #include "squashfs.h" |
| 44 | #include "decompressor.h" | ||
| 45 | 45 | ||
| 46 | static struct file_system_type squashfs_fs_type; | 46 | static struct file_system_type squashfs_fs_type; |
| 47 | static const struct super_operations squashfs_super_ops; | 47 | static const struct super_operations squashfs_super_ops; |
| 48 | 48 | ||
| 49 | static int supported_squashfs_filesystem(short major, short minor, short comp) | 49 | static const struct squashfs_decompressor *supported_squashfs_filesystem(short |
| 50 | major, short minor, short id) | ||
| 50 | { | 51 | { |
| 52 | const struct squashfs_decompressor *decompressor; | ||
| 53 | |||
| 51 | if (major < SQUASHFS_MAJOR) { | 54 | if (major < SQUASHFS_MAJOR) { |
| 52 | ERROR("Major/Minor mismatch, older Squashfs %d.%d " | 55 | ERROR("Major/Minor mismatch, older Squashfs %d.%d " |
| 53 | "filesystems are unsupported\n", major, minor); | 56 | "filesystems are unsupported\n", major, minor); |
| 54 | return -EINVAL; | 57 | return NULL; |
| 55 | } else if (major > SQUASHFS_MAJOR || minor > SQUASHFS_MINOR) { | 58 | } else if (major > SQUASHFS_MAJOR || minor > SQUASHFS_MINOR) { |
| 56 | ERROR("Major/Minor mismatch, trying to mount newer " | 59 | ERROR("Major/Minor mismatch, trying to mount newer " |
| 57 | "%d.%d filesystem\n", major, minor); | 60 | "%d.%d filesystem\n", major, minor); |
| 58 | ERROR("Please update your kernel\n"); | 61 | ERROR("Please update your kernel\n"); |
| 59 | return -EINVAL; | 62 | return NULL; |
| 60 | } | 63 | } |
| 61 | 64 | ||
| 62 | if (comp != ZLIB_COMPRESSION) | 65 | decompressor = squashfs_lookup_decompressor(id); |
| 63 | return -EINVAL; | 66 | if (!decompressor->supported) { |
| 67 | ERROR("Filesystem uses \"%s\" compression. This is not " | ||
| 68 | "supported\n", decompressor->name); | ||
| 69 | return NULL; | ||
| 70 | } | ||
| 64 | 71 | ||
| 65 | return 0; | 72 | return decompressor; |
| 66 | } | 73 | } |
| 67 | 74 | ||
| 68 | 75 | ||
| @@ -87,13 +94,6 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent) | |||
| 87 | } | 94 | } |
| 88 | msblk = sb->s_fs_info; | 95 | msblk = sb->s_fs_info; |
| 89 | 96 | ||
| 90 | msblk->stream.workspace = kmalloc(zlib_inflate_workspacesize(), | ||
| 91 | GFP_KERNEL); | ||
| 92 | if (msblk->stream.workspace == NULL) { | ||
| 93 | ERROR("Failed to allocate zlib workspace\n"); | ||
| 94 | goto failure; | ||
| 95 | } | ||
| 96 | |||
| 97 | sblk = kzalloc(sizeof(*sblk), GFP_KERNEL); | 97 | sblk = kzalloc(sizeof(*sblk), GFP_KERNEL); |
| 98 | if (sblk == NULL) { | 98 | if (sblk == NULL) { |
| 99 | ERROR("Failed to allocate squashfs_super_block\n"); | 99 | ERROR("Failed to allocate squashfs_super_block\n"); |
| @@ -120,25 +120,25 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent) | |||
| 120 | goto failed_mount; | 120 | goto failed_mount; |
| 121 | } | 121 | } |
| 122 | 122 | ||
| 123 | err = -EINVAL; | ||
| 124 | |||
| 123 | /* Check it is a SQUASHFS superblock */ | 125 | /* Check it is a SQUASHFS superblock */ |
| 124 | sb->s_magic = le32_to_cpu(sblk->s_magic); | 126 | sb->s_magic = le32_to_cpu(sblk->s_magic); |
| 125 | if (sb->s_magic != SQUASHFS_MAGIC) { | 127 | if (sb->s_magic != SQUASHFS_MAGIC) { |
| 126 | if (!silent) | 128 | if (!silent) |
| 127 | ERROR("Can't find a SQUASHFS superblock on %s\n", | 129 | ERROR("Can't find a SQUASHFS superblock on %s\n", |
| 128 | bdevname(sb->s_bdev, b)); | 130 | bdevname(sb->s_bdev, b)); |
| 129 | err = -EINVAL; | ||
| 130 | goto failed_mount; | 131 | goto failed_mount; |
| 131 | } | 132 | } |
| 132 | 133 | ||
| 133 | /* Check the MAJOR & MINOR versions and compression type */ | 134 | /* Check the MAJOR & MINOR versions and lookup compression type */ |
| 134 | err = supported_squashfs_filesystem(le16_to_cpu(sblk->s_major), | 135 | msblk->decompressor = supported_squashfs_filesystem( |
| 136 | le16_to_cpu(sblk->s_major), | ||
| 135 | le16_to_cpu(sblk->s_minor), | 137 | le16_to_cpu(sblk->s_minor), |
| 136 | le16_to_cpu(sblk->compression)); | 138 | le16_to_cpu(sblk->compression)); |
| 137 | if (err < 0) | 139 | if (msblk->decompressor == NULL) |
| 138 | goto failed_mount; | 140 | goto failed_mount; |
| 139 | 141 | ||
| 140 | err = -EINVAL; | ||
| 141 | |||
| 142 | /* | 142 | /* |
| 143 | * Check if there's xattrs in the filesystem. These are not | 143 | * Check if there's xattrs in the filesystem. These are not |
| 144 | * supported in this version, so warn that they will be ignored. | 144 | * supported in this version, so warn that they will be ignored. |
| @@ -205,6 +205,10 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent) | |||
| 205 | 205 | ||
| 206 | err = -ENOMEM; | 206 | err = -ENOMEM; |
| 207 | 207 | ||
| 208 | msblk->stream = squashfs_decompressor_init(msblk); | ||
| 209 | if (msblk->stream == NULL) | ||
| 210 | goto failed_mount; | ||
| 211 | |||
| 208 | msblk->block_cache = squashfs_cache_init("metadata", | 212 | msblk->block_cache = squashfs_cache_init("metadata", |
| 209 | SQUASHFS_CACHED_BLKS, SQUASHFS_METADATA_SIZE); | 213 | SQUASHFS_CACHED_BLKS, SQUASHFS_METADATA_SIZE); |
| 210 | if (msblk->block_cache == NULL) | 214 | if (msblk->block_cache == NULL) |
| @@ -292,17 +296,16 @@ failed_mount: | |||
| 292 | squashfs_cache_delete(msblk->block_cache); | 296 | squashfs_cache_delete(msblk->block_cache); |
| 293 | squashfs_cache_delete(msblk->fragment_cache); | 297 | squashfs_cache_delete(msblk->fragment_cache); |
| 294 | squashfs_cache_delete(msblk->read_page); | 298 | squashfs_cache_delete(msblk->read_page); |
| 299 | squashfs_decompressor_free(msblk, msblk->stream); | ||
| 295 | kfree(msblk->inode_lookup_table); | 300 | kfree(msblk->inode_lookup_table); |
| 296 | kfree(msblk->fragment_index); | 301 | kfree(msblk->fragment_index); |
| 297 | kfree(msblk->id_table); | 302 | kfree(msblk->id_table); |
| 298 | kfree(msblk->stream.workspace); | ||
| 299 | kfree(sb->s_fs_info); | 303 | kfree(sb->s_fs_info); |
| 300 | sb->s_fs_info = NULL; | 304 | sb->s_fs_info = NULL; |
| 301 | kfree(sblk); | 305 | kfree(sblk); |
| 302 | return err; | 306 | return err; |
| 303 | 307 | ||
| 304 | failure: | 308 | failure: |
| 305 | kfree(msblk->stream.workspace); | ||
| 306 | kfree(sb->s_fs_info); | 309 | kfree(sb->s_fs_info); |
| 307 | sb->s_fs_info = NULL; | 310 | sb->s_fs_info = NULL; |
| 308 | return -ENOMEM; | 311 | return -ENOMEM; |
| @@ -346,10 +349,10 @@ static void squashfs_put_super(struct super_block *sb) | |||
| 346 | squashfs_cache_delete(sbi->block_cache); | 349 | squashfs_cache_delete(sbi->block_cache); |
| 347 | squashfs_cache_delete(sbi->fragment_cache); | 350 | squashfs_cache_delete(sbi->fragment_cache); |
| 348 | squashfs_cache_delete(sbi->read_page); | 351 | squashfs_cache_delete(sbi->read_page); |
| 352 | squashfs_decompressor_free(sbi, sbi->stream); | ||
| 349 | kfree(sbi->id_table); | 353 | kfree(sbi->id_table); |
| 350 | kfree(sbi->fragment_index); | 354 | kfree(sbi->fragment_index); |
| 351 | kfree(sbi->meta_index); | 355 | kfree(sbi->meta_index); |
| 352 | kfree(sbi->stream.workspace); | ||
| 353 | kfree(sb->s_fs_info); | 356 | kfree(sb->s_fs_info); |
| 354 | sb->s_fs_info = NULL; | 357 | sb->s_fs_info = NULL; |
| 355 | } | 358 | } |
diff --git a/fs/squashfs/symlink.c b/fs/squashfs/symlink.c index 83d87880aac8..e80be2022a7f 100644 --- a/fs/squashfs/symlink.c +++ b/fs/squashfs/symlink.c | |||
| @@ -36,7 +36,6 @@ | |||
| 36 | #include <linux/slab.h> | 36 | #include <linux/slab.h> |
| 37 | #include <linux/string.h> | 37 | #include <linux/string.h> |
| 38 | #include <linux/pagemap.h> | 38 | #include <linux/pagemap.h> |
| 39 | #include <linux/zlib.h> | ||
| 40 | 39 | ||
| 41 | #include "squashfs_fs.h" | 40 | #include "squashfs_fs.h" |
| 42 | #include "squashfs_fs_sb.h" | 41 | #include "squashfs_fs_sb.h" |
diff --git a/fs/squashfs/zlib_wrapper.c b/fs/squashfs/zlib_wrapper.c new file mode 100644 index 000000000000..4dd70e04333b --- /dev/null +++ b/fs/squashfs/zlib_wrapper.c | |||
| @@ -0,0 +1,150 @@ | |||
| 1 | /* | ||
| 2 | * Squashfs - a compressed read only filesystem for Linux | ||
| 3 | * | ||
| 4 | * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 | ||
| 5 | * Phillip Lougher <phillip@lougher.demon.co.uk> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or | ||
| 8 | * modify it under the terms of the GNU General Public License | ||
| 9 | * as published by the Free Software Foundation; either version 2, | ||
| 10 | * or (at your option) any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
| 20 | * | ||
| 21 | * zlib_wrapper.c | ||
| 22 | */ | ||
| 23 | |||
| 24 | |||
| 25 | #include <linux/mutex.h> | ||
| 26 | #include <linux/buffer_head.h> | ||
| 27 | #include <linux/zlib.h> | ||
| 28 | |||
| 29 | #include "squashfs_fs.h" | ||
| 30 | #include "squashfs_fs_sb.h" | ||
| 31 | #include "squashfs_fs_i.h" | ||
| 32 | #include "squashfs.h" | ||
| 33 | #include "decompressor.h" | ||
| 34 | |||
| 35 | static void *zlib_init(struct squashfs_sb_info *dummy) | ||
| 36 | { | ||
| 37 | z_stream *stream = kmalloc(sizeof(z_stream), GFP_KERNEL); | ||
| 38 | if (stream == NULL) | ||
| 39 | goto failed; | ||
| 40 | stream->workspace = kmalloc(zlib_inflate_workspacesize(), | ||
| 41 | GFP_KERNEL); | ||
| 42 | if (stream->workspace == NULL) | ||
| 43 | goto failed; | ||
| 44 | |||
| 45 | return stream; | ||
| 46 | |||
| 47 | failed: | ||
| 48 | ERROR("Failed to allocate zlib workspace\n"); | ||
| 49 | kfree(stream); | ||
| 50 | return NULL; | ||
| 51 | } | ||
| 52 | |||
| 53 | |||
| 54 | static void zlib_free(void *strm) | ||
| 55 | { | ||
| 56 | z_stream *stream = strm; | ||
| 57 | |||
| 58 | if (stream) | ||
| 59 | kfree(stream->workspace); | ||
| 60 | kfree(stream); | ||
| 61 | } | ||
| 62 | |||
| 63 | |||
| 64 | static int zlib_uncompress(struct squashfs_sb_info *msblk, void **buffer, | ||
| 65 | struct buffer_head **bh, int b, int offset, int length, int srclength, | ||
| 66 | int pages) | ||
| 67 | { | ||
| 68 | int zlib_err = 0, zlib_init = 0; | ||
| 69 | int avail, bytes, k = 0, page = 0; | ||
| 70 | z_stream *stream = msblk->stream; | ||
| 71 | |||
| 72 | mutex_lock(&msblk->read_data_mutex); | ||
| 73 | |||
| 74 | stream->avail_out = 0; | ||
| 75 | stream->avail_in = 0; | ||
| 76 | |||
| 77 | bytes = length; | ||
| 78 | do { | ||
| 79 | if (stream->avail_in == 0 && k < b) { | ||
| 80 | avail = min(bytes, msblk->devblksize - offset); | ||
| 81 | bytes -= avail; | ||
| 82 | wait_on_buffer(bh[k]); | ||
| 83 | if (!buffer_uptodate(bh[k])) | ||
| 84 | goto release_mutex; | ||
| 85 | |||
| 86 | if (avail == 0) { | ||
| 87 | offset = 0; | ||
| 88 | put_bh(bh[k++]); | ||
| 89 | continue; | ||
| 90 | } | ||
| 91 | |||
| 92 | stream->next_in = bh[k]->b_data + offset; | ||
| 93 | stream->avail_in = avail; | ||
| 94 | offset = 0; | ||
| 95 | } | ||
| 96 | |||
| 97 | if (stream->avail_out == 0 && page < pages) { | ||
| 98 | stream->next_out = buffer[page++]; | ||
| 99 | stream->avail_out = PAGE_CACHE_SIZE; | ||
| 100 | } | ||
| 101 | |||
| 102 | if (!zlib_init) { | ||
| 103 | zlib_err = zlib_inflateInit(stream); | ||
| 104 | if (zlib_err != Z_OK) { | ||
| 105 | ERROR("zlib_inflateInit returned unexpected " | ||
| 106 | "result 0x%x, srclength %d\n", | ||
| 107 | zlib_err, srclength); | ||
| 108 | goto release_mutex; | ||
| 109 | } | ||
| 110 | zlib_init = 1; | ||
| 111 | } | ||
| 112 | |||
| 113 | zlib_err = zlib_inflate(stream, Z_SYNC_FLUSH); | ||
| 114 | |||
| 115 | if (stream->avail_in == 0 && k < b) | ||
| 116 | put_bh(bh[k++]); | ||
| 117 | } while (zlib_err == Z_OK); | ||
| 118 | |||
| 119 | if (zlib_err != Z_STREAM_END) { | ||
| 120 | ERROR("zlib_inflate error, data probably corrupt\n"); | ||
| 121 | goto release_mutex; | ||
| 122 | } | ||
| 123 | |||
| 124 | zlib_err = zlib_inflateEnd(stream); | ||
| 125 | if (zlib_err != Z_OK) { | ||
| 126 | ERROR("zlib_inflate error, data probably corrupt\n"); | ||
| 127 | goto release_mutex; | ||
| 128 | } | ||
| 129 | |||
| 130 | mutex_unlock(&msblk->read_data_mutex); | ||
| 131 | return stream->total_out; | ||
| 132 | |||
| 133 | release_mutex: | ||
| 134 | mutex_unlock(&msblk->read_data_mutex); | ||
| 135 | |||
| 136 | for (; k < b; k++) | ||
| 137 | put_bh(bh[k]); | ||
| 138 | |||
| 139 | return -EIO; | ||
| 140 | } | ||
| 141 | |||
| 142 | const struct squashfs_decompressor squashfs_zlib_comp_ops = { | ||
| 143 | .init = zlib_init, | ||
| 144 | .free = zlib_free, | ||
| 145 | .decompress = zlib_uncompress, | ||
| 146 | .id = ZLIB_COMPRESSION, | ||
| 147 | .name = "zlib", | ||
| 148 | .supported = 1 | ||
| 149 | }; | ||
| 150 | |||
