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 /* workspace buffer size for s390 zlib hardware support */ 24 #define ZLIB_DFLTCC_BUF_SIZE (4 * PAGE_SIZE) 25 26 struct workspace { 27 z_stream strm; 28 char *buf; 29 unsigned int buf_size; 30 struct list_head list; 31 int level; 32 }; 33 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) 47 { 48 struct workspace *workspace = list_entry(ws, struct workspace, list); 49 50 kvfree(workspace->strm.workspace); 51 kfree(workspace->buf); 52 kfree(workspace); 53 } 54 55 struct list_head *zlib_alloc_workspace(unsigned int level) 56 { 57 struct workspace *workspace; 58 int workspacesize; 59 60 workspace = kzalloc(sizeof(*workspace), GFP_KERNEL); 61 if (!workspace) 62 return ERR_PTR(-ENOMEM); 63 64 workspacesize = max(zlib_deflate_workspacesize(MAX_WBITS, MAX_MEM_LEVEL), 65 zlib_inflate_workspacesize()); 66 workspace->strm.workspace = kvzalloc(workspacesize, GFP_KERNEL | __GFP_NOWARN); 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 } 83 if (!workspace->strm.workspace || !workspace->buf) 84 goto fail; 85 86 INIT_LIST_HEAD(&workspace->list); 87 88 return &workspace->list; 89 fail: 90 zlib_free_workspace(&workspace->list); 91 return ERR_PTR(-ENOMEM); 92 } 93 94 int zlib_compress_folios(struct list_head *ws, struct address_space *mapping, 95 u64 start, struct folio **folios, unsigned long *out_folios, 96 unsigned long *total_in, unsigned long *total_out) 97 { 98 struct workspace *workspace = list_entry(ws, struct workspace, list); 99 int ret; 100 char *data_in = NULL; 101 char *cfolio_out; 102 int nr_folios = 0; 103 struct folio *in_folio = NULL; 104 struct folio *out_folio = NULL; 105 unsigned long bytes_left; 106 unsigned int in_buf_folios; 107 unsigned long len = *total_out; 108 unsigned long nr_dest_folios = *out_folios; 109 const unsigned long max_out = nr_dest_folios * PAGE_SIZE; 110 111 *out_folios = 0; 112 *total_out = 0; 113 *total_in = 0; 114 115 if (Z_OK != zlib_deflateInit(&workspace->strm, workspace->level)) { 116 pr_warn("BTRFS: deflateInit failed\n"); 117 ret = -EIO; 118 goto out; 119 } 120 121 workspace->strm.total_in = 0; 122 workspace->strm.total_out = 0; 123 124 out_folio = btrfs_alloc_compr_folio(); 125 if (out_folio == NULL) { 126 ret = -ENOMEM; 127 goto out; 128 } 129 cfolio_out = folio_address(out_folio); 130 folios[0] = out_folio; 131 nr_folios = 1; 132 133 workspace->strm.next_in = workspace->buf; 134 workspace->strm.avail_in = 0; 135 workspace->strm.next_out = cfolio_out; 136 workspace->strm.avail_out = PAGE_SIZE; 137 138 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_folios = min(DIV_ROUND_UP(bytes_left, PAGE_SIZE), 146 workspace->buf_size / PAGE_SIZE); 147 if (in_buf_folios > 1) { 148 int i; 149 150 for (i = 0; i < in_buf_folios; i++) { 151 if (data_in) { 152 kunmap_local(data_in); 153 folio_put(in_folio); 154 data_in = NULL; 155 } 156 ret = btrfs_compress_filemap_get_folio(mapping, 157 start, &in_folio); 158 if (ret < 0) 159 goto out; 160 data_in = kmap_local_folio(in_folio, 0); 161 copy_page(workspace->buf + i * PAGE_SIZE, 162 data_in); 163 start += PAGE_SIZE; 164 } 165 workspace->strm.next_in = workspace->buf; 166 } else { 167 if (data_in) { 168 kunmap_local(data_in); 169 folio_put(in_folio); 170 data_in = NULL; 171 } 172 ret = btrfs_compress_filemap_get_folio(mapping, 173 start, &in_folio); 174 if (ret < 0) 175 goto out; 176 data_in = kmap_local_folio(in_folio, 0); 177 start += PAGE_SIZE; 178 workspace->strm.next_in = data_in; 179 } 180 workspace->strm.avail_in = min(bytes_left, 181 (unsigned long) workspace->buf_size); 182 } 183 184 ret = zlib_deflate(&workspace->strm, Z_SYNC_FLUSH); 185 if (ret != Z_OK) { 186 pr_debug("BTRFS: deflate in loop returned %d\n", 187 ret); 188 zlib_deflateEnd(&workspace->strm); 189 ret = -EIO; 190 goto out; 191 } 192 193 /* we're making it bigger, give up */ 194 if (workspace->strm.total_in > 8192 && 195 workspace->strm.total_in < 196 workspace->strm.total_out) { 197 ret = -E2BIG; 198 goto out; 199 } 200 /* we need another page for writing out. Test this 201 * before the total_in so we will pull in a new page for 202 * the stream end if required 203 */ 204 if (workspace->strm.avail_out == 0) { 205 if (nr_folios == nr_dest_folios) { 206 ret = -E2BIG; 207 goto out; 208 } 209 out_folio = btrfs_alloc_compr_folio(); 210 if (out_folio == NULL) { 211 ret = -ENOMEM; 212 goto out; 213 } 214 cfolio_out = folio_address(out_folio); 215 folios[nr_folios] = out_folio; 216 nr_folios++; 217 workspace->strm.avail_out = PAGE_SIZE; 218 workspace->strm.next_out = cfolio_out; 219 } 220 /* we're all done */ 221 if (workspace->strm.total_in >= len) 222 break; 223 if (workspace->strm.total_out > max_out) 224 break; 225 } 226 workspace->strm.avail_in = 0; 227 /* 228 * Call deflate with Z_FINISH flush parameter providing more output 229 * space but no more input data, until it returns with Z_STREAM_END. 230 */ 231 while (ret != Z_STREAM_END) { 232 ret = zlib_deflate(&workspace->strm, Z_FINISH); 233 if (ret == Z_STREAM_END) 234 break; 235 if (ret != Z_OK && ret != Z_BUF_ERROR) { 236 zlib_deflateEnd(&workspace->strm); 237 ret = -EIO; 238 goto out; 239 } else if (workspace->strm.avail_out == 0) { 240 /* Get another folio for the stream end. */ 241 if (nr_folios == nr_dest_folios) { 242 ret = -E2BIG; 243 goto out; 244 } 245 out_folio = btrfs_alloc_compr_folio(); 246 if (out_folio == NULL) { 247 ret = -ENOMEM; 248 goto out; 249 } 250 cfolio_out = folio_address(out_folio); 251 folios[nr_folios] = out_folio; 252 nr_folios++; 253 workspace->strm.avail_out = PAGE_SIZE; 254 workspace->strm.next_out = cfolio_out; 255 } 256 } 257 zlib_deflateEnd(&workspace->strm); 258 259 if (workspace->strm.total_out >= workspace->strm.total_in) { 260 ret = -E2BIG; 261 goto out; 262 } 263 264 ret = 0; 265 *total_out = workspace->strm.total_out; 266 *total_in = workspace->strm.total_in; 267 out: 268 *out_folios = nr_folios; 269 if (data_in) { 270 kunmap_local(data_in); 271 folio_put(in_folio); 272 } 273 274 return ret; 275 } 276 277 int zlib_decompress_bio(struct list_head *ws, struct compressed_bio *cb) 278 { 279 struct workspace *workspace = list_entry(ws, struct workspace, list); 280 int ret = 0, ret2; 281 int wbits = MAX_WBITS; 282 char *data_in; 283 size_t total_out = 0; 284 unsigned long folio_in_index = 0; 285 size_t srclen = cb->compressed_len; 286 unsigned long total_folios_in = DIV_ROUND_UP(srclen, PAGE_SIZE); 287 unsigned long buf_start; 288 struct folio **folios_in = cb->compressed_folios; 289 290 data_in = kmap_local_folio(folios_in[folio_in_index], 0); 291 workspace->strm.next_in = data_in; 292 workspace->strm.avail_in = min_t(size_t, srclen, PAGE_SIZE); 293 workspace->strm.total_in = 0; 294 295 workspace->strm.total_out = 0; 296 workspace->strm.next_out = workspace->buf; 297 workspace->strm.avail_out = workspace->buf_size; 298 299 /* If it's deflate, and it's got no preset dictionary, then 300 we can tell zlib to skip the adler32 check. */ 301 if (srclen > 2 && !(data_in[1] & PRESET_DICT) && 302 ((data_in[0] & 0x0f) == Z_DEFLATED) && 303 !(((data_in[0]<<8) + data_in[1]) % 31)) { 304 305 wbits = -((data_in[0] >> 4) + 8); 306 workspace->strm.next_in += 2; 307 workspace->strm.avail_in -= 2; 308 } 309 310 if (Z_OK != zlib_inflateInit2(&workspace->strm, wbits)) { 311 pr_warn("BTRFS: inflateInit failed\n"); 312 kunmap_local(data_in); 313 return -EIO; 314 } 315 while (workspace->strm.total_in < srclen) { 316 ret = zlib_inflate(&workspace->strm, Z_NO_FLUSH); 317 if (ret != Z_OK && ret != Z_STREAM_END) 318 break; 319 320 buf_start = total_out; 321 total_out = workspace->strm.total_out; 322 323 /* we didn't make progress in this inflate call, we're done */ 324 if (buf_start == total_out) 325 break; 326 327 ret2 = btrfs_decompress_buf2page(workspace->buf, 328 total_out - buf_start, cb, buf_start); 329 if (ret2 == 0) { 330 ret = 0; 331 goto done; 332 } 333 334 workspace->strm.next_out = workspace->buf; 335 workspace->strm.avail_out = workspace->buf_size; 336 337 if (workspace->strm.avail_in == 0) { 338 unsigned long tmp; 339 kunmap_local(data_in); 340 folio_in_index++; 341 if (folio_in_index >= total_folios_in) { 342 data_in = NULL; 343 break; 344 } 345 data_in = kmap_local_folio(folios_in[folio_in_index], 0); 346 workspace->strm.next_in = data_in; 347 tmp = srclen - workspace->strm.total_in; 348 workspace->strm.avail_in = min(tmp, PAGE_SIZE); 349 } 350 } 351 if (ret != Z_STREAM_END) 352 ret = -EIO; 353 else 354 ret = 0; 355 done: 356 zlib_inflateEnd(&workspace->strm); 357 if (data_in) 358 kunmap_local(data_in); 359 return ret; 360 } 361 362 int zlib_decompress(struct list_head *ws, const u8 *data_in, 363 struct page *dest_page, unsigned long dest_pgoff, size_t srclen, 364 size_t destlen) 365 { 366 struct workspace *workspace = list_entry(ws, struct workspace, list); 367 int ret = 0; 368 int wbits = MAX_WBITS; 369 unsigned long to_copy; 370 371 workspace->strm.next_in = data_in; 372 workspace->strm.avail_in = srclen; 373 workspace->strm.total_in = 0; 374 375 workspace->strm.next_out = workspace->buf; 376 workspace->strm.avail_out = workspace->buf_size; 377 workspace->strm.total_out = 0; 378 /* If it's deflate, and it's got no preset dictionary, then 379 we can tell zlib to skip the adler32 check. */ 380 if (srclen > 2 && !(data_in[1] & PRESET_DICT) && 381 ((data_in[0] & 0x0f) == Z_DEFLATED) && 382 !(((data_in[0]<<8) + data_in[1]) % 31)) { 383 384 wbits = -((data_in[0] >> 4) + 8); 385 workspace->strm.next_in += 2; 386 workspace->strm.avail_in -= 2; 387 } 388 389 if (Z_OK != zlib_inflateInit2(&workspace->strm, wbits)) { 390 pr_warn("BTRFS: inflateInit failed\n"); 391 return -EIO; 392 } 393 394 /* 395 * Everything (in/out buf) should be at most one sector, there should 396 * be no need to switch any input/output buffer. 397 */ 398 ret = zlib_inflate(&workspace->strm, Z_FINISH); 399 to_copy = min(workspace->strm.total_out, destlen); 400 if (ret != Z_STREAM_END) 401 goto out; 402 403 memcpy_to_page(dest_page, dest_pgoff, workspace->buf, to_copy); 404 405 out: 406 if (unlikely(to_copy != destlen)) { 407 pr_warn_ratelimited("BTRFS: inflate failed, decompressed=%lu expected=%zu\n", 408 to_copy, destlen); 409 ret = -EIO; 410 } else { 411 ret = 0; 412 } 413 414 zlib_inflateEnd(&workspace->strm); 415 416 if (unlikely(to_copy < destlen)) 417 memzero_page(dest_page, dest_pgoff + to_copy, destlen - to_copy); 418 return ret; 419 } 420 421 const struct btrfs_compress_op btrfs_zlib_compress = { 422 .workspace_manager = &wsm, 423 .max_level = 9, 424 .default_level = BTRFS_ZLIB_DEFAULT_LEVEL, 425 }; 426