f2a56e999e5f9407212253cf60d752dea5f01ae1
[linux-2.6-block.git] / fs / btrfs / zlib.c
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 "compression.h"
22
23 struct workspace {
24         z_stream strm;
25         char *buf;
26         struct list_head list;
27         int level;
28 };
29
30 static struct workspace_manager wsm;
31
32 struct list_head *zlib_get_workspace(unsigned int level)
33 {
34         struct list_head *ws = btrfs_get_workspace(&wsm, level);
35         struct workspace *workspace = list_entry(ws, struct workspace, list);
36
37         workspace->level = level;
38
39         return ws;
40 }
41
42 void zlib_put_workspace(struct list_head *ws)
43 {
44         btrfs_put_workspace(&wsm, 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 = kvmalloc(workspacesize, GFP_KERNEL);
68         workspace->level = level;
69         workspace->buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
70         if (!workspace->strm.workspace || !workspace->buf)
71                 goto fail;
72
73         INIT_LIST_HEAD(&workspace->list);
74
75         return &workspace->list;
76 fail:
77         zlib_free_workspace(&workspace->list);
78         return ERR_PTR(-ENOMEM);
79 }
80
81 int zlib_compress_pages(struct list_head *ws, struct address_space *mapping,
82                 u64 start, struct page **pages, unsigned long *out_pages,
83                 unsigned long *total_in, unsigned long *total_out)
84 {
85         struct workspace *workspace = list_entry(ws, struct workspace, list);
86         int ret;
87         char *data_in;
88         char *cpage_out;
89         int nr_pages = 0;
90         struct page *in_page = NULL;
91         struct page *out_page = NULL;
92         unsigned long bytes_left;
93         unsigned long len = *total_out;
94         unsigned long nr_dest_pages = *out_pages;
95         const unsigned long max_out = nr_dest_pages * PAGE_SIZE;
96
97         *out_pages = 0;
98         *total_out = 0;
99         *total_in = 0;
100
101         if (Z_OK != zlib_deflateInit(&workspace->strm, workspace->level)) {
102                 pr_warn("BTRFS: deflateInit failed\n");
103                 ret = -EIO;
104                 goto out;
105         }
106
107         workspace->strm.total_in = 0;
108         workspace->strm.total_out = 0;
109
110         in_page = find_get_page(mapping, start >> PAGE_SHIFT);
111         data_in = kmap(in_page);
112
113         out_page = alloc_page(GFP_NOFS | __GFP_HIGHMEM);
114         if (out_page == NULL) {
115                 ret = -ENOMEM;
116                 goto out;
117         }
118         cpage_out = kmap(out_page);
119         pages[0] = out_page;
120         nr_pages = 1;
121
122         workspace->strm.next_in = data_in;
123         workspace->strm.next_out = cpage_out;
124         workspace->strm.avail_out = PAGE_SIZE;
125         workspace->strm.avail_in = min(len, PAGE_SIZE);
126
127         while (workspace->strm.total_in < len) {
128                 ret = zlib_deflate(&workspace->strm, Z_SYNC_FLUSH);
129                 if (ret != Z_OK) {
130                         pr_debug("BTRFS: deflate in loop returned %d\n",
131                                ret);
132                         zlib_deflateEnd(&workspace->strm);
133                         ret = -EIO;
134                         goto out;
135                 }
136
137                 /* we're making it bigger, give up */
138                 if (workspace->strm.total_in > 8192 &&
139                     workspace->strm.total_in <
140                     workspace->strm.total_out) {
141                         ret = -E2BIG;
142                         goto out;
143                 }
144                 /* we need another page for writing out.  Test this
145                  * before the total_in so we will pull in a new page for
146                  * the stream end if required
147                  */
148                 if (workspace->strm.avail_out == 0) {
149                         kunmap(out_page);
150                         if (nr_pages == nr_dest_pages) {
151                                 out_page = NULL;
152                                 ret = -E2BIG;
153                                 goto out;
154                         }
155                         out_page = alloc_page(GFP_NOFS | __GFP_HIGHMEM);
156                         if (out_page == NULL) {
157                                 ret = -ENOMEM;
158                                 goto out;
159                         }
160                         cpage_out = kmap(out_page);
161                         pages[nr_pages] = out_page;
162                         nr_pages++;
163                         workspace->strm.avail_out = PAGE_SIZE;
164                         workspace->strm.next_out = cpage_out;
165                 }
166                 /* we're all done */
167                 if (workspace->strm.total_in >= len)
168                         break;
169
170                 /* we've read in a full page, get a new one */
171                 if (workspace->strm.avail_in == 0) {
172                         if (workspace->strm.total_out > max_out)
173                                 break;
174
175                         bytes_left = len - workspace->strm.total_in;
176                         kunmap(in_page);
177                         put_page(in_page);
178
179                         start += PAGE_SIZE;
180                         in_page = find_get_page(mapping,
181                                                 start >> PAGE_SHIFT);
182                         data_in = kmap(in_page);
183                         workspace->strm.avail_in = min(bytes_left,
184                                                            PAGE_SIZE);
185                         workspace->strm.next_in = data_in;
186                 }
187         }
188         workspace->strm.avail_in = 0;
189         ret = zlib_deflate(&workspace->strm, Z_FINISH);
190         zlib_deflateEnd(&workspace->strm);
191
192         if (ret != Z_STREAM_END) {
193                 ret = -EIO;
194                 goto out;
195         }
196
197         if (workspace->strm.total_out >= workspace->strm.total_in) {
198                 ret = -E2BIG;
199                 goto out;
200         }
201
202         ret = 0;
203         *total_out = workspace->strm.total_out;
204         *total_in = workspace->strm.total_in;
205 out:
206         *out_pages = nr_pages;
207         if (out_page)
208                 kunmap(out_page);
209
210         if (in_page) {
211                 kunmap(in_page);
212                 put_page(in_page);
213         }
214         return ret;
215 }
216
217 int zlib_decompress_bio(struct list_head *ws, struct compressed_bio *cb)
218 {
219         struct workspace *workspace = list_entry(ws, struct workspace, list);
220         int ret = 0, ret2;
221         int wbits = MAX_WBITS;
222         char *data_in;
223         size_t total_out = 0;
224         unsigned long page_in_index = 0;
225         size_t srclen = cb->compressed_len;
226         unsigned long total_pages_in = DIV_ROUND_UP(srclen, PAGE_SIZE);
227         unsigned long buf_start;
228         struct page **pages_in = cb->compressed_pages;
229         u64 disk_start = cb->start;
230         struct bio *orig_bio = cb->orig_bio;
231
232         data_in = kmap(pages_in[page_in_index]);
233         workspace->strm.next_in = data_in;
234         workspace->strm.avail_in = min_t(size_t, srclen, PAGE_SIZE);
235         workspace->strm.total_in = 0;
236
237         workspace->strm.total_out = 0;
238         workspace->strm.next_out = workspace->buf;
239         workspace->strm.avail_out = PAGE_SIZE;
240
241         /* If it's deflate, and it's got no preset dictionary, then
242            we can tell zlib to skip the adler32 check. */
243         if (srclen > 2 && !(data_in[1] & PRESET_DICT) &&
244             ((data_in[0] & 0x0f) == Z_DEFLATED) &&
245             !(((data_in[0]<<8) + data_in[1]) % 31)) {
246
247                 wbits = -((data_in[0] >> 4) + 8);
248                 workspace->strm.next_in += 2;
249                 workspace->strm.avail_in -= 2;
250         }
251
252         if (Z_OK != zlib_inflateInit2(&workspace->strm, wbits)) {
253                 pr_warn("BTRFS: inflateInit failed\n");
254                 kunmap(pages_in[page_in_index]);
255                 return -EIO;
256         }
257         while (workspace->strm.total_in < srclen) {
258                 ret = zlib_inflate(&workspace->strm, Z_NO_FLUSH);
259                 if (ret != Z_OK && ret != Z_STREAM_END)
260                         break;
261
262                 buf_start = total_out;
263                 total_out = workspace->strm.total_out;
264
265                 /* we didn't make progress in this inflate call, we're done */
266                 if (buf_start == total_out)
267                         break;
268
269                 ret2 = btrfs_decompress_buf2page(workspace->buf, buf_start,
270                                                  total_out, disk_start,
271                                                  orig_bio);
272                 if (ret2 == 0) {
273                         ret = 0;
274                         goto done;
275                 }
276
277                 workspace->strm.next_out = workspace->buf;
278                 workspace->strm.avail_out = PAGE_SIZE;
279
280                 if (workspace->strm.avail_in == 0) {
281                         unsigned long tmp;
282                         kunmap(pages_in[page_in_index]);
283                         page_in_index++;
284                         if (page_in_index >= total_pages_in) {
285                                 data_in = NULL;
286                                 break;
287                         }
288                         data_in = kmap(pages_in[page_in_index]);
289                         workspace->strm.next_in = data_in;
290                         tmp = srclen - workspace->strm.total_in;
291                         workspace->strm.avail_in = min(tmp,
292                                                            PAGE_SIZE);
293                 }
294         }
295         if (ret != Z_STREAM_END)
296                 ret = -EIO;
297         else
298                 ret = 0;
299 done:
300         zlib_inflateEnd(&workspace->strm);
301         if (data_in)
302                 kunmap(pages_in[page_in_index]);
303         if (!ret)
304                 zero_fill_bio(orig_bio);
305         return ret;
306 }
307
308 int zlib_decompress(struct list_head *ws, unsigned char *data_in,
309                 struct page *dest_page, unsigned long start_byte, size_t srclen,
310                 size_t destlen)
311 {
312         struct workspace *workspace = list_entry(ws, struct workspace, list);
313         int ret = 0;
314         int wbits = MAX_WBITS;
315         unsigned long bytes_left;
316         unsigned long total_out = 0;
317         unsigned long pg_offset = 0;
318         char *kaddr;
319
320         destlen = min_t(unsigned long, destlen, PAGE_SIZE);
321         bytes_left = destlen;
322
323         workspace->strm.next_in = data_in;
324         workspace->strm.avail_in = srclen;
325         workspace->strm.total_in = 0;
326
327         workspace->strm.next_out = workspace->buf;
328         workspace->strm.avail_out = PAGE_SIZE;
329         workspace->strm.total_out = 0;
330         /* If it's deflate, and it's got no preset dictionary, then
331            we can tell zlib to skip the adler32 check. */
332         if (srclen > 2 && !(data_in[1] & PRESET_DICT) &&
333             ((data_in[0] & 0x0f) == Z_DEFLATED) &&
334             !(((data_in[0]<<8) + data_in[1]) % 31)) {
335
336                 wbits = -((data_in[0] >> 4) + 8);
337                 workspace->strm.next_in += 2;
338                 workspace->strm.avail_in -= 2;
339         }
340
341         if (Z_OK != zlib_inflateInit2(&workspace->strm, wbits)) {
342                 pr_warn("BTRFS: inflateInit failed\n");
343                 return -EIO;
344         }
345
346         while (bytes_left > 0) {
347                 unsigned long buf_start;
348                 unsigned long buf_offset;
349                 unsigned long bytes;
350
351                 ret = zlib_inflate(&workspace->strm, Z_NO_FLUSH);
352                 if (ret != Z_OK && ret != Z_STREAM_END)
353                         break;
354
355                 buf_start = total_out;
356                 total_out = workspace->strm.total_out;
357
358                 if (total_out == buf_start) {
359                         ret = -EIO;
360                         break;
361                 }
362
363                 if (total_out <= start_byte)
364                         goto next;
365
366                 if (total_out > start_byte && buf_start < start_byte)
367                         buf_offset = start_byte - buf_start;
368                 else
369                         buf_offset = 0;
370
371                 bytes = min(PAGE_SIZE - pg_offset,
372                             PAGE_SIZE - buf_offset);
373                 bytes = min(bytes, bytes_left);
374
375                 kaddr = kmap_atomic(dest_page);
376                 memcpy(kaddr + pg_offset, workspace->buf + buf_offset, bytes);
377                 kunmap_atomic(kaddr);
378
379                 pg_offset += bytes;
380                 bytes_left -= bytes;
381 next:
382                 workspace->strm.next_out = workspace->buf;
383                 workspace->strm.avail_out = PAGE_SIZE;
384         }
385
386         if (ret != Z_STREAM_END && bytes_left != 0)
387                 ret = -EIO;
388         else
389                 ret = 0;
390
391         zlib_inflateEnd(&workspace->strm);
392
393         /*
394          * this should only happen if zlib returned fewer bytes than we
395          * expected.  btrfs_get_block is responsible for zeroing from the
396          * end of the inline extent (destlen) to the end of the page
397          */
398         if (pg_offset < destlen) {
399                 kaddr = kmap_atomic(dest_page);
400                 memset(kaddr + pg_offset, 0, destlen - pg_offset);
401                 kunmap_atomic(kaddr);
402         }
403         return ret;
404 }
405
406 const struct btrfs_compress_op btrfs_zlib_compress = {
407         .workspace_manager      = &wsm,
408         .get_workspace          = zlib_get_workspace,
409         .put_workspace          = zlib_put_workspace,
410         .alloc_workspace        = zlib_alloc_workspace,
411         .free_workspace         = zlib_free_workspace,
412         .max_level              = 9,
413         .default_level          = BTRFS_ZLIB_DEFAULT_LEVEL,
414 };