15e5c12b0Sopenharmony_ci/** 25e5c12b0Sopenharmony_ci * compress.c 35e5c12b0Sopenharmony_ci * 45e5c12b0Sopenharmony_ci * Copyright (c) 2020 Google Inc. 55e5c12b0Sopenharmony_ci * Robin Hsu <robinhsu@google.com> 65e5c12b0Sopenharmony_ci * : add sload compression support 75e5c12b0Sopenharmony_ci * 85e5c12b0Sopenharmony_ci * This program is free software; you can redistribute it and/or modify 95e5c12b0Sopenharmony_ci * it under the terms of the GNU General Public License version 2 as 105e5c12b0Sopenharmony_ci * published by the Free Software Foundation. 115e5c12b0Sopenharmony_ci */ 125e5c12b0Sopenharmony_ci 135e5c12b0Sopenharmony_ci/* for config.h for general environment (non-Android) */ 145e5c12b0Sopenharmony_ci#include "f2fs.h" 155e5c12b0Sopenharmony_ci 165e5c12b0Sopenharmony_ci#include "compress.h" 175e5c12b0Sopenharmony_ci#ifdef HAVE_LIBLZO2 185e5c12b0Sopenharmony_ci#include <lzo/lzo1x.h> /* for lzo1x_1_15_compress() */ 195e5c12b0Sopenharmony_ci#endif 205e5c12b0Sopenharmony_ci#ifdef HAVE_LIBLZ4 215e5c12b0Sopenharmony_ci#include <lz4.h> /* for LZ4_compress_fast_extState() */ 225e5c12b0Sopenharmony_ci#endif 235e5c12b0Sopenharmony_ci 245e5c12b0Sopenharmony_ci/* 255e5c12b0Sopenharmony_ci * macro/constants borrowed from kernel header (GPL-2.0): 265e5c12b0Sopenharmony_ci * include/linux/lzo.h, and include/linux/lz4.h 275e5c12b0Sopenharmony_ci */ 285e5c12b0Sopenharmony_ci#ifdef HAVE_LIBLZO2 295e5c12b0Sopenharmony_ci#define lzo1x_worst_compress(x) ((x) + (x) / 16 + 64 + 3 + 2) 305e5c12b0Sopenharmony_ci#define LZO_WORK_SIZE ALIGN_UP(LZO1X_1_15_MEM_COMPRESS, 8) 315e5c12b0Sopenharmony_ci#endif 325e5c12b0Sopenharmony_ci#ifdef HAVE_LIBLZ4 335e5c12b0Sopenharmony_ci#define LZ4_MEMORY_USAGE 14 345e5c12b0Sopenharmony_ci#define LZ4_MAX_INPUT_SIZE 0x7E000000 /* 2 113 929 216 bytes */ 355e5c12b0Sopenharmony_ci#define LZ4_MEM_COMPRESS sizeof(LZ4_stream_t) 365e5c12b0Sopenharmony_ci#define LZ4_ACCELERATION_DEFAULT 1 375e5c12b0Sopenharmony_ci#define LZ4_WORK_SIZE ALIGN_UP(LZ4_MEM_COMPRESS, 8) 385e5c12b0Sopenharmony_ci#endif 395e5c12b0Sopenharmony_ci 405e5c12b0Sopenharmony_ci#if defined(HAVE_LIBLZO2) || defined(HAVE_LIBLZ4) 415e5c12b0Sopenharmony_cistatic void reset_cc(struct compress_ctx *cc) 425e5c12b0Sopenharmony_ci{ 435e5c12b0Sopenharmony_ci memset(cc->rbuf, 0, cc->cluster_size * F2FS_BLKSIZE); 445e5c12b0Sopenharmony_ci memset(cc->cbuf->cdata, 0, cc->cluster_size * F2FS_BLKSIZE 455e5c12b0Sopenharmony_ci - F2FS_BLKSIZE); 465e5c12b0Sopenharmony_ci} 475e5c12b0Sopenharmony_ci#endif 485e5c12b0Sopenharmony_ci 495e5c12b0Sopenharmony_ci#ifdef HAVE_LIBLZO2 505e5c12b0Sopenharmony_cistatic void lzo_compress_init(struct compress_ctx *cc) 515e5c12b0Sopenharmony_ci{ 525e5c12b0Sopenharmony_ci size_t size = cc->cluster_size * F2FS_BLKSIZE; 535e5c12b0Sopenharmony_ci size_t alloc = size + lzo1x_worst_compress(size) 545e5c12b0Sopenharmony_ci + COMPRESS_HEADER_SIZE + LZO_WORK_SIZE; 555e5c12b0Sopenharmony_ci cc->private = malloc(alloc); 565e5c12b0Sopenharmony_ci ASSERT(cc->private); 575e5c12b0Sopenharmony_ci cc->rbuf = (char *) cc->private + LZO_WORK_SIZE; 585e5c12b0Sopenharmony_ci cc->cbuf = (struct compress_data *)((char *) cc->rbuf + size); 595e5c12b0Sopenharmony_ci} 605e5c12b0Sopenharmony_ci 615e5c12b0Sopenharmony_cistatic int lzo_compress(struct compress_ctx *cc) 625e5c12b0Sopenharmony_ci{ 635e5c12b0Sopenharmony_ci int ret = lzo1x_1_15_compress(cc->rbuf, cc->rlen, cc->cbuf->cdata, 645e5c12b0Sopenharmony_ci (lzo_uintp)(&cc->clen), cc->private); 655e5c12b0Sopenharmony_ci cc->cbuf->clen = cpu_to_le32(cc->clen); 665e5c12b0Sopenharmony_ci return ret; 675e5c12b0Sopenharmony_ci} 685e5c12b0Sopenharmony_ci#endif 695e5c12b0Sopenharmony_ci 705e5c12b0Sopenharmony_ci#ifdef HAVE_LIBLZ4 715e5c12b0Sopenharmony_cistatic void lz4_compress_init(struct compress_ctx *cc) 725e5c12b0Sopenharmony_ci{ 735e5c12b0Sopenharmony_ci size_t size = cc->cluster_size * F2FS_BLKSIZE; 745e5c12b0Sopenharmony_ci size_t alloc = size + LZ4_COMPRESSBOUND(size) 755e5c12b0Sopenharmony_ci + COMPRESS_HEADER_SIZE + LZ4_WORK_SIZE; 765e5c12b0Sopenharmony_ci cc->private = malloc(alloc); 775e5c12b0Sopenharmony_ci ASSERT(cc->private); 785e5c12b0Sopenharmony_ci cc->rbuf = (char *) cc->private + LZ4_WORK_SIZE; 795e5c12b0Sopenharmony_ci cc->cbuf = (struct compress_data *)((char *) cc->rbuf + size); 805e5c12b0Sopenharmony_ci} 815e5c12b0Sopenharmony_ci 825e5c12b0Sopenharmony_cistatic int lz4_compress(struct compress_ctx *cc) 835e5c12b0Sopenharmony_ci{ 845e5c12b0Sopenharmony_ci cc->clen = LZ4_compress_fast_extState(cc->private, cc->rbuf, 855e5c12b0Sopenharmony_ci (char *)cc->cbuf->cdata, cc->rlen, 865e5c12b0Sopenharmony_ci cc->rlen - F2FS_BLKSIZE * c.compress.min_blocks - 875e5c12b0Sopenharmony_ci COMPRESS_HEADER_SIZE, 885e5c12b0Sopenharmony_ci LZ4_ACCELERATION_DEFAULT); 895e5c12b0Sopenharmony_ci 905e5c12b0Sopenharmony_ci if (!cc->clen) 915e5c12b0Sopenharmony_ci return 1; 925e5c12b0Sopenharmony_ci 935e5c12b0Sopenharmony_ci cc->cbuf->clen = cpu_to_le32(cc->clen); 945e5c12b0Sopenharmony_ci return 0; 955e5c12b0Sopenharmony_ci} 965e5c12b0Sopenharmony_ci#endif 975e5c12b0Sopenharmony_ci 985e5c12b0Sopenharmony_ciconst char *supported_comp_names[] = { 995e5c12b0Sopenharmony_ci "lzo", 1005e5c12b0Sopenharmony_ci "lz4", 1015e5c12b0Sopenharmony_ci "", 1025e5c12b0Sopenharmony_ci}; 1035e5c12b0Sopenharmony_ci 1045e5c12b0Sopenharmony_cicompress_ops supported_comp_ops[] = { 1055e5c12b0Sopenharmony_ci#ifdef HAVE_LIBLZO2 1065e5c12b0Sopenharmony_ci {lzo_compress_init, lzo_compress, reset_cc}, 1075e5c12b0Sopenharmony_ci#else 1085e5c12b0Sopenharmony_ci {NULL, NULL, NULL}, 1095e5c12b0Sopenharmony_ci#endif 1105e5c12b0Sopenharmony_ci#ifdef HAVE_LIBLZ4 1115e5c12b0Sopenharmony_ci {lz4_compress_init, lz4_compress, reset_cc}, 1125e5c12b0Sopenharmony_ci#else 1135e5c12b0Sopenharmony_ci {NULL, NULL, NULL}, 1145e5c12b0Sopenharmony_ci#endif 1155e5c12b0Sopenharmony_ci}; 1165e5c12b0Sopenharmony_ci 1175e5c12b0Sopenharmony_ci/* linked list */ 1185e5c12b0Sopenharmony_citypedef struct _ext_t { 1195e5c12b0Sopenharmony_ci const char *ext; 1205e5c12b0Sopenharmony_ci struct _ext_t *next; 1215e5c12b0Sopenharmony_ci} ext_t; 1225e5c12b0Sopenharmony_ci 1235e5c12b0Sopenharmony_cistatic ext_t *extension_list; 1245e5c12b0Sopenharmony_ci 1255e5c12b0Sopenharmony_cistatic bool ext_found(const char *ext) 1265e5c12b0Sopenharmony_ci{ 1275e5c12b0Sopenharmony_ci ext_t *p = extension_list; 1285e5c12b0Sopenharmony_ci 1295e5c12b0Sopenharmony_ci while (p != NULL && strcmp(ext, p->ext)) 1305e5c12b0Sopenharmony_ci p = p->next; 1315e5c12b0Sopenharmony_ci return (p != NULL); 1325e5c12b0Sopenharmony_ci} 1335e5c12b0Sopenharmony_ci 1345e5c12b0Sopenharmony_cistatic const char *get_ext(const char *path) 1355e5c12b0Sopenharmony_ci{ 1365e5c12b0Sopenharmony_ci char *p = strrchr(path, '.'); 1375e5c12b0Sopenharmony_ci 1385e5c12b0Sopenharmony_ci return p == NULL ? path + strlen(path) : p + 1; 1395e5c12b0Sopenharmony_ci} 1405e5c12b0Sopenharmony_ci 1415e5c12b0Sopenharmony_cistatic bool ext_do_filter(const char *path) 1425e5c12b0Sopenharmony_ci{ 1435e5c12b0Sopenharmony_ci return (ext_found(get_ext(path)) == true) ^ 1445e5c12b0Sopenharmony_ci (c.compress.filter == COMPR_FILTER_ALLOW); 1455e5c12b0Sopenharmony_ci} 1465e5c12b0Sopenharmony_ci 1475e5c12b0Sopenharmony_cistatic void ext_filter_add(const char *ext) 1485e5c12b0Sopenharmony_ci{ 1495e5c12b0Sopenharmony_ci ext_t *node; 1505e5c12b0Sopenharmony_ci 1515e5c12b0Sopenharmony_ci ASSERT(ext != NULL); 1525e5c12b0Sopenharmony_ci if (ext_found(ext)) 1535e5c12b0Sopenharmony_ci return; /* ext was already registered */ 1545e5c12b0Sopenharmony_ci node = malloc(sizeof(ext_t)); 1555e5c12b0Sopenharmony_ci ASSERT(node != NULL); 1565e5c12b0Sopenharmony_ci node->ext = ext; 1575e5c12b0Sopenharmony_ci node->next = extension_list; 1585e5c12b0Sopenharmony_ci extension_list = node; 1595e5c12b0Sopenharmony_ci} 1605e5c12b0Sopenharmony_ci 1615e5c12b0Sopenharmony_cistatic void ext_filter_destroy(void) 1625e5c12b0Sopenharmony_ci{ 1635e5c12b0Sopenharmony_ci ext_t *p; 1645e5c12b0Sopenharmony_ci 1655e5c12b0Sopenharmony_ci while (extension_list != NULL) { 1665e5c12b0Sopenharmony_ci p = extension_list; 1675e5c12b0Sopenharmony_ci extension_list = p->next; 1685e5c12b0Sopenharmony_ci free(p); 1695e5c12b0Sopenharmony_ci } 1705e5c12b0Sopenharmony_ci} 1715e5c12b0Sopenharmony_ci 1725e5c12b0Sopenharmony_cifilter_ops ext_filter = { 1735e5c12b0Sopenharmony_ci .add = ext_filter_add, 1745e5c12b0Sopenharmony_ci .destroy = ext_filter_destroy, 1755e5c12b0Sopenharmony_ci .filter = ext_do_filter, 1765e5c12b0Sopenharmony_ci}; 177