[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH] squash4: fix handling of fragments and sparse files
From: |
Andrei Borzenkov |
Subject: |
[PATCH] squash4: fix handling of fragments and sparse files |
Date: |
Sat, 18 Feb 2017 11:16:43 +0300 |
1. Do not assume block list and fragment are mutually exclusive. Squash
can pack file tail as fragment (unless -no-fragments is specified); so
check read offset and read either from block list or from fragments as
appropriate.
2. Support sparse files with zero blocks.
3. Fix fragment read - frag.offset is absolute fragment position,
not offset relative to ino.chunk.
Reported and tested by Carlo Caione <address@hidden>
---
@Vladimir: we need regression tests for both of these cases. We could real small
files only by accident - block list was zero, so it appeared to work.
@Carlo, please test. I'm surprised it worked for you even without fragments as
your file is sparse and grub immediately choked on the first zero block.
grub-core/fs/squash4.c | 55 +++++++++++++++++++++++++++++++++-----------------
1 file changed, 36 insertions(+), 19 deletions(-)
diff --git a/grub-core/fs/squash4.c b/grub-core/fs/squash4.c
index b97b344..deee71a 100644
--- a/grub-core/fs/squash4.c
+++ b/grub-core/fs/squash4.c
@@ -823,7 +823,12 @@ direct_read (struct grub_squash_data *data,
curread = data->blksz - boff;
if (curread > len)
curread = len;
- if (!(ino->block_sizes[i]
+ if (!ino->block_sizes[i])
+ {
+ /* Sparse block */
+ grub_memset (buf, '\0', curread);
+ }
+ else if (!(ino->block_sizes[i]
& grub_cpu_to_le32_compile_time (SQUASH_BLOCK_UNCOMPRESSED)))
{
char *block;
@@ -873,36 +878,57 @@ direct_read (struct grub_squash_data *data,
static grub_ssize_t
-grub_squash_read_data (struct grub_squash_data *data,
- struct grub_squash_cache_inode *ino,
- grub_off_t off, char *buf, grub_size_t len)
+grub_squash_read (grub_file_t file, char *buf, grub_size_t len)
{
+ struct grub_squash_data *data = file->data;
+ struct grub_squash_cache_inode *ino = &data->ino;
+ grub_off_t off = file->offset;
grub_err_t err;
grub_uint64_t a = 0, b;
grub_uint32_t fragment = 0;
int compressed = 0;
struct grub_squash_frag_desc frag;
+ grub_off_t blk_len;
+ grub_uint64_t mask = grub_le_to_cpu32 (data->sb.block_size) - 1;
+ grub_size_t orig_len = len;
switch (ino->ino.type)
{
case grub_cpu_to_le16_compile_time (SQUASH_TYPE_LONG_REGULAR):
- a = grub_le_to_cpu64 (ino->ino.long_file.chunk);
fragment = grub_le_to_cpu32 (ino->ino.long_file.fragment);
break;
case grub_cpu_to_le16_compile_time (SQUASH_TYPE_REGULAR):
- a = grub_le_to_cpu32 (ino->ino.file.chunk);
fragment = grub_le_to_cpu32 (ino->ino.file.fragment);
break;
}
- if (fragment == 0xffffffff)
- return direct_read (data, ino, off, buf, len);
+ /* Squash may pack file tail as fragment. So read initial part directly and
+ get tail from fragments */
+ blk_len = fragment == 0xffffffff ? file->size : file->size & ~mask;
+ if (off < blk_len)
+ {
+ grub_size_t read_len = blk_len - off;
+ grub_ssize_t res;
+
+ if (read_len > len)
+ read_len = len;
+ res = direct_read (data, ino, off, buf, read_len);
+ if ((grub_size_t) res != read_len)
+ return -1; /* FIXME: is short read possible here? */
+ len -= read_len;
+ if (!len)
+ return read_len;
+ buf += read_len;
+ off = 0;
+ }
+ else
+ off -= blk_len;
err = read_chunk (data, &frag, sizeof (frag),
data->fragments, sizeof (frag) * fragment);
if (err)
return -1;
- a += grub_le_to_cpu64 (frag.offset);
+ a = grub_le_to_cpu64 (frag.offset);
compressed = !(frag.size & grub_cpu_to_le32_compile_time
(SQUASH_BLOCK_UNCOMPRESSED));
if (ino->ino.type == grub_cpu_to_le16_compile_time
(SQUASH_TYPE_LONG_REGULAR))
b = grub_le_to_cpu32 (ino->ino.long_file.offset) + off;
@@ -943,16 +969,7 @@ grub_squash_read_data (struct grub_squash_data *data,
if (err)
return -1;
}
- return len;
-}
-
-static grub_ssize_t
-grub_squash_read (grub_file_t file, char *buf, grub_size_t len)
-{
- struct grub_squash_data *data = file->data;
-
- return grub_squash_read_data (data, &data->ino,
- file->offset, buf, len);
+ return orig_len;
}
static grub_err_t
--
tg: (2fb8cd2..) u/squash-tail-fragment (depends on: master)
- Re: Problem with ISO9660 and files stored on multiple extents, (continued)
- Re: Problem with ISO9660 and files stored on multiple extents, Carlo Caione, 2017/02/16
- Re: Problem with ISO9660 and files stored on multiple extents, Vladimir 'phcoder' Serbinenko, 2017/02/16
- Re: Problem with ISO9660 and files stored on multiple extents, Carlo Caione, 2017/02/16
- Re: Problem with ISO9660 and files stored on multiple extents, Vladimir 'phcoder' Serbinenko, 2017/02/16
- Re: Problem with ISO9660 and files stored on multiple extents, Carlo Caione, 2017/02/16
- Re: Problem with ISO9660 and files stored on multiple extents, Vladimir 'phcoder' Serbinenko, 2017/02/16
- Re: Problem with ISO9660 and files stored on multiple extents, Andrei Borzenkov, 2017/02/16
- Re: Problem with ISO9660 and files stored on multiple extents, Carlo Caione, 2017/02/16
- Re: Problem with ISO9660 and files stored on multiple extents, Andrei Borzenkov, 2017/02/17
- Re: Problem with ISO9660 and files stored on multiple extents, Andrei Borzenkov, 2017/02/17
- [PATCH] squash4: fix handling of fragments and sparse files,
Andrei Borzenkov <=
- Re: [PATCH] squash4: fix handling of fragments and sparse files, Carlo Caione, 2017/02/19
- Re: [PATCH] squash4: fix handling of fragments and sparse files, Vladimir 'phcoder' Serbinenko, 2017/02/23
- Re: [PATCH] squash4: fix handling of fragments and sparse files, Andrei Borzenkov, 2017/02/24