xref: /openbmc/linux/fs/btrfs/zlib.c (revision 74ce1896)
1 /*
2  * Copyright (C) 2008 Oracle.  All rights reserved.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public
6  * License v2 as published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public
14  * License along with this program; if not, write to the
15  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16  * Boston, MA 021110-1307, USA.
17  *
18  * Based on jffs2 zlib code:
19  * Copyright © 2001-2007 Red Hat, Inc.
20  * Created by David Woodhouse <dwmw2@infradead.org>
21  */
22 
23 #include <linux/kernel.h>
24 #include <linux/slab.h>
25 #include <linux/zlib.h>
26 #include <linux/zutil.h>
27 #include <linux/mm.h>
28 #include <linux/init.h>
29 #include <linux/err.h>
30 #include <linux/sched.h>
31 #include <linux/pagemap.h>
32 #include <linux/bio.h>
33 #include <linux/refcount.h>
34 #include "compression.h"
35 
36 struct workspace {
37 	z_stream strm;
38 	char *buf;
39 	struct list_head list;
40 };
41 
42 static void zlib_free_workspace(struct list_head *ws)
43 {
44 	struct workspace *workspace = list_entry(ws, struct workspace, list);
45 
46 	kvfree(workspace->strm.workspace);
47 	kfree(workspace->buf);
48 	kfree(workspace);
49 }
50 
51 static struct list_head *zlib_alloc_workspace(void)
52 {
53 	struct workspace *workspace;
54 	int workspacesize;
55 
56 	workspace = kzalloc(sizeof(*workspace), GFP_KERNEL);
57 	if (!workspace)
58 		return ERR_PTR(-ENOMEM);
59 
60 	workspacesize = max(zlib_deflate_workspacesize(MAX_WBITS, MAX_MEM_LEVEL),
61 			zlib_inflate_workspacesize());
62 	workspace->strm.workspace = kvmalloc(workspacesize, GFP_KERNEL);
63 	workspace->buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
64 	if (!workspace->strm.workspace || !workspace->buf)
65 		goto fail;
66 
67 	INIT_LIST_HEAD(&workspace->list);
68 
69 	return &workspace->list;
70 fail:
71 	zlib_free_workspace(&workspace->list);
72 	return ERR_PTR(-ENOMEM);
73 }
74 
75 static int zlib_compress_pages(struct list_head *ws,
76 			       struct address_space *mapping,
77 			       u64 start,
78 			       struct page **pages,
79 			       unsigned long *out_pages,
80 			       unsigned long *total_in,
81 			       unsigned long *total_out)
82 {
83 	struct workspace *workspace = list_entry(ws, struct workspace, list);
84 	int ret;
85 	char *data_in;
86 	char *cpage_out;
87 	int nr_pages = 0;
88 	struct page *in_page = NULL;
89 	struct page *out_page = NULL;
90 	unsigned long bytes_left;
91 	unsigned long len = *total_out;
92 	unsigned long nr_dest_pages = *out_pages;
93 	const unsigned long max_out = nr_dest_pages * PAGE_SIZE;
94 
95 	*out_pages = 0;
96 	*total_out = 0;
97 	*total_in = 0;
98 
99 	if (Z_OK != zlib_deflateInit(&workspace->strm, 3)) {
100 		pr_warn("BTRFS: deflateInit failed\n");
101 		ret = -EIO;
102 		goto out;
103 	}
104 
105 	workspace->strm.total_in = 0;
106 	workspace->strm.total_out = 0;
107 
108 	in_page = find_get_page(mapping, start >> PAGE_SHIFT);
109 	data_in = kmap(in_page);
110 
111 	out_page = alloc_page(GFP_NOFS | __GFP_HIGHMEM);
112 	if (out_page == NULL) {
113 		ret = -ENOMEM;
114 		goto out;
115 	}
116 	cpage_out = kmap(out_page);
117 	pages[0] = out_page;
118 	nr_pages = 1;
119 
120 	workspace->strm.next_in = data_in;
121 	workspace->strm.next_out = cpage_out;
122 	workspace->strm.avail_out = PAGE_SIZE;
123 	workspace->strm.avail_in = min(len, PAGE_SIZE);
124 
125 	while (workspace->strm.total_in < len) {
126 		ret = zlib_deflate(&workspace->strm, Z_SYNC_FLUSH);
127 		if (ret != Z_OK) {
128 			pr_debug("BTRFS: deflate in loop returned %d\n",
129 			       ret);
130 			zlib_deflateEnd(&workspace->strm);
131 			ret = -EIO;
132 			goto out;
133 		}
134 
135 		/* we're making it bigger, give up */
136 		if (workspace->strm.total_in > 8192 &&
137 		    workspace->strm.total_in <
138 		    workspace->strm.total_out) {
139 			ret = -E2BIG;
140 			goto out;
141 		}
142 		/* we need another page for writing out.  Test this
143 		 * before the total_in so we will pull in a new page for
144 		 * the stream end if required
145 		 */
146 		if (workspace->strm.avail_out == 0) {
147 			kunmap(out_page);
148 			if (nr_pages == nr_dest_pages) {
149 				out_page = NULL;
150 				ret = -E2BIG;
151 				goto out;
152 			}
153 			out_page = alloc_page(GFP_NOFS | __GFP_HIGHMEM);
154 			if (out_page == NULL) {
155 				ret = -ENOMEM;
156 				goto out;
157 			}
158 			cpage_out = kmap(out_page);
159 			pages[nr_pages] = out_page;
160 			nr_pages++;
161 			workspace->strm.avail_out = PAGE_SIZE;
162 			workspace->strm.next_out = cpage_out;
163 		}
164 		/* we're all done */
165 		if (workspace->strm.total_in >= len)
166 			break;
167 
168 		/* we've read in a full page, get a new one */
169 		if (workspace->strm.avail_in == 0) {
170 			if (workspace->strm.total_out > max_out)
171 				break;
172 
173 			bytes_left = len - workspace->strm.total_in;
174 			kunmap(in_page);
175 			put_page(in_page);
176 
177 			start += PAGE_SIZE;
178 			in_page = find_get_page(mapping,
179 						start >> PAGE_SHIFT);
180 			data_in = kmap(in_page);
181 			workspace->strm.avail_in = min(bytes_left,
182 							   PAGE_SIZE);
183 			workspace->strm.next_in = data_in;
184 		}
185 	}
186 	workspace->strm.avail_in = 0;
187 	ret = zlib_deflate(&workspace->strm, Z_FINISH);
188 	zlib_deflateEnd(&workspace->strm);
189 
190 	if (ret != Z_STREAM_END) {
191 		ret = -EIO;
192 		goto out;
193 	}
194 
195 	if (workspace->strm.total_out >= workspace->strm.total_in) {
196 		ret = -E2BIG;
197 		goto out;
198 	}
199 
200 	ret = 0;
201 	*total_out = workspace->strm.total_out;
202 	*total_in = workspace->strm.total_in;
203 out:
204 	*out_pages = nr_pages;
205 	if (out_page)
206 		kunmap(out_page);
207 
208 	if (in_page) {
209 		kunmap(in_page);
210 		put_page(in_page);
211 	}
212 	return ret;
213 }
214 
215 static int zlib_decompress_bio(struct list_head *ws, struct compressed_bio *cb)
216 {
217 	struct workspace *workspace = list_entry(ws, struct workspace, list);
218 	int ret = 0, ret2;
219 	int wbits = MAX_WBITS;
220 	char *data_in;
221 	size_t total_out = 0;
222 	unsigned long page_in_index = 0;
223 	size_t srclen = cb->compressed_len;
224 	unsigned long total_pages_in = DIV_ROUND_UP(srclen, PAGE_SIZE);
225 	unsigned long buf_start;
226 	struct page **pages_in = cb->compressed_pages;
227 	u64 disk_start = cb->start;
228 	struct bio *orig_bio = cb->orig_bio;
229 
230 	data_in = kmap(pages_in[page_in_index]);
231 	workspace->strm.next_in = data_in;
232 	workspace->strm.avail_in = min_t(size_t, srclen, PAGE_SIZE);
233 	workspace->strm.total_in = 0;
234 
235 	workspace->strm.total_out = 0;
236 	workspace->strm.next_out = workspace->buf;
237 	workspace->strm.avail_out = PAGE_SIZE;
238 
239 	/* If it's deflate, and it's got no preset dictionary, then
240 	   we can tell zlib to skip the adler32 check. */
241 	if (srclen > 2 && !(data_in[1] & PRESET_DICT) &&
242 	    ((data_in[0] & 0x0f) == Z_DEFLATED) &&
243 	    !(((data_in[0]<<8) + data_in[1]) % 31)) {
244 
245 		wbits = -((data_in[0] >> 4) + 8);
246 		workspace->strm.next_in += 2;
247 		workspace->strm.avail_in -= 2;
248 	}
249 
250 	if (Z_OK != zlib_inflateInit2(&workspace->strm, wbits)) {
251 		pr_warn("BTRFS: inflateInit failed\n");
252 		kunmap(pages_in[page_in_index]);
253 		return -EIO;
254 	}
255 	while (workspace->strm.total_in < srclen) {
256 		ret = zlib_inflate(&workspace->strm, Z_NO_FLUSH);
257 		if (ret != Z_OK && ret != Z_STREAM_END)
258 			break;
259 
260 		buf_start = total_out;
261 		total_out = workspace->strm.total_out;
262 
263 		/* we didn't make progress in this inflate call, we're done */
264 		if (buf_start == total_out)
265 			break;
266 
267 		ret2 = btrfs_decompress_buf2page(workspace->buf, buf_start,
268 						 total_out, disk_start,
269 						 orig_bio);
270 		if (ret2 == 0) {
271 			ret = 0;
272 			goto done;
273 		}
274 
275 		workspace->strm.next_out = workspace->buf;
276 		workspace->strm.avail_out = PAGE_SIZE;
277 
278 		if (workspace->strm.avail_in == 0) {
279 			unsigned long tmp;
280 			kunmap(pages_in[page_in_index]);
281 			page_in_index++;
282 			if (page_in_index >= total_pages_in) {
283 				data_in = NULL;
284 				break;
285 			}
286 			data_in = kmap(pages_in[page_in_index]);
287 			workspace->strm.next_in = data_in;
288 			tmp = srclen - workspace->strm.total_in;
289 			workspace->strm.avail_in = min(tmp,
290 							   PAGE_SIZE);
291 		}
292 	}
293 	if (ret != Z_STREAM_END)
294 		ret = -EIO;
295 	else
296 		ret = 0;
297 done:
298 	zlib_inflateEnd(&workspace->strm);
299 	if (data_in)
300 		kunmap(pages_in[page_in_index]);
301 	if (!ret)
302 		zero_fill_bio(orig_bio);
303 	return ret;
304 }
305 
306 static int zlib_decompress(struct list_head *ws, unsigned char *data_in,
307 			   struct page *dest_page,
308 			   unsigned long start_byte,
309 			   size_t srclen, size_t destlen)
310 {
311 	struct workspace *workspace = list_entry(ws, struct workspace, list);
312 	int ret = 0;
313 	int wbits = MAX_WBITS;
314 	unsigned long bytes_left;
315 	unsigned long total_out = 0;
316 	unsigned long pg_offset = 0;
317 	char *kaddr;
318 
319 	destlen = min_t(unsigned long, destlen, PAGE_SIZE);
320 	bytes_left = destlen;
321 
322 	workspace->strm.next_in = data_in;
323 	workspace->strm.avail_in = srclen;
324 	workspace->strm.total_in = 0;
325 
326 	workspace->strm.next_out = workspace->buf;
327 	workspace->strm.avail_out = PAGE_SIZE;
328 	workspace->strm.total_out = 0;
329 	/* If it's deflate, and it's got no preset dictionary, then
330 	   we can tell zlib to skip the adler32 check. */
331 	if (srclen > 2 && !(data_in[1] & PRESET_DICT) &&
332 	    ((data_in[0] & 0x0f) == Z_DEFLATED) &&
333 	    !(((data_in[0]<<8) + data_in[1]) % 31)) {
334 
335 		wbits = -((data_in[0] >> 4) + 8);
336 		workspace->strm.next_in += 2;
337 		workspace->strm.avail_in -= 2;
338 	}
339 
340 	if (Z_OK != zlib_inflateInit2(&workspace->strm, wbits)) {
341 		pr_warn("BTRFS: inflateInit failed\n");
342 		return -EIO;
343 	}
344 
345 	while (bytes_left > 0) {
346 		unsigned long buf_start;
347 		unsigned long buf_offset;
348 		unsigned long bytes;
349 
350 		ret = zlib_inflate(&workspace->strm, Z_NO_FLUSH);
351 		if (ret != Z_OK && ret != Z_STREAM_END)
352 			break;
353 
354 		buf_start = total_out;
355 		total_out = workspace->strm.total_out;
356 
357 		if (total_out == buf_start) {
358 			ret = -EIO;
359 			break;
360 		}
361 
362 		if (total_out <= start_byte)
363 			goto next;
364 
365 		if (total_out > start_byte && buf_start < start_byte)
366 			buf_offset = start_byte - buf_start;
367 		else
368 			buf_offset = 0;
369 
370 		bytes = min(PAGE_SIZE - pg_offset,
371 			    PAGE_SIZE - buf_offset);
372 		bytes = min(bytes, bytes_left);
373 
374 		kaddr = kmap_atomic(dest_page);
375 		memcpy(kaddr + pg_offset, workspace->buf + buf_offset, bytes);
376 		kunmap_atomic(kaddr);
377 
378 		pg_offset += bytes;
379 		bytes_left -= bytes;
380 next:
381 		workspace->strm.next_out = workspace->buf;
382 		workspace->strm.avail_out = PAGE_SIZE;
383 	}
384 
385 	if (ret != Z_STREAM_END && bytes_left != 0)
386 		ret = -EIO;
387 	else
388 		ret = 0;
389 
390 	zlib_inflateEnd(&workspace->strm);
391 
392 	/*
393 	 * this should only happen if zlib returned fewer bytes than we
394 	 * expected.  btrfs_get_block is responsible for zeroing from the
395 	 * end of the inline extent (destlen) to the end of the page
396 	 */
397 	if (pg_offset < destlen) {
398 		kaddr = kmap_atomic(dest_page);
399 		memset(kaddr + pg_offset, 0, destlen - pg_offset);
400 		kunmap_atomic(kaddr);
401 	}
402 	return ret;
403 }
404 
405 const struct btrfs_compress_op btrfs_zlib_compress = {
406 	.alloc_workspace	= zlib_alloc_workspace,
407 	.free_workspace		= zlib_free_workspace,
408 	.compress_pages		= zlib_compress_pages,
409 	.decompress_bio		= zlib_decompress_bio,
410 	.decompress		= zlib_decompress,
411 };
412