Make zlib decompression multi-threaded. Signed-off-by: Stephen Hemminger <shemminger@xxxxxxxxxx> --- a/fs/squashfs/zlib_wrapper.c 2011-04-22 10:57:09.450024619 -0700 +++ b/fs/squashfs/zlib_wrapper.c 2011-04-22 13:15:52.509266395 -0700 @@ -26,6 +26,7 @@ #include <linux/buffer_head.h> #include <linux/slab.h> #include <linux/zlib.h> +#include <linux/percpu.h> #include <linux/vmalloc.h> #include "squashfs_fs.h" @@ -33,31 +34,53 @@ #include "squashfs.h" #include "decompressor.h" +/* don't use per superblock stream anymore. */ static void *zlib_init(struct squashfs_sb_info *dummy, void *buff, int len) { - z_stream *stream = kmalloc(sizeof(z_stream), GFP_KERNEL); - if (stream == NULL) - goto failed; - stream->workspace = vmalloc(zlib_inflate_workspacesize()); - if (stream->workspace == NULL) - goto failed; + z_stream __percpu *percpu; + z_stream *stream; + int cpu, cpu0; + + percpu = alloc_percpu(z_stream); + if (!percpu) { + ERROR("Failed to allocate per cpu stream\n"); + return ERR_PTR(-ENOMEM); + } + + for_each_possible_cpu(cpu) { + stream = per_cpu_ptr(percpu, cpu); + + stream->workspace = vmalloc(zlib_inflate_workspacesize()); + if (stream->workspace == NULL) + goto failed; + } - return stream; + return (__force void *) percpu; failed: - ERROR("Failed to allocate zlib workspace\n"); - kfree(stream); + for_each_possible_cpu(cpu0) { + if (cpu0 == cpu) + break; + stream = per_cpu_ptr(percpu, cpu); + vfree(stream->workspace); + } + free_percpu(percpu); + + ERROR("Failed to allocate zlib workspaces\n"); return ERR_PTR(-ENOMEM); } - static void zlib_free(void *strm) { - z_stream *stream = strm; + z_stream __percpu *percpu = (z_stream __percpu *) strm; + int cpu; - if (stream) + for_each_possible_cpu(cpu) { + z_stream *stream = per_cpu_ptr(percpu, cpu); vfree(stream->workspace); - kfree(stream); + + } + free_percpu(percpu); } @@ -67,9 +90,8 @@ static int zlib_uncompress(struct squash { int zlib_err, zlib_init = 0; int k = 0, page = 0; - z_stream *stream = msblk->stream; - - mutex_lock(&msblk->read_data_mutex); + z_stream __percpu *percpu = (z_stream __percpu *)msblk->stream; + z_stream *stream = get_cpu_ptr(percpu); stream->avail_out = 0; stream->avail_in = 0; @@ -80,7 +102,7 @@ static int zlib_uncompress(struct squash length -= avail; wait_on_buffer(bh[k]); if (!buffer_uptodate(bh[k])) - goto release_mutex; + goto put_per_cpu; stream->next_in = bh[k]->b_data + offset; stream->avail_in = avail; @@ -98,7 +120,7 @@ static int zlib_uncompress(struct squash ERROR("zlib_inflateInit returned unexpected " "result 0x%x, srclength %d\n", zlib_err, srclength); - goto release_mutex; + goto put_per_cpu; } zlib_init = 1; } @@ -111,26 +133,26 @@ static int zlib_uncompress(struct squash if (zlib_err != Z_STREAM_END) { ERROR("zlib_inflate error, data probably corrupt\n"); - goto release_mutex; + goto put_per_cpu; } zlib_err = zlib_inflateEnd(stream); if (zlib_err != Z_OK) { ERROR("zlib_inflate error, data probably corrupt\n"); - goto release_mutex; + goto put_per_cpu; } if (k < b) { ERROR("zlib_uncompress error, data remaining\n"); - goto release_mutex; + goto put_per_cpu; } length = stream->total_out; - mutex_unlock(&msblk->read_data_mutex); + put_cpu_ptr(stream); return length; -release_mutex: - mutex_unlock(&msblk->read_data_mutex); +put_per_cpu: + put_cpu_ptr(stream); for (; k < b; k++) put_bh(bh[k]); -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html