hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/fs/btrfs/zlib.c
....@@ -20,14 +20,30 @@
2020 #include <linux/refcount.h>
2121 #include "compression.h"
2222
23
+/* workspace buffer size for s390 zlib hardware support */
24
+#define ZLIB_DFLTCC_BUF_SIZE (4 * PAGE_SIZE)
25
+
2326 struct workspace {
2427 z_stream strm;
2528 char *buf;
29
+ unsigned int buf_size;
2630 struct list_head list;
2731 int level;
2832 };
2933
30
-static void zlib_free_workspace(struct list_head *ws)
34
+static struct workspace_manager wsm;
35
+
36
+struct list_head *zlib_get_workspace(unsigned int level)
37
+{
38
+ struct list_head *ws = btrfs_get_workspace(BTRFS_COMPRESS_ZLIB, level);
39
+ struct workspace *workspace = list_entry(ws, struct workspace, list);
40
+
41
+ workspace->level = level;
42
+
43
+ return ws;
44
+}
45
+
46
+void zlib_free_workspace(struct list_head *ws)
3147 {
3248 struct workspace *workspace = list_entry(ws, struct workspace, list);
3349
....@@ -36,7 +52,7 @@
3652 kfree(workspace);
3753 }
3854
39
-static struct list_head *zlib_alloc_workspace(void)
55
+struct list_head *zlib_alloc_workspace(unsigned int level)
4056 {
4157 struct workspace *workspace;
4258 int workspacesize;
....@@ -47,8 +63,23 @@
4763
4864 workspacesize = max(zlib_deflate_workspacesize(MAX_WBITS, MAX_MEM_LEVEL),
4965 zlib_inflate_workspacesize());
50
- workspace->strm.workspace = kvmalloc(workspacesize, GFP_KERNEL);
51
- workspace->buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
66
+ workspace->strm.workspace = kvzalloc(workspacesize, GFP_KERNEL);
67
+ workspace->level = level;
68
+ workspace->buf = NULL;
69
+ /*
70
+ * In case of s390 zlib hardware support, allocate lager workspace
71
+ * buffer. If allocator fails, fall back to a single page buffer.
72
+ */
73
+ if (zlib_deflate_dfltcc_enabled()) {
74
+ workspace->buf = kmalloc(ZLIB_DFLTCC_BUF_SIZE,
75
+ __GFP_NOMEMALLOC | __GFP_NORETRY |
76
+ __GFP_NOWARN | GFP_NOIO);
77
+ workspace->buf_size = ZLIB_DFLTCC_BUF_SIZE;
78
+ }
79
+ if (!workspace->buf) {
80
+ workspace->buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
81
+ workspace->buf_size = PAGE_SIZE;
82
+ }
5283 if (!workspace->strm.workspace || !workspace->buf)
5384 goto fail;
5485
....@@ -60,13 +91,9 @@
6091 return ERR_PTR(-ENOMEM);
6192 }
6293
63
-static int zlib_compress_pages(struct list_head *ws,
64
- struct address_space *mapping,
65
- u64 start,
66
- struct page **pages,
67
- unsigned long *out_pages,
68
- unsigned long *total_in,
69
- unsigned long *total_out)
94
+int zlib_compress_pages(struct list_head *ws, struct address_space *mapping,
95
+ u64 start, struct page **pages, unsigned long *out_pages,
96
+ unsigned long *total_in, unsigned long *total_out)
7097 {
7198 struct workspace *workspace = list_entry(ws, struct workspace, list);
7299 int ret;
....@@ -76,6 +103,7 @@
76103 struct page *in_page = NULL;
77104 struct page *out_page = NULL;
78105 unsigned long bytes_left;
106
+ unsigned int in_buf_pages;
79107 unsigned long len = *total_out;
80108 unsigned long nr_dest_pages = *out_pages;
81109 const unsigned long max_out = nr_dest_pages * PAGE_SIZE;
....@@ -93,9 +121,6 @@
93121 workspace->strm.total_in = 0;
94122 workspace->strm.total_out = 0;
95123
96
- in_page = find_get_page(mapping, start >> PAGE_SHIFT);
97
- data_in = kmap(in_page);
98
-
99124 out_page = alloc_page(GFP_NOFS | __GFP_HIGHMEM);
100125 if (out_page == NULL) {
101126 ret = -ENOMEM;
....@@ -105,12 +130,51 @@
105130 pages[0] = out_page;
106131 nr_pages = 1;
107132
108
- workspace->strm.next_in = data_in;
133
+ workspace->strm.next_in = workspace->buf;
134
+ workspace->strm.avail_in = 0;
109135 workspace->strm.next_out = cpage_out;
110136 workspace->strm.avail_out = PAGE_SIZE;
111
- workspace->strm.avail_in = min(len, PAGE_SIZE);
112137
113138 while (workspace->strm.total_in < len) {
139
+ /*
140
+ * Get next input pages and copy the contents to
141
+ * the workspace buffer if required.
142
+ */
143
+ if (workspace->strm.avail_in == 0) {
144
+ bytes_left = len - workspace->strm.total_in;
145
+ in_buf_pages = min(DIV_ROUND_UP(bytes_left, PAGE_SIZE),
146
+ workspace->buf_size / PAGE_SIZE);
147
+ if (in_buf_pages > 1) {
148
+ int i;
149
+
150
+ for (i = 0; i < in_buf_pages; i++) {
151
+ if (in_page) {
152
+ kunmap(in_page);
153
+ put_page(in_page);
154
+ }
155
+ in_page = find_get_page(mapping,
156
+ start >> PAGE_SHIFT);
157
+ data_in = kmap(in_page);
158
+ memcpy(workspace->buf + i * PAGE_SIZE,
159
+ data_in, PAGE_SIZE);
160
+ start += PAGE_SIZE;
161
+ }
162
+ workspace->strm.next_in = workspace->buf;
163
+ } else {
164
+ if (in_page) {
165
+ kunmap(in_page);
166
+ put_page(in_page);
167
+ }
168
+ in_page = find_get_page(mapping,
169
+ start >> PAGE_SHIFT);
170
+ data_in = kmap(in_page);
171
+ start += PAGE_SIZE;
172
+ workspace->strm.next_in = data_in;
173
+ }
174
+ workspace->strm.avail_in = min(bytes_left,
175
+ (unsigned long) workspace->buf_size);
176
+ }
177
+
114178 ret = zlib_deflate(&workspace->strm, Z_SYNC_FLUSH);
115179 if (ret != Z_OK) {
116180 pr_debug("BTRFS: deflate in loop returned %d\n",
....@@ -152,33 +216,43 @@
152216 /* we're all done */
153217 if (workspace->strm.total_in >= len)
154218 break;
155
-
156
- /* we've read in a full page, get a new one */
157
- if (workspace->strm.avail_in == 0) {
158
- if (workspace->strm.total_out > max_out)
159
- break;
160
-
161
- bytes_left = len - workspace->strm.total_in;
162
- kunmap(in_page);
163
- put_page(in_page);
164
-
165
- start += PAGE_SIZE;
166
- in_page = find_get_page(mapping,
167
- start >> PAGE_SHIFT);
168
- data_in = kmap(in_page);
169
- workspace->strm.avail_in = min(bytes_left,
170
- PAGE_SIZE);
171
- workspace->strm.next_in = data_in;
172
- }
219
+ if (workspace->strm.total_out > max_out)
220
+ break;
173221 }
174222 workspace->strm.avail_in = 0;
175
- ret = zlib_deflate(&workspace->strm, Z_FINISH);
176
- zlib_deflateEnd(&workspace->strm);
177
-
178
- if (ret != Z_STREAM_END) {
179
- ret = -EIO;
180
- goto out;
223
+ /*
224
+ * Call deflate with Z_FINISH flush parameter providing more output
225
+ * space but no more input data, until it returns with Z_STREAM_END.
226
+ */
227
+ while (ret != Z_STREAM_END) {
228
+ ret = zlib_deflate(&workspace->strm, Z_FINISH);
229
+ if (ret == Z_STREAM_END)
230
+ break;
231
+ if (ret != Z_OK && ret != Z_BUF_ERROR) {
232
+ zlib_deflateEnd(&workspace->strm);
233
+ ret = -EIO;
234
+ goto out;
235
+ } else if (workspace->strm.avail_out == 0) {
236
+ /* get another page for the stream end */
237
+ kunmap(out_page);
238
+ if (nr_pages == nr_dest_pages) {
239
+ out_page = NULL;
240
+ ret = -E2BIG;
241
+ goto out;
242
+ }
243
+ out_page = alloc_page(GFP_NOFS | __GFP_HIGHMEM);
244
+ if (out_page == NULL) {
245
+ ret = -ENOMEM;
246
+ goto out;
247
+ }
248
+ cpage_out = kmap(out_page);
249
+ pages[nr_pages] = out_page;
250
+ nr_pages++;
251
+ workspace->strm.avail_out = PAGE_SIZE;
252
+ workspace->strm.next_out = cpage_out;
253
+ }
181254 }
255
+ zlib_deflateEnd(&workspace->strm);
182256
183257 if (workspace->strm.total_out >= workspace->strm.total_in) {
184258 ret = -E2BIG;
....@@ -200,7 +274,7 @@
200274 return ret;
201275 }
202276
203
-static int zlib_decompress_bio(struct list_head *ws, struct compressed_bio *cb)
277
+int zlib_decompress_bio(struct list_head *ws, struct compressed_bio *cb)
204278 {
205279 struct workspace *workspace = list_entry(ws, struct workspace, list);
206280 int ret = 0, ret2;
....@@ -222,7 +296,7 @@
222296
223297 workspace->strm.total_out = 0;
224298 workspace->strm.next_out = workspace->buf;
225
- workspace->strm.avail_out = PAGE_SIZE;
299
+ workspace->strm.avail_out = workspace->buf_size;
226300
227301 /* If it's deflate, and it's got no preset dictionary, then
228302 we can tell zlib to skip the adler32 check. */
....@@ -261,7 +335,7 @@
261335 }
262336
263337 workspace->strm.next_out = workspace->buf;
264
- workspace->strm.avail_out = PAGE_SIZE;
338
+ workspace->strm.avail_out = workspace->buf_size;
265339
266340 if (workspace->strm.avail_in == 0) {
267341 unsigned long tmp;
....@@ -291,10 +365,9 @@
291365 return ret;
292366 }
293367
294
-static int zlib_decompress(struct list_head *ws, unsigned char *data_in,
295
- struct page *dest_page,
296
- unsigned long start_byte,
297
- size_t srclen, size_t destlen)
368
+int zlib_decompress(struct list_head *ws, unsigned char *data_in,
369
+ struct page *dest_page, unsigned long start_byte, size_t srclen,
370
+ size_t destlen)
298371 {
299372 struct workspace *workspace = list_entry(ws, struct workspace, list);
300373 int ret = 0;
....@@ -312,7 +385,7 @@
312385 workspace->strm.total_in = 0;
313386
314387 workspace->strm.next_out = workspace->buf;
315
- workspace->strm.avail_out = PAGE_SIZE;
388
+ workspace->strm.avail_out = workspace->buf_size;
316389 workspace->strm.total_out = 0;
317390 /* If it's deflate, and it's got no preset dictionary, then
318391 we can tell zlib to skip the adler32 check. */
....@@ -356,7 +429,7 @@
356429 buf_offset = 0;
357430
358431 bytes = min(PAGE_SIZE - pg_offset,
359
- PAGE_SIZE - buf_offset);
432
+ PAGE_SIZE - (buf_offset % PAGE_SIZE));
360433 bytes = min(bytes, bytes_left);
361434
362435 kaddr = kmap_atomic(dest_page);
....@@ -367,7 +440,7 @@
367440 bytes_left -= bytes;
368441 next:
369442 workspace->strm.next_out = workspace->buf;
370
- workspace->strm.avail_out = PAGE_SIZE;
443
+ workspace->strm.avail_out = workspace->buf_size;
371444 }
372445
373446 if (ret != Z_STREAM_END && bytes_left != 0)
....@@ -390,22 +463,8 @@
390463 return ret;
391464 }
392465
393
-static void zlib_set_level(struct list_head *ws, unsigned int type)
394
-{
395
- struct workspace *workspace = list_entry(ws, struct workspace, list);
396
- unsigned level = (type & 0xF0) >> 4;
397
-
398
- if (level > 9)
399
- level = 9;
400
-
401
- workspace->level = level > 0 ? level : 3;
402
-}
403
-
404466 const struct btrfs_compress_op btrfs_zlib_compress = {
405
- .alloc_workspace = zlib_alloc_workspace,
406
- .free_workspace = zlib_free_workspace,
407
- .compress_pages = zlib_compress_pages,
408
- .decompress_bio = zlib_decompress_bio,
409
- .decompress = zlib_decompress,
410
- .set_level = zlib_set_level,
467
+ .workspace_manager = &wsm,
468
+ .max_level = 9,
469
+ .default_level = BTRFS_ZLIB_DEFAULT_LEVEL,
411470 };