Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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) };