1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2008 Oracle. All rights reserved.
5 * Based on jffs2 zlib code:
6 * Copyright © 2001-2007 Red Hat, Inc.
7 * Created by David Woodhouse <dwmw2@infradead.org>
10 #include <linux/kernel.h>
11 #include <linux/slab.h>
12 #include <linux/zlib.h>
13 #include <linux/zutil.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"
26 /* workspace buffer size for s390 zlib hardware support */
27 #define ZLIB_DFLTCC_BUF_SIZE (4 * PAGE_SIZE)
32 unsigned int buf_size
;
33 struct list_head list
;
37 static struct workspace_manager wsm
;
39 struct list_head
*zlib_get_workspace(unsigned int level
)
41 struct list_head
*ws
= btrfs_get_workspace(BTRFS_COMPRESS_ZLIB
, level
);
42 struct workspace
*workspace
= list_entry(ws
, struct workspace
, list
);
44 workspace
->level
= level
;
49 void zlib_free_workspace(struct list_head
*ws
)
51 struct workspace
*workspace
= list_entry(ws
, struct workspace
, list
);
53 kvfree(workspace
->strm
.workspace
);
54 kfree(workspace
->buf
);
58 struct list_head
*zlib_alloc_workspace(unsigned int level
)
60 struct workspace
*workspace
;
63 workspace
= kzalloc(sizeof(*workspace
), GFP_KERNEL
);
65 return ERR_PTR(-ENOMEM
);
67 workspacesize
= max(zlib_deflate_workspacesize(MAX_WBITS
, MAX_MEM_LEVEL
),
68 zlib_inflate_workspacesize());
69 workspace
->strm
.workspace
= kvzalloc(workspacesize
, GFP_KERNEL
| __GFP_NOWARN
);
70 workspace
->level
= level
;
71 workspace
->buf
= NULL
;
73 * In case of s390 zlib hardware support, allocate lager workspace
74 * buffer. If allocator fails, fall back to a single page buffer.
76 if (zlib_deflate_dfltcc_enabled()) {
77 workspace
->buf
= kmalloc(ZLIB_DFLTCC_BUF_SIZE
,
78 __GFP_NOMEMALLOC
| __GFP_NORETRY
|
79 __GFP_NOWARN
| GFP_NOIO
);
80 workspace
->buf_size
= ZLIB_DFLTCC_BUF_SIZE
;
82 if (!workspace
->buf
) {
83 workspace
->buf
= kmalloc(PAGE_SIZE
, GFP_KERNEL
);
84 workspace
->buf_size
= PAGE_SIZE
;
86 if (!workspace
->strm
.workspace
|| !workspace
->buf
)
89 INIT_LIST_HEAD(&workspace
->list
);
91 return &workspace
->list
;
93 zlib_free_workspace(&workspace
->list
);
94 return ERR_PTR(-ENOMEM
);
97 int zlib_compress_folios(struct list_head
*ws
, struct address_space
*mapping
,
98 u64 start
, struct folio
**folios
, unsigned long *out_folios
,
99 unsigned long *total_in
, unsigned long *total_out
)
101 struct workspace
*workspace
= list_entry(ws
, struct workspace
, list
);
103 char *data_in
= NULL
;
106 struct folio
*in_folio
= NULL
;
107 struct folio
*out_folio
= NULL
;
108 unsigned long bytes_left
;
109 unsigned int in_buf_folios
;
110 unsigned long len
= *total_out
;
111 unsigned long nr_dest_folios
= *out_folios
;
112 const unsigned long max_out
= nr_dest_folios
* PAGE_SIZE
;
113 const u64 orig_end
= start
+ len
;
119 ret
= zlib_deflateInit(&workspace
->strm
, workspace
->level
);
120 if (unlikely(ret
!= Z_OK
)) {
121 struct btrfs_inode
*inode
= BTRFS_I(mapping
->host
);
123 btrfs_err(inode
->root
->fs_info
,
124 "zlib compression init failed, error %d root %llu inode %llu offset %llu",
125 ret
, btrfs_root_id(inode
->root
), btrfs_ino(inode
), start
);
130 workspace
->strm
.total_in
= 0;
131 workspace
->strm
.total_out
= 0;
133 out_folio
= btrfs_alloc_compr_folio();
134 if (out_folio
== NULL
) {
138 cfolio_out
= folio_address(out_folio
);
139 folios
[0] = out_folio
;
142 workspace
->strm
.next_in
= workspace
->buf
;
143 workspace
->strm
.avail_in
= 0;
144 workspace
->strm
.next_out
= cfolio_out
;
145 workspace
->strm
.avail_out
= PAGE_SIZE
;
147 while (workspace
->strm
.total_in
< len
) {
149 * Get next input pages and copy the contents to
150 * the workspace buffer if required.
152 if (workspace
->strm
.avail_in
== 0) {
153 bytes_left
= len
- workspace
->strm
.total_in
;
154 in_buf_folios
= min(DIV_ROUND_UP(bytes_left
, PAGE_SIZE
),
155 workspace
->buf_size
/ PAGE_SIZE
);
156 if (in_buf_folios
> 1) {
159 /* S390 hardware acceleration path, not subpage. */
160 ASSERT(!btrfs_is_subpage(
161 inode_to_fs_info(mapping
->host
),
163 for (i
= 0; i
< in_buf_folios
; i
++) {
165 kunmap_local(data_in
);
169 ret
= btrfs_compress_filemap_get_folio(mapping
,
173 data_in
= kmap_local_folio(in_folio
, 0);
174 copy_page(workspace
->buf
+ i
* PAGE_SIZE
,
177 workspace
->strm
.avail_in
=
178 (in_buf_folios
<< PAGE_SHIFT
);
180 workspace
->strm
.next_in
= workspace
->buf
;
183 unsigned int cur_len
;
186 kunmap_local(data_in
);
190 ret
= btrfs_compress_filemap_get_folio(mapping
,
194 pg_off
= offset_in_page(start
);
195 cur_len
= btrfs_calc_input_length(orig_end
, start
);
196 data_in
= kmap_local_folio(in_folio
, pg_off
);
198 workspace
->strm
.next_in
= data_in
;
199 workspace
->strm
.avail_in
= cur_len
;
203 ret
= zlib_deflate(&workspace
->strm
, Z_SYNC_FLUSH
);
204 if (unlikely(ret
!= Z_OK
)) {
205 struct btrfs_inode
*inode
= BTRFS_I(mapping
->host
);
207 btrfs_warn(inode
->root
->fs_info
,
208 "zlib compression failed, error %d root %llu inode %llu offset %llu",
209 ret
, btrfs_root_id(inode
->root
), btrfs_ino(inode
),
211 zlib_deflateEnd(&workspace
->strm
);
216 /* we're making it bigger, give up */
217 if (workspace
->strm
.total_in
> 8192 &&
218 workspace
->strm
.total_in
<
219 workspace
->strm
.total_out
) {
223 /* we need another page for writing out. Test this
224 * before the total_in so we will pull in a new page for
225 * the stream end if required
227 if (workspace
->strm
.avail_out
== 0) {
228 if (nr_folios
== nr_dest_folios
) {
232 out_folio
= btrfs_alloc_compr_folio();
233 if (out_folio
== NULL
) {
237 cfolio_out
= folio_address(out_folio
);
238 folios
[nr_folios
] = out_folio
;
240 workspace
->strm
.avail_out
= PAGE_SIZE
;
241 workspace
->strm
.next_out
= cfolio_out
;
244 if (workspace
->strm
.total_in
>= len
)
246 if (workspace
->strm
.total_out
> max_out
)
249 workspace
->strm
.avail_in
= 0;
251 * Call deflate with Z_FINISH flush parameter providing more output
252 * space but no more input data, until it returns with Z_STREAM_END.
254 while (ret
!= Z_STREAM_END
) {
255 ret
= zlib_deflate(&workspace
->strm
, Z_FINISH
);
256 if (ret
== Z_STREAM_END
)
258 if (ret
!= Z_OK
&& ret
!= Z_BUF_ERROR
) {
259 zlib_deflateEnd(&workspace
->strm
);
262 } else if (workspace
->strm
.avail_out
== 0) {
263 /* Get another folio for the stream end. */
264 if (nr_folios
== nr_dest_folios
) {
268 out_folio
= btrfs_alloc_compr_folio();
269 if (out_folio
== NULL
) {
273 cfolio_out
= folio_address(out_folio
);
274 folios
[nr_folios
] = out_folio
;
276 workspace
->strm
.avail_out
= PAGE_SIZE
;
277 workspace
->strm
.next_out
= cfolio_out
;
280 zlib_deflateEnd(&workspace
->strm
);
282 if (workspace
->strm
.total_out
>= workspace
->strm
.total_in
) {
288 *total_out
= workspace
->strm
.total_out
;
289 *total_in
= workspace
->strm
.total_in
;
291 *out_folios
= nr_folios
;
293 kunmap_local(data_in
);
300 int zlib_decompress_bio(struct list_head
*ws
, struct compressed_bio
*cb
)
302 struct workspace
*workspace
= list_entry(ws
, struct workspace
, list
);
304 int wbits
= MAX_WBITS
;
306 size_t total_out
= 0;
307 unsigned long folio_in_index
= 0;
308 size_t srclen
= cb
->compressed_len
;
309 unsigned long total_folios_in
= DIV_ROUND_UP(srclen
, PAGE_SIZE
);
310 unsigned long buf_start
;
311 struct folio
**folios_in
= cb
->compressed_folios
;
313 data_in
= kmap_local_folio(folios_in
[folio_in_index
], 0);
314 workspace
->strm
.next_in
= data_in
;
315 workspace
->strm
.avail_in
= min_t(size_t, srclen
, PAGE_SIZE
);
316 workspace
->strm
.total_in
= 0;
318 workspace
->strm
.total_out
= 0;
319 workspace
->strm
.next_out
= workspace
->buf
;
320 workspace
->strm
.avail_out
= workspace
->buf_size
;
322 /* If it's deflate, and it's got no preset dictionary, then
323 we can tell zlib to skip the adler32 check. */
324 if (srclen
> 2 && !(data_in
[1] & PRESET_DICT
) &&
325 ((data_in
[0] & 0x0f) == Z_DEFLATED
) &&
326 !(((data_in
[0]<<8) + data_in
[1]) % 31)) {
328 wbits
= -((data_in
[0] >> 4) + 8);
329 workspace
->strm
.next_in
+= 2;
330 workspace
->strm
.avail_in
-= 2;
333 ret
= zlib_inflateInit2(&workspace
->strm
, wbits
);
334 if (unlikely(ret
!= Z_OK
)) {
335 struct btrfs_inode
*inode
= cb
->bbio
.inode
;
337 kunmap_local(data_in
);
338 btrfs_err(inode
->root
->fs_info
,
339 "zlib decompression init failed, error %d root %llu inode %llu offset %llu",
340 ret
, btrfs_root_id(inode
->root
), btrfs_ino(inode
), cb
->start
);
343 while (workspace
->strm
.total_in
< srclen
) {
344 ret
= zlib_inflate(&workspace
->strm
, Z_NO_FLUSH
);
345 if (ret
!= Z_OK
&& ret
!= Z_STREAM_END
)
348 buf_start
= total_out
;
349 total_out
= workspace
->strm
.total_out
;
351 /* we didn't make progress in this inflate call, we're done */
352 if (buf_start
== total_out
)
355 ret2
= btrfs_decompress_buf2page(workspace
->buf
,
356 total_out
- buf_start
, cb
, buf_start
);
362 workspace
->strm
.next_out
= workspace
->buf
;
363 workspace
->strm
.avail_out
= workspace
->buf_size
;
365 if (workspace
->strm
.avail_in
== 0) {
367 kunmap_local(data_in
);
369 if (folio_in_index
>= total_folios_in
) {
373 data_in
= kmap_local_folio(folios_in
[folio_in_index
], 0);
374 workspace
->strm
.next_in
= data_in
;
375 tmp
= srclen
- workspace
->strm
.total_in
;
376 workspace
->strm
.avail_in
= min(tmp
, PAGE_SIZE
);
379 if (unlikely(ret
!= Z_STREAM_END
)) {
380 btrfs_err(cb
->bbio
.inode
->root
->fs_info
,
381 "zlib decompression failed, error %d root %llu inode %llu offset %llu",
382 ret
, btrfs_root_id(cb
->bbio
.inode
->root
),
383 btrfs_ino(cb
->bbio
.inode
), cb
->start
);
389 zlib_inflateEnd(&workspace
->strm
);
391 kunmap_local(data_in
);
395 int zlib_decompress(struct list_head
*ws
, const u8
*data_in
,
396 struct folio
*dest_folio
, unsigned long dest_pgoff
, size_t srclen
,
399 struct workspace
*workspace
= list_entry(ws
, struct workspace
, list
);
401 int wbits
= MAX_WBITS
;
402 unsigned long to_copy
;
404 workspace
->strm
.next_in
= data_in
;
405 workspace
->strm
.avail_in
= srclen
;
406 workspace
->strm
.total_in
= 0;
408 workspace
->strm
.next_out
= workspace
->buf
;
409 workspace
->strm
.avail_out
= workspace
->buf_size
;
410 workspace
->strm
.total_out
= 0;
411 /* If it's deflate, and it's got no preset dictionary, then
412 we can tell zlib to skip the adler32 check. */
413 if (srclen
> 2 && !(data_in
[1] & PRESET_DICT
) &&
414 ((data_in
[0] & 0x0f) == Z_DEFLATED
) &&
415 !(((data_in
[0]<<8) + data_in
[1]) % 31)) {
417 wbits
= -((data_in
[0] >> 4) + 8);
418 workspace
->strm
.next_in
+= 2;
419 workspace
->strm
.avail_in
-= 2;
422 ret
= zlib_inflateInit2(&workspace
->strm
, wbits
);
423 if (unlikely(ret
!= Z_OK
)) {
424 struct btrfs_inode
*inode
= folio_to_inode(dest_folio
);
426 btrfs_err(inode
->root
->fs_info
,
427 "zlib decompression init failed, error %d root %llu inode %llu offset %llu",
428 ret
, btrfs_root_id(inode
->root
), btrfs_ino(inode
),
429 folio_pos(dest_folio
));
434 * Everything (in/out buf) should be at most one sector, there should
435 * be no need to switch any input/output buffer.
437 ret
= zlib_inflate(&workspace
->strm
, Z_FINISH
);
438 to_copy
= min(workspace
->strm
.total_out
, destlen
);
439 if (ret
!= Z_STREAM_END
)
442 memcpy_to_folio(dest_folio
, dest_pgoff
, workspace
->buf
, to_copy
);
445 if (unlikely(to_copy
!= destlen
)) {
446 struct btrfs_inode
*inode
= folio_to_inode(dest_folio
);
448 btrfs_err(inode
->root
->fs_info
,
449 "zlib decompression failed, error %d root %llu inode %llu offset %llu decompressed %lu expected %zu",
450 ret
, btrfs_root_id(inode
->root
), btrfs_ino(inode
),
451 folio_pos(dest_folio
), to_copy
, destlen
);
457 zlib_inflateEnd(&workspace
->strm
);
459 if (unlikely(to_copy
< destlen
))
460 folio_zero_range(dest_folio
, dest_pgoff
+ to_copy
, destlen
- to_copy
);
464 const struct btrfs_compress_op btrfs_zlib_compress
= {
465 .workspace_manager
= &wsm
,
467 .default_level
= BTRFS_ZLIB_DEFAULT_LEVEL
,