]> git.ipfire.org Git - thirdparty/u-boot.git/blobdiff - fs/btrfs/compression.c
command: Introduce functions to obtain command arguments
[thirdparty/u-boot.git] / fs / btrfs / compression.c
index 346875d45a1be3761cbd749d168f1d9a44979149..c69524d38eccd066429153e4adb149a3b49e34d3 100644 (file)
@@ -2,46 +2,56 @@
 /*
  * BTRFS filesystem implementation for U-Boot
  *
- * 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz
+ * 2017 Marek BehĂșn, CZ.NIC, kabel@kernel.org
  */
 
 #include "btrfs.h"
+#include <abuf.h>
+#include <log.h>
 #include <malloc.h>
 #include <linux/lzo.h>
 #include <linux/zstd.h>
+#include <linux/compat.h>
 #include <u-boot/zlib.h>
 #include <asm/unaligned.h>
 
+/* Header for each segment, LE32, recording the compressed size */
+#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;
 
-       if (clen < 4)
+       if (clen < LZO_LEN)
                return -1;
 
        tot_len = le32_to_cpu(get_unaligned((u32 *)cbuf));
-       cbuf += 4;
-       clen -= 4;
-       tot_len -= 4;
+       tot_in = 0;
+       cbuf += LZO_LEN;
+       clen -= LZO_LEN;
+       tot_len -= LZO_LEN;
+       tot_in += LZO_LEN;
 
        if (tot_len == 0 && dlen)
                return -1;
-       if (tot_len < 4)
+       if (tot_len < LZO_LEN)
                return -1;
 
        res = 0;
 
-       while (tot_len > 4) {
+       while (tot_len > LZO_LEN) {
+               u32 rem_page;
+
                in_len = le32_to_cpu(get_unaligned((u32 *)cbuf));
-               cbuf += 4;
-               clen -= 4;
+               cbuf += LZO_LEN;
+               clen -= LZO_LEN;
 
-               if (in_len > clen || tot_len < 4 + in_len)
+               if (in_len > clen || tot_len < LZO_LEN + in_len)
                        return -1;
 
-               tot_len -= 4 + in_len;
+               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);
@@ -54,6 +64,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;
@@ -94,7 +116,7 @@ static u32 decompress_zlib(const u8 *_cbuf, u32 clen, u8 *dbuf, u32 dlen)
        while (stream.total_in < clen) {
                stream.next_in = cbuf + stream.total_in;
                stream.avail_in = min((u32) (clen - stream.total_in),
-                                     (u32) btrfs_info.sb.sectorsize);
+                                       current_fs_info->sectorsize);
 
                ret = inflate(&stream, Z_NO_FLUSH);
                if (ret != Z_OK)
@@ -115,54 +137,12 @@ static u32 decompress_zlib(const u8 *_cbuf, u32 clen, u8 *dbuf, u32 dlen)
 
 static u32 decompress_zstd(const u8 *cbuf, u32 clen, u8 *dbuf, u32 dlen)
 {
-       ZSTD_DStream *dstream;
-       ZSTD_inBuffer in_buf;
-       ZSTD_outBuffer out_buf;
-       void *workspace;
-       size_t wsize;
-       u32 res = -1;
-
-       wsize = ZSTD_DStreamWorkspaceBound(ZSTD_BTRFS_MAX_INPUT);
-       workspace = malloc(wsize);
-       if (!workspace) {
-               debug("%s: cannot allocate workspace of size %zu\n", __func__,
-                     wsize);
-               return -1;
-       }
-
-       dstream = ZSTD_initDStream(ZSTD_BTRFS_MAX_INPUT, workspace, wsize);
-       if (!dstream) {
-               printf("%s: ZSTD_initDStream failed\n", __func__);
-               goto err_free;
-       }
-
-       in_buf.src = cbuf;
-       in_buf.pos = 0;
-       in_buf.size = clen;
+       struct abuf in, out;
 
-       out_buf.dst = dbuf;
-       out_buf.pos = 0;
-       out_buf.size = dlen;
+       abuf_init_set(&in, (u8 *)cbuf, clen);
+       abuf_init_set(&out, dbuf, dlen);
 
-       while (1) {
-               size_t ret;
-
-               ret = ZSTD_decompressStream(dstream, &out_buf, &in_buf);
-               if (ZSTD_isError(ret)) {
-                       printf("%s: ZSTD_decompressStream error %d\n", __func__,
-                              ZSTD_getErrorCode(ret));
-                       goto err_free;
-               }
-
-               if (in_buf.pos >= clen || !ret)
-                       break;
-       }
-
-       res = out_buf.pos;
-
-err_free:
-       free(workspace);
-       return res;
+       return zstd_decompress(&in, &out);
 }
 
 u32 btrfs_decompress(u8 type, const char *c, u32 clen, char *d, u32 dlen)