1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Copyright (c) 2013 |
4 | * Phillip Lougher <phillip@squashfs.org.uk> |
5 | */ |
6 | |
7 | #include <linux/types.h> |
8 | #include <linux/mutex.h> |
9 | #include <linux/slab.h> |
10 | #include <linux/bio.h> |
11 | |
12 | #include "squashfs_fs.h" |
13 | #include "squashfs_fs_sb.h" |
14 | #include "decompressor.h" |
15 | #include "squashfs.h" |
16 | |
17 | /* |
18 | * This file implements single-threaded decompression in the |
19 | * decompressor framework |
20 | */ |
21 | |
22 | struct squashfs_stream { |
23 | void *stream; |
24 | struct mutex mutex; |
25 | }; |
26 | |
27 | static void *squashfs_decompressor_create(struct squashfs_sb_info *msblk, |
28 | void *comp_opts) |
29 | { |
30 | struct squashfs_stream *stream; |
31 | int err = -ENOMEM; |
32 | |
33 | stream = kmalloc(size: sizeof(*stream), GFP_KERNEL); |
34 | if (stream == NULL) |
35 | goto out; |
36 | |
37 | stream->stream = msblk->decompressor->init(msblk, comp_opts); |
38 | if (IS_ERR(ptr: stream->stream)) { |
39 | err = PTR_ERR(ptr: stream->stream); |
40 | goto out; |
41 | } |
42 | |
43 | kfree(objp: comp_opts); |
44 | mutex_init(&stream->mutex); |
45 | return stream; |
46 | |
47 | out: |
48 | kfree(objp: stream); |
49 | return ERR_PTR(error: err); |
50 | } |
51 | |
52 | static void squashfs_decompressor_destroy(struct squashfs_sb_info *msblk) |
53 | { |
54 | struct squashfs_stream *stream = msblk->stream; |
55 | |
56 | if (stream) { |
57 | msblk->decompressor->free(stream->stream); |
58 | kfree(objp: stream); |
59 | } |
60 | } |
61 | |
62 | static int squashfs_decompress(struct squashfs_sb_info *msblk, struct bio *bio, |
63 | int offset, int length, |
64 | struct squashfs_page_actor *output) |
65 | { |
66 | int res; |
67 | struct squashfs_stream *stream = msblk->stream; |
68 | |
69 | mutex_lock(&stream->mutex); |
70 | res = msblk->decompressor->decompress(msblk, stream->stream, bio, |
71 | offset, length, output); |
72 | mutex_unlock(lock: &stream->mutex); |
73 | |
74 | if (res < 0) |
75 | ERROR("%s decompression failed, data probably corrupt\n" , |
76 | msblk->decompressor->name); |
77 | |
78 | return res; |
79 | } |
80 | |
81 | static int squashfs_max_decompressors(void) |
82 | { |
83 | return 1; |
84 | } |
85 | |
86 | const struct squashfs_decompressor_thread_ops squashfs_decompressor_single = { |
87 | .create = squashfs_decompressor_create, |
88 | .destroy = squashfs_decompressor_destroy, |
89 | .decompress = squashfs_decompress, |
90 | .max_decompressors = squashfs_max_decompressors, |
91 | }; |
92 | |