diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/btrfs/compression.c | 20 |
1 files changed, 19 insertions, 1 deletions
diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c index 4ef44ce114..b1884fc15e 100644 --- a/fs/btrfs/compression.c +++ b/fs/btrfs/compression.c @@ -9,6 +9,7 @@ #include <malloc.h> #include <linux/lzo.h> #include <linux/zstd.h> +#include <linux/compat.h> #include <u-boot/zlib.h> #include <asm/unaligned.h> @@ -16,7 +17,7 @@ #define LZO_LEN 4 static u32 decompress_lzo(const u8 *cbuf, u32 clen, u8 *dbuf, u32 dlen) { - u32 tot_len, in_len, res; + u32 tot_len, tot_in, in_len, res; size_t out_len; int ret; @@ -24,9 +25,11 @@ static u32 decompress_lzo(const u8 *cbuf, u32 clen, u8 *dbuf, u32 dlen) return -1; tot_len = le32_to_cpu(get_unaligned((u32 *)cbuf)); + tot_in = 0; cbuf += LZO_LEN; clen -= LZO_LEN; tot_len -= LZO_LEN; + tot_in += LZO_LEN; if (tot_len == 0 && dlen) return -1; @@ -36,6 +39,8 @@ static u32 decompress_lzo(const u8 *cbuf, u32 clen, u8 *dbuf, u32 dlen) res = 0; while (tot_len > LZO_LEN) { + u32 rem_page; + in_len = le32_to_cpu(get_unaligned((u32 *)cbuf)); cbuf += LZO_LEN; clen -= LZO_LEN; @@ -44,6 +49,7 @@ static u32 decompress_lzo(const u8 *cbuf, u32 clen, u8 *dbuf, u32 dlen) return -1; tot_len -= (LZO_LEN + in_len); + tot_in += (LZO_LEN + in_len); out_len = dlen; ret = lzo1x_decompress_safe(cbuf, in_len, dbuf, &out_len); @@ -56,6 +62,18 @@ static u32 decompress_lzo(const u8 *cbuf, u32 clen, u8 *dbuf, u32 dlen) dlen -= out_len; res += out_len; + + /* + * If the 4 bytes header does not fit to the rest of the page we + * have to move to next one, or we read some garbage. + */ + rem_page = PAGE_SIZE - (tot_in % PAGE_SIZE); + if (rem_page < LZO_LEN) { + cbuf += rem_page; + tot_in += rem_page; + clen -= rem_page; + tot_len -= rem_page; + } } return res; |