mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-21 08:19:28 +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>
111 lines
2.6 KiB
C
111 lines
2.6 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
/*
|
|
* Copyright (c) 2013
|
|
* Phillip Lougher <phillip@squashfs.org.uk>
|
|
*/
|
|
|
|
#include <linux/types.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/percpu.h>
|
|
#include <linux/buffer_head.h>
|
|
#include <linux/local_lock.h>
|
|
|
|
#include "squashfs_fs.h"
|
|
#include "squashfs_fs_sb.h"
|
|
#include "decompressor.h"
|
|
#include "squashfs.h"
|
|
|
|
/*
|
|
* This file implements multi-threaded decompression using percpu
|
|
* variables, one thread per cpu core.
|
|
*/
|
|
|
|
struct squashfs_stream {
|
|
void *stream;
|
|
local_lock_t lock;
|
|
};
|
|
|
|
static void *squashfs_decompressor_create(struct squashfs_sb_info *msblk,
|
|
void *comp_opts)
|
|
{
|
|
struct squashfs_stream *stream;
|
|
struct squashfs_stream __percpu *percpu;
|
|
int err, cpu;
|
|
|
|
percpu = alloc_percpu(struct squashfs_stream);
|
|
if (percpu == NULL)
|
|
return ERR_PTR(-ENOMEM);
|
|
|
|
for_each_possible_cpu(cpu) {
|
|
stream = per_cpu_ptr(percpu, cpu);
|
|
stream->stream = msblk->decompressor->init(msblk, comp_opts);
|
|
if (IS_ERR(stream->stream)) {
|
|
err = PTR_ERR(stream->stream);
|
|
goto out;
|
|
}
|
|
local_lock_init(&stream->lock);
|
|
}
|
|
|
|
kfree(comp_opts);
|
|
return (__force void *) percpu;
|
|
|
|
out:
|
|
for_each_possible_cpu(cpu) {
|
|
stream = per_cpu_ptr(percpu, cpu);
|
|
if (!IS_ERR_OR_NULL(stream->stream))
|
|
msblk->decompressor->free(stream->stream);
|
|
}
|
|
free_percpu(percpu);
|
|
return ERR_PTR(err);
|
|
}
|
|
|
|
static void squashfs_decompressor_destroy(struct squashfs_sb_info *msblk)
|
|
{
|
|
struct squashfs_stream __percpu *percpu =
|
|
(struct squashfs_stream __percpu *) msblk->stream;
|
|
struct squashfs_stream *stream;
|
|
int cpu;
|
|
|
|
if (msblk->stream) {
|
|
for_each_possible_cpu(cpu) {
|
|
stream = per_cpu_ptr(percpu, cpu);
|
|
msblk->decompressor->free(stream->stream);
|
|
}
|
|
free_percpu(percpu);
|
|
}
|
|
}
|
|
|
|
static int squashfs_decompress(struct squashfs_sb_info *msblk, struct bio *bio,
|
|
int offset, int length, struct squashfs_page_actor *output)
|
|
{
|
|
struct squashfs_stream *stream;
|
|
struct squashfs_stream __percpu *percpu =
|
|
(struct squashfs_stream __percpu *) msblk->stream;
|
|
int res;
|
|
|
|
local_lock(&percpu->lock);
|
|
stream = this_cpu_ptr(percpu);
|
|
|
|
res = msblk->decompressor->decompress(msblk, stream->stream, bio,
|
|
offset, length, output);
|
|
|
|
local_unlock(&percpu->lock);
|
|
|
|
if (res < 0)
|
|
ERROR("%s decompression failed, data probably corrupt\n",
|
|
msblk->decompressor->name);
|
|
|
|
return res;
|
|
}
|
|
|
|
static int squashfs_max_decompressors(void)
|
|
{
|
|
return num_possible_cpus();
|
|
}
|
|
|
|
const struct squashfs_decompressor_thread_ops squashfs_decompressor_percpu = {
|
|
.create = squashfs_decompressor_create,
|
|
.destroy = squashfs_decompressor_destroy,
|
|
.decompress = squashfs_decompress,
|
|
.max_decompressors = squashfs_max_decompressors,
|
|
};
|