Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

squashfs: allows users to configure the number of decompression threads

The maximum number of threads in the decompressor_multi.c file is fixed
and cannot be adjusted according to user needs. Therefore, the mount
parameter needs to be added to allow users to configure the number of
threads as required. The upper limit is num_online_cpus() * 2.

Link: https://lkml.kernel.org/r/20221019030930.130456-3-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>

authored by

Xiaoming Ni and committed by
Andrew Morton
fb40fe04 80f78409

+66 -10
+14 -2
fs/squashfs/Kconfig
··· 73 73 select SQUASHFS_DECOMP_SINGLE 74 74 select SQUASHFS_DECOMP_MULTI 75 75 select SQUASHFS_DECOMP_MULTI_PERCPU 76 + select SQUASHFS_MOUNT_DECOMP_THREADS 76 77 help 77 78 Compile all parallel decompression modes and specify the 78 79 decompression mode by setting "threads=" during mount. 79 - threads=<single|multi|percpu> 80 - 81 80 default Decompressor parallelisation is SQUASHFS_DECOMP_SINGLE 82 81 83 82 choice ··· 125 126 decompressor per core. It uses percpu variables to ensure 126 127 decompression is load-balanced across the cores. 127 128 endchoice 129 + 130 + config SQUASHFS_MOUNT_DECOMP_THREADS 131 + bool "Add the mount parameter 'threads=' for squashfs" 132 + depends on SQUASHFS 133 + depends on SQUASHFS_DECOMP_MULTI 134 + default n 135 + help 136 + Use threads= to set the decompression parallel mode and the number of threads. 137 + If SQUASHFS_CHOICE_DECOMP_BY_MOUNT=y 138 + threads=<single|multi|percpu|1|2|3|...> 139 + else 140 + threads=<2|3|...> 141 + The upper limit is num_online_cpus() * 2. 128 142 129 143 config SQUASHFS_XATTR 130 144 bool "Squashfs XATTR support"
+2 -2
fs/squashfs/decompressor_multi.c
··· 144 144 * If there is no available decomp and already full, 145 145 * let's wait for releasing decomp from other users. 146 146 */ 147 - if (stream->avail_decomp >= MAX_DECOMPRESSOR) 147 + if (stream->avail_decomp >= msblk->max_thread_num) 148 148 goto wait; 149 149 150 150 /* Let's allocate new decomp */ ··· 160 160 } 161 161 162 162 stream->avail_decomp++; 163 - WARN_ON(stream->avail_decomp > MAX_DECOMPRESSOR); 163 + WARN_ON(stream->avail_decomp > msblk->max_thread_num); 164 164 165 165 mutex_unlock(&stream->mutex); 166 166 break;
+1
fs/squashfs/squashfs_fs_sb.h
··· 67 67 unsigned int ids; 68 68 bool panic_on_errors; 69 69 const struct squashfs_decompressor_thread_ops *thread_ops; 70 + int max_thread_num; 70 71 }; 71 72 #endif
+49 -6
fs/squashfs/super.c
··· 53 53 struct squashfs_mount_opts { 54 54 enum Opt_errors errors; 55 55 const struct squashfs_decompressor_thread_ops *thread_ops; 56 + int thread_num; 56 57 }; 57 58 58 59 static const struct constant_table squashfs_param_errors[] = { ··· 68 67 {} 69 68 }; 70 69 71 - static int squashfs_parse_param_threads(const char *str, struct squashfs_mount_opts *opts) 70 + 71 + static int squashfs_parse_param_threads_str(const char *str, struct squashfs_mount_opts *opts) 72 72 { 73 73 #ifdef CONFIG_SQUASHFS_CHOICE_DECOMP_BY_MOUNT 74 74 if (strcmp(str, "single") == 0) { ··· 86 84 } 87 85 #endif 88 86 return -EINVAL; 87 + } 88 + 89 + static int squashfs_parse_param_threads_num(const char *str, struct squashfs_mount_opts *opts) 90 + { 91 + #ifdef CONFIG_SQUASHFS_MOUNT_DECOMP_THREADS 92 + int ret; 93 + unsigned long num; 94 + 95 + ret = kstrtoul(str, 0, &num); 96 + if (ret != 0) 97 + return -EINVAL; 98 + if (num > 1) { 99 + opts->thread_ops = &squashfs_decompressor_multi; 100 + if (num > opts->thread_ops->max_decompressors()) 101 + return -EINVAL; 102 + opts->thread_num = (int)num; 103 + return 0; 104 + } 105 + #ifdef CONFIG_SQUASHFS_DECOMP_SINGLE 106 + if (num == 1) { 107 + opts->thread_ops = &squashfs_decompressor_single; 108 + opts->thread_num = 1; 109 + return 0; 110 + } 111 + #endif 112 + #endif /* !CONFIG_SQUASHFS_MOUNT_DECOMP_THREADS */ 113 + return -EINVAL; 114 + } 115 + 116 + static int squashfs_parse_param_threads(const char *str, struct squashfs_mount_opts *opts) 117 + { 118 + int ret = squashfs_parse_param_threads_str(str, opts); 119 + 120 + if (ret == 0) 121 + return ret; 122 + return squashfs_parse_param_threads_num(str, opts); 89 123 } 90 124 91 125 static int squashfs_parse_param(struct fs_context *fc, struct fs_parameter *param) ··· 232 194 goto failed_mount; 233 195 } 234 196 msblk->thread_ops = opts->thread_ops; 197 + if (opts->thread_num == 0) { 198 + msblk->max_thread_num = msblk->thread_ops->max_decompressors(); 199 + } else { 200 + msblk->max_thread_num = opts->thread_num; 201 + } 235 202 236 203 /* Check the MAJOR & MINOR versions and lookup compression type */ 237 204 msblk->decompressor = supported_squashfs_filesystem( ··· 322 279 323 280 /* Allocate read_page block */ 324 281 msblk->read_page = squashfs_cache_init("data", 325 - msblk->thread_ops->max_decompressors(), msblk->block_size); 282 + msblk->max_thread_num, msblk->block_size); 326 283 if (msblk->read_page == NULL) { 327 284 errorf(fc, "Failed to allocate read_page block"); 328 285 goto failed_mount; ··· 510 467 seq_puts(s, ",threads=single"); 511 468 return 0; 512 469 } 513 - if (msblk->thread_ops == &squashfs_decompressor_multi) { 514 - seq_puts(s, ",threads=multi"); 515 - return 0; 516 - } 517 470 if (msblk->thread_ops == &squashfs_decompressor_percpu) { 518 471 seq_puts(s, ",threads=percpu"); 519 472 return 0; 520 473 } 474 + #endif 475 + #ifdef CONFIG_SQUASHFS_MOUNT_DECOMP_THREADS 476 + seq_printf(s, ",threads=%d", msblk->max_thread_num); 521 477 #endif 522 478 return 0; 523 479 } ··· 538 496 #else 539 497 #error "fail: unknown squashfs decompression thread mode?" 540 498 #endif 499 + opts->thread_num = 0; 541 500 fc->fs_private = opts; 542 501 fc->ops = &squashfs_context_ops; 543 502 return 0;