mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-23 17:30:02 +00:00
![Xiaoming Ni](/assets/img/avatar_default.png)
Patch series 'squashfs: Add the mount parameter "threads="'. Currently, Squashfs supports multiple decompressor parallel modes. However, this mode can be configured only during kernel building and does not support flexible selection during runtime. In the current patch set, the mount parameter "threads=" is added to allow users to select the parallel decompressor mode and configure the number of decompressors when mounting a file system. "threads=<single|multi|percpu|1|2|3|...>" The upper limit is num_online_cpus() * 2. This patch (of 2): Squashfs supports three decompression concurrency modes: Single-thread mode: concurrent reads are blocked and the memory overhead is small. Multi-thread mode/percpu mode: reduces concurrent read blocking but increases memory overhead. The corresponding schema must be fixed at compile time. During mounting, the concurrent decompression mode cannot be adjusted based on file read blocking. The mount parameter theads=<single|multi|percpu> is added to select the concurrent decompression mode of a single SquashFS file system image. Link: https://lkml.kernel.org/r/20221019030930.130456-1-nixiaoming@huawei.com Link: https://lkml.kernel.org/r/20221019030930.130456-2-nixiaoming@huawei.com Signed-off-by: Xiaoming Ni <nixiaoming@huawei.com> Reviewed-by: Phillip Lougher <phillip@squashfs.org.uk> Cc: Jianguo Chen <chenjianguo3@huawei.com> Cc: Jubin Zhong <zhongjubin@huawei.com> Cc: Zhang Yi <yi.zhang@huawei.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
142 lines
3.3 KiB
C
142 lines
3.3 KiB
C
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
/*
|
|
* Squashfs - a compressed read only filesystem for Linux
|
|
*
|
|
* Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
|
|
* Phillip Lougher <phillip@squashfs.org.uk>
|
|
*
|
|
* decompressor.c
|
|
*/
|
|
|
|
#include <linux/types.h>
|
|
#include <linux/mutex.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/buffer_head.h>
|
|
|
|
#include "squashfs_fs.h"
|
|
#include "squashfs_fs_sb.h"
|
|
#include "decompressor.h"
|
|
#include "squashfs.h"
|
|
#include "page_actor.h"
|
|
|
|
/*
|
|
* This file (and decompressor.h) implements a decompressor framework for
|
|
* Squashfs, allowing multiple decompressors to be easily supported
|
|
*/
|
|
|
|
static const struct squashfs_decompressor squashfs_lzma_unsupported_comp_ops = {
|
|
NULL, NULL, NULL, NULL, LZMA_COMPRESSION, "lzma", 0
|
|
};
|
|
|
|
#ifndef CONFIG_SQUASHFS_LZ4
|
|
static const struct squashfs_decompressor squashfs_lz4_comp_ops = {
|
|
NULL, NULL, NULL, NULL, LZ4_COMPRESSION, "lz4", 0
|
|
};
|
|
#endif
|
|
|
|
#ifndef CONFIG_SQUASHFS_LZO
|
|
static const struct squashfs_decompressor squashfs_lzo_comp_ops = {
|
|
NULL, NULL, NULL, NULL, LZO_COMPRESSION, "lzo", 0
|
|
};
|
|
#endif
|
|
|
|
#ifndef CONFIG_SQUASHFS_XZ
|
|
static const struct squashfs_decompressor squashfs_xz_comp_ops = {
|
|
NULL, NULL, NULL, NULL, XZ_COMPRESSION, "xz", 0
|
|
};
|
|
#endif
|
|
|
|
#ifndef CONFIG_SQUASHFS_ZLIB
|
|
static const struct squashfs_decompressor squashfs_zlib_comp_ops = {
|
|
NULL, NULL, NULL, NULL, ZLIB_COMPRESSION, "zlib", 0
|
|
};
|
|
#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
|
|
};
|
|
|
|
static const struct squashfs_decompressor *decompressor[] = {
|
|
&squashfs_zlib_comp_ops,
|
|
&squashfs_lz4_comp_ops,
|
|
&squashfs_lzo_comp_ops,
|
|
&squashfs_xz_comp_ops,
|
|
&squashfs_lzma_unsupported_comp_ops,
|
|
&squashfs_zstd_comp_ops,
|
|
&squashfs_unknown_comp_ops
|
|
};
|
|
|
|
|
|
const struct squashfs_decompressor *squashfs_lookup_decompressor(int id)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; decompressor[i]->id; i++)
|
|
if (id == decompressor[i]->id)
|
|
break;
|
|
|
|
return decompressor[i];
|
|
}
|
|
|
|
|
|
static void *get_comp_opts(struct super_block *sb, unsigned short flags)
|
|
{
|
|
struct squashfs_sb_info *msblk = sb->s_fs_info;
|
|
void *buffer = NULL, *comp_opts;
|
|
struct squashfs_page_actor *actor = NULL;
|
|
int length = 0;
|
|
|
|
/*
|
|
* Read decompressor specific options from file system if present
|
|
*/
|
|
if (SQUASHFS_COMP_OPTS(flags)) {
|
|
buffer = kmalloc(PAGE_SIZE, GFP_KERNEL);
|
|
if (buffer == NULL) {
|
|
comp_opts = ERR_PTR(-ENOMEM);
|
|
goto out;
|
|
}
|
|
|
|
actor = squashfs_page_actor_init(&buffer, 1, 0);
|
|
if (actor == NULL) {
|
|
comp_opts = ERR_PTR(-ENOMEM);
|
|
goto out;
|
|
}
|
|
|
|
length = squashfs_read_data(sb,
|
|
sizeof(struct squashfs_super_block), 0, NULL, actor);
|
|
|
|
if (length < 0) {
|
|
comp_opts = ERR_PTR(length);
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
comp_opts = squashfs_comp_opts(msblk, buffer, length);
|
|
|
|
out:
|
|
kfree(actor);
|
|
kfree(buffer);
|
|
return comp_opts;
|
|
}
|
|
|
|
|
|
void *squashfs_decompressor_setup(struct super_block *sb, unsigned short flags)
|
|
{
|
|
struct squashfs_sb_info *msblk = sb->s_fs_info;
|
|
void *stream, *comp_opts = get_comp_opts(sb, flags);
|
|
|
|
if (IS_ERR(comp_opts))
|
|
return comp_opts;
|
|
|
|
stream = msblk->thread_ops->create(msblk, comp_opts);
|
|
if (IS_ERR(stream))
|
|
kfree(comp_opts);
|
|
|
|
return stream;
|
|
}
|