diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/squashfs/Makefile | 2 | ||||
-rw-r--r-- | fs/squashfs/block.c | 11 | ||||
-rw-r--r-- | fs/squashfs/decompressor.c | 47 | ||||
-rw-r--r-- | fs/squashfs/decompressor.h | 21 | ||||
-rw-r--r-- | fs/squashfs/decompressor_single.c | 86 | ||||
-rw-r--r-- | fs/squashfs/lzo_wrapper.c | 24 | ||||
-rw-r--r-- | fs/squashfs/squashfs.h | 9 | ||||
-rw-r--r-- | fs/squashfs/squashfs_fs_sb.h | 3 | ||||
-rw-r--r-- | fs/squashfs/super.c | 10 | ||||
-rw-r--r-- | fs/squashfs/xz_wrapper.c | 89 | ||||
-rw-r--r-- | fs/squashfs/zlib_wrapper.c | 50 |
11 files changed, 216 insertions, 136 deletions
diff --git a/fs/squashfs/Makefile b/fs/squashfs/Makefile index 110b0476f3b4..c223c8439c21 100644 --- a/fs/squashfs/Makefile +++ b/fs/squashfs/Makefile | |||
@@ -4,7 +4,7 @@ | |||
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 decompressor.o | 7 | squashfs-y += namei.o super.o symlink.o decompressor.o decompressor_single.o |
8 | squashfs-$(CONFIG_SQUASHFS_XATTR) += xattr.o xattr_id.o | 8 | squashfs-$(CONFIG_SQUASHFS_XATTR) += xattr.o xattr_id.o |
9 | squashfs-$(CONFIG_SQUASHFS_LZO) += lzo_wrapper.o | 9 | squashfs-$(CONFIG_SQUASHFS_LZO) += lzo_wrapper.o |
10 | squashfs-$(CONFIG_SQUASHFS_XZ) += xz_wrapper.o | 10 | squashfs-$(CONFIG_SQUASHFS_XZ) += xz_wrapper.o |
diff --git a/fs/squashfs/block.c b/fs/squashfs/block.c index 41d108ecc9be..4dd402597f22 100644 --- a/fs/squashfs/block.c +++ b/fs/squashfs/block.c | |||
@@ -93,7 +93,7 @@ int squashfs_read_data(struct super_block *sb, void **buffer, u64 index, | |||
93 | struct buffer_head **bh; | 93 | struct buffer_head **bh; |
94 | int offset = index & ((1 << msblk->devblksize_log2) - 1); | 94 | int offset = index & ((1 << msblk->devblksize_log2) - 1); |
95 | u64 cur_index = index >> msblk->devblksize_log2; | 95 | u64 cur_index = index >> msblk->devblksize_log2; |
96 | int bytes, compressed, b = 0, k = 0, page = 0, avail; | 96 | int bytes, compressed, b = 0, k = 0, page = 0, avail, i; |
97 | 97 | ||
98 | bh = kcalloc(((srclength + msblk->devblksize - 1) | 98 | bh = kcalloc(((srclength + msblk->devblksize - 1) |
99 | >> msblk->devblksize_log2) + 1, sizeof(*bh), GFP_KERNEL); | 99 | >> msblk->devblksize_log2) + 1, sizeof(*bh), GFP_KERNEL); |
@@ -158,6 +158,12 @@ int squashfs_read_data(struct super_block *sb, void **buffer, u64 index, | |||
158 | ll_rw_block(READ, b - 1, bh + 1); | 158 | ll_rw_block(READ, b - 1, bh + 1); |
159 | } | 159 | } |
160 | 160 | ||
161 | for (i = 0; i < b; i++) { | ||
162 | wait_on_buffer(bh[i]); | ||
163 | if (!buffer_uptodate(bh[i])) | ||
164 | goto block_release; | ||
165 | } | ||
166 | |||
161 | if (compressed) { | 167 | if (compressed) { |
162 | length = squashfs_decompress(msblk, buffer, bh, b, offset, | 168 | length = squashfs_decompress(msblk, buffer, bh, b, offset, |
163 | length, srclength, pages); | 169 | length, srclength, pages); |
@@ -172,9 +178,6 @@ int squashfs_read_data(struct super_block *sb, void **buffer, u64 index, | |||
172 | for (bytes = length; k < b; k++) { | 178 | for (bytes = length; k < b; k++) { |
173 | in = min(bytes, msblk->devblksize - offset); | 179 | in = min(bytes, msblk->devblksize - offset); |
174 | bytes -= in; | 180 | bytes -= in; |
175 | wait_on_buffer(bh[k]); | ||
176 | if (!buffer_uptodate(bh[k])) | ||
177 | goto block_release; | ||
178 | while (in) { | 181 | while (in) { |
179 | if (pg_offset == PAGE_CACHE_SIZE) { | 182 | if (pg_offset == PAGE_CACHE_SIZE) { |
180 | page++; | 183 | page++; |
diff --git a/fs/squashfs/decompressor.c b/fs/squashfs/decompressor.c index 3f6271d86abc..234291f79ba5 100644 --- a/fs/squashfs/decompressor.c +++ b/fs/squashfs/decompressor.c | |||
@@ -37,29 +37,29 @@ | |||
37 | */ | 37 | */ |
38 | 38 | ||
39 | static const struct squashfs_decompressor squashfs_lzma_unsupported_comp_ops = { | 39 | static const struct squashfs_decompressor squashfs_lzma_unsupported_comp_ops = { |
40 | NULL, NULL, NULL, LZMA_COMPRESSION, "lzma", 0 | 40 | NULL, NULL, NULL, NULL, LZMA_COMPRESSION, "lzma", 0 |
41 | }; | 41 | }; |
42 | 42 | ||
43 | #ifndef CONFIG_SQUASHFS_LZO | 43 | #ifndef CONFIG_SQUASHFS_LZO |
44 | static const struct squashfs_decompressor squashfs_lzo_comp_ops = { | 44 | static const struct squashfs_decompressor squashfs_lzo_comp_ops = { |
45 | NULL, NULL, NULL, LZO_COMPRESSION, "lzo", 0 | 45 | NULL, NULL, NULL, NULL, LZO_COMPRESSION, "lzo", 0 |
46 | }; | 46 | }; |
47 | #endif | 47 | #endif |
48 | 48 | ||
49 | #ifndef CONFIG_SQUASHFS_XZ | 49 | #ifndef CONFIG_SQUASHFS_XZ |
50 | static const struct squashfs_decompressor squashfs_xz_comp_ops = { | 50 | static const struct squashfs_decompressor squashfs_xz_comp_ops = { |
51 | NULL, NULL, NULL, XZ_COMPRESSION, "xz", 0 | 51 | NULL, NULL, NULL, NULL, XZ_COMPRESSION, "xz", 0 |
52 | }; | 52 | }; |
53 | #endif | 53 | #endif |
54 | 54 | ||
55 | #ifndef CONFIG_SQUASHFS_ZLIB | 55 | #ifndef CONFIG_SQUASHFS_ZLIB |
56 | static const struct squashfs_decompressor squashfs_zlib_comp_ops = { | 56 | static const struct squashfs_decompressor squashfs_zlib_comp_ops = { |
57 | NULL, NULL, NULL, ZLIB_COMPRESSION, "zlib", 0 | 57 | NULL, NULL, NULL, NULL, ZLIB_COMPRESSION, "zlib", 0 |
58 | }; | 58 | }; |
59 | #endif | 59 | #endif |
60 | 60 | ||
61 | static const struct squashfs_decompressor squashfs_unknown_comp_ops = { | 61 | static const struct squashfs_decompressor squashfs_unknown_comp_ops = { |
62 | NULL, NULL, NULL, 0, "unknown", 0 | 62 | NULL, NULL, NULL, NULL, 0, "unknown", 0 |
63 | }; | 63 | }; |
64 | 64 | ||
65 | static const struct squashfs_decompressor *decompressor[] = { | 65 | static const struct squashfs_decompressor *decompressor[] = { |
@@ -83,10 +83,10 @@ const struct squashfs_decompressor *squashfs_lookup_decompressor(int id) | |||
83 | } | 83 | } |
84 | 84 | ||
85 | 85 | ||
86 | void *squashfs_decompressor_init(struct super_block *sb, unsigned short flags) | 86 | static void *get_comp_opts(struct super_block *sb, unsigned short flags) |
87 | { | 87 | { |
88 | struct squashfs_sb_info *msblk = sb->s_fs_info; | 88 | struct squashfs_sb_info *msblk = sb->s_fs_info; |
89 | void *strm, *buffer = NULL; | 89 | void *buffer = NULL, *comp_opts; |
90 | int length = 0; | 90 | int length = 0; |
91 | 91 | ||
92 | /* | 92 | /* |
@@ -94,23 +94,40 @@ void *squashfs_decompressor_init(struct super_block *sb, unsigned short flags) | |||
94 | */ | 94 | */ |
95 | if (SQUASHFS_COMP_OPTS(flags)) { | 95 | if (SQUASHFS_COMP_OPTS(flags)) { |
96 | buffer = kmalloc(PAGE_CACHE_SIZE, GFP_KERNEL); | 96 | buffer = kmalloc(PAGE_CACHE_SIZE, GFP_KERNEL); |
97 | if (buffer == NULL) | 97 | if (buffer == NULL) { |
98 | return ERR_PTR(-ENOMEM); | 98 | comp_opts = ERR_PTR(-ENOMEM); |
99 | goto out; | ||
100 | } | ||
99 | 101 | ||
100 | length = squashfs_read_data(sb, &buffer, | 102 | length = squashfs_read_data(sb, &buffer, |
101 | sizeof(struct squashfs_super_block), 0, NULL, | 103 | sizeof(struct squashfs_super_block), 0, NULL, |
102 | PAGE_CACHE_SIZE, 1); | 104 | PAGE_CACHE_SIZE, 1); |
103 | 105 | ||
104 | if (length < 0) { | 106 | if (length < 0) { |
105 | strm = ERR_PTR(length); | 107 | comp_opts = ERR_PTR(length); |
106 | goto finished; | 108 | goto out; |
107 | } | 109 | } |
108 | } | 110 | } |
109 | 111 | ||
110 | strm = msblk->decompressor->init(msblk, buffer, length); | 112 | comp_opts = squashfs_comp_opts(msblk, buffer, length); |
111 | 113 | ||
112 | finished: | 114 | out: |
113 | kfree(buffer); | 115 | kfree(buffer); |
116 | return comp_opts; | ||
117 | } | ||
118 | |||
119 | |||
120 | void *squashfs_decompressor_setup(struct super_block *sb, unsigned short flags) | ||
121 | { | ||
122 | struct squashfs_sb_info *msblk = sb->s_fs_info; | ||
123 | void *stream, *comp_opts = get_comp_opts(sb, flags); | ||
124 | |||
125 | if (IS_ERR(comp_opts)) | ||
126 | return comp_opts; | ||
127 | |||
128 | stream = squashfs_decompressor_create(msblk, comp_opts); | ||
129 | if (IS_ERR(stream)) | ||
130 | kfree(comp_opts); | ||
114 | 131 | ||
115 | return strm; | 132 | return stream; |
116 | } | 133 | } |
diff --git a/fs/squashfs/decompressor.h b/fs/squashfs/decompressor.h index 330073e29029..6cdb20a3878a 100644 --- a/fs/squashfs/decompressor.h +++ b/fs/squashfs/decompressor.h | |||
@@ -24,28 +24,21 @@ | |||
24 | */ | 24 | */ |
25 | 25 | ||
26 | struct squashfs_decompressor { | 26 | struct squashfs_decompressor { |
27 | void *(*init)(struct squashfs_sb_info *, void *, int); | 27 | void *(*init)(struct squashfs_sb_info *, void *); |
28 | void *(*comp_opts)(struct squashfs_sb_info *, void *, int); | ||
28 | void (*free)(void *); | 29 | void (*free)(void *); |
29 | int (*decompress)(struct squashfs_sb_info *, void **, | 30 | int (*decompress)(struct squashfs_sb_info *, void *, void **, |
30 | struct buffer_head **, int, int, int, int, int); | 31 | struct buffer_head **, int, int, int, int, int); |
31 | int id; | 32 | int id; |
32 | char *name; | 33 | char *name; |
33 | int supported; | 34 | int supported; |
34 | }; | 35 | }; |
35 | 36 | ||
36 | static inline void squashfs_decompressor_free(struct squashfs_sb_info *msblk, | 37 | static inline void *squashfs_comp_opts(struct squashfs_sb_info *msblk, |
37 | void *s) | 38 | void *buff, int length) |
38 | { | 39 | { |
39 | if (msblk->decompressor) | 40 | return msblk->decompressor->comp_opts ? |
40 | msblk->decompressor->free(s); | 41 | msblk->decompressor->comp_opts(msblk, buff, length) : NULL; |
41 | } | ||
42 | |||
43 | static inline int squashfs_decompress(struct squashfs_sb_info *msblk, | ||
44 | void **buffer, struct buffer_head **bh, int b, int offset, int length, | ||
45 | int srclength, int pages) | ||
46 | { | ||
47 | return msblk->decompressor->decompress(msblk, buffer, bh, b, offset, | ||
48 | length, srclength, pages); | ||
49 | } | 42 | } |
50 | 43 | ||
51 | #ifdef CONFIG_SQUASHFS_XZ | 44 | #ifdef CONFIG_SQUASHFS_XZ |
diff --git a/fs/squashfs/decompressor_single.c b/fs/squashfs/decompressor_single.c new file mode 100644 index 000000000000..f857cf6f22d4 --- /dev/null +++ b/fs/squashfs/decompressor_single.c | |||
@@ -0,0 +1,86 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013 | ||
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/types.h> | ||
10 | #include <linux/mutex.h> | ||
11 | #include <linux/slab.h> | ||
12 | #include <linux/buffer_head.h> | ||
13 | |||
14 | #include "squashfs_fs.h" | ||
15 | #include "squashfs_fs_sb.h" | ||
16 | #include "decompressor.h" | ||
17 | #include "squashfs.h" | ||
18 | |||
19 | /* | ||
20 | * This file implements single-threaded decompression in the | ||
21 | * decompressor framework | ||
22 | */ | ||
23 | |||
24 | struct squashfs_stream { | ||
25 | void *stream; | ||
26 | struct mutex mutex; | ||
27 | }; | ||
28 | |||
29 | void *squashfs_decompressor_create(struct squashfs_sb_info *msblk, | ||
30 | void *comp_opts) | ||
31 | { | ||
32 | struct squashfs_stream *stream; | ||
33 | int err = -ENOMEM; | ||
34 | |||
35 | stream = kmalloc(sizeof(*stream), GFP_KERNEL); | ||
36 | if (stream == NULL) | ||
37 | goto out; | ||
38 | |||
39 | stream->stream = msblk->decompressor->init(msblk, comp_opts); | ||
40 | if (IS_ERR(stream->stream)) { | ||
41 | err = PTR_ERR(stream->stream); | ||
42 | goto out; | ||
43 | } | ||
44 | |||
45 | kfree(comp_opts); | ||
46 | mutex_init(&stream->mutex); | ||
47 | return stream; | ||
48 | |||
49 | out: | ||
50 | kfree(stream); | ||
51 | return ERR_PTR(err); | ||
52 | } | ||
53 | |||
54 | void squashfs_decompressor_destroy(struct squashfs_sb_info *msblk) | ||
55 | { | ||
56 | struct squashfs_stream *stream = msblk->stream; | ||
57 | |||
58 | if (stream) { | ||
59 | msblk->decompressor->free(stream->stream); | ||
60 | kfree(stream); | ||
61 | } | ||
62 | } | ||
63 | |||
64 | int squashfs_decompress(struct squashfs_sb_info *msblk, | ||
65 | void **buffer, struct buffer_head **bh, int b, int offset, int length, | ||
66 | int srclength, int pages) | ||
67 | { | ||
68 | int res; | ||
69 | struct squashfs_stream *stream = msblk->stream; | ||
70 | |||
71 | mutex_lock(&stream->mutex); | ||
72 | res = msblk->decompressor->decompress(msblk, stream->stream, buffer, | ||
73 | bh, b, offset, length, srclength, pages); | ||
74 | mutex_unlock(&stream->mutex); | ||
75 | |||
76 | if (res < 0) | ||
77 | ERROR("%s decompression failed, data probably corrupt\n", | ||
78 | msblk->decompressor->name); | ||
79 | |||
80 | return res; | ||
81 | } | ||
82 | |||
83 | int squashfs_max_decompressors(void) | ||
84 | { | ||
85 | return 1; | ||
86 | } | ||
diff --git a/fs/squashfs/lzo_wrapper.c b/fs/squashfs/lzo_wrapper.c index 00f4dfc5f088..75c3b5779172 100644 --- a/fs/squashfs/lzo_wrapper.c +++ b/fs/squashfs/lzo_wrapper.c | |||
@@ -37,7 +37,7 @@ struct squashfs_lzo { | |||
37 | void *output; | 37 | void *output; |
38 | }; | 38 | }; |
39 | 39 | ||
40 | static void *lzo_init(struct squashfs_sb_info *msblk, void *buff, int len) | 40 | static void *lzo_init(struct squashfs_sb_info *msblk, void *buff) |
41 | { | 41 | { |
42 | int block_size = max_t(int, msblk->block_size, SQUASHFS_METADATA_SIZE); | 42 | int block_size = max_t(int, msblk->block_size, SQUASHFS_METADATA_SIZE); |
43 | 43 | ||
@@ -74,22 +74,16 @@ static void lzo_free(void *strm) | |||
74 | } | 74 | } |
75 | 75 | ||
76 | 76 | ||
77 | static int lzo_uncompress(struct squashfs_sb_info *msblk, void **buffer, | 77 | static int lzo_uncompress(struct squashfs_sb_info *msblk, void *strm, |
78 | struct buffer_head **bh, int b, int offset, int length, int srclength, | 78 | void **buffer, struct buffer_head **bh, int b, int offset, int length, |
79 | int pages) | 79 | int srclength, int pages) |
80 | { | 80 | { |
81 | struct squashfs_lzo *stream = msblk->stream; | 81 | struct squashfs_lzo *stream = strm; |
82 | void *buff = stream->input; | 82 | void *buff = stream->input; |
83 | int avail, i, bytes = length, res; | 83 | int avail, i, bytes = length, res; |
84 | size_t out_len = srclength; | 84 | size_t out_len = srclength; |
85 | 85 | ||
86 | mutex_lock(&msblk->read_data_mutex); | ||
87 | |||
88 | for (i = 0; i < b; i++) { | 86 | for (i = 0; i < b; i++) { |
89 | wait_on_buffer(bh[i]); | ||
90 | if (!buffer_uptodate(bh[i])) | ||
91 | goto block_release; | ||
92 | |||
93 | avail = min(bytes, msblk->devblksize - offset); | 87 | avail = min(bytes, msblk->devblksize - offset); |
94 | memcpy(buff, bh[i]->b_data + offset, avail); | 88 | memcpy(buff, bh[i]->b_data + offset, avail); |
95 | buff += avail; | 89 | buff += avail; |
@@ -111,17 +105,9 @@ static int lzo_uncompress(struct squashfs_sb_info *msblk, void **buffer, | |||
111 | bytes -= avail; | 105 | bytes -= avail; |
112 | } | 106 | } |
113 | 107 | ||
114 | mutex_unlock(&msblk->read_data_mutex); | ||
115 | return res; | 108 | return res; |
116 | 109 | ||
117 | block_release: | ||
118 | for (; i < b; i++) | ||
119 | put_bh(bh[i]); | ||
120 | |||
121 | failed: | 110 | failed: |
122 | mutex_unlock(&msblk->read_data_mutex); | ||
123 | |||
124 | ERROR("lzo decompression failed, data probably corrupt\n"); | ||
125 | return -EIO; | 111 | return -EIO; |
126 | } | 112 | } |
127 | 113 | ||
diff --git a/fs/squashfs/squashfs.h b/fs/squashfs/squashfs.h index d1266516ed08..2e2751df8452 100644 --- a/fs/squashfs/squashfs.h +++ b/fs/squashfs/squashfs.h | |||
@@ -48,7 +48,14 @@ extern void *squashfs_read_table(struct super_block *, u64, int); | |||
48 | 48 | ||
49 | /* decompressor.c */ | 49 | /* decompressor.c */ |
50 | extern const struct squashfs_decompressor *squashfs_lookup_decompressor(int); | 50 | extern const struct squashfs_decompressor *squashfs_lookup_decompressor(int); |
51 | extern void *squashfs_decompressor_init(struct super_block *, unsigned short); | 51 | extern void *squashfs_decompressor_setup(struct super_block *, unsigned short); |
52 | |||
53 | /* decompressor_xxx.c */ | ||
54 | extern void *squashfs_decompressor_create(struct squashfs_sb_info *, void *); | ||
55 | extern void squashfs_decompressor_destroy(struct squashfs_sb_info *); | ||
56 | extern int squashfs_decompress(struct squashfs_sb_info *, void **, | ||
57 | struct buffer_head **, int, int, int, int, int); | ||
58 | extern int squashfs_max_decompressors(void); | ||
52 | 59 | ||
53 | /* export.c */ | 60 | /* export.c */ |
54 | extern __le64 *squashfs_read_inode_lookup_table(struct super_block *, u64, u64, | 61 | extern __le64 *squashfs_read_inode_lookup_table(struct super_block *, u64, u64, |
diff --git a/fs/squashfs/squashfs_fs_sb.h b/fs/squashfs/squashfs_fs_sb.h index 52934a22f296..9cdcf4150d59 100644 --- a/fs/squashfs/squashfs_fs_sb.h +++ b/fs/squashfs/squashfs_fs_sb.h | |||
@@ -63,10 +63,9 @@ struct squashfs_sb_info { | |||
63 | __le64 *id_table; | 63 | __le64 *id_table; |
64 | __le64 *fragment_index; | 64 | __le64 *fragment_index; |
65 | __le64 *xattr_id_table; | 65 | __le64 *xattr_id_table; |
66 | struct mutex read_data_mutex; | ||
67 | struct mutex meta_index_mutex; | 66 | struct mutex meta_index_mutex; |
68 | struct meta_index *meta_index; | 67 | struct meta_index *meta_index; |
69 | void *stream; | 68 | struct squashfs_stream *stream; |
70 | __le64 *inode_lookup_table; | 69 | __le64 *inode_lookup_table; |
71 | u64 inode_table; | 70 | u64 inode_table; |
72 | u64 directory_table; | 71 | u64 directory_table; |
diff --git a/fs/squashfs/super.c b/fs/squashfs/super.c index 60553a9053ca..202df6312d4e 100644 --- a/fs/squashfs/super.c +++ b/fs/squashfs/super.c | |||
@@ -98,7 +98,6 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent) | |||
98 | msblk->devblksize = sb_min_blocksize(sb, SQUASHFS_DEVBLK_SIZE); | 98 | msblk->devblksize = sb_min_blocksize(sb, SQUASHFS_DEVBLK_SIZE); |
99 | msblk->devblksize_log2 = ffz(~msblk->devblksize); | 99 | msblk->devblksize_log2 = ffz(~msblk->devblksize); |
100 | 100 | ||
101 | mutex_init(&msblk->read_data_mutex); | ||
102 | mutex_init(&msblk->meta_index_mutex); | 101 | mutex_init(&msblk->meta_index_mutex); |
103 | 102 | ||
104 | /* | 103 | /* |
@@ -206,13 +205,14 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent) | |||
206 | goto failed_mount; | 205 | goto failed_mount; |
207 | 206 | ||
208 | /* Allocate read_page block */ | 207 | /* Allocate read_page block */ |
209 | msblk->read_page = squashfs_cache_init("data", 1, msblk->block_size); | 208 | msblk->read_page = squashfs_cache_init("data", |
209 | squashfs_max_decompressors(), msblk->block_size); | ||
210 | if (msblk->read_page == NULL) { | 210 | if (msblk->read_page == NULL) { |
211 | ERROR("Failed to allocate read_page block\n"); | 211 | ERROR("Failed to allocate read_page block\n"); |
212 | goto failed_mount; | 212 | goto failed_mount; |
213 | } | 213 | } |
214 | 214 | ||
215 | msblk->stream = squashfs_decompressor_init(sb, flags); | 215 | msblk->stream = squashfs_decompressor_setup(sb, flags); |
216 | if (IS_ERR(msblk->stream)) { | 216 | if (IS_ERR(msblk->stream)) { |
217 | err = PTR_ERR(msblk->stream); | 217 | err = PTR_ERR(msblk->stream); |
218 | msblk->stream = NULL; | 218 | msblk->stream = NULL; |
@@ -336,7 +336,7 @@ failed_mount: | |||
336 | squashfs_cache_delete(msblk->block_cache); | 336 | squashfs_cache_delete(msblk->block_cache); |
337 | squashfs_cache_delete(msblk->fragment_cache); | 337 | squashfs_cache_delete(msblk->fragment_cache); |
338 | squashfs_cache_delete(msblk->read_page); | 338 | squashfs_cache_delete(msblk->read_page); |
339 | squashfs_decompressor_free(msblk, msblk->stream); | 339 | squashfs_decompressor_destroy(msblk); |
340 | kfree(msblk->inode_lookup_table); | 340 | kfree(msblk->inode_lookup_table); |
341 | kfree(msblk->fragment_index); | 341 | kfree(msblk->fragment_index); |
342 | kfree(msblk->id_table); | 342 | kfree(msblk->id_table); |
@@ -383,7 +383,7 @@ static void squashfs_put_super(struct super_block *sb) | |||
383 | squashfs_cache_delete(sbi->block_cache); | 383 | squashfs_cache_delete(sbi->block_cache); |
384 | squashfs_cache_delete(sbi->fragment_cache); | 384 | squashfs_cache_delete(sbi->fragment_cache); |
385 | squashfs_cache_delete(sbi->read_page); | 385 | squashfs_cache_delete(sbi->read_page); |
386 | squashfs_decompressor_free(sbi, sbi->stream); | 386 | squashfs_decompressor_destroy(sbi); |
387 | kfree(sbi->id_table); | 387 | kfree(sbi->id_table); |
388 | kfree(sbi->fragment_index); | 388 | kfree(sbi->fragment_index); |
389 | kfree(sbi->meta_index); | 389 | kfree(sbi->meta_index); |
diff --git a/fs/squashfs/xz_wrapper.c b/fs/squashfs/xz_wrapper.c index 1760b7d108f6..5d1d07cca6b4 100644 --- a/fs/squashfs/xz_wrapper.c +++ b/fs/squashfs/xz_wrapper.c | |||
@@ -38,38 +38,63 @@ struct squashfs_xz { | |||
38 | struct xz_buf buf; | 38 | struct xz_buf buf; |
39 | }; | 39 | }; |
40 | 40 | ||
41 | struct comp_opts { | 41 | struct disk_comp_opts { |
42 | __le32 dictionary_size; | 42 | __le32 dictionary_size; |
43 | __le32 flags; | 43 | __le32 flags; |
44 | }; | 44 | }; |
45 | 45 | ||
46 | static void *squashfs_xz_init(struct squashfs_sb_info *msblk, void *buff, | 46 | struct comp_opts { |
47 | int len) | 47 | int dict_size; |
48 | }; | ||
49 | |||
50 | static void *squashfs_xz_comp_opts(struct squashfs_sb_info *msblk, | ||
51 | void *buff, int len) | ||
48 | { | 52 | { |
49 | struct comp_opts *comp_opts = buff; | 53 | struct disk_comp_opts *comp_opts = buff; |
50 | struct squashfs_xz *stream; | 54 | struct comp_opts *opts; |
51 | int dict_size = msblk->block_size; | 55 | int err = 0, n; |
52 | int err, n; | 56 | |
57 | opts = kmalloc(sizeof(*opts), GFP_KERNEL); | ||
58 | if (opts == NULL) { | ||
59 | err = -ENOMEM; | ||
60 | goto out2; | ||
61 | } | ||
53 | 62 | ||
54 | if (comp_opts) { | 63 | if (comp_opts) { |
55 | /* check compressor options are the expected length */ | 64 | /* check compressor options are the expected length */ |
56 | if (len < sizeof(*comp_opts)) { | 65 | if (len < sizeof(*comp_opts)) { |
57 | err = -EIO; | 66 | err = -EIO; |
58 | goto failed; | 67 | goto out; |
59 | } | 68 | } |
60 | 69 | ||
61 | dict_size = le32_to_cpu(comp_opts->dictionary_size); | 70 | opts->dict_size = le32_to_cpu(comp_opts->dictionary_size); |
62 | 71 | ||
63 | /* the dictionary size should be 2^n or 2^n+2^(n+1) */ | 72 | /* the dictionary size should be 2^n or 2^n+2^(n+1) */ |
64 | n = ffs(dict_size) - 1; | 73 | n = ffs(opts->dict_size) - 1; |
65 | if (dict_size != (1 << n) && dict_size != (1 << n) + | 74 | if (opts->dict_size != (1 << n) && opts->dict_size != (1 << n) + |
66 | (1 << (n + 1))) { | 75 | (1 << (n + 1))) { |
67 | err = -EIO; | 76 | err = -EIO; |
68 | goto failed; | 77 | goto out; |
69 | } | 78 | } |
70 | } | 79 | } else |
80 | /* use defaults */ | ||
81 | opts->dict_size = max_t(int, msblk->block_size, | ||
82 | SQUASHFS_METADATA_SIZE); | ||
71 | 83 | ||
72 | dict_size = max_t(int, dict_size, SQUASHFS_METADATA_SIZE); | 84 | return opts; |
85 | |||
86 | out: | ||
87 | kfree(opts); | ||
88 | out2: | ||
89 | return ERR_PTR(err); | ||
90 | } | ||
91 | |||
92 | |||
93 | static void *squashfs_xz_init(struct squashfs_sb_info *msblk, void *buff) | ||
94 | { | ||
95 | struct comp_opts *comp_opts = buff; | ||
96 | struct squashfs_xz *stream; | ||
97 | int err; | ||
73 | 98 | ||
74 | stream = kmalloc(sizeof(*stream), GFP_KERNEL); | 99 | stream = kmalloc(sizeof(*stream), GFP_KERNEL); |
75 | if (stream == NULL) { | 100 | if (stream == NULL) { |
@@ -77,7 +102,7 @@ static void *squashfs_xz_init(struct squashfs_sb_info *msblk, void *buff, | |||
77 | goto failed; | 102 | goto failed; |
78 | } | 103 | } |
79 | 104 | ||
80 | stream->state = xz_dec_init(XZ_PREALLOC, dict_size); | 105 | stream->state = xz_dec_init(XZ_PREALLOC, comp_opts->dict_size); |
81 | if (stream->state == NULL) { | 106 | if (stream->state == NULL) { |
82 | kfree(stream); | 107 | kfree(stream); |
83 | err = -ENOMEM; | 108 | err = -ENOMEM; |
@@ -103,15 +128,13 @@ static void squashfs_xz_free(void *strm) | |||
103 | } | 128 | } |
104 | 129 | ||
105 | 130 | ||
106 | static int squashfs_xz_uncompress(struct squashfs_sb_info *msblk, void **buffer, | 131 | static int squashfs_xz_uncompress(struct squashfs_sb_info *msblk, void *strm, |
107 | struct buffer_head **bh, int b, int offset, int length, int srclength, | 132 | void **buffer, struct buffer_head **bh, int b, int offset, int length, |
108 | int pages) | 133 | int srclength, int pages) |
109 | { | 134 | { |
110 | enum xz_ret xz_err; | 135 | enum xz_ret xz_err; |
111 | int avail, total = 0, k = 0, page = 0; | 136 | int avail, total = 0, k = 0, page = 0; |
112 | struct squashfs_xz *stream = msblk->stream; | 137 | struct squashfs_xz *stream = strm; |
113 | |||
114 | mutex_lock(&msblk->read_data_mutex); | ||
115 | 138 | ||
116 | xz_dec_reset(stream->state); | 139 | xz_dec_reset(stream->state); |
117 | stream->buf.in_pos = 0; | 140 | stream->buf.in_pos = 0; |
@@ -124,10 +147,6 @@ static int squashfs_xz_uncompress(struct squashfs_sb_info *msblk, void **buffer, | |||
124 | if (stream->buf.in_pos == stream->buf.in_size && k < b) { | 147 | if (stream->buf.in_pos == stream->buf.in_size && k < b) { |
125 | avail = min(length, msblk->devblksize - offset); | 148 | avail = min(length, msblk->devblksize - offset); |
126 | length -= avail; | 149 | length -= avail; |
127 | wait_on_buffer(bh[k]); | ||
128 | if (!buffer_uptodate(bh[k])) | ||
129 | goto release_mutex; | ||
130 | |||
131 | stream->buf.in = bh[k]->b_data + offset; | 150 | stream->buf.in = bh[k]->b_data + offset; |
132 | stream->buf.in_size = avail; | 151 | stream->buf.in_size = avail; |
133 | stream->buf.in_pos = 0; | 152 | stream->buf.in_pos = 0; |
@@ -147,23 +166,12 @@ static int squashfs_xz_uncompress(struct squashfs_sb_info *msblk, void **buffer, | |||
147 | put_bh(bh[k++]); | 166 | put_bh(bh[k++]); |
148 | } while (xz_err == XZ_OK); | 167 | } while (xz_err == XZ_OK); |
149 | 168 | ||
150 | if (xz_err != XZ_STREAM_END) { | 169 | if (xz_err != XZ_STREAM_END || k < b) |
151 | ERROR("xz_dec_run error, data probably corrupt\n"); | 170 | goto out; |
152 | goto release_mutex; | ||
153 | } | ||
154 | |||
155 | if (k < b) { | ||
156 | ERROR("xz_uncompress error, input remaining\n"); | ||
157 | goto release_mutex; | ||
158 | } | ||
159 | |||
160 | total += stream->buf.out_pos; | ||
161 | mutex_unlock(&msblk->read_data_mutex); | ||
162 | return total; | ||
163 | 171 | ||
164 | release_mutex: | 172 | return total + stream->buf.out_pos; |
165 | mutex_unlock(&msblk->read_data_mutex); | ||
166 | 173 | ||
174 | out: | ||
167 | for (; k < b; k++) | 175 | for (; k < b; k++) |
168 | put_bh(bh[k]); | 176 | put_bh(bh[k]); |
169 | 177 | ||
@@ -172,6 +180,7 @@ release_mutex: | |||
172 | 180 | ||
173 | const struct squashfs_decompressor squashfs_xz_comp_ops = { | 181 | const struct squashfs_decompressor squashfs_xz_comp_ops = { |
174 | .init = squashfs_xz_init, | 182 | .init = squashfs_xz_init, |
183 | .comp_opts = squashfs_xz_comp_opts, | ||
175 | .free = squashfs_xz_free, | 184 | .free = squashfs_xz_free, |
176 | .decompress = squashfs_xz_uncompress, | 185 | .decompress = squashfs_xz_uncompress, |
177 | .id = XZ_COMPRESSION, | 186 | .id = XZ_COMPRESSION, |
diff --git a/fs/squashfs/zlib_wrapper.c b/fs/squashfs/zlib_wrapper.c index 55d918fd2d86..bb049027d15c 100644 --- a/fs/squashfs/zlib_wrapper.c +++ b/fs/squashfs/zlib_wrapper.c | |||
@@ -33,7 +33,7 @@ | |||
33 | #include "squashfs.h" | 33 | #include "squashfs.h" |
34 | #include "decompressor.h" | 34 | #include "decompressor.h" |
35 | 35 | ||
36 | static void *zlib_init(struct squashfs_sb_info *dummy, void *buff, int len) | 36 | static void *zlib_init(struct squashfs_sb_info *dummy, void *buff) |
37 | { | 37 | { |
38 | z_stream *stream = kmalloc(sizeof(z_stream), GFP_KERNEL); | 38 | z_stream *stream = kmalloc(sizeof(z_stream), GFP_KERNEL); |
39 | if (stream == NULL) | 39 | if (stream == NULL) |
@@ -61,15 +61,13 @@ static void zlib_free(void *strm) | |||
61 | } | 61 | } |
62 | 62 | ||
63 | 63 | ||
64 | static int zlib_uncompress(struct squashfs_sb_info *msblk, void **buffer, | 64 | static int zlib_uncompress(struct squashfs_sb_info *msblk, void *strm, |
65 | struct buffer_head **bh, int b, int offset, int length, int srclength, | 65 | void **buffer, struct buffer_head **bh, int b, int offset, int length, |
66 | int pages) | 66 | int srclength, int pages) |
67 | { | 67 | { |
68 | int zlib_err, zlib_init = 0; | 68 | int zlib_err, zlib_init = 0; |
69 | int k = 0, page = 0; | 69 | int k = 0, page = 0; |
70 | z_stream *stream = msblk->stream; | 70 | z_stream *stream = strm; |
71 | |||
72 | mutex_lock(&msblk->read_data_mutex); | ||
73 | 71 | ||
74 | stream->avail_out = 0; | 72 | stream->avail_out = 0; |
75 | stream->avail_in = 0; | 73 | stream->avail_in = 0; |
@@ -78,10 +76,6 @@ static int zlib_uncompress(struct squashfs_sb_info *msblk, void **buffer, | |||
78 | if (stream->avail_in == 0 && k < b) { | 76 | if (stream->avail_in == 0 && k < b) { |
79 | int avail = min(length, msblk->devblksize - offset); | 77 | int avail = min(length, msblk->devblksize - offset); |
80 | length -= avail; | 78 | length -= avail; |
81 | wait_on_buffer(bh[k]); | ||
82 | if (!buffer_uptodate(bh[k])) | ||
83 | goto release_mutex; | ||
84 | |||
85 | stream->next_in = bh[k]->b_data + offset; | 79 | stream->next_in = bh[k]->b_data + offset; |
86 | stream->avail_in = avail; | 80 | stream->avail_in = avail; |
87 | offset = 0; | 81 | offset = 0; |
@@ -94,12 +88,8 @@ static int zlib_uncompress(struct squashfs_sb_info *msblk, void **buffer, | |||
94 | 88 | ||
95 | if (!zlib_init) { | 89 | if (!zlib_init) { |
96 | zlib_err = zlib_inflateInit(stream); | 90 | zlib_err = zlib_inflateInit(stream); |
97 | if (zlib_err != Z_OK) { | 91 | if (zlib_err != Z_OK) |
98 | ERROR("zlib_inflateInit returned unexpected " | 92 | goto out; |
99 | "result 0x%x, srclength %d\n", | ||
100 | zlib_err, srclength); | ||
101 | goto release_mutex; | ||
102 | } | ||
103 | zlib_init = 1; | 93 | zlib_init = 1; |
104 | } | 94 | } |
105 | 95 | ||
@@ -109,29 +99,19 @@ static int zlib_uncompress(struct squashfs_sb_info *msblk, void **buffer, | |||
109 | put_bh(bh[k++]); | 99 | put_bh(bh[k++]); |
110 | } while (zlib_err == Z_OK); | 100 | } while (zlib_err == Z_OK); |
111 | 101 | ||
112 | if (zlib_err != Z_STREAM_END) { | 102 | if (zlib_err != Z_STREAM_END) |
113 | ERROR("zlib_inflate error, data probably corrupt\n"); | 103 | goto out; |
114 | goto release_mutex; | ||
115 | } | ||
116 | 104 | ||
117 | zlib_err = zlib_inflateEnd(stream); | 105 | zlib_err = zlib_inflateEnd(stream); |
118 | if (zlib_err != Z_OK) { | 106 | if (zlib_err != Z_OK) |
119 | ERROR("zlib_inflate error, data probably corrupt\n"); | 107 | goto out; |
120 | goto release_mutex; | ||
121 | } | ||
122 | |||
123 | if (k < b) { | ||
124 | ERROR("zlib_uncompress error, data remaining\n"); | ||
125 | goto release_mutex; | ||
126 | } | ||
127 | 108 | ||
128 | length = stream->total_out; | 109 | if (k < b) |
129 | mutex_unlock(&msblk->read_data_mutex); | 110 | goto out; |
130 | return length; | ||
131 | 111 | ||
132 | release_mutex: | 112 | return stream->total_out; |
133 | mutex_unlock(&msblk->read_data_mutex); | ||
134 | 113 | ||
114 | out: | ||
135 | for (; k < b; k++) | 115 | for (; k < b; k++) |
136 | put_bh(bh[k]); | 116 | put_bh(bh[k]); |
137 | 117 | ||