btrfs: added support for zlib decompression of inline extents.
Reuse code from tarfs to decompress zlib compressed inline extents. No idea yet on how to decompress regular extents which are currently served by the file cache.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Copyright 2011, Jérôme Duval, [email protected].
|
||||
* Copyright 2008, Axel Dörfler, [email protected].
|
||||
* Copyright 2005-2007, Ingo Weinhold, [email protected].
|
||||
* This file may be used under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
@@ -9,6 +10,7 @@
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <zlib.h>
|
||||
|
||||
#include "BPlusTree.h"
|
||||
#include "CachedBlock.h"
|
||||
@@ -197,20 +199,27 @@ Inode::ReadAt(off_t pos, uint8* buffer, size_t* _length)
|
||||
search_key.SetObjectID(fID);
|
||||
search_key.SetOffset(pos + 1);
|
||||
|
||||
size_t item_size;
|
||||
btrfs_extent_data *extent_data;
|
||||
status_t status = fVolume->FSTree()->FindPrevious(search_key,
|
||||
(void**)&extent_data);
|
||||
(void**)&extent_data, &item_size);
|
||||
if (status != B_OK) {
|
||||
ERROR("Inode::FindBlock(): Couldn't find extent_data 0x%lx\n", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
uint8 compression = extent_data->Compression();
|
||||
if (FileCache() != NULL
|
||||
&& extent_data->Type() == BTRFS_EXTENT_DATA_REGULAR) {
|
||||
TRACE("inode %" B_PRIdINO ": ReadAt cache (pos %lld, length %lu)\n",
|
||||
ID(), pos, length);
|
||||
free(extent_data);
|
||||
return file_cache_read(FileCache(), NULL, pos, buffer, _length);
|
||||
if (compression == BTRFS_EXTENT_COMPRESS_NONE)
|
||||
return file_cache_read(FileCache(), NULL, pos, buffer, _length);
|
||||
else if (compression == BTRFS_EXTENT_COMPRESS_ZLIB)
|
||||
panic("zlib isn't unsupported for regular extent\n");
|
||||
else
|
||||
panic("unknown extent compression; %d\n", compression);
|
||||
}
|
||||
|
||||
TRACE("Inode::ReadAt(%" B_PRIdINO ") key.Offset() %lld\n", ID(),
|
||||
@@ -220,8 +229,87 @@ Inode::ReadAt(off_t pos, uint8* buffer, size_t* _length)
|
||||
if (extent_data->Type() != BTRFS_EXTENT_DATA_INLINE)
|
||||
panic("unknown extent type; %d\n", extent_data->Type());
|
||||
|
||||
*_length = min_c(extent_data->MemoryBytes() - diff, *_length);
|
||||
memcpy(buffer, extent_data->inline_data, *_length);
|
||||
*_length = min_c(extent_data->Size() - diff, *_length);
|
||||
if (compression == BTRFS_EXTENT_COMPRESS_NONE)
|
||||
memcpy(buffer, extent_data->inline_data, *_length);
|
||||
else if (compression == BTRFS_EXTENT_COMPRESS_ZLIB) {
|
||||
char in[2048];
|
||||
z_stream zStream = {
|
||||
(Bytef*)in, // next in
|
||||
sizeof(in), // avail in
|
||||
0, // total in
|
||||
NULL, // next out
|
||||
0, // avail out
|
||||
0, // total out
|
||||
0, // msg
|
||||
0, // state
|
||||
Z_NULL, // zalloc
|
||||
Z_NULL, // zfree
|
||||
Z_NULL, // opaque
|
||||
0, // data type
|
||||
0, // adler
|
||||
0, // reserved
|
||||
};
|
||||
|
||||
int status;
|
||||
ssize_t offset = 0;
|
||||
size_t inline_size = item_size - 13;
|
||||
bool headerRead = false;
|
||||
|
||||
TRACE("Inode::ReadAt(%" B_PRIdINO ") diff %lld size %ld\n", ID(),
|
||||
diff, item_size);
|
||||
|
||||
do {
|
||||
ssize_t bytesRead = min_c(sizeof(in), inline_size - offset);
|
||||
memcpy(in, extent_data->inline_data + offset, bytesRead);
|
||||
if (bytesRead != (ssize_t)sizeof(in)) {
|
||||
if (bytesRead <= 0) {
|
||||
status = Z_STREAM_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
zStream.avail_in = bytesRead;
|
||||
zStream.next_in = (Bytef*)in;
|
||||
|
||||
if (!headerRead) {
|
||||
headerRead = true;
|
||||
|
||||
zStream.avail_out = length;
|
||||
zStream.next_out = (Bytef*)buffer;
|
||||
|
||||
status = inflateInit2(&zStream, 15);
|
||||
if (status != Z_OK) {
|
||||
free(extent_data);
|
||||
return B_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
status = inflate(&zStream, Z_SYNC_FLUSH);
|
||||
offset += bytesRead;
|
||||
if (diff > 0) {
|
||||
zStream.next_out -= max_c(bytesRead, diff);
|
||||
diff -= max_c(bytesRead, diff);
|
||||
}
|
||||
|
||||
if (zStream.avail_in != 0 && status != Z_STREAM_END) {
|
||||
TRACE("Inode::ReadAt() didn't read whole block: %s\n",
|
||||
zStream.msg);
|
||||
}
|
||||
} while (status == Z_OK);
|
||||
|
||||
inflateEnd(&zStream);
|
||||
|
||||
if (status != Z_STREAM_END) {
|
||||
TRACE("Inode::ReadAt() inflating failed: %d!\n", status);
|
||||
free(extent_data);
|
||||
return B_BAD_DATA;
|
||||
}
|
||||
|
||||
*_length = zStream.total_out;
|
||||
|
||||
} else
|
||||
panic("unknown extent compression; %d\n", compression);
|
||||
free(extent_data);
|
||||
return B_OK;
|
||||
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
SubDir HAIKU_TOP src add-ons kernel file_systems btrfs ;
|
||||
|
||||
UseHeaders [ FDirName $(HAIKU_TOP) headers libs zlib ] ;
|
||||
|
||||
UsePrivateHeaders [ FDirName kernel util ] ;
|
||||
UsePrivateHeaders shared storage ;
|
||||
UsePrivateKernelHeaders ;
|
||||
SubDirSysHdrs $(HAIKU_TOP) headers libs zlib ;
|
||||
|
||||
SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src libs zlib ] ;
|
||||
|
||||
KernelAddon btrfs :
|
||||
kernel_interface.cpp
|
||||
@@ -14,4 +19,11 @@ KernelAddon btrfs :
|
||||
DirectoryIterator.cpp
|
||||
Inode.cpp
|
||||
Volume.cpp
|
||||
|
||||
inflate.c
|
||||
inffast.c
|
||||
inftrees.c
|
||||
adler32.c
|
||||
crc32.c
|
||||
zutil.c
|
||||
;
|
||||
|
||||
@@ -279,6 +279,7 @@ struct btrfs_extent_data {
|
||||
return B_LENDIAN_TO_HOST_INT64(generation); }
|
||||
uint64 MemoryBytes() const {
|
||||
return B_LENDIAN_TO_HOST_INT64(memory_size); }
|
||||
uint8 Compression() const { return compression; }
|
||||
uint8 Type() const { return type; }
|
||||
uint64 DiskOffset() const {
|
||||
return B_LENDIAN_TO_HOST_INT64(disk_offset); }
|
||||
@@ -310,6 +311,10 @@ struct btrfs_extent_data {
|
||||
#define BTRFS_KEY_TYPE_ROOT_ITEM 132
|
||||
#define BTRFS_KEY_TYPE_XATTR_ITEM 24
|
||||
|
||||
#define BTRFS_EXTENT_COMPRESS_NONE 0
|
||||
#define BTRFS_EXTENT_COMPRESS_ZLIB 1
|
||||
#define BTRFS_EXTENT_COMPRESS_LZO 2
|
||||
|
||||
#define BTRFS_EXTENT_DATA_INLINE 0
|
||||
#define BTRFS_EXTENT_DATA_REGULAR 1
|
||||
#define BTRFS_EXTENT_DATA_PRE 2
|
||||
|
||||
Reference in New Issue
Block a user