Blame view

fs/squashfs/xz_wrapper.c 4.26 KB
81bb8debd   Phillip Lougher   Squashfs: add XZ ...
1
2
3
4
  /*
   * Squashfs - a compressed read only filesystem for Linux
   *
   * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
d7f2ff671   Phillip Lougher   Squashfs: update ...
5
   * Phillip Lougher <phillip@squashfs.org.uk>
81bb8debd   Phillip Lougher   Squashfs: add XZ ...
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public License
   * as published by the Free Software Foundation; either version 2,
   * or (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
   *
   * xz_wrapper.c
   */
  
  
  #include <linux/mutex.h>
  #include <linux/buffer_head.h>
  #include <linux/slab.h>
  #include <linux/xz.h>
ff750311d   Phillip Lougher   Squashfs: add com...
29
  #include <linux/bitops.h>
81bb8debd   Phillip Lougher   Squashfs: add XZ ...
30
31
32
  
  #include "squashfs_fs.h"
  #include "squashfs_fs_sb.h"
81bb8debd   Phillip Lougher   Squashfs: add XZ ...
33
34
  #include "squashfs.h"
  #include "decompressor.h"
846b730e9   Phillip Lougher   Squashfs: General...
35
  #include "page_actor.h"
81bb8debd   Phillip Lougher   Squashfs: add XZ ...
36
37
38
39
40
  
  struct squashfs_xz {
  	struct xz_dec *state;
  	struct xz_buf buf;
  };
9508c6b90   Phillip Lougher   Squashfs: Refacto...
41
  struct disk_comp_opts {
ff750311d   Phillip Lougher   Squashfs: add com...
42
43
44
  	__le32 dictionary_size;
  	__le32 flags;
  };
9508c6b90   Phillip Lougher   Squashfs: Refacto...
45
46
47
48
49
50
  struct comp_opts {
  	int dict_size;
  };
  
  static void *squashfs_xz_comp_opts(struct squashfs_sb_info *msblk,
  	void *buff, int len)
81bb8debd   Phillip Lougher   Squashfs: add XZ ...
51
  {
9508c6b90   Phillip Lougher   Squashfs: Refacto...
52
53
54
55
56
57
58
59
60
  	struct disk_comp_opts *comp_opts = buff;
  	struct comp_opts *opts;
  	int err = 0, n;
  
  	opts = kmalloc(sizeof(*opts), GFP_KERNEL);
  	if (opts == NULL) {
  		err = -ENOMEM;
  		goto out2;
  	}
ff750311d   Phillip Lougher   Squashfs: add com...
61
62
63
64
65
  
  	if (comp_opts) {
  		/* check compressor options are the expected length */
  		if (len < sizeof(*comp_opts)) {
  			err = -EIO;
9508c6b90   Phillip Lougher   Squashfs: Refacto...
66
  			goto out;
ff750311d   Phillip Lougher   Squashfs: add com...
67
  		}
9508c6b90   Phillip Lougher   Squashfs: Refacto...
68
  		opts->dict_size = le32_to_cpu(comp_opts->dictionary_size);
ff750311d   Phillip Lougher   Squashfs: add com...
69
70
  
  		/* the dictionary size should be 2^n or 2^n+2^(n+1) */
9508c6b90   Phillip Lougher   Squashfs: Refacto...
71
72
  		n = ffs(opts->dict_size) - 1;
  		if (opts->dict_size != (1 << n) && opts->dict_size != (1 << n) +
ff750311d   Phillip Lougher   Squashfs: add com...
73
74
  						(1 << (n + 1))) {
  			err = -EIO;
9508c6b90   Phillip Lougher   Squashfs: Refacto...
75
  			goto out;
ff750311d   Phillip Lougher   Squashfs: add com...
76
  		}
9508c6b90   Phillip Lougher   Squashfs: Refacto...
77
78
79
80
  	} else
  		/* use defaults */
  		opts->dict_size = max_t(int, msblk->block_size,
  							SQUASHFS_METADATA_SIZE);
ff750311d   Phillip Lougher   Squashfs: add com...
81

9508c6b90   Phillip Lougher   Squashfs: Refacto...
82
83
84
85
86
87
88
89
90
91
92
93
94
95
  	return opts;
  
  out:
  	kfree(opts);
  out2:
  	return ERR_PTR(err);
  }
  
  
  static void *squashfs_xz_init(struct squashfs_sb_info *msblk, void *buff)
  {
  	struct comp_opts *comp_opts = buff;
  	struct squashfs_xz *stream;
  	int err;
81bb8debd   Phillip Lougher   Squashfs: add XZ ...
96

ff750311d   Phillip Lougher   Squashfs: add com...
97
98
99
  	stream = kmalloc(sizeof(*stream), GFP_KERNEL);
  	if (stream == NULL) {
  		err = -ENOMEM;
81bb8debd   Phillip Lougher   Squashfs: add XZ ...
100
  		goto failed;
ff750311d   Phillip Lougher   Squashfs: add com...
101
  	}
81bb8debd   Phillip Lougher   Squashfs: add XZ ...
102

9508c6b90   Phillip Lougher   Squashfs: Refacto...
103
  	stream->state = xz_dec_init(XZ_PREALLOC, comp_opts->dict_size);
ff750311d   Phillip Lougher   Squashfs: add com...
104
105
106
  	if (stream->state == NULL) {
  		kfree(stream);
  		err = -ENOMEM;
81bb8debd   Phillip Lougher   Squashfs: add XZ ...
107
  		goto failed;
ff750311d   Phillip Lougher   Squashfs: add com...
108
  	}
81bb8debd   Phillip Lougher   Squashfs: add XZ ...
109
110
111
112
  
  	return stream;
  
  failed:
ff750311d   Phillip Lougher   Squashfs: add com...
113
114
115
  	ERROR("Failed to initialise xz decompressor
  ");
  	return ERR_PTR(err);
81bb8debd   Phillip Lougher   Squashfs: add XZ ...
116
117
118
119
120
121
122
123
124
125
126
127
  }
  
  
  static void squashfs_xz_free(void *strm)
  {
  	struct squashfs_xz *stream = strm;
  
  	if (stream) {
  		xz_dec_end(stream->state);
  		kfree(stream);
  	}
  }
9508c6b90   Phillip Lougher   Squashfs: Refacto...
128
  static int squashfs_xz_uncompress(struct squashfs_sb_info *msblk, void *strm,
846b730e9   Phillip Lougher   Squashfs: General...
129
130
  	struct buffer_head **bh, int b, int offset, int length,
  	struct squashfs_page_actor *output)
81bb8debd   Phillip Lougher   Squashfs: add XZ ...
131
132
  {
  	enum xz_ret xz_err;
846b730e9   Phillip Lougher   Squashfs: General...
133
  	int avail, total = 0, k = 0;
9508c6b90   Phillip Lougher   Squashfs: Refacto...
134
  	struct squashfs_xz *stream = strm;
81bb8debd   Phillip Lougher   Squashfs: add XZ ...
135
136
137
138
139
  
  	xz_dec_reset(stream->state);
  	stream->buf.in_pos = 0;
  	stream->buf.in_size = 0;
  	stream->buf.out_pos = 0;
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
140
  	stream->buf.out_size = PAGE_SIZE;
846b730e9   Phillip Lougher   Squashfs: General...
141
  	stream->buf.out = squashfs_first_page(output);
81bb8debd   Phillip Lougher   Squashfs: add XZ ...
142
143
144
145
146
  
  	do {
  		if (stream->buf.in_pos == stream->buf.in_size && k < b) {
  			avail = min(length, msblk->devblksize - offset);
  			length -= avail;
81bb8debd   Phillip Lougher   Squashfs: add XZ ...
147
148
149
150
151
  			stream->buf.in = bh[k]->b_data + offset;
  			stream->buf.in_size = avail;
  			stream->buf.in_pos = 0;
  			offset = 0;
  		}
846b730e9   Phillip Lougher   Squashfs: General...
152
153
154
155
  		if (stream->buf.out_pos == stream->buf.out_size) {
  			stream->buf.out = squashfs_next_page(output);
  			if (stream->buf.out != NULL) {
  				stream->buf.out_pos = 0;
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
156
  				total += PAGE_SIZE;
846b730e9   Phillip Lougher   Squashfs: General...
157
  			}
81bb8debd   Phillip Lougher   Squashfs: add XZ ...
158
159
160
161
162
163
164
  		}
  
  		xz_err = xz_dec_run(stream->state, &stream->buf);
  
  		if (stream->buf.in_pos == stream->buf.in_size && k < b)
  			put_bh(bh[k++]);
  	} while (xz_err == XZ_OK);
846b730e9   Phillip Lougher   Squashfs: General...
165
  	squashfs_finish_page(output);
9508c6b90   Phillip Lougher   Squashfs: Refacto...
166
167
  	if (xz_err != XZ_STREAM_END || k < b)
  		goto out;
81bb8debd   Phillip Lougher   Squashfs: add XZ ...
168

9508c6b90   Phillip Lougher   Squashfs: Refacto...
169
  	return total + stream->buf.out_pos;
81bb8debd   Phillip Lougher   Squashfs: add XZ ...
170

9508c6b90   Phillip Lougher   Squashfs: Refacto...
171
  out:
81bb8debd   Phillip Lougher   Squashfs: add XZ ...
172
173
174
175
176
177
178
179
  	for (; k < b; k++)
  		put_bh(bh[k]);
  
  	return -EIO;
  }
  
  const struct squashfs_decompressor squashfs_xz_comp_ops = {
  	.init = squashfs_xz_init,
9508c6b90   Phillip Lougher   Squashfs: Refacto...
180
  	.comp_opts = squashfs_xz_comp_opts,
81bb8debd   Phillip Lougher   Squashfs: add XZ ...
181
182
183
184
185
186
  	.free = squashfs_xz_free,
  	.decompress = squashfs_xz_uncompress,
  	.id = XZ_COMPRESSION,
  	.name = "xz",
  	.supported = 1
  };