From 81bb8debd0d570dc67dc1e9d8b612632cb941893 Mon Sep 17 00:00:00 2001 From: Phillip Lougher Date: Thu, 9 Dec 2010 02:02:29 +0000 Subject: Squashfs: add XZ compression support Add support for reading file systems compressed with the XZ compression algorithm. This patch adds the XZ decompressor wrapper code. Signed-off-by: Phillip Lougher diff --git a/fs/squashfs/squashfs_fs.h b/fs/squashfs/squashfs_fs.h index c5137fc..39533fe 100644 --- a/fs/squashfs/squashfs_fs.h +++ b/fs/squashfs/squashfs_fs.h @@ -238,6 +238,7 @@ struct meta_index { #define ZLIB_COMPRESSION 1 #define LZMA_COMPRESSION 2 #define LZO_COMPRESSION 3 +#define XZ_COMPRESSION 4 struct squashfs_super_block { __le32 s_magic; diff --git a/fs/squashfs/xz_wrapper.c b/fs/squashfs/xz_wrapper.c new file mode 100644 index 0000000..856756c --- /dev/null +++ b/fs/squashfs/xz_wrapper.c @@ -0,0 +1,153 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 + * Phillip Lougher + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * xz_wrapper.c + */ + + +#include +#include +#include +#include + +#include "squashfs_fs.h" +#include "squashfs_fs_sb.h" +#include "squashfs_fs_i.h" +#include "squashfs.h" +#include "decompressor.h" + +struct squashfs_xz { + struct xz_dec *state; + struct xz_buf buf; +}; + +static void *squashfs_xz_init(struct squashfs_sb_info *msblk) +{ + int block_size = max_t(int, msblk->block_size, SQUASHFS_METADATA_SIZE); + + struct squashfs_xz *stream = kmalloc(sizeof(*stream), GFP_KERNEL); + if (stream == NULL) + goto failed; + + stream->state = xz_dec_init(XZ_PREALLOC, block_size); + if (stream->state == NULL) + goto failed; + + return stream; + +failed: + ERROR("Failed to allocate xz workspace\n"); + kfree(stream); + return NULL; +} + + +static void squashfs_xz_free(void *strm) +{ + struct squashfs_xz *stream = strm; + + if (stream) { + xz_dec_end(stream->state); + kfree(stream); + } +} + + +static int squashfs_xz_uncompress(struct squashfs_sb_info *msblk, void **buffer, + struct buffer_head **bh, int b, int offset, int length, int srclength, + int pages) +{ + enum xz_ret xz_err; + int avail, total = 0, k = 0, page = 0; + struct squashfs_xz *stream = msblk->stream; + + mutex_lock(&msblk->read_data_mutex); + + xz_dec_reset(stream->state); + stream->buf.in_pos = 0; + stream->buf.in_size = 0; + stream->buf.out_pos = 0; + stream->buf.out_size = PAGE_CACHE_SIZE; + stream->buf.out = buffer[page++]; + + do { + if (stream->buf.in_pos == stream->buf.in_size && k < b) { + avail = min(length, msblk->devblksize - offset); + length -= avail; + wait_on_buffer(bh[k]); + if (!buffer_uptodate(bh[k])) + goto release_mutex; + + if (avail == 0) { + offset = 0; + put_bh(bh[k++]); + continue; + } + + stream->buf.in = bh[k]->b_data + offset; + stream->buf.in_size = avail; + stream->buf.in_pos = 0; + offset = 0; + } + + if (stream->buf.out_pos == stream->buf.out_size + && page < pages) { + stream->buf.out = buffer[page++]; + stream->buf.out_pos = 0; + total += PAGE_CACHE_SIZE; + } + + xz_err = xz_dec_run(stream->state, &stream->buf); + + if (stream->buf.in_pos == stream->buf.in_size && k < b) + put_bh(bh[k++]); + } while (xz_err == XZ_OK); + + if (xz_err != XZ_STREAM_END) { + ERROR("xz_dec_run error, data probably corrupt\n"); + goto release_mutex; + } + + if (k < b) { + ERROR("xz_uncompress error, input remaining\n"); + goto release_mutex; + } + + total += stream->buf.out_pos; + mutex_unlock(&msblk->read_data_mutex); + return total; + +release_mutex: + mutex_unlock(&msblk->read_data_mutex); + + for (; k < b; k++) + put_bh(bh[k]); + + return -EIO; +} + +const struct squashfs_decompressor squashfs_xz_comp_ops = { + .init = squashfs_xz_init, + .free = squashfs_xz_free, + .decompress = squashfs_xz_uncompress, + .id = XZ_COMPRESSION, + .name = "xz", + .supported = 1 +}; -- cgit v0.10.2 From 7a43ae523744c01b6187013e781f44c2281c579c Mon Sep 17 00:00:00 2001 From: Phillip Lougher Date: Thu, 9 Dec 2010 02:08:31 +0000 Subject: Squashfs: Add XZ compression configuration option Signed-off-by: Phillip Lougher diff --git a/fs/squashfs/Kconfig b/fs/squashfs/Kconfig index e5f63da..50cc4ed 100644 --- a/fs/squashfs/Kconfig +++ b/fs/squashfs/Kconfig @@ -53,6 +53,21 @@ config SQUASHFS_LZO If unsure, say N. +config SQUASHFS_XZ + bool "Include support for XZ compressed file systems" + depends on SQUASHFS + select XZ_DEC + help + Saying Y here includes support for reading Squashfs file systems + compressed with XZ compresssion. XZ gives better compression than + the default zlib compression, at the expense of greater CPU and + memory overhead. + + XZ is not the standard compression used in Squashfs and so most + file systems will be readable without selecting this option. + + If unsure, say N. + config SQUASHFS_EMBEDDED bool "Additional option for memory-constrained systems" depends on SQUASHFS diff --git a/fs/squashfs/Makefile b/fs/squashfs/Makefile index 7672bac..cecf2be 100644 --- a/fs/squashfs/Makefile +++ b/fs/squashfs/Makefile @@ -7,3 +7,4 @@ squashfs-y += block.o cache.o dir.o export.o file.o fragment.o id.o inode.o squashfs-y += namei.o super.o symlink.o zlib_wrapper.o decompressor.o squashfs-$(CONFIG_SQUASHFS_XATTR) += xattr.o xattr_id.o squashfs-$(CONFIG_SQUASHFS_LZO) += lzo_wrapper.o +squashfs-$(CONFIG_SQUASHFS_XZ) += xz_wrapper.o diff --git a/fs/squashfs/decompressor.c b/fs/squashfs/decompressor.c index 24af9ce..482d781 100644 --- a/fs/squashfs/decompressor.c +++ b/fs/squashfs/decompressor.c @@ -46,6 +46,12 @@ static const struct squashfs_decompressor squashfs_lzo_unsupported_comp_ops = { }; #endif +#ifndef CONFIG_SQUASHFS_XZ +static const struct squashfs_decompressor squashfs_xz_comp_ops = { + NULL, NULL, NULL, XZ_COMPRESSION, "xz", 0 +}; +#endif + static const struct squashfs_decompressor squashfs_unknown_comp_ops = { NULL, NULL, NULL, 0, "unknown", 0 }; @@ -58,6 +64,7 @@ static const struct squashfs_decompressor *decompressor[] = { #else &squashfs_lzo_unsupported_comp_ops, #endif + &squashfs_xz_comp_ops, &squashfs_unknown_comp_ops }; diff --git a/fs/squashfs/decompressor.h b/fs/squashfs/decompressor.h index 7425f80..57e1acb 100644 --- a/fs/squashfs/decompressor.h +++ b/fs/squashfs/decompressor.h @@ -52,4 +52,9 @@ static inline int squashfs_decompress(struct squashfs_sb_info *msblk, return msblk->decompressor->decompress(msblk, buffer, bh, b, offset, length, srclength, pages); } + +#ifdef CONFIG_SQUASHFS_XZ +extern const struct squashfs_decompressor squashfs_xz_comp_ops; +#endif + #endif -- cgit v0.10.2 From 170cf02165272dfe026eba183563bad973ca4f05 Mon Sep 17 00:00:00 2001 From: Phillip Lougher Date: Wed, 5 Jan 2011 17:52:26 +0000 Subject: Squashfs: remove unnecessary variable in zlib_wrapper Get rid of unnecessary bytes variable, and remove redundant initialisation of zlib_err. Signed-off-by: Phillip Lougher diff --git a/fs/squashfs/zlib_wrapper.c b/fs/squashfs/zlib_wrapper.c index 7a60387..1f4833b 100644 --- a/fs/squashfs/zlib_wrapper.c +++ b/fs/squashfs/zlib_wrapper.c @@ -66,8 +66,8 @@ static int zlib_uncompress(struct squashfs_sb_info *msblk, void **buffer, struct buffer_head **bh, int b, int offset, int length, int srclength, int pages) { - int zlib_err = 0, zlib_init = 0; - int avail, bytes, k = 0, page = 0; + int zlib_err, zlib_init = 0; + int k = 0, page = 0; z_stream *stream = msblk->stream; mutex_lock(&msblk->read_data_mutex); @@ -75,11 +75,10 @@ static int zlib_uncompress(struct squashfs_sb_info *msblk, void **buffer, stream->avail_out = 0; stream->avail_in = 0; - bytes = length; do { if (stream->avail_in == 0 && k < b) { - avail = min(bytes, msblk->devblksize - offset); - bytes -= avail; + int avail = min(length, msblk->devblksize - offset); + length -= avail; wait_on_buffer(bh[k]); if (!buffer_uptodate(bh[k])) goto release_mutex; -- cgit v0.10.2 From e7ee11f0ecd587caed0063c5f68ca20fef699f32 Mon Sep 17 00:00:00 2001 From: Phillip Lougher Date: Wed, 5 Jan 2011 18:02:37 +0000 Subject: Squashfs: add missing check in zlib_wrapper On file system corruption zlib can return Z_STREAM_OK with input buffers remaining, which will not be released. Signed-off-by: Phillip Lougher diff --git a/fs/squashfs/zlib_wrapper.c b/fs/squashfs/zlib_wrapper.c index 1f4833b..ab5801f 100644 --- a/fs/squashfs/zlib_wrapper.c +++ b/fs/squashfs/zlib_wrapper.c @@ -127,6 +127,11 @@ static int zlib_uncompress(struct squashfs_sb_info *msblk, void **buffer, goto release_mutex; } + if (k < b) { + ERROR("zlib_uncompress error, data remaining\n"); + goto release_mutex; + } + length = stream->total_out; mutex_unlock(&msblk->read_data_mutex); return length; -- cgit v0.10.2 From 6197fd86789a28760f8375b5ae8885cd7258042f Mon Sep 17 00:00:00 2001 From: Phillip Lougher Date: Wed, 5 Jan 2011 18:15:58 +0000 Subject: Squashfs: get rid of default n in Kconfig As pointed out by Geert Uytterhoeven, "default n" is the default, no reason to specify it. Signed-off-by: Phillip Lougher diff --git a/fs/squashfs/Kconfig b/fs/squashfs/Kconfig index 50cc4ed..aa68a8a 100644 --- a/fs/squashfs/Kconfig +++ b/fs/squashfs/Kconfig @@ -29,7 +29,6 @@ config SQUASHFS config SQUASHFS_XATTR bool "Squashfs XATTR support" depends on SQUASHFS - default n help Saying Y here includes support for extended attributes (xattrs). Xattrs are name:value pairs associated with inodes by @@ -40,7 +39,6 @@ config SQUASHFS_XATTR config SQUASHFS_LZO bool "Include support for LZO compressed file systems" depends on SQUASHFS - default n select LZO_DECOMPRESS help Saying Y here includes support for reading Squashfs file systems @@ -71,7 +69,6 @@ config SQUASHFS_XZ config SQUASHFS_EMBEDDED bool "Additional option for memory-constrained systems" depends on SQUASHFS - default n help Saying Y here allows you to specify cache size. -- cgit v0.10.2 From 8fcd97216f45b1691f8f91f35cc108d06e0bfca8 Mon Sep 17 00:00:00 2001 From: Phillip Lougher Date: Thu, 6 Jan 2011 06:08:50 +0000 Subject: Squashfs: move squashfs_i() definition from squashfs.h Move squashfs_i() definition out of squashfs.h, this eliminates the need to #include squashfs_fs_i.h from numerous files. Signed-off-by: Phillip Lougher diff --git a/fs/squashfs/block.c b/fs/squashfs/block.c index 653c030..2fb2882 100644 --- a/fs/squashfs/block.c +++ b/fs/squashfs/block.c @@ -34,7 +34,6 @@ #include "squashfs_fs.h" #include "squashfs_fs_sb.h" -#include "squashfs_fs_i.h" #include "squashfs.h" #include "decompressor.h" diff --git a/fs/squashfs/cache.c b/fs/squashfs/cache.c index 57314be..26b15ae 100644 --- a/fs/squashfs/cache.c +++ b/fs/squashfs/cache.c @@ -55,7 +55,6 @@ #include "squashfs_fs.h" #include "squashfs_fs_sb.h" -#include "squashfs_fs_i.h" #include "squashfs.h" /* diff --git a/fs/squashfs/decompressor.c b/fs/squashfs/decompressor.c index 482d781..50b22d3 100644 --- a/fs/squashfs/decompressor.c +++ b/fs/squashfs/decompressor.c @@ -27,7 +27,6 @@ #include "squashfs_fs.h" #include "squashfs_fs_sb.h" -#include "squashfs_fs_i.h" #include "decompressor.h" #include "squashfs.h" diff --git a/fs/squashfs/fragment.c b/fs/squashfs/fragment.c index 7c90bbd..7eef571 100644 --- a/fs/squashfs/fragment.c +++ b/fs/squashfs/fragment.c @@ -39,7 +39,6 @@ #include "squashfs_fs.h" #include "squashfs_fs_sb.h" -#include "squashfs_fs_i.h" #include "squashfs.h" /* diff --git a/fs/squashfs/id.c b/fs/squashfs/id.c index b7f64bc..d8f3245 100644 --- a/fs/squashfs/id.c +++ b/fs/squashfs/id.c @@ -37,7 +37,6 @@ #include "squashfs_fs.h" #include "squashfs_fs_sb.h" -#include "squashfs_fs_i.h" #include "squashfs.h" /* diff --git a/fs/squashfs/lzo_wrapper.c b/fs/squashfs/lzo_wrapper.c index 5d87789..7da759e 100644 --- a/fs/squashfs/lzo_wrapper.c +++ b/fs/squashfs/lzo_wrapper.c @@ -29,7 +29,6 @@ #include "squashfs_fs.h" #include "squashfs_fs_sb.h" -#include "squashfs_fs_i.h" #include "squashfs.h" #include "decompressor.h" diff --git a/fs/squashfs/squashfs.h b/fs/squashfs/squashfs.h index 5d45569..18f187f 100644 --- a/fs/squashfs/squashfs.h +++ b/fs/squashfs/squashfs.h @@ -27,11 +27,6 @@ #define WARNING(s, args...) pr_warning("SQUASHFS: "s, ## args) -static inline struct squashfs_inode_info *squashfs_i(struct inode *inode) -{ - return list_entry(inode, struct squashfs_inode_info, vfs_inode); -} - /* block.c */ extern int squashfs_read_data(struct super_block *, void **, u64, int, u64 *, int, int); diff --git a/fs/squashfs/squashfs_fs_i.h b/fs/squashfs/squashfs_fs_i.h index d3e3a37..359baef 100644 --- a/fs/squashfs/squashfs_fs_i.h +++ b/fs/squashfs/squashfs_fs_i.h @@ -45,4 +45,10 @@ struct squashfs_inode_info { }; struct inode vfs_inode; }; + + +static inline struct squashfs_inode_info *squashfs_i(struct inode *inode) +{ + return list_entry(inode, struct squashfs_inode_info, vfs_inode); +} #endif diff --git a/fs/squashfs/xattr_id.c b/fs/squashfs/xattr_id.c index d33be5d..05385db 100644 --- a/fs/squashfs/xattr_id.c +++ b/fs/squashfs/xattr_id.c @@ -32,7 +32,6 @@ #include "squashfs_fs.h" #include "squashfs_fs_sb.h" -#include "squashfs_fs_i.h" #include "squashfs.h" #include "xattr.h" diff --git a/fs/squashfs/zlib_wrapper.c b/fs/squashfs/zlib_wrapper.c index ab5801f..818a5e0 100644 --- a/fs/squashfs/zlib_wrapper.c +++ b/fs/squashfs/zlib_wrapper.c @@ -29,7 +29,6 @@ #include "squashfs_fs.h" #include "squashfs_fs_sb.h" -#include "squashfs_fs_i.h" #include "squashfs.h" #include "decompressor.h" -- cgit v0.10.2 From 01a678c5a2f41663b8faf03d17e2bbdbf44158a9 Mon Sep 17 00:00:00 2001 From: Phillip Lougher Date: Wed, 5 Jan 2011 18:23:53 +0000 Subject: Squashfs: simplify CONFIG_SQUASHFS_LZO handling Get rid of messy repeated #if(n)def CONFIG_SQUASHFS_LZO code in decompressor.c Signed-off-by: Phillip Lougher diff --git a/fs/squashfs/decompressor.c b/fs/squashfs/decompressor.c index 50b22d3..a5940e5 100644 --- a/fs/squashfs/decompressor.c +++ b/fs/squashfs/decompressor.c @@ -40,7 +40,7 @@ static const struct squashfs_decompressor squashfs_lzma_unsupported_comp_ops = { }; #ifndef CONFIG_SQUASHFS_LZO -static const struct squashfs_decompressor squashfs_lzo_unsupported_comp_ops = { +static const struct squashfs_decompressor squashfs_lzo_comp_ops = { NULL, NULL, NULL, LZO_COMPRESSION, "lzo", 0 }; #endif @@ -57,13 +57,9 @@ static const struct squashfs_decompressor squashfs_unknown_comp_ops = { static const struct squashfs_decompressor *decompressor[] = { &squashfs_zlib_comp_ops, - &squashfs_lzma_unsupported_comp_ops, -#ifdef CONFIG_SQUASHFS_LZO &squashfs_lzo_comp_ops, -#else - &squashfs_lzo_unsupported_comp_ops, -#endif &squashfs_xz_comp_ops, + &squashfs_lzma_unsupported_comp_ops, &squashfs_unknown_comp_ops }; diff --git a/fs/squashfs/decompressor.h b/fs/squashfs/decompressor.h index 57e1acb..3b305a7 100644 --- a/fs/squashfs/decompressor.h +++ b/fs/squashfs/decompressor.h @@ -57,4 +57,8 @@ static inline int squashfs_decompress(struct squashfs_sb_info *msblk, extern const struct squashfs_decompressor squashfs_xz_comp_ops; #endif +#ifdef CONFIG_SQUASHFS_LZO +extern const struct squashfs_decompressor squashfs_lzo_comp_ops; +#endif + #endif diff --git a/fs/squashfs/squashfs.h b/fs/squashfs/squashfs.h index 18f187f..ba729d8 100644 --- a/fs/squashfs/squashfs.h +++ b/fs/squashfs/squashfs.h @@ -99,6 +99,3 @@ extern const struct xattr_handler *squashfs_xattr_handlers[]; /* zlib_wrapper.c */ extern const struct squashfs_decompressor squashfs_zlib_comp_ops; - -/* lzo_wrapper.c */ -extern const struct squashfs_decompressor squashfs_lzo_comp_ops; -- cgit v0.10.2