^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (C) 2008 Oracle. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Based on jffs2 zlib code:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright © 2001-2007 Red Hat, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Created by David Woodhouse <dwmw2@infradead.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/zlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/zutil.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/pagemap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/bio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/refcount.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include "compression.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) /* workspace buffer size for s390 zlib hardware support */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define ZLIB_DFLTCC_BUF_SIZE (4 * PAGE_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) struct workspace {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) z_stream strm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) char *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) unsigned int buf_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) struct list_head list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) int level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) static struct workspace_manager wsm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) struct list_head *zlib_get_workspace(unsigned int level)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) struct list_head *ws = btrfs_get_workspace(BTRFS_COMPRESS_ZLIB, level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) struct workspace *workspace = list_entry(ws, struct workspace, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) workspace->level = level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) return ws;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) void zlib_free_workspace(struct list_head *ws)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) struct workspace *workspace = list_entry(ws, struct workspace, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) kvfree(workspace->strm.workspace);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) kfree(workspace->buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) kfree(workspace);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) struct list_head *zlib_alloc_workspace(unsigned int level)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) struct workspace *workspace;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) int workspacesize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) workspace = kzalloc(sizeof(*workspace), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) if (!workspace)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) workspacesize = max(zlib_deflate_workspacesize(MAX_WBITS, MAX_MEM_LEVEL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) zlib_inflate_workspacesize());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) workspace->strm.workspace = kvmalloc(workspacesize, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) workspace->level = level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) workspace->buf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) * In case of s390 zlib hardware support, allocate lager workspace
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) * buffer. If allocator fails, fall back to a single page buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) if (zlib_deflate_dfltcc_enabled()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) workspace->buf = kmalloc(ZLIB_DFLTCC_BUF_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) __GFP_NOMEMALLOC | __GFP_NORETRY |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) __GFP_NOWARN | GFP_NOIO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) workspace->buf_size = ZLIB_DFLTCC_BUF_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) if (!workspace->buf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) workspace->buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) workspace->buf_size = PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) if (!workspace->strm.workspace || !workspace->buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) INIT_LIST_HEAD(&workspace->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) return &workspace->list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) zlib_free_workspace(&workspace->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) int zlib_compress_pages(struct list_head *ws, struct address_space *mapping,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) u64 start, struct page **pages, unsigned long *out_pages,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) unsigned long *total_in, unsigned long *total_out)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) struct workspace *workspace = list_entry(ws, struct workspace, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) char *data_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) char *cpage_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) int nr_pages = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) struct page *in_page = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) struct page *out_page = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) unsigned long bytes_left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) unsigned int in_buf_pages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) unsigned long len = *total_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) unsigned long nr_dest_pages = *out_pages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) const unsigned long max_out = nr_dest_pages * PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) *out_pages = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) *total_out = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) *total_in = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) if (Z_OK != zlib_deflateInit(&workspace->strm, workspace->level)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) pr_warn("BTRFS: deflateInit failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) workspace->strm.total_in = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) workspace->strm.total_out = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) out_page = alloc_page(GFP_NOFS | __GFP_HIGHMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) if (out_page == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) cpage_out = kmap(out_page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) pages[0] = out_page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) nr_pages = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) workspace->strm.next_in = workspace->buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) workspace->strm.avail_in = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) workspace->strm.next_out = cpage_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) workspace->strm.avail_out = PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) while (workspace->strm.total_in < len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) * Get next input pages and copy the contents to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) * the workspace buffer if required.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) if (workspace->strm.avail_in == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) bytes_left = len - workspace->strm.total_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) in_buf_pages = min(DIV_ROUND_UP(bytes_left, PAGE_SIZE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) workspace->buf_size / PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) if (in_buf_pages > 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) for (i = 0; i < in_buf_pages; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) if (in_page) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) kunmap(in_page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) put_page(in_page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) in_page = find_get_page(mapping,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) start >> PAGE_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) data_in = kmap(in_page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) memcpy(workspace->buf + i * PAGE_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) data_in, PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) start += PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) workspace->strm.next_in = workspace->buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) if (in_page) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) kunmap(in_page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) put_page(in_page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) in_page = find_get_page(mapping,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) start >> PAGE_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) data_in = kmap(in_page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) start += PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) workspace->strm.next_in = data_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) workspace->strm.avail_in = min(bytes_left,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) (unsigned long) workspace->buf_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) ret = zlib_deflate(&workspace->strm, Z_SYNC_FLUSH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) if (ret != Z_OK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) pr_debug("BTRFS: deflate in loop returned %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) zlib_deflateEnd(&workspace->strm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) /* we're making it bigger, give up */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) if (workspace->strm.total_in > 8192 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) workspace->strm.total_in <
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) workspace->strm.total_out) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) ret = -E2BIG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) /* we need another page for writing out. Test this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) * before the total_in so we will pull in a new page for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) * the stream end if required
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) if (workspace->strm.avail_out == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) kunmap(out_page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) if (nr_pages == nr_dest_pages) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) out_page = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) ret = -E2BIG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) out_page = alloc_page(GFP_NOFS | __GFP_HIGHMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) if (out_page == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) cpage_out = kmap(out_page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) pages[nr_pages] = out_page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) nr_pages++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) workspace->strm.avail_out = PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) workspace->strm.next_out = cpage_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) /* we're all done */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) if (workspace->strm.total_in >= len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) if (workspace->strm.total_out > max_out)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) workspace->strm.avail_in = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) * Call deflate with Z_FINISH flush parameter providing more output
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) * space but no more input data, until it returns with Z_STREAM_END.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) while (ret != Z_STREAM_END) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) ret = zlib_deflate(&workspace->strm, Z_FINISH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) if (ret == Z_STREAM_END)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) if (ret != Z_OK && ret != Z_BUF_ERROR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) zlib_deflateEnd(&workspace->strm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) } else if (workspace->strm.avail_out == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) /* get another page for the stream end */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) kunmap(out_page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) if (nr_pages == nr_dest_pages) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) out_page = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) ret = -E2BIG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) out_page = alloc_page(GFP_NOFS | __GFP_HIGHMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) if (out_page == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) cpage_out = kmap(out_page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) pages[nr_pages] = out_page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) nr_pages++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) workspace->strm.avail_out = PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) workspace->strm.next_out = cpage_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) zlib_deflateEnd(&workspace->strm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) if (workspace->strm.total_out >= workspace->strm.total_in) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) ret = -E2BIG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) *total_out = workspace->strm.total_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) *total_in = workspace->strm.total_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) *out_pages = nr_pages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) if (out_page)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) kunmap(out_page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) if (in_page) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) kunmap(in_page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) put_page(in_page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) int zlib_decompress_bio(struct list_head *ws, struct compressed_bio *cb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) struct workspace *workspace = list_entry(ws, struct workspace, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) int ret = 0, ret2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) int wbits = MAX_WBITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) char *data_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) size_t total_out = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) unsigned long page_in_index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) size_t srclen = cb->compressed_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) unsigned long total_pages_in = DIV_ROUND_UP(srclen, PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) unsigned long buf_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) struct page **pages_in = cb->compressed_pages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) u64 disk_start = cb->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) struct bio *orig_bio = cb->orig_bio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) data_in = kmap(pages_in[page_in_index]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) workspace->strm.next_in = data_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) workspace->strm.avail_in = min_t(size_t, srclen, PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) workspace->strm.total_in = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) workspace->strm.total_out = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) workspace->strm.next_out = workspace->buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) workspace->strm.avail_out = workspace->buf_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) /* If it's deflate, and it's got no preset dictionary, then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) we can tell zlib to skip the adler32 check. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) if (srclen > 2 && !(data_in[1] & PRESET_DICT) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) ((data_in[0] & 0x0f) == Z_DEFLATED) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) !(((data_in[0]<<8) + data_in[1]) % 31)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) wbits = -((data_in[0] >> 4) + 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) workspace->strm.next_in += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) workspace->strm.avail_in -= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) if (Z_OK != zlib_inflateInit2(&workspace->strm, wbits)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) pr_warn("BTRFS: inflateInit failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) kunmap(pages_in[page_in_index]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) while (workspace->strm.total_in < srclen) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) ret = zlib_inflate(&workspace->strm, Z_NO_FLUSH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) if (ret != Z_OK && ret != Z_STREAM_END)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) buf_start = total_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) total_out = workspace->strm.total_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) /* we didn't make progress in this inflate call, we're done */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) if (buf_start == total_out)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) ret2 = btrfs_decompress_buf2page(workspace->buf, buf_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) total_out, disk_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) orig_bio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) if (ret2 == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) workspace->strm.next_out = workspace->buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) workspace->strm.avail_out = workspace->buf_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) if (workspace->strm.avail_in == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) unsigned long tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) kunmap(pages_in[page_in_index]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) page_in_index++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) if (page_in_index >= total_pages_in) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) data_in = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) data_in = kmap(pages_in[page_in_index]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) workspace->strm.next_in = data_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) tmp = srclen - workspace->strm.total_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) workspace->strm.avail_in = min(tmp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) if (ret != Z_STREAM_END)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) zlib_inflateEnd(&workspace->strm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) if (data_in)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) kunmap(pages_in[page_in_index]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) zero_fill_bio(orig_bio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) int zlib_decompress(struct list_head *ws, unsigned char *data_in,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) struct page *dest_page, unsigned long start_byte, size_t srclen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) size_t destlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) struct workspace *workspace = list_entry(ws, struct workspace, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) int wbits = MAX_WBITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) unsigned long bytes_left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) unsigned long total_out = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) unsigned long pg_offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) char *kaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) destlen = min_t(unsigned long, destlen, PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) bytes_left = destlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) workspace->strm.next_in = data_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) workspace->strm.avail_in = srclen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) workspace->strm.total_in = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) workspace->strm.next_out = workspace->buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) workspace->strm.avail_out = workspace->buf_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) workspace->strm.total_out = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) /* If it's deflate, and it's got no preset dictionary, then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) we can tell zlib to skip the adler32 check. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) if (srclen > 2 && !(data_in[1] & PRESET_DICT) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) ((data_in[0] & 0x0f) == Z_DEFLATED) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) !(((data_in[0]<<8) + data_in[1]) % 31)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) wbits = -((data_in[0] >> 4) + 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) workspace->strm.next_in += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) workspace->strm.avail_in -= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) if (Z_OK != zlib_inflateInit2(&workspace->strm, wbits)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) pr_warn("BTRFS: inflateInit failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) while (bytes_left > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) unsigned long buf_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) unsigned long buf_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) unsigned long bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) ret = zlib_inflate(&workspace->strm, Z_NO_FLUSH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) if (ret != Z_OK && ret != Z_STREAM_END)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) buf_start = total_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) total_out = workspace->strm.total_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) if (total_out == buf_start) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) if (total_out <= start_byte)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) goto next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) if (total_out > start_byte && buf_start < start_byte)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) buf_offset = start_byte - buf_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) buf_offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) bytes = min(PAGE_SIZE - pg_offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) PAGE_SIZE - (buf_offset % PAGE_SIZE));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) bytes = min(bytes, bytes_left);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) kaddr = kmap_atomic(dest_page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) memcpy(kaddr + pg_offset, workspace->buf + buf_offset, bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) kunmap_atomic(kaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) pg_offset += bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) bytes_left -= bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) next:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) workspace->strm.next_out = workspace->buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) workspace->strm.avail_out = workspace->buf_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) if (ret != Z_STREAM_END && bytes_left != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) zlib_inflateEnd(&workspace->strm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) * this should only happen if zlib returned fewer bytes than we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) * expected. btrfs_get_block is responsible for zeroing from the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) * end of the inline extent (destlen) to the end of the page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) if (pg_offset < destlen) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) kaddr = kmap_atomic(dest_page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) memset(kaddr + pg_offset, 0, destlen - pg_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) kunmap_atomic(kaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) const struct btrfs_compress_op btrfs_zlib_compress = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) .workspace_manager = &wsm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) .max_level = 9,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) .default_level = BTRFS_ZLIB_DEFAULT_LEVEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) };