Skip to content

Commit 80f7840

Browse files
nixiaomingakpm00
authored andcommitted
squashfs: add the mount parameter theads=<single|multi|percpu>
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/[email protected] Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Xiaoming Ni <[email protected]> Reviewed-by: Phillip Lougher <[email protected]> Cc: Jianguo Chen <[email protected]> Cc: Jubin Zhong <[email protected]> Cc: Zhang Yi <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent 4197530 commit 80f7840

9 files changed

+147
-32
lines changed

fs/squashfs/Kconfig

+34-5
Original file line numberDiff line numberDiff line change
@@ -54,25 +54,54 @@ config SQUASHFS_FILE_DIRECT
5454

5555
endchoice
5656

57+
config SQUASHFS_DECOMP_SINGLE
58+
depends on SQUASHFS
59+
def_bool n
60+
61+
config SQUASHFS_DECOMP_MULTI
62+
depends on SQUASHFS
63+
def_bool n
64+
65+
config SQUASHFS_DECOMP_MULTI_PERCPU
66+
depends on SQUASHFS
67+
def_bool n
68+
69+
config SQUASHFS_CHOICE_DECOMP_BY_MOUNT
70+
bool "Select the parallel decompression mode during mount"
71+
depends on SQUASHFS
72+
default n
73+
select SQUASHFS_DECOMP_SINGLE
74+
select SQUASHFS_DECOMP_MULTI
75+
select SQUASHFS_DECOMP_MULTI_PERCPU
76+
help
77+
Compile all parallel decompression modes and specify the
78+
decompression mode by setting "threads=" during mount.
79+
threads=<single|multi|percpu>
80+
81+
default Decompressor parallelisation is SQUASHFS_DECOMP_SINGLE
82+
5783
choice
58-
prompt "Decompressor parallelisation options"
84+
prompt "Select decompression parallel mode at compile time"
5985
depends on SQUASHFS
86+
depends on !SQUASHFS_CHOICE_DECOMP_BY_MOUNT
6087
help
6188
Squashfs now supports three parallelisation options for
6289
decompression. Each one exhibits various trade-offs between
6390
decompression performance and CPU and memory usage.
6491

6592
If in doubt, select "Single threaded compression"
6693

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

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

88-
config SQUASHFS_DECOMP_MULTI_PERCPU
117+
config SQUASHFS_COMPILE_DECOMP_MULTI_PERCPU
89118
bool "Use percpu multiple decompressors for parallel I/O"
119+
select SQUASHFS_DECOMP_MULTI_PERCPU
90120
help
91121
By default Squashfs uses a single decompressor but it gives
92122
poor performance on parallel I/O workloads when using multiple CPU
@@ -95,7 +125,6 @@ config SQUASHFS_DECOMP_MULTI_PERCPU
95125
This decompressor implementation uses a maximum of one
96126
decompressor per core. It uses percpu variables to ensure
97127
decompression is load-balanced across the cores.
98-
99128
endchoice
100129

101130
config SQUASHFS_XATTR

fs/squashfs/block.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ int squashfs_read_data(struct super_block *sb, u64 index, int length,
216216
res = -EIO;
217217
goto out_free_bio;
218218
}
219-
res = squashfs_decompress(msblk, bio, offset, length, output);
219+
res = msblk->thread_ops->decompress(msblk, bio, offset, length, output);
220220
} else {
221221
res = copy_bio_to_actor(bio, output, offset, length);
222222
}

fs/squashfs/decompressor.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ void *squashfs_decompressor_setup(struct super_block *sb, unsigned short flags)
134134
if (IS_ERR(comp_opts))
135135
return comp_opts;
136136

137-
stream = squashfs_decompressor_create(msblk, comp_opts);
137+
stream = msblk->thread_ops->create(msblk, comp_opts);
138138
if (IS_ERR(stream))
139139
kfree(comp_opts);
140140

fs/squashfs/decompressor_multi.c

+11-5
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,11 @@
2929
#define MAX_DECOMPRESSOR (num_online_cpus() * 2)
3030

3131

32-
int squashfs_max_decompressors(void)
32+
static int squashfs_max_decompressors(void)
3333
{
3434
return MAX_DECOMPRESSOR;
3535
}
3636

37-
3837
struct squashfs_stream {
3938
void *comp_opts;
4039
struct list_head strm_list;
@@ -59,7 +58,7 @@ static void put_decomp_stream(struct decomp_stream *decomp_strm,
5958
wake_up(&stream->wait);
6059
}
6160

62-
void *squashfs_decompressor_create(struct squashfs_sb_info *msblk,
61+
static void *squashfs_decompressor_create(struct squashfs_sb_info *msblk,
6362
void *comp_opts)
6463
{
6564
struct squashfs_stream *stream;
@@ -103,7 +102,7 @@ void *squashfs_decompressor_create(struct squashfs_sb_info *msblk,
103102
}
104103

105104

106-
void squashfs_decompressor_destroy(struct squashfs_sb_info *msblk)
105+
static void squashfs_decompressor_destroy(struct squashfs_sb_info *msblk)
107106
{
108107
struct squashfs_stream *stream = msblk->stream;
109108
if (stream) {
@@ -180,7 +179,7 @@ static struct decomp_stream *get_decomp_stream(struct squashfs_sb_info *msblk,
180179
}
181180

182181

183-
int squashfs_decompress(struct squashfs_sb_info *msblk, struct bio *bio,
182+
static int squashfs_decompress(struct squashfs_sb_info *msblk, struct bio *bio,
184183
int offset, int length,
185184
struct squashfs_page_actor *output)
186185
{
@@ -195,3 +194,10 @@ int squashfs_decompress(struct squashfs_sb_info *msblk, struct bio *bio,
195194
msblk->decompressor->name);
196195
return res;
197196
}
197+
198+
const struct squashfs_decompressor_thread_ops squashfs_decompressor_multi = {
199+
.create = squashfs_decompressor_create,
200+
.destroy = squashfs_decompressor_destroy,
201+
.decompress = squashfs_decompress,
202+
.max_decompressors = squashfs_max_decompressors,
203+
};

fs/squashfs/decompressor_multi_percpu.c

+16-7
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ struct squashfs_stream {
2525
local_lock_t lock;
2626
};
2727

28-
void *squashfs_decompressor_create(struct squashfs_sb_info *msblk,
28+
static void *squashfs_decompressor_create(struct squashfs_sb_info *msblk,
2929
void *comp_opts)
3030
{
3131
struct squashfs_stream *stream;
@@ -59,7 +59,7 @@ void *squashfs_decompressor_create(struct squashfs_sb_info *msblk,
5959
return ERR_PTR(err);
6060
}
6161

62-
void squashfs_decompressor_destroy(struct squashfs_sb_info *msblk)
62+
static void squashfs_decompressor_destroy(struct squashfs_sb_info *msblk)
6363
{
6464
struct squashfs_stream __percpu *percpu =
6565
(struct squashfs_stream __percpu *) msblk->stream;
@@ -75,19 +75,21 @@ void squashfs_decompressor_destroy(struct squashfs_sb_info *msblk)
7575
}
7676
}
7777

78-
int squashfs_decompress(struct squashfs_sb_info *msblk, struct bio *bio,
78+
static int squashfs_decompress(struct squashfs_sb_info *msblk, struct bio *bio,
7979
int offset, int length, struct squashfs_page_actor *output)
8080
{
8181
struct squashfs_stream *stream;
82+
struct squashfs_stream __percpu *percpu =
83+
(struct squashfs_stream __percpu *) msblk->stream;
8284
int res;
8385

84-
local_lock(&msblk->stream->lock);
85-
stream = this_cpu_ptr(msblk->stream);
86+
local_lock(&percpu->lock);
87+
stream = this_cpu_ptr(percpu);
8688

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

90-
local_unlock(&msblk->stream->lock);
92+
local_unlock(&percpu->lock);
9193

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

99-
int squashfs_max_decompressors(void)
101+
static int squashfs_max_decompressors(void)
100102
{
101103
return num_possible_cpus();
102104
}
105+
106+
const struct squashfs_decompressor_thread_ops squashfs_decompressor_percpu = {
107+
.create = squashfs_decompressor_create,
108+
.destroy = squashfs_decompressor_destroy,
109+
.decompress = squashfs_decompress,
110+
.max_decompressors = squashfs_max_decompressors,
111+
};

fs/squashfs/decompressor_single.c

+11-4
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ struct squashfs_stream {
2424
struct mutex mutex;
2525
};
2626

27-
void *squashfs_decompressor_create(struct squashfs_sb_info *msblk,
27+
static void *squashfs_decompressor_create(struct squashfs_sb_info *msblk,
2828
void *comp_opts)
2929
{
3030
struct squashfs_stream *stream;
@@ -49,7 +49,7 @@ void *squashfs_decompressor_create(struct squashfs_sb_info *msblk,
4949
return ERR_PTR(err);
5050
}
5151

52-
void squashfs_decompressor_destroy(struct squashfs_sb_info *msblk)
52+
static void squashfs_decompressor_destroy(struct squashfs_sb_info *msblk)
5353
{
5454
struct squashfs_stream *stream = msblk->stream;
5555

@@ -59,7 +59,7 @@ void squashfs_decompressor_destroy(struct squashfs_sb_info *msblk)
5959
}
6060
}
6161

62-
int squashfs_decompress(struct squashfs_sb_info *msblk, struct bio *bio,
62+
static int squashfs_decompress(struct squashfs_sb_info *msblk, struct bio *bio,
6363
int offset, int length,
6464
struct squashfs_page_actor *output)
6565
{
@@ -78,7 +78,14 @@ int squashfs_decompress(struct squashfs_sb_info *msblk, struct bio *bio,
7878
return res;
7979
}
8080

81-
int squashfs_max_decompressors(void)
81+
static int squashfs_max_decompressors(void)
8282
{
8383
return 1;
8484
}
85+
86+
const struct squashfs_decompressor_thread_ops squashfs_decompressor_single = {
87+
.create = squashfs_decompressor_create,
88+
.destroy = squashfs_decompressor_destroy,
89+
.decompress = squashfs_decompress,
90+
.max_decompressors = squashfs_max_decompressors,
91+
};

fs/squashfs/squashfs.h

+18-5
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,24 @@ extern const struct squashfs_decompressor *squashfs_lookup_decompressor(int);
3838
extern void *squashfs_decompressor_setup(struct super_block *, unsigned short);
3939

4040
/* decompressor_xxx.c */
41-
extern void *squashfs_decompressor_create(struct squashfs_sb_info *, void *);
42-
extern void squashfs_decompressor_destroy(struct squashfs_sb_info *);
43-
extern int squashfs_decompress(struct squashfs_sb_info *, struct bio *,
44-
int, int, struct squashfs_page_actor *);
45-
extern int squashfs_max_decompressors(void);
41+
42+
struct squashfs_decompressor_thread_ops {
43+
void * (*create)(struct squashfs_sb_info *msblk, void *comp_opts);
44+
void (*destroy)(struct squashfs_sb_info *msblk);
45+
int (*decompress)(struct squashfs_sb_info *msblk, struct bio *bio,
46+
int offset, int length, struct squashfs_page_actor *output);
47+
int (*max_decompressors)(void);
48+
};
49+
50+
#ifdef CONFIG_SQUASHFS_DECOMP_SINGLE
51+
extern const struct squashfs_decompressor_thread_ops squashfs_decompressor_single;
52+
#endif
53+
#ifdef CONFIG_SQUASHFS_DECOMP_MULTI
54+
extern const struct squashfs_decompressor_thread_ops squashfs_decompressor_multi;
55+
#endif
56+
#ifdef CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU
57+
extern const struct squashfs_decompressor_thread_ops squashfs_decompressor_percpu;
58+
#endif
4659

4760
/* export.c */
4861
extern __le64 *squashfs_read_inode_lookup_table(struct super_block *, u64, u64,

fs/squashfs/squashfs_fs_sb.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ struct squashfs_sb_info {
5353
__le64 *xattr_id_table;
5454
struct mutex meta_index_mutex;
5555
struct meta_index *meta_index;
56-
struct squashfs_stream *stream;
56+
void *stream;
5757
__le64 *inode_lookup_table;
5858
u64 inode_table;
5959
u64 directory_table;
@@ -66,5 +66,6 @@ struct squashfs_sb_info {
6666
int xattr_ids;
6767
unsigned int ids;
6868
bool panic_on_errors;
69+
const struct squashfs_decompressor_thread_ops *thread_ops;
6970
};
7071
#endif

0 commit comments

Comments
 (0)