xref: /linux/fs/btrfs/zlib.c (revision 6e7fd890f1d6ac83805409e9c346240de2705584)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2008 Oracle.  All rights reserved.
4  *
5  * Based on jffs2 zlib code:
6  * Copyright © 2001-2007 Red Hat, Inc.
7  * Created by David Woodhouse <dwmw2@infradead.org>
8  */
9 
10 #include <linux/kernel.h>
11 #include <linux/slab.h>
12 #include <linux/zlib.h>
13 #include <linux/zutil.h>
14 #include <linux/mm.h>
15 #include <linux/init.h>
16 #include <linux/err.h>
17 #include <linux/sched.h>
18 #include <linux/pagemap.h>
19 #include <linux/bio.h>
20 #include <linux/refcount.h>
21 #include "btrfs_inode.h"
22 #include "compression.h"
23 
24 /* workspace buffer size for s390 zlib hardware support */
25 #define ZLIB_DFLTCC_BUF_SIZE    (4 * PAGE_SIZE)
26 
27 struct workspace {
28 	z_stream strm;
29 	char *buf;
30 	unsigned int buf_size;
31 	struct list_head list;
32 	int level;
33 };
34 
35 static struct workspace_manager wsm;
36 
37 struct list_head *zlib_get_workspace(unsigned int level)
38 {
39 	struct list_head *ws = btrfs_get_workspace(BTRFS_COMPRESS_ZLIB, level);
40 	struct workspace *workspace = list_entry(ws, struct workspace, list);
41 
42 	workspace->level = level;
43 
44 	return ws;
45 }
46 
47 void zlib_free_workspace(struct list_head *ws)
48 {
49 	struct workspace *workspace = list_entry(ws, struct workspace, list);
50 
51 	kvfree(workspace->strm.workspace);
52 	kfree(workspace->buf);
53 	kfree(workspace);
54 }
55 
56 struct list_head *zlib_alloc_workspace(unsigned int level)
57 {
58 	struct workspace *workspace;
59 	int workspacesize;
60 
61 	workspace = kzalloc(sizeof(*workspace), GFP_KERNEL);
62 	if (!workspace)
63 		return ERR_PTR(-ENOMEM);
64 
65 	workspacesize = max(zlib_deflate_workspacesize(MAX_WBITS, MAX_MEM_LEVEL),
66 			zlib_inflate_workspacesize());
67 	workspace->strm.workspace = kvzalloc(workspacesize, GFP_KERNEL | __GFP_NOWARN);
68 	workspace->level = level;
69 	workspace->buf = NULL;
70 	/*
71 	 * In case of s390 zlib hardware support, allocate lager workspace
72 	 * buffer. If allocator fails, fall back to a single page buffer.
73 	 */
74 	if (zlib_deflate_dfltcc_enabled()) {
75 		workspace->buf = kmalloc(ZLIB_DFLTCC_BUF_SIZE,
76 					 __GFP_NOMEMALLOC | __GFP_NORETRY |
77 					 __GFP_NOWARN | GFP_NOIO);
78 		workspace->buf_size = ZLIB_DFLTCC_BUF_SIZE;
79 	}
80 	if (!workspace->buf) {
81 		workspace->buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
82 		workspace->buf_size = PAGE_SIZE;
83 	}
84 	if (!workspace->strm.workspace || !workspace->buf)
85 		goto fail;
86 
87 	INIT_LIST_HEAD(&workspace->list);
88 
89 	return &workspace->list;
90 fail:
91 	zlib_free_workspace(&workspace->list);
92 	return ERR_PTR(-ENOMEM);
93 }
94 
95 int zlib_compress_folios(struct list_head *ws, struct address_space *mapping,
96 			 u64 start, struct folio **folios, unsigned long *out_folios,
97 			 unsigned long *total_in, unsigned long *total_out)
98 {
99 	struct workspace *workspace = list_entry(ws, struct workspace, list);
100 	int ret;
101 	char *data_in = NULL;
102 	char *cfolio_out;
103 	int nr_folios = 0;
104 	struct folio *in_folio = NULL;
105 	struct folio *out_folio = NULL;
106 	unsigned long bytes_left;
107 	unsigned int in_buf_folios;
108 	unsigned long len = *total_out;
109 	unsigned long nr_dest_folios = *out_folios;
110 	const unsigned long max_out = nr_dest_folios * PAGE_SIZE;
111 
112 	*out_folios = 0;
113 	*total_out = 0;
114 	*total_in = 0;
115 
116 	ret = zlib_deflateInit(&workspace->strm, workspace->level);
117 	if (unlikely(ret != Z_OK)) {
118 		struct btrfs_inode *inode = BTRFS_I(mapping->host);
119 
120 		btrfs_err(inode->root->fs_info,
121 	"zlib compression init failed, error %d root %llu inode %llu offset %llu",
122 			  ret, btrfs_root_id(inode->root), btrfs_ino(inode), start);
123 		ret = -EIO;
124 		goto out;
125 	}
126 
127 	workspace->strm.total_in = 0;
128 	workspace->strm.total_out = 0;
129 
130 	out_folio = btrfs_alloc_compr_folio();
131 	if (out_folio == NULL) {
132 		ret = -ENOMEM;
133 		goto out;
134 	}
135 	cfolio_out = folio_address(out_folio);
136 	folios[0] = out_folio;
137 	nr_folios = 1;
138 
139 	workspace->strm.next_in = workspace->buf;
140 	workspace->strm.avail_in = 0;
141 	workspace->strm.next_out = cfolio_out;
142 	workspace->strm.avail_out = PAGE_SIZE;
143 
144 	while (workspace->strm.total_in < len) {
145 		/*
146 		 * Get next input pages and copy the contents to
147 		 * the workspace buffer if required.
148 		 */
149 		if (workspace->strm.avail_in == 0) {
150 			bytes_left = len - workspace->strm.total_in;
151 			in_buf_folios = min(DIV_ROUND_UP(bytes_left, PAGE_SIZE),
152 					    workspace->buf_size / PAGE_SIZE);
153 			if (in_buf_folios > 1) {
154 				int i;
155 
156 				for (i = 0; i < in_buf_folios; i++) {
157 					if (data_in) {
158 						kunmap_local(data_in);
159 						folio_put(in_folio);
160 						data_in = NULL;
161 					}
162 					ret = btrfs_compress_filemap_get_folio(mapping,
163 							start, &in_folio);
164 					if (ret < 0)
165 						goto out;
166 					data_in = kmap_local_folio(in_folio, 0);
167 					copy_page(workspace->buf + i * PAGE_SIZE,
168 						  data_in);
169 					start += PAGE_SIZE;
170 				}
171 				workspace->strm.next_in = workspace->buf;
172 			} else {
173 				if (data_in) {
174 					kunmap_local(data_in);
175 					folio_put(in_folio);
176 					data_in = NULL;
177 				}
178 				ret = btrfs_compress_filemap_get_folio(mapping,
179 						start, &in_folio);
180 				if (ret < 0)
181 					goto out;
182 				data_in = kmap_local_folio(in_folio, 0);
183 				start += PAGE_SIZE;
184 				workspace->strm.next_in = data_in;
185 			}
186 			workspace->strm.avail_in = min(bytes_left,
187 						       (unsigned long) workspace->buf_size);
188 		}
189 
190 		ret = zlib_deflate(&workspace->strm, Z_SYNC_FLUSH);
191 		if (unlikely(ret != Z_OK)) {
192 			struct btrfs_inode *inode = BTRFS_I(mapping->host);
193 
194 			btrfs_warn(inode->root->fs_info,
195 		"zlib compression failed, error %d root %llu inode %llu offset %llu",
196 				   ret, btrfs_root_id(inode->root), btrfs_ino(inode),
197 				   start);
198 			zlib_deflateEnd(&workspace->strm);
199 			ret = -EIO;
200 			goto out;
201 		}
202 
203 		/* we're making it bigger, give up */
204 		if (workspace->strm.total_in > 8192 &&
205 		    workspace->strm.total_in <
206 		    workspace->strm.total_out) {
207 			ret = -E2BIG;
208 			goto out;
209 		}
210 		/* we need another page for writing out.  Test this
211 		 * before the total_in so we will pull in a new page for
212 		 * the stream end if required
213 		 */
214 		if (workspace->strm.avail_out == 0) {
215 			if (nr_folios == nr_dest_folios) {
216 				ret = -E2BIG;
217 				goto out;
218 			}
219 			out_folio = btrfs_alloc_compr_folio();
220 			if (out_folio == NULL) {
221 				ret = -ENOMEM;
222 				goto out;
223 			}
224 			cfolio_out = folio_address(out_folio);
225 			folios[nr_folios] = out_folio;
226 			nr_folios++;
227 			workspace->strm.avail_out = PAGE_SIZE;
228 			workspace->strm.next_out = cfolio_out;
229 		}
230 		/* we're all done */
231 		if (workspace->strm.total_in >= len)
232 			break;
233 		if (workspace->strm.total_out > max_out)
234 			break;
235 	}
236 	workspace->strm.avail_in = 0;
237 	/*
238 	 * Call deflate with Z_FINISH flush parameter providing more output
239 	 * space but no more input data, until it returns with Z_STREAM_END.
240 	 */
241 	while (ret != Z_STREAM_END) {
242 		ret = zlib_deflate(&workspace->strm, Z_FINISH);
243 		if (ret == Z_STREAM_END)
244 			break;
245 		if (ret != Z_OK && ret != Z_BUF_ERROR) {
246 			zlib_deflateEnd(&workspace->strm);
247 			ret = -EIO;
248 			goto out;
249 		} else if (workspace->strm.avail_out == 0) {
250 			/* Get another folio for the stream end. */
251 			if (nr_folios == nr_dest_folios) {
252 				ret = -E2BIG;
253 				goto out;
254 			}
255 			out_folio = btrfs_alloc_compr_folio();
256 			if (out_folio == NULL) {
257 				ret = -ENOMEM;
258 				goto out;
259 			}
260 			cfolio_out = folio_address(out_folio);
261 			folios[nr_folios] = out_folio;
262 			nr_folios++;
263 			workspace->strm.avail_out = PAGE_SIZE;
264 			workspace->strm.next_out = cfolio_out;
265 		}
266 	}
267 	zlib_deflateEnd(&workspace->strm);
268 
269 	if (workspace->strm.total_out >= workspace->strm.total_in) {
270 		ret = -E2BIG;
271 		goto out;
272 	}
273 
274 	ret = 0;
275 	*total_out = workspace->strm.total_out;
276 	*total_in = workspace->strm.total_in;
277 out:
278 	*out_folios = nr_folios;
279 	if (data_in) {
280 		kunmap_local(data_in);
281 		folio_put(in_folio);
282 	}
283 
284 	return ret;
285 }
286 
287 int zlib_decompress_bio(struct list_head *ws, struct compressed_bio *cb)
288 {
289 	struct workspace *workspace = list_entry(ws, struct workspace, list);
290 	int ret = 0, ret2;
291 	int wbits = MAX_WBITS;
292 	char *data_in;
293 	size_t total_out = 0;
294 	unsigned long folio_in_index = 0;
295 	size_t srclen = cb->compressed_len;
296 	unsigned long total_folios_in = DIV_ROUND_UP(srclen, PAGE_SIZE);
297 	unsigned long buf_start;
298 	struct folio **folios_in = cb->compressed_folios;
299 
300 	data_in = kmap_local_folio(folios_in[folio_in_index], 0);
301 	workspace->strm.next_in = data_in;
302 	workspace->strm.avail_in = min_t(size_t, srclen, PAGE_SIZE);
303 	workspace->strm.total_in = 0;
304 
305 	workspace->strm.total_out = 0;
306 	workspace->strm.next_out = workspace->buf;
307 	workspace->strm.avail_out = workspace->buf_size;
308 
309 	/* If it's deflate, and it's got no preset dictionary, then
310 	   we can tell zlib to skip the adler32 check. */
311 	if (srclen > 2 && !(data_in[1] & PRESET_DICT) &&
312 	    ((data_in[0] & 0x0f) == Z_DEFLATED) &&
313 	    !(((data_in[0]<<8) + data_in[1]) % 31)) {
314 
315 		wbits = -((data_in[0] >> 4) + 8);
316 		workspace->strm.next_in += 2;
317 		workspace->strm.avail_in -= 2;
318 	}
319 
320 	ret = zlib_inflateInit2(&workspace->strm, wbits);
321 	if (unlikely(ret != Z_OK)) {
322 		struct btrfs_inode *inode = cb->bbio.inode;
323 
324 		kunmap_local(data_in);
325 		btrfs_err(inode->root->fs_info,
326 	"zlib decompression init failed, error %d root %llu inode %llu offset %llu",
327 			  ret, btrfs_root_id(inode->root), btrfs_ino(inode), cb->start);
328 		return -EIO;
329 	}
330 	while (workspace->strm.total_in < srclen) {
331 		ret = zlib_inflate(&workspace->strm, Z_NO_FLUSH);
332 		if (ret != Z_OK && ret != Z_STREAM_END)
333 			break;
334 
335 		buf_start = total_out;
336 		total_out = workspace->strm.total_out;
337 
338 		/* we didn't make progress in this inflate call, we're done */
339 		if (buf_start == total_out)
340 			break;
341 
342 		ret2 = btrfs_decompress_buf2page(workspace->buf,
343 				total_out - buf_start, cb, buf_start);
344 		if (ret2 == 0) {
345 			ret = 0;
346 			goto done;
347 		}
348 
349 		workspace->strm.next_out = workspace->buf;
350 		workspace->strm.avail_out = workspace->buf_size;
351 
352 		if (workspace->strm.avail_in == 0) {
353 			unsigned long tmp;
354 			kunmap_local(data_in);
355 			folio_in_index++;
356 			if (folio_in_index >= total_folios_in) {
357 				data_in = NULL;
358 				break;
359 			}
360 			data_in = kmap_local_folio(folios_in[folio_in_index], 0);
361 			workspace->strm.next_in = data_in;
362 			tmp = srclen - workspace->strm.total_in;
363 			workspace->strm.avail_in = min(tmp, PAGE_SIZE);
364 		}
365 	}
366 	if (unlikely(ret != Z_STREAM_END)) {
367 		btrfs_err(cb->bbio.inode->root->fs_info,
368 		"zlib decompression failed, error %d root %llu inode %llu offset %llu",
369 			  ret, btrfs_root_id(cb->bbio.inode->root),
370 			  btrfs_ino(cb->bbio.inode), cb->start);
371 		ret = -EIO;
372 	} else {
373 		ret = 0;
374 	}
375 done:
376 	zlib_inflateEnd(&workspace->strm);
377 	if (data_in)
378 		kunmap_local(data_in);
379 	return ret;
380 }
381 
382 int zlib_decompress(struct list_head *ws, const u8 *data_in,
383 		struct page *dest_page, unsigned long dest_pgoff, size_t srclen,
384 		size_t destlen)
385 {
386 	struct workspace *workspace = list_entry(ws, struct workspace, list);
387 	int ret = 0;
388 	int wbits = MAX_WBITS;
389 	unsigned long to_copy;
390 
391 	workspace->strm.next_in = data_in;
392 	workspace->strm.avail_in = srclen;
393 	workspace->strm.total_in = 0;
394 
395 	workspace->strm.next_out = workspace->buf;
396 	workspace->strm.avail_out = workspace->buf_size;
397 	workspace->strm.total_out = 0;
398 	/* If it's deflate, and it's got no preset dictionary, then
399 	   we can tell zlib to skip the adler32 check. */
400 	if (srclen > 2 && !(data_in[1] & PRESET_DICT) &&
401 	    ((data_in[0] & 0x0f) == Z_DEFLATED) &&
402 	    !(((data_in[0]<<8) + data_in[1]) % 31)) {
403 
404 		wbits = -((data_in[0] >> 4) + 8);
405 		workspace->strm.next_in += 2;
406 		workspace->strm.avail_in -= 2;
407 	}
408 
409 	ret = zlib_inflateInit2(&workspace->strm, wbits);
410 	if (unlikely(ret != Z_OK)) {
411 		struct btrfs_inode *inode = BTRFS_I(dest_page->mapping->host);
412 
413 		btrfs_err(inode->root->fs_info,
414 		"zlib decompression init failed, error %d root %llu inode %llu offset %llu",
415 			  ret, btrfs_root_id(inode->root), btrfs_ino(inode),
416 			  page_offset(dest_page));
417 		return -EIO;
418 	}
419 
420 	/*
421 	 * Everything (in/out buf) should be at most one sector, there should
422 	 * be no need to switch any input/output buffer.
423 	 */
424 	ret = zlib_inflate(&workspace->strm, Z_FINISH);
425 	to_copy = min(workspace->strm.total_out, destlen);
426 	if (ret != Z_STREAM_END)
427 		goto out;
428 
429 	memcpy_to_page(dest_page, dest_pgoff, workspace->buf, to_copy);
430 
431 out:
432 	if (unlikely(to_copy != destlen)) {
433 		struct btrfs_inode *inode = BTRFS_I(dest_page->mapping->host);
434 
435 		btrfs_err(inode->root->fs_info,
436 "zlib decompression failed, error %d root %llu inode %llu offset %llu decompressed %lu expected %zu",
437 			  ret, btrfs_root_id(inode->root), btrfs_ino(inode),
438 			  page_offset(dest_page), to_copy, destlen);
439 		ret = -EIO;
440 	} else {
441 		ret = 0;
442 	}
443 
444 	zlib_inflateEnd(&workspace->strm);
445 
446 	if (unlikely(to_copy < destlen))
447 		memzero_page(dest_page, dest_pgoff + to_copy, destlen - to_copy);
448 	return ret;
449 }
450 
451 const struct btrfs_compress_op btrfs_zlib_compress = {
452 	.workspace_manager	= &wsm,
453 	.max_level		= 9,
454 	.default_level		= BTRFS_ZLIB_DEFAULT_LEVEL,
455 };
456