diff options
Diffstat (limited to 'fs/squashfs/block.c')
-rw-r--r-- | fs/squashfs/block.c | 81 |
1 files changed, 7 insertions, 74 deletions
diff --git a/fs/squashfs/block.c b/fs/squashfs/block.c index 2a7960310349..653c030eb840 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 |
@@ -88,9 +87,8 @@ int squashfs_read_data(struct super_block *sb, void **buffer, u64 index, | |||
88 | u64 cur_index = index >> msblk->devblksize_log2; | 87 | u64 cur_index = index >> msblk->devblksize_log2; |
89 | int bytes, compressed, b = 0, k = 0, page = 0, avail; | 88 | int bytes, compressed, b = 0, k = 0, page = 0, avail; |
90 | 89 | ||
91 | 90 | bh = kcalloc(((srclength + msblk->devblksize - 1) | |
92 | bh = kcalloc((msblk->block_size >> msblk->devblksize_log2) + 1, | 91 | >> msblk->devblksize_log2) + 1, sizeof(*bh), GFP_KERNEL); |
93 | sizeof(*bh), GFP_KERNEL); | ||
94 | if (bh == NULL) | 92 | if (bh == NULL) |
95 | return -ENOMEM; | 93 | return -ENOMEM; |
96 | 94 | ||
@@ -153,72 +151,10 @@ int squashfs_read_data(struct super_block *sb, void **buffer, u64 index, | |||
153 | } | 151 | } |
154 | 152 | ||
155 | if (compressed) { | 153 | if (compressed) { |
156 | int zlib_err = 0, zlib_init = 0; | 154 | length = squashfs_decompress(msblk, buffer, bh, b, offset, |
157 | 155 | length, srclength, pages); | |
158 | /* | 156 | if (length < 0) |
159 | * Uncompress block. | 157 | 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 { | 158 | } else { |
223 | /* | 159 | /* |
224 | * Block is uncompressed. | 160 | * Block is uncompressed. |
@@ -255,9 +191,6 @@ int squashfs_read_data(struct super_block *sb, void **buffer, u64 index, | |||
255 | kfree(bh); | 191 | kfree(bh); |
256 | return length; | 192 | return length; |
257 | 193 | ||
258 | release_mutex: | ||
259 | mutex_unlock(&msblk->read_data_mutex); | ||
260 | |||
261 | block_release: | 194 | block_release: |
262 | for (; k < b; k++) | 195 | for (; k < b; k++) |
263 | put_bh(bh[k]); | 196 | put_bh(bh[k]); |