linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/2] squashfs: Add the mount parameter "threads="
@ 2022-08-15  3:10 Xiaoming Ni
  2022-08-15  3:10 ` [PATCH 1/2] squashfs: add the mount parameter theads=<single|multi|percpu> Xiaoming Ni
                   ` (2 more replies)
  0 siblings, 3 replies; 38+ messages in thread
From: Xiaoming Ni @ 2022-08-15  3:10 UTC (permalink / raw)
  To: linux-kernel, phillip
  Cc: nixiaoming, wangle6, yi.zhang, wangbing6, zhongjubin, chenjianguo3

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.

Xiaoming Ni (2):
  squashfs: add the mount parameter theads=<single|multi|percpu>
  squashfs: Allows users to configure the number of decompression
    threads.

 fs/squashfs/Kconfig                     | 24 ++++++++--
 fs/squashfs/decompressor_multi.c        | 32 ++++++++------
 fs/squashfs/decompressor_multi_percpu.c | 37 ++++++++++------
 fs/squashfs/decompressor_single.c       | 23 ++++++----
 fs/squashfs/squashfs.h                  | 39 ++++++++++++++---
 fs/squashfs/squashfs_fs_sb.h            |  4 +-
 fs/squashfs/super.c                     | 77 ++++++++++++++++++++++++++++++++-
 7 files changed, 191 insertions(+), 45 deletions(-)

-- 
2.12.3


^ permalink raw reply	[flat|nested] 38+ messages in thread

* [PATCH 1/2] squashfs: add the mount parameter theads=<single|multi|percpu>
  2022-08-15  3:10 [PATCH 0/2] squashfs: Add the mount parameter "threads=" Xiaoming Ni
@ 2022-08-15  3:10 ` Xiaoming Ni
  2022-08-15 11:19   ` kernel test robot
  2022-08-15  3:11 ` [PATCH 2/2] squashfs: Allows users to configure the number of decompression threads Xiaoming Ni
  2022-08-16  1:00 ` [PATCH v2 0/2] squashfs: Add the mount parameter "threads=" Xiaoming Ni
  2 siblings, 1 reply; 38+ messages in thread
From: Xiaoming Ni @ 2022-08-15  3:10 UTC (permalink / raw)
  To: linux-kernel, phillip
  Cc: nixiaoming, wangle6, yi.zhang, wangbing6, zhongjubin, chenjianguo3

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.

Signed-off-by: Xiaoming Ni <nixiaoming@huawei.com>
---
 fs/squashfs/Kconfig                     | 20 ++++++++++--
 fs/squashfs/decompressor_multi.c        | 28 +++++++++-------
 fs/squashfs/decompressor_multi_percpu.c | 37 +++++++++++++--------
 fs/squashfs/decompressor_single.c       | 23 ++++++++-----
 fs/squashfs/squashfs.h                  | 39 +++++++++++++++++++---
 fs/squashfs/squashfs_fs_sb.h            |  3 +-
 fs/squashfs/super.c                     | 58 ++++++++++++++++++++++++++++++++-
 7 files changed, 166 insertions(+), 42 deletions(-)

diff --git a/fs/squashfs/Kconfig b/fs/squashfs/Kconfig
index 916e78fabcaa..af9f8c41f2de 100644
--- a/fs/squashfs/Kconfig
+++ b/fs/squashfs/Kconfig
@@ -55,7 +55,7 @@ config SQUASHFS_FILE_DIRECT
 endchoice
 
 choice
-	prompt "Decompressor parallelisation options"
+	prompt "default Decompressor parallelisation options"
 	depends on SQUASHFS
 	help
 	  Squashfs now supports three parallelisation options for
@@ -64,8 +64,23 @@ choice
 
 	  If in doubt, select "Single threaded compression"
 
+	config SQUASHFS_DECOMP_DEFAULT_SINGLE
+	bool "Single threaded compression"
+	select SQUASHFS_DECOMP_SINGLE
+
+	config SQUASHFS_DECOMP_DEFAULT_MULTI
+	bool "Use multiple decompressors for parallel I/O"
+	select SQUASHFS_DECOMP_MULTI
+
+	config SQUASHFS_DECOMP_DEFAULT_PERCPU
+	bool "Use percpu multiple decompressors for parallel I/O"
+	select SQUASHFS_DECOMP_MULTI_PERCPU
+
+endchoice
+
 config SQUASHFS_DECOMP_SINGLE
 	bool "Single threaded compression"
+	depends on SQUASHFS
 	help
 	  Traditionally Squashfs has used single-threaded decompression.
 	  Only one block (data or metadata) can be decompressed at any
@@ -73,6 +88,7 @@ config SQUASHFS_DECOMP_SINGLE
 
 config SQUASHFS_DECOMP_MULTI
 	bool "Use multiple decompressors for parallel I/O"
+	depends on SQUASHFS
 	help
 	  By default Squashfs uses a single decompressor but it gives
 	  poor performance on parallel I/O workloads when using multiple CPU
@@ -87,6 +103,7 @@ config SQUASHFS_DECOMP_MULTI
 
 config SQUASHFS_DECOMP_MULTI_PERCPU
 	bool "Use percpu multiple decompressors for parallel I/O"
+	depends on SQUASHFS
 	help
 	  By default Squashfs uses a single decompressor but it gives
 	  poor performance on parallel I/O workloads when using multiple CPU
@@ -96,7 +113,6 @@ config SQUASHFS_DECOMP_MULTI_PERCPU
 	  decompressor per core.  It uses percpu variables to ensure
 	  decompression is load-balanced across the cores.
 
-endchoice
 
 config SQUASHFS_XATTR
 	bool "Squashfs XATTR support"
diff --git a/fs/squashfs/decompressor_multi.c b/fs/squashfs/decompressor_multi.c
index db9f12a3ea05..7b2723b77e75 100644
--- a/fs/squashfs/decompressor_multi.c
+++ b/fs/squashfs/decompressor_multi.c
@@ -29,13 +29,12 @@
 #define MAX_DECOMPRESSOR	(num_online_cpus() * 2)
 
 
-int squashfs_max_decompressors(void)
+static int squashfs_max_decompressors_multi(void)
 {
 	return MAX_DECOMPRESSOR;
 }
 
-
-struct squashfs_stream {
+struct squashfs_stream_multi {
 	void			*comp_opts;
 	struct list_head	strm_list;
 	struct mutex		mutex;
@@ -51,7 +50,7 @@ struct decomp_stream {
 
 
 static void put_decomp_stream(struct decomp_stream *decomp_strm,
-				struct squashfs_stream *stream)
+				struct squashfs_stream_multi *stream)
 {
 	mutex_lock(&stream->mutex);
 	list_add(&decomp_strm->list, &stream->strm_list);
@@ -59,10 +58,10 @@ 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_multi(struct squashfs_sb_info *msblk,
 				void *comp_opts)
 {
-	struct squashfs_stream *stream;
+	struct squashfs_stream_multi *stream;
 	struct decomp_stream *decomp_strm = NULL;
 	int err = -ENOMEM;
 
@@ -103,9 +102,9 @@ void *squashfs_decompressor_create(struct squashfs_sb_info *msblk,
 }
 
 
-void squashfs_decompressor_destroy(struct squashfs_sb_info *msblk)
+static void squashfs_decompressor_destroy_multi(struct squashfs_sb_info *msblk)
 {
-	struct squashfs_stream *stream = msblk->stream;
+	struct squashfs_stream_multi *stream = msblk->stream;
 	if (stream) {
 		struct decomp_stream *decomp_strm;
 
@@ -125,7 +124,7 @@ void squashfs_decompressor_destroy(struct squashfs_sb_info *msblk)
 
 
 static struct decomp_stream *get_decomp_stream(struct squashfs_sb_info *msblk,
-					struct squashfs_stream *stream)
+					struct squashfs_stream_multi *stream)
 {
 	struct decomp_stream *decomp_strm;
 
@@ -180,12 +179,12 @@ 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_multi(struct squashfs_sb_info *msblk, struct bio *bio,
 			int offset, int length,
 			struct squashfs_page_actor *output)
 {
 	int res;
-	struct squashfs_stream *stream = msblk->stream;
+	struct squashfs_stream_multi *stream = msblk->stream;
 	struct decomp_stream *decomp_stream = get_decomp_stream(msblk, stream);
 	res = msblk->decompressor->decompress(msblk, decomp_stream->stream,
 		bio, offset, length, output);
@@ -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_multi,
+	.destroy = squashfs_decompressor_destroy_multi,
+	.decompress = squashfs_decompress_multi,
+	.max_decompressors = squashfs_max_decompressors_multi,
+};
diff --git a/fs/squashfs/decompressor_multi_percpu.c b/fs/squashfs/decompressor_multi_percpu.c
index b881b9283b7f..2d540bb13970 100644
--- a/fs/squashfs/decompressor_multi_percpu.c
+++ b/fs/squashfs/decompressor_multi_percpu.c
@@ -20,19 +20,19 @@
  * variables, one thread per cpu core.
  */
 
-struct squashfs_stream {
+struct squashfs_stream_percpu {
 	void			*stream;
 	local_lock_t	lock;
 };
 
-void *squashfs_decompressor_create(struct squashfs_sb_info *msblk,
+static void *squashfs_decompressor_create_percpu(struct squashfs_sb_info *msblk,
 						void *comp_opts)
 {
-	struct squashfs_stream *stream;
-	struct squashfs_stream __percpu *percpu;
+	struct squashfs_stream_percpu *stream;
+	struct squashfs_stream_percpu __percpu *percpu;
 	int err, cpu;
 
-	percpu = alloc_percpu(struct squashfs_stream);
+	percpu = alloc_percpu(struct squashfs_stream_percpu);
 	if (percpu == NULL)
 		return ERR_PTR(-ENOMEM);
 
@@ -59,11 +59,11 @@ 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_percpu(struct squashfs_sb_info *msblk)
 {
-	struct squashfs_stream __percpu *percpu =
-			(struct squashfs_stream __percpu *) msblk->stream;
-	struct squashfs_stream *stream;
+	struct squashfs_stream_percpu __percpu *percpu =
+			(struct squashfs_stream_percpu __percpu *) msblk->stream;
+	struct squashfs_stream_percpu *stream;
 	int cpu;
 
 	if (msblk->stream) {
@@ -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_percpu(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 *stream;
 	int res;
 
-	local_lock(&msblk->stream->lock);
+	preempt_disable();
 	stream = this_cpu_ptr(msblk->stream);
+	local_lock(&stream->lock);
 
 	res = msblk->decompressor->decompress(msblk, stream->stream, bio,
 					      offset, length, output);
 
-	local_unlock(&msblk->stream->lock);
+	local_unlock(&stream->lock);
+	preempt_enable();
 
 	if (res < 0)
 		ERROR("%s decompression failed, data probably corrupt\n",
@@ -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_percpu(void)
 {
 	return num_possible_cpus();
 }
+
+const struct squashfs_decompressor_thread_ops squashfs_decompressor_percpu = {
+	.create = squashfs_decompressor_create_percpu,
+	.destroy = squashfs_decompressor_destroy_percpu,
+	.decompress = squashfs_decompress_percpu,
+	.max_decompressors = squashfs_max_decompressors_percpu,
+};
diff --git a/fs/squashfs/decompressor_single.c b/fs/squashfs/decompressor_single.c
index 4eb3d083d45e..41449de0ea4c 100644
--- a/fs/squashfs/decompressor_single.c
+++ b/fs/squashfs/decompressor_single.c
@@ -19,15 +19,15 @@
  * decompressor framework
  */
 
-struct squashfs_stream {
+struct squashfs_stream_single {
 	void		*stream;
 	struct mutex	mutex;
 };
 
-void *squashfs_decompressor_create(struct squashfs_sb_info *msblk,
+static void *squashfs_decompressor_create_single(struct squashfs_sb_info *msblk,
 						void *comp_opts)
 {
-	struct squashfs_stream *stream;
+	struct squashfs_stream_single *stream;
 	int err = -ENOMEM;
 
 	stream = kmalloc(sizeof(*stream), GFP_KERNEL);
@@ -49,9 +49,9 @@ 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_single(struct squashfs_sb_info *msblk)
 {
-	struct squashfs_stream *stream = msblk->stream;
+	struct squashfs_stream_single *stream = msblk->stream;
 
 	if (stream) {
 		msblk->decompressor->free(stream->stream);
@@ -59,12 +59,12 @@ void squashfs_decompressor_destroy(struct squashfs_sb_info *msblk)
 	}
 }
 
-int squashfs_decompress(struct squashfs_sb_info *msblk, struct bio *bio,
+static int squashfs_decompress_single(struct squashfs_sb_info *msblk, struct bio *bio,
 			int offset, int length,
 			struct squashfs_page_actor *output)
 {
 	int res;
-	struct squashfs_stream *stream = msblk->stream;
+	struct squashfs_stream_single *stream = msblk->stream;
 
 	mutex_lock(&stream->mutex);
 	res = msblk->decompressor->decompress(msblk, stream->stream, bio,
@@ -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_single(void)
 {
 	return 1;
 }
+
+const struct squashfs_decompressor_thread_ops squashfs_decompressor_single = {
+	.create = squashfs_decompressor_create_single,
+	.destroy = squashfs_decompressor_destroy_single,
+	.decompress = squashfs_decompress_single,
+	.max_decompressors = squashfs_max_decompressors_single,
+};
diff --git a/fs/squashfs/squashfs.h b/fs/squashfs/squashfs.h
index 9783e01c8100..514cba134f11 100644
--- a/fs/squashfs/squashfs.h
+++ b/fs/squashfs/squashfs.h
@@ -38,11 +38,40 @@ 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
+
+static inline void *squashfs_decompressor_create(struct squashfs_sb_info *msblk, void *comp_opts)
+{
+	return msblk->thread_ops->create(msblk, comp_opts);
+}
+
+static inline void squashfs_decompressor_destroy(struct squashfs_sb_info *msblk)
+{
+	msblk->thread_ops->destroy(msblk);
+}
+
+static inline int squashfs_decompress(struct squashfs_sb_info *msblk, struct bio *bio,
+				      int offset, int length, struct squashfs_page_actor *output)
+{
+	return msblk->thread_ops->decompress(msblk, bio, offset, length, output);
+}
 
 /* export.c */
 extern __le64 *squashfs_read_inode_lookup_table(struct super_block *, u64, u64,
diff --git a/fs/squashfs/squashfs_fs_sb.h b/fs/squashfs/squashfs_fs_sb.h
index 1e90c2575f9b..f1e5dad8ae0a 100644
--- a/fs/squashfs/squashfs_fs_sb.h
+++ b/fs/squashfs/squashfs_fs_sb.h
@@ -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;
@@ -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
diff --git a/fs/squashfs/super.c b/fs/squashfs/super.c
index 32565dafa7f3..6fd44683a84b 100644
--- a/fs/squashfs/super.c
+++ b/fs/squashfs/super.c
@@ -47,10 +47,12 @@ enum Opt_errors {
 
 enum squashfs_param {
 	Opt_errors,
+	Opt_threads,
 };
 
 struct squashfs_mount_opts {
 	enum Opt_errors errors;
+	const struct squashfs_decompressor_thread_ops *thread_ops;
 };
 
 static const struct constant_table squashfs_param_errors[] = {
@@ -61,9 +63,33 @@ static const struct constant_table squashfs_param_errors[] = {
 
 static const struct fs_parameter_spec squashfs_fs_parameters[] = {
 	fsparam_enum("errors", Opt_errors, squashfs_param_errors),
+	fsparam_string("threads", Opt_threads),
 	{}
 };
 
+static int squashfs_parse_param_threads(const char *str, struct squashfs_mount_opts *opts)
+{
+#ifdef CONFIG_SQUASHFS_DECOMP_SINGLE
+	if (strcmp(str, "single") == 0) {
+		opts->thread_ops = &squashfs_decompressor_single;
+		return 0;
+	}
+#endif
+#ifdef CONFIG_SQUASHFS_DECOMP_MULTI
+	if (strcmp(str, "multi") == 0) {
+		opts->thread_ops = &squashfs_decompressor_multi;
+		return 0;
+	}
+#endif
+#ifdef CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU
+	if (strcmp(str, "percpu") == 0) {
+		opts->thread_ops = &squashfs_decompressor_percpu;
+		return 0;
+	}
+#endif
+	return -EINVAL;
+}
+
 static int squashfs_parse_param(struct fs_context *fc, struct fs_parameter *param)
 {
 	struct squashfs_mount_opts *opts = fc->fs_private;
@@ -78,6 +104,10 @@ static int squashfs_parse_param(struct fs_context *fc, struct fs_parameter *para
 	case Opt_errors:
 		opts->errors = result.uint_32;
 		break;
+	case Opt_threads:
+		if (squashfs_parse_param_threads(param->string, opts) != 0)
+			return -EINVAL;
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -167,6 +197,7 @@ static int squashfs_fill_super(struct super_block *sb, struct fs_context *fc)
 			       sb->s_bdev);
 		goto failed_mount;
 	}
+	msblk->thread_ops = opts->thread_ops;
 
 	/* Check the MAJOR & MINOR versions and lookup compression type */
 	msblk->decompressor = supported_squashfs_filesystem(
@@ -252,7 +283,7 @@ static int squashfs_fill_super(struct super_block *sb, struct fs_context *fc)
 
 	/* Allocate read_page block */
 	msblk->read_page = squashfs_cache_init("data",
-		squashfs_max_decompressors(), msblk->block_size);
+		msblk->thread_ops->max_decompressors(), msblk->block_size);
 	if (msblk->read_page == NULL) {
 		errorf(fc, "Failed to allocate read_page block");
 		goto failed_mount;
@@ -435,6 +466,24 @@ static int squashfs_show_options(struct seq_file *s, struct dentry *root)
 	else
 		seq_puts(s, ",errors=continue");
 
+#ifdef CONFIG_SQUASHFS_DECOMP_SINGLE
+	if (msblk->thread_ops == &squashfs_decompressor_single) {
+		seq_puts(s, ",threads=single");
+		return 0;
+	}
+#endif
+#ifdef CONFIG_SQUASHFS_DECOMP_MULTI
+	if (msblk->thread_ops == &squashfs_decompressor_multi) {
+		seq_puts(s, ",threads=multi");
+		return 0;
+	}
+#endif
+#ifdef CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU
+	if (msblk->thread_ops == &squashfs_decompressor_percpu) {
+		seq_puts(s, ",threads=percpu");
+		return 0;
+	}
+#endif
 	return 0;
 }
 
@@ -446,6 +495,13 @@ static int squashfs_init_fs_context(struct fs_context *fc)
 	if (!opts)
 		return -ENOMEM;
 
+#ifdef CONFIG_SQUASHFS_DECOMP_DEFAULT_SINGLE
+	opts->thread_ops = &squashfs_decompressor_single;
+#elif defined(CONFIG_SQUASHFS_DECOMP_DEFAULT_MULTI)
+	opts->thread_ops = &squashfs_decompressor_multi,
+#elif defined(CONFIG_SQUASHFS_DECOMP_DEFAULT_PERCPU)
+	opts->thread_ops = &squashfs_decompressor_percpu;
+#endif
 	fc->fs_private = opts;
 	fc->ops = &squashfs_context_ops;
 	return 0;
-- 
2.12.3


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH 2/2] squashfs: Allows users to configure the number of decompression threads.
  2022-08-15  3:10 [PATCH 0/2] squashfs: Add the mount parameter "threads=" Xiaoming Ni
  2022-08-15  3:10 ` [PATCH 1/2] squashfs: add the mount parameter theads=<single|multi|percpu> Xiaoming Ni
@ 2022-08-15  3:11 ` Xiaoming Ni
  2022-08-16  1:00 ` [PATCH v2 0/2] squashfs: Add the mount parameter "threads=" Xiaoming Ni
  2 siblings, 0 replies; 38+ messages in thread
From: Xiaoming Ni @ 2022-08-15  3:11 UTC (permalink / raw)
  To: linux-kernel, phillip
  Cc: nixiaoming, wangle6, yi.zhang, wangbing6, zhongjubin, chenjianguo3

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.

Signed-off-by: Xiaoming Ni <nixiaoming@huawei.com>
---
 fs/squashfs/Kconfig              |  4 +++-
 fs/squashfs/decompressor_multi.c |  4 ++--
 fs/squashfs/squashfs_fs_sb.h     |  1 +
 fs/squashfs/super.c              | 45 ++++++++++++++++++++++++++++------------
 4 files changed, 38 insertions(+), 16 deletions(-)

diff --git a/fs/squashfs/Kconfig b/fs/squashfs/Kconfig
index af9f8c41f2de..3f42b4099dc7 100644
--- a/fs/squashfs/Kconfig
+++ b/fs/squashfs/Kconfig
@@ -99,7 +99,9 @@ config SQUASHFS_DECOMP_MULTI
 
 	  This decompressor implementation uses up to two parallel
 	  decompressors per core.  It dynamically allocates decompressors
-	  on a demand basis.
+	  on a demand basis.  You can also set the number of threads by setting threads=<number> of
+	  the mount parameter.
+
 
 config SQUASHFS_DECOMP_MULTI_PERCPU
 	bool "Use percpu multiple decompressors for parallel I/O"
diff --git a/fs/squashfs/decompressor_multi.c b/fs/squashfs/decompressor_multi.c
index 7b2723b77e75..6d1cea325cca 100644
--- a/fs/squashfs/decompressor_multi.c
+++ b/fs/squashfs/decompressor_multi.c
@@ -144,7 +144,7 @@ static struct decomp_stream *get_decomp_stream(struct squashfs_sb_info *msblk,
 		 * If there is no available decomp and already full,
 		 * let's wait for releasing decomp from other users.
 		 */
-		if (stream->avail_decomp >= MAX_DECOMPRESSOR)
+		if (stream->avail_decomp >= msblk->max_thread_num)
 			goto wait;
 
 		/* Let's allocate new decomp */
@@ -160,7 +160,7 @@ static struct decomp_stream *get_decomp_stream(struct squashfs_sb_info *msblk,
 		}
 
 		stream->avail_decomp++;
-		WARN_ON(stream->avail_decomp > MAX_DECOMPRESSOR);
+		WARN_ON(stream->avail_decomp > msblk->max_thread_num);
 
 		mutex_unlock(&stream->mutex);
 		break;
diff --git a/fs/squashfs/squashfs_fs_sb.h b/fs/squashfs/squashfs_fs_sb.h
index f1e5dad8ae0a..659082e9e51d 100644
--- a/fs/squashfs/squashfs_fs_sb.h
+++ b/fs/squashfs/squashfs_fs_sb.h
@@ -67,5 +67,6 @@ struct squashfs_sb_info {
 	unsigned int				ids;
 	bool					panic_on_errors;
 	const struct squashfs_decompressor_thread_ops *thread_ops;
+	int					max_thread_num;
 };
 #endif
diff --git a/fs/squashfs/super.c b/fs/squashfs/super.c
index 6fd44683a84b..f3533e20d0b7 100644
--- a/fs/squashfs/super.c
+++ b/fs/squashfs/super.c
@@ -53,6 +53,7 @@ enum squashfs_param {
 struct squashfs_mount_opts {
 	enum Opt_errors errors;
 	const struct squashfs_decompressor_thread_ops *thread_ops;
+	int thread_num;
 };
 
 static const struct constant_table squashfs_param_errors[] = {
@@ -69,6 +70,8 @@ static const struct fs_parameter_spec squashfs_fs_parameters[] = {
 
 static int squashfs_parse_param_threads(const char *str, struct squashfs_mount_opts *opts)
 {
+	unsigned long num;
+	int ret;
 #ifdef CONFIG_SQUASHFS_DECOMP_SINGLE
 	if (strcmp(str, "single") == 0) {
 		opts->thread_ops = &squashfs_decompressor_single;
@@ -87,7 +90,24 @@ static int squashfs_parse_param_threads(const char *str, struct squashfs_mount_o
 		return 0;
 	}
 #endif
+	ret = kstrtoul(str, 0, &num);
+	if (ret != 0 || num == 0)
+		return -EINVAL;
+#ifdef CONFIG_SQUASHFS_DECOMP_SINGLE
+	if (num == 1) {
+		opts->thread_ops = &squashfs_decompressor_single;
+		return 0;
+	}
+#endif
+#ifdef CONFIG_SQUASHFS_DECOMP_MULTI
+	opts->thread_ops = &squashfs_decompressor_multi;
+	if (num > opts->thread_ops->max_decompressors())
+		num = opts->thread_ops->max_decompressors();
+	opts->thread_num = (int)num;
+	return 0;
+#else
 	return -EINVAL;
+#endif
 }
 
 static int squashfs_parse_param(struct fs_context *fc, struct fs_parameter *param)
@@ -198,6 +218,11 @@ static int squashfs_fill_super(struct super_block *sb, struct fs_context *fc)
 		goto failed_mount;
 	}
 	msblk->thread_ops = opts->thread_ops;
+	if (opts->thread_num == 0) {
+		msblk->max_thread_num = opts->thread_ops->max_decompressors();
+	} else {
+		msblk->max_thread_num = opts->thread_num;
+	}
 
 	/* Check the MAJOR & MINOR versions and lookup compression type */
 	msblk->decompressor = supported_squashfs_filesystem(
@@ -283,7 +308,7 @@ static int squashfs_fill_super(struct super_block *sb, struct fs_context *fc)
 
 	/* Allocate read_page block */
 	msblk->read_page = squashfs_cache_init("data",
-		msblk->thread_ops->max_decompressors(), msblk->block_size);
+		msblk->max_thread_num, msblk->block_size);
 	if (msblk->read_page == NULL) {
 		errorf(fc, "Failed to allocate read_page block");
 		goto failed_mount;
@@ -466,24 +491,17 @@ static int squashfs_show_options(struct seq_file *s, struct dentry *root)
 	else
 		seq_puts(s, ",errors=continue");
 
-#ifdef CONFIG_SQUASHFS_DECOMP_SINGLE
-	if (msblk->thread_ops == &squashfs_decompressor_single) {
-		seq_puts(s, ",threads=single");
-		return 0;
-	}
-#endif
-#ifdef CONFIG_SQUASHFS_DECOMP_MULTI
-	if (msblk->thread_ops == &squashfs_decompressor_multi) {
-		seq_puts(s, ",threads=multi");
-		return 0;
-	}
-#endif
 #ifdef CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU
+	/*
+	 * thread=percpu and thread=<number> have different configuration effects.
+	 * the parameters need to be treated differently when they are displayed.
+	 */
 	if (msblk->thread_ops == &squashfs_decompressor_percpu) {
 		seq_puts(s, ",threads=percpu");
 		return 0;
 	}
 #endif
+	seq_printf(s, ",threads=%u", msblk->max_thread_num);
 	return 0;
 }
 
@@ -502,6 +520,7 @@ static int squashfs_init_fs_context(struct fs_context *fc)
 #elif defined(CONFIG_SQUASHFS_DECOMP_DEFAULT_PERCPU)
 	opts->thread_ops = &squashfs_decompressor_percpu;
 #endif
+	opts->thread_num = 0;
 	fc->fs_private = opts;
 	fc->ops = &squashfs_context_ops;
 	return 0;
-- 
2.12.3


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* Re: [PATCH 1/2] squashfs: add the mount parameter theads=<single|multi|percpu>
  2022-08-15  3:10 ` [PATCH 1/2] squashfs: add the mount parameter theads=<single|multi|percpu> Xiaoming Ni
@ 2022-08-15 11:19   ` kernel test robot
  0 siblings, 0 replies; 38+ messages in thread
From: kernel test robot @ 2022-08-15 11:19 UTC (permalink / raw)
  To: Xiaoming Ni, linux-kernel, phillip
  Cc: kbuild-all, nixiaoming, wangle6, yi.zhang, wangbing6, zhongjubin,
	chenjianguo3

Hi Xiaoming,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on v6.0-rc1]
[also build test WARNING on linus/master next-20220815]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Xiaoming-Ni/squashfs-Add-the-mount-parameter-threads/20220815-111318
base:    568035b01cfb107af8d2e4bd2fb9aea22cf5b868
config: sparc-randconfig-s042-20220814 (https://download.01.org/0day-ci/archive/20220815/202208151921.Y0vJnA6c-lkp@intel.com/config)
compiler: sparc-linux-gcc (GCC) 12.1.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # apt-get install sparse
        # sparse version: v0.6.4-39-gce1a6720-dirty
        # https://github.com/intel-lab-lkp/linux/commit/dcb72eaed7732d884148ce37d23442956296d0d6
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Xiaoming-Ni/squashfs-Add-the-mount-parameter-threads/20220815-111318
        git checkout dcb72eaed7732d884148ce37d23442956296d0d6
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=sparc SHELL=/bin/bash fs/squashfs/

If you fix the issue, kindly add following tag where applicable
Reported-by: kernel test robot <lkp@intel.com>

sparse warnings: (new ones prefixed by >>)
>> fs/squashfs/decompressor_multi_percpu.c:85:18: sparse: sparse: incorrect type in initializer (different address spaces) @@     expected void const [noderef] __percpu *__vpp_verify @@     got void * @@
   fs/squashfs/decompressor_multi_percpu.c:85:18: sparse:     expected void const [noderef] __percpu *__vpp_verify
   fs/squashfs/decompressor_multi_percpu.c:85:18: sparse:     got void *
   fs/squashfs/decompressor_multi_percpu.c:86:9: sparse: sparse: incorrect type in initializer (different address spaces) @@     expected void const [noderef] __percpu *__vpp_verify @@     got struct local_lock_t * @@
   fs/squashfs/decompressor_multi_percpu.c:86:9: sparse:     expected void const [noderef] __percpu *__vpp_verify
   fs/squashfs/decompressor_multi_percpu.c:86:9: sparse:     got struct local_lock_t *
   fs/squashfs/decompressor_multi_percpu.c:91:9: sparse: sparse: incorrect type in initializer (different address spaces) @@     expected void const [noderef] __percpu *__vpp_verify @@     got struct local_lock_t * @@
   fs/squashfs/decompressor_multi_percpu.c:91:9: sparse:     expected void const [noderef] __percpu *__vpp_verify
   fs/squashfs/decompressor_multi_percpu.c:91:9: sparse:     got struct local_lock_t *

vim +85 fs/squashfs/decompressor_multi_percpu.c

d208383d640727 Phillip Lougher  2013-11-18   77  
dcb72eaed7732d Xiaoming Ni      2022-08-15   78  static int squashfs_decompress_percpu(struct squashfs_sb_info *msblk, struct bio *bio,
93e72b3c612adc Philippe Liard   2020-06-01   79  	int offset, int length, struct squashfs_page_actor *output)
d208383d640727 Phillip Lougher  2013-11-18   80  {
dcb72eaed7732d Xiaoming Ni      2022-08-15   81  	struct squashfs_stream_percpu *stream;
fd56200a16c72c Julia Cartwright 2020-05-27   82  	int res;
fd56200a16c72c Julia Cartwright 2020-05-27   83  
dcb72eaed7732d Xiaoming Ni      2022-08-15   84  	preempt_disable();
fd56200a16c72c Julia Cartwright 2020-05-27  @85  	stream = this_cpu_ptr(msblk->stream);
dcb72eaed7732d Xiaoming Ni      2022-08-15   86  	local_lock(&stream->lock);
fd56200a16c72c Julia Cartwright 2020-05-27   87  
93e72b3c612adc Philippe Liard   2020-06-01   88  	res = msblk->decompressor->decompress(msblk, stream->stream, bio,
846b730e99518a Phillip Lougher  2013-11-18   89  					      offset, length, output);
fd56200a16c72c Julia Cartwright 2020-05-27   90  
dcb72eaed7732d Xiaoming Ni      2022-08-15   91  	local_unlock(&stream->lock);
dcb72eaed7732d Xiaoming Ni      2022-08-15   92  	preempt_enable();
d208383d640727 Phillip Lougher  2013-11-18   93  
d208383d640727 Phillip Lougher  2013-11-18   94  	if (res < 0)
d208383d640727 Phillip Lougher  2013-11-18   95  		ERROR("%s decompression failed, data probably corrupt\n",
d208383d640727 Phillip Lougher  2013-11-18   96  			msblk->decompressor->name);
d208383d640727 Phillip Lougher  2013-11-18   97  
d208383d640727 Phillip Lougher  2013-11-18   98  	return res;
d208383d640727 Phillip Lougher  2013-11-18   99  }
d208383d640727 Phillip Lougher  2013-11-18  100  

-- 
0-DAY CI Kernel Test Service
https://01.org/lkp

^ permalink raw reply	[flat|nested] 38+ messages in thread

* [PATCH v2 0/2] squashfs: Add the mount parameter "threads="
  2022-08-15  3:10 [PATCH 0/2] squashfs: Add the mount parameter "threads=" Xiaoming Ni
  2022-08-15  3:10 ` [PATCH 1/2] squashfs: add the mount parameter theads=<single|multi|percpu> Xiaoming Ni
  2022-08-15  3:11 ` [PATCH 2/2] squashfs: Allows users to configure the number of decompression threads Xiaoming Ni
@ 2022-08-16  1:00 ` Xiaoming Ni
  2022-08-16  1:00   ` [PATCH v2 1/2] squashfs: add the mount parameter theads=<single|multi|percpu> Xiaoming Ni
                     ` (3 more replies)
  2 siblings, 4 replies; 38+ messages in thread
From: Xiaoming Ni @ 2022-08-16  1:00 UTC (permalink / raw)
  To: linux-kernel, phillip
  Cc: nixiaoming, wangle6, yi.zhang, wangbing6, zhongjubin, chenjianguo3

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.

v2: fix warning: sparse: incorrect type in initializer (different address spaces)
  Reported-by: kernel test robot <lkp@intel.com>

v1: https://lore.kernel.org/lkml/20220815031100.75243-1-nixiaoming@huawei.com/
----

Xiaoming Ni (2):
  squashfs: add the mount parameter theads=<single|multi|percpu>
  squashfs: Allows users to configure the number of decompression
    threads.

 fs/squashfs/Kconfig                     | 24 ++++++++--
 fs/squashfs/decompressor_multi.c        | 32 ++++++++------
 fs/squashfs/decompressor_multi_percpu.c | 39 ++++++++++-------
 fs/squashfs/decompressor_single.c       | 23 ++++++----
 fs/squashfs/squashfs.h                  | 39 ++++++++++++++---
 fs/squashfs/squashfs_fs_sb.h            |  4 +-
 fs/squashfs/super.c                     | 77 ++++++++++++++++++++++++++++++++-
 7 files changed, 192 insertions(+), 46 deletions(-)

-- 
2.12.3


^ permalink raw reply	[flat|nested] 38+ messages in thread

* [PATCH v2 1/2] squashfs: add the mount parameter theads=<single|multi|percpu>
  2022-08-16  1:00 ` [PATCH v2 0/2] squashfs: Add the mount parameter "threads=" Xiaoming Ni
@ 2022-08-16  1:00   ` Xiaoming Ni
  2022-08-16  1:00   ` [PATCH v2 2/2] squashfs: Allows users to configure the number of decompression threads Xiaoming Ni
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 38+ messages in thread
From: Xiaoming Ni @ 2022-08-16  1:00 UTC (permalink / raw)
  To: linux-kernel, phillip
  Cc: nixiaoming, wangle6, yi.zhang, wangbing6, zhongjubin, chenjianguo3

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.

Signed-off-by: Xiaoming Ni <nixiaoming@huawei.com>
---
 fs/squashfs/Kconfig                     | 20 ++++++++++--
 fs/squashfs/decompressor_multi.c        | 28 +++++++++-------
 fs/squashfs/decompressor_multi_percpu.c | 39 +++++++++++++---------
 fs/squashfs/decompressor_single.c       | 23 ++++++++-----
 fs/squashfs/squashfs.h                  | 39 +++++++++++++++++++---
 fs/squashfs/squashfs_fs_sb.h            |  3 +-
 fs/squashfs/super.c                     | 58 ++++++++++++++++++++++++++++++++-
 7 files changed, 167 insertions(+), 43 deletions(-)

diff --git a/fs/squashfs/Kconfig b/fs/squashfs/Kconfig
index 916e78fabcaa..af9f8c41f2de 100644
--- a/fs/squashfs/Kconfig
+++ b/fs/squashfs/Kconfig
@@ -55,7 +55,7 @@ config SQUASHFS_FILE_DIRECT
 endchoice
 
 choice
-	prompt "Decompressor parallelisation options"
+	prompt "default Decompressor parallelisation options"
 	depends on SQUASHFS
 	help
 	  Squashfs now supports three parallelisation options for
@@ -64,8 +64,23 @@ choice
 
 	  If in doubt, select "Single threaded compression"
 
+	config SQUASHFS_DECOMP_DEFAULT_SINGLE
+	bool "Single threaded compression"
+	select SQUASHFS_DECOMP_SINGLE
+
+	config SQUASHFS_DECOMP_DEFAULT_MULTI
+	bool "Use multiple decompressors for parallel I/O"
+	select SQUASHFS_DECOMP_MULTI
+
+	config SQUASHFS_DECOMP_DEFAULT_PERCPU
+	bool "Use percpu multiple decompressors for parallel I/O"
+	select SQUASHFS_DECOMP_MULTI_PERCPU
+
+endchoice
+
 config SQUASHFS_DECOMP_SINGLE
 	bool "Single threaded compression"
+	depends on SQUASHFS
 	help
 	  Traditionally Squashfs has used single-threaded decompression.
 	  Only one block (data or metadata) can be decompressed at any
@@ -73,6 +88,7 @@ config SQUASHFS_DECOMP_SINGLE
 
 config SQUASHFS_DECOMP_MULTI
 	bool "Use multiple decompressors for parallel I/O"
+	depends on SQUASHFS
 	help
 	  By default Squashfs uses a single decompressor but it gives
 	  poor performance on parallel I/O workloads when using multiple CPU
@@ -87,6 +103,7 @@ config SQUASHFS_DECOMP_MULTI
 
 config SQUASHFS_DECOMP_MULTI_PERCPU
 	bool "Use percpu multiple decompressors for parallel I/O"
+	depends on SQUASHFS
 	help
 	  By default Squashfs uses a single decompressor but it gives
 	  poor performance on parallel I/O workloads when using multiple CPU
@@ -96,7 +113,6 @@ config SQUASHFS_DECOMP_MULTI_PERCPU
 	  decompressor per core.  It uses percpu variables to ensure
 	  decompression is load-balanced across the cores.
 
-endchoice
 
 config SQUASHFS_XATTR
 	bool "Squashfs XATTR support"
diff --git a/fs/squashfs/decompressor_multi.c b/fs/squashfs/decompressor_multi.c
index db9f12a3ea05..7b2723b77e75 100644
--- a/fs/squashfs/decompressor_multi.c
+++ b/fs/squashfs/decompressor_multi.c
@@ -29,13 +29,12 @@
 #define MAX_DECOMPRESSOR	(num_online_cpus() * 2)
 
 
-int squashfs_max_decompressors(void)
+static int squashfs_max_decompressors_multi(void)
 {
 	return MAX_DECOMPRESSOR;
 }
 
-
-struct squashfs_stream {
+struct squashfs_stream_multi {
 	void			*comp_opts;
 	struct list_head	strm_list;
 	struct mutex		mutex;
@@ -51,7 +50,7 @@ struct decomp_stream {
 
 
 static void put_decomp_stream(struct decomp_stream *decomp_strm,
-				struct squashfs_stream *stream)
+				struct squashfs_stream_multi *stream)
 {
 	mutex_lock(&stream->mutex);
 	list_add(&decomp_strm->list, &stream->strm_list);
@@ -59,10 +58,10 @@ 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_multi(struct squashfs_sb_info *msblk,
 				void *comp_opts)
 {
-	struct squashfs_stream *stream;
+	struct squashfs_stream_multi *stream;
 	struct decomp_stream *decomp_strm = NULL;
 	int err = -ENOMEM;
 
@@ -103,9 +102,9 @@ void *squashfs_decompressor_create(struct squashfs_sb_info *msblk,
 }
 
 
-void squashfs_decompressor_destroy(struct squashfs_sb_info *msblk)
+static void squashfs_decompressor_destroy_multi(struct squashfs_sb_info *msblk)
 {
-	struct squashfs_stream *stream = msblk->stream;
+	struct squashfs_stream_multi *stream = msblk->stream;
 	if (stream) {
 		struct decomp_stream *decomp_strm;
 
@@ -125,7 +124,7 @@ void squashfs_decompressor_destroy(struct squashfs_sb_info *msblk)
 
 
 static struct decomp_stream *get_decomp_stream(struct squashfs_sb_info *msblk,
-					struct squashfs_stream *stream)
+					struct squashfs_stream_multi *stream)
 {
 	struct decomp_stream *decomp_strm;
 
@@ -180,12 +179,12 @@ 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_multi(struct squashfs_sb_info *msblk, struct bio *bio,
 			int offset, int length,
 			struct squashfs_page_actor *output)
 {
 	int res;
-	struct squashfs_stream *stream = msblk->stream;
+	struct squashfs_stream_multi *stream = msblk->stream;
 	struct decomp_stream *decomp_stream = get_decomp_stream(msblk, stream);
 	res = msblk->decompressor->decompress(msblk, decomp_stream->stream,
 		bio, offset, length, output);
@@ -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_multi,
+	.destroy = squashfs_decompressor_destroy_multi,
+	.decompress = squashfs_decompress_multi,
+	.max_decompressors = squashfs_max_decompressors_multi,
+};
diff --git a/fs/squashfs/decompressor_multi_percpu.c b/fs/squashfs/decompressor_multi_percpu.c
index b881b9283b7f..e24455a7b04d 100644
--- a/fs/squashfs/decompressor_multi_percpu.c
+++ b/fs/squashfs/decompressor_multi_percpu.c
@@ -20,19 +20,19 @@
  * variables, one thread per cpu core.
  */
 
-struct squashfs_stream {
+struct squashfs_stream_percpu {
 	void			*stream;
 	local_lock_t	lock;
 };
 
-void *squashfs_decompressor_create(struct squashfs_sb_info *msblk,
+static void *squashfs_decompressor_create_percpu(struct squashfs_sb_info *msblk,
 						void *comp_opts)
 {
-	struct squashfs_stream *stream;
-	struct squashfs_stream __percpu *percpu;
+	struct squashfs_stream_percpu *stream;
+	struct squashfs_stream_percpu __percpu *percpu;
 	int err, cpu;
 
-	percpu = alloc_percpu(struct squashfs_stream);
+	percpu = alloc_percpu(struct squashfs_stream_percpu);
 	if (percpu == NULL)
 		return ERR_PTR(-ENOMEM);
 
@@ -59,11 +59,11 @@ 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_percpu(struct squashfs_sb_info *msblk)
 {
-	struct squashfs_stream __percpu *percpu =
-			(struct squashfs_stream __percpu *) msblk->stream;
-	struct squashfs_stream *stream;
+	struct squashfs_stream_percpu __percpu *percpu =
+			(struct squashfs_stream_percpu __percpu *) msblk->stream;
+	struct squashfs_stream_percpu *stream;
 	int cpu;
 
 	if (msblk->stream) {
@@ -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_percpu(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 *stream;
+	struct squashfs_stream_percpu __percpu *percpu =
+			(struct squashfs_stream_percpu __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",
@@ -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_percpu(void)
 {
 	return num_possible_cpus();
 }
+
+const struct squashfs_decompressor_thread_ops squashfs_decompressor_percpu = {
+	.create = squashfs_decompressor_create_percpu,
+	.destroy = squashfs_decompressor_destroy_percpu,
+	.decompress = squashfs_decompress_percpu,
+	.max_decompressors = squashfs_max_decompressors_percpu,
+};
diff --git a/fs/squashfs/decompressor_single.c b/fs/squashfs/decompressor_single.c
index 4eb3d083d45e..41449de0ea4c 100644
--- a/fs/squashfs/decompressor_single.c
+++ b/fs/squashfs/decompressor_single.c
@@ -19,15 +19,15 @@
  * decompressor framework
  */
 
-struct squashfs_stream {
+struct squashfs_stream_single {
 	void		*stream;
 	struct mutex	mutex;
 };
 
-void *squashfs_decompressor_create(struct squashfs_sb_info *msblk,
+static void *squashfs_decompressor_create_single(struct squashfs_sb_info *msblk,
 						void *comp_opts)
 {
-	struct squashfs_stream *stream;
+	struct squashfs_stream_single *stream;
 	int err = -ENOMEM;
 
 	stream = kmalloc(sizeof(*stream), GFP_KERNEL);
@@ -49,9 +49,9 @@ 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_single(struct squashfs_sb_info *msblk)
 {
-	struct squashfs_stream *stream = msblk->stream;
+	struct squashfs_stream_single *stream = msblk->stream;
 
 	if (stream) {
 		msblk->decompressor->free(stream->stream);
@@ -59,12 +59,12 @@ void squashfs_decompressor_destroy(struct squashfs_sb_info *msblk)
 	}
 }
 
-int squashfs_decompress(struct squashfs_sb_info *msblk, struct bio *bio,
+static int squashfs_decompress_single(struct squashfs_sb_info *msblk, struct bio *bio,
 			int offset, int length,
 			struct squashfs_page_actor *output)
 {
 	int res;
-	struct squashfs_stream *stream = msblk->stream;
+	struct squashfs_stream_single *stream = msblk->stream;
 
 	mutex_lock(&stream->mutex);
 	res = msblk->decompressor->decompress(msblk, stream->stream, bio,
@@ -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_single(void)
 {
 	return 1;
 }
+
+const struct squashfs_decompressor_thread_ops squashfs_decompressor_single = {
+	.create = squashfs_decompressor_create_single,
+	.destroy = squashfs_decompressor_destroy_single,
+	.decompress = squashfs_decompress_single,
+	.max_decompressors = squashfs_max_decompressors_single,
+};
diff --git a/fs/squashfs/squashfs.h b/fs/squashfs/squashfs.h
index 9783e01c8100..514cba134f11 100644
--- a/fs/squashfs/squashfs.h
+++ b/fs/squashfs/squashfs.h
@@ -38,11 +38,40 @@ 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
+
+static inline void *squashfs_decompressor_create(struct squashfs_sb_info *msblk, void *comp_opts)
+{
+	return msblk->thread_ops->create(msblk, comp_opts);
+}
+
+static inline void squashfs_decompressor_destroy(struct squashfs_sb_info *msblk)
+{
+	msblk->thread_ops->destroy(msblk);
+}
+
+static inline int squashfs_decompress(struct squashfs_sb_info *msblk, struct bio *bio,
+				      int offset, int length, struct squashfs_page_actor *output)
+{
+	return msblk->thread_ops->decompress(msblk, bio, offset, length, output);
+}
 
 /* export.c */
 extern __le64 *squashfs_read_inode_lookup_table(struct super_block *, u64, u64,
diff --git a/fs/squashfs/squashfs_fs_sb.h b/fs/squashfs/squashfs_fs_sb.h
index 1e90c2575f9b..f1e5dad8ae0a 100644
--- a/fs/squashfs/squashfs_fs_sb.h
+++ b/fs/squashfs/squashfs_fs_sb.h
@@ -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;
@@ -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
diff --git a/fs/squashfs/super.c b/fs/squashfs/super.c
index 32565dafa7f3..6fd44683a84b 100644
--- a/fs/squashfs/super.c
+++ b/fs/squashfs/super.c
@@ -47,10 +47,12 @@ enum Opt_errors {
 
 enum squashfs_param {
 	Opt_errors,
+	Opt_threads,
 };
 
 struct squashfs_mount_opts {
 	enum Opt_errors errors;
+	const struct squashfs_decompressor_thread_ops *thread_ops;
 };
 
 static const struct constant_table squashfs_param_errors[] = {
@@ -61,9 +63,33 @@ static const struct constant_table squashfs_param_errors[] = {
 
 static const struct fs_parameter_spec squashfs_fs_parameters[] = {
 	fsparam_enum("errors", Opt_errors, squashfs_param_errors),
+	fsparam_string("threads", Opt_threads),
 	{}
 };
 
+static int squashfs_parse_param_threads(const char *str, struct squashfs_mount_opts *opts)
+{
+#ifdef CONFIG_SQUASHFS_DECOMP_SINGLE
+	if (strcmp(str, "single") == 0) {
+		opts->thread_ops = &squashfs_decompressor_single;
+		return 0;
+	}
+#endif
+#ifdef CONFIG_SQUASHFS_DECOMP_MULTI
+	if (strcmp(str, "multi") == 0) {
+		opts->thread_ops = &squashfs_decompressor_multi;
+		return 0;
+	}
+#endif
+#ifdef CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU
+	if (strcmp(str, "percpu") == 0) {
+		opts->thread_ops = &squashfs_decompressor_percpu;
+		return 0;
+	}
+#endif
+	return -EINVAL;
+}
+
 static int squashfs_parse_param(struct fs_context *fc, struct fs_parameter *param)
 {
 	struct squashfs_mount_opts *opts = fc->fs_private;
@@ -78,6 +104,10 @@ static int squashfs_parse_param(struct fs_context *fc, struct fs_parameter *para
 	case Opt_errors:
 		opts->errors = result.uint_32;
 		break;
+	case Opt_threads:
+		if (squashfs_parse_param_threads(param->string, opts) != 0)
+			return -EINVAL;
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -167,6 +197,7 @@ static int squashfs_fill_super(struct super_block *sb, struct fs_context *fc)
 			       sb->s_bdev);
 		goto failed_mount;
 	}
+	msblk->thread_ops = opts->thread_ops;
 
 	/* Check the MAJOR & MINOR versions and lookup compression type */
 	msblk->decompressor = supported_squashfs_filesystem(
@@ -252,7 +283,7 @@ static int squashfs_fill_super(struct super_block *sb, struct fs_context *fc)
 
 	/* Allocate read_page block */
 	msblk->read_page = squashfs_cache_init("data",
-		squashfs_max_decompressors(), msblk->block_size);
+		msblk->thread_ops->max_decompressors(), msblk->block_size);
 	if (msblk->read_page == NULL) {
 		errorf(fc, "Failed to allocate read_page block");
 		goto failed_mount;
@@ -435,6 +466,24 @@ static int squashfs_show_options(struct seq_file *s, struct dentry *root)
 	else
 		seq_puts(s, ",errors=continue");
 
+#ifdef CONFIG_SQUASHFS_DECOMP_SINGLE
+	if (msblk->thread_ops == &squashfs_decompressor_single) {
+		seq_puts(s, ",threads=single");
+		return 0;
+	}
+#endif
+#ifdef CONFIG_SQUASHFS_DECOMP_MULTI
+	if (msblk->thread_ops == &squashfs_decompressor_multi) {
+		seq_puts(s, ",threads=multi");
+		return 0;
+	}
+#endif
+#ifdef CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU
+	if (msblk->thread_ops == &squashfs_decompressor_percpu) {
+		seq_puts(s, ",threads=percpu");
+		return 0;
+	}
+#endif
 	return 0;
 }
 
@@ -446,6 +495,13 @@ static int squashfs_init_fs_context(struct fs_context *fc)
 	if (!opts)
 		return -ENOMEM;
 
+#ifdef CONFIG_SQUASHFS_DECOMP_DEFAULT_SINGLE
+	opts->thread_ops = &squashfs_decompressor_single;
+#elif defined(CONFIG_SQUASHFS_DECOMP_DEFAULT_MULTI)
+	opts->thread_ops = &squashfs_decompressor_multi,
+#elif defined(CONFIG_SQUASHFS_DECOMP_DEFAULT_PERCPU)
+	opts->thread_ops = &squashfs_decompressor_percpu;
+#endif
 	fc->fs_private = opts;
 	fc->ops = &squashfs_context_ops;
 	return 0;
-- 
2.12.3


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH v2 2/2] squashfs: Allows users to configure the number of decompression threads.
  2022-08-16  1:00 ` [PATCH v2 0/2] squashfs: Add the mount parameter "threads=" Xiaoming Ni
  2022-08-16  1:00   ` [PATCH v2 1/2] squashfs: add the mount parameter theads=<single|multi|percpu> Xiaoming Ni
@ 2022-08-16  1:00   ` Xiaoming Ni
  2022-08-26  6:19   ` ping //Re: [PATCH v2 0/2] squashfs: Add the mount parameter "threads=" Xiaoming Ni
  2022-09-02  9:48   ` [PATCH v3 " Xiaoming Ni
  3 siblings, 0 replies; 38+ messages in thread
From: Xiaoming Ni @ 2022-08-16  1:00 UTC (permalink / raw)
  To: linux-kernel, phillip
  Cc: nixiaoming, wangle6, yi.zhang, wangbing6, zhongjubin, chenjianguo3

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.

Signed-off-by: Xiaoming Ni <nixiaoming@huawei.com>
---
 fs/squashfs/Kconfig              |  4 +++-
 fs/squashfs/decompressor_multi.c |  4 ++--
 fs/squashfs/squashfs_fs_sb.h     |  1 +
 fs/squashfs/super.c              | 45 ++++++++++++++++++++++++++++------------
 4 files changed, 38 insertions(+), 16 deletions(-)

diff --git a/fs/squashfs/Kconfig b/fs/squashfs/Kconfig
index af9f8c41f2de..3f42b4099dc7 100644
--- a/fs/squashfs/Kconfig
+++ b/fs/squashfs/Kconfig
@@ -99,7 +99,9 @@ config SQUASHFS_DECOMP_MULTI
 
 	  This decompressor implementation uses up to two parallel
 	  decompressors per core.  It dynamically allocates decompressors
-	  on a demand basis.
+	  on a demand basis.  You can also set the number of threads by setting threads=<number> of
+	  the mount parameter.
+
 
 config SQUASHFS_DECOMP_MULTI_PERCPU
 	bool "Use percpu multiple decompressors for parallel I/O"
diff --git a/fs/squashfs/decompressor_multi.c b/fs/squashfs/decompressor_multi.c
index 7b2723b77e75..6d1cea325cca 100644
--- a/fs/squashfs/decompressor_multi.c
+++ b/fs/squashfs/decompressor_multi.c
@@ -144,7 +144,7 @@ static struct decomp_stream *get_decomp_stream(struct squashfs_sb_info *msblk,
 		 * If there is no available decomp and already full,
 		 * let's wait for releasing decomp from other users.
 		 */
-		if (stream->avail_decomp >= MAX_DECOMPRESSOR)
+		if (stream->avail_decomp >= msblk->max_thread_num)
 			goto wait;
 
 		/* Let's allocate new decomp */
@@ -160,7 +160,7 @@ static struct decomp_stream *get_decomp_stream(struct squashfs_sb_info *msblk,
 		}
 
 		stream->avail_decomp++;
-		WARN_ON(stream->avail_decomp > MAX_DECOMPRESSOR);
+		WARN_ON(stream->avail_decomp > msblk->max_thread_num);
 
 		mutex_unlock(&stream->mutex);
 		break;
diff --git a/fs/squashfs/squashfs_fs_sb.h b/fs/squashfs/squashfs_fs_sb.h
index f1e5dad8ae0a..659082e9e51d 100644
--- a/fs/squashfs/squashfs_fs_sb.h
+++ b/fs/squashfs/squashfs_fs_sb.h
@@ -67,5 +67,6 @@ struct squashfs_sb_info {
 	unsigned int				ids;
 	bool					panic_on_errors;
 	const struct squashfs_decompressor_thread_ops *thread_ops;
+	int					max_thread_num;
 };
 #endif
diff --git a/fs/squashfs/super.c b/fs/squashfs/super.c
index 6fd44683a84b..f3533e20d0b7 100644
--- a/fs/squashfs/super.c
+++ b/fs/squashfs/super.c
@@ -53,6 +53,7 @@ enum squashfs_param {
 struct squashfs_mount_opts {
 	enum Opt_errors errors;
 	const struct squashfs_decompressor_thread_ops *thread_ops;
+	int thread_num;
 };
 
 static const struct constant_table squashfs_param_errors[] = {
@@ -69,6 +70,8 @@ static const struct fs_parameter_spec squashfs_fs_parameters[] = {
 
 static int squashfs_parse_param_threads(const char *str, struct squashfs_mount_opts *opts)
 {
+	unsigned long num;
+	int ret;
 #ifdef CONFIG_SQUASHFS_DECOMP_SINGLE
 	if (strcmp(str, "single") == 0) {
 		opts->thread_ops = &squashfs_decompressor_single;
@@ -87,7 +90,24 @@ static int squashfs_parse_param_threads(const char *str, struct squashfs_mount_o
 		return 0;
 	}
 #endif
+	ret = kstrtoul(str, 0, &num);
+	if (ret != 0 || num == 0)
+		return -EINVAL;
+#ifdef CONFIG_SQUASHFS_DECOMP_SINGLE
+	if (num == 1) {
+		opts->thread_ops = &squashfs_decompressor_single;
+		return 0;
+	}
+#endif
+#ifdef CONFIG_SQUASHFS_DECOMP_MULTI
+	opts->thread_ops = &squashfs_decompressor_multi;
+	if (num > opts->thread_ops->max_decompressors())
+		num = opts->thread_ops->max_decompressors();
+	opts->thread_num = (int)num;
+	return 0;
+#else
 	return -EINVAL;
+#endif
 }
 
 static int squashfs_parse_param(struct fs_context *fc, struct fs_parameter *param)
@@ -198,6 +218,11 @@ static int squashfs_fill_super(struct super_block *sb, struct fs_context *fc)
 		goto failed_mount;
 	}
 	msblk->thread_ops = opts->thread_ops;
+	if (opts->thread_num == 0) {
+		msblk->max_thread_num = opts->thread_ops->max_decompressors();
+	} else {
+		msblk->max_thread_num = opts->thread_num;
+	}
 
 	/* Check the MAJOR & MINOR versions and lookup compression type */
 	msblk->decompressor = supported_squashfs_filesystem(
@@ -283,7 +308,7 @@ static int squashfs_fill_super(struct super_block *sb, struct fs_context *fc)
 
 	/* Allocate read_page block */
 	msblk->read_page = squashfs_cache_init("data",
-		msblk->thread_ops->max_decompressors(), msblk->block_size);
+		msblk->max_thread_num, msblk->block_size);
 	if (msblk->read_page == NULL) {
 		errorf(fc, "Failed to allocate read_page block");
 		goto failed_mount;
@@ -466,24 +491,17 @@ static int squashfs_show_options(struct seq_file *s, struct dentry *root)
 	else
 		seq_puts(s, ",errors=continue");
 
-#ifdef CONFIG_SQUASHFS_DECOMP_SINGLE
-	if (msblk->thread_ops == &squashfs_decompressor_single) {
-		seq_puts(s, ",threads=single");
-		return 0;
-	}
-#endif
-#ifdef CONFIG_SQUASHFS_DECOMP_MULTI
-	if (msblk->thread_ops == &squashfs_decompressor_multi) {
-		seq_puts(s, ",threads=multi");
-		return 0;
-	}
-#endif
 #ifdef CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU
+	/*
+	 * thread=percpu and thread=<number> have different configuration effects.
+	 * the parameters need to be treated differently when they are displayed.
+	 */
 	if (msblk->thread_ops == &squashfs_decompressor_percpu) {
 		seq_puts(s, ",threads=percpu");
 		return 0;
 	}
 #endif
+	seq_printf(s, ",threads=%u", msblk->max_thread_num);
 	return 0;
 }
 
@@ -502,6 +520,7 @@ static int squashfs_init_fs_context(struct fs_context *fc)
 #elif defined(CONFIG_SQUASHFS_DECOMP_DEFAULT_PERCPU)
 	opts->thread_ops = &squashfs_decompressor_percpu;
 #endif
+	opts->thread_num = 0;
 	fc->fs_private = opts;
 	fc->ops = &squashfs_context_ops;
 	return 0;
-- 
2.12.3


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* ping //Re: [PATCH v2 0/2] squashfs: Add the mount parameter "threads="
  2022-08-16  1:00 ` [PATCH v2 0/2] squashfs: Add the mount parameter "threads=" Xiaoming Ni
  2022-08-16  1:00   ` [PATCH v2 1/2] squashfs: add the mount parameter theads=<single|multi|percpu> Xiaoming Ni
  2022-08-16  1:00   ` [PATCH v2 2/2] squashfs: Allows users to configure the number of decompression threads Xiaoming Ni
@ 2022-08-26  6:19   ` Xiaoming Ni
  2022-08-28 23:18     ` Phillip Lougher
  2022-09-02  9:48   ` [PATCH v3 " Xiaoming Ni
  3 siblings, 1 reply; 38+ messages in thread
From: Xiaoming Ni @ 2022-08-26  6:19 UTC (permalink / raw)
  To: linux-kernel, phillip
  Cc: wangle6, yi.zhang, wangbing6, zhongjubin, chenjianguo3

ping


On 2022/8/16 9:00, Xiaoming Ni wrote:
> 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.
> 
> v2: fix warning: sparse: incorrect type in initializer (different address spaces)
>    Reported-by: kernel test robot <lkp@intel.com>
> 
> v1: https://lore.kernel.org/lkml/20220815031100.75243-1-nixiaoming@huawei.com/
> ----
> 
> Xiaoming Ni (2):
>    squashfs: add the mount parameter theads=<single|multi|percpu>
>    squashfs: Allows users to configure the number of decompression
>      threads.
> 
>   fs/squashfs/Kconfig                     | 24 ++++++++--
>   fs/squashfs/decompressor_multi.c        | 32 ++++++++------
>   fs/squashfs/decompressor_multi_percpu.c | 39 ++++++++++-------
>   fs/squashfs/decompressor_single.c       | 23 ++++++----
>   fs/squashfs/squashfs.h                  | 39 ++++++++++++++---
>   fs/squashfs/squashfs_fs_sb.h            |  4 +-
>   fs/squashfs/super.c                     | 77 ++++++++++++++++++++++++++++++++-
>   7 files changed, 192 insertions(+), 46 deletions(-)
> 


^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: ping //Re: [PATCH v2 0/2] squashfs: Add the mount parameter "threads="
  2022-08-26  6:19   ` ping //Re: [PATCH v2 0/2] squashfs: Add the mount parameter "threads=" Xiaoming Ni
@ 2022-08-28 23:18     ` Phillip Lougher
  2022-08-30 13:38       ` Xiaoming Ni
  0 siblings, 1 reply; 38+ messages in thread
From: Phillip Lougher @ 2022-08-28 23:18 UTC (permalink / raw)
  To: Xiaoming Ni, linux-kernel
  Cc: wangle6, yi.zhang, wangbing6, zhongjubin, chenjianguo3

On 26/08/2022 07:19, Xiaoming Ni wrote:
> ping
> 
> 
> On 2022/8/16 9:00, Xiaoming Ni wrote:
>> 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.
>>
>> v2: fix warning: sparse: incorrect type in initializer (different 
>> address spaces)
>>    Reported-by: kernel test robot <lkp@intel.com>

I have made an initial review of the patches, and I have the following
comments.

Good things about the patch-series.

1. In principle I have no objections to making this configurable at
    mount time.  But, a use-case for why this has become necessary
    would help in the evaluation.

2. In general the code changes are good.  They are predominantly
    exposing the existing different decompressor functionality into
    structures which can be selected at mount time.  They do not
    change existing functionality, and so there are no issues
    about unexpected regressions.

Things which I don't like about the patch-series.

1. There is no default kernel configuration option to keep the existing
    behaviour, that is build time selectable only.  There may be many
    companies/people where for "security" reasons the ability to
    switch to a more CPU/memory intensive decompressor or more threads
    is a risk.

    Yes, I know the new kernel configuration options allow only the
    selected default decompressor mode to be built.  In theory that
    will restrict the available decompressors to the single decompressor
    selected at build time.  So not much different to the current
    position?  But, if the CONFIG_SQUASHFS_DECOMP_MULTI decompressor
    is selected, that will now allow more threads to be used than is
    current, where it is currently restricted to num_online_cpus() * 2.

2. You have decided to allow the mutiple decompressor implementations
    to be selected at mount time - but you have also allowed only one
    decompressor to be built at kernel build time.  This means you
    end up in the fairly silly situation of having a mount time
    option which allows the user to select between one decompressor.
    There doesn't seem much point in having an option which allows
    nothing to be changed.

3. Using thread=<number>, where thread=1 you use SQUASHFS_DECOMP_SINGLE
    if it has been built, otherwise you fall back to
    SQUASHFS_DECOMP_MULTI.  This meants the effect of thread=1 is
    indeterminate and depends on the build options.  I would suggest
    thread=1 should always mean use SQUASHFS_DECOMP_SINGLE.

4. If SQUASHFS_DECOMP_MULTI is selected, there isn't a limit on the
    maximum amount of threads allowed, and there is no ability to
    set the maximum number of threads allowed at kernel build time
    either.

All of the above seems to be a bit of a mess.

As regards points 1 - 3, personally I would add a default kernel
configuration option that keeps the existing behaviour, build time
selectable only, no additional mount time options.  Then a
kernel configuration option that allows the different decompressors
to be selected at mount time, but which always builds all the
decompressors.  This will avoid the silliness of point 2, and
the indeterminate behaviour of point 3.

As regards point 4, I think you should require the maximum number
of threads allowable to be determined at build time, this is
good for security and avoids attempts to use too much CPU
and memory.  The default at kernel build time should be minimal,
to avoid cases where an unchanged value can cause a potential
security hazard on a low end system.  In otherwords it is
up to the user at build time to set the value to an appropriate
value for their system.

Phillip

---
Phillip Lougher, Squashfs author and maintainer.

>>
>> v1: 
>> https://lore.kernel.org/lkml/20220815031100.75243-1-nixiaoming@huawei.com/ 
>>
>> ----
>>
>> Xiaoming Ni (2):
>>    squashfs: add the mount parameter theads=<single|multi|percpu>
>>    squashfs: Allows users to configure the number of decompression
>>      threads.
>>
>>   fs/squashfs/Kconfig                     | 24 ++++++++--
>>   fs/squashfs/decompressor_multi.c        | 32 ++++++++------
>>   fs/squashfs/decompressor_multi_percpu.c | 39 ++++++++++-------
>>   fs/squashfs/decompressor_single.c       | 23 ++++++----
>>   fs/squashfs/squashfs.h                  | 39 ++++++++++++++---
>>   fs/squashfs/squashfs_fs_sb.h            |  4 +-
>>   fs/squashfs/super.c                     | 77 
>> ++++++++++++++++++++++++++++++++-
>>   7 files changed, 192 insertions(+), 46 deletions(-)
>>
> 


^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: ping //Re: [PATCH v2 0/2] squashfs: Add the mount parameter "threads="
  2022-08-28 23:18     ` Phillip Lougher
@ 2022-08-30 13:38       ` Xiaoming Ni
  2022-08-30 18:08         ` Phillip Lougher
  0 siblings, 1 reply; 38+ messages in thread
From: Xiaoming Ni @ 2022-08-30 13:38 UTC (permalink / raw)
  To: Phillip Lougher, linux-kernel
  Cc: wangle6, yi.zhang, wangbing6, zhongjubin, chenjianguo3

On 2022/8/29 7:18, Phillip Lougher wrote:
> On 26/08/2022 07:19, Xiaoming Ni wrote:
>> ping
>>
>>
>> On 2022/8/16 9:00, Xiaoming Ni wrote:
>>> 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.
>>>
>>> v2: fix warning: sparse: incorrect type in initializer (different 
>>> address spaces)
>>>    Reported-by: kernel test robot <lkp@intel.com>
> 
> I have made an initial review of the patches, and I have the following
> comments.
> 
> Good things about the patch-series.
> 
> 1. In principle I have no objections to making this configurable at
>     mount time.  But, a use-case for why this has become necessary
>     would help in the evaluation.
> 
> 2. In general the code changes are good.  They are predominantly
>     exposing the existing different decompressor functionality into
>     structures which can be selected at mount time.  They do not
>     change existing functionality, and so there are no issues
>     about unexpected regressions.
> 
> Things which I don't like about the patch-series.
> 
> 1. There is no default kernel configuration option to keep the existing
>     behaviour, that is build time selectable only.  There may be many
>     companies/people where for "security" reasons the ability to
>     switch to a more CPU/memory intensive decompressor or more threads
>     is a risk.
> 
>     Yes, I know the new kernel configuration options allow only the
>     selected default decompressor mode to be built.  In theory that
>     will restrict the available decompressors to the single decompressor
>     selected at build time.  So not much different to the current
>     position?  But, if the CONFIG_SQUASHFS_DECOMP_MULTI decompressor
>     is selected, that will now allow more threads to be used than is
No more threads than before the patch.

>     current, where it is currently restricted to num_online_cpus() * 2.
After the patch is installed, the maximum number of threads is still 
num_online_cpus() * 2.

[PATCH v2 2/2] squashfs: Allows users to configure the number of 
decompression threads

+#ifdef CONFIG_SQUASHFS_DECOMP_MULTI
+    opts->thread_ops = &squashfs_decompressor_multi;
+    if (num > opts->thread_ops->max_decompressors())
+        num = opts->thread_ops->max_decompressors();
+    opts->thread_num = (int)num;
+    return 0;
+#else

> 
> 2. You have decided to allow the mutiple decompressor implementations
>     to be selected at mount time - but you have also allowed only one
>     decompressor to be built at kernel build time.  This means you
>     end up in the fairly silly situation of having a mount time
>     option which allows the user to select between one decompressor.
>     There doesn't seem much point in having an option which allows
>     nothing to be changed.
When multiple decompression modes are selected during kernel build, or 
only SQUASHFS_DECOMP_MULTI is selected during kernel build, the mount 
parameter "threads=" is meaningful,
However, when only SQUASHFS_DECOMP_SINGLE or 
SQUASHFS_DECOMP_MULTI_PERCPU is selected, the mount parameter "threads=" 
is meaningless.

Thank you for your guidance


> 
> 3. Using thread=<number>, where thread=1 you use SQUASHFS_DECOMP_SINGLE
>     if it has been built, otherwise you fall back to
>     SQUASHFS_DECOMP_MULTI.  This meants the effect of thread=1 is
>     indeterminate and depends on the build options.  I would suggest
>     thread=1 should always mean use SQUASHFS_DECOMP_SINGLE.

SQUASHFS_DECOMP_MULTI and SQUASHFS_DECOMP_SINGLE are selected during 
construction. Thread=1 indicates that SQUASHFS_DECOMP_SINGLEI is used.

If only SQUASHFS_DECOMP_MULTI is selected during construction, thread=1 
indicates that SQUASHFS_DECOMP_MULTI is used, and only one decompression 
thread is created.

Would it be better to provide more flexible mount options for images 
that build only SQUASHFS_DECOMP_MULTI?

> 
> 4. If SQUASHFS_DECOMP_MULTI is selected, there isn't a limit on the
>     maximum amount of threads allowed, and there is no ability to
>     set the maximum number of threads allowed at kernel build time
>     either.
After the patch is installed, the maximum number of threads is still 
num_online_cpus() * 2.

[PATCH v2 2/2] squashfs: Allows users to configure the number of 
decompression threads

+#ifdef CONFIG_SQUASHFS_DECOMP_MULTI
+    opts->thread_ops = &squashfs_decompressor_multi;
+    if (num > opts->thread_ops->max_decompressors())
+        num = opts->thread_ops->max_decompressors();
+    opts->thread_num = (int)num;
+    return 0;

Did I misunderstand your question?


> 
> All of the above seems to be a bit of a mess.
> 
> As regards points 1 - 3, personally I would add a default kernel
> configuration option that keeps the existing behaviour, build time
> selectable only, no additional mount time options.  Then a
> kernel configuration option that allows the different decompressors
> to be selected at mount time, but which always builds all the
> decompressors.  This will avoid the silliness of point 2, and
Would it be better to allow flexible selection of decompression mode 
combinations?

> the indeterminate behaviour of point 3.
> 
> As regards point 4, I think you should require the maximum number
> of threads allowable to be determined at build time, this is
> good for security and avoids attempts to use too much CPU
> and memory.  The default at kernel build time should be minimal,
> to avoid cases where an unchanged value can cause a potential
> security hazard on a low end system.  In otherwords it is
> up to the user at build time to set the value to an appropriate
> value for their system.
In patch 2, the maximum number of threads has been limited,
Have I misunderstood your question


> 
> Phillip
> 
> ---
> Phillip Lougher, Squashfs author and maintainer.
> 

Thanks
Xiaoming Ni

>>>
>>> v1: 
>>> https://lore.kernel.org/lkml/20220815031100.75243-1-nixiaoming@huawei.com/ 
>>>
>>> ----
>>>
>>> Xiaoming Ni (2):
>>>    squashfs: add the mount parameter theads=<single|multi|percpu>
>>>    squashfs: Allows users to configure the number of decompression
>>>      threads.
>>>
>>>   fs/squashfs/Kconfig                     | 24 ++++++++--
>>>   fs/squashfs/decompressor_multi.c        | 32 ++++++++------
>>>   fs/squashfs/decompressor_multi_percpu.c | 39 ++++++++++-------
>>>   fs/squashfs/decompressor_single.c       | 23 ++++++----
>>>   fs/squashfs/squashfs.h                  | 39 ++++++++++++++---
>>>   fs/squashfs/squashfs_fs_sb.h            |  4 +-
>>>   fs/squashfs/super.c                     | 77 
>>> ++++++++++++++++++++++++++++++++-
>>>   7 files changed, 192 insertions(+), 46 deletions(-)
>>>
>>
> 
> 
> .


^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: ping //Re: [PATCH v2 0/2] squashfs: Add the mount parameter "threads="
  2022-08-30 13:38       ` Xiaoming Ni
@ 2022-08-30 18:08         ` Phillip Lougher
  2022-08-30 18:34           ` Phillip Lougher
  0 siblings, 1 reply; 38+ messages in thread
From: Phillip Lougher @ 2022-08-30 18:08 UTC (permalink / raw)
  To: Xiaoming Ni, linux-kernel
  Cc: wangle6, yi.zhang, wangbing6, zhongjubin, chenjianguo3

On 30/08/2022 14:38, Xiaoming Ni wrote:
> On 2022/8/29 7:18, Phillip Lougher wrote:
>> On 26/08/2022 07:19, Xiaoming Ni wrote:
>>> ping
>>>
>>>
>>> On 2022/8/16 9:00, Xiaoming Ni wrote:
>>>> 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.
>>>>
>>>> v2: fix warning: sparse: incorrect type in initializer (different 
>>>> address spaces)
>>>>    Reported-by: kernel test robot <lkp@intel.com>
>>
>> I have made an initial review of the patches, and I have the following
>> comments.
>>
>> Good things about the patch-series.
>>
>> 1. In principle I have no objections to making this configurable at
>>     mount time.  But, a use-case for why this has become necessary
>>     would help in the evaluation.
>>
>> 2. In general the code changes are good.  They are predominantly
>>     exposing the existing different decompressor functionality into
>>     structures which can be selected at mount time.  They do not
>>     change existing functionality, and so there are no issues
>>     about unexpected regressions.
>>
>> Things which I don't like about the patch-series.
>>
>> 1. There is no default kernel configuration option to keep the existing
>>     behaviour, that is build time selectable only.  There may be many
>>     companies/people where for "security" reasons the ability to
>>     switch to a more CPU/memory intensive decompressor or more threads
>>     is a risk.
>>
>>     Yes, I know the new kernel configuration options allow only the
>>     selected default decompressor mode to be built.  In theory that
>>     will restrict the available decompressors to the single decompressor
>>     selected at build time.  So not much different to the current
>>     position?  But, if the CONFIG_SQUASHFS_DECOMP_MULTI decompressor
>>     is selected, that will now allow more threads to be used than is
> No more threads than before the patch.
> 
>>     current, where it is currently restricted to num_online_cpus() * 2.
> After the patch is installed, the maximum number of threads is still 
> num_online_cpus() * 2.
> 
> [PATCH v2 2/2] squashfs: Allows users to configure the number of 
> decompression threads
> 
> +#ifdef CONFIG_SQUASHFS_DECOMP_MULTI
> +    opts->thread_ops = &squashfs_decompressor_multi;
> +    if (num > opts->thread_ops->max_decompressors())
> +        num = opts->thread_ops->max_decompressors();
> +    opts->thread_num = (int)num;
> +    return 0;
> +#else
> 

I missed that the maximum number of threads is still limited
to num_online_cpus() * 2.

You should make it clear in the patch commit message what the
thread maximum is (and that it is unchanged).

This means some of my reservations go away.

>>
>> 2. You have decided to allow the mutiple decompressor implementations
>>     to be selected at mount time - but you have also allowed only one
>>     decompressor to be built at kernel build time.  This means you
>>     end up in the fairly silly situation of having a mount time
>>     option which allows the user to select between one decompressor.
>>     There doesn't seem much point in having an option which allows
>>     nothing to be changed.
> When multiple decompression modes are selected during kernel build, or 
> only SQUASHFS_DECOMP_MULTI is selected during kernel build, the mount 
> parameter "threads=" is meaningful,
> However, when only SQUASHFS_DECOMP_SINGLE or 
> SQUASHFS_DECOMP_MULTI_PERCPU is selected, the mount parameter "threads=" 
> is meaningless.
> 
> Thank you for your guidance
> 
> 
>>
>> 3. Using thread=<number>, where thread=1 you use SQUASHFS_DECOMP_SINGLE
>>     if it has been built, otherwise you fall back to
>>     SQUASHFS_DECOMP_MULTI.  This meants the effect of thread=1 is
>>     indeterminate and depends on the build options.  I would suggest
>>     thread=1 should always mean use SQUASHFS_DECOMP_SINGLE.
> 
> SQUASHFS_DECOMP_MULTI and SQUASHFS_DECOMP_SINGLE are selected during 
> construction. Thread=1 indicates that SQUASHFS_DECOMP_SINGLEI is used.
> 
> If only SQUASHFS_DECOMP_MULTI is selected during construction, thread=1 
> indicates that SQUASHFS_DECOMP_MULTI is used, and only one decompression 
> thread is created.

That is wrong.  It violates the principles of KISS (keep it simple) and 
least surprise.

I will spell it out for you.

thread=1 meaning either SQUASHFS_DECOMP_SINGLE or SQUASHFS_DECOMP_MULTI
depending on the built, adds an ambiguity which cannot be determined
unless you know how the kernel was built.  This violates KISS.

SQUASHFS_DECOMP_MULTI is for parallel decompression - it's in the name.
Over-loading it to do single decompression again violates KISS and
it also violates the principle of least suprise.  Many people will not
think single decompression should be possible with only 
SQUASHFS_DECOMP_MULTI built in.

SQUASHFS_DECOMP_SINGLE is for doing single decompression - again it's in 
the name.

So

SQUASHFS_DECOMP_MULTI for threads >= 2
SQUASHFS_DECOMP_SINGLE for thread = 1

This keeps it simple and follows the principle of least suprise.

If you want single threaded operation as a choice, then build the 
SQUASHFS_DECOMP_SINGLE decompressor.

> 
> Would it be better to provide more flexible mount options for images 
> that build only SQUASHFS_DECOMP_MULTI?
>  >> 4. If SQUASHFS_DECOMP_MULTI is selected, there isn't a limit on the
>>     maximum amount of threads allowed, and there is no ability to
>>     set the maximum number of threads allowed at kernel build time
>>     either.
> After the patch is installed, the maximum number of threads is still 
> num_online_cpus() * 2.
> 
> [PATCH v2 2/2] squashfs: Allows users to configure the number of 
> decompression threads
> 
> +#ifdef CONFIG_SQUASHFS_DECOMP_MULTI
> +    opts->thread_ops = &squashfs_decompressor_multi;
> +    if (num > opts->thread_ops->max_decompressors())
> +        num = opts->thread_ops->max_decompressors();
> +    opts->thread_num = (int)num;
> +    return 0;
> 
> Did I misunderstand your question?
> 
> 
>>
>> All of the above seems to be a bit of a mess.
>>
>> As regards points 1 - 3, personally I would add a default kernel
>> configuration option that keeps the existing behaviour, build time
>> selectable only, no additional mount time options.  Then a
>> kernel configuration option that allows the different decompressors
>> to be selected at mount time, but which always builds all the
>> decompressors.  This will avoid the silliness of point 2, and
> Would it be better to allow flexible selection of decompression mode 
> combinations?

I told you I don't like that (*).  I also told you I want the default 
behaviour to be the current behaviour.

Feel free to disagree, but that isn't a good way to get your patch
reviewed or accepted by me.

Cheers

Phillip

(*) Adding options to select the decompressor at mount time, but,
     also allowing only 1 - 2 decompressors to be built is a waste of
     time.  It has the effect of giving something with one hand and
     taking it alway with the other.  Build the lot, this also
     keeps it simple.



^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: ping //Re: [PATCH v2 0/2] squashfs: Add the mount parameter "threads="
  2022-08-30 18:08         ` Phillip Lougher
@ 2022-08-30 18:34           ` Phillip Lougher
  2022-08-31  1:09             ` Xiaoming Ni
  0 siblings, 1 reply; 38+ messages in thread
From: Phillip Lougher @ 2022-08-30 18:34 UTC (permalink / raw)
  To: Xiaoming Ni, linux-kernel
  Cc: wangle6, yi.zhang, wangbing6, zhongjubin, chenjianguo3

On 30/08/2022 19:08, Phillip Lougher wrote:
> On 30/08/2022 14:38, Xiaoming Ni wrote:
>> On 2022/8/29 7:18, Phillip Lougher wrote:

>>> As regards points 1 - 3, personally I would add a default kernel
>>> configuration option that keeps the existing behaviour, build time
>>> selectable only, no additional mount time options.  Then a
>>> kernel configuration option that allows the different decompressors
>>> to be selected at mount time, but which always builds all the
>>> decompressors.  This will avoid the silliness of point 2, and
>> Would it be better to allow flexible selection of decompression mode 
>> combinations?
> 
> I told you I don't like that (*).  I also told you I want the default 
> behaviour to be the current behaviour.
> 
> Feel free to disagree, but that isn't a good way to get your patch
> reviewed or accepted by me.
> 
> Cheers
> 
> Phillip
> 
> (*) Adding options to select the decompressor at mount time, but,
>      also allowing only 1 - 2 decompressors to be built is a waste of
>      time.  It has the effect of giving something with one hand and
>      taking it alway with the other.  Build the lot, this also
>      keeps it simple.
> 
> 

It also splatters super.c with #ifdef CONFIG lines.

phillip@phoenix:/external/stripe/linux/fs/squashfs$ grep "CONFIG_" super.c
#ifdef CONFIG_SQUASHFS_DECOMP_SINGLE
#ifdef CONFIG_SQUASHFS_DECOMP_MULTI
#ifdef CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU
#ifdef CONFIG_SQUASHFS_DECOMP_SINGLE
#ifdef CONFIG_SQUASHFS_DECOMP_MULTI
#ifdef CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU
#ifdef CONFIG_SQUASHFS_DECOMP_DEFAULT_SINGLE
#elif defined(CONFIG_SQUASHFS_DECOMP_DEFAULT_MULTI)
#elif defined(CONFIG_SQUASHFS_DECOMP_DEFAULT_PERCPU)

Or

static int squashfs_parse_param_threads(const char *str, struct 
squashfs_mount_opts *opts)
{
         unsigned long num;
         int ret;
#ifdef CONFIG_SQUASHFS_DECOMP_SINGLE
         if (strcmp(str, "single") == 0) {
                 opts->thread_ops = &squashfs_decompressor_single;
                 return 0;
         }
#endif
#ifdef CONFIG_SQUASHFS_DECOMP_MULTI
         if (strcmp(str, "multi") == 0) {
                 opts->thread_ops = &squashfs_decompressor_multi;
                 return 0;
         }
#endif
#ifdef CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU
         if (strcmp(str, "percpu") == 0) {
                 opts->thread_ops = &squashfs_decompressor_percpu;
                 return 0;
         }
#endif
         ret = kstrtoul(str, 0, &num);
         if (ret != 0 || num == 0)
                 return -EINVAL;
#ifdef CONFIG_SQUASHFS_DECOMP_SINGLE
         if (num == 1) {
                 opts->thread_ops = &squashfs_decompressor_single;
                 return 0;
         }
#endif
#ifdef CONFIG_SQUASHFS_DECOMP_MULTI
         opts->thread_ops = &squashfs_decompressor_multi;
         if (num > opts->thread_ops->max_decompressors())
                 num = opts->thread_ops->max_decompressors();
         opts->thread_num = (int)num;
         return 0;
#else
         return -EINVAL;
#endif
}

SNIP

static int squashfs_show_options(struct seq_file *s, struct dentry *root)
{
         struct super_block *sb = root->d_sb;
         struct squashfs_sb_info *msblk = sb->s_fs_info;

         if (msblk->panic_on_errors)
                 seq_puts(s, ",errors=panic");
         else
                 seq_puts(s, ",errors=continue");

#ifdef CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU
         /*
          * thread=percpu and thread=<number> have different 
configuration effects.
          * the parameters need to be treated differently when they are 
displayed.
          */
         if (msblk->thread_ops == &squashfs_decompressor_percpu) {
                 seq_puts(s, ",threads=percpu");
                 return 0;
         }
#endif
         seq_printf(s, ",threads=%u", msblk->max_thread_num);
         return 0;
}

static int squashfs_init_fs_context(struct fs_context *fc)
{
         struct squashfs_mount_opts *opts;

         opts = kzalloc(sizeof(*opts), GFP_KERNEL);
         if (!opts)
                 return -ENOMEM;

#ifdef CONFIG_SQUASHFS_DECOMP_DEFAULT_SINGLE
         opts->thread_ops = &squashfs_decompressor_single;
#elif defined(CONFIG_SQUASHFS_DECOMP_DEFAULT_MULTI)
         opts->thread_ops = &squashfs_decompressor_multi,
#elif defined(CONFIG_SQUASHFS_DECOMP_DEFAULT_PERCPU)
         opts->thread_ops = &squashfs_decompressor_percpu;
#endif


^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: ping //Re: [PATCH v2 0/2] squashfs: Add the mount parameter "threads="
  2022-08-30 18:34           ` Phillip Lougher
@ 2022-08-31  1:09             ` Xiaoming Ni
  0 siblings, 0 replies; 38+ messages in thread
From: Xiaoming Ni @ 2022-08-31  1:09 UTC (permalink / raw)
  To: Phillip Lougher, linux-kernel
  Cc: wangle6, yi.zhang, wangbing6, zhongjubin, chenjianguo3

On 2022/8/31 2:34, Phillip Lougher wrote:
> On 30/08/2022 19:08, Phillip Lougher wrote:
>> On 30/08/2022 14:38, Xiaoming Ni wrote:
>>> On 2022/8/29 7:18, Phillip Lougher wrote:
> 
>>>> As regards points 1 - 3, personally I would add a default kernel
>>>> configuration option that keeps the existing behaviour, build time
>>>> selectable only, no additional mount time options.  Then a
>>>> kernel configuration option that allows the different decompressors
>>>> to be selected at mount time, but which always builds all the
>>>> decompressors.  This will avoid the silliness of point 2, and
>>> Would it be better to allow flexible selection of decompression mode 
>>> combinations?
>>
>> I told you I don't like that (*).  I also told you I want the default 
>> behaviour to be the current behaviour.
>>
>> Feel free to disagree, but that isn't a good way to get your patch
>> reviewed or accepted by me.
>>
>> Cheers
>>
>> Phillip
>>
>> (*) Adding options to select the decompressor at mount time, but,
>>      also allowing only 1 - 2 decompressors to be built is a waste of
>>      time.  It has the effect of giving something with one hand and
>>      taking it alway with the other.  Build the lot, this also
>>      keeps it simple.
>>
>>
> 
> It also splatters super.c with #ifdef CONFIG lines.
> 
> phillip@phoenix:/external/stripe/linux/fs/squashfs$ grep "CONFIG_" super.c
> #ifdef CONFIG_SQUASHFS_DECOMP_SINGLE
> #ifdef CONFIG_SQUASHFS_DECOMP_MULTI
> #ifdef CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU
> #ifdef CONFIG_SQUASHFS_DECOMP_SINGLE
> #ifdef CONFIG_SQUASHFS_DECOMP_MULTI
> #ifdef CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU
> #ifdef CONFIG_SQUASHFS_DECOMP_DEFAULT_SINGLE
> #elif defined(CONFIG_SQUASHFS_DECOMP_DEFAULT_MULTI)
> #elif defined(CONFIG_SQUASHFS_DECOMP_DEFAULT_PERCPU)
> 
> Or
> 
> static int squashfs_parse_param_threads(const char *str, struct 
> squashfs_mount_opts *opts)
> {
>          unsigned long num;
>          int ret;
> #ifdef CONFIG_SQUASHFS_DECOMP_SINGLE
>          if (strcmp(str, "single") == 0) {
>                  opts->thread_ops = &squashfs_decompressor_single;
>                  return 0;
>          }
> #endif
> #ifdef CONFIG_SQUASHFS_DECOMP_MULTI
>          if (strcmp(str, "multi") == 0) {
>                  opts->thread_ops = &squashfs_decompressor_multi;
>                  return 0;
>          }
> #endif
> #ifdef CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU
>          if (strcmp(str, "percpu") == 0) {
>                  opts->thread_ops = &squashfs_decompressor_percpu;
>                  return 0;
>          }
> #endif
>          ret = kstrtoul(str, 0, &num);
>          if (ret != 0 || num == 0)
>                  return -EINVAL;
> #ifdef CONFIG_SQUASHFS_DECOMP_SINGLE
>          if (num == 1) {
>                  opts->thread_ops = &squashfs_decompressor_single;
>                  return 0;
>          }
> #endif
> #ifdef CONFIG_SQUASHFS_DECOMP_MULTI
>          opts->thread_ops = &squashfs_decompressor_multi;
>          if (num > opts->thread_ops->max_decompressors())
>                  num = opts->thread_ops->max_decompressors();
>          opts->thread_num = (int)num;
>          return 0;
> #else
>          return -EINVAL;
> #endif
> }
> 
> SNIP
> 
> static int squashfs_show_options(struct seq_file *s, struct dentry *root)
> {
>          struct super_block *sb = root->d_sb;
>          struct squashfs_sb_info *msblk = sb->s_fs_info;
> 
>          if (msblk->panic_on_errors)
>                  seq_puts(s, ",errors=panic");
>          else
>                  seq_puts(s, ",errors=continue");
> 
> #ifdef CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU
>          /*
>           * thread=percpu and thread=<number> have different 
> configuration effects.
>           * the parameters need to be treated differently when they are 
> displayed.
>           */
>          if (msblk->thread_ops == &squashfs_decompressor_percpu) {
>                  seq_puts(s, ",threads=percpu");
>                  return 0;
>          }
> #endif
>          seq_printf(s, ",threads=%u", msblk->max_thread_num);
>          return 0;
> }
> 
> static int squashfs_init_fs_context(struct fs_context *fc)
> {
>          struct squashfs_mount_opts *opts;
> 
>          opts = kzalloc(sizeof(*opts), GFP_KERNEL);
>          if (!opts)
>                  return -ENOMEM;
> 
> #ifdef CONFIG_SQUASHFS_DECOMP_DEFAULT_SINGLE
>          opts->thread_ops = &squashfs_decompressor_single;
> #elif defined(CONFIG_SQUASHFS_DECOMP_DEFAULT_MULTI)
>          opts->thread_ops = &squashfs_decompressor_multi,
> #elif defined(CONFIG_SQUASHFS_DECOMP_DEFAULT_PERCPU)
>          opts->thread_ops = &squashfs_decompressor_percpu;
> #endif
> 
> 
Thanks for your guidance, I will update it in v3 patch as soon as possible

Thanks

Xiaoming Ni



^ permalink raw reply	[flat|nested] 38+ messages in thread

* [PATCH v3 0/2] squashfs: Add the mount parameter "threads="
  2022-08-16  1:00 ` [PATCH v2 0/2] squashfs: Add the mount parameter "threads=" Xiaoming Ni
                     ` (2 preceding siblings ...)
  2022-08-26  6:19   ` ping //Re: [PATCH v2 0/2] squashfs: Add the mount parameter "threads=" Xiaoming Ni
@ 2022-09-02  9:48   ` Xiaoming Ni
  2022-09-02  9:48     ` [PATCH v3 1/2] squashfs: add the mount parameter theads=<single|multi|percpu> Xiaoming Ni
                       ` (3 more replies)
  3 siblings, 4 replies; 38+ messages in thread
From: Xiaoming Ni @ 2022-09-02  9:48 UTC (permalink / raw)
  To: linux-kernel, phillip
  Cc: nixiaoming, wangle6, yi.zhang, wangbing6, zhongjubin, chenjianguo3

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.



v3: Based on Philip Lougher's suggestion, make the following updates:
  1. The default configuration is the same as that before the patch installation.
  2. Compile the three decompression modes when the new configuration is enabled.
  3. "threads=1" supports only the SQUASHFS_DECOMP_SINGLE mode.

v2: https://lore.kernel.org/lkml/20220816010052.15764-1-nixiaoming@huawei.com/
  fix warning: sparse: incorrect type in initializer (different address spaces)
  Reported-by: kernel test robot <lkp@intel.com>

v1: https://lore.kernel.org/lkml/20220815031100.75243-1-nixiaoming@huawei.com/

Xiaoming Ni (2):
  squashfs: add the mount parameter theads=<single|multi|percpu>
  squashfs: Allows users to configure the number of decompression
    threads.

 fs/squashfs/Kconfig                     | 51 ++++++++++++++++--
 fs/squashfs/decompressor_multi.c        | 32 +++++++-----
 fs/squashfs/decompressor_multi_percpu.c | 39 ++++++++------
 fs/squashfs/decompressor_single.c       | 23 +++++---
 fs/squashfs/squashfs.h                  | 43 +++++++++++++--
 fs/squashfs/squashfs_fs_sb.h            |  4 +-
 fs/squashfs/super.c                     | 93 ++++++++++++++++++++++++++++++++-
 7 files changed, 237 insertions(+), 48 deletions(-)

-- 
2.12.3


^ permalink raw reply	[flat|nested] 38+ messages in thread

* [PATCH v3 1/2] squashfs: add the mount parameter theads=<single|multi|percpu>
  2022-09-02  9:48   ` [PATCH v3 " Xiaoming Ni
@ 2022-09-02  9:48     ` Xiaoming Ni
  2022-09-09 15:44       ` Phillip Lougher
  2022-09-09 15:50       ` Phillip Lougher
  2022-09-02  9:48     ` [PATCH v3 2/2] squashfs: Allows users to configure the number of decompression threads Xiaoming Ni
                       ` (2 subsequent siblings)
  3 siblings, 2 replies; 38+ messages in thread
From: Xiaoming Ni @ 2022-09-02  9:48 UTC (permalink / raw)
  To: linux-kernel, phillip
  Cc: nixiaoming, wangle6, yi.zhang, wangbing6, zhongjubin, chenjianguo3

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.

Signed-off-by: Xiaoming Ni <nixiaoming@huawei.com>
---
 fs/squashfs/Kconfig                     | 40 ++++++++++++++++++++++----
 fs/squashfs/decompressor_multi.c        | 28 ++++++++++--------
 fs/squashfs/decompressor_multi_percpu.c | 39 +++++++++++++++----------
 fs/squashfs/decompressor_single.c       | 23 +++++++++------
 fs/squashfs/squashfs.h                  | 43 ++++++++++++++++++++++++----
 fs/squashfs/squashfs_fs_sb.h            |  3 +-
 fs/squashfs/super.c                     | 50 ++++++++++++++++++++++++++++++++-
 7 files changed, 180 insertions(+), 46 deletions(-)

diff --git a/fs/squashfs/Kconfig b/fs/squashfs/Kconfig
index 916e78fabcaa..9c2827459f40 100644
--- a/fs/squashfs/Kconfig
+++ b/fs/squashfs/Kconfig
@@ -54,9 +54,37 @@ 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
@@ -64,15 +92,17 @@ choice
 
 	  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
@@ -85,8 +115,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
@@ -95,7 +126,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
diff --git a/fs/squashfs/decompressor_multi.c b/fs/squashfs/decompressor_multi.c
index db9f12a3ea05..7b2723b77e75 100644
--- a/fs/squashfs/decompressor_multi.c
+++ b/fs/squashfs/decompressor_multi.c
@@ -29,13 +29,12 @@
 #define MAX_DECOMPRESSOR	(num_online_cpus() * 2)
 
 
-int squashfs_max_decompressors(void)
+static int squashfs_max_decompressors_multi(void)
 {
 	return MAX_DECOMPRESSOR;
 }
 
-
-struct squashfs_stream {
+struct squashfs_stream_multi {
 	void			*comp_opts;
 	struct list_head	strm_list;
 	struct mutex		mutex;
@@ -51,7 +50,7 @@ struct decomp_stream {
 
 
 static void put_decomp_stream(struct decomp_stream *decomp_strm,
-				struct squashfs_stream *stream)
+				struct squashfs_stream_multi *stream)
 {
 	mutex_lock(&stream->mutex);
 	list_add(&decomp_strm->list, &stream->strm_list);
@@ -59,10 +58,10 @@ 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_multi(struct squashfs_sb_info *msblk,
 				void *comp_opts)
 {
-	struct squashfs_stream *stream;
+	struct squashfs_stream_multi *stream;
 	struct decomp_stream *decomp_strm = NULL;
 	int err = -ENOMEM;
 
@@ -103,9 +102,9 @@ void *squashfs_decompressor_create(struct squashfs_sb_info *msblk,
 }
 
 
-void squashfs_decompressor_destroy(struct squashfs_sb_info *msblk)
+static void squashfs_decompressor_destroy_multi(struct squashfs_sb_info *msblk)
 {
-	struct squashfs_stream *stream = msblk->stream;
+	struct squashfs_stream_multi *stream = msblk->stream;
 	if (stream) {
 		struct decomp_stream *decomp_strm;
 
@@ -125,7 +124,7 @@ void squashfs_decompressor_destroy(struct squashfs_sb_info *msblk)
 
 
 static struct decomp_stream *get_decomp_stream(struct squashfs_sb_info *msblk,
-					struct squashfs_stream *stream)
+					struct squashfs_stream_multi *stream)
 {
 	struct decomp_stream *decomp_strm;
 
@@ -180,12 +179,12 @@ 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_multi(struct squashfs_sb_info *msblk, struct bio *bio,
 			int offset, int length,
 			struct squashfs_page_actor *output)
 {
 	int res;
-	struct squashfs_stream *stream = msblk->stream;
+	struct squashfs_stream_multi *stream = msblk->stream;
 	struct decomp_stream *decomp_stream = get_decomp_stream(msblk, stream);
 	res = msblk->decompressor->decompress(msblk, decomp_stream->stream,
 		bio, offset, length, output);
@@ -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_multi,
+	.destroy = squashfs_decompressor_destroy_multi,
+	.decompress = squashfs_decompress_multi,
+	.max_decompressors = squashfs_max_decompressors_multi,
+};
diff --git a/fs/squashfs/decompressor_multi_percpu.c b/fs/squashfs/decompressor_multi_percpu.c
index b881b9283b7f..e24455a7b04d 100644
--- a/fs/squashfs/decompressor_multi_percpu.c
+++ b/fs/squashfs/decompressor_multi_percpu.c
@@ -20,19 +20,19 @@
  * variables, one thread per cpu core.
  */
 
-struct squashfs_stream {
+struct squashfs_stream_percpu {
 	void			*stream;
 	local_lock_t	lock;
 };
 
-void *squashfs_decompressor_create(struct squashfs_sb_info *msblk,
+static void *squashfs_decompressor_create_percpu(struct squashfs_sb_info *msblk,
 						void *comp_opts)
 {
-	struct squashfs_stream *stream;
-	struct squashfs_stream __percpu *percpu;
+	struct squashfs_stream_percpu *stream;
+	struct squashfs_stream_percpu __percpu *percpu;
 	int err, cpu;
 
-	percpu = alloc_percpu(struct squashfs_stream);
+	percpu = alloc_percpu(struct squashfs_stream_percpu);
 	if (percpu == NULL)
 		return ERR_PTR(-ENOMEM);
 
@@ -59,11 +59,11 @@ 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_percpu(struct squashfs_sb_info *msblk)
 {
-	struct squashfs_stream __percpu *percpu =
-			(struct squashfs_stream __percpu *) msblk->stream;
-	struct squashfs_stream *stream;
+	struct squashfs_stream_percpu __percpu *percpu =
+			(struct squashfs_stream_percpu __percpu *) msblk->stream;
+	struct squashfs_stream_percpu *stream;
 	int cpu;
 
 	if (msblk->stream) {
@@ -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_percpu(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 *stream;
+	struct squashfs_stream_percpu __percpu *percpu =
+			(struct squashfs_stream_percpu __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",
@@ -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_percpu(void)
 {
 	return num_possible_cpus();
 }
+
+const struct squashfs_decompressor_thread_ops squashfs_decompressor_percpu = {
+	.create = squashfs_decompressor_create_percpu,
+	.destroy = squashfs_decompressor_destroy_percpu,
+	.decompress = squashfs_decompress_percpu,
+	.max_decompressors = squashfs_max_decompressors_percpu,
+};
diff --git a/fs/squashfs/decompressor_single.c b/fs/squashfs/decompressor_single.c
index 4eb3d083d45e..41449de0ea4c 100644
--- a/fs/squashfs/decompressor_single.c
+++ b/fs/squashfs/decompressor_single.c
@@ -19,15 +19,15 @@
  * decompressor framework
  */
 
-struct squashfs_stream {
+struct squashfs_stream_single {
 	void		*stream;
 	struct mutex	mutex;
 };
 
-void *squashfs_decompressor_create(struct squashfs_sb_info *msblk,
+static void *squashfs_decompressor_create_single(struct squashfs_sb_info *msblk,
 						void *comp_opts)
 {
-	struct squashfs_stream *stream;
+	struct squashfs_stream_single *stream;
 	int err = -ENOMEM;
 
 	stream = kmalloc(sizeof(*stream), GFP_KERNEL);
@@ -49,9 +49,9 @@ 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_single(struct squashfs_sb_info *msblk)
 {
-	struct squashfs_stream *stream = msblk->stream;
+	struct squashfs_stream_single *stream = msblk->stream;
 
 	if (stream) {
 		msblk->decompressor->free(stream->stream);
@@ -59,12 +59,12 @@ void squashfs_decompressor_destroy(struct squashfs_sb_info *msblk)
 	}
 }
 
-int squashfs_decompress(struct squashfs_sb_info *msblk, struct bio *bio,
+static int squashfs_decompress_single(struct squashfs_sb_info *msblk, struct bio *bio,
 			int offset, int length,
 			struct squashfs_page_actor *output)
 {
 	int res;
-	struct squashfs_stream *stream = msblk->stream;
+	struct squashfs_stream_single *stream = msblk->stream;
 
 	mutex_lock(&stream->mutex);
 	res = msblk->decompressor->decompress(msblk, stream->stream, bio,
@@ -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_single(void)
 {
 	return 1;
 }
+
+const struct squashfs_decompressor_thread_ops squashfs_decompressor_single = {
+	.create = squashfs_decompressor_create_single,
+	.destroy = squashfs_decompressor_destroy_single,
+	.decompress = squashfs_decompress_single,
+	.max_decompressors = squashfs_max_decompressors_single,
+};
diff --git a/fs/squashfs/squashfs.h b/fs/squashfs/squashfs.h
index 9783e01c8100..9a383ad0dae0 100644
--- a/fs/squashfs/squashfs.h
+++ b/fs/squashfs/squashfs.h
@@ -38,12 +38,45 @@ 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
+
+static inline void *squashfs_decompressor_create(struct squashfs_sb_info *msblk, void *comp_opts)
+{
+	return msblk->thread_ops->create(msblk, comp_opts);
+}
+
+static inline void squashfs_decompressor_destroy(struct squashfs_sb_info *msblk)
+{
+	msblk->thread_ops->destroy(msblk);
+}
+
+static inline int squashfs_decompress(struct squashfs_sb_info *msblk, struct bio *bio,
+				      int offset, int length, struct squashfs_page_actor *output)
+{
+	return msblk->thread_ops->decompress(msblk, bio, offset, length, output);
+}
+
+static inline int squashfs_max_decompressors(struct squashfs_sb_info *msblk)
+{
+	return msblk->thread_ops->max_decompressors();
+}
 /* export.c */
 extern __le64 *squashfs_read_inode_lookup_table(struct super_block *, u64, u64,
 				unsigned int);
diff --git a/fs/squashfs/squashfs_fs_sb.h b/fs/squashfs/squashfs_fs_sb.h
index 1e90c2575f9b..f1e5dad8ae0a 100644
--- a/fs/squashfs/squashfs_fs_sb.h
+++ b/fs/squashfs/squashfs_fs_sb.h
@@ -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;
@@ -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
diff --git a/fs/squashfs/super.c b/fs/squashfs/super.c
index 32565dafa7f3..fd4e70d45f3c 100644
--- a/fs/squashfs/super.c
+++ b/fs/squashfs/super.c
@@ -47,10 +47,12 @@ enum Opt_errors {
 
 enum squashfs_param {
 	Opt_errors,
+	Opt_threads,
 };
 
 struct squashfs_mount_opts {
 	enum Opt_errors errors;
+	const struct squashfs_decompressor_thread_ops *thread_ops;
 };
 
 static const struct constant_table squashfs_param_errors[] = {
@@ -61,9 +63,29 @@ static const struct constant_table squashfs_param_errors[] = {
 
 static const struct fs_parameter_spec squashfs_fs_parameters[] = {
 	fsparam_enum("errors", Opt_errors, squashfs_param_errors),
+	fsparam_string("threads", Opt_threads),
 	{}
 };
 
+static int squashfs_parse_param_threads(const char *str, struct squashfs_mount_opts *opts)
+{
+#ifdef CONFIG_SQUASHFS_CHOICE_DECOMP_BY_MOUNT
+	if (strcmp(str, "single") == 0) {
+		opts->thread_ops = &squashfs_decompressor_single;
+		return 0;
+	}
+	if (strcmp(str, "multi") == 0) {
+		opts->thread_ops = &squashfs_decompressor_multi;
+		return 0;
+	}
+	if (strcmp(str, "percpu") == 0) {
+		opts->thread_ops = &squashfs_decompressor_percpu;
+		return 0;
+	}
+#endif
+	return -EINVAL;
+}
+
 static int squashfs_parse_param(struct fs_context *fc, struct fs_parameter *param)
 {
 	struct squashfs_mount_opts *opts = fc->fs_private;
@@ -78,6 +100,10 @@ static int squashfs_parse_param(struct fs_context *fc, struct fs_parameter *para
 	case Opt_errors:
 		opts->errors = result.uint_32;
 		break;
+	case Opt_threads:
+		if (squashfs_parse_param_threads(param->string, opts) != 0)
+			return -EINVAL;
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -167,6 +193,7 @@ static int squashfs_fill_super(struct super_block *sb, struct fs_context *fc)
 			       sb->s_bdev);
 		goto failed_mount;
 	}
+	msblk->thread_ops = opts->thread_ops;
 
 	/* Check the MAJOR & MINOR versions and lookup compression type */
 	msblk->decompressor = supported_squashfs_filesystem(
@@ -252,7 +279,7 @@ static int squashfs_fill_super(struct super_block *sb, struct fs_context *fc)
 
 	/* Allocate read_page block */
 	msblk->read_page = squashfs_cache_init("data",
-		squashfs_max_decompressors(), msblk->block_size);
+		squashfs_max_decompressors(msblk), msblk->block_size);
 	if (msblk->read_page == NULL) {
 		errorf(fc, "Failed to allocate read_page block");
 		goto failed_mount;
@@ -435,6 +462,20 @@ static int squashfs_show_options(struct seq_file *s, struct dentry *root)
 	else
 		seq_puts(s, ",errors=continue");
 
+#ifdef CONFIG_SQUASHFS_CHOICE_DECOMP_BY_MOUNT
+	if (msblk->thread_ops == &squashfs_decompressor_single) {
+		seq_puts(s, ",threads=single");
+		return 0;
+	}
+	if (msblk->thread_ops == &squashfs_decompressor_multi) {
+		seq_puts(s, ",threads=multi");
+		return 0;
+	}
+	if (msblk->thread_ops == &squashfs_decompressor_percpu) {
+		seq_puts(s, ",threads=percpu");
+		return 0;
+	}
+#endif
 	return 0;
 }
 
@@ -446,6 +487,13 @@ static int squashfs_init_fs_context(struct fs_context *fc)
 	if (!opts)
 		return -ENOMEM;
 
+#ifdef CONFIG_SQUASHFS_DECOMP_SINGLE
+	opts->thread_ops = &squashfs_decompressor_single;
+#elif CONFIG_SQUASHFS_DECOMP_MULTI
+	opts->thread_ops = &squashfs_decompressor_multi;
+#elif CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU
+	opts->thread_ops = &squashfs_decompressor_percpu;
+#endif
 	fc->fs_private = opts;
 	fc->ops = &squashfs_context_ops;
 	return 0;
-- 
2.12.3


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH v3 2/2] squashfs: Allows users to configure the number of decompression threads.
  2022-09-02  9:48   ` [PATCH v3 " Xiaoming Ni
  2022-09-02  9:48     ` [PATCH v3 1/2] squashfs: add the mount parameter theads=<single|multi|percpu> Xiaoming Ni
@ 2022-09-02  9:48     ` Xiaoming Ni
  2022-09-09 15:26     ` [PATCH v3 0/2] squashfs: Add the mount parameter "threads=" Phillip Lougher
  2022-09-16  8:36     ` [PATCH v4 " Xiaoming Ni
  3 siblings, 0 replies; 38+ messages in thread
From: Xiaoming Ni @ 2022-09-02  9:48 UTC (permalink / raw)
  To: linux-kernel, phillip
  Cc: nixiaoming, wangle6, yi.zhang, wangbing6, zhongjubin, chenjianguo3

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.

Signed-off-by: Xiaoming Ni <nixiaoming@huawei.com>
---
 fs/squashfs/Kconfig              | 17 +++++++++--
 fs/squashfs/decompressor_multi.c |  4 +--
 fs/squashfs/squashfs_fs_sb.h     |  1 +
 fs/squashfs/super.c              | 63 +++++++++++++++++++++++++++++++++-------
 4 files changed, 70 insertions(+), 15 deletions(-)

diff --git a/fs/squashfs/Kconfig b/fs/squashfs/Kconfig
index 9c2827459f40..60fc98bdf421 100644
--- a/fs/squashfs/Kconfig
+++ b/fs/squashfs/Kconfig
@@ -73,12 +73,10 @@ config SQUASHFS_CHOICE_DECOMP_BY_MOUNT
 	select SQUASHFS_DECOMP_SINGLE
 	select SQUASHFS_DECOMP_MULTI
 	select SQUASHFS_DECOMP_MULTI_PERCPU
+	select SQUASHFS_MOUNT_DECOMP_THREADS
 	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
@@ -128,6 +126,19 @@ config SQUASHFS_COMPILE_DECOMP_MULTI_PERCPU
 	  decompression is load-balanced across the cores.
 endchoice
 
+config SQUASHFS_MOUNT_DECOMP_THREADS
+	bool "Add the mount parameter 'threads=' for squashfs"
+	depends on SQUASHFS
+	depends on SQUASHFS_DECOMP_MULTI
+	default n
+	help
+	  Use threads= to set the decompression parallel mode and the number of threads.
+	  If SQUASHFS_CHOICE_DECOMP_BY_MOUNT=y
+	      threads=<single|multi|percpu|1|2|3|...>
+	  else
+	      threads=<2|3|...>
+	  The upper limit is num_online_cpus() * 2.
+
 config SQUASHFS_XATTR
 	bool "Squashfs XATTR support"
 	depends on SQUASHFS
diff --git a/fs/squashfs/decompressor_multi.c b/fs/squashfs/decompressor_multi.c
index 7b2723b77e75..6d1cea325cca 100644
--- a/fs/squashfs/decompressor_multi.c
+++ b/fs/squashfs/decompressor_multi.c
@@ -144,7 +144,7 @@ static struct decomp_stream *get_decomp_stream(struct squashfs_sb_info *msblk,
 		 * If there is no available decomp and already full,
 		 * let's wait for releasing decomp from other users.
 		 */
-		if (stream->avail_decomp >= MAX_DECOMPRESSOR)
+		if (stream->avail_decomp >= msblk->max_thread_num)
 			goto wait;
 
 		/* Let's allocate new decomp */
@@ -160,7 +160,7 @@ static struct decomp_stream *get_decomp_stream(struct squashfs_sb_info *msblk,
 		}
 
 		stream->avail_decomp++;
-		WARN_ON(stream->avail_decomp > MAX_DECOMPRESSOR);
+		WARN_ON(stream->avail_decomp > msblk->max_thread_num);
 
 		mutex_unlock(&stream->mutex);
 		break;
diff --git a/fs/squashfs/squashfs_fs_sb.h b/fs/squashfs/squashfs_fs_sb.h
index f1e5dad8ae0a..659082e9e51d 100644
--- a/fs/squashfs/squashfs_fs_sb.h
+++ b/fs/squashfs/squashfs_fs_sb.h
@@ -67,5 +67,6 @@ struct squashfs_sb_info {
 	unsigned int				ids;
 	bool					panic_on_errors;
 	const struct squashfs_decompressor_thread_ops *thread_ops;
+	int					max_thread_num;
 };
 #endif
diff --git a/fs/squashfs/super.c b/fs/squashfs/super.c
index fd4e70d45f3c..5705749e7d44 100644
--- a/fs/squashfs/super.c
+++ b/fs/squashfs/super.c
@@ -53,6 +53,7 @@ enum squashfs_param {
 struct squashfs_mount_opts {
 	enum Opt_errors errors;
 	const struct squashfs_decompressor_thread_ops *thread_ops;
+	int thread_num;
 };
 
 static const struct constant_table squashfs_param_errors[] = {
@@ -67,7 +68,8 @@ static const struct fs_parameter_spec squashfs_fs_parameters[] = {
 	{}
 };
 
-static int squashfs_parse_param_threads(const char *str, struct squashfs_mount_opts *opts)
+
+static int squashfs_parse_param_threads_str(const char *str, struct squashfs_mount_opts *opts)
 {
 #ifdef CONFIG_SQUASHFS_CHOICE_DECOMP_BY_MOUNT
 	if (strcmp(str, "single") == 0) {
@@ -86,6 +88,42 @@ static int squashfs_parse_param_threads(const char *str, struct squashfs_mount_o
 	return -EINVAL;
 }
 
+static int squashfs_parse_param_threads_num(const char *str, struct squashfs_mount_opts *opts)
+{
+#ifdef CONFIG_SQUASHFS_MOUNT_DECOMP_THREADS
+	int ret;
+	unsigned long num;
+
+	ret = kstrtoul(str, 0, &num);
+	if (ret != 0)
+		return -EINVAL;
+	if (num > 1) {
+		opts->thread_ops = &squashfs_decompressor_multi;
+		if (num > opts->thread_ops->max_decompressors())
+			return -EINVAL;
+		opts->thread_num = (int)num;
+		return 0;
+	}
+#ifdef CONFIG_SQUASHFS_DECOMP_SINGLE
+	if (num == 1) {
+		opts->thread_ops = &squashfs_decompressor_single;
+		opts->thread_num = 1;
+		return 0;
+	}
+#endif
+#endif /* !CONFIG_SQUASHFS_MOUNT_DECOMP_THREADS */
+	return -EINVAL;
+}
+
+static int squashfs_parse_param_threads(const char *str, struct squashfs_mount_opts *opts)
+{
+	int ret = squashfs_parse_param_threads_str(str, opts);
+
+	if (ret == 0)
+		return ret;
+	return squashfs_parse_param_threads_num(str, opts);
+}
+
 static int squashfs_parse_param(struct fs_context *fc, struct fs_parameter *param)
 {
 	struct squashfs_mount_opts *opts = fc->fs_private;
@@ -194,6 +232,11 @@ static int squashfs_fill_super(struct super_block *sb, struct fs_context *fc)
 		goto failed_mount;
 	}
 	msblk->thread_ops = opts->thread_ops;
+	if (opts->thread_num == 0) {
+		msblk->max_thread_num = squashfs_max_decompressors(msblk);
+	} else {
+		msblk->max_thread_num = opts->thread_num;
+	}
 
 	/* Check the MAJOR & MINOR versions and lookup compression type */
 	msblk->decompressor = supported_squashfs_filesystem(
@@ -279,7 +322,7 @@ static int squashfs_fill_super(struct super_block *sb, struct fs_context *fc)
 
 	/* Allocate read_page block */
 	msblk->read_page = squashfs_cache_init("data",
-		squashfs_max_decompressors(msblk), msblk->block_size);
+		msblk->max_thread_num, msblk->block_size);
 	if (msblk->read_page == NULL) {
 		errorf(fc, "Failed to allocate read_page block");
 		goto failed_mount;
@@ -463,18 +506,17 @@ static int squashfs_show_options(struct seq_file *s, struct dentry *root)
 		seq_puts(s, ",errors=continue");
 
 #ifdef CONFIG_SQUASHFS_CHOICE_DECOMP_BY_MOUNT
-	if (msblk->thread_ops == &squashfs_decompressor_single) {
-		seq_puts(s, ",threads=single");
-		return 0;
-	}
-	if (msblk->thread_ops == &squashfs_decompressor_multi) {
-		seq_puts(s, ",threads=multi");
-		return 0;
-	}
 	if (msblk->thread_ops == &squashfs_decompressor_percpu) {
 		seq_puts(s, ",threads=percpu");
 		return 0;
 	}
+	if (msblk->thread_ops == &squashfs_decompressor_single) {
+		seq_puts(s, ",threads=single");
+		return 0;
+	}
+#endif
+#ifdef CONFIG_SQUASHFS_MOUNT_DECOMP_THREADS
+	seq_printf(s, ",threads=%d", msblk->max_thread_num);
 #endif
 	return 0;
 }
@@ -494,6 +536,7 @@ static int squashfs_init_fs_context(struct fs_context *fc)
 #elif CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU
 	opts->thread_ops = &squashfs_decompressor_percpu;
 #endif
+	opts->thread_num = 0;
 	fc->fs_private = opts;
 	fc->ops = &squashfs_context_ops;
 	return 0;
-- 
2.12.3


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* Re: [PATCH v3 0/2] squashfs: Add the mount parameter "threads="
  2022-09-02  9:48   ` [PATCH v3 " Xiaoming Ni
  2022-09-02  9:48     ` [PATCH v3 1/2] squashfs: add the mount parameter theads=<single|multi|percpu> Xiaoming Ni
  2022-09-02  9:48     ` [PATCH v3 2/2] squashfs: Allows users to configure the number of decompression threads Xiaoming Ni
@ 2022-09-09 15:26     ` Phillip Lougher
  2022-09-16  8:36     ` [PATCH v4 " Xiaoming Ni
  3 siblings, 0 replies; 38+ messages in thread
From: Phillip Lougher @ 2022-09-09 15:26 UTC (permalink / raw)
  To: Xiaoming Ni, linux-kernel
  Cc: wangle6, yi.zhang, wangbing6, zhongjubin, chenjianguo3

On 02/09/2022 10:48, Xiaoming Ni wrote:
> 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.
> 
> 
> 
> v3: Based on Philip Lougher's suggestion, make the following updates:
>    1. The default configuration is the same as that before the patch installation.
>    2. Compile the three decompression modes when the new configuration is enabled.
>    3. "threads=1" supports only the SQUASHFS_DECOMP_SINGLE mode.
> 

Hi,

This patch-set looks a lot better IMHO.  I only have a couple of
relatively minor issues, which will be dealt with as comments on
the patches.

Phillip

> v2: https://lore.kernel.org/lkml/20220816010052.15764-1-nixiaoming@huawei.com/
>    fix warning: sparse: incorrect type in initializer (different address spaces)
>    Reported-by: kernel test robot <lkp@intel.com>
> 
> v1: https://lore.kernel.org/lkml/20220815031100.75243-1-nixiaoming@huawei.com/
> 
> Xiaoming Ni (2):
>    squashfs: add the mount parameter theads=<single|multi|percpu>
>    squashfs: Allows users to configure the number of decompression
>      threads.
> 
>   fs/squashfs/Kconfig                     | 51 ++++++++++++++++--
>   fs/squashfs/decompressor_multi.c        | 32 +++++++-----
>   fs/squashfs/decompressor_multi_percpu.c | 39 ++++++++------
>   fs/squashfs/decompressor_single.c       | 23 +++++---
>   fs/squashfs/squashfs.h                  | 43 +++++++++++++--
>   fs/squashfs/squashfs_fs_sb.h            |  4 +-
>   fs/squashfs/super.c                     | 93 ++++++++++++++++++++++++++++++++-
>   7 files changed, 237 insertions(+), 48 deletions(-)
> 


^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH v3 1/2] squashfs: add the mount parameter theads=<single|multi|percpu>
  2022-09-02  9:48     ` [PATCH v3 1/2] squashfs: add the mount parameter theads=<single|multi|percpu> Xiaoming Ni
@ 2022-09-09 15:44       ` Phillip Lougher
  2022-09-13  2:46         ` Xiaoming Ni
  2022-09-09 15:50       ` Phillip Lougher
  1 sibling, 1 reply; 38+ messages in thread
From: Phillip Lougher @ 2022-09-09 15:44 UTC (permalink / raw)
  To: nixiaoming
  Cc: chenjianguo3, linux-kernel, phillip, wangbing6, wangle6,
	yi.zhang, zhongjubin

Review comments below.

Xiaoming Ni <nixiaoming@huawei.com> wrote:
>Squashfs supports three decompression concurrency modes:
>	Single-thread mode: concurrent reads are blocked and the memory overhead
>is small.

Please wrap over 80 column line.

>	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.
>
>Signed-off-by: Xiaoming Ni <nixiaoming@huawei.com>
>---
> fs/squashfs/Kconfig                     | 40 ++++++++++++++++++++++----
> fs/squashfs/decompressor_multi.c        | 28 ++++++++++--------
> fs/squashfs/decompressor_multi_percpu.c | 39 +++++++++++++++----------
> fs/squashfs/decompressor_single.c       | 23 +++++++++------
> fs/squashfs/squashfs.h                  | 43 ++++++++++++++++++++++++----
> fs/squashfs/squashfs_fs_sb.h            |  3 +-
> fs/squashfs/super.c                     | 50 ++++++++++++++++++++++++++++++++-
> 7 files changed, 180 insertions(+), 46 deletions(-)
>
>diff --git a/fs/squashfs/Kconfig b/fs/squashfs/Kconfig
>index 916e78fabcaa..9c2827459f40 100644
>--- a/fs/squashfs/Kconfig
>+++ b/fs/squashfs/Kconfig
>@@ -54,9 +54,37 @@ 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>

git am reports "warning: 1 line adds whitespace errors.", which is here.

[SNIP]

>diff --git a/fs/squashfs/decompressor_multi.c b/fs/squashfs/decompressor_multi.c
>index db9f12a3ea05..7b2723b77e75 100644
>--- a/fs/squashfs/decompressor_multi.c
>+++ b/fs/squashfs/decompressor_multi.c
>@@ -29,13 +29,12 @@
> #define MAX_DECOMPRESSOR	(num_online_cpus() * 2)
> 
> 
>-int squashfs_max_decompressors(void)
>+static int squashfs_max_decompressors_multi(void)

Changing the name of the function *should* be unnecessary, because
you're making it static.

> {
> 	return MAX_DECOMPRESSOR;
> }
> 
>-
>-struct squashfs_stream {
>+struct squashfs_stream_multi {

Again changing the name of the structure should be unnecessary.

This is just extra noise.

The current "diffstat" for the 3 decompression threading implementations is:

fs/squashfs/decompressor_multi.c        | 28 ++++++++++--------
fs/squashfs/decompressor_multi_percpu.c | 39 +++++++++++++++----------
fs/squashfs/decompressor_single.c       | 23 +++++++++------

But, once you get rid of this noise, it drops to

fs/squashfs/decompressor_multi.c        | 16 +++++---
fs/squashfs/decompressor_multi_percpu.c | 23 +++++++----
fs/squashfs/decompressor_single.c       | 15 ++++++--

[SNIP]

>--- a/fs/squashfs/squashfs.h
>+++ b/fs/squashfs/squashfs.h
>@@ -38,12 +38,45 @@ extern const struct squashfs_decompressor *squashfs_lookup_decompressor(int);
> extern void *squashfs_decompressor_setup(struct super_block *, unsigned short);
> 
> /* decompressor_xxx.c */

[SNIP]

>+
>+static inline void *squashfs_decompressor_create(struct squashfs_sb_info *msblk, void *comp_opts)
>+{
>+	return msblk->thread_ops->create(msblk, comp_opts);
>+}
>+
>+static inline void squashfs_decompressor_destroy(struct squashfs_sb_info *msblk)
>+{
>+	msblk->thread_ops->destroy(msblk);
>+}
>+
>+static inline int squashfs_decompress(struct squashfs_sb_info *msblk, struct bio *bio,
>+				      int offset, int length, struct squashfs_page_actor *output)
>+{
>+	return msblk->thread_ops->decompress(msblk, bio, offset, length, output);
>+}
>+
>+static inline int squashfs_max_decompressors(struct squashfs_sb_info *msblk)
>+{
>+	return msblk->thread_ops->max_decompressors();
>+}

The above is the reason why you've had to rename the functions in the
decompression threading implementations.  Because you've put the new
accessors into squashfs.h which is also included by the threading
implementations which causes a name clash.

But, the correct way to avoid this clash, is to put the accessors into
a new header file, which isn't included by the decompression threading
implementations.

The following patch does this cleanup, to simplify the patch here.  It also
moves the struct squashfs_decompressor_thread_ops definition into
decompressor.h which is a better place.

Phillip

 fs/squashfs/block.c                     |  1 +
 fs/squashfs/decompressor.c              |  1 +
 fs/squashfs/decompressor.h              |  8 +++++
 fs/squashfs/decompressor_multi.c        | 28 ++++++++---------
 fs/squashfs/decompressor_multi_percpu.c | 36 +++++++++++-----------
 fs/squashfs/decompressor_single.c       | 24 +++++++--------
 fs/squashfs/squashfs.h                  | 40 -------------------------
 fs/squashfs/super.c                     |  1 +
 fs/squashfs/threading.h                 | 30 +++++++++++++++++++
 9 files changed, 85 insertions(+), 84 deletions(-)
 create mode 100644 fs/squashfs/threading.h

diff --git a/fs/squashfs/block.c b/fs/squashfs/block.c
index 833aca92301f..9bcf7e1b64be 100644
--- a/fs/squashfs/block.c
+++ b/fs/squashfs/block.c
@@ -26,6 +26,7 @@
 #include "squashfs.h"
 #include "decompressor.h"
 #include "page_actor.h"
+#include "threading.h"
 
 /*
  * Returns the amount of bytes copied to the page actor.
diff --git a/fs/squashfs/decompressor.c b/fs/squashfs/decompressor.c
index d57bef91ab08..5c355fca0df5 100644
--- a/fs/squashfs/decompressor.c
+++ b/fs/squashfs/decompressor.c
@@ -18,6 +18,7 @@
 #include "decompressor.h"
 #include "squashfs.h"
 #include "page_actor.h"
+#include "threading.h"
 
 /*
  * This file (and decompressor.h) implements a decompressor framework for
diff --git a/fs/squashfs/decompressor.h b/fs/squashfs/decompressor.h
index 19ab60834389..5b5ec4828930 100644
--- a/fs/squashfs/decompressor.h
+++ b/fs/squashfs/decompressor.h
@@ -24,6 +24,14 @@ struct squashfs_decompressor {
 	int	supported;
 };
 
+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);
+};
+
 static inline void *squashfs_comp_opts(struct squashfs_sb_info *msblk,
 							void *buff, int length)
 {
diff --git a/fs/squashfs/decompressor_multi.c b/fs/squashfs/decompressor_multi.c
index 7b2723b77e75..eb25432bd149 100644
--- a/fs/squashfs/decompressor_multi.c
+++ b/fs/squashfs/decompressor_multi.c
@@ -29,12 +29,12 @@
 #define MAX_DECOMPRESSOR	(num_online_cpus() * 2)
 
 
-static int squashfs_max_decompressors_multi(void)
+static int squashfs_max_decompressors(void)
 {
 	return MAX_DECOMPRESSOR;
 }
 
-struct squashfs_stream_multi {
+struct squashfs_stream {
 	void			*comp_opts;
 	struct list_head	strm_list;
 	struct mutex		mutex;
@@ -50,7 +50,7 @@ struct decomp_stream {
 
 
 static void put_decomp_stream(struct decomp_stream *decomp_strm,
-				struct squashfs_stream_multi *stream)
+				struct squashfs_stream *stream)
 {
 	mutex_lock(&stream->mutex);
 	list_add(&decomp_strm->list, &stream->strm_list);
@@ -58,10 +58,10 @@ static void put_decomp_stream(struct decomp_stream *decomp_strm,
 	wake_up(&stream->wait);
 }
 
-static void *squashfs_decompressor_create_multi(struct squashfs_sb_info *msblk,
+static void *squashfs_decompressor_create(struct squashfs_sb_info *msblk,
 				void *comp_opts)
 {
-	struct squashfs_stream_multi *stream;
+	struct squashfs_stream *stream;
 	struct decomp_stream *decomp_strm = NULL;
 	int err = -ENOMEM;
 
@@ -102,9 +102,9 @@ static void *squashfs_decompressor_create_multi(struct squashfs_sb_info *msblk,
 }
 
 
-static void squashfs_decompressor_destroy_multi(struct squashfs_sb_info *msblk)
+static void squashfs_decompressor_destroy(struct squashfs_sb_info *msblk)
 {
-	struct squashfs_stream_multi *stream = msblk->stream;
+	struct squashfs_stream *stream = msblk->stream;
 	if (stream) {
 		struct decomp_stream *decomp_strm;
 
@@ -124,7 +124,7 @@ static void squashfs_decompressor_destroy_multi(struct squashfs_sb_info *msblk)
 
 
 static struct decomp_stream *get_decomp_stream(struct squashfs_sb_info *msblk,
-					struct squashfs_stream_multi *stream)
+					struct squashfs_stream *stream)
 {
 	struct decomp_stream *decomp_strm;
 
@@ -179,12 +179,12 @@ static struct decomp_stream *get_decomp_stream(struct squashfs_sb_info *msblk,
 }
 
 
-static int squashfs_decompress_multi(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)
 {
 	int res;
-	struct squashfs_stream_multi *stream = msblk->stream;
+	struct squashfs_stream *stream = msblk->stream;
 	struct decomp_stream *decomp_stream = get_decomp_stream(msblk, stream);
 	res = msblk->decompressor->decompress(msblk, decomp_stream->stream,
 		bio, offset, length, output);
@@ -196,8 +196,8 @@ static int squashfs_decompress_multi(struct squashfs_sb_info *msblk, struct bio
 }
 
 const struct squashfs_decompressor_thread_ops squashfs_decompressor_multi = {
-	.create = squashfs_decompressor_create_multi,
-	.destroy = squashfs_decompressor_destroy_multi,
-	.decompress = squashfs_decompress_multi,
-	.max_decompressors = squashfs_max_decompressors_multi,
+	.create = squashfs_decompressor_create,
+	.destroy = squashfs_decompressor_destroy,
+	.decompress = squashfs_decompress,
+	.max_decompressors = squashfs_max_decompressors,
 };
diff --git a/fs/squashfs/decompressor_multi_percpu.c b/fs/squashfs/decompressor_multi_percpu.c
index e24455a7b04d..1dfadf76ed9a 100644
--- a/fs/squashfs/decompressor_multi_percpu.c
+++ b/fs/squashfs/decompressor_multi_percpu.c
@@ -20,19 +20,19 @@
  * variables, one thread per cpu core.
  */
 
-struct squashfs_stream_percpu {
+struct squashfs_stream {
 	void			*stream;
 	local_lock_t	lock;
 };
 
-static void *squashfs_decompressor_create_percpu(struct squashfs_sb_info *msblk,
+static void *squashfs_decompressor_create(struct squashfs_sb_info *msblk,
 						void *comp_opts)
 {
-	struct squashfs_stream_percpu *stream;
-	struct squashfs_stream_percpu __percpu *percpu;
+	struct squashfs_stream *stream;
+	struct squashfs_stream __percpu *percpu;
 	int err, cpu;
 
-	percpu = alloc_percpu(struct squashfs_stream_percpu);
+	percpu = alloc_percpu(struct squashfs_stream);
 	if (percpu == NULL)
 		return ERR_PTR(-ENOMEM);
 
@@ -59,11 +59,11 @@ static void *squashfs_decompressor_create_percpu(struct squashfs_sb_info *msblk,
 	return ERR_PTR(err);
 }
 
-static void squashfs_decompressor_destroy_percpu(struct squashfs_sb_info *msblk)
+static void squashfs_decompressor_destroy(struct squashfs_sb_info *msblk)
 {
-	struct squashfs_stream_percpu __percpu *percpu =
-			(struct squashfs_stream_percpu __percpu *) msblk->stream;
-	struct squashfs_stream_percpu *stream;
+	struct squashfs_stream __percpu *percpu =
+			(struct squashfs_stream __percpu *) msblk->stream;
+	struct squashfs_stream *stream;
 	int cpu;
 
 	if (msblk->stream) {
@@ -75,12 +75,12 @@ static void squashfs_decompressor_destroy_percpu(struct squashfs_sb_info *msblk)
 	}
 }
 
-static int squashfs_decompress_percpu(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_percpu *stream;
-	struct squashfs_stream_percpu __percpu *percpu =
-			(struct squashfs_stream_percpu __percpu *) msblk->stream;
+	struct squashfs_stream *stream;
+	struct squashfs_stream __percpu *percpu =
+			(struct squashfs_stream __percpu *) msblk->stream;
 	int res;
 
 	local_lock(&percpu->lock);
@@ -98,14 +98,14 @@ static int squashfs_decompress_percpu(struct squashfs_sb_info *msblk, struct bio
 	return res;
 }
 
-static int squashfs_max_decompressors_percpu(void)
+static int squashfs_max_decompressors(void)
 {
 	return num_possible_cpus();
 }
 
 const struct squashfs_decompressor_thread_ops squashfs_decompressor_percpu = {
-	.create = squashfs_decompressor_create_percpu,
-	.destroy = squashfs_decompressor_destroy_percpu,
-	.decompress = squashfs_decompress_percpu,
-	.max_decompressors = squashfs_max_decompressors_percpu,
+	.create = squashfs_decompressor_create,
+	.destroy = squashfs_decompressor_destroy,
+	.decompress = squashfs_decompress,
+	.max_decompressors = squashfs_max_decompressors,
 };
diff --git a/fs/squashfs/decompressor_single.c b/fs/squashfs/decompressor_single.c
index 41449de0ea4c..6f161887710b 100644
--- a/fs/squashfs/decompressor_single.c
+++ b/fs/squashfs/decompressor_single.c
@@ -19,15 +19,15 @@
  * decompressor framework
  */
 
-struct squashfs_stream_single {
+struct squashfs_stream {
 	void		*stream;
 	struct mutex	mutex;
 };
 
-static void *squashfs_decompressor_create_single(struct squashfs_sb_info *msblk,
+static void *squashfs_decompressor_create(struct squashfs_sb_info *msblk,
 						void *comp_opts)
 {
-	struct squashfs_stream_single *stream;
+	struct squashfs_stream *stream;
 	int err = -ENOMEM;
 
 	stream = kmalloc(sizeof(*stream), GFP_KERNEL);
@@ -49,9 +49,9 @@ static void *squashfs_decompressor_create_single(struct squashfs_sb_info *msblk,
 	return ERR_PTR(err);
 }
 
-static void squashfs_decompressor_destroy_single(struct squashfs_sb_info *msblk)
+static void squashfs_decompressor_destroy(struct squashfs_sb_info *msblk)
 {
-	struct squashfs_stream_single *stream = msblk->stream;
+	struct squashfs_stream *stream = msblk->stream;
 
 	if (stream) {
 		msblk->decompressor->free(stream->stream);
@@ -59,12 +59,12 @@ static void squashfs_decompressor_destroy_single(struct squashfs_sb_info *msblk)
 	}
 }
 
-static int squashfs_decompress_single(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)
 {
 	int res;
-	struct squashfs_stream_single *stream = msblk->stream;
+	struct squashfs_stream *stream = msblk->stream;
 
 	mutex_lock(&stream->mutex);
 	res = msblk->decompressor->decompress(msblk, stream->stream, bio,
@@ -78,14 +78,14 @@ static int squashfs_decompress_single(struct squashfs_sb_info *msblk, struct bio
 	return res;
 }
 
-static int squashfs_max_decompressors_single(void)
+static int squashfs_max_decompressors(void)
 {
 	return 1;
 }
 
 const struct squashfs_decompressor_thread_ops squashfs_decompressor_single = {
-	.create = squashfs_decompressor_create_single,
-	.destroy = squashfs_decompressor_destroy_single,
-	.decompress = squashfs_decompress_single,
-	.max_decompressors = squashfs_max_decompressors_single,
+	.create = squashfs_decompressor_create,
+	.destroy = squashfs_decompressor_destroy,
+	.decompress = squashfs_decompress,
+	.max_decompressors = squashfs_max_decompressors,
 };
diff --git a/fs/squashfs/squashfs.h b/fs/squashfs/squashfs.h
index 9a383ad0dae0..9ba9e95440f8 100644
--- a/fs/squashfs/squashfs.h
+++ b/fs/squashfs/squashfs.h
@@ -37,46 +37,6 @@ extern void *squashfs_read_table(struct super_block *, u64, int);
 extern const struct squashfs_decompressor *squashfs_lookup_decompressor(int);
 extern void *squashfs_decompressor_setup(struct super_block *, unsigned short);
 
-/* decompressor_xxx.c */
-
-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
-
-static inline void *squashfs_decompressor_create(struct squashfs_sb_info *msblk, void *comp_opts)
-{
-	return msblk->thread_ops->create(msblk, comp_opts);
-}
-
-static inline void squashfs_decompressor_destroy(struct squashfs_sb_info *msblk)
-{
-	msblk->thread_ops->destroy(msblk);
-}
-
-static inline int squashfs_decompress(struct squashfs_sb_info *msblk, struct bio *bio,
-				      int offset, int length, struct squashfs_page_actor *output)
-{
-	return msblk->thread_ops->decompress(msblk, bio, offset, length, output);
-}
-
-static inline int squashfs_max_decompressors(struct squashfs_sb_info *msblk)
-{
-	return msblk->thread_ops->max_decompressors();
-}
 /* export.c */
 extern __le64 *squashfs_read_inode_lookup_table(struct super_block *, u64, u64,
 				unsigned int);
diff --git a/fs/squashfs/super.c b/fs/squashfs/super.c
index fd4e70d45f3c..d7dc4b304aa0 100644
--- a/fs/squashfs/super.c
+++ b/fs/squashfs/super.c
@@ -36,6 +36,7 @@
 #include "squashfs.h"
 #include "decompressor.h"
 #include "xattr.h"
+#include "threading.h"
 
 static struct file_system_type squashfs_fs_type;
 static const struct super_operations squashfs_super_ops;
diff --git a/fs/squashfs/threading.h b/fs/squashfs/threading.h
new file mode 100644
index 000000000000..bd06519fb8b9
--- /dev/null
+++ b/fs/squashfs/threading.h
@@ -0,0 +1,30 @@
+#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
+
+static inline void *squashfs_decompressor_create(struct squashfs_sb_info *msblk, void *comp_opts)
+{
+	return msblk->thread_ops->create(msblk, comp_opts);
+}
+
+static inline void squashfs_decompressor_destroy(struct squashfs_sb_info *msblk)
+{
+	msblk->thread_ops->destroy(msblk);
+}
+
+static inline int squashfs_decompress(struct squashfs_sb_info *msblk, struct bio *bio,
+				      int offset, int length, struct squashfs_page_actor *output)
+{
+	return msblk->thread_ops->decompress(msblk, bio, offset, length, output);
+}
+
+static inline int squashfs_max_decompressors(struct squashfs_sb_info *msblk)
+{
+	return msblk->thread_ops->max_decompressors();
+}
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* Re: [PATCH v3 1/2] squashfs: add the mount parameter theads=<single|multi|percpu>
  2022-09-02  9:48     ` [PATCH v3 1/2] squashfs: add the mount parameter theads=<single|multi|percpu> Xiaoming Ni
  2022-09-09 15:44       ` Phillip Lougher
@ 2022-09-09 15:50       ` Phillip Lougher
  2022-09-13  2:47         ` Xiaoming Ni
  1 sibling, 1 reply; 38+ messages in thread
From: Phillip Lougher @ 2022-09-09 15:50 UTC (permalink / raw)
  To: Xiaoming Ni, linux-kernel
  Cc: wangle6, yi.zhang, wangbing6, zhongjubin, chenjianguo3

On 02/09/2022 10:48, Xiaoming Ni wrote:
> 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.
> 
> Signed-off-by: Xiaoming Ni <nixiaoming@huawei.com>

Additional review comment ...

[SNIP]

> diff --git a/fs/squashfs/super.c b/fs/squashfs/super.c
> index 32565dafa7f3..fd4e70d45f3c 100644
> --- a/fs/squashfs/super.c
> +++ b/fs/squashfs/super.c
> @@ -47,10 +47,12 @@ enum Opt_errors {

[SNIP]

> +#ifdef CONFIG_SQUASHFS_DECOMP_SINGLE
> +	opts->thread_ops = &squashfs_decompressor_single; > +#elif CONFIG_SQUASHFS_DECOMP_MULTI

this should be

#elif defined CONFIG_SQUASHFS_DECOMP_MULTI

> +	opts->thread_ops = &squashfs_decompressor_multi;
> +#elif CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU

this should be

#elif defined CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU

Phillip

> +	opts->thread_ops = &squashfs_decompressor_percpu;
> +#endif
>   	fc->fs_private = opts;
>   	fc->ops = &squashfs_context_ops;
>   	return 0;


^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH v3 1/2] squashfs: add the mount parameter theads=<single|multi|percpu>
  2022-09-09 15:44       ` Phillip Lougher
@ 2022-09-13  2:46         ` Xiaoming Ni
  0 siblings, 0 replies; 38+ messages in thread
From: Xiaoming Ni @ 2022-09-13  2:46 UTC (permalink / raw)
  To: Phillip Lougher
  Cc: chenjianguo3, linux-kernel, wangbing6, wangle6, yi.zhang, zhongjubin

On 2022/9/9 23:44, Phillip Lougher wrote:
> Review comments below.
> 
> Xiaoming Ni <nixiaoming@huawei.com> wrote:
>> Squashfs supports three decompression concurrency modes:
>> 	Single-thread mode: concurrent reads are blocked and the memory overhead
>> is small.
> 
> Please wrap over 80 column line.
Thanks for your review, I'll fix it in the next patch version

...
>> +	  Compile all parallel decompression modes and specify the
>> +	  decompression mode by setting "threads=" during mount.
>> +
>> +	  	  threads=<single|multi|percpu>
> 
> git am reports "warning: 1 line adds whitespace errors.", which is here.

Thanks for your review, I'll fix it in the next patch version

> [SNIP]
> 
>> diff --git a/fs/squashfs/decompressor_multi.c b/fs/squashfs/decompressor_multi.c
>> index db9f12a3ea05..7b2723b77e75 100644
>> --- a/fs/squashfs/decompressor_multi.c
>> +++ b/fs/squashfs/decompressor_multi.c
>> @@ -29,13 +29,12 @@
>> #define MAX_DECOMPRESSOR	(num_online_cpus() * 2)
>>
>>
>> -int squashfs_max_decompressors(void)
>> +static int squashfs_max_decompressors_multi(void)
> 
> Changing the name of the function *should* be unnecessary, because
> you're making it static.
> 
>> {
>> 	return MAX_DECOMPRESSOR;
>> }
>>
>> -
>> -struct squashfs_stream {
>> +struct squashfs_stream_multi {
> 
> Again changing the name of the structure should be unnecessary.
> 
> This is just extra noise.
> 
> The current "diffstat" for the 3 decompression threading implementations is:
> 
> fs/squashfs/decompressor_multi.c        | 28 ++++++++++--------
> fs/squashfs/decompressor_multi_percpu.c | 39 +++++++++++++++----------
> fs/squashfs/decompressor_single.c       | 23 +++++++++------
> 
> But, once you get rid of this noise, it drops to
> 
> fs/squashfs/decompressor_multi.c        | 16 +++++---
> fs/squashfs/decompressor_multi_percpu.c | 23 +++++++----
> fs/squashfs/decompressor_single.c       | 15 ++++++--
> 
> [SNIP]
Thanks for your comment, I'll use it in the next patch version to reduce 
the amount of code changes.

> 
>> --- a/fs/squashfs/squashfs.h
>> +++ b/fs/squashfs/squashfs.h
>> @@ -38,12 +38,45 @@ extern const struct squashfs_decompressor *squashfs_lookup_decompressor(int);
>> extern void *squashfs_decompressor_setup(struct super_block *, unsigned short);
>>
>> /* decompressor_xxx.c */
> 
> [SNIP]
> 
>> +
>> +static inline void *squashfs_decompressor_create(struct squashfs_sb_info *msblk, void *comp_opts)
>> +{
>> +	return msblk->thread_ops->create(msblk, comp_opts);
>> +}
>> +
>> +static inline void squashfs_decompressor_destroy(struct squashfs_sb_info *msblk)
>> +{
>> +	msblk->thread_ops->destroy(msblk);
>> +}
>> +
>> +static inline int squashfs_decompress(struct squashfs_sb_info *msblk, struct bio *bio,
>> +				      int offset, int length, struct squashfs_page_actor *output)
>> +{
>> +	return msblk->thread_ops->decompress(msblk, bio, offset, length, output);
>> +}
>> +
>> +static inline int squashfs_max_decompressors(struct squashfs_sb_info *msblk)
>> +{
>> +	return msblk->thread_ops->max_decompressors();
>> +}
> 
> The above is the reason why you've had to rename the functions in the
> decompression threading implementations.  Because you've put the new
> accessors into squashfs.h which is also included by the threading
> implementations which causes a name clash.
> 
> But, the correct way to avoid this clash, is to put the accessors into
> a new header file, which isn't included by the decompression threading
> implementations.
> 
> The following patch does this cleanup, to simplify the patch here.  It also
> moves the struct squashfs_decompressor_thread_ops definition into
> decompressor.h which is a better place.
> 
> Phillip
> 
>   fs/squashfs/block.c                     |  1 +
>   fs/squashfs/decompressor.c              |  1 +
>   fs/squashfs/decompressor.h              |  8 +++++
>   fs/squashfs/decompressor_multi.c        | 28 ++++++++---------
>   fs/squashfs/decompressor_multi_percpu.c | 36 +++++++++++-----------
>   fs/squashfs/decompressor_single.c       | 24 +++++++--------
>   fs/squashfs/squashfs.h                  | 40 -------------------------
>   fs/squashfs/super.c                     |  1 +
>   fs/squashfs/threading.h                 | 30 +++++++++++++++++++
>   9 files changed, 85 insertions(+), 84 deletions(-)
>   create mode 100644 fs/squashfs/threading.h

I re-checked the use of create(), destory(), decompress(), 
max_decompressors() and found that the corresponding function had only 
one or two call points, so do we not need to encapsulate in .h?

Squashfs_decompress() is called only once in fs/squashfs/block.c, 
squashfs_read_data().
Squashfs_decompressor_create() is called only once in 
fs/squashfs/decompressor.c, squashfs_decompressor_setup().
squashfs_max_decompressors() is called only once in fs/squashfs/super.c, 
squashfs_fill_super().
squashfs_decompressor_destroy() is called only in fs/squashfs/super.c, 
squashfs_fill_super() and squashfs_put_super().


Thanks
Xiaoming Ni

> 
> diff --git a/fs/squashfs/block.c b/fs/squashfs/block.c
> index 833aca92301f..9bcf7e1b64be 100644
> --- a/fs/squashfs/block.c
> +++ b/fs/squashfs/block.c
> @@ -26,6 +26,7 @@
>   #include "squashfs.h"
>   #include "decompressor.h"
>   #include "page_actor.h"
> +#include "threading.h"
>   
>   /*
>    * Returns the amount of bytes copied to the page actor.
> diff --git a/fs/squashfs/decompressor.c b/fs/squashfs/decompressor.c
> index d57bef91ab08..5c355fca0df5 100644
> --- a/fs/squashfs/decompressor.c
> +++ b/fs/squashfs/decompressor.c
> @@ -18,6 +18,7 @@
>   #include "decompressor.h"
>   #include "squashfs.h"
>   #include "page_actor.h"
> +#include "threading.h"
>   
>   /*
>    * This file (and decompressor.h) implements a decompressor framework for
> diff --git a/fs/squashfs/decompressor.h b/fs/squashfs/decompressor.h
> index 19ab60834389..5b5ec4828930 100644
> --- a/fs/squashfs/decompressor.h
> +++ b/fs/squashfs/decompressor.h
> @@ -24,6 +24,14 @@ struct squashfs_decompressor {
>   	int	supported;
>   };
>   
> +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);
> +};
> +
>   static inline void *squashfs_comp_opts(struct squashfs_sb_info *msblk,
>   							void *buff, int length)
>   {
> diff --git a/fs/squashfs/decompressor_multi.c b/fs/squashfs/decompressor_multi.c
> index 7b2723b77e75..eb25432bd149 100644
> --- a/fs/squashfs/decompressor_multi.c
> +++ b/fs/squashfs/decompressor_multi.c
> @@ -29,12 +29,12 @@
>   #define MAX_DECOMPRESSOR	(num_online_cpus() * 2)
>   
>   
> -static int squashfs_max_decompressors_multi(void)
> +static int squashfs_max_decompressors(void)
>   {
>   	return MAX_DECOMPRESSOR;
>   }
>   
> -struct squashfs_stream_multi {
> +struct squashfs_stream {
>   	void			*comp_opts;
>   	struct list_head	strm_list;
>   	struct mutex		mutex;
> @@ -50,7 +50,7 @@ struct decomp_stream {
>   
>   
>   static void put_decomp_stream(struct decomp_stream *decomp_strm,
> -				struct squashfs_stream_multi *stream)
> +				struct squashfs_stream *stream)
>   {
>   	mutex_lock(&stream->mutex);
>   	list_add(&decomp_strm->list, &stream->strm_list);
> @@ -58,10 +58,10 @@ static void put_decomp_stream(struct decomp_stream *decomp_strm,
>   	wake_up(&stream->wait);
>   }
>   
> -static void *squashfs_decompressor_create_multi(struct squashfs_sb_info *msblk,
> +static void *squashfs_decompressor_create(struct squashfs_sb_info *msblk,
>   				void *comp_opts)
>   {
> -	struct squashfs_stream_multi *stream;
> +	struct squashfs_stream *stream;
>   	struct decomp_stream *decomp_strm = NULL;
>   	int err = -ENOMEM;
>   
> @@ -102,9 +102,9 @@ static void *squashfs_decompressor_create_multi(struct squashfs_sb_info *msblk,
>   }
>   
>   
> -static void squashfs_decompressor_destroy_multi(struct squashfs_sb_info *msblk)
> +static void squashfs_decompressor_destroy(struct squashfs_sb_info *msblk)
>   {
> -	struct squashfs_stream_multi *stream = msblk->stream;
> +	struct squashfs_stream *stream = msblk->stream;
>   	if (stream) {
>   		struct decomp_stream *decomp_strm;
>   
> @@ -124,7 +124,7 @@ static void squashfs_decompressor_destroy_multi(struct squashfs_sb_info *msblk)
>   
>   
>   static struct decomp_stream *get_decomp_stream(struct squashfs_sb_info *msblk,
> -					struct squashfs_stream_multi *stream)
> +					struct squashfs_stream *stream)
>   {
>   	struct decomp_stream *decomp_strm;
>   
> @@ -179,12 +179,12 @@ static struct decomp_stream *get_decomp_stream(struct squashfs_sb_info *msblk,
>   }
>   
>   
> -static int squashfs_decompress_multi(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)
>   {
>   	int res;
> -	struct squashfs_stream_multi *stream = msblk->stream;
> +	struct squashfs_stream *stream = msblk->stream;
>   	struct decomp_stream *decomp_stream = get_decomp_stream(msblk, stream);
>   	res = msblk->decompressor->decompress(msblk, decomp_stream->stream,
>   		bio, offset, length, output);
> @@ -196,8 +196,8 @@ static int squashfs_decompress_multi(struct squashfs_sb_info *msblk, struct bio
>   }
>   
>   const struct squashfs_decompressor_thread_ops squashfs_decompressor_multi = {
> -	.create = squashfs_decompressor_create_multi,
> -	.destroy = squashfs_decompressor_destroy_multi,
> -	.decompress = squashfs_decompress_multi,
> -	.max_decompressors = squashfs_max_decompressors_multi,
> +	.create = squashfs_decompressor_create,
> +	.destroy = squashfs_decompressor_destroy,
> +	.decompress = squashfs_decompress,
> +	.max_decompressors = squashfs_max_decompressors,
>   };
> diff --git a/fs/squashfs/decompressor_multi_percpu.c b/fs/squashfs/decompressor_multi_percpu.c
> index e24455a7b04d..1dfadf76ed9a 100644
> --- a/fs/squashfs/decompressor_multi_percpu.c
> +++ b/fs/squashfs/decompressor_multi_percpu.c
> @@ -20,19 +20,19 @@
>    * variables, one thread per cpu core.
>    */
>   
> -struct squashfs_stream_percpu {
> +struct squashfs_stream {
>   	void			*stream;
>   	local_lock_t	lock;
>   };
>   
> -static void *squashfs_decompressor_create_percpu(struct squashfs_sb_info *msblk,
> +static void *squashfs_decompressor_create(struct squashfs_sb_info *msblk,
>   						void *comp_opts)
>   {
> -	struct squashfs_stream_percpu *stream;
> -	struct squashfs_stream_percpu __percpu *percpu;
> +	struct squashfs_stream *stream;
> +	struct squashfs_stream __percpu *percpu;
>   	int err, cpu;
>   
> -	percpu = alloc_percpu(struct squashfs_stream_percpu);
> +	percpu = alloc_percpu(struct squashfs_stream);
>   	if (percpu == NULL)
>   		return ERR_PTR(-ENOMEM);
>   
> @@ -59,11 +59,11 @@ static void *squashfs_decompressor_create_percpu(struct squashfs_sb_info *msblk,
>   	return ERR_PTR(err);
>   }
>   
> -static void squashfs_decompressor_destroy_percpu(struct squashfs_sb_info *msblk)
> +static void squashfs_decompressor_destroy(struct squashfs_sb_info *msblk)
>   {
> -	struct squashfs_stream_percpu __percpu *percpu =
> -			(struct squashfs_stream_percpu __percpu *) msblk->stream;
> -	struct squashfs_stream_percpu *stream;
> +	struct squashfs_stream __percpu *percpu =
> +			(struct squashfs_stream __percpu *) msblk->stream;
> +	struct squashfs_stream *stream;
>   	int cpu;
>   
>   	if (msblk->stream) {
> @@ -75,12 +75,12 @@ static void squashfs_decompressor_destroy_percpu(struct squashfs_sb_info *msblk)
>   	}
>   }
>   
> -static int squashfs_decompress_percpu(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_percpu *stream;
> -	struct squashfs_stream_percpu __percpu *percpu =
> -			(struct squashfs_stream_percpu __percpu *) msblk->stream;
> +	struct squashfs_stream *stream;
> +	struct squashfs_stream __percpu *percpu =
> +			(struct squashfs_stream __percpu *) msblk->stream;
>   	int res;
>   
>   	local_lock(&percpu->lock);
> @@ -98,14 +98,14 @@ static int squashfs_decompress_percpu(struct squashfs_sb_info *msblk, struct bio
>   	return res;
>   }
>   
> -static int squashfs_max_decompressors_percpu(void)
> +static int squashfs_max_decompressors(void)
>   {
>   	return num_possible_cpus();
>   }
>   
>   const struct squashfs_decompressor_thread_ops squashfs_decompressor_percpu = {
> -	.create = squashfs_decompressor_create_percpu,
> -	.destroy = squashfs_decompressor_destroy_percpu,
> -	.decompress = squashfs_decompress_percpu,
> -	.max_decompressors = squashfs_max_decompressors_percpu,
> +	.create = squashfs_decompressor_create,
> +	.destroy = squashfs_decompressor_destroy,
> +	.decompress = squashfs_decompress,
> +	.max_decompressors = squashfs_max_decompressors,
>   };
> diff --git a/fs/squashfs/decompressor_single.c b/fs/squashfs/decompressor_single.c
> index 41449de0ea4c..6f161887710b 100644
> --- a/fs/squashfs/decompressor_single.c
> +++ b/fs/squashfs/decompressor_single.c
> @@ -19,15 +19,15 @@
>    * decompressor framework
>    */
>   
> -struct squashfs_stream_single {
> +struct squashfs_stream {
>   	void		*stream;
>   	struct mutex	mutex;
>   };
>   
> -static void *squashfs_decompressor_create_single(struct squashfs_sb_info *msblk,
> +static void *squashfs_decompressor_create(struct squashfs_sb_info *msblk,
>   						void *comp_opts)
>   {
> -	struct squashfs_stream_single *stream;
> +	struct squashfs_stream *stream;
>   	int err = -ENOMEM;
>   
>   	stream = kmalloc(sizeof(*stream), GFP_KERNEL);
> @@ -49,9 +49,9 @@ static void *squashfs_decompressor_create_single(struct squashfs_sb_info *msblk,
>   	return ERR_PTR(err);
>   }
>   
> -static void squashfs_decompressor_destroy_single(struct squashfs_sb_info *msblk)
> +static void squashfs_decompressor_destroy(struct squashfs_sb_info *msblk)
>   {
> -	struct squashfs_stream_single *stream = msblk->stream;
> +	struct squashfs_stream *stream = msblk->stream;
>   
>   	if (stream) {
>   		msblk->decompressor->free(stream->stream);
> @@ -59,12 +59,12 @@ static void squashfs_decompressor_destroy_single(struct squashfs_sb_info *msblk)
>   	}
>   }
>   
> -static int squashfs_decompress_single(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)
>   {
>   	int res;
> -	struct squashfs_stream_single *stream = msblk->stream;
> +	struct squashfs_stream *stream = msblk->stream;
>   
>   	mutex_lock(&stream->mutex);
>   	res = msblk->decompressor->decompress(msblk, stream->stream, bio,
> @@ -78,14 +78,14 @@ static int squashfs_decompress_single(struct squashfs_sb_info *msblk, struct bio
>   	return res;
>   }
>   
> -static int squashfs_max_decompressors_single(void)
> +static int squashfs_max_decompressors(void)
>   {
>   	return 1;
>   }
>   
>   const struct squashfs_decompressor_thread_ops squashfs_decompressor_single = {
> -	.create = squashfs_decompressor_create_single,
> -	.destroy = squashfs_decompressor_destroy_single,
> -	.decompress = squashfs_decompress_single,
> -	.max_decompressors = squashfs_max_decompressors_single,
> +	.create = squashfs_decompressor_create,
> +	.destroy = squashfs_decompressor_destroy,
> +	.decompress = squashfs_decompress,
> +	.max_decompressors = squashfs_max_decompressors,
>   };
> diff --git a/fs/squashfs/squashfs.h b/fs/squashfs/squashfs.h
> index 9a383ad0dae0..9ba9e95440f8 100644
> --- a/fs/squashfs/squashfs.h
> +++ b/fs/squashfs/squashfs.h
> @@ -37,46 +37,6 @@ extern void *squashfs_read_table(struct super_block *, u64, int);
>   extern const struct squashfs_decompressor *squashfs_lookup_decompressor(int);
>   extern void *squashfs_decompressor_setup(struct super_block *, unsigned short);
>   
> -/* decompressor_xxx.c */
> -
> -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
> -
> -static inline void *squashfs_decompressor_create(struct squashfs_sb_info *msblk, void *comp_opts)
> -{
> -	return msblk->thread_ops->create(msblk, comp_opts);
> -}
> -
> -static inline void squashfs_decompressor_destroy(struct squashfs_sb_info *msblk)
> -{
> -	msblk->thread_ops->destroy(msblk);
> -}
> -
> -static inline int squashfs_decompress(struct squashfs_sb_info *msblk, struct bio *bio,
> -				      int offset, int length, struct squashfs_page_actor *output)
> -{
> -	return msblk->thread_ops->decompress(msblk, bio, offset, length, output);
> -}
> -
> -static inline int squashfs_max_decompressors(struct squashfs_sb_info *msblk)
> -{
> -	return msblk->thread_ops->max_decompressors();
> -}
>   /* export.c */
>   extern __le64 *squashfs_read_inode_lookup_table(struct super_block *, u64, u64,
>   				unsigned int);
> diff --git a/fs/squashfs/super.c b/fs/squashfs/super.c
> index fd4e70d45f3c..d7dc4b304aa0 100644
> --- a/fs/squashfs/super.c
> +++ b/fs/squashfs/super.c
> @@ -36,6 +36,7 @@
>   #include "squashfs.h"
>   #include "decompressor.h"
>   #include "xattr.h"
> +#include "threading.h"
>   
>   static struct file_system_type squashfs_fs_type;
>   static const struct super_operations squashfs_super_ops;
> diff --git a/fs/squashfs/threading.h b/fs/squashfs/threading.h
> new file mode 100644
> index 000000000000..bd06519fb8b9
> --- /dev/null
> +++ b/fs/squashfs/threading.h
> @@ -0,0 +1,30 @@
> +#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
> +
> +static inline void *squashfs_decompressor_create(struct squashfs_sb_info *msblk, void *comp_opts)
> +{
> +	return msblk->thread_ops->create(msblk, comp_opts);
> +}
> +
> +static inline void squashfs_decompressor_destroy(struct squashfs_sb_info *msblk)
> +{
> +	msblk->thread_ops->destroy(msblk);
> +}
> +
> +static inline int squashfs_decompress(struct squashfs_sb_info *msblk, struct bio *bio,
> +				      int offset, int length, struct squashfs_page_actor *output)
> +{
> +	return msblk->thread_ops->decompress(msblk, bio, offset, length, output);
> +}
> +
> +static inline int squashfs_max_decompressors(struct squashfs_sb_info *msblk)
> +{
> +	return msblk->thread_ops->max_decompressors();
> +}
> 


^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH v3 1/2] squashfs: add the mount parameter theads=<single|multi|percpu>
  2022-09-09 15:50       ` Phillip Lougher
@ 2022-09-13  2:47         ` Xiaoming Ni
  0 siblings, 0 replies; 38+ messages in thread
From: Xiaoming Ni @ 2022-09-13  2:47 UTC (permalink / raw)
  To: Phillip Lougher, linux-kernel
  Cc: wangle6, yi.zhang, wangbing6, zhongjubin, chenjianguo3

On 2022/9/9 23:50, Phillip Lougher wrote:
> On 02/09/2022 10:48, Xiaoming Ni wrote:
>> 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.
>>
>> Signed-off-by: Xiaoming Ni <nixiaoming@huawei.com>
> 
> Additional review comment ...
> 
> [SNIP]
> 
>> diff --git a/fs/squashfs/super.c b/fs/squashfs/super.c
>> index 32565dafa7f3..fd4e70d45f3c 100644
>> --- a/fs/squashfs/super.c
>> +++ b/fs/squashfs/super.c
>> @@ -47,10 +47,12 @@ enum Opt_errors {
> 
> [SNIP]
> 
>> +#ifdef CONFIG_SQUASHFS_DECOMP_SINGLE
>> +    opts->thread_ops = &squashfs_decompressor_single; > +#elif 
>> CONFIG_SQUASHFS_DECOMP_MULTI
> 
> this should be
> 
> #elif defined CONFIG_SQUASHFS_DECOMP_MULTI
> 

Thanks for your comment, I'll fix it in the next patch version

>> +    opts->thread_ops = &squashfs_decompressor_multi;
>> +#elif CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU
> 
> this should be
> 
> #elif defined CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU
> 

Thanks for your comment, I'll fix it in the next patch version

> Phillip
> 
>> +    opts->thread_ops = &squashfs_decompressor_percpu;
>> +#endif
>>       fc->fs_private = opts;
>>       fc->ops = &squashfs_context_ops;
>>       return 0;
> 
> 
> .

Thanks
Xiaoming Ni

^ permalink raw reply	[flat|nested] 38+ messages in thread

* [PATCH v4 0/2] squashfs: Add the mount parameter "threads="
  2022-09-02  9:48   ` [PATCH v3 " Xiaoming Ni
                       ` (2 preceding siblings ...)
  2022-09-09 15:26     ` [PATCH v3 0/2] squashfs: Add the mount parameter "threads=" Phillip Lougher
@ 2022-09-16  8:36     ` Xiaoming Ni
  2022-09-16  8:36       ` [PATCH v4 1/2] squashfs: add the mount parameter theads=<single|multi|percpu> Xiaoming Ni
                         ` (3 more replies)
  3 siblings, 4 replies; 38+ messages in thread
From: Xiaoming Ni @ 2022-09-16  8:36 UTC (permalink / raw)
  To: linux-kernel, phillip
  Cc: nixiaoming, wangle6, yi.zhang, wangbing6, zhongjubin, chenjianguo3

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.


v4: Based on Philip Lougher's suggestion, make the following updates:
 1. Use static modifiers to avoid changing symbol names.
 2. Fixed some formatting issues

v3: https://lore.kernel.org/lkml/20220902094855.22666-1-nixiaoming@huawei.com/
  Based on Philip Lougher's suggestion, make the following updates:
  1. The default configuration is the same as that before the patch installation.
  2. Compile the three decompression modes when the new configuration is enabled.
  3. "threads=1" supports only the SQUASHFS_DECOMP_SINGLE mode.

v2: https://lore.kernel.org/lkml/20220816010052.15764-1-nixiaoming@huawei.com/
  fix warning: sparse: incorrect type in initializer (different address spaces)
  Reported-by: kernel test robot <lkp@intel.com>

v1: https://lore.kernel.org/lkml/20220815031100.75243-1-nixiaoming@huawei.com/

Xiaoming Ni (2):
  squashfs: add the mount parameter theads=<single|multi|percpu>
  squashfs: Allows users to configure the number of  decompression
    threads

 fs/squashfs/Kconfig                     | 51 +++++++++++++++--
 fs/squashfs/block.c                     |  2 +-
 fs/squashfs/decompressor.c              |  2 +-
 fs/squashfs/decompressor_multi.c        | 20 ++++---
 fs/squashfs/decompressor_multi_percpu.c | 23 +++++---
 fs/squashfs/decompressor_single.c       | 15 +++--
 fs/squashfs/squashfs.h                  | 23 ++++++--
 fs/squashfs/squashfs_fs_sb.h            |  4 +-
 fs/squashfs/super.c                     | 97 ++++++++++++++++++++++++++++++++-
 9 files changed, 203 insertions(+), 34 deletions(-)

-- 
2.12.3


^ permalink raw reply	[flat|nested] 38+ messages in thread

* [PATCH v4 1/2] squashfs: add the mount parameter theads=<single|multi|percpu>
  2022-09-16  8:36     ` [PATCH v4 " Xiaoming Ni
@ 2022-09-16  8:36       ` Xiaoming Ni
  2022-09-28  2:20         ` Phillip Lougher
  2022-09-16  8:36       ` [PATCH v4 2/2] squashfs: Allows users to configure the number of decompression threads Xiaoming Ni
                         ` (2 subsequent siblings)
  3 siblings, 1 reply; 38+ messages in thread
From: Xiaoming Ni @ 2022-09-16  8:36 UTC (permalink / raw)
  To: linux-kernel, phillip
  Cc: nixiaoming, wangle6, yi.zhang, wangbing6, zhongjubin, chenjianguo3

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.

Signed-off-by: Xiaoming Ni <nixiaoming@huawei.com>
---
 fs/squashfs/Kconfig                     | 39 +++++++++++++++++++++---
 fs/squashfs/block.c                     |  2 +-
 fs/squashfs/decompressor.c              |  2 +-
 fs/squashfs/decompressor_multi.c        | 16 +++++++---
 fs/squashfs/decompressor_multi_percpu.c | 23 +++++++++-----
 fs/squashfs/decompressor_single.c       | 15 ++++++---
 fs/squashfs/squashfs.h                  | 23 +++++++++++---
 fs/squashfs/squashfs_fs_sb.h            |  3 +-
 fs/squashfs/super.c                     | 54 +++++++++++++++++++++++++++++++--
 9 files changed, 145 insertions(+), 32 deletions(-)

diff --git a/fs/squashfs/Kconfig b/fs/squashfs/Kconfig
index 916e78fabcaa..218bacdd4298 100644
--- a/fs/squashfs/Kconfig
+++ b/fs/squashfs/Kconfig
@@ -54,9 +54,36 @@ 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
@@ -64,15 +91,17 @@ choice
 
 	  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
@@ -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
@@ -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
diff --git a/fs/squashfs/block.c b/fs/squashfs/block.c
index 833aca92301f..bed3bb8b27fa 100644
--- a/fs/squashfs/block.c
+++ b/fs/squashfs/block.c
@@ -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);
 	}
diff --git a/fs/squashfs/decompressor.c b/fs/squashfs/decompressor.c
index d57bef91ab08..8893cb9b4198 100644
--- a/fs/squashfs/decompressor.c
+++ b/fs/squashfs/decompressor.c
@@ -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);
 
diff --git a/fs/squashfs/decompressor_multi.c b/fs/squashfs/decompressor_multi.c
index db9f12a3ea05..eb25432bd149 100644
--- a/fs/squashfs/decompressor_multi.c
+++ b/fs/squashfs/decompressor_multi.c
@@ -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;
@@ -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;
@@ -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) {
@@ -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)
 {
@@ -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,
+};
diff --git a/fs/squashfs/decompressor_multi_percpu.c b/fs/squashfs/decompressor_multi_percpu.c
index b881b9283b7f..1dfadf76ed9a 100644
--- a/fs/squashfs/decompressor_multi_percpu.c
+++ b/fs/squashfs/decompressor_multi_percpu.c
@@ -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;
@@ -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;
@@ -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",
@@ -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,
+};
diff --git a/fs/squashfs/decompressor_single.c b/fs/squashfs/decompressor_single.c
index 4eb3d083d45e..6f161887710b 100644
--- a/fs/squashfs/decompressor_single.c
+++ b/fs/squashfs/decompressor_single.c
@@ -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;
@@ -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;
 
@@ -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)
 {
@@ -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,
+};
diff --git a/fs/squashfs/squashfs.h b/fs/squashfs/squashfs.h
index 9783e01c8100..a6164fdf9435 100644
--- a/fs/squashfs/squashfs.h
+++ b/fs/squashfs/squashfs.h
@@ -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,
diff --git a/fs/squashfs/squashfs_fs_sb.h b/fs/squashfs/squashfs_fs_sb.h
index 1e90c2575f9b..f1e5dad8ae0a 100644
--- a/fs/squashfs/squashfs_fs_sb.h
+++ b/fs/squashfs/squashfs_fs_sb.h
@@ -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;
@@ -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
diff --git a/fs/squashfs/super.c b/fs/squashfs/super.c
index 32565dafa7f3..2a33ffe85292 100644
--- a/fs/squashfs/super.c
+++ b/fs/squashfs/super.c
@@ -47,10 +47,12 @@ enum Opt_errors {
 
 enum squashfs_param {
 	Opt_errors,
+	Opt_threads,
 };
 
 struct squashfs_mount_opts {
 	enum Opt_errors errors;
+	const struct squashfs_decompressor_thread_ops *thread_ops;
 };
 
 static const struct constant_table squashfs_param_errors[] = {
@@ -61,9 +63,29 @@ static const struct constant_table squashfs_param_errors[] = {
 
 static const struct fs_parameter_spec squashfs_fs_parameters[] = {
 	fsparam_enum("errors", Opt_errors, squashfs_param_errors),
+	fsparam_string("threads", Opt_threads),
 	{}
 };
 
+static int squashfs_parse_param_threads(const char *str, struct squashfs_mount_opts *opts)
+{
+#ifdef CONFIG_SQUASHFS_CHOICE_DECOMP_BY_MOUNT
+	if (strcmp(str, "single") == 0) {
+		opts->thread_ops = &squashfs_decompressor_single;
+		return 0;
+	}
+	if (strcmp(str, "multi") == 0) {
+		opts->thread_ops = &squashfs_decompressor_multi;
+		return 0;
+	}
+	if (strcmp(str, "percpu") == 0) {
+		opts->thread_ops = &squashfs_decompressor_percpu;
+		return 0;
+	}
+#endif
+	return -EINVAL;
+}
+
 static int squashfs_parse_param(struct fs_context *fc, struct fs_parameter *param)
 {
 	struct squashfs_mount_opts *opts = fc->fs_private;
@@ -78,6 +100,10 @@ static int squashfs_parse_param(struct fs_context *fc, struct fs_parameter *para
 	case Opt_errors:
 		opts->errors = result.uint_32;
 		break;
+	case Opt_threads:
+		if (squashfs_parse_param_threads(param->string, opts) != 0)
+			return -EINVAL;
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -167,6 +193,7 @@ static int squashfs_fill_super(struct super_block *sb, struct fs_context *fc)
 			       sb->s_bdev);
 		goto failed_mount;
 	}
+	msblk->thread_ops = opts->thread_ops;
 
 	/* Check the MAJOR & MINOR versions and lookup compression type */
 	msblk->decompressor = supported_squashfs_filesystem(
@@ -252,7 +279,7 @@ static int squashfs_fill_super(struct super_block *sb, struct fs_context *fc)
 
 	/* Allocate read_page block */
 	msblk->read_page = squashfs_cache_init("data",
-		squashfs_max_decompressors(), msblk->block_size);
+		msblk->thread_ops->max_decompressors(), msblk->block_size);
 	if (msblk->read_page == NULL) {
 		errorf(fc, "Failed to allocate read_page block");
 		goto failed_mount;
@@ -383,7 +410,7 @@ static int squashfs_fill_super(struct super_block *sb, struct fs_context *fc)
 	squashfs_cache_delete(msblk->block_cache);
 	squashfs_cache_delete(msblk->fragment_cache);
 	squashfs_cache_delete(msblk->read_page);
-	squashfs_decompressor_destroy(msblk);
+	msblk->thread_ops->destroy(msblk);
 	kfree(msblk->inode_lookup_table);
 	kfree(msblk->fragment_index);
 	kfree(msblk->id_table);
@@ -435,6 +462,20 @@ static int squashfs_show_options(struct seq_file *s, struct dentry *root)
 	else
 		seq_puts(s, ",errors=continue");
 
+#ifdef CONFIG_SQUASHFS_CHOICE_DECOMP_BY_MOUNT
+	if (msblk->thread_ops == &squashfs_decompressor_single) {
+		seq_puts(s, ",threads=single");
+		return 0;
+	}
+	if (msblk->thread_ops == &squashfs_decompressor_multi) {
+		seq_puts(s, ",threads=multi");
+		return 0;
+	}
+	if (msblk->thread_ops == &squashfs_decompressor_percpu) {
+		seq_puts(s, ",threads=percpu");
+		return 0;
+	}
+#endif
 	return 0;
 }
 
@@ -446,6 +487,13 @@ static int squashfs_init_fs_context(struct fs_context *fc)
 	if (!opts)
 		return -ENOMEM;
 
+#ifdef CONFIG_SQUASHFS_DECOMP_SINGLE
+	opts->thread_ops = &squashfs_decompressor_single;
+#elif CONFIG_SQUASHFS_DECOMP_MULTI
+	opts->thread_ops = &squashfs_decompressor_multi;
+#elif CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU
+	opts->thread_ops = &squashfs_decompressor_percpu;
+#endif
 	fc->fs_private = opts;
 	fc->ops = &squashfs_context_ops;
 	return 0;
@@ -478,7 +526,7 @@ static void squashfs_put_super(struct super_block *sb)
 		squashfs_cache_delete(sbi->block_cache);
 		squashfs_cache_delete(sbi->fragment_cache);
 		squashfs_cache_delete(sbi->read_page);
-		squashfs_decompressor_destroy(sbi);
+		sbi->thread_ops->destroy(sbi);
 		kfree(sbi->id_table);
 		kfree(sbi->fragment_index);
 		kfree(sbi->meta_index);
-- 
2.12.3


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH v4 2/2] squashfs: Allows users to configure the number of  decompression threads
  2022-09-16  8:36     ` [PATCH v4 " Xiaoming Ni
  2022-09-16  8:36       ` [PATCH v4 1/2] squashfs: add the mount parameter theads=<single|multi|percpu> Xiaoming Ni
@ 2022-09-16  8:36       ` Xiaoming Ni
  2022-09-27  1:05       ` ping //Re: [PATCH v4 0/2] squashfs: Add the mount parameter "threads=" Xiaoming Ni
  2022-09-30  9:14       ` [PATCH v5 " Xiaoming Ni
  3 siblings, 0 replies; 38+ messages in thread
From: Xiaoming Ni @ 2022-09-16  8:36 UTC (permalink / raw)
  To: linux-kernel, phillip
  Cc: nixiaoming, wangle6, yi.zhang, wangbing6, zhongjubin, chenjianguo3

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.

Signed-off-by: Xiaoming Ni <nixiaoming@huawei.com>
---
 fs/squashfs/Kconfig              | 16 ++++++++--
 fs/squashfs/decompressor_multi.c |  4 +--
 fs/squashfs/squashfs_fs_sb.h     |  1 +
 fs/squashfs/super.c              | 67 +++++++++++++++++++++++++++++++++-------
 4 files changed, 72 insertions(+), 16 deletions(-)

diff --git a/fs/squashfs/Kconfig b/fs/squashfs/Kconfig
index 218bacdd4298..60fc98bdf421 100644
--- a/fs/squashfs/Kconfig
+++ b/fs/squashfs/Kconfig
@@ -73,11 +73,10 @@ config SQUASHFS_CHOICE_DECOMP_BY_MOUNT
 	select SQUASHFS_DECOMP_SINGLE
 	select SQUASHFS_DECOMP_MULTI
 	select SQUASHFS_DECOMP_MULTI_PERCPU
+	select SQUASHFS_MOUNT_DECOMP_THREADS
 	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
@@ -127,6 +126,19 @@ config SQUASHFS_COMPILE_DECOMP_MULTI_PERCPU
 	  decompression is load-balanced across the cores.
 endchoice
 
+config SQUASHFS_MOUNT_DECOMP_THREADS
+	bool "Add the mount parameter 'threads=' for squashfs"
+	depends on SQUASHFS
+	depends on SQUASHFS_DECOMP_MULTI
+	default n
+	help
+	  Use threads= to set the decompression parallel mode and the number of threads.
+	  If SQUASHFS_CHOICE_DECOMP_BY_MOUNT=y
+	      threads=<single|multi|percpu|1|2|3|...>
+	  else
+	      threads=<2|3|...>
+	  The upper limit is num_online_cpus() * 2.
+
 config SQUASHFS_XATTR
 	bool "Squashfs XATTR support"
 	depends on SQUASHFS
diff --git a/fs/squashfs/decompressor_multi.c b/fs/squashfs/decompressor_multi.c
index eb25432bd149..416c53eedbd1 100644
--- a/fs/squashfs/decompressor_multi.c
+++ b/fs/squashfs/decompressor_multi.c
@@ -144,7 +144,7 @@ static struct decomp_stream *get_decomp_stream(struct squashfs_sb_info *msblk,
 		 * If there is no available decomp and already full,
 		 * let's wait for releasing decomp from other users.
 		 */
-		if (stream->avail_decomp >= MAX_DECOMPRESSOR)
+		if (stream->avail_decomp >= msblk->max_thread_num)
 			goto wait;
 
 		/* Let's allocate new decomp */
@@ -160,7 +160,7 @@ static struct decomp_stream *get_decomp_stream(struct squashfs_sb_info *msblk,
 		}
 
 		stream->avail_decomp++;
-		WARN_ON(stream->avail_decomp > MAX_DECOMPRESSOR);
+		WARN_ON(stream->avail_decomp > msblk->max_thread_num);
 
 		mutex_unlock(&stream->mutex);
 		break;
diff --git a/fs/squashfs/squashfs_fs_sb.h b/fs/squashfs/squashfs_fs_sb.h
index f1e5dad8ae0a..659082e9e51d 100644
--- a/fs/squashfs/squashfs_fs_sb.h
+++ b/fs/squashfs/squashfs_fs_sb.h
@@ -67,5 +67,6 @@ struct squashfs_sb_info {
 	unsigned int				ids;
 	bool					panic_on_errors;
 	const struct squashfs_decompressor_thread_ops *thread_ops;
+	int					max_thread_num;
 };
 #endif
diff --git a/fs/squashfs/super.c b/fs/squashfs/super.c
index 2a33ffe85292..cd7b3e530dcf 100644
--- a/fs/squashfs/super.c
+++ b/fs/squashfs/super.c
@@ -53,6 +53,7 @@ enum squashfs_param {
 struct squashfs_mount_opts {
 	enum Opt_errors errors;
 	const struct squashfs_decompressor_thread_ops *thread_ops;
+	int thread_num;
 };
 
 static const struct constant_table squashfs_param_errors[] = {
@@ -67,7 +68,8 @@ static const struct fs_parameter_spec squashfs_fs_parameters[] = {
 	{}
 };
 
-static int squashfs_parse_param_threads(const char *str, struct squashfs_mount_opts *opts)
+
+static int squashfs_parse_param_threads_str(const char *str, struct squashfs_mount_opts *opts)
 {
 #ifdef CONFIG_SQUASHFS_CHOICE_DECOMP_BY_MOUNT
 	if (strcmp(str, "single") == 0) {
@@ -86,6 +88,42 @@ static int squashfs_parse_param_threads(const char *str, struct squashfs_mount_o
 	return -EINVAL;
 }
 
+static int squashfs_parse_param_threads_num(const char *str, struct squashfs_mount_opts *opts)
+{
+#ifdef CONFIG_SQUASHFS_MOUNT_DECOMP_THREADS
+	int ret;
+	unsigned long num;
+
+	ret = kstrtoul(str, 0, &num);
+	if (ret != 0)
+		return -EINVAL;
+	if (num > 1) {
+		opts->thread_ops = &squashfs_decompressor_multi;
+		if (num > opts->thread_ops->max_decompressors())
+			return -EINVAL;
+		opts->thread_num = (int)num;
+		return 0;
+	}
+#ifdef CONFIG_SQUASHFS_DECOMP_SINGLE
+	if (num == 1) {
+		opts->thread_ops = &squashfs_decompressor_single;
+		opts->thread_num = 1;
+		return 0;
+	}
+#endif
+#endif /* !CONFIG_SQUASHFS_MOUNT_DECOMP_THREADS */
+	return -EINVAL;
+}
+
+static int squashfs_parse_param_threads(const char *str, struct squashfs_mount_opts *opts)
+{
+	int ret = squashfs_parse_param_threads_str(str, opts);
+
+	if (ret == 0)
+		return ret;
+	return squashfs_parse_param_threads_num(str, opts);
+}
+
 static int squashfs_parse_param(struct fs_context *fc, struct fs_parameter *param)
 {
 	struct squashfs_mount_opts *opts = fc->fs_private;
@@ -194,6 +232,11 @@ static int squashfs_fill_super(struct super_block *sb, struct fs_context *fc)
 		goto failed_mount;
 	}
 	msblk->thread_ops = opts->thread_ops;
+	if (opts->thread_num == 0) {
+		msblk->max_thread_num = msblk->thread_ops->max_decompressors();
+	} else {
+		msblk->max_thread_num = opts->thread_num;
+	}
 
 	/* Check the MAJOR & MINOR versions and lookup compression type */
 	msblk->decompressor = supported_squashfs_filesystem(
@@ -279,7 +322,7 @@ static int squashfs_fill_super(struct super_block *sb, struct fs_context *fc)
 
 	/* Allocate read_page block */
 	msblk->read_page = squashfs_cache_init("data",
-		msblk->thread_ops->max_decompressors(), msblk->block_size);
+		msblk->max_thread_num, msblk->block_size);
 	if (msblk->read_page == NULL) {
 		errorf(fc, "Failed to allocate read_page block");
 		goto failed_mount;
@@ -463,18 +506,17 @@ static int squashfs_show_options(struct seq_file *s, struct dentry *root)
 		seq_puts(s, ",errors=continue");
 
 #ifdef CONFIG_SQUASHFS_CHOICE_DECOMP_BY_MOUNT
-	if (msblk->thread_ops == &squashfs_decompressor_single) {
-		seq_puts(s, ",threads=single");
-		return 0;
-	}
-	if (msblk->thread_ops == &squashfs_decompressor_multi) {
-		seq_puts(s, ",threads=multi");
-		return 0;
-	}
 	if (msblk->thread_ops == &squashfs_decompressor_percpu) {
 		seq_puts(s, ",threads=percpu");
 		return 0;
 	}
+	if (msblk->thread_ops == &squashfs_decompressor_single) {
+		seq_puts(s, ",threads=single");
+		return 0;
+	}
+#endif
+#ifdef CONFIG_SQUASHFS_MOUNT_DECOMP_THREADS
+	seq_printf(s, ",threads=%d", msblk->max_thread_num);
 #endif
 	return 0;
 }
@@ -489,11 +531,12 @@ static int squashfs_init_fs_context(struct fs_context *fc)
 
 #ifdef CONFIG_SQUASHFS_DECOMP_SINGLE
 	opts->thread_ops = &squashfs_decompressor_single;
-#elif CONFIG_SQUASHFS_DECOMP_MULTI
+#elif defined(CONFIG_SQUASHFS_DECOMP_MULTI)
 	opts->thread_ops = &squashfs_decompressor_multi;
-#elif CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU
+#elif defined(CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU)
 	opts->thread_ops = &squashfs_decompressor_percpu;
 #endif
+	opts->thread_num = 0;
 	fc->fs_private = opts;
 	fc->ops = &squashfs_context_ops;
 	return 0;
-- 
2.12.3


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* ping //Re: [PATCH v4 0/2] squashfs: Add the mount parameter "threads="
  2022-09-16  8:36     ` [PATCH v4 " Xiaoming Ni
  2022-09-16  8:36       ` [PATCH v4 1/2] squashfs: add the mount parameter theads=<single|multi|percpu> Xiaoming Ni
  2022-09-16  8:36       ` [PATCH v4 2/2] squashfs: Allows users to configure the number of decompression threads Xiaoming Ni
@ 2022-09-27  1:05       ` Xiaoming Ni
  2022-09-30  9:14       ` [PATCH v5 " Xiaoming Ni
  3 siblings, 0 replies; 38+ messages in thread
From: Xiaoming Ni @ 2022-09-27  1:05 UTC (permalink / raw)
  To: linux-kernel, phillip
  Cc: wangle6, yi.zhang, wangbing6, zhongjubin, chenjianguo3

ping

On 2022/9/16 16:36, Xiaoming Ni wrote:
> 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.
> 
> 
> v4: Based on Philip Lougher's suggestion, make the following updates:
>   1. Use static modifiers to avoid changing symbol names.
>   2. Fixed some formatting issues
> 
> v3: https://lore.kernel.org/lkml/20220902094855.22666-1-nixiaoming@huawei.com/
>    Based on Philip Lougher's suggestion, make the following updates:
>    1. The default configuration is the same as that before the patch installation.
>    2. Compile the three decompression modes when the new configuration is enabled.
>    3. "threads=1" supports only the SQUASHFS_DECOMP_SINGLE mode.
> 
> v2: https://lore.kernel.org/lkml/20220816010052.15764-1-nixiaoming@huawei.com/
>    fix warning: sparse: incorrect type in initializer (different address spaces)
>    Reported-by: kernel test robot <lkp@intel.com>
> 
> v1: https://lore.kernel.org/lkml/20220815031100.75243-1-nixiaoming@huawei.com/
> 
> Xiaoming Ni (2):
>    squashfs: add the mount parameter theads=<single|multi|percpu>
>    squashfs: Allows users to configure the number of  decompression
>      threads
> 
>   fs/squashfs/Kconfig                     | 51 +++++++++++++++--
>   fs/squashfs/block.c                     |  2 +-
>   fs/squashfs/decompressor.c              |  2 +-
>   fs/squashfs/decompressor_multi.c        | 20 ++++---
>   fs/squashfs/decompressor_multi_percpu.c | 23 +++++---
>   fs/squashfs/decompressor_single.c       | 15 +++--
>   fs/squashfs/squashfs.h                  | 23 ++++++--
>   fs/squashfs/squashfs_fs_sb.h            |  4 +-
>   fs/squashfs/super.c                     | 97 ++++++++++++++++++++++++++++++++-
>   9 files changed, 203 insertions(+), 34 deletions(-)
> 


^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH v4 1/2] squashfs: add the mount parameter theads=<single|multi|percpu>
  2022-09-16  8:36       ` [PATCH v4 1/2] squashfs: add the mount parameter theads=<single|multi|percpu> Xiaoming Ni
@ 2022-09-28  2:20         ` Phillip Lougher
  2022-09-28  3:06           ` Xiaoming Ni
  0 siblings, 1 reply; 38+ messages in thread
From: Phillip Lougher @ 2022-09-28  2:20 UTC (permalink / raw)
  To: Xiaoming Ni, linux-kernel
  Cc: wangle6, yi.zhang, wangbing6, zhongjubin, chenjianguo3

On 16/09/2022 09:36, Xiaoming Ni wrote:
> 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.
> 
> Signed-off-by: Xiaoming Ni <nixiaoming@huawei.com>
>   
> +#ifdef CONFIG_SQUASHFS_DECOMP_SINGLE
> +	opts->thread_ops = &squashfs_decompressor_single;
> +#elif CONFIG_SQUASHFS_DECOMP_MULTI
> +	opts->thread_ops = &squashfs_decompressor_multi;
> +#elif CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU

In my previous review I asked you to fix the above two #elif
lines.  You have done so in this patch series, but, only in the
second patch which seems perverse.

The reason why this isn't a good approach.  If you *only* apply this 
patch, with the following Squashfs configuration options

phillip@phoenix:/external/stripe/linux$ grep SQUASHFS .config
CONFIG_SQUASHFS=y
# CONFIG_SQUASHFS_FILE_CACHE is not set
CONFIG_SQUASHFS_FILE_DIRECT=y
CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU=y
# CONFIG_SQUASHFS_CHOICE_DECOMP_BY_MOUNT is not set
# CONFIG_SQUASHFS_COMPILE_DECOMP_SINGLE is not set
# CONFIG_SQUASHFS_COMPILE_DECOMP_MULTI is not set
CONFIG_SQUASHFS_COMPILE_DECOMP_MULTI_PERCPU=y
CONFIG_SQUASHFS_XATTR=y
CONFIG_SQUASHFS_ZLIB=y
CONFIG_SQUASHFS_LZ4=y
CONFIG_SQUASHFS_LZO=y
CONFIG_SQUASHFS_XZ=y
CONFIG_SQUASHFS_ZSTD=y
# CONFIG_SQUASHFS_4K_DEVBLK_SIZE is not set
# CONFIG_SQUASHFS_EMBEDDED is not set
CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3


You will get the following build warning

phillip@phoenix:/external/stripe/linux$ make bzImage
   SYNC    include/config/auto.conf.cmd
   CALL    scripts/checksyscalls.sh
   CALL    scripts/atomic/check-atomics.sh
   DESCEND objtool
   CHK     include/generated/compile.h
   UPD     kernel/config_data
   GZIP    kernel/config_data.gz
   CC      kernel/configs.o
   AR      kernel/built-in.a
   CC      fs/squashfs/block.o
   CC      fs/squashfs/cache.o
   CC      fs/squashfs/dir.o
   CC      fs/squashfs/export.o
   CC      fs/squashfs/file.o
   CC      fs/squashfs/fragment.o
   CC      fs/squashfs/id.o
   CC      fs/squashfs/inode.o
   CC      fs/squashfs/namei.o
   CC      fs/squashfs/super.o
fs/squashfs/super.c: In function ‘squashfs_init_fs_context’:
fs/squashfs/super.c:492:7: warning: "CONFIG_SQUASHFS_DECOMP_MULTI" is 
not defined, evaluates to 0 [-Wundef]
   492 | #elif CONFIG_SQUASHFS_DECOMP_MULTI
       |       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~

This strictly breaks the git bisectability rule.  Every patch should
be compilable and not break the build or produce warnings.  If not
it makes git bisect difficult to use to find regressions.

This can be avoided by fixing the issue in *this* patch.  So
please do so.

Thanks

Phillip

> +	opts->thread_ops = &squashfs_decompressor_percpu;
> +#endif
>   	fc->fs_private = opts;
>   	fc->ops = &squashfs_context_ops;
>   	return 0;
> @@ -478,7 +526,7 @@ static void squashfs_put_super(struct super_block *sb)
>   		squashfs_cache_delete(sbi->block_cache);
>   		squashfs_cache_delete(sbi->fragment_cache);
>   		squashfs_cache_delete(sbi->read_page);
> -		squashfs_decompressor_destroy(sbi);
> +		sbi->thread_ops->destroy(sbi);
>   		kfree(sbi->id_table);
>   		kfree(sbi->fragment_index);
>   		kfree(sbi->meta_index);


^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH v4 1/2] squashfs: add the mount parameter theads=<single|multi|percpu>
  2022-09-28  2:20         ` Phillip Lougher
@ 2022-09-28  3:06           ` Xiaoming Ni
  0 siblings, 0 replies; 38+ messages in thread
From: Xiaoming Ni @ 2022-09-28  3:06 UTC (permalink / raw)
  To: Phillip Lougher, linux-kernel
  Cc: wangle6, yi.zhang, wangbing6, zhongjubin, chenjianguo3

On 2022/9/28 10:20, Phillip Lougher wrote:
> On 16/09/2022 09:36, Xiaoming Ni wrote:
>> 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.
>>
>> Signed-off-by: Xiaoming Ni <nixiaoming@huawei.com>
>> +#ifdef CONFIG_SQUASHFS_DECOMP_SINGLE
>> +    opts->thread_ops = &squashfs_decompressor_single;
>> +#elif CONFIG_SQUASHFS_DECOMP_MULTI
>> +    opts->thread_ops = &squashfs_decompressor_multi;
>> +#elif CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU
> 
> In my previous review I asked you to fix the above two #elif
> lines.  You have done so in this patch series, but, only in the
> second patch which seems perverse.
> 
> The reason why this isn't a good approach.  If you *only* apply this 
> patch, with the following Squashfs configuration options
> 
I'm so sorry.
I made a low-level mistake in patching.
I will re-check the previous review comments and resend the patch.

Thanks



> phillip@phoenix:/external/stripe/linux$ grep SQUASHFS .config
> CONFIG_SQUASHFS=y
> # CONFIG_SQUASHFS_FILE_CACHE is not set
> CONFIG_SQUASHFS_FILE_DIRECT=y
> CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU=y
> # CONFIG_SQUASHFS_CHOICE_DECOMP_BY_MOUNT is not set
> # CONFIG_SQUASHFS_COMPILE_DECOMP_SINGLE is not set
> # CONFIG_SQUASHFS_COMPILE_DECOMP_MULTI is not set
> CONFIG_SQUASHFS_COMPILE_DECOMP_MULTI_PERCPU=y
> CONFIG_SQUASHFS_XATTR=y
> CONFIG_SQUASHFS_ZLIB=y
> CONFIG_SQUASHFS_LZ4=y
> CONFIG_SQUASHFS_LZO=y
> CONFIG_SQUASHFS_XZ=y
> CONFIG_SQUASHFS_ZSTD=y
> # CONFIG_SQUASHFS_4K_DEVBLK_SIZE is not set
> # CONFIG_SQUASHFS_EMBEDDED is not set
> CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
> 
> 
> You will get the following build warning
> 
> phillip@phoenix:/external/stripe/linux$ make bzImage
>    SYNC    include/config/auto.conf.cmd
>    CALL    scripts/checksyscalls.sh
>    CALL    scripts/atomic/check-atomics.sh
>    DESCEND objtool
>    CHK     include/generated/compile.h
>    UPD     kernel/config_data
>    GZIP    kernel/config_data.gz
>    CC      kernel/configs.o
>    AR      kernel/built-in.a
>    CC      fs/squashfs/block.o
>    CC      fs/squashfs/cache.o
>    CC      fs/squashfs/dir.o
>    CC      fs/squashfs/export.o
>    CC      fs/squashfs/file.o
>    CC      fs/squashfs/fragment.o
>    CC      fs/squashfs/id.o
>    CC      fs/squashfs/inode.o
>    CC      fs/squashfs/namei.o
>    CC      fs/squashfs/super.o
> fs/squashfs/super.c: In function ‘squashfs_init_fs_context’:
> fs/squashfs/super.c:492:7: warning: "CONFIG_SQUASHFS_DECOMP_MULTI" is 
> not defined, evaluates to 0 [-Wundef]
>    492 | #elif CONFIG_SQUASHFS_DECOMP_MULTI
>        |       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
> 
> This strictly breaks the git bisectability rule.  Every patch should
> be compilable and not break the build or produce warnings.  If not
> it makes git bisect difficult to use to find regressions.
> 
> This can be avoided by fixing the issue in *this* patch.  So
> please do so.
> 
> Thanks
> 
> Phillip
> 
>> +    opts->thread_ops = &squashfs_decompressor_percpu;
>> +#endif
>>       fc->fs_private = opts;
>>       fc->ops = &squashfs_context_ops;
>>       return 0;
>> @@ -478,7 +526,7 @@ static void squashfs_put_super(struct super_block 
>> *sb)
>>           squashfs_cache_delete(sbi->block_cache);
>>           squashfs_cache_delete(sbi->fragment_cache);
>>           squashfs_cache_delete(sbi->read_page);
>> -        squashfs_decompressor_destroy(sbi);
>> +        sbi->thread_ops->destroy(sbi);
>>           kfree(sbi->id_table);
>>           kfree(sbi->fragment_index);
>>           kfree(sbi->meta_index);
> 
> 
> .


^ permalink raw reply	[flat|nested] 38+ messages in thread

* [PATCH v5 0/2] squashfs: Add the mount parameter "threads="
  2022-09-16  8:36     ` [PATCH v4 " Xiaoming Ni
                         ` (2 preceding siblings ...)
  2022-09-27  1:05       ` ping //Re: [PATCH v4 0/2] squashfs: Add the mount parameter "threads=" Xiaoming Ni
@ 2022-09-30  9:14       ` Xiaoming Ni
  2022-09-30  9:14         ` [PATCH v5 1/2] squashfs: add the mount parameter theads=<single|multi|percpu> Xiaoming Ni
                           ` (3 more replies)
  3 siblings, 4 replies; 38+ messages in thread
From: Xiaoming Ni @ 2022-09-30  9:14 UTC (permalink / raw)
  To: linux-kernel, phillip
  Cc: nixiaoming, wangle6, yi.zhang, zhongjubin, chenjianguo3

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.

v5: fix a low-level mistake in patching:
  fs/squashfs/super.c:492:7: warning: "CONFIG_SQUASHFS_DECOMP_MULTI" is 
  not defined, evaluates to 0 [-Wundef]

v4: https://lore.kernel.org/lkml/20220916083604.33408-1-nixiaoming@huawei.com/
 Based on Philip Lougher's suggestion, make the following updates:
 1. Use static modifiers to avoid changing symbol names.
 2. Fixed some formatting issues

v3: https://lore.kernel.org/lkml/20220902094855.22666-1-nixiaoming@huawei.com/
  Based on Philip Lougher's suggestion, make the following updates:
  1. The default configuration is the same as that before the patch installation.
  2. Compile the three decompression modes when the new configuration is enabled.
  3. "threads=1" supports only the SQUASHFS_DECOMP_SINGLE mode.

v2: https://lore.kernel.org/lkml/20220816010052.15764-1-nixiaoming@huawei.com/
  fix warning: sparse: incorrect type in initializer (different address spaces)
  Reported-by: kernel test robot <lkp@intel.com>

v1: https://lore.kernel.org/lkml/20220815031100.75243-1-nixiaoming@huawei.com/

Xiaoming Ni (2):
  squashfs: add the mount parameter theads=<single|multi|percpu>
  squashfs: Allows users to configure the number of  decompression
    threads

 fs/squashfs/Kconfig                     | 51 ++++++++++++++++--
 fs/squashfs/block.c                     |  2 +-
 fs/squashfs/decompressor.c              |  2 +-
 fs/squashfs/decompressor_multi.c        | 20 ++++---
 fs/squashfs/decompressor_multi_percpu.c | 23 +++++---
 fs/squashfs/decompressor_single.c       | 15 ++++--
 fs/squashfs/squashfs.h                  | 23 ++++++--
 fs/squashfs/squashfs_fs_sb.h            |  4 +-
 fs/squashfs/super.c                     | 93 +++++++++++++++++++++++++++++++--
 9 files changed, 199 insertions(+), 34 deletions(-)

-- 
2.12.3


^ permalink raw reply	[flat|nested] 38+ messages in thread

* [PATCH v5 1/2] squashfs: add the mount parameter theads=<single|multi|percpu>
  2022-09-30  9:14       ` [PATCH v5 " Xiaoming Ni
@ 2022-09-30  9:14         ` Xiaoming Ni
  2022-10-17 21:58           ` Re " Phillip Lougher
  2022-09-30  9:14         ` [PATCH v5 2/2] squashfs: Allows users to configure the number of decompression threads Xiaoming Ni
                           ` (2 subsequent siblings)
  3 siblings, 1 reply; 38+ messages in thread
From: Xiaoming Ni @ 2022-09-30  9:14 UTC (permalink / raw)
  To: linux-kernel, phillip
  Cc: nixiaoming, wangle6, yi.zhang, zhongjubin, chenjianguo3

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.

Signed-off-by: Xiaoming Ni <nixiaoming@huawei.com>
---
 fs/squashfs/Kconfig                     | 39 +++++++++++++++++++++----
 fs/squashfs/block.c                     |  2 +-
 fs/squashfs/decompressor.c              |  2 +-
 fs/squashfs/decompressor_multi.c        | 16 +++++++----
 fs/squashfs/decompressor_multi_percpu.c | 23 ++++++++++-----
 fs/squashfs/decompressor_single.c       | 15 +++++++---
 fs/squashfs/squashfs.h                  | 23 +++++++++++----
 fs/squashfs/squashfs_fs_sb.h            |  3 +-
 fs/squashfs/super.c                     | 50 +++++++++++++++++++++++++++++++--
 9 files changed, 141 insertions(+), 32 deletions(-)

diff --git a/fs/squashfs/Kconfig b/fs/squashfs/Kconfig
index 916e78fabcaa..218bacdd4298 100644
--- a/fs/squashfs/Kconfig
+++ b/fs/squashfs/Kconfig
@@ -54,9 +54,36 @@ 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
@@ -64,15 +91,17 @@ choice
 
 	  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
@@ -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
@@ -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
diff --git a/fs/squashfs/block.c b/fs/squashfs/block.c
index 833aca92301f..bed3bb8b27fa 100644
--- a/fs/squashfs/block.c
+++ b/fs/squashfs/block.c
@@ -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);
 	}
diff --git a/fs/squashfs/decompressor.c b/fs/squashfs/decompressor.c
index d57bef91ab08..8893cb9b4198 100644
--- a/fs/squashfs/decompressor.c
+++ b/fs/squashfs/decompressor.c
@@ -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);
 
diff --git a/fs/squashfs/decompressor_multi.c b/fs/squashfs/decompressor_multi.c
index db9f12a3ea05..eb25432bd149 100644
--- a/fs/squashfs/decompressor_multi.c
+++ b/fs/squashfs/decompressor_multi.c
@@ -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;
@@ -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;
@@ -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) {
@@ -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)
 {
@@ -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,
+};
diff --git a/fs/squashfs/decompressor_multi_percpu.c b/fs/squashfs/decompressor_multi_percpu.c
index b881b9283b7f..1dfadf76ed9a 100644
--- a/fs/squashfs/decompressor_multi_percpu.c
+++ b/fs/squashfs/decompressor_multi_percpu.c
@@ -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;
@@ -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;
@@ -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",
@@ -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,
+};
diff --git a/fs/squashfs/decompressor_single.c b/fs/squashfs/decompressor_single.c
index 4eb3d083d45e..6f161887710b 100644
--- a/fs/squashfs/decompressor_single.c
+++ b/fs/squashfs/decompressor_single.c
@@ -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;
@@ -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;
 
@@ -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)
 {
@@ -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,
+};
diff --git a/fs/squashfs/squashfs.h b/fs/squashfs/squashfs.h
index 9783e01c8100..a6164fdf9435 100644
--- a/fs/squashfs/squashfs.h
+++ b/fs/squashfs/squashfs.h
@@ -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,
diff --git a/fs/squashfs/squashfs_fs_sb.h b/fs/squashfs/squashfs_fs_sb.h
index 1e90c2575f9b..f1e5dad8ae0a 100644
--- a/fs/squashfs/squashfs_fs_sb.h
+++ b/fs/squashfs/squashfs_fs_sb.h
@@ -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;
@@ -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
diff --git a/fs/squashfs/super.c b/fs/squashfs/super.c
index 32565dafa7f3..6ba6fb90b391 100644
--- a/fs/squashfs/super.c
+++ b/fs/squashfs/super.c
@@ -47,10 +47,12 @@ enum Opt_errors {
 
 enum squashfs_param {
 	Opt_errors,
+	Opt_threads,
 };
 
 struct squashfs_mount_opts {
 	enum Opt_errors errors;
+	const struct squashfs_decompressor_thread_ops *thread_ops;
 };
 
 static const struct constant_table squashfs_param_errors[] = {
@@ -61,9 +63,29 @@ static const struct constant_table squashfs_param_errors[] = {
 
 static const struct fs_parameter_spec squashfs_fs_parameters[] = {
 	fsparam_enum("errors", Opt_errors, squashfs_param_errors),
+	fsparam_string("threads", Opt_threads),
 	{}
 };
 
+static int squashfs_parse_param_threads(const char *str, struct squashfs_mount_opts *opts)
+{
+#ifdef CONFIG_SQUASHFS_CHOICE_DECOMP_BY_MOUNT
+	if (strcmp(str, "single") == 0) {
+		opts->thread_ops = &squashfs_decompressor_single;
+		return 0;
+	}
+	if (strcmp(str, "multi") == 0) {
+		opts->thread_ops = &squashfs_decompressor_multi;
+		return 0;
+	}
+	if (strcmp(str, "percpu") == 0) {
+		opts->thread_ops = &squashfs_decompressor_percpu;
+		return 0;
+	}
+#endif
+	return -EINVAL;
+}
+
 static int squashfs_parse_param(struct fs_context *fc, struct fs_parameter *param)
 {
 	struct squashfs_mount_opts *opts = fc->fs_private;
@@ -78,6 +100,10 @@ static int squashfs_parse_param(struct fs_context *fc, struct fs_parameter *para
 	case Opt_errors:
 		opts->errors = result.uint_32;
 		break;
+	case Opt_threads:
+		if (squashfs_parse_param_threads(param->string, opts) != 0)
+			return -EINVAL;
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -167,6 +193,7 @@ static int squashfs_fill_super(struct super_block *sb, struct fs_context *fc)
 			       sb->s_bdev);
 		goto failed_mount;
 	}
+	msblk->thread_ops = opts->thread_ops;
 
 	/* Check the MAJOR & MINOR versions and lookup compression type */
 	msblk->decompressor = supported_squashfs_filesystem(
@@ -252,7 +279,7 @@ static int squashfs_fill_super(struct super_block *sb, struct fs_context *fc)
 
 	/* Allocate read_page block */
 	msblk->read_page = squashfs_cache_init("data",
-		squashfs_max_decompressors(), msblk->block_size);
+		msblk->thread_ops->max_decompressors(), msblk->block_size);
 	if (msblk->read_page == NULL) {
 		errorf(fc, "Failed to allocate read_page block");
 		goto failed_mount;
@@ -383,7 +410,7 @@ static int squashfs_fill_super(struct super_block *sb, struct fs_context *fc)
 	squashfs_cache_delete(msblk->block_cache);
 	squashfs_cache_delete(msblk->fragment_cache);
 	squashfs_cache_delete(msblk->read_page);
-	squashfs_decompressor_destroy(msblk);
+	msblk->thread_ops->destroy(msblk);
 	kfree(msblk->inode_lookup_table);
 	kfree(msblk->fragment_index);
 	kfree(msblk->id_table);
@@ -435,6 +462,20 @@ static int squashfs_show_options(struct seq_file *s, struct dentry *root)
 	else
 		seq_puts(s, ",errors=continue");
 
+#ifdef CONFIG_SQUASHFS_CHOICE_DECOMP_BY_MOUNT
+	if (msblk->thread_ops == &squashfs_decompressor_single) {
+		seq_puts(s, ",threads=single");
+		return 0;
+	}
+	if (msblk->thread_ops == &squashfs_decompressor_multi) {
+		seq_puts(s, ",threads=multi");
+		return 0;
+	}
+	if (msblk->thread_ops == &squashfs_decompressor_percpu) {
+		seq_puts(s, ",threads=percpu");
+		return 0;
+	}
+#endif
 	return 0;
 }
 
@@ -446,6 +487,9 @@ static int squashfs_init_fs_context(struct fs_context *fc)
 	if (!opts)
 		return -ENOMEM;
 
+#ifdef CONFIG_SQUASHFS_CHOICE_DECOMP_BY_MOUNT
+	opts->thread_ops = &squashfs_decompressor_single;
+#endif
 	fc->fs_private = opts;
 	fc->ops = &squashfs_context_ops;
 	return 0;
@@ -478,7 +522,7 @@ static void squashfs_put_super(struct super_block *sb)
 		squashfs_cache_delete(sbi->block_cache);
 		squashfs_cache_delete(sbi->fragment_cache);
 		squashfs_cache_delete(sbi->read_page);
-		squashfs_decompressor_destroy(sbi);
+		sbi->thread_ops->destroy(sbi);
 		kfree(sbi->id_table);
 		kfree(sbi->fragment_index);
 		kfree(sbi->meta_index);
-- 
2.12.3


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH v5 2/2] squashfs: Allows users to configure the number of  decompression threads
  2022-09-30  9:14       ` [PATCH v5 " Xiaoming Ni
  2022-09-30  9:14         ` [PATCH v5 1/2] squashfs: add the mount parameter theads=<single|multi|percpu> Xiaoming Ni
@ 2022-09-30  9:14         ` Xiaoming Ni
  2022-10-17  0:57         ` ping// Re: [PATCH v5 0/2] squashfs: Add the mount parameter "threads=" Xiaoming Ni
  2022-10-19  3:09         ` [PATCH v6 " Xiaoming Ni
  3 siblings, 0 replies; 38+ messages in thread
From: Xiaoming Ni @ 2022-09-30  9:14 UTC (permalink / raw)
  To: linux-kernel, phillip
  Cc: nixiaoming, wangle6, yi.zhang, zhongjubin, chenjianguo3

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.

Signed-off-by: Xiaoming Ni <nixiaoming@huawei.com>
---
 fs/squashfs/Kconfig              | 16 ++++++++--
 fs/squashfs/decompressor_multi.c |  4 +--
 fs/squashfs/squashfs_fs_sb.h     |  1 +
 fs/squashfs/super.c              | 63 +++++++++++++++++++++++++++++++++-------
 4 files changed, 70 insertions(+), 14 deletions(-)

diff --git a/fs/squashfs/Kconfig b/fs/squashfs/Kconfig
index 218bacdd4298..60fc98bdf421 100644
--- a/fs/squashfs/Kconfig
+++ b/fs/squashfs/Kconfig
@@ -73,11 +73,10 @@ config SQUASHFS_CHOICE_DECOMP_BY_MOUNT
 	select SQUASHFS_DECOMP_SINGLE
 	select SQUASHFS_DECOMP_MULTI
 	select SQUASHFS_DECOMP_MULTI_PERCPU
+	select SQUASHFS_MOUNT_DECOMP_THREADS
 	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
@@ -127,6 +126,19 @@ config SQUASHFS_COMPILE_DECOMP_MULTI_PERCPU
 	  decompression is load-balanced across the cores.
 endchoice
 
+config SQUASHFS_MOUNT_DECOMP_THREADS
+	bool "Add the mount parameter 'threads=' for squashfs"
+	depends on SQUASHFS
+	depends on SQUASHFS_DECOMP_MULTI
+	default n
+	help
+	  Use threads= to set the decompression parallel mode and the number of threads.
+	  If SQUASHFS_CHOICE_DECOMP_BY_MOUNT=y
+	      threads=<single|multi|percpu|1|2|3|...>
+	  else
+	      threads=<2|3|...>
+	  The upper limit is num_online_cpus() * 2.
+
 config SQUASHFS_XATTR
 	bool "Squashfs XATTR support"
 	depends on SQUASHFS
diff --git a/fs/squashfs/decompressor_multi.c b/fs/squashfs/decompressor_multi.c
index eb25432bd149..416c53eedbd1 100644
--- a/fs/squashfs/decompressor_multi.c
+++ b/fs/squashfs/decompressor_multi.c
@@ -144,7 +144,7 @@ static struct decomp_stream *get_decomp_stream(struct squashfs_sb_info *msblk,
 		 * If there is no available decomp and already full,
 		 * let's wait for releasing decomp from other users.
 		 */
-		if (stream->avail_decomp >= MAX_DECOMPRESSOR)
+		if (stream->avail_decomp >= msblk->max_thread_num)
 			goto wait;
 
 		/* Let's allocate new decomp */
@@ -160,7 +160,7 @@ static struct decomp_stream *get_decomp_stream(struct squashfs_sb_info *msblk,
 		}
 
 		stream->avail_decomp++;
-		WARN_ON(stream->avail_decomp > MAX_DECOMPRESSOR);
+		WARN_ON(stream->avail_decomp > msblk->max_thread_num);
 
 		mutex_unlock(&stream->mutex);
 		break;
diff --git a/fs/squashfs/squashfs_fs_sb.h b/fs/squashfs/squashfs_fs_sb.h
index f1e5dad8ae0a..659082e9e51d 100644
--- a/fs/squashfs/squashfs_fs_sb.h
+++ b/fs/squashfs/squashfs_fs_sb.h
@@ -67,5 +67,6 @@ struct squashfs_sb_info {
 	unsigned int				ids;
 	bool					panic_on_errors;
 	const struct squashfs_decompressor_thread_ops *thread_ops;
+	int					max_thread_num;
 };
 #endif
diff --git a/fs/squashfs/super.c b/fs/squashfs/super.c
index 6ba6fb90b391..920449e1675f 100644
--- a/fs/squashfs/super.c
+++ b/fs/squashfs/super.c
@@ -53,6 +53,7 @@ enum squashfs_param {
 struct squashfs_mount_opts {
 	enum Opt_errors errors;
 	const struct squashfs_decompressor_thread_ops *thread_ops;
+	int thread_num;
 };
 
 static const struct constant_table squashfs_param_errors[] = {
@@ -67,7 +68,8 @@ static const struct fs_parameter_spec squashfs_fs_parameters[] = {
 	{}
 };
 
-static int squashfs_parse_param_threads(const char *str, struct squashfs_mount_opts *opts)
+
+static int squashfs_parse_param_threads_str(const char *str, struct squashfs_mount_opts *opts)
 {
 #ifdef CONFIG_SQUASHFS_CHOICE_DECOMP_BY_MOUNT
 	if (strcmp(str, "single") == 0) {
@@ -86,6 +88,42 @@ static int squashfs_parse_param_threads(const char *str, struct squashfs_mount_o
 	return -EINVAL;
 }
 
+static int squashfs_parse_param_threads_num(const char *str, struct squashfs_mount_opts *opts)
+{
+#ifdef CONFIG_SQUASHFS_MOUNT_DECOMP_THREADS
+	int ret;
+	unsigned long num;
+
+	ret = kstrtoul(str, 0, &num);
+	if (ret != 0)
+		return -EINVAL;
+	if (num > 1) {
+		opts->thread_ops = &squashfs_decompressor_multi;
+		if (num > opts->thread_ops->max_decompressors())
+			return -EINVAL;
+		opts->thread_num = (int)num;
+		return 0;
+	}
+#ifdef CONFIG_SQUASHFS_DECOMP_SINGLE
+	if (num == 1) {
+		opts->thread_ops = &squashfs_decompressor_single;
+		opts->thread_num = 1;
+		return 0;
+	}
+#endif
+#endif /* !CONFIG_SQUASHFS_MOUNT_DECOMP_THREADS */
+	return -EINVAL;
+}
+
+static int squashfs_parse_param_threads(const char *str, struct squashfs_mount_opts *opts)
+{
+	int ret = squashfs_parse_param_threads_str(str, opts);
+
+	if (ret == 0)
+		return ret;
+	return squashfs_parse_param_threads_num(str, opts);
+}
+
 static int squashfs_parse_param(struct fs_context *fc, struct fs_parameter *param)
 {
 	struct squashfs_mount_opts *opts = fc->fs_private;
@@ -194,6 +232,11 @@ static int squashfs_fill_super(struct super_block *sb, struct fs_context *fc)
 		goto failed_mount;
 	}
 	msblk->thread_ops = opts->thread_ops;
+	if (opts->thread_num == 0) {
+		msblk->max_thread_num = msblk->thread_ops->max_decompressors();
+	} else {
+		msblk->max_thread_num = opts->thread_num;
+	}
 
 	/* Check the MAJOR & MINOR versions and lookup compression type */
 	msblk->decompressor = supported_squashfs_filesystem(
@@ -279,7 +322,7 @@ static int squashfs_fill_super(struct super_block *sb, struct fs_context *fc)
 
 	/* Allocate read_page block */
 	msblk->read_page = squashfs_cache_init("data",
-		msblk->thread_ops->max_decompressors(), msblk->block_size);
+		msblk->max_thread_num, msblk->block_size);
 	if (msblk->read_page == NULL) {
 		errorf(fc, "Failed to allocate read_page block");
 		goto failed_mount;
@@ -463,18 +506,17 @@ static int squashfs_show_options(struct seq_file *s, struct dentry *root)
 		seq_puts(s, ",errors=continue");
 
 #ifdef CONFIG_SQUASHFS_CHOICE_DECOMP_BY_MOUNT
-	if (msblk->thread_ops == &squashfs_decompressor_single) {
-		seq_puts(s, ",threads=single");
-		return 0;
-	}
-	if (msblk->thread_ops == &squashfs_decompressor_multi) {
-		seq_puts(s, ",threads=multi");
-		return 0;
-	}
 	if (msblk->thread_ops == &squashfs_decompressor_percpu) {
 		seq_puts(s, ",threads=percpu");
 		return 0;
 	}
+	if (msblk->thread_ops == &squashfs_decompressor_single) {
+		seq_puts(s, ",threads=single");
+		return 0;
+	}
+#endif
+#ifdef CONFIG_SQUASHFS_MOUNT_DECOMP_THREADS
+	seq_printf(s, ",threads=%d", msblk->max_thread_num);
 #endif
 	return 0;
 }
@@ -490,6 +532,7 @@ static int squashfs_init_fs_context(struct fs_context *fc)
 #ifdef CONFIG_SQUASHFS_CHOICE_DECOMP_BY_MOUNT
 	opts->thread_ops = &squashfs_decompressor_single;
 #endif
+	opts->thread_num = 0;
 	fc->fs_private = opts;
 	fc->ops = &squashfs_context_ops;
 	return 0;
-- 
2.12.3


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* ping// Re: [PATCH v5 0/2] squashfs: Add the mount parameter "threads="
  2022-09-30  9:14       ` [PATCH v5 " Xiaoming Ni
  2022-09-30  9:14         ` [PATCH v5 1/2] squashfs: add the mount parameter theads=<single|multi|percpu> Xiaoming Ni
  2022-09-30  9:14         ` [PATCH v5 2/2] squashfs: Allows users to configure the number of decompression threads Xiaoming Ni
@ 2022-10-17  0:57         ` Xiaoming Ni
  2022-10-17 22:59           ` Phillip Lougher
  2022-10-19  3:09         ` [PATCH v6 " Xiaoming Ni
  3 siblings, 1 reply; 38+ messages in thread
From: Xiaoming Ni @ 2022-10-17  0:57 UTC (permalink / raw)
  To: linux-kernel, phillip; +Cc: wangle6, yi.zhang, zhongjubin, chenjianguo3

ping

On 2022/9/30 17:14, Xiaoming Ni wrote:
> 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.
> 
> v5: fix a low-level mistake in patching:
>    fs/squashfs/super.c:492:7: warning: "CONFIG_SQUASHFS_DECOMP_MULTI" is
>    not defined, evaluates to 0 [-Wundef]
> 
> v4: https://lore.kernel.org/lkml/20220916083604.33408-1-nixiaoming@huawei.com/
>   Based on Philip Lougher's suggestion, make the following updates:
>   1. Use static modifiers to avoid changing symbol names.
>   2. Fixed some formatting issues
> 
> v3: https://lore.kernel.org/lkml/20220902094855.22666-1-nixiaoming@huawei.com/
>    Based on Philip Lougher's suggestion, make the following updates:
>    1. The default configuration is the same as that before the patch installation.
>    2. Compile the three decompression modes when the new configuration is enabled.
>    3. "threads=1" supports only the SQUASHFS_DECOMP_SINGLE mode.
> 
> v2: https://lore.kernel.org/lkml/20220816010052.15764-1-nixiaoming@huawei.com/
>    fix warning: sparse: incorrect type in initializer (different address spaces)
>    Reported-by: kernel test robot <lkp@intel.com>
> 
> v1: https://lore.kernel.org/lkml/20220815031100.75243-1-nixiaoming@huawei.com/
> 
> Xiaoming Ni (2):
>    squashfs: add the mount parameter theads=<single|multi|percpu>
>    squashfs: Allows users to configure the number of  decompression
>      threads
> 
>   fs/squashfs/Kconfig                     | 51 ++++++++++++++++--
>   fs/squashfs/block.c                     |  2 +-
>   fs/squashfs/decompressor.c              |  2 +-
>   fs/squashfs/decompressor_multi.c        | 20 ++++---
>   fs/squashfs/decompressor_multi_percpu.c | 23 +++++---
>   fs/squashfs/decompressor_single.c       | 15 ++++--
>   fs/squashfs/squashfs.h                  | 23 ++++++--
>   fs/squashfs/squashfs_fs_sb.h            |  4 +-
>   fs/squashfs/super.c                     | 93 +++++++++++++++++++++++++++++++--
>   9 files changed, 199 insertions(+), 34 deletions(-)
> 


^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re [PATCH v5 1/2] squashfs: add the mount parameter theads=<single|multi|percpu>
  2022-09-30  9:14         ` [PATCH v5 1/2] squashfs: add the mount parameter theads=<single|multi|percpu> Xiaoming Ni
@ 2022-10-17 21:58           ` Phillip Lougher
  0 siblings, 0 replies; 38+ messages in thread
From: Phillip Lougher @ 2022-10-17 21:58 UTC (permalink / raw)
  To: nixiaoming
  Cc: chenjianguo3, linux-kernel, phillip, wangle6, yi.zhang, zhongjubin

On 30 Sep 2022 17:14:05 +0800 Xiaoming Ni wrote:
>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.
>

You have made another mistake in fixing this patch.

Previously, I asked you to fix patch lines (appearing in V3) which caused
a build error.

These lines were:

@@ -446,6 +487,13 @@ static int squashfs_init_fs_context(struct fs_context *fc)
 	if (!opts)
 		return -ENOMEM;
 
+#ifdef CONFIG_SQUASHFS_DECOMP_SINGLE
+	opts->thread_ops = &squashfs_decompressor_single;
+#elif CONFIG_SQUASHFS_DECOMP_MULTI
+	opts->thread_ops = &squashfs_decompressor_multi;
+#elif CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU
+	opts->thread_ops = &squashfs_decompressor_percpu;
+#endif
 	fc->fs_private = opts;
 	fc->ops = &squashfs_context_ops;
 	return 0;

I expected you to replace the

+#elif CONFIG_SQUASHFS_DECOMP_MULTI

line with

+#elif defined(CONFIG_SQUASHFS_DECOMP_MULTI)

and the

+#elif CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU

line with

+#elif defined(CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU)

If you had done that then the patch set would finally have been OK.

Instead you did this in this patch ...

> 
>@@ -446,6 +487,9 @@ static int squashfs_init_fs_context(struct fs_context *fc)
> 	if (!opts)
> 		return -ENOMEM;
> 
>+#ifdef CONFIG_SQUASHFS_CHOICE_DECOMP_BY_MOUNT
>+	opts->thread_ops = &squashfs_decompressor_single;
>+#endif
> 	fc->fs_private = opts;
> 	fc->ops = &squashfs_context_ops;
> 	return 0;

You have removed the build error by removing the offending lines.

But, you have rather obviously left opt->thread_ops unassigned
if CONFIG_SQUASHFS_CHOICE_DECOMP_BY_MOUNT is not set.

Given the following configuration

CONFIG_SQUASHFS=y
# CONFIG_SQUASHFS_FILE_CACHE is not set
CONFIG_SQUASHFS_FILE_DIRECT=y
CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU=y
# CONFIG_SQUASHFS_CHOICE_DECOMP_BY_MOUNT is not set
# CONFIG_SQUASHFS_COMPILE_DECOMP_SINGLE is not set
# CONFIG_SQUASHFS_COMPILE_DECOMP_MULTI is not set
CONFIG_SQUASHFS_COMPILE_DECOMP_MULTI_PERCPU=y
CONFIG_SQUASHFS_XATTR=y
CONFIG_SQUASHFS_ZLIB=y
CONFIG_SQUASHFS_LZ4=y
CONFIG_SQUASHFS_LZO=y
CONFIG_SQUASHFS_XZ=y
CONFIG_SQUASHFS_ZSTD=y
# CONFIG_SQUASHFS_4K_DEVBLK_SIZE is not set
# CONFIG_SQUASHFS_EMBEDDED is not set
CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3

You will get the following kernel oops with this patch applied.

root@logopolis:~# mount -t squashfs /dev/sdb /mnt
BUG: kernel NULL pointer dereference, address: 0000000000000018
#PF: supervisor read access in kernel mode
#PF: error_code(0x0000) - not-present page
PGD 8000000004db0067 P4D 8000000004db0067 PUD 5bf0067 PMD 0 
Oops: 0000 [#1] PREEMPT SMP PTI
CPU: 3 PID: 1482 Comm: mount Not tainted 6.0.0+ #38
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.15.0-0-g2dd4b9b3f840-prebuilt.qemu.org 04/01/2014
RIP: 0010:squashfs_fill_super+0x2d5/0x700
Code: e0 c9 02 82 e8 2c d0 ff ff 48 89 43 10 48 89 c7 48 85 c0 0f 84 10 03 00 00 8b 93 98 00 00 00 48 8b 83 c0 00 00 00 89 54 24 04 <48> 8b 40 18 e8 12 51 b8 00 8b 54 24 04 48 c7 c7 86 fb 21 82 89 c6
RSP: 0018:ffffc900024e7de0 EFLAGS: 00010286
RAX: 0000000000000000 RBX: ffff88800611b300 RCX: 00000000000003db
RDX: 0000000000100000 RSI: 0000000000000cc0 RDI: ffff888004411600
RBP: ffff888004689000 R08: ffff888004411900 R09: 0000000000000000
R10: ffff88800440f450 R11: 0000000000024298 R12: ffff888004ea9540
R13: 000002c12876123d R14: ffff8880044115a0 R15: 00000000000000c0
FS:  00007f99343ea840(0000) GS:ffff88807dd80000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000000000000018 CR3: 00000000046ea000 CR4: 00000000000006e0
Call Trace:
 <TASK>
 ? squashfs_init_fs_context+0x40/0x40
 get_tree_bdev+0x16a/0x260
 vfs_get_tree+0x20/0xb0
 path_mount+0x2d3/0xa70
 __x64_sys_mount+0x194/0x1f0
 do_syscall_64+0x43/0x90
 entry_SYSCALL_64_after_hwframe+0x63/0xcd
RIP: 0033:0x7f9933621d8a
Code: 48 8b 0d 01 c1 2b 00 f7 d8 64 89 01 48 83 c8 ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 49 89 ca b8 a5 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d ce c0 2b 00 f7 d8 64 89 01 48
RSP: 002b:00007ffd3d78d138 EFLAGS: 00000202 ORIG_RAX: 00000000000000a5
RAX: ffffffffffffffda RBX: 00007ffd3d78d260 RCX: 00007f9933621d8a
RDX: 00000000006191e0 RSI: 00000000006191c0 RDI: 00000000006191a0
RBP: 00000000c0ed0000 R08: 0000000000000000 R09: 0000000000619300
R10: ffffffffc0ed0000 R11: 0000000000000202 R12: 00000000006191c0
R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000
 </TASK>
Modules linked in:
CR2: 0000000000000018
---[ end trace 0000000000000000 ]---
RIP: 0010:squashfs_fill_super+0x2d5/0x700
Code: e0 c9 02 82 e8 2c d0 ff ff 48 89 43 10 48 89 c7 48 85 c0 0f 84 10 03 00 00 8b 93 98 00 00 00 48 8b 83 c0 00 00 00 89 54 24 04 <48> 8b 40 18 e8 12 51 b8 00 8b 54 24 04 48 c7 c7 86 fb 21 82 89 c6
RSP: 0018:ffffc900024e7de0 EFLAGS: 00010286
RAX: 0000000000000000 RBX: ffff88800611b300 RCX: 00000000000003db
RDX: 0000000000100000 RSI: 0000000000000cc0 RDI: ffff888004411600
RBP: ffff888004689000 R08: ffff888004411900 R09: 0000000000000000
R10: ffff88800440f450 R11: 0000000000024298 R12: ffff888004ea9540
R13: 000002c12876123d R14: ffff8880044115a0 R15: 00000000000000c0
FS:  00007f99343ea840(0000) GS:ffff88807dd80000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000000000000018 CR3: 00000000046ea000 CR4: 00000000000006e0
Killed

I do not understand why you have not fixed the patch as I have asked,
and instead repeatedly sent patches which are obviously broken.

Cheers

Phillip

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: ping// Re: [PATCH v5 0/2] squashfs: Add the mount parameter "threads="
  2022-10-17  0:57         ` ping// Re: [PATCH v5 0/2] squashfs: Add the mount parameter "threads=" Xiaoming Ni
@ 2022-10-17 22:59           ` Phillip Lougher
  2022-10-18  6:24             ` Xiaoming Ni
  0 siblings, 1 reply; 38+ messages in thread
From: Phillip Lougher @ 2022-10-17 22:59 UTC (permalink / raw)
  To: Xiaoming Ni
  Cc: linux-kernel, phillip, wangle6, yi.zhang, zhongjubin, chenjianguo3

On Mon, Oct 17, 2022 at 2:11 AM Xiaoming Ni <nixiaoming@huawei.com> wrote:
>
> ping

I was hoping you'd notice the obvious mistake you made in the patch set,
and send an updated version, which would avoid me having to point out
such mistakes again.

I have replied to patch [1/2]

Phillip

>
> On 2022/9/30 17:14, Xiaoming Ni wrote:
> > 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.
> >
> > v5: fix a low-level mistake in patching:
> >    fs/squashfs/super.c:492:7: warning: "CONFIG_SQUASHFS_DECOMP_MULTI" is
> >    not defined, evaluates to 0 [-Wundef]
> >
> > v4: https://lore.kernel.org/lkml/20220916083604.33408-1-nixiaoming@huawei.com/
> >   Based on Philip Lougher's suggestion, make the following updates:
> >   1. Use static modifiers to avoid changing symbol names.
> >   2. Fixed some formatting issues
> >
> > v3: https://lore.kernel.org/lkml/20220902094855.22666-1-nixiaoming@huawei.com/
> >    Based on Philip Lougher's suggestion, make the following updates:
> >    1. The default configuration is the same as that before the patch installation.
> >    2. Compile the three decompression modes when the new configuration is enabled.
> >    3. "threads=1" supports only the SQUASHFS_DECOMP_SINGLE mode.
> >
> > v2: https://lore.kernel.org/lkml/20220816010052.15764-1-nixiaoming@huawei.com/
> >    fix warning: sparse: incorrect type in initializer (different address spaces)
> >    Reported-by: kernel test robot <lkp@intel.com>
> >
> > v1: https://lore.kernel.org/lkml/20220815031100.75243-1-nixiaoming@huawei.com/
> >
> > Xiaoming Ni (2):
> >    squashfs: add the mount parameter theads=<single|multi|percpu>
> >    squashfs: Allows users to configure the number of  decompression
> >      threads
> >
> >   fs/squashfs/Kconfig                     | 51 ++++++++++++++++--
> >   fs/squashfs/block.c                     |  2 +-
> >   fs/squashfs/decompressor.c              |  2 +-
> >   fs/squashfs/decompressor_multi.c        | 20 ++++---
> >   fs/squashfs/decompressor_multi_percpu.c | 23 +++++---
> >   fs/squashfs/decompressor_single.c       | 15 ++++--
> >   fs/squashfs/squashfs.h                  | 23 ++++++--
> >   fs/squashfs/squashfs_fs_sb.h            |  4 +-
> >   fs/squashfs/super.c                     | 93 +++++++++++++++++++++++++++++++--
> >   9 files changed, 199 insertions(+), 34 deletions(-)
> >
>

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: ping// Re: [PATCH v5 0/2] squashfs: Add the mount parameter "threads="
  2022-10-17 22:59           ` Phillip Lougher
@ 2022-10-18  6:24             ` Xiaoming Ni
  0 siblings, 0 replies; 38+ messages in thread
From: Xiaoming Ni @ 2022-10-18  6:24 UTC (permalink / raw)
  To: Phillip Lougher
  Cc: linux-kernel, phillip, wangle6, yi.zhang, zhongjubin, chenjianguo3

On 2022/10/18 6:59, Phillip Lougher wrote:
> On Mon, Oct 17, 2022 at 2:11 AM Xiaoming Ni <nixiaoming@huawei.com> wrote:
>>
>> ping
> 
> I was hoping you'd notice the obvious mistake you made in the patch set,
> and send an updated version, which would avoid me having to point out
> such mistakes again.
> 
> I have replied to patch [1/2]
> 
> Phillip
> 
I'm so sorry.
I'm very ashamed of my serial mistakes.

I'll fix it again later and resend it, I'm sorry I need to take up your 
valuable time to help review it again.


Thanks
Xiaoming Ni



^ permalink raw reply	[flat|nested] 38+ messages in thread

* [PATCH v6 0/2] squashfs: Add the mount parameter "threads="
  2022-09-30  9:14       ` [PATCH v5 " Xiaoming Ni
                           ` (2 preceding siblings ...)
  2022-10-17  0:57         ` ping// Re: [PATCH v5 0/2] squashfs: Add the mount parameter "threads=" Xiaoming Ni
@ 2022-10-19  3:09         ` Xiaoming Ni
  2022-10-19  3:09           ` [PATCH v6 1/2] squashfs: add the mount parameter theads=<single|multi|percpu> Xiaoming Ni
                             ` (2 more replies)
  3 siblings, 3 replies; 38+ messages in thread
From: Xiaoming Ni @ 2022-10-19  3:09 UTC (permalink / raw)
  To: linux-kernel, phillip
  Cc: nixiaoming, wangle6, yi.zhang, zhongjubin, chenjianguo3

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.

v6: fix opt->thread_ops unassigned if CONFIG_SQUASHFS_CHOICE_DECOMP_BY_MOUNT is not set.

v5: https://lore.kernel.org/lkml/20220930091406.50869-1-nixiaoming@huawei.com/
  fix a low-level mistake in patching:
  fs/squashfs/super.c:492:7: warning: "CONFIG_SQUASHFS_DECOMP_MULTI" is 
  not defined, evaluates to 0 [-Wundef]

v4: https://lore.kernel.org/lkml/20220916083604.33408-1-nixiaoming@huawei.com/
 Based on Philip Lougher's suggestion, make the following updates:
 1. Use static modifiers to avoid changing symbol names.
 2. Fixed some formatting issues

v3: https://lore.kernel.org/lkml/20220902094855.22666-1-nixiaoming@huawei.com/
  Based on Philip Lougher's suggestion, make the following updates:
  1. The default configuration is the same as that before the patch installation.
  2. Compile the three decompression modes when the new configuration is enabled.
  3. "threads=1" supports only the SQUASHFS_DECOMP_SINGLE mode.

v2: https://lore.kernel.org/lkml/20220816010052.15764-1-nixiaoming@huawei.com/
  fix warning: sparse: incorrect type in initializer (different address spaces)
  Reported-by: kernel test robot <lkp@intel.com>

v1: https://lore.kernel.org/lkml/20220815031100.75243-1-nixiaoming@huawei.com/
*** BLURB HERE ***

Xiaoming Ni (2):
  squashfs: add the mount parameter theads=<single|multi|percpu>
  squashfs: Allows users to configure the number of decompression
    threads

 fs/squashfs/Kconfig                     | 51 +++++++++++--
 fs/squashfs/block.c                     |  2 +-
 fs/squashfs/decompressor.c              |  2 +-
 fs/squashfs/decompressor_multi.c        | 20 +++--
 fs/squashfs/decompressor_multi_percpu.c | 23 ++++--
 fs/squashfs/decompressor_single.c       | 15 +++-
 fs/squashfs/squashfs.h                  | 23 ++++--
 fs/squashfs/squashfs_fs_sb.h            |  4 +-
 fs/squashfs/super.c                     | 97 ++++++++++++++++++++++++-
 9 files changed, 203 insertions(+), 34 deletions(-)

-- 
2.27.0


^ permalink raw reply	[flat|nested] 38+ messages in thread

* [PATCH v6 1/2] squashfs: add the mount parameter theads=<single|multi|percpu>
  2022-10-19  3:09         ` [PATCH v6 " Xiaoming Ni
@ 2022-10-19  3:09           ` Xiaoming Ni
  2022-10-19  3:09           ` [PATCH v6 2/2] squashfs: Allows users to configure the number of decompression threads Xiaoming Ni
  2022-10-27 22:44           ` [PATCH v6 0/2] squashfs: Add the mount parameter "threads=" Phillip Lougher
  2 siblings, 0 replies; 38+ messages in thread
From: Xiaoming Ni @ 2022-10-19  3:09 UTC (permalink / raw)
  To: linux-kernel, phillip
  Cc: nixiaoming, wangle6, yi.zhang, zhongjubin, chenjianguo3

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.

Signed-off-by: Xiaoming Ni <nixiaoming@huawei.com>
---
 fs/squashfs/Kconfig                     | 39 ++++++++++++++---
 fs/squashfs/block.c                     |  2 +-
 fs/squashfs/decompressor.c              |  2 +-
 fs/squashfs/decompressor_multi.c        | 16 ++++---
 fs/squashfs/decompressor_multi_percpu.c | 23 ++++++----
 fs/squashfs/decompressor_single.c       | 15 +++++--
 fs/squashfs/squashfs.h                  | 23 +++++++---
 fs/squashfs/squashfs_fs_sb.h            |  3 +-
 fs/squashfs/super.c                     | 56 +++++++++++++++++++++++--
 9 files changed, 147 insertions(+), 32 deletions(-)

diff --git a/fs/squashfs/Kconfig b/fs/squashfs/Kconfig
index 916e78fabcaa..218bacdd4298 100644
--- a/fs/squashfs/Kconfig
+++ b/fs/squashfs/Kconfig
@@ -54,9 +54,36 @@ 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
@@ -64,15 +91,17 @@ choice
 
 	  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
@@ -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
@@ -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
diff --git a/fs/squashfs/block.c b/fs/squashfs/block.c
index 833aca92301f..bed3bb8b27fa 100644
--- a/fs/squashfs/block.c
+++ b/fs/squashfs/block.c
@@ -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);
 	}
diff --git a/fs/squashfs/decompressor.c b/fs/squashfs/decompressor.c
index d57bef91ab08..8893cb9b4198 100644
--- a/fs/squashfs/decompressor.c
+++ b/fs/squashfs/decompressor.c
@@ -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);
 
diff --git a/fs/squashfs/decompressor_multi.c b/fs/squashfs/decompressor_multi.c
index db9f12a3ea05..eb25432bd149 100644
--- a/fs/squashfs/decompressor_multi.c
+++ b/fs/squashfs/decompressor_multi.c
@@ -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;
@@ -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;
@@ -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) {
@@ -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)
 {
@@ -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,
+};
diff --git a/fs/squashfs/decompressor_multi_percpu.c b/fs/squashfs/decompressor_multi_percpu.c
index b881b9283b7f..1dfadf76ed9a 100644
--- a/fs/squashfs/decompressor_multi_percpu.c
+++ b/fs/squashfs/decompressor_multi_percpu.c
@@ -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;
@@ -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;
@@ -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",
@@ -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,
+};
diff --git a/fs/squashfs/decompressor_single.c b/fs/squashfs/decompressor_single.c
index 4eb3d083d45e..6f161887710b 100644
--- a/fs/squashfs/decompressor_single.c
+++ b/fs/squashfs/decompressor_single.c
@@ -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;
@@ -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;
 
@@ -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)
 {
@@ -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,
+};
diff --git a/fs/squashfs/squashfs.h b/fs/squashfs/squashfs.h
index 9783e01c8100..a6164fdf9435 100644
--- a/fs/squashfs/squashfs.h
+++ b/fs/squashfs/squashfs.h
@@ -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,
diff --git a/fs/squashfs/squashfs_fs_sb.h b/fs/squashfs/squashfs_fs_sb.h
index 1e90c2575f9b..f1e5dad8ae0a 100644
--- a/fs/squashfs/squashfs_fs_sb.h
+++ b/fs/squashfs/squashfs_fs_sb.h
@@ -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;
@@ -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
diff --git a/fs/squashfs/super.c b/fs/squashfs/super.c
index 32565dafa7f3..aac3ea72a9ba 100644
--- a/fs/squashfs/super.c
+++ b/fs/squashfs/super.c
@@ -47,10 +47,12 @@ enum Opt_errors {
 
 enum squashfs_param {
 	Opt_errors,
+	Opt_threads,
 };
 
 struct squashfs_mount_opts {
 	enum Opt_errors errors;
+	const struct squashfs_decompressor_thread_ops *thread_ops;
 };
 
 static const struct constant_table squashfs_param_errors[] = {
@@ -61,9 +63,29 @@ static const struct constant_table squashfs_param_errors[] = {
 
 static const struct fs_parameter_spec squashfs_fs_parameters[] = {
 	fsparam_enum("errors", Opt_errors, squashfs_param_errors),
+	fsparam_string("threads", Opt_threads),
 	{}
 };
 
+static int squashfs_parse_param_threads(const char *str, struct squashfs_mount_opts *opts)
+{
+#ifdef CONFIG_SQUASHFS_CHOICE_DECOMP_BY_MOUNT
+	if (strcmp(str, "single") == 0) {
+		opts->thread_ops = &squashfs_decompressor_single;
+		return 0;
+	}
+	if (strcmp(str, "multi") == 0) {
+		opts->thread_ops = &squashfs_decompressor_multi;
+		return 0;
+	}
+	if (strcmp(str, "percpu") == 0) {
+		opts->thread_ops = &squashfs_decompressor_percpu;
+		return 0;
+	}
+#endif
+	return -EINVAL;
+}
+
 static int squashfs_parse_param(struct fs_context *fc, struct fs_parameter *param)
 {
 	struct squashfs_mount_opts *opts = fc->fs_private;
@@ -78,6 +100,10 @@ static int squashfs_parse_param(struct fs_context *fc, struct fs_parameter *para
 	case Opt_errors:
 		opts->errors = result.uint_32;
 		break;
+	case Opt_threads:
+		if (squashfs_parse_param_threads(param->string, opts) != 0)
+			return -EINVAL;
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -167,6 +193,7 @@ static int squashfs_fill_super(struct super_block *sb, struct fs_context *fc)
 			       sb->s_bdev);
 		goto failed_mount;
 	}
+	msblk->thread_ops = opts->thread_ops;
 
 	/* Check the MAJOR & MINOR versions and lookup compression type */
 	msblk->decompressor = supported_squashfs_filesystem(
@@ -252,7 +279,7 @@ static int squashfs_fill_super(struct super_block *sb, struct fs_context *fc)
 
 	/* Allocate read_page block */
 	msblk->read_page = squashfs_cache_init("data",
-		squashfs_max_decompressors(), msblk->block_size);
+		msblk->thread_ops->max_decompressors(), msblk->block_size);
 	if (msblk->read_page == NULL) {
 		errorf(fc, "Failed to allocate read_page block");
 		goto failed_mount;
@@ -383,7 +410,7 @@ static int squashfs_fill_super(struct super_block *sb, struct fs_context *fc)
 	squashfs_cache_delete(msblk->block_cache);
 	squashfs_cache_delete(msblk->fragment_cache);
 	squashfs_cache_delete(msblk->read_page);
-	squashfs_decompressor_destroy(msblk);
+	msblk->thread_ops->destroy(msblk);
 	kfree(msblk->inode_lookup_table);
 	kfree(msblk->fragment_index);
 	kfree(msblk->id_table);
@@ -435,6 +462,20 @@ static int squashfs_show_options(struct seq_file *s, struct dentry *root)
 	else
 		seq_puts(s, ",errors=continue");
 
+#ifdef CONFIG_SQUASHFS_CHOICE_DECOMP_BY_MOUNT
+	if (msblk->thread_ops == &squashfs_decompressor_single) {
+		seq_puts(s, ",threads=single");
+		return 0;
+	}
+	if (msblk->thread_ops == &squashfs_decompressor_multi) {
+		seq_puts(s, ",threads=multi");
+		return 0;
+	}
+	if (msblk->thread_ops == &squashfs_decompressor_percpu) {
+		seq_puts(s, ",threads=percpu");
+		return 0;
+	}
+#endif
 	return 0;
 }
 
@@ -446,6 +487,15 @@ static int squashfs_init_fs_context(struct fs_context *fc)
 	if (!opts)
 		return -ENOMEM;
 
+#ifdef CONFIG_SQUASHFS_DECOMP_SINGLE
+	opts->thread_ops = &squashfs_decompressor_single;
+#elif defined(CONFIG_SQUASHFS_DECOMP_MULTI)
+	opts->thread_ops = &squashfs_decompressor_multi;
+#elif defined(CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU)
+	opts->thread_ops = &squashfs_decompressor_percpu;
+#else
+#error "fail: unknown squashfs decompression thread mode?"
+#endif
 	fc->fs_private = opts;
 	fc->ops = &squashfs_context_ops;
 	return 0;
@@ -478,7 +528,7 @@ static void squashfs_put_super(struct super_block *sb)
 		squashfs_cache_delete(sbi->block_cache);
 		squashfs_cache_delete(sbi->fragment_cache);
 		squashfs_cache_delete(sbi->read_page);
-		squashfs_decompressor_destroy(sbi);
+		sbi->thread_ops->destroy(sbi);
 		kfree(sbi->id_table);
 		kfree(sbi->fragment_index);
 		kfree(sbi->meta_index);
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH v6 2/2] squashfs: Allows users to configure the number of decompression threads
  2022-10-19  3:09         ` [PATCH v6 " Xiaoming Ni
  2022-10-19  3:09           ` [PATCH v6 1/2] squashfs: add the mount parameter theads=<single|multi|percpu> Xiaoming Ni
@ 2022-10-19  3:09           ` Xiaoming Ni
  2022-10-27 22:44           ` [PATCH v6 0/2] squashfs: Add the mount parameter "threads=" Phillip Lougher
  2 siblings, 0 replies; 38+ messages in thread
From: Xiaoming Ni @ 2022-10-19  3:09 UTC (permalink / raw)
  To: linux-kernel, phillip
  Cc: nixiaoming, wangle6, yi.zhang, zhongjubin, chenjianguo3

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.

Signed-off-by: Xiaoming Ni <nixiaoming@huawei.com>
---
 fs/squashfs/Kconfig              | 16 ++++++++--
 fs/squashfs/decompressor_multi.c |  4 +--
 fs/squashfs/squashfs_fs_sb.h     |  1 +
 fs/squashfs/super.c              | 55 ++++++++++++++++++++++++++++----
 4 files changed, 66 insertions(+), 10 deletions(-)

diff --git a/fs/squashfs/Kconfig b/fs/squashfs/Kconfig
index 218bacdd4298..60fc98bdf421 100644
--- a/fs/squashfs/Kconfig
+++ b/fs/squashfs/Kconfig
@@ -73,11 +73,10 @@ config SQUASHFS_CHOICE_DECOMP_BY_MOUNT
 	select SQUASHFS_DECOMP_SINGLE
 	select SQUASHFS_DECOMP_MULTI
 	select SQUASHFS_DECOMP_MULTI_PERCPU
+	select SQUASHFS_MOUNT_DECOMP_THREADS
 	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
@@ -127,6 +126,19 @@ config SQUASHFS_COMPILE_DECOMP_MULTI_PERCPU
 	  decompression is load-balanced across the cores.
 endchoice
 
+config SQUASHFS_MOUNT_DECOMP_THREADS
+	bool "Add the mount parameter 'threads=' for squashfs"
+	depends on SQUASHFS
+	depends on SQUASHFS_DECOMP_MULTI
+	default n
+	help
+	  Use threads= to set the decompression parallel mode and the number of threads.
+	  If SQUASHFS_CHOICE_DECOMP_BY_MOUNT=y
+	      threads=<single|multi|percpu|1|2|3|...>
+	  else
+	      threads=<2|3|...>
+	  The upper limit is num_online_cpus() * 2.
+
 config SQUASHFS_XATTR
 	bool "Squashfs XATTR support"
 	depends on SQUASHFS
diff --git a/fs/squashfs/decompressor_multi.c b/fs/squashfs/decompressor_multi.c
index eb25432bd149..416c53eedbd1 100644
--- a/fs/squashfs/decompressor_multi.c
+++ b/fs/squashfs/decompressor_multi.c
@@ -144,7 +144,7 @@ static struct decomp_stream *get_decomp_stream(struct squashfs_sb_info *msblk,
 		 * If there is no available decomp and already full,
 		 * let's wait for releasing decomp from other users.
 		 */
-		if (stream->avail_decomp >= MAX_DECOMPRESSOR)
+		if (stream->avail_decomp >= msblk->max_thread_num)
 			goto wait;
 
 		/* Let's allocate new decomp */
@@ -160,7 +160,7 @@ static struct decomp_stream *get_decomp_stream(struct squashfs_sb_info *msblk,
 		}
 
 		stream->avail_decomp++;
-		WARN_ON(stream->avail_decomp > MAX_DECOMPRESSOR);
+		WARN_ON(stream->avail_decomp > msblk->max_thread_num);
 
 		mutex_unlock(&stream->mutex);
 		break;
diff --git a/fs/squashfs/squashfs_fs_sb.h b/fs/squashfs/squashfs_fs_sb.h
index f1e5dad8ae0a..659082e9e51d 100644
--- a/fs/squashfs/squashfs_fs_sb.h
+++ b/fs/squashfs/squashfs_fs_sb.h
@@ -67,5 +67,6 @@ struct squashfs_sb_info {
 	unsigned int				ids;
 	bool					panic_on_errors;
 	const struct squashfs_decompressor_thread_ops *thread_ops;
+	int					max_thread_num;
 };
 #endif
diff --git a/fs/squashfs/super.c b/fs/squashfs/super.c
index aac3ea72a9ba..1e428ca9414e 100644
--- a/fs/squashfs/super.c
+++ b/fs/squashfs/super.c
@@ -53,6 +53,7 @@ enum squashfs_param {
 struct squashfs_mount_opts {
 	enum Opt_errors errors;
 	const struct squashfs_decompressor_thread_ops *thread_ops;
+	int thread_num;
 };
 
 static const struct constant_table squashfs_param_errors[] = {
@@ -67,7 +68,8 @@ static const struct fs_parameter_spec squashfs_fs_parameters[] = {
 	{}
 };
 
-static int squashfs_parse_param_threads(const char *str, struct squashfs_mount_opts *opts)
+
+static int squashfs_parse_param_threads_str(const char *str, struct squashfs_mount_opts *opts)
 {
 #ifdef CONFIG_SQUASHFS_CHOICE_DECOMP_BY_MOUNT
 	if (strcmp(str, "single") == 0) {
@@ -86,6 +88,42 @@ static int squashfs_parse_param_threads(const char *str, struct squashfs_mount_o
 	return -EINVAL;
 }
 
+static int squashfs_parse_param_threads_num(const char *str, struct squashfs_mount_opts *opts)
+{
+#ifdef CONFIG_SQUASHFS_MOUNT_DECOMP_THREADS
+	int ret;
+	unsigned long num;
+
+	ret = kstrtoul(str, 0, &num);
+	if (ret != 0)
+		return -EINVAL;
+	if (num > 1) {
+		opts->thread_ops = &squashfs_decompressor_multi;
+		if (num > opts->thread_ops->max_decompressors())
+			return -EINVAL;
+		opts->thread_num = (int)num;
+		return 0;
+	}
+#ifdef CONFIG_SQUASHFS_DECOMP_SINGLE
+	if (num == 1) {
+		opts->thread_ops = &squashfs_decompressor_single;
+		opts->thread_num = 1;
+		return 0;
+	}
+#endif
+#endif /* !CONFIG_SQUASHFS_MOUNT_DECOMP_THREADS */
+	return -EINVAL;
+}
+
+static int squashfs_parse_param_threads(const char *str, struct squashfs_mount_opts *opts)
+{
+	int ret = squashfs_parse_param_threads_str(str, opts);
+
+	if (ret == 0)
+		return ret;
+	return squashfs_parse_param_threads_num(str, opts);
+}
+
 static int squashfs_parse_param(struct fs_context *fc, struct fs_parameter *param)
 {
 	struct squashfs_mount_opts *opts = fc->fs_private;
@@ -194,6 +232,11 @@ static int squashfs_fill_super(struct super_block *sb, struct fs_context *fc)
 		goto failed_mount;
 	}
 	msblk->thread_ops = opts->thread_ops;
+	if (opts->thread_num == 0) {
+		msblk->max_thread_num = msblk->thread_ops->max_decompressors();
+	} else {
+		msblk->max_thread_num = opts->thread_num;
+	}
 
 	/* Check the MAJOR & MINOR versions and lookup compression type */
 	msblk->decompressor = supported_squashfs_filesystem(
@@ -279,7 +322,7 @@ static int squashfs_fill_super(struct super_block *sb, struct fs_context *fc)
 
 	/* Allocate read_page block */
 	msblk->read_page = squashfs_cache_init("data",
-		msblk->thread_ops->max_decompressors(), msblk->block_size);
+		msblk->max_thread_num, msblk->block_size);
 	if (msblk->read_page == NULL) {
 		errorf(fc, "Failed to allocate read_page block");
 		goto failed_mount;
@@ -467,14 +510,13 @@ static int squashfs_show_options(struct seq_file *s, struct dentry *root)
 		seq_puts(s, ",threads=single");
 		return 0;
 	}
-	if (msblk->thread_ops == &squashfs_decompressor_multi) {
-		seq_puts(s, ",threads=multi");
-		return 0;
-	}
 	if (msblk->thread_ops == &squashfs_decompressor_percpu) {
 		seq_puts(s, ",threads=percpu");
 		return 0;
 	}
+#endif
+#ifdef CONFIG_SQUASHFS_MOUNT_DECOMP_THREADS
+	seq_printf(s, ",threads=%d", msblk->max_thread_num);
 #endif
 	return 0;
 }
@@ -496,6 +538,7 @@ static int squashfs_init_fs_context(struct fs_context *fc)
 #else
 #error "fail: unknown squashfs decompression thread mode?"
 #endif
+	opts->thread_num = 0;
 	fc->fs_private = opts;
 	fc->ops = &squashfs_context_ops;
 	return 0;
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* Re: [PATCH v6 0/2] squashfs: Add the mount parameter "threads="
  2022-10-19  3:09         ` [PATCH v6 " Xiaoming Ni
  2022-10-19  3:09           ` [PATCH v6 1/2] squashfs: add the mount parameter theads=<single|multi|percpu> Xiaoming Ni
  2022-10-19  3:09           ` [PATCH v6 2/2] squashfs: Allows users to configure the number of decompression threads Xiaoming Ni
@ 2022-10-27 22:44           ` Phillip Lougher
  2 siblings, 0 replies; 38+ messages in thread
From: Phillip Lougher @ 2022-10-27 22:44 UTC (permalink / raw)
  To: Xiaoming Ni, linux-kernel, Andrew Morton
  Cc: wangle6, yi.zhang, zhongjubin, chenjianguo3

On 19/10/2022 04:09, Xiaoming Ni wrote:
> 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.
> 
> v6: fix opt->thread_ops unassigned if CONFIG_SQUASHFS_CHOICE_DECOMP_BY_MOUNT is not set.
> 

This version looks good to me.  Thanks.

Reviewed-by: Phillip Lougher <phillip@squashfs.org.uk>

> v5: https://lore.kernel.org/lkml/20220930091406.50869-1-nixiaoming@huawei.com/
>    fix a low-level mistake in patching:
>    fs/squashfs/super.c:492:7: warning: "CONFIG_SQUASHFS_DECOMP_MULTI" is
>    not defined, evaluates to 0 [-Wundef]
> 
> v4: https://lore.kernel.org/lkml/20220916083604.33408-1-nixiaoming@huawei.com/
>   Based on Philip Lougher's suggestion, make the following updates:
>   1. Use static modifiers to avoid changing symbol names.
>   2. Fixed some formatting issues
> 
> v3: https://lore.kernel.org/lkml/20220902094855.22666-1-nixiaoming@huawei.com/
>    Based on Philip Lougher's suggestion, make the following updates:
>    1. The default configuration is the same as that before the patch installation.
>    2. Compile the three decompression modes when the new configuration is enabled.
>    3. "threads=1" supports only the SQUASHFS_DECOMP_SINGLE mode.
> 
> v2: https://lore.kernel.org/lkml/20220816010052.15764-1-nixiaoming@huawei.com/
>    fix warning: sparse: incorrect type in initializer (different address spaces)
>    Reported-by: kernel test robot <lkp@intel.com>
> 
> v1: https://lore.kernel.org/lkml/20220815031100.75243-1-nixiaoming@huawei.com/
> *** BLURB HERE ***
> 
> Xiaoming Ni (2):
>    squashfs: add the mount parameter theads=<single|multi|percpu>
>    squashfs: Allows users to configure the number of decompression
>      threads
> 
>   fs/squashfs/Kconfig                     | 51 +++++++++++--
>   fs/squashfs/block.c                     |  2 +-
>   fs/squashfs/decompressor.c              |  2 +-
>   fs/squashfs/decompressor_multi.c        | 20 +++--
>   fs/squashfs/decompressor_multi_percpu.c | 23 ++++--
>   fs/squashfs/decompressor_single.c       | 15 +++-
>   fs/squashfs/squashfs.h                  | 23 ++++--
>   fs/squashfs/squashfs_fs_sb.h            |  4 +-
>   fs/squashfs/super.c                     | 97 ++++++++++++++++++++++++-
>   9 files changed, 203 insertions(+), 34 deletions(-)
> 


^ permalink raw reply	[flat|nested] 38+ messages in thread

end of thread, other threads:[~2022-10-27 22:44 UTC | newest]

Thread overview: 38+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-08-15  3:10 [PATCH 0/2] squashfs: Add the mount parameter "threads=" Xiaoming Ni
2022-08-15  3:10 ` [PATCH 1/2] squashfs: add the mount parameter theads=<single|multi|percpu> Xiaoming Ni
2022-08-15 11:19   ` kernel test robot
2022-08-15  3:11 ` [PATCH 2/2] squashfs: Allows users to configure the number of decompression threads Xiaoming Ni
2022-08-16  1:00 ` [PATCH v2 0/2] squashfs: Add the mount parameter "threads=" Xiaoming Ni
2022-08-16  1:00   ` [PATCH v2 1/2] squashfs: add the mount parameter theads=<single|multi|percpu> Xiaoming Ni
2022-08-16  1:00   ` [PATCH v2 2/2] squashfs: Allows users to configure the number of decompression threads Xiaoming Ni
2022-08-26  6:19   ` ping //Re: [PATCH v2 0/2] squashfs: Add the mount parameter "threads=" Xiaoming Ni
2022-08-28 23:18     ` Phillip Lougher
2022-08-30 13:38       ` Xiaoming Ni
2022-08-30 18:08         ` Phillip Lougher
2022-08-30 18:34           ` Phillip Lougher
2022-08-31  1:09             ` Xiaoming Ni
2022-09-02  9:48   ` [PATCH v3 " Xiaoming Ni
2022-09-02  9:48     ` [PATCH v3 1/2] squashfs: add the mount parameter theads=<single|multi|percpu> Xiaoming Ni
2022-09-09 15:44       ` Phillip Lougher
2022-09-13  2:46         ` Xiaoming Ni
2022-09-09 15:50       ` Phillip Lougher
2022-09-13  2:47         ` Xiaoming Ni
2022-09-02  9:48     ` [PATCH v3 2/2] squashfs: Allows users to configure the number of decompression threads Xiaoming Ni
2022-09-09 15:26     ` [PATCH v3 0/2] squashfs: Add the mount parameter "threads=" Phillip Lougher
2022-09-16  8:36     ` [PATCH v4 " Xiaoming Ni
2022-09-16  8:36       ` [PATCH v4 1/2] squashfs: add the mount parameter theads=<single|multi|percpu> Xiaoming Ni
2022-09-28  2:20         ` Phillip Lougher
2022-09-28  3:06           ` Xiaoming Ni
2022-09-16  8:36       ` [PATCH v4 2/2] squashfs: Allows users to configure the number of decompression threads Xiaoming Ni
2022-09-27  1:05       ` ping //Re: [PATCH v4 0/2] squashfs: Add the mount parameter "threads=" Xiaoming Ni
2022-09-30  9:14       ` [PATCH v5 " Xiaoming Ni
2022-09-30  9:14         ` [PATCH v5 1/2] squashfs: add the mount parameter theads=<single|multi|percpu> Xiaoming Ni
2022-10-17 21:58           ` Re " Phillip Lougher
2022-09-30  9:14         ` [PATCH v5 2/2] squashfs: Allows users to configure the number of decompression threads Xiaoming Ni
2022-10-17  0:57         ` ping// Re: [PATCH v5 0/2] squashfs: Add the mount parameter "threads=" Xiaoming Ni
2022-10-17 22:59           ` Phillip Lougher
2022-10-18  6:24             ` Xiaoming Ni
2022-10-19  3:09         ` [PATCH v6 " Xiaoming Ni
2022-10-19  3:09           ` [PATCH v6 1/2] squashfs: add the mount parameter theads=<single|multi|percpu> Xiaoming Ni
2022-10-19  3:09           ` [PATCH v6 2/2] squashfs: Allows users to configure the number of decompression threads Xiaoming Ni
2022-10-27 22:44           ` [PATCH v6 0/2] squashfs: Add the mount parameter "threads=" Phillip Lougher

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).