mirror of
https://github.com/kdave/btrfs-progs
synced 2025-02-07 13:21:34 +00:00
btrfs-progs: restore, fix page alignment issue for lzo compression
When runing restore under lzo compression, "bad compress length" problems are encountered. It is because there is a page alignment problem with the @decompress_lzo, as follows: |------| |----|-| |------|...|------| page ^ page page | 3 bytes left When lzo pages are compressed in memory, we will ensure that the 4 bytes length header will not cross a page boundary. There is a situation that 3 (or less) bytes are left at the end of a page, and then the 4 bytes len is stored at the start of the next page. But the @decompress_lzo doesn't go to the start of the next page and continue to read the next 4 bytes which crosses two pages, so a random value is fetched as a "bad compress length". So we check page alignment every time before we are going to fetch the next @len and after the former piece of data is decompressed. If the current page that we reach has less than 4 bytes left, then we should fetch the next @len at the start of next page. Signed-off-by: Gui Hecheng <guihc.fnst@cn.fujitsu.com> [simplifed and moved into decompress_lzo] Signed-off-by: David Sterba <dsterba@suse.cz>
This commit is contained in:
parent
895b772996
commit
f18f8b7afc
@ -111,6 +111,8 @@ static int decompress_lzo(unsigned char *inbuf, char *outbuf, u64 compress_len,
|
||||
tot_in = LZO_LEN;
|
||||
|
||||
while (tot_in < tot_len) {
|
||||
size_t mod_page;
|
||||
size_t rem_page;
|
||||
in_len = read_compress_length(inbuf);
|
||||
|
||||
if ((tot_in + LZO_LEN + in_len) > tot_len) {
|
||||
@ -134,6 +136,17 @@ static int decompress_lzo(unsigned char *inbuf, char *outbuf, u64 compress_len,
|
||||
outbuf += new_len;
|
||||
inbuf += in_len;
|
||||
tot_in += in_len;
|
||||
|
||||
/*
|
||||
* If the 4 byte header does not fit to the rest of the page we
|
||||
* have to move to the next one, unless we read some garbage
|
||||
*/
|
||||
mod_page = tot_in % PAGE_CACHE_SIZE;
|
||||
rem_page = PAGE_CACHE_SIZE - mod_page;
|
||||
if (rem_page < LZO_LEN) {
|
||||
inbuf += rem_page;
|
||||
tot_in += rem_page;
|
||||
}
|
||||
}
|
||||
|
||||
*decompress_len = out_len;
|
||||
|
Loading…
Reference in New Issue
Block a user