|
@@ -36,6 +36,7 @@
|
|
|
#include "squashfs_fs_sb.h"
|
|
|
#include "squashfs.h"
|
|
|
#include "decompressor.h"
|
|
|
+#include "page_actor.h"
|
|
|
|
|
|
/*
|
|
|
* Read the metadata block length, this is stored in the first two
|
|
@@ -86,16 +87,16 @@ static struct buffer_head *get_block_length(struct super_block *sb,
|
|
|
* generated a larger block - this does occasionally happen with compression
|
|
|
* algorithms).
|
|
|
*/
|
|
|
-int squashfs_read_data(struct super_block *sb, void **buffer, u64 index,
|
|
|
- int length, u64 *next_index, int srclength, int pages)
|
|
|
+int squashfs_read_data(struct super_block *sb, u64 index, int length,
|
|
|
+ u64 *next_index, struct squashfs_page_actor *output)
|
|
|
{
|
|
|
struct squashfs_sb_info *msblk = sb->s_fs_info;
|
|
|
struct buffer_head **bh;
|
|
|
int offset = index & ((1 << msblk->devblksize_log2) - 1);
|
|
|
u64 cur_index = index >> msblk->devblksize_log2;
|
|
|
- int bytes, compressed, b = 0, k = 0, page = 0, avail, i;
|
|
|
+ int bytes, compressed, b = 0, k = 0, avail, i;
|
|
|
|
|
|
- bh = kcalloc(((srclength + msblk->devblksize - 1)
|
|
|
+ bh = kcalloc(((output->length + msblk->devblksize - 1)
|
|
|
>> msblk->devblksize_log2) + 1, sizeof(*bh), GFP_KERNEL);
|
|
|
if (bh == NULL)
|
|
|
return -ENOMEM;
|
|
@@ -111,9 +112,9 @@ int squashfs_read_data(struct super_block *sb, void **buffer, u64 index,
|
|
|
*next_index = index + length;
|
|
|
|
|
|
TRACE("Block @ 0x%llx, %scompressed size %d, src size %d\n",
|
|
|
- index, compressed ? "" : "un", length, srclength);
|
|
|
+ index, compressed ? "" : "un", length, output->length);
|
|
|
|
|
|
- if (length < 0 || length > srclength ||
|
|
|
+ if (length < 0 || length > output->length ||
|
|
|
(index + length) > msblk->bytes_used)
|
|
|
goto read_failure;
|
|
|
|
|
@@ -145,7 +146,7 @@ int squashfs_read_data(struct super_block *sb, void **buffer, u64 index,
|
|
|
TRACE("Block @ 0x%llx, %scompressed size %d\n", index,
|
|
|
compressed ? "" : "un", length);
|
|
|
|
|
|
- if (length < 0 || length > srclength ||
|
|
|
+ if (length < 0 || length > output->length ||
|
|
|
(index + length) > msblk->bytes_used)
|
|
|
goto block_release;
|
|
|
|
|
@@ -165,8 +166,8 @@ int squashfs_read_data(struct super_block *sb, void **buffer, u64 index,
|
|
|
}
|
|
|
|
|
|
if (compressed) {
|
|
|
- length = squashfs_decompress(msblk, buffer, bh, b, offset,
|
|
|
- length, srclength, pages);
|
|
|
+ length = squashfs_decompress(msblk, bh, b, offset, length,
|
|
|
+ output);
|
|
|
if (length < 0)
|
|
|
goto read_failure;
|
|
|
} else {
|
|
@@ -174,19 +175,20 @@ int squashfs_read_data(struct super_block *sb, void **buffer, u64 index,
|
|
|
* Block is uncompressed.
|
|
|
*/
|
|
|
int in, pg_offset = 0;
|
|
|
+ void *data = squashfs_first_page(output);
|
|
|
|
|
|
for (bytes = length; k < b; k++) {
|
|
|
in = min(bytes, msblk->devblksize - offset);
|
|
|
bytes -= in;
|
|
|
while (in) {
|
|
|
if (pg_offset == PAGE_CACHE_SIZE) {
|
|
|
- page++;
|
|
|
+ data = squashfs_next_page(output);
|
|
|
pg_offset = 0;
|
|
|
}
|
|
|
avail = min_t(int, in, PAGE_CACHE_SIZE -
|
|
|
pg_offset);
|
|
|
- memcpy(buffer[page] + pg_offset,
|
|
|
- bh[k]->b_data + offset, avail);
|
|
|
+ memcpy(data + pg_offset, bh[k]->b_data + offset,
|
|
|
+ avail);
|
|
|
in -= avail;
|
|
|
pg_offset += avail;
|
|
|
offset += avail;
|
|
@@ -194,6 +196,7 @@ int squashfs_read_data(struct super_block *sb, void **buffer, u64 index,
|
|
|
offset = 0;
|
|
|
put_bh(bh[k]);
|
|
|
}
|
|
|
+ squashfs_finish_page(output);
|
|
|
}
|
|
|
|
|
|
kfree(bh);
|