0001
0002
0003
0004
0005
0006
0007 #include <linux/types.h>
0008 #include <linux/slab.h>
0009 #include <linux/percpu.h>
0010 #include <linux/buffer_head.h>
0011 #include <linux/local_lock.h>
0012
0013 #include "squashfs_fs.h"
0014 #include "squashfs_fs_sb.h"
0015 #include "decompressor.h"
0016 #include "squashfs.h"
0017
0018
0019
0020
0021
0022
0023 struct squashfs_stream {
0024 void *stream;
0025 local_lock_t lock;
0026 };
0027
0028 void *squashfs_decompressor_create(struct squashfs_sb_info *msblk,
0029 void *comp_opts)
0030 {
0031 struct squashfs_stream *stream;
0032 struct squashfs_stream __percpu *percpu;
0033 int err, cpu;
0034
0035 percpu = alloc_percpu(struct squashfs_stream);
0036 if (percpu == NULL)
0037 return ERR_PTR(-ENOMEM);
0038
0039 for_each_possible_cpu(cpu) {
0040 stream = per_cpu_ptr(percpu, cpu);
0041 stream->stream = msblk->decompressor->init(msblk, comp_opts);
0042 if (IS_ERR(stream->stream)) {
0043 err = PTR_ERR(stream->stream);
0044 goto out;
0045 }
0046 local_lock_init(&stream->lock);
0047 }
0048
0049 kfree(comp_opts);
0050 return (__force void *) percpu;
0051
0052 out:
0053 for_each_possible_cpu(cpu) {
0054 stream = per_cpu_ptr(percpu, cpu);
0055 if (!IS_ERR_OR_NULL(stream->stream))
0056 msblk->decompressor->free(stream->stream);
0057 }
0058 free_percpu(percpu);
0059 return ERR_PTR(err);
0060 }
0061
0062 void squashfs_decompressor_destroy(struct squashfs_sb_info *msblk)
0063 {
0064 struct squashfs_stream __percpu *percpu =
0065 (struct squashfs_stream __percpu *) msblk->stream;
0066 struct squashfs_stream *stream;
0067 int cpu;
0068
0069 if (msblk->stream) {
0070 for_each_possible_cpu(cpu) {
0071 stream = per_cpu_ptr(percpu, cpu);
0072 msblk->decompressor->free(stream->stream);
0073 }
0074 free_percpu(percpu);
0075 }
0076 }
0077
0078 int squashfs_decompress(struct squashfs_sb_info *msblk, struct bio *bio,
0079 int offset, int length, struct squashfs_page_actor *output)
0080 {
0081 struct squashfs_stream *stream;
0082 int res;
0083
0084 local_lock(&msblk->stream->lock);
0085 stream = this_cpu_ptr(msblk->stream);
0086
0087 res = msblk->decompressor->decompress(msblk, stream->stream, bio,
0088 offset, length, output);
0089
0090 local_unlock(&msblk->stream->lock);
0091
0092 if (res < 0)
0093 ERROR("%s decompression failed, data probably corrupt\n",
0094 msblk->decompressor->name);
0095
0096 return res;
0097 }
0098
0099 int squashfs_max_decompressors(void)
0100 {
0101 return num_possible_cpus();
0102 }