openwrt/tools/mtd-utils/patches/136-mkfs.ubifs-xz-support.p...

405 lines
11 KiB
Diff

--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
# -*- sh -*-
-CPPFLAGS += -I./include $(ZLIBCPPFLAGS) $(LZOCPPFLAGS) -I./include/linux/lzma
+CPPFLAGS += -I./include $(ZLIBCPPFLAGS) $(LZOCPPFLAGS) $(XZCPPFLAGS) -I./include/linux/lzma
ifeq ($(WITHOUT_XATTR), 1)
CPPFLAGS += -DWITHOUT_XATTR
--- a/mkfs.ubifs/compr.c
+++ b/mkfs.ubifs/compr.c
@@ -127,6 +127,114 @@ static inline int lzo_init(void) { retur
static inline void lzo_fini(void) { }
#endif
+#ifndef WITHOUT_XZ
+
+#include <lzma.h>
+
+struct xz_ctx {
+ lzma_filter filters[3];
+ lzma_options_lzma opts;
+};
+
+static struct xz_ctx *xz_ctx;
+
+#define LZMA_COMPRESSION_LEVEL 9
+
+static struct xz_ctx *xz_ctx_init(void)
+{
+ struct xz_ctx *ctx;
+ lzma_options_lzma *opts_lzma;
+ uint32_t preset;
+ int ret;
+
+ ctx = malloc(sizeof(struct xz_ctx));
+ if (ctx == NULL)
+ goto err;
+
+ memset(ctx, 0, sizeof(struct xz_ctx));
+
+ opts_lzma = &ctx->opts;
+
+ preset = LZMA_COMPRESSION_LEVEL | LZMA_PRESET_EXTREME;
+ ret = lzma_lzma_preset(opts_lzma, preset);
+ if (ret)
+ goto err_free_ctx;
+
+ /* TODO: allow to specify LZMA options via command line */
+#if 0
+ opts_lzma->lc = 3;
+ opts_lzma->lp = 0;
+ opts_lzma->pb = 2;
+ opts_lzma->nice_len = 64;
+#else
+ opts_lzma->lc = 0;
+ opts_lzma->lp = 2;
+ opts_lzma->pb = 2;
+ opts_lzma->nice_len = 64;
+#endif
+
+ ctx->filters[0].id = LZMA_FILTER_LZMA2;
+ ctx->filters[0].options = opts_lzma;
+ ctx->filters[1].id = LZMA_VLI_UNKNOWN;
+
+ return ctx;
+
+err_free_ctx:
+ free(ctx);
+err:
+ return NULL;
+}
+
+static void xz_ctx_free(struct xz_ctx *ctx)
+{
+ free(ctx);
+}
+
+static int xz_init(void)
+{
+ xz_ctx = xz_ctx_init();
+ if (xz_ctx == NULL)
+ return -1;
+
+ return 0;
+}
+
+static void xz_fini(void)
+{
+ xz_ctx_free(xz_ctx);
+}
+
+static int xz_compress(void *in_buf, size_t in_len, void *out_buf,
+ size_t *out_len)
+{
+ size_t ret_len;
+ lzma_ret ret_xz;
+ int ret;
+
+ ret = -1;
+
+ ret_len = 0;
+ ret_xz = lzma_stream_buffer_encode(xz_ctx->filters, LZMA_CHECK_CRC32,
+ NULL, in_buf, in_len, out_buf,
+ &ret_len, *out_len);
+ if (ret_xz != LZMA_OK) {
+ fprintf(stderr, "XZ error: %d\n", (int) ret_xz);
+ goto out;
+ }
+
+ *out_len = ret_len;
+
+ ret = 0;
+out:
+ return ret;
+}
+#else
+static inline int xz_init(void) { return 0; }
+static inline void xz_fini(void) { }
+static inline int xz_compress(void *in_buf, size_t in_len, void *out_buf,
+ size_t *out_len) { return -1; }
+#endif
+
static int no_compress(void *in_buf, size_t in_len, void *out_buf,
size_t *out_len)
{
@@ -199,6 +307,9 @@ int compress_data(void *in_buf, size_t i
case MKFS_UBIFS_COMPR_LZO:
ret = lzo_compress(in_buf, in_len, out_buf, out_len);
break;
+ case MKFS_UBIFS_COMPR_XZ:
+ ret = xz_compress(in_buf, in_len, out_buf, out_len);
+ break;
case MKFS_UBIFS_COMPR_ZLIB:
ret = zlib_deflate(in_buf, in_len, out_buf, out_len);
break;
@@ -226,12 +337,18 @@ int init_compression(void)
if (ret)
goto err;
+ ret = xz_init();
+ if (ret)
+ goto err_lzo;
+
zlib_buf = malloc(UBIFS_BLOCK_SIZE * WORST_COMPR_FACTOR);
if (!zlib_buf)
- goto err_lzo;
+ goto err_xz;
return 0;
+err_xz:
+ xz_fini();
err_lzo:
lzo_fini();
err:
@@ -241,6 +358,7 @@ err:
void destroy_compression(void)
{
free(zlib_buf);
+ xz_fini();
lzo_fini();
if (errcnt)
fprintf(stderr, "%llu compression errors occurred\n", errcnt);
--- a/mkfs.ubifs/compr.h
+++ b/mkfs.ubifs/compr.h
@@ -36,6 +36,7 @@ enum compression_type
MKFS_UBIFS_COMPR_NONE,
MKFS_UBIFS_COMPR_LZO,
MKFS_UBIFS_COMPR_ZLIB,
+ MKFS_UBIFS_COMPR_XZ,
};
int compress_data(void *in_buf, size_t in_len, void *out_buf, size_t *out_len,
--- a/mkfs.ubifs/Makefile
+++ b/mkfs.ubifs/Makefile
@@ -6,21 +6,33 @@ ALL_SOURCES=*.[ch] hashtable/*.[ch]
TARGETS = mkfs.ubifs
+MKFS_UBIFS_OBJS = $(addprefix $(BUILDDIR)/,\
+ crc16.o lpt.o compr.o devtable.o \
+ hashtable/hashtable.o hashtable/hashtable_itr.o)
+
ifeq ($(WITHOUT_LZO), 1)
CPPFLAGS += -DWITHOUT_LZO
else
LZOLDLIBS = -llzo2
endif
-LDLIBS_mkfs.ubifs = -lz $(LZOLDLIBS) -lm -luuid -L$(BUILDDIR)/../ubi-utils/ -lubi
+ifeq ($(WITHOUT_XZ), 1)
+ CPPFLAGS += -DWITHOUT_XZ
+else
+ifneq ($(LZMA_STATIC_LIB),)
+ MKFS_UBIFS_OBJS += $(LZMA_STATIC_LIB)
+else
+ XZLDLIBS = -llzma
+endif
+endif
+
+LDLIBS_mkfs.ubifs = -lz $(LZOLDLIBS) $(XZLDLIBS) -lm -luuid -L$(BUILDDIR)/../ubi-utils/ -lubi
LDLIBS_mkfs.ubifs += -L$(BUILDDIR)/../lib -lmtd
-LDLIBS_mkfs.ubifs += $(ZLIBLDFLAGS) $(LZOLDFLAGS)
+LDLIBS_mkfs.ubifs += $(ZLIBLDFLAGS) $(LZOLDFLAGS) $(XZLDFLAGS)
include ../common.mk
-$(BUILDDIR)/mkfs.ubifs: $(addprefix $(BUILDDIR)/,\
- crc16.o lpt.o compr.o devtable.o \
- hashtable/hashtable.o hashtable/hashtable_itr.o)
+$(BUILDDIR)/mkfs.ubifs: $(MKFS_UBIFS_OBJS)
clean::
rm -f $(BUILDDIR)/hashtable/*.o cscope.*
--- a/mkfs.ubifs/mkfs.ubifs.c
+++ b/mkfs.ubifs/mkfs.ubifs.c
@@ -98,6 +98,9 @@ struct ubifs_info info_;
static struct ubifs_info *c = &info_;
static libubi_t ubi;
+static int force_compr_set;
+static int force_compr;
+
/* Debug levels are: 0 (none), 1 (statistics), 2 (files) ,3 (more details) */
int debug_level;
int verbose;
@@ -132,7 +135,7 @@ static struct inum_mapping **hash_table;
/* Inode creation sequence number */
static unsigned long long creat_sqnum;
-static const char *optstring = "d:r:m:o:D:h?vVe:c:g:f:Fp:k:x:X:j:R:l:j:UQq";
+static const char *optstring = "d:r:m:o:D:h?vVe:c:g:f:Fp:k:x:X:y:j:R:l:j:UQq";
static const struct option longopts[] = {
{"root", 1, NULL, 'r'},
@@ -149,6 +152,7 @@ static const struct option longopts[] =
{"reserved", 1, NULL, 'R'},
{"compr", 1, NULL, 'x'},
{"favor-percent", 1, NULL, 'X'},
+ {"force-compr", 1, NULL, 'y'},
{"fanout", 1, NULL, 'f'},
{"space-fixup", 0, NULL, 'F'},
{"keyhash", 1, NULL, 'k'},
@@ -178,11 +182,13 @@ static const char *helptext =
"-o, --output=FILE output to FILE\n"
"-j, --jrn-size=SIZE journal size\n"
"-R, --reserved=SIZE how much space should be reserved for the super-user\n"
-"-x, --compr=TYPE compression type - \"lzo\", \"favor_lzo\", \"zlib\" or\n"
-" \"none\" (default: \"lzo\")\n"
+"-x, --compr=TYPE default compression type - \"lzo\", \"favor_lzo\",\n"
+" \"zlib\" or \"none\" (default: \"lzo\")\n"
"-X, --favor-percent may only be used with favor LZO compression and defines\n"
" how many percent better zlib should compress to make\n"
" mkfs.ubifs use zlib instead of LZO (default 20%)\n"
+"-y, --force-compr=TYPE force to build the fs with different compression -\n"
+" \"lzo\", \"zlib\" or \"none\"\n"
"-f, --fanout=NUM fanout NUM (default: 8)\n"
"-F, --space-fixup file-system free space has to be fixed up on first mount\n"
" (requires kernel version 3.0 or greater)\n"
@@ -530,6 +536,43 @@ static int open_ubi(const char *node)
return 0;
}
+static const char *get_compr_str(int compr)
+{
+ switch (compr) {
+ case UBIFS_COMPR_LZO:
+ return "lzo";
+ case UBIFS_COMPR_ZLIB:
+ return "zlib";
+ case UBIFS_COMPR_XZ:
+ return "xz";
+ case UBIFS_COMPR_NONE:
+ return "none";
+ }
+
+ return "unknown";
+}
+
+static int get_compr_option(char *opt, int *compr_type, int *favor_lzo)
+{
+ *compr_type = UBIFS_COMPR_LZO;
+
+ if (favor_lzo)
+ *favor_lzo = 0;
+
+ if (favor_lzo && strcmp(optarg, "favor_lzo") == 0)
+ *favor_lzo = 1;
+ else if (strcmp(optarg, "zlib") == 0)
+ *compr_type = UBIFS_COMPR_ZLIB;
+ else if (strcmp(optarg, "xz") == 0)
+ *compr_type = UBIFS_COMPR_XZ;
+ else if (strcmp(optarg, "none") == 0)
+ *compr_type = UBIFS_COMPR_NONE;
+ else if (strcmp(optarg, "lzo") != 0)
+ return -1;
+
+ return 0;
+}
+
static int get_options(int argc, char**argv)
{
int opt, i;
@@ -649,14 +692,13 @@ static int get_options(int argc, char**a
return err_msg("bad key hash");
break;
case 'x':
- if (strcmp(optarg, "favor_lzo") == 0)
- c->favor_lzo = 1;
- else if (strcmp(optarg, "zlib") == 0)
- c->default_compr = UBIFS_COMPR_ZLIB;
- else if (strcmp(optarg, "none") == 0)
- c->default_compr = UBIFS_COMPR_NONE;
- else if (strcmp(optarg, "lzo") != 0)
- return err_msg("bad compressor name");
+ if (get_compr_option(optarg, &c->default_compr,
+ &c->favor_lzo))
+ return err_msg("bad compressor name '%s'",
+ optarg);
+ if (c->default_compr == UBIFS_COMPR_XZ)
+ return err_msg("'%s' can't be used as default compressor",
+ optarg);
break;
case 'X':
c->favor_percent = strtol(optarg, &endp, 0);
@@ -665,6 +707,12 @@ static int get_options(int argc, char**a
return err_msg("bad favor LZO percent '%s'",
optarg);
break;
+ case 'y':
+ if (get_compr_option(optarg, &force_compr, NULL))
+ return err_msg("bad forced compressor name '%s'",
+ optarg);
+ force_compr_set = 1;
+ break;
case 'j':
c->max_bud_bytes = get_bytes(optarg);
if (c->max_bud_bytes <= 0)
@@ -749,6 +797,9 @@ static int get_options(int argc, char**a
c->min_io_size = 8;
c->rp_size = add_space_overhead(c->rp_size);
+ if (force_compr_set == 0)
+ force_compr = c->default_compr;
+
if (verbose) {
printf("mkfs.ubifs\n");
printf("\troot: %s\n", root);
@@ -758,17 +809,10 @@ static int get_options(int argc, char**a
printf("\toutput: %s\n", output);
printf("\tjrn_size: %llu\n", c->max_bud_bytes);
printf("\treserved: %llu\n", c->rp_size);
- switch (c->default_compr) {
- case UBIFS_COMPR_LZO:
- printf("\tcompr: lzo\n");
- break;
- case UBIFS_COMPR_ZLIB:
- printf("\tcompr: zlib\n");
- break;
- case UBIFS_COMPR_NONE:
- printf("\tcompr: none\n");
- break;
- }
+ printf("\tcompr: %s\n", get_compr_str(c->default_compr));
+ if (force_compr_set)
+ printf("\tforced compr: %s\n",
+ get_compr_str(force_compr));
printf("\tkeyhash: %s\n", (c->key_hash == key_r5_hash) ?
"r5" : "test");
printf("\tfanout: %d\n", c->fanout);
@@ -1353,7 +1397,7 @@ static int add_file(const char *path_nam
use_compr = UBIFS_COMPR_LZO;
else
#endif
- use_compr = c->default_compr;
+ use_compr = force_compr;
compr_type = compress_data(buf, bytes_read, &dn->data,
&out_len, use_compr);
dn->compr_type = cpu_to_le16(compr_type);
--- a/mkfs.ubifs/mkfs.ubifs.h
+++ b/mkfs.ubifs/mkfs.ubifs.h
@@ -77,6 +77,9 @@
#if MKFS_UBIFS_COMPR_ZLIB != UBIFS_COMPR_ZLIB
#error MKFS_UBIFS_COMPR_ZLIB != UBIFS_COMPR_ZLIB
#endif
+#if MKFS_UBIFS_COMPR_XZ != UBIFS_COMPR_XZ
+#error MKFS_UBIFS_COMPR_XZ != UBIFS_COMPR_XZ
+#endif
extern int verbose;
extern int debug_level;
--- a/mkfs.ubifs/ubifs-media.h
+++ b/mkfs.ubifs/ubifs-media.h
@@ -303,6 +303,7 @@ enum {
UBIFS_COMPR_NONE,
UBIFS_COMPR_LZO,
UBIFS_COMPR_ZLIB,
+ UBIFS_COMPR_XZ,
UBIFS_COMPR_TYPES_CNT,
};