Skip to content

Commit

Permalink
squashfs: add the mount parameter theads=<single|multi|percpu>
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
nixiaoming authored and akpm00 committed Oct 28, 2022
1 parent 8efdc6f commit b064577
Show file tree
Hide file tree
Showing 9 changed files with 147 additions and 32 deletions.
39 changes: 34 additions & 5 deletions fs/squashfs/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -54,25 +54,54 @@ config SQUASHFS_FILE_DIRECT

endchoice

config SQUASHFS_DECOMP_SINGLE
depends on SQUASHFS
def_bool n

config SQUASHFS_DECOMP_MULTI
depends on SQUASHFS
def_bool n

config SQUASHFS_DECOMP_MULTI_PERCPU
depends on SQUASHFS
def_bool n

config SQUASHFS_CHOICE_DECOMP_BY_MOUNT
bool "Select the parallel decompression mode during mount"
depends on SQUASHFS
default n
select SQUASHFS_DECOMP_SINGLE
select SQUASHFS_DECOMP_MULTI
select SQUASHFS_DECOMP_MULTI_PERCPU
help
Compile all parallel decompression modes and specify the
decompression mode by setting "threads=" during mount.
threads=<single|multi|percpu>

default Decompressor parallelisation is SQUASHFS_DECOMP_SINGLE

choice
prompt "Decompressor parallelisation options"
prompt "Select decompression parallel mode at compile time"
depends on SQUASHFS
depends on !SQUASHFS_CHOICE_DECOMP_BY_MOUNT
help
Squashfs now supports three parallelisation options for
decompression. Each one exhibits various trade-offs between
decompression performance and CPU and memory usage.

If in doubt, select "Single threaded compression"

config SQUASHFS_DECOMP_SINGLE
config SQUASHFS_COMPILE_DECOMP_SINGLE
bool "Single threaded compression"
select SQUASHFS_DECOMP_SINGLE
help
Traditionally Squashfs has used single-threaded decompression.
Only one block (data or metadata) can be decompressed at any
one time. This limits CPU and memory usage to a minimum.

config SQUASHFS_DECOMP_MULTI
config SQUASHFS_COMPILE_DECOMP_MULTI
bool "Use multiple decompressors for parallel I/O"
select SQUASHFS_DECOMP_MULTI
help
By default Squashfs uses a single decompressor but it gives
poor performance on parallel I/O workloads when using multiple CPU
Expand All @@ -85,8 +114,9 @@ config SQUASHFS_DECOMP_MULTI
decompressors per core. It dynamically allocates decompressors
on a demand basis.

config SQUASHFS_DECOMP_MULTI_PERCPU
config SQUASHFS_COMPILE_DECOMP_MULTI_PERCPU
bool "Use percpu multiple decompressors for parallel I/O"
select SQUASHFS_DECOMP_MULTI_PERCPU
help
By default Squashfs uses a single decompressor but it gives
poor performance on parallel I/O workloads when using multiple CPU
Expand All @@ -95,7 +125,6 @@ config SQUASHFS_DECOMP_MULTI_PERCPU
This decompressor implementation uses a maximum of one
decompressor per core. It uses percpu variables to ensure
decompression is load-balanced across the cores.

endchoice

config SQUASHFS_XATTR
Expand Down
2 changes: 1 addition & 1 deletion fs/squashfs/block.c
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ int squashfs_read_data(struct super_block *sb, u64 index, int length,
res = -EIO;
goto out_free_bio;
}
res = squashfs_decompress(msblk, bio, offset, length, output);
res = msblk->thread_ops->decompress(msblk, bio, offset, length, output);
} else {
res = copy_bio_to_actor(bio, output, offset, length);
}
Expand Down
2 changes: 1 addition & 1 deletion fs/squashfs/decompressor.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ void *squashfs_decompressor_setup(struct super_block *sb, unsigned short flags)
if (IS_ERR(comp_opts))
return comp_opts;

stream = squashfs_decompressor_create(msblk, comp_opts);
stream = msblk->thread_ops->create(msblk, comp_opts);
if (IS_ERR(stream))
kfree(comp_opts);

Expand Down
16 changes: 11 additions & 5 deletions fs/squashfs/decompressor_multi.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,11 @@
#define MAX_DECOMPRESSOR (num_online_cpus() * 2)


int squashfs_max_decompressors(void)
static int squashfs_max_decompressors(void)
{
return MAX_DECOMPRESSOR;
}


struct squashfs_stream {
void *comp_opts;
struct list_head strm_list;
Expand All @@ -59,7 +58,7 @@ static void put_decomp_stream(struct decomp_stream *decomp_strm,
wake_up(&stream->wait);
}

void *squashfs_decompressor_create(struct squashfs_sb_info *msblk,
static void *squashfs_decompressor_create(struct squashfs_sb_info *msblk,
void *comp_opts)
{
struct squashfs_stream *stream;
Expand Down Expand Up @@ -103,7 +102,7 @@ void *squashfs_decompressor_create(struct squashfs_sb_info *msblk,
}


void squashfs_decompressor_destroy(struct squashfs_sb_info *msblk)
static void squashfs_decompressor_destroy(struct squashfs_sb_info *msblk)
{
struct squashfs_stream *stream = msblk->stream;
if (stream) {
Expand Down Expand Up @@ -180,7 +179,7 @@ static struct decomp_stream *get_decomp_stream(struct squashfs_sb_info *msblk,
}


int squashfs_decompress(struct squashfs_sb_info *msblk, struct bio *bio,
static int squashfs_decompress(struct squashfs_sb_info *msblk, struct bio *bio,
int offset, int length,
struct squashfs_page_actor *output)
{
Expand All @@ -195,3 +194,10 @@ int squashfs_decompress(struct squashfs_sb_info *msblk, struct bio *bio,
msblk->decompressor->name);
return res;
}

const struct squashfs_decompressor_thread_ops squashfs_decompressor_multi = {
.create = squashfs_decompressor_create,
.destroy = squashfs_decompressor_destroy,
.decompress = squashfs_decompress,
.max_decompressors = squashfs_max_decompressors,
};
23 changes: 16 additions & 7 deletions fs/squashfs/decompressor_multi_percpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ struct squashfs_stream {
local_lock_t lock;
};

void *squashfs_decompressor_create(struct squashfs_sb_info *msblk,
static void *squashfs_decompressor_create(struct squashfs_sb_info *msblk,
void *comp_opts)
{
struct squashfs_stream *stream;
Expand Down Expand Up @@ -59,7 +59,7 @@ void *squashfs_decompressor_create(struct squashfs_sb_info *msblk,
return ERR_PTR(err);
}

void squashfs_decompressor_destroy(struct squashfs_sb_info *msblk)
static void squashfs_decompressor_destroy(struct squashfs_sb_info *msblk)
{
struct squashfs_stream __percpu *percpu =
(struct squashfs_stream __percpu *) msblk->stream;
Expand All @@ -75,19 +75,21 @@ void squashfs_decompressor_destroy(struct squashfs_sb_info *msblk)
}
}

int squashfs_decompress(struct squashfs_sb_info *msblk, struct bio *bio,
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(&msblk->stream->lock);
stream = this_cpu_ptr(msblk->stream);
local_lock(&percpu->lock);
stream = this_cpu_ptr(percpu);

res = msblk->decompressor->decompress(msblk, stream->stream, bio,
offset, length, output);

local_unlock(&msblk->stream->lock);
local_unlock(&percpu->lock);

if (res < 0)
ERROR("%s decompression failed, data probably corrupt\n",
Expand All @@ -96,7 +98,14 @@ int squashfs_decompress(struct squashfs_sb_info *msblk, struct bio *bio,
return res;
}

int squashfs_max_decompressors(void)
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,
};
15 changes: 11 additions & 4 deletions fs/squashfs/decompressor_single.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ struct squashfs_stream {
struct mutex mutex;
};

void *squashfs_decompressor_create(struct squashfs_sb_info *msblk,
static void *squashfs_decompressor_create(struct squashfs_sb_info *msblk,
void *comp_opts)
{
struct squashfs_stream *stream;
Expand All @@ -49,7 +49,7 @@ void *squashfs_decompressor_create(struct squashfs_sb_info *msblk,
return ERR_PTR(err);
}

void squashfs_decompressor_destroy(struct squashfs_sb_info *msblk)
static void squashfs_decompressor_destroy(struct squashfs_sb_info *msblk)
{
struct squashfs_stream *stream = msblk->stream;

Expand All @@ -59,7 +59,7 @@ void squashfs_decompressor_destroy(struct squashfs_sb_info *msblk)
}
}

int squashfs_decompress(struct squashfs_sb_info *msblk, struct bio *bio,
static int squashfs_decompress(struct squashfs_sb_info *msblk, struct bio *bio,
int offset, int length,
struct squashfs_page_actor *output)
{
Expand All @@ -78,7 +78,14 @@ int squashfs_decompress(struct squashfs_sb_info *msblk, struct bio *bio,
return res;
}

int squashfs_max_decompressors(void)
static int squashfs_max_decompressors(void)
{
return 1;
}

const struct squashfs_decompressor_thread_ops squashfs_decompressor_single = {
.create = squashfs_decompressor_create,
.destroy = squashfs_decompressor_destroy,
.decompress = squashfs_decompress,
.max_decompressors = squashfs_max_decompressors,
};
23 changes: 18 additions & 5 deletions fs/squashfs/squashfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,24 @@ extern const struct squashfs_decompressor *squashfs_lookup_decompressor(int);
extern void *squashfs_decompressor_setup(struct super_block *, unsigned short);

/* decompressor_xxx.c */
extern void *squashfs_decompressor_create(struct squashfs_sb_info *, void *);
extern void squashfs_decompressor_destroy(struct squashfs_sb_info *);
extern int squashfs_decompress(struct squashfs_sb_info *, struct bio *,
int, int, struct squashfs_page_actor *);
extern int squashfs_max_decompressors(void);

struct squashfs_decompressor_thread_ops {
void * (*create)(struct squashfs_sb_info *msblk, void *comp_opts);
void (*destroy)(struct squashfs_sb_info *msblk);
int (*decompress)(struct squashfs_sb_info *msblk, struct bio *bio,
int offset, int length, struct squashfs_page_actor *output);
int (*max_decompressors)(void);
};

#ifdef CONFIG_SQUASHFS_DECOMP_SINGLE
extern const struct squashfs_decompressor_thread_ops squashfs_decompressor_single;
#endif
#ifdef CONFIG_SQUASHFS_DECOMP_MULTI
extern const struct squashfs_decompressor_thread_ops squashfs_decompressor_multi;
#endif
#ifdef CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU
extern const struct squashfs_decompressor_thread_ops squashfs_decompressor_percpu;
#endif

/* export.c */
extern __le64 *squashfs_read_inode_lookup_table(struct super_block *, u64, u64,
Expand Down
3 changes: 2 additions & 1 deletion fs/squashfs/squashfs_fs_sb.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ struct squashfs_sb_info {
__le64 *xattr_id_table;
struct mutex meta_index_mutex;
struct meta_index *meta_index;
struct squashfs_stream *stream;
void *stream;
__le64 *inode_lookup_table;
u64 inode_table;
u64 directory_table;
Expand All @@ -66,5 +66,6 @@ struct squashfs_sb_info {
int xattr_ids;
unsigned int ids;
bool panic_on_errors;
const struct squashfs_decompressor_thread_ops *thread_ops;
};
#endif
Loading

0 comments on commit b064577

Please sign in to comment.