Add support for LZO compression in btrfs.
* Makefile.util.def (libgrubmods.a): Add minilzo.c and add required flags to cflags in cppflags. * Makefile.core.def (btrfs): Likewise. * grub-core/fs/btrfs.c: Include minilzo.h. (grub_btrfs_superblock): Add sectorsize, nodesize, leafsize, stripsize and dummy5 field. (GRUB_BTRFS_COMPRESSION_LZO): New define. (grub_btrfs_extent_read): Add support for LZO compression type.
This commit is contained in:
parent
b6085f3236
commit
095f077e6d
4 changed files with 143 additions and 12 deletions
|
@ -1,3 +1,16 @@
|
|||
2011-08-14 Szymon Janc <szymon@janc.net.pl>
|
||||
|
||||
Add support for LZO compression in btrfs.
|
||||
|
||||
* Makefile.util.def (libgrubmods.a): Add minilzo.c and add required flags
|
||||
to cflags in cppflags.
|
||||
* Makefile.core.def (btrfs): Likewise.
|
||||
* grub-core/fs/btrfs.c: Include minilzo.h.
|
||||
(grub_btrfs_superblock): Add sectorsize, nodesize, leafsize, stripsize and
|
||||
dummy5 field.
|
||||
(GRUB_BTRFS_COMPRESSION_LZO): New define.
|
||||
(grub_btrfs_extent_read): Add support for LZO compression type.
|
||||
|
||||
2011-08-14 Szymon Janc <szymon@janc.net.pl>
|
||||
|
||||
* grub-core/fs/btrfs.c: Some code style fixes.
|
||||
|
|
|
@ -33,6 +33,8 @@ library = {
|
|||
|
||||
library = {
|
||||
name = libgrubmods.a;
|
||||
cflags = '$(CFLAGS_POSIX) -Wno-undef';
|
||||
cppflags = '-I$(srcdir)/lib/posix_wrap -I$(top_srcdir)/grub-core/lib/minilzo -DMINILZO_HAVE_CONFIG_H';
|
||||
|
||||
common_nodist = grub_script.tab.c;
|
||||
common_nodist = grub_script.yy.c;
|
||||
|
@ -107,6 +109,7 @@ library = {
|
|||
common = grub-core/script/argv.c;
|
||||
common = grub-core/io/gzio.c;
|
||||
common = grub-core/kern/ia64/dl_helper.c;
|
||||
common = grub-core/lib/minilzo/minilzo.c;
|
||||
};
|
||||
|
||||
program = {
|
||||
|
|
|
@ -979,6 +979,9 @@ module = {
|
|||
name = btrfs;
|
||||
common = fs/btrfs.c;
|
||||
common = lib/crc.c;
|
||||
common = lib/minilzo/minilzo.c;
|
||||
cflags = '$(CFLAGS_POSIX) -Wno-undef';
|
||||
cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/minilzo -DMINILZO_HAVE_CONFIG_H';
|
||||
};
|
||||
|
||||
module = {
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <grub/types.h>
|
||||
#include <grub/lib/crc.h>
|
||||
#include <grub/deflate.h>
|
||||
#include "minilzo.h"
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
|
@ -51,10 +52,15 @@ struct grub_btrfs_superblock
|
|||
grub_uint64_t chunk_tree;
|
||||
grub_uint8_t dummy2[0x20];
|
||||
grub_uint64_t root_dir_objectid;
|
||||
grub_uint8_t dummy3[0x41];
|
||||
grub_uint8_t dummy3[0x8];
|
||||
grub_uint32_t sectorsize;
|
||||
grub_uint32_t nodesize;
|
||||
grub_uint32_t leafsize;
|
||||
grub_uint32_t stripsize;
|
||||
grub_uint8_t dummy4[0x29];
|
||||
struct grub_btrfs_device this_device;
|
||||
char label[0x100];
|
||||
grub_uint8_t dummy4[0x100];
|
||||
grub_uint8_t dummy5[0x100];
|
||||
grub_uint8_t bootstrap_mapping[0x800];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
@ -216,6 +222,7 @@ struct grub_btrfs_extent_data
|
|||
|
||||
#define GRUB_BTRFS_COMPRESSION_NONE 0
|
||||
#define GRUB_BTRFS_COMPRESSION_ZLIB 1
|
||||
#define GRUB_BTRFS_COMPRESSION_LZO 2
|
||||
|
||||
#define GRUB_BTRFS_OBJECT_ID_CHUNK 0x100
|
||||
|
||||
|
@ -954,7 +961,8 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data,
|
|||
}
|
||||
|
||||
if (data->extent->compression != GRUB_BTRFS_COMPRESSION_NONE
|
||||
&& data->extent->compression != GRUB_BTRFS_COMPRESSION_ZLIB)
|
||||
&& data->extent->compression != GRUB_BTRFS_COMPRESSION_ZLIB
|
||||
&& data->extent->compression != GRUB_BTRFS_COMPRESSION_LZO)
|
||||
{
|
||||
grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||
"compression type 0x%x not supported",
|
||||
|
@ -980,6 +988,42 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data,
|
|||
!= (grub_ssize_t) csize)
|
||||
return -1;
|
||||
}
|
||||
else if (data->extent->compression == GRUB_BTRFS_COMPRESSION_LZO)
|
||||
{
|
||||
grub_uint32_t total_size, chunk_size;
|
||||
unsigned char *obuf;
|
||||
unsigned char *ibuf = (unsigned char *) data->extent->inl;
|
||||
lzo_uint ocnt = extoff + csize;
|
||||
int ret;
|
||||
|
||||
obuf = grub_malloc (extoff + csize);
|
||||
if (!obuf)
|
||||
return -1;
|
||||
|
||||
total_size = grub_le_to_cpu32 (grub_get_unaligned32 (ibuf));
|
||||
ibuf += sizeof (total_size);
|
||||
|
||||
chunk_size = grub_le_to_cpu32 (grub_get_unaligned32 (ibuf));
|
||||
ibuf += sizeof (chunk_size);
|
||||
|
||||
/* Can we have multiple chunks in inline extent? */
|
||||
if (chunk_size + (sizeof (grub_uint32_t) * 2) != total_size)
|
||||
{
|
||||
grub_free (obuf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = lzo1x_decompress_safe (ibuf, chunk_size, obuf, &ocnt, NULL);
|
||||
|
||||
if (ret != LZO_E_OK)
|
||||
{
|
||||
grub_free (obuf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
grub_memcpy (buf, obuf + extoff, ocnt - extoff);
|
||||
grub_free (obuf);
|
||||
}
|
||||
else
|
||||
grub_memcpy (buf, data->extent->inl + extoff, csize);
|
||||
break;
|
||||
|
@ -989,9 +1033,10 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data,
|
|||
grub_memset (buf, 0, csize);
|
||||
break;
|
||||
}
|
||||
if (data->extent->compression == GRUB_BTRFS_COMPRESSION_ZLIB)
|
||||
|
||||
if (data->extent->compression != GRUB_BTRFS_COMPRESSION_NONE)
|
||||
{
|
||||
char *tmp;
|
||||
void *tmp;
|
||||
grub_uint64_t zsize;
|
||||
zsize = grub_le_to_cpu64 (data->extent->compressed_size);
|
||||
tmp = grub_malloc (zsize);
|
||||
|
@ -1005,16 +1050,83 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data,
|
|||
grub_free (tmp);
|
||||
return -1;
|
||||
}
|
||||
if (grub_zlib_decompress (tmp, zsize, extoff +
|
||||
grub_le_to_cpu64 (data->extent->offset),
|
||||
buf, csize) != (grub_ssize_t) csize)
|
||||
|
||||
if (data->extent->compression == GRUB_BTRFS_COMPRESSION_ZLIB)
|
||||
{
|
||||
grub_ssize_t ret;
|
||||
|
||||
ret = grub_zlib_decompress (tmp, zsize, extoff
|
||||
+ grub_le_to_cpu64 (data->extent->offset),
|
||||
buf, csize);
|
||||
|
||||
grub_free (tmp);
|
||||
|
||||
if (ret != (grub_ssize_t) csize)
|
||||
return -1;
|
||||
|
||||
break;
|
||||
}
|
||||
else if (data->extent->compression == GRUB_BTRFS_COMPRESSION_LZO)
|
||||
{
|
||||
grub_uint32_t total_size, chunk_size, usize = 0;
|
||||
grub_size_t off = extoff;
|
||||
unsigned char *chunk, *ibuf = tmp;
|
||||
char *obuf = buf;
|
||||
/* XXX Is this correct size from sblock? */
|
||||
grub_uint32_t udata_size = grub_le_to_cpu32 (data->sblock.sectorsize);
|
||||
|
||||
chunk = grub_malloc (udata_size);
|
||||
if (!chunk)
|
||||
{
|
||||
grub_free (tmp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* XXX Use this for some sanity checks while decompressing. */
|
||||
total_size = grub_le_to_cpu32 (grub_get_unaligned32 (ibuf));
|
||||
ibuf += sizeof (total_size);
|
||||
|
||||
chunk_size = grub_le_to_cpu32 (grub_get_unaligned32 (ibuf));
|
||||
ibuf += sizeof (chunk_size);
|
||||
|
||||
/* Jump to first chunk with requested data. */
|
||||
while (off >= udata_size)
|
||||
{
|
||||
chunk_size = grub_le_to_cpu32 (grub_get_unaligned32 (ibuf));
|
||||
ibuf += sizeof (chunk_size);
|
||||
ibuf += chunk_size;
|
||||
off -= udata_size;
|
||||
}
|
||||
|
||||
while (usize < csize)
|
||||
{
|
||||
chunk_size = grub_le_to_cpu32 (grub_get_unaligned32 (ibuf));
|
||||
lzo_uint csize2 = udata_size;
|
||||
int diff;
|
||||
|
||||
ibuf += sizeof (chunk_size);
|
||||
|
||||
if (lzo1x_decompress_safe (ibuf, chunk_size, chunk, &csize2, NULL) != LZO_E_OK)
|
||||
{
|
||||
grub_free (tmp);
|
||||
grub_free (chunk);
|
||||
return -1;
|
||||
}
|
||||
|
||||
diff = grub_min (csize2 - off, csize - usize);
|
||||
|
||||
grub_memcpy (obuf, chunk + off, diff);
|
||||
obuf += diff;
|
||||
ibuf += chunk_size;
|
||||
usize += diff;
|
||||
off = 0;
|
||||
}
|
||||
|
||||
grub_free (tmp);
|
||||
grub_free (chunk);
|
||||
break;
|
||||
}
|
||||
}
|
||||
err = grub_btrfs_read_logical (data,
|
||||
grub_le_to_cpu64 (data->extent->laddr)
|
||||
+ grub_le_to_cpu64 (data->extent->offset)
|
||||
|
|
Loading…
Reference in a new issue