aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorPhillip Lougher <phillip@squashfs.org.uk>2013-11-17 21:31:36 -0500
committerPhillip Lougher <phillip@squashfs.org.uk>2013-11-19 22:58:03 -0500
commitd208383d640727b70cd6689bc17e67e9b5ebf4ff (patch)
tree03a6146c22473beb13e2ebda605d6a332ddb758b /fs
parentcd59c2ec5f37a2bc1315c9324aab6c21d43ffa1a (diff)
Squashfs: add multi-threaded decompression using percpu variable
Add a multi-threaded decompression implementation which uses percpu variables. Using percpu variables has advantages and disadvantages over implementations which do not use percpu variables. Advantages: * the nature of percpu variables ensures decompression is load-balanced across the multiple cores. * simplicity. Disadvantages: it limits decompression to one thread per core. Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
Diffstat (limited to 'fs')
-rw-r--r--fs/squashfs/Kconfig57
-rw-r--r--fs/squashfs/Makefile10
-rw-r--r--fs/squashfs/decompressor_multi_percpu.c98
3 files changed, 145 insertions, 20 deletions
diff --git a/fs/squashfs/Kconfig b/fs/squashfs/Kconfig
index 1c6d340fc61f..159bd6676dc2 100644
--- a/fs/squashfs/Kconfig
+++ b/fs/squashfs/Kconfig
@@ -25,6 +25,50 @@ config SQUASHFS
25 25
26 If unsure, say N. 26 If unsure, say N.
27 27
28choice
29 prompt "Decompressor parallelisation options"
30 depends on SQUASHFS
31 help
32 Squashfs now supports three parallelisation options for
33 decompression. Each one exhibits various trade-offs between
34 decompression performance and CPU and memory usage.
35
36 If in doubt, select "Single threaded compression"
37
38config SQUASHFS_DECOMP_SINGLE
39 bool "Single threaded compression"
40 help
41 Traditionally Squashfs has used single-threaded decompression.
42 Only one block (data or metadata) can be decompressed at any
43 one time. This limits CPU and memory usage to a minimum.
44
45config SQUASHFS_DECOMP_MULTI
46 bool "Use multiple decompressors for parallel I/O"
47 help
48 By default Squashfs uses a single decompressor but it gives
49 poor performance on parallel I/O workloads when using multiple CPU
50 machines due to waiting on decompressor availability.
51
52 If you have a parallel I/O workload and your system has enough memory,
53 using this option may improve overall I/O performance.
54
55 This decompressor implementation uses up to two parallel
56 decompressors per core. It dynamically allocates decompressors
57 on a demand basis.
58
59config SQUASHFS_DECOMP_MULTI_PERCPU
60 bool "Use percpu multiple decompressors for parallel I/O"
61 help
62 By default Squashfs uses a single decompressor but it gives
63 poor performance on parallel I/O workloads when using multiple CPU
64 machines due to waiting on decompressor availability.
65
66 This decompressor implementation uses a maximum of one
67 decompressor per core. It uses percpu variables to ensure
68 decompression is load-balanced across the cores.
69
70endchoice
71
28config SQUASHFS_XATTR 72config SQUASHFS_XATTR
29 bool "Squashfs XATTR support" 73 bool "Squashfs XATTR support"
30 depends on SQUASHFS 74 depends on SQUASHFS
@@ -63,19 +107,6 @@ config SQUASHFS_LZO
63 107
64 If unsure, say N. 108 If unsure, say N.
65 109
66config SQUASHFS_MULTI_DECOMPRESSOR
67 bool "Use multiple decompressors for handling parallel I/O"
68 depends on SQUASHFS
69 help
70 By default Squashfs uses a single decompressor but it gives
71 poor performance on parallel I/O workloads when using multiple CPU
72 machines due to waiting on decompressor availability.
73
74 If you have a parallel I/O workload and your system has enough memory,
75 using this option may improve overall I/O performance.
76
77 If unsure, say N.
78
79config SQUASHFS_XZ 110config SQUASHFS_XZ
80 bool "Include support for XZ compressed file systems" 111 bool "Include support for XZ compressed file systems"
81 depends on SQUASHFS 112 depends on SQUASHFS
diff --git a/fs/squashfs/Makefile b/fs/squashfs/Makefile
index dfebc3b12d61..5833b96ee69c 100644
--- a/fs/squashfs/Makefile
+++ b/fs/squashfs/Makefile
@@ -5,14 +5,10 @@
5obj-$(CONFIG_SQUASHFS) += squashfs.o 5obj-$(CONFIG_SQUASHFS) += squashfs.o
6squashfs-y += block.o cache.o dir.o export.o file.o fragment.o id.o inode.o 6squashfs-y += block.o cache.o dir.o export.o file.o fragment.o id.o inode.o
7squashfs-y += namei.o super.o symlink.o decompressor.o 7squashfs-y += namei.o super.o symlink.o decompressor.o
8 8squashfs-$(CONFIG_SQUASHFS_DECOMP_SINGLE) += decompressor_single.o
9squashfs-$(CONFIG_SQUASHFS_DECOMP_MULTI) += decompressor_multi.o
10squashfs-$(CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU) += decompressor_multi_percpu.o
9squashfs-$(CONFIG_SQUASHFS_XATTR) += xattr.o xattr_id.o 11squashfs-$(CONFIG_SQUASHFS_XATTR) += xattr.o xattr_id.o
10squashfs-$(CONFIG_SQUASHFS_LZO) += lzo_wrapper.o 12squashfs-$(CONFIG_SQUASHFS_LZO) += lzo_wrapper.o
11squashfs-$(CONFIG_SQUASHFS_XZ) += xz_wrapper.o 13squashfs-$(CONFIG_SQUASHFS_XZ) += xz_wrapper.o
12squashfs-$(CONFIG_SQUASHFS_ZLIB) += zlib_wrapper.o 14squashfs-$(CONFIG_SQUASHFS_ZLIB) += zlib_wrapper.o
13
14ifdef CONFIG_SQUASHFS_MULTI_DECOMPRESSOR
15 squashfs-y += decompressor_multi.o
16else
17 squashfs-y += decompressor_single.o
18endif
diff --git a/fs/squashfs/decompressor_multi_percpu.c b/fs/squashfs/decompressor_multi_percpu.c
new file mode 100644
index 000000000000..0e7b679bc4ad
--- /dev/null
+++ b/fs/squashfs/decompressor_multi_percpu.c
@@ -0,0 +1,98 @@
1/*
2 * Copyright (c) 2013
3 * Phillip Lougher <phillip@squashfs.org.uk>
4 *
5 * This work is licensed under the terms of the GNU GPL, version 2. See
6 * the COPYING file in the top-level directory.
7 */
8
9#include <linux/types.h>
10#include <linux/slab.h>
11#include <linux/percpu.h>
12#include <linux/buffer_head.h>
13
14#include "squashfs_fs.h"
15#include "squashfs_fs_sb.h"
16#include "decompressor.h"
17#include "squashfs.h"
18
19/*
20 * This file implements multi-threaded decompression using percpu
21 * variables, one thread per cpu core.
22 */
23
24struct squashfs_stream {
25 void *stream;
26};
27
28void *squashfs_decompressor_create(struct squashfs_sb_info *msblk,
29 void *comp_opts)
30{
31 struct squashfs_stream *stream;
32 struct squashfs_stream __percpu *percpu;
33 int err, cpu;
34
35 percpu = alloc_percpu(struct squashfs_stream);
36 if (percpu == NULL)
37 return ERR_PTR(-ENOMEM);
38
39 for_each_possible_cpu(cpu) {
40 stream = per_cpu_ptr(percpu, cpu);
41 stream->stream = msblk->decompressor->init(msblk, comp_opts);
42 if (IS_ERR(stream->stream)) {
43 err = PTR_ERR(stream->stream);
44 goto out;
45 }
46 }
47
48 kfree(comp_opts);
49 return (__force void *) percpu;
50
51out:
52 for_each_possible_cpu(cpu) {
53 stream = per_cpu_ptr(percpu, cpu);
54 if (!IS_ERR_OR_NULL(stream->stream))
55 msblk->decompressor->free(stream->stream);
56 }
57 free_percpu(percpu);
58 return ERR_PTR(err);
59}
60
61void squashfs_decompressor_destroy(struct squashfs_sb_info *msblk)
62{
63 struct squashfs_stream __percpu *percpu =
64 (struct squashfs_stream __percpu *) msblk->stream;
65 struct squashfs_stream *stream;
66 int cpu;
67
68 if (msblk->stream) {
69 for_each_possible_cpu(cpu) {
70 stream = per_cpu_ptr(percpu, cpu);
71 msblk->decompressor->free(stream->stream);
72 }
73 free_percpu(percpu);
74 }
75}
76
77int squashfs_decompress(struct squashfs_sb_info *msblk,
78 void **buffer, struct buffer_head **bh, int b, int offset, int length,
79 int srclength, int pages)
80{
81 struct squashfs_stream __percpu *percpu =
82 (struct squashfs_stream __percpu *) msblk->stream;
83 struct squashfs_stream *stream = get_cpu_ptr(percpu);
84 int res = msblk->decompressor->decompress(msblk, stream->stream, buffer,
85 bh, b, offset, length, srclength, pages);
86 put_cpu_ptr(stream);
87
88 if (res < 0)
89 ERROR("%s decompression failed, data probably corrupt\n",
90 msblk->decompressor->name);
91
92 return res;
93}
94
95int squashfs_max_decompressors(void)
96{
97 return num_possible_cpus();
98}