Skip to content

Commit

Permalink
Merge branch 'for-next/zstd'
Browse files Browse the repository at this point in the history
  • Loading branch information
saschahauer committed Feb 8, 2018
2 parents 0dce537 + 5a7a1a0 commit 69b589a
Show file tree
Hide file tree
Showing 25 changed files with 8,860 additions and 0 deletions.
9 changes: 9 additions & 0 deletions fs/squashfs/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,12 @@ if !SQUASHFS_XZ
comment "XZ support disabled"
endif

config SQUASHFS_ZSTD
bool
depends on FS_SQUASHFS
depends on ZSTD_DECOMPRESS
default y

if !SQUASHFS_ZSTD
comment "ZSTD support disabled"
endif
1 change: 1 addition & 0 deletions fs/squashfs/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ obj-$(CONFIG_SQUASHFS_XZ) += xz_wrapper.o
obj-$(CONFIG_SQUASHFS_LZO) += lzo_wrapper.o
obj-$(CONFIG_SQUASHFS_LZ4) += lz4_wrapper.o
obj-$(CONFIG_SQUASHFS_ZLIB) += zlib_wrapper.o
obj-$(CONFIG_SQUASHFS_ZSTD) += zstd_wrapper.o
7 changes: 7 additions & 0 deletions fs/squashfs/decompressor.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,12 @@ static const struct squashfs_decompressor squashfs_zlib_comp_ops = {
};
#endif

#ifndef CONFIG_SQUASHFS_ZSTD
static const struct squashfs_decompressor squashfs_zstd_comp_ops = {
NULL, NULL, NULL, NULL, ZSTD_COMPRESSION, "zstd", 0
};
#endif

static const struct squashfs_decompressor squashfs_unknown_comp_ops = {
NULL, NULL, NULL, NULL, 0, "unknown", 0
};
Expand All @@ -68,6 +74,7 @@ static const struct squashfs_decompressor *decompressor[] = {
&squashfs_lzo_comp_ops,
&squashfs_xz_comp_ops,
&squashfs_lzma_unsupported_comp_ops,
&squashfs_zstd_comp_ops,
&squashfs_unknown_comp_ops
};

Expand Down
4 changes: 4 additions & 0 deletions fs/squashfs/decompressor.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,8 @@ extern const struct squashfs_decompressor squashfs_lzo_comp_ops;
extern const struct squashfs_decompressor squashfs_zlib_comp_ops;
#endif

#ifdef CONFIG_SQUASHFS_ZSTD
extern const struct squashfs_decompressor squashfs_zstd_comp_ops;
#endif

#endif
1 change: 1 addition & 0 deletions fs/squashfs/squashfs_fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ struct meta_index {
#define LZO_COMPRESSION 3
#define XZ_COMPRESSION 4
#define LZ4_COMPRESSION 5
#define ZSTD_COMPRESSION 6

struct squashfs_super_block {
__le32 s_magic;
Expand Down
147 changes: 147 additions & 0 deletions fs/squashfs/zstd_wrapper.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
/*
* Squashfs - a compressed read only filesystem for Linux
*
* Copyright (c) 2016-present, Facebook, Inc.
* All rights reserved.
*
* 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.
*
* zstd_wrapper.c
*/

#include <linux/zstd.h>

#include "squashfs_fs.h"
#include "squashfs_fs_sb.h"
#include "squashfs.h"
#include "decompressor.h"
#include "page_actor.h"

struct workspace {
void *mem;
size_t mem_size;
size_t window_size;
};

static void *zstd_init(struct squashfs_sb_info *msblk, void *buff)
{
struct workspace *wksp = kmalloc(sizeof(*wksp), GFP_KERNEL);

if (wksp == NULL)
goto failed;
wksp->window_size = max_t(size_t,
msblk->block_size, SQUASHFS_METADATA_SIZE);
wksp->mem_size = ZSTD_DStreamWorkspaceBound(wksp->window_size);
wksp->mem = vmalloc(wksp->mem_size);
if (wksp->mem == NULL)
goto failed;

return wksp;

failed:
ERROR("Failed to allocate zstd workspace\n");
kfree(wksp);
return ERR_PTR(-ENOMEM);
}


static void zstd_free(void *strm)
{
struct workspace *wksp = strm;

if (wksp)
vfree(wksp->mem);
kfree(wksp);
}


static int zstd_uncompress(struct squashfs_sb_info *msblk, void *strm,
char **bh, int b, int offset, int length,
struct squashfs_page_actor *output)
{
struct workspace *wksp = strm;
ZSTD_DStream *stream;
size_t total_out = 0;
size_t zstd_err;
int k = 0;
ZSTD_inBuffer in_buf = { NULL, 0, 0 };
ZSTD_outBuffer out_buf = { NULL, 0, 0 };

stream = ZSTD_initDStream(wksp->window_size, wksp->mem, wksp->mem_size);

if (!stream) {
ERROR("Failed to initialize zstd decompressor\n");
goto out;
}

out_buf.size = PAGE_SIZE;
out_buf.dst = squashfs_first_page(output);

do {
if (in_buf.pos == in_buf.size && k < b) {
int avail = min(length, msblk->devblksize - offset);

length -= avail;
in_buf.src = bh[k] + offset;
in_buf.size = avail;
in_buf.pos = 0;
offset = 0;
}

if (out_buf.pos == out_buf.size) {
out_buf.dst = squashfs_next_page(output);
if (out_buf.dst == NULL) {
/* Shouldn't run out of pages
* before stream is done.
*/
squashfs_finish_page(output);
goto out;
}
out_buf.pos = 0;
out_buf.size = PAGE_SIZE;
}

total_out -= out_buf.pos;
zstd_err = ZSTD_decompressStream(stream, &out_buf, &in_buf);
total_out += out_buf.pos; /* add the additional data produced */

if (in_buf.pos == in_buf.size && k < b)
kfree(bh[k++]);
} while (zstd_err != 0 && !ZSTD_isError(zstd_err));

squashfs_finish_page(output);

if (ZSTD_isError(zstd_err)) {
ERROR("zstd decompression error: %d\n",
(int)ZSTD_getErrorCode(zstd_err));
goto out;
}

if (k < b)
goto out;

return (int)total_out;

out:
for (; k < b; k++)
kfree(bh[k]);

return -EIO;
}

const struct squashfs_decompressor squashfs_zstd_comp_ops = {
.init = zstd_init,
.free = zstd_free,
.decompress = zstd_uncompress,
.id = ZSTD_COMPRESSION,
.name = "zstd",
.supported = 1
};
2 changes: 2 additions & 0 deletions include/linux/unaligned/generic.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#ifndef _LINUX_UNALIGNED_GENERIC_H
#define _LINUX_UNALIGNED_GENERIC_H

#include <linux/compiler.h>

/*
* Cause a link-time error if we try an unaligned access other than
* 1,2,4 or 8 bytes long
Expand Down
Loading

0 comments on commit 69b589a

Please sign in to comment.