aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/squashfs/Makefile2
-rw-r--r--fs/squashfs/block.c11
-rw-r--r--fs/squashfs/decompressor.c47
-rw-r--r--fs/squashfs/decompressor.h21
-rw-r--r--fs/squashfs/decompressor_single.c86
-rw-r--r--fs/squashfs/lzo_wrapper.c24
-rw-r--r--fs/squashfs/squashfs.h9
-rw-r--r--fs/squashfs/squashfs_fs_sb.h3
-rw-r--r--fs/squashfs/super.c10
-rw-r--r--fs/squashfs/xz_wrapper.c89
-rw-r--r--fs/squashfs/zlib_wrapper.c50
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
5obj-$(CONFIG_SQUASHFS) += squashfs.o 5obj-$(CONFIG_SQUASHFS) += squashfs.o
6squashfs-y += block.o cache.o dir.o export.o file.o fragment.o id.o inode.o 6squashfs-y += block.o cache.o dir.o export.o file.o fragment.o id.o inode.o
7squashfs-y += namei.o super.o symlink.o decompressor.o 7squashfs-y += namei.o super.o symlink.o decompressor.o decompressor_single.o
8squashfs-$(CONFIG_SQUASHFS_XATTR) += xattr.o xattr_id.o 8squashfs-$(CONFIG_SQUASHFS_XATTR) += xattr.o xattr_id.o
9squashfs-$(CONFIG_SQUASHFS_LZO) += lzo_wrapper.o 9squashfs-$(CONFIG_SQUASHFS_LZO) += lzo_wrapper.o
10squashfs-$(CONFIG_SQUASHFS_XZ) += xz_wrapper.o 10squashfs-$(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
39static const struct squashfs_decompressor squashfs_lzma_unsupported_comp_ops = { 39static 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
44static const struct squashfs_decompressor squashfs_lzo_comp_ops = { 44static 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
50static const struct squashfs_decompressor squashfs_xz_comp_ops = { 50static 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
56static const struct squashfs_decompressor squashfs_zlib_comp_ops = { 56static 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
61static const struct squashfs_decompressor squashfs_unknown_comp_ops = { 61static 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
65static const struct squashfs_decompressor *decompressor[] = { 65static const struct squashfs_decompressor *decompressor[] = {
@@ -83,10 +83,10 @@ const struct squashfs_decompressor *squashfs_lookup_decompressor(int id)
83} 83}
84 84
85 85
86void *squashfs_decompressor_init(struct super_block *sb, unsigned short flags) 86static 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
112finished: 114out:
113 kfree(buffer); 115 kfree(buffer);
116 return comp_opts;
117}
118
119
120void *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
26struct squashfs_decompressor { 26struct 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
36static inline void squashfs_decompressor_free(struct squashfs_sb_info *msblk, 37static 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
43static 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
24struct squashfs_stream {
25 void *stream;
26 struct mutex mutex;
27};
28
29void *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
49out:
50 kfree(stream);
51 return ERR_PTR(err);
52}
53
54void 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
64int 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
83int 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
40static void *lzo_init(struct squashfs_sb_info *msblk, void *buff, int len) 40static 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
77static int lzo_uncompress(struct squashfs_sb_info *msblk, void **buffer, 77static 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
117block_release:
118 for (; i < b; i++)
119 put_bh(bh[i]);
120
121failed: 110failed:
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 */
50extern const struct squashfs_decompressor *squashfs_lookup_decompressor(int); 50extern const struct squashfs_decompressor *squashfs_lookup_decompressor(int);
51extern void *squashfs_decompressor_init(struct super_block *, unsigned short); 51extern void *squashfs_decompressor_setup(struct super_block *, unsigned short);
52
53/* decompressor_xxx.c */
54extern void *squashfs_decompressor_create(struct squashfs_sb_info *, void *);
55extern void squashfs_decompressor_destroy(struct squashfs_sb_info *);
56extern int squashfs_decompress(struct squashfs_sb_info *, void **,
57 struct buffer_head **, int, int, int, int, int);
58extern int squashfs_max_decompressors(void);
52 59
53/* export.c */ 60/* export.c */
54extern __le64 *squashfs_read_inode_lookup_table(struct super_block *, u64, u64, 61extern __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
41struct comp_opts { 41struct disk_comp_opts {
42 __le32 dictionary_size; 42 __le32 dictionary_size;
43 __le32 flags; 43 __le32 flags;
44}; 44};
45 45
46static void *squashfs_xz_init(struct squashfs_sb_info *msblk, void *buff, 46struct comp_opts {
47 int len) 47 int dict_size;
48};
49
50static 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
86out:
87 kfree(opts);
88out2:
89 return ERR_PTR(err);
90}
91
92
93static 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
106static int squashfs_xz_uncompress(struct squashfs_sb_info *msblk, void **buffer, 131static 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
164release_mutex: 172 return total + stream->buf.out_pos;
165 mutex_unlock(&msblk->read_data_mutex);
166 173
174out:
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
173const struct squashfs_decompressor squashfs_xz_comp_ops = { 181const 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
36static void *zlib_init(struct squashfs_sb_info *dummy, void *buff, int len) 36static 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
64static int zlib_uncompress(struct squashfs_sb_info *msblk, void **buffer, 64static 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
132release_mutex: 112 return stream->total_out;
133 mutex_unlock(&msblk->read_data_mutex);
134 113
114out:
135 for (; k < b; k++) 115 for (; k < b; k++)
136 put_bh(bh[k]); 116 put_bh(bh[k]);
137 117