Signed-off-by: Stephen Hemminger <shemminger@xxxxxxxxxx> --- a/fs/squashfs/lzo_wrapper.c 2011-04-22 13:15:28.349003198 -0700 +++ b/fs/squashfs/lzo_wrapper.c 2011-04-22 13:21:03.320648456 -0700 @@ -22,6 +22,7 @@ */ #include <linux/mutex.h> +#include <linux/percpu.h> #include <linux/buffer_head.h> #include <linux/slab.h> #include <linux/vmalloc.h> @@ -40,51 +41,71 @@ struct squashfs_lzo { static void *lzo_init(struct squashfs_sb_info *msblk, void *buff, int len) { int block_size = max_t(int, msblk->block_size, SQUASHFS_METADATA_SIZE); + struct squashfs_lzo __percpu *percpu; + struct squashfs_lzo *stream; + int cpu, cpu0; + + percpu = alloc_percpu(struct squashfs_lzo); + if (!percpu) { + ERROR("Failed to allocate per cpu stream\n"); + return ERR_PTR(-ENOMEM); + } - struct squashfs_lzo *stream = kzalloc(sizeof(*stream), GFP_KERNEL); - if (stream == NULL) - goto failed; - stream->input = vmalloc(block_size); - if (stream->input == NULL) - goto failed; - stream->output = vmalloc(block_size); - if (stream->output == NULL) - goto failed2; + for_each_possible_cpu(cpu) { + stream = per_cpu_ptr(percpu, cpu); + + stream->input = vmalloc(block_size); + if (stream->input == NULL) + goto failed; + + stream->output = vmalloc(block_size); + if (stream->output == NULL) + goto failed2; + } - return stream; + return (__force void *) percpu; failed2: vfree(stream->input); failed: + for_each_possible_cpu(cpu0) { + if (cpu0 == cpu) + break; + stream = per_cpu_ptr(percpu, cpu); + vfree(stream->output); + vfree(stream->input); + } ERROR("Failed to allocate lzo workspace\n"); - kfree(stream); + free_percpu(percpu); return ERR_PTR(-ENOMEM); } static void lzo_free(void *strm) { - struct squashfs_lzo *stream = strm; + struct squashfs_lzo __percpu *percpu + = (struct squashfs_lzo __percpu *) strm; + int cpu; - if (stream) { + for_each_possible_cpu(cpu) { + struct squashfs_lzo *stream = per_cpu_ptr(percpu, cpu); vfree(stream->input); vfree(stream->output); } - kfree(stream); + free_percpu(percpu); } - static int lzo_uncompress(struct squashfs_sb_info *msblk, void **buffer, struct buffer_head **bh, int b, int offset, int length, int srclength, int pages) { - struct squashfs_lzo *stream = msblk->stream; + struct squashfs_lzo __percpu *percpu + = (struct squashfs_lzo __percpu *)msblk->stream; + struct squashfs_lzo *stream = get_cpu_ptr(percpu); void *buff = stream->input; int avail, i, bytes = length, res; size_t out_len = srclength; - mutex_lock(&msblk->read_data_mutex); - for (i = 0; i < b; i++) { wait_on_buffer(bh[i]); if (!buffer_uptodate(bh[i])) @@ -111,7 +132,7 @@ static int lzo_uncompress(struct squashf bytes -= avail; } - mutex_unlock(&msblk->read_data_mutex); + put_cpu_ptr(stream); return res; block_release: @@ -119,7 +140,7 @@ block_release: put_bh(bh[i]); failed: - mutex_unlock(&msblk->read_data_mutex); + put_cpu_ptr(stream); ERROR("lzo decompression failed, data probably corrupt\n"); return -EIO; -- 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