szip: Add seekable zip format
Subsystems (3)
A message that is not in the archive (sent off-list or not yet received): [email protected]
PATCH 1/2 szip: Add seekable zip format
Add support for inflating seekable zip format. This uses zlib underneath. In order to create a seekable zip file, use the szip utility which can be obtained from
https://github.com/glandium/faulty.lib
We shall use this to implement transparent decompression on ext4. The use would be very similar to that used by the faulty.lib linker.
--- include/linux/szip.h | 32 ++++++++ lib/Kconfig | 8 ++ lib/Makefile | 1 + lib/szip.c | 217 +++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 258 insertions(+) create mode 100644 include/linux/szip.h create mode 100644 lib/szip.c
include/linux/szip.h new file +32 -0
@@ -0,0 +1,32 @@ +#ifndef __SZIP_H +#define __SZIP_H + +#include <linux/zlib.h> +#include <linux/types.h> + +#define SZIP_HEADER_SIZE (20) + +struct szip_struct { +u32 magic; +u32 total_size; +u16 chunk_size; +u16 dict_size; +u32 nr_chunks; +u16 last_chunk_size; +signed char window_bits; +signed char filter; +unsigned *offset_table; +unsigned *dictionary; +char *buffer; +void *workspace; +}; + +extern int szip_decompress (struct szip_struct *,char *,size_t ); +extern int szip_seekable_decompress (struct szip_struct *,size_t , +size_t ,char *,size_t ); +extern size_t szip_uncompressed_size (struct szip_struct *); +extern int szip_init (struct szip_struct *,char *); +extern void szip_init_offset_table (struct szip_struct *szip,char *buf); +extern size_t szip_offset_table_size (struct szip_struct *szip); + +#endif
lib/Kconfig +8 -0
@@ -213,6 +213,14 @@ config DECOMPRESS_LZO select LZO_DECOMPRESS tristate +config SZIP + select ZLIB_INFLATE + tristate + help + Use this to provide szip decompression support. szip is a seekable + zlib format. Check https://github.com/glandium/faulty.lib for the + szip tool. This is required for transparent ext4 decompression. + # # Generic allocator support is selected if needed #
lib/Makefile +1 -0
@@ -77,6 +77,7 @@ obj-$(CONFIG_LZO_COMPRESS) += lzo/ obj-$(CONFIG_LZO_DECOMPRESS) += lzo/ obj-$(CONFIG_XZ_DEC) += xz/ obj-$(CONFIG_RAID6_PQ) += raid6/ +obj-${CONFIG_SZIP} += szip.o lib-$(CONFIG_DECOMPRESS_GZIP) += decompress_inflate.o lib-$(CONFIG_DECOMPRESS_BZIP2) += decompress_bunzip2.o
lib/szip.c new file +217 -0
217 lines not on this page · raw message
Signature · 1 line
1.8.1.4
PATCH 2/2 Add rudimentary transparent decompression support to ext4
In reply to a message not in the archiveAdds basic support for transparently reading compressed files in ext4.
Lots of issues in this patch
1. It requires a fully read file from disk, no seeking allowed
2. Compressed files give their compressed sizes and not uncompressed sizes. Therefore cat will return truncated data (since the buffer isn't big enough)
3. It adds a new file operation. That will be *removed*.
4. Doesn't mmap decompressed data
--- fs/ext4/file.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ fs/read_write.c | 3 +++ include/linux/fs.h | 1 + 3 files changed, 70 insertions(+)
fs/ext4/file.c +66 -0
@@ -31,6 +31,9 @@#include "xattr.h" #include "acl.h" +#include <linux/zlib.h> +#include <linux/szip.h> +/* * Called when an inode is released. Note that this is different * from ext4_file_open: open gets called at every open, but release
@@ -623,6 +626,68 @@ loff_t ext4_llseek(struct file *file, loff_t offset, int whence)return -EINVAL ; } +static int ext4_is_file_compressed (struct file *file) +{ +struct inode *inode = file->f_mapping->host; +return ext4_test_inode_flag (inode,EXT4_INODE_COMPR ); +} + +static int _ext4_decompress (char __user *buf,int sz) +{ +/* +* We can really cheat here since we have the full buffer already read +* and made available +*/ +struct szip_struct szip; +char *temp; +size_t uncom_size; + +int ret =szip_init (&szip, buf); +if (ret) { + ret =-1 ; + goto out; + } + + uncom_size =szip_uncompressed_size (&szip); + temp =kmalloc (uncom_size,GFP_NOFS ); +if (!temp) { + ret =-2 ; + goto out; + } + + ret =szip_decompress (&szip, temp,0 ); +if (ret) { + ret =-3 ; + goto out_free; + } + + sz =min_t (int, sz, uncom_size); + +memset (buf,0 , sz); +memcpy (buf, temp, sz); +out_free: +kfree (temp); + +out: +return ret; + +} + +int ext4_decompress (struct file *file,char __user *buf,size_t len) +{ +int ret =0 ; + +if (!ext4_is_file_compressed (file)) +return 0 ; + + ret =_ext4_decompress (buf, len); +if (ret) { + goto out; + } +out: +return ret; +} +const struct file_operations ext4_file_operations = { .llseek = ext4_llseek, .read = do_sync_read,
@@ -640,6 +705,7 @@ const struct file_operations ext4_file_operations = { .splice_read = generic_file_splice_read, .splice_write = generic_file_splice_write, .fallocate = ext4_fallocate, + .decompress = ext4_decompress, };const struct inode_operations ext4_file_inode_operations = {
fs/read_write.c +3 -0
@@ -330,6 +330,7 @@ int rw_verify_area(int read_write, struct file *file, loff_t *ppos, size_t countreturn count >MAX_RW_COUNT ?MAX_RW_COUNT : count; } +ssize_t do_sync_read (struct file *filp,char __user *buf,size_t len,loff_t *ppos) {struct iovec iov = { .iov_base = buf, .iov_len = len };
@@ -345,6 +346,8 @@ ssize_t do_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppif (-EIOCBQUEUED == ret) ret =wait_on_sync_kiocb (&kiocb); *ppos = kiocb.ki_pos; +if (filp->f_op->decompress) + filp->f_op->decompress (filp, buf, len);return ret; }
include/linux/fs.h +1 -0
@@ -1543,6 +1543,7 @@ struct file_operations {long (*fallocate)(struct file *file,int mode,loff_t offset,loff_t len);int (*show_fdinfo)(struct seq_file *m,struct file *f); +int (*decompress)(struct file *,char *,size_t ); };struct inode_operations {
Signature · 1 line
1.8.1.4