blob: 7077476171480ff6b0c8ec065c7bbfe78823c493 [file] [log] [blame]
Phillip Loughere2780ab2009-01-05 08:46:27 +00001/*
2 * Squashfs - a compressed read only filesystem for Linux
3 *
4 * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
Phillip Lougherd7f2ff62011-05-26 10:39:56 +01005 * Phillip Lougher <phillip@squashfs.org.uk>
Phillip Loughere2780ab2009-01-05 08:46:27 +00006 *
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 * block.c
22 */
23
24/*
25 * This file implements the low-level routines to read and decompress
26 * datablocks and metadata blocks.
27 */
28
29#include <linux/fs.h>
30#include <linux/vfs.h>
Adrien Schildknecht6c8928f2016-10-17 18:22:32 -070031#include <linux/bio.h>
Phillip Loughere2780ab2009-01-05 08:46:27 +000032#include <linux/slab.h>
Phillip Loughere2780ab2009-01-05 08:46:27 +000033#include <linux/string.h>
Adrien Schildknecht6c8928f2016-10-17 18:22:32 -070034#include <linux/pagemap.h>
Phillip Loughere2780ab2009-01-05 08:46:27 +000035#include <linux/buffer_head.h>
Adrien Schildknecht6c8928f2016-10-17 18:22:32 -070036#include <linux/workqueue.h>
Phillip Loughere2780ab2009-01-05 08:46:27 +000037
38#include "squashfs_fs.h"
39#include "squashfs_fs_sb.h"
Phillip Loughere2780ab2009-01-05 08:46:27 +000040#include "squashfs.h"
Phillip Lougher4c0f0bb2009-10-06 04:04:15 +010041#include "decompressor.h"
Phillip Lougher846b7302013-11-18 02:59:12 +000042#include "page_actor.h"
Phillip Loughere2780ab2009-01-05 08:46:27 +000043
Adrien Schildknecht6c8928f2016-10-17 18:22:32 -070044static struct workqueue_struct *squashfs_read_wq;
45
46struct squashfs_read_request {
47 struct super_block *sb;
48 u64 index;
49 int length;
50 int compressed;
51 int offset;
52 u64 read_end;
53 struct squashfs_page_actor *output;
54 enum {
55 SQUASHFS_COPY,
56 SQUASHFS_DECOMPRESS,
57 SQUASHFS_METADATA,
58 } data_processing;
59 bool synchronous;
60
61 /*
62 * If the read is synchronous, it is possible to retrieve information
63 * about the request by setting these pointers.
64 */
65 int *res;
66 int *bytes_read;
67 int *bytes_uncompressed;
68
69 int nr_buffers;
70 struct buffer_head **bh;
71 struct work_struct offload;
72};
73
74struct squashfs_bio_request {
75 struct buffer_head **bh;
76 int nr_buffers;
77};
78
79static int squashfs_bio_submit(struct squashfs_read_request *req);
80
81int squashfs_init_read_wq(void)
Phillip Loughere2780ab2009-01-05 08:46:27 +000082{
Adrien Schildknecht6c8928f2016-10-17 18:22:32 -070083 squashfs_read_wq = create_workqueue("SquashFS read wq");
84 return !!squashfs_read_wq;
85}
Phillip Loughere2780ab2009-01-05 08:46:27 +000086
Adrien Schildknecht6c8928f2016-10-17 18:22:32 -070087void squashfs_destroy_read_wq(void)
88{
89 flush_workqueue(squashfs_read_wq);
90 destroy_workqueue(squashfs_read_wq);
91}
Phillip Loughere2780ab2009-01-05 08:46:27 +000092
Adrien Schildknecht6c8928f2016-10-17 18:22:32 -070093static void free_read_request(struct squashfs_read_request *req, int error)
94{
95 if (!req->synchronous)
96 squashfs_page_actor_free(req->output, error);
97 if (req->res)
98 *(req->res) = error;
99 kfree(req->bh);
100 kfree(req);
101}
Phillip Lougher36894562011-01-25 15:07:34 -0800102
Adrien Schildknecht6c8928f2016-10-17 18:22:32 -0700103static void squashfs_process_blocks(struct squashfs_read_request *req)
104{
105 int error = 0;
106 int bytes, i, length;
107 struct squashfs_sb_info *msblk = req->sb->s_fs_info;
108 struct squashfs_page_actor *actor = req->output;
109 struct buffer_head **bh = req->bh;
110 int nr_buffers = req->nr_buffers;
111
112 for (i = 0; i < nr_buffers; ++i) {
113 if (!bh[i])
114 continue;
115 wait_on_buffer(bh[i]);
116 if (!buffer_uptodate(bh[i]))
117 error = -EIO;
118 }
119 if (error)
120 goto cleanup;
121
122 if (req->data_processing == SQUASHFS_METADATA) {
123 /* Extract the length of the metadata block */
124 if (req->offset != msblk->devblksize - 1) {
125 length = le16_to_cpup((__le16 *)
126 (bh[0]->b_data + req->offset));
127 } else {
128 length = (unsigned char)bh[0]->b_data[req->offset];
129 length |= (unsigned char)bh[1]->b_data[0] << 8;
130 }
131 req->compressed = SQUASHFS_COMPRESSED(length);
132 req->data_processing = req->compressed ? SQUASHFS_DECOMPRESS
133 : SQUASHFS_COPY;
134 length = SQUASHFS_COMPRESSED_SIZE(length);
135 if (req->index + length + 2 > req->read_end) {
136 for (i = 0; i < nr_buffers; ++i)
137 put_bh(bh[i]);
138 kfree(bh);
139 req->length = length;
140 req->index += 2;
141 squashfs_bio_submit(req);
142 return;
143 }
144 req->length = length;
145 req->offset = (req->offset + 2) % PAGE_SIZE;
146 if (req->offset < 2) {
147 put_bh(bh[0]);
148 ++bh;
149 --nr_buffers;
150 }
151 }
152 if (req->bytes_read)
153 *(req->bytes_read) = req->length;
154
155 if (req->data_processing == SQUASHFS_COPY) {
156 squashfs_bh_to_actor(bh, nr_buffers, req->output, req->offset,
157 req->length, msblk->devblksize);
158 } else if (req->data_processing == SQUASHFS_DECOMPRESS) {
159 req->length = squashfs_decompress(msblk, bh, nr_buffers,
160 req->offset, req->length, actor);
161 if (req->length < 0) {
162 error = -EIO;
163 goto cleanup;
Phillip Lougher36894562011-01-25 15:07:34 -0800164 }
Phillip Loughere2780ab2009-01-05 08:46:27 +0000165 }
166
Adrien Schildknecht6c8928f2016-10-17 18:22:32 -0700167 /* Last page may have trailing bytes not filled */
168 bytes = req->length % PAGE_SIZE;
169 if (bytes && actor->page[actor->pages - 1])
170 zero_user_segment(actor->page[actor->pages - 1], bytes,
171 PAGE_SIZE);
172
173cleanup:
174 if (req->bytes_uncompressed)
175 *(req->bytes_uncompressed) = req->length;
176 if (error) {
177 for (i = 0; i < nr_buffers; ++i)
178 if (bh[i])
179 put_bh(bh[i]);
180 }
181 free_read_request(req, error);
Phillip Loughere2780ab2009-01-05 08:46:27 +0000182}
183
Adrien Schildknecht6c8928f2016-10-17 18:22:32 -0700184static void read_wq_handler(struct work_struct *work)
185{
186 squashfs_process_blocks(container_of(work,
187 struct squashfs_read_request, offload));
188}
189
190static void squashfs_bio_end_io(struct bio *bio)
191{
192 int i;
193 int error = bio->bi_error;
194 struct squashfs_bio_request *bio_req = bio->bi_private;
195
196 bio_put(bio);
197
198 for (i = 0; i < bio_req->nr_buffers; ++i) {
199 if (!bio_req->bh[i])
200 continue;
201 if (!error)
202 set_buffer_uptodate(bio_req->bh[i]);
203 else
204 clear_buffer_uptodate(bio_req->bh[i]);
205 unlock_buffer(bio_req->bh[i]);
206 }
207 kfree(bio_req);
208}
209
Adrien Schildknecht60cc09a2016-09-29 15:25:30 -0700210static int bh_is_optional(struct squashfs_read_request *req, int idx)
211{
212 int start_idx, end_idx;
213 struct squashfs_sb_info *msblk = req->sb->s_fs_info;
214
215 start_idx = (idx * msblk->devblksize - req->offset) >> PAGE_SHIFT;
216 end_idx = ((idx + 1) * msblk->devblksize - req->offset + 1) >> PAGE_SHIFT;
217 if (start_idx >= req->output->pages)
218 return 1;
219 if (start_idx < 0)
220 start_idx = end_idx;
221 if (end_idx >= req->output->pages)
222 end_idx = start_idx;
223 return !req->output->page[start_idx] && !req->output->page[end_idx];
224}
225
Adrien Schildknecht6c8928f2016-10-17 18:22:32 -0700226static int actor_getblks(struct squashfs_read_request *req, u64 block)
227{
228 int i;
229
230 req->bh = kmalloc_array(req->nr_buffers, sizeof(*(req->bh)), GFP_NOIO);
231 if (!req->bh)
232 return -ENOMEM;
233
234 for (i = 0; i < req->nr_buffers; ++i) {
Adrien Schildknecht60cc09a2016-09-29 15:25:30 -0700235 /*
236 * When dealing with an uncompressed block, the actor may
237 * contains NULL pages. There's no need to read the buffers
238 * associated with these pages.
239 */
240 if (!req->compressed && bh_is_optional(req, i)) {
241 req->bh[i] = NULL;
242 continue;
243 }
Adrien Schildknecht6c8928f2016-10-17 18:22:32 -0700244 req->bh[i] = sb_getblk(req->sb, block + i);
245 if (!req->bh[i]) {
246 while (--i) {
247 if (req->bh[i])
248 put_bh(req->bh[i]);
249 }
250 return -1;
251 }
252 }
253 return 0;
254}
255
256static int squashfs_bio_submit(struct squashfs_read_request *req)
257{
258 struct bio *bio = NULL;
259 struct buffer_head *bh;
260 struct squashfs_bio_request *bio_req = NULL;
261 int b = 0, prev_block = 0;
262 struct squashfs_sb_info *msblk = req->sb->s_fs_info;
263
264 u64 read_start = round_down(req->index, msblk->devblksize);
265 u64 read_end = round_up(req->index + req->length, msblk->devblksize);
266 sector_t block = read_start >> msblk->devblksize_log2;
267 sector_t block_end = read_end >> msblk->devblksize_log2;
268 int offset = read_start - round_down(req->index, PAGE_SIZE);
269 int nr_buffers = block_end - block;
270 int blksz = msblk->devblksize;
271 int bio_max_pages = nr_buffers > BIO_MAX_PAGES ? BIO_MAX_PAGES
272 : nr_buffers;
273
274 /* Setup the request */
275 req->read_end = read_end;
276 req->offset = req->index - read_start;
277 req->nr_buffers = nr_buffers;
278 if (actor_getblks(req, block) < 0)
279 goto getblk_failed;
280
281 /* Create and submit the BIOs */
282 for (b = 0; b < nr_buffers; ++b, offset += blksz) {
283 bh = req->bh[b];
284 if (!bh || !trylock_buffer(bh))
285 continue;
286 if (buffer_uptodate(bh)) {
287 unlock_buffer(bh);
288 continue;
289 }
290 offset %= PAGE_SIZE;
291
292 /* Append the buffer to the current BIO if it is contiguous */
293 if (bio && bio_req && prev_block + 1 == b) {
294 if (bio_add_page(bio, bh->b_page, blksz, offset)) {
295 bio_req->nr_buffers += 1;
296 prev_block = b;
297 continue;
298 }
299 }
300
301 /* Otherwise, submit the current BIO and create a new one */
302 if (bio)
303 submit_bio(bio);
304 bio_req = kcalloc(1, sizeof(struct squashfs_bio_request),
305 GFP_NOIO);
306 if (!bio_req)
307 goto req_alloc_failed;
308 bio_req->bh = &req->bh[b];
309 bio = bio_alloc(GFP_NOIO, bio_max_pages);
310 if (!bio)
311 goto bio_alloc_failed;
312 bio->bi_bdev = req->sb->s_bdev;
313 bio->bi_iter.bi_sector = (block + b)
314 << (msblk->devblksize_log2 - 9);
315 bio_set_op_attrs(bio, REQ_OP_READ, 0);
316 bio->bi_private = bio_req;
317 bio->bi_end_io = squashfs_bio_end_io;
318
319 bio_add_page(bio, bh->b_page, blksz, offset);
320 bio_req->nr_buffers += 1;
321 prev_block = b;
322 }
323 if (bio)
324 submit_bio(bio);
325
326 if (req->synchronous)
327 squashfs_process_blocks(req);
328 else {
329 INIT_WORK(&req->offload, read_wq_handler);
330 schedule_work(&req->offload);
331 }
332 return 0;
333
334bio_alloc_failed:
335 kfree(bio_req);
336req_alloc_failed:
337 unlock_buffer(bh);
338 while (--nr_buffers >= b)
339 if (req->bh[nr_buffers])
340 put_bh(req->bh[nr_buffers]);
341 while (--b >= 0)
342 if (req->bh[b])
343 wait_on_buffer(req->bh[b]);
344getblk_failed:
345 free_read_request(req, -ENOMEM);
346 return -ENOMEM;
347}
348
349static int read_metadata_block(struct squashfs_read_request *req,
350 u64 *next_index)
351{
352 int ret, error, bytes_read = 0, bytes_uncompressed = 0;
353 struct squashfs_sb_info *msblk = req->sb->s_fs_info;
354
355 if (req->index + 2 > msblk->bytes_used) {
356 free_read_request(req, -EINVAL);
357 return -EINVAL;
358 }
359 req->length = 2;
360
361 /* Do not read beyond the end of the device */
362 if (req->index + req->length > msblk->bytes_used)
363 req->length = msblk->bytes_used - req->index;
364 req->data_processing = SQUASHFS_METADATA;
365
366 /*
367 * Reading metadata is always synchronous because we don't know the
368 * length in advance and the function is expected to update
369 * 'next_index' and return the length.
370 */
371 req->synchronous = true;
372 req->res = &error;
373 req->bytes_read = &bytes_read;
374 req->bytes_uncompressed = &bytes_uncompressed;
375
376 TRACE("Metadata block @ 0x%llx, %scompressed size %d, src size %d\n",
377 req->index, req->compressed ? "" : "un", bytes_read,
378 req->output->length);
379
380 ret = squashfs_bio_submit(req);
381 if (ret)
382 return ret;
383 if (error)
384 return error;
385 if (next_index)
386 *next_index += 2 + bytes_read;
387 return bytes_uncompressed;
388}
389
390static int read_data_block(struct squashfs_read_request *req, int length,
391 u64 *next_index, bool synchronous)
392{
393 int ret, error = 0, bytes_uncompressed = 0, bytes_read = 0;
394
395 req->compressed = SQUASHFS_COMPRESSED_BLOCK(length);
396 req->length = length = SQUASHFS_COMPRESSED_SIZE_BLOCK(length);
397 req->data_processing = req->compressed ? SQUASHFS_DECOMPRESS
398 : SQUASHFS_COPY;
399
400 req->synchronous = synchronous;
401 if (synchronous) {
402 req->res = &error;
403 req->bytes_read = &bytes_read;
404 req->bytes_uncompressed = &bytes_uncompressed;
405 }
406
407 TRACE("Data block @ 0x%llx, %scompressed size %d, src size %d\n",
408 req->index, req->compressed ? "" : "un", req->length,
409 req->output->length);
410
411 ret = squashfs_bio_submit(req);
412 if (ret)
413 return ret;
414 if (synchronous)
415 ret = error ? error : bytes_uncompressed;
416 if (next_index)
417 *next_index += length;
418 return ret;
419}
Phillip Loughere2780ab2009-01-05 08:46:27 +0000420
421/*
422 * Read and decompress a metadata block or datablock. Length is non-zero
423 * if a datablock is being read (the size is stored elsewhere in the
424 * filesystem), otherwise the length is obtained from the first two bytes of
425 * the metadata block. A bit in the length field indicates if the block
426 * is stored uncompressed in the filesystem (usually because compression
Phillip Lougherec9267b2012-03-06 01:18:49 +0000427 * generated a larger block - this does occasionally happen with compression
428 * algorithms).
Phillip Loughere2780ab2009-01-05 08:46:27 +0000429 */
Adrien Schildknecht6c8928f2016-10-17 18:22:32 -0700430static int __squashfs_read_data(struct super_block *sb, u64 index, int length,
431 u64 *next_index, struct squashfs_page_actor *output, bool sync)
Phillip Loughere2780ab2009-01-05 08:46:27 +0000432{
Adrien Schildknecht6c8928f2016-10-17 18:22:32 -0700433 struct squashfs_read_request *req;
Phillip Loughere2780ab2009-01-05 08:46:27 +0000434
Adrien Schildknecht6c8928f2016-10-17 18:22:32 -0700435 req = kcalloc(1, sizeof(struct squashfs_read_request), GFP_KERNEL);
436 if (!req) {
437 if (!sync)
438 squashfs_page_actor_free(output, -ENOMEM);
Phillip Loughere2780ab2009-01-05 08:46:27 +0000439 return -ENOMEM;
Phillip Loughere2780ab2009-01-05 08:46:27 +0000440 }
441
Adrien Schildknecht6c8928f2016-10-17 18:22:32 -0700442 req->sb = sb;
443 req->index = index;
444 req->output = output;
445
446 if (next_index)
447 *next_index = index;
448
449 if (length)
450 length = read_data_block(req, length, next_index, sync);
451 else
452 length = read_metadata_block(req, next_index);
453
454 if (length < 0) {
455 ERROR("squashfs_read_data failed to read block 0x%llx\n",
456 (unsigned long long)index);
457 return -EIO;
Phillip Lougher9508c6b2013-11-13 02:56:26 +0000458 }
459
Phillip Loughere2780ab2009-01-05 08:46:27 +0000460 return length;
Adrien Schildknecht6c8928f2016-10-17 18:22:32 -0700461}
Phillip Loughere2780ab2009-01-05 08:46:27 +0000462
Adrien Schildknecht6c8928f2016-10-17 18:22:32 -0700463int squashfs_read_data(struct super_block *sb, u64 index, int length,
464 u64 *next_index, struct squashfs_page_actor *output)
465{
466 return __squashfs_read_data(sb, index, length, next_index, output,
467 true);
468}
Phillip Loughere2780ab2009-01-05 08:46:27 +0000469
Adrien Schildknecht6c8928f2016-10-17 18:22:32 -0700470int squashfs_read_data_async(struct super_block *sb, u64 index, int length,
471 u64 *next_index, struct squashfs_page_actor *output)
472{
473
474 return __squashfs_read_data(sb, index, length, next_index, output,
475 false);
Phillip Loughere2780ab2009-01-05 08:46:27 +0000476}