23 #include <linux/kernel.h>
24 #include <linux/slab.h>
30 #include <linux/sched.h>
42 static void zlib_free_workspace(
struct list_head *
ws)
52 static struct list_head *zlib_alloc_workspace(
void)
56 workspace = kzalloc(
sizeof(*workspace),
GFP_NOFS);
68 INIT_LIST_HEAD(&workspace->
list);
70 return &workspace->
list;
72 zlib_free_workspace(&workspace->
list);
76 static int zlib_compress_pages(
struct list_head *
ws,
80 unsigned long nr_dest_pages,
81 unsigned long *out_pages,
82 unsigned long *total_in,
83 unsigned long *total_out,
84 unsigned long max_out)
86 struct workspace *workspace =
list_entry(ws,
struct workspace,
list);
93 unsigned long bytes_left;
109 data_in =
kmap(in_page);
112 if (out_page ==
NULL) {
116 cpage_out =
kmap(out_page);
148 if (nr_pages == nr_dest_pages) {
154 if (out_page ==
NULL) {
158 cpage_out =
kmap(out_page);
159 pages[nr_pages] = out_page;
180 data_in =
kmap(in_page);
204 *out_pages = nr_pages;
215 static int zlib_decompress_biovec(
struct list_head *ws,
struct page **pages_in,
217 struct bio_vec *bvec,
221 struct workspace *workspace =
list_entry(ws,
struct workspace,
list);
225 size_t total_out = 0;
226 unsigned long page_in_index = 0;
227 unsigned long page_out_index = 0;
230 unsigned long buf_start;
231 unsigned long pg_offset;
233 data_in =
kmap(pages_in[page_in_index]);
247 !(((data_in[0]<<8) + data_in[1]) % 31)) {
249 wbits = -((data_in[0] >> 4) + 8);
263 buf_start = total_out;
267 if (buf_start == total_out)
271 total_out, disk_start,
273 &page_out_index, &pg_offset);
284 kunmap(pages_in[page_in_index]);
286 if (page_in_index >= total_pages_in) {
290 data_in =
kmap(pages_in[page_in_index]);
304 kunmap(pages_in[page_in_index]);
308 static int zlib_decompress(
struct list_head *ws,
unsigned char *data_in,
309 struct page *dest_page,
310 unsigned long start_byte,
311 size_t srclen,
size_t destlen)
313 struct workspace *workspace =
list_entry(ws,
struct workspace,
list);
316 unsigned long bytes_left = destlen;
317 unsigned long total_out = 0;
329 if (srclen > 2 && !(data_in[1] & PRESET_DICT) &&
331 !(((data_in[0]<<8) + data_in[1]) % 31)) {
333 wbits = -((data_in[0] >> 4) + 8);
343 while (bytes_left > 0) {
344 unsigned long buf_start;
345 unsigned long buf_offset;
347 unsigned long pg_offset = 0;
353 buf_start = total_out;
356 if (total_out == buf_start) {
361 if (total_out <= start_byte)
364 if (total_out > start_byte && buf_start < start_byte)
365 buf_offset = start_byte - buf_start;
371 bytes =
min(bytes, bytes_left);
374 memcpy(kaddr + pg_offset, workspace->
buf + buf_offset, bytes);
394 .alloc_workspace = zlib_alloc_workspace,
395 .free_workspace = zlib_free_workspace,
396 .compress_pages = zlib_compress_pages,
397 .decompress_biovec = zlib_decompress_biovec,
398 .decompress = zlib_decompress,