VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

More than 9999 Commits   32 Branches   54 Tags
29b24f6ca112d drivers/staging/erofs/decompressor.c (Gao Xiang           2019-07-31 23:57:31 +0800   1) // SPDX-License-Identifier: GPL-2.0-only
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800   2) /*
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800   3)  * Copyright (C) 2019 HUAWEI, Inc.
592e7cd00bb9d fs/erofs/decompressor.c              (Alexander A. Klimov 2020-07-13 15:09:44 +0200   4)  *             https://www.huawei.com/
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800   5)  * Created by Gao Xiang <gaoxiang25@huawei.com>
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800   6)  */
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800   7) #include "compress.h"
46c2d1494332e drivers/staging/erofs/decompressor.c (Gao Xiang           2019-07-31 23:57:44 +0800   8) #include <linux/module.h>
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800   9) #include <linux/lz4.h>
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800  10) 
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800  11) #ifndef LZ4_DISTANCE_MAX	/* history window size */
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800  12) #define LZ4_DISTANCE_MAX 65535	/* set to maximum value by default */
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800  13) #endif
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800  14) 
af89bcef55ff6 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-07-03 14:52:09 +0800  15) #define LZ4_MAX_DISTANCE_PAGES	(DIV_ROUND_UP(LZ4_DISTANCE_MAX, PAGE_SIZE) + 1)
0ffd71bcc3a03 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:56 +0800  16) #ifndef LZ4_DECOMPRESS_INPLACE_MARGIN
0ffd71bcc3a03 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:56 +0800  17) #define LZ4_DECOMPRESS_INPLACE_MARGIN(srcsize)  (((srcsize) >> 8) + 32)
0ffd71bcc3a03 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:56 +0800  18) #endif
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800  19) 
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800  20) struct z_erofs_decompressor {
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800  21) 	/*
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800  22) 	 * if destpages have sparsed pages, fill them with bounce pages.
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800  23) 	 * it also check whether destpages indicate continuous physical memory.
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800  24) 	 */
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800  25) 	int (*prepare_destpages)(struct z_erofs_decompress_req *rq,
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800  26) 				 struct list_head *pagepool);
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800  27) 	int (*decompress)(struct z_erofs_decompress_req *rq, u8 *out);
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800  28) 	char *name;
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800  29) };
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800  30) 
5d50538fc567c fs/erofs/decompressor.c              (Huang Jianan        2021-03-29 09:23:06 +0800  31) int z_erofs_load_lz4_config(struct super_block *sb,
46249cded18ac fs/erofs/decompressor.c              (Gao Xiang           2021-03-29 09:23:07 +0800  32) 			    struct erofs_super_block *dsb,
46249cded18ac fs/erofs/decompressor.c              (Gao Xiang           2021-03-29 09:23:07 +0800  33) 			    struct z_erofs_lz4_cfgs *lz4, int size)
5d50538fc567c fs/erofs/decompressor.c              (Huang Jianan        2021-03-29 09:23:06 +0800  34) {
4fea63f7d76e4 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:23 +0800  35) 	struct erofs_sb_info *sbi = EROFS_SB(sb);
46249cded18ac fs/erofs/decompressor.c              (Gao Xiang           2021-03-29 09:23:07 +0800  36) 	u16 distance;
46249cded18ac fs/erofs/decompressor.c              (Gao Xiang           2021-03-29 09:23:07 +0800  37) 
46249cded18ac fs/erofs/decompressor.c              (Gao Xiang           2021-03-29 09:23:07 +0800  38) 	if (lz4) {
46249cded18ac fs/erofs/decompressor.c              (Gao Xiang           2021-03-29 09:23:07 +0800  39) 		if (size < sizeof(struct z_erofs_lz4_cfgs)) {
46249cded18ac fs/erofs/decompressor.c              (Gao Xiang           2021-03-29 09:23:07 +0800  40) 			erofs_err(sb, "invalid lz4 cfgs, size=%u", size);
46249cded18ac fs/erofs/decompressor.c              (Gao Xiang           2021-03-29 09:23:07 +0800  41) 			return -EINVAL;
46249cded18ac fs/erofs/decompressor.c              (Gao Xiang           2021-03-29 09:23:07 +0800  42) 		}
46249cded18ac fs/erofs/decompressor.c              (Gao Xiang           2021-03-29 09:23:07 +0800  43) 		distance = le16_to_cpu(lz4->max_distance);
4fea63f7d76e4 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:23 +0800  44) 
4fea63f7d76e4 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:23 +0800  45) 		sbi->lz4.max_pclusterblks = le16_to_cpu(lz4->max_pclusterblks);
4fea63f7d76e4 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:23 +0800  46) 		if (!sbi->lz4.max_pclusterblks) {
4fea63f7d76e4 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:23 +0800  47) 			sbi->lz4.max_pclusterblks = 1;	/* reserved case */
4fea63f7d76e4 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:23 +0800  48) 		} else if (sbi->lz4.max_pclusterblks >
4fea63f7d76e4 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:23 +0800  49) 			   Z_EROFS_PCLUSTER_MAX_SIZE / EROFS_BLKSIZ) {
4fea63f7d76e4 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:23 +0800  50) 			erofs_err(sb, "too large lz4 pclusterblks %u",
4fea63f7d76e4 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:23 +0800  51) 				  sbi->lz4.max_pclusterblks);
4fea63f7d76e4 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:23 +0800  52) 			return -EINVAL;
4fea63f7d76e4 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:23 +0800  53) 		} else if (sbi->lz4.max_pclusterblks >= 2) {
4fea63f7d76e4 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:23 +0800  54) 			erofs_info(sb, "EXPERIMENTAL big pcluster feature in use. Use at your own risk!");
4fea63f7d76e4 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:23 +0800  55) 		}
46249cded18ac fs/erofs/decompressor.c              (Gao Xiang           2021-03-29 09:23:07 +0800  56) 	} else {
14373711dd54b fs/erofs/decompressor.c              (Gao Xiang           2021-03-29 18:00:12 +0800  57) 		distance = le16_to_cpu(dsb->u1.lz4_max_distance);
4fea63f7d76e4 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:23 +0800  58) 		sbi->lz4.max_pclusterblks = 1;
46249cded18ac fs/erofs/decompressor.c              (Gao Xiang           2021-03-29 09:23:07 +0800  59) 	}
5d50538fc567c fs/erofs/decompressor.c              (Huang Jianan        2021-03-29 09:23:06 +0800  60) 
4fea63f7d76e4 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:23 +0800  61) 	sbi->lz4.max_distance_pages = distance ?
5d50538fc567c fs/erofs/decompressor.c              (Huang Jianan        2021-03-29 09:23:06 +0800  62) 					DIV_ROUND_UP(distance, PAGE_SIZE) + 1 :
5d50538fc567c fs/erofs/decompressor.c              (Huang Jianan        2021-03-29 09:23:06 +0800  63) 					LZ4_MAX_DISTANCE_PAGES;
4fea63f7d76e4 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:23 +0800  64) 	return erofs_pcpubuf_growsize(sbi->lz4.max_pclusterblks);
5d50538fc567c fs/erofs/decompressor.c              (Huang Jianan        2021-03-29 09:23:06 +0800  65) }
5d50538fc567c fs/erofs/decompressor.c              (Huang Jianan        2021-03-29 09:23:06 +0800  66) 
99634bf388db0 fs/erofs/decompressor.c              (Gao Xiang           2019-09-04 10:09:05 +0800  67) static int z_erofs_lz4_prepare_destpages(struct z_erofs_decompress_req *rq,
99634bf388db0 fs/erofs/decompressor.c              (Gao Xiang           2019-09-04 10:09:05 +0800  68) 					 struct list_head *pagepool)
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800  69) {
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800  70) 	const unsigned int nr =
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800  71) 		PAGE_ALIGN(rq->pageofs_out + rq->outputsize) >> PAGE_SHIFT;
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800  72) 	struct page *availables[LZ4_MAX_DISTANCE_PAGES] = { NULL };
af89bcef55ff6 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-07-03 14:52:09 +0800  73) 	unsigned long bounced[DIV_ROUND_UP(LZ4_MAX_DISTANCE_PAGES,
af89bcef55ff6 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-07-03 14:52:09 +0800  74) 					   BITS_PER_LONG)] = { 0 };
5d50538fc567c fs/erofs/decompressor.c              (Huang Jianan        2021-03-29 09:23:06 +0800  75) 	unsigned int lz4_max_distance_pages =
5d50538fc567c fs/erofs/decompressor.c              (Huang Jianan        2021-03-29 09:23:06 +0800  76) 				EROFS_SB(rq->sb)->lz4.max_distance_pages;
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800  77) 	void *kaddr = NULL;
af89bcef55ff6 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-07-03 14:52:09 +0800  78) 	unsigned int i, j, top;
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800  79) 
af89bcef55ff6 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-07-03 14:52:09 +0800  80) 	top = 0;
af89bcef55ff6 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-07-03 14:52:09 +0800  81) 	for (i = j = 0; i < nr; ++i, ++j) {
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800  82) 		struct page *const page = rq->out[i];
af89bcef55ff6 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-07-03 14:52:09 +0800  83) 		struct page *victim;
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800  84) 
5d50538fc567c fs/erofs/decompressor.c              (Huang Jianan        2021-03-29 09:23:06 +0800  85) 		if (j >= lz4_max_distance_pages)
af89bcef55ff6 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-07-03 14:52:09 +0800  86) 			j = 0;
af89bcef55ff6 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-07-03 14:52:09 +0800  87) 
af89bcef55ff6 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-07-03 14:52:09 +0800  88) 		/* 'valid' bounced can only be tested after a complete round */
af89bcef55ff6 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-07-03 14:52:09 +0800  89) 		if (test_bit(j, bounced)) {
5d50538fc567c fs/erofs/decompressor.c              (Huang Jianan        2021-03-29 09:23:06 +0800  90) 			DBG_BUGON(i < lz4_max_distance_pages);
5d50538fc567c fs/erofs/decompressor.c              (Huang Jianan        2021-03-29 09:23:06 +0800  91) 			DBG_BUGON(top >= lz4_max_distance_pages);
5d50538fc567c fs/erofs/decompressor.c              (Huang Jianan        2021-03-29 09:23:06 +0800  92) 			availables[top++] = rq->out[i - lz4_max_distance_pages];
af89bcef55ff6 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-07-03 14:52:09 +0800  93) 		}
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800  94) 
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800  95) 		if (page) {
af89bcef55ff6 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-07-03 14:52:09 +0800  96) 			__clear_bit(j, bounced);
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800  97) 			if (kaddr) {
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800  98) 				if (kaddr + PAGE_SIZE == page_address(page))
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800  99) 					kaddr += PAGE_SIZE;
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 100) 				else
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 101) 					kaddr = NULL;
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 102) 			} else if (!i) {
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 103) 				kaddr = page_address(page);
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 104) 			}
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 105) 			continue;
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 106) 		}
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 107) 		kaddr = NULL;
af89bcef55ff6 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-07-03 14:52:09 +0800 108) 		__set_bit(j, bounced);
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 109) 
af89bcef55ff6 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-07-03 14:52:09 +0800 110) 		if (top) {
af89bcef55ff6 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-07-03 14:52:09 +0800 111) 			victim = availables[--top];
af89bcef55ff6 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-07-03 14:52:09 +0800 112) 			get_page(victim);
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 113) 		} else {
b4892fa3e7fd6 fs/erofs/decompressor.c              (Huang Jianan        2021-03-16 11:15:14 +0800 114) 			victim = erofs_allocpage(pagepool,
b4892fa3e7fd6 fs/erofs/decompressor.c              (Huang Jianan        2021-03-16 11:15:14 +0800 115) 						 GFP_KERNEL | __GFP_NOFAIL);
6aaa7b0664e68 fs/erofs/decompressor.c              (Gao Xiang           2020-12-08 17:58:32 +0800 116) 			set_page_private(victim, Z_EROFS_SHORTLIVED_PAGE);
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 117) 		}
af89bcef55ff6 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-07-03 14:52:09 +0800 118) 		rq->out[i] = victim;
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 119) 	}
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 120) 	return kaddr ? 1 : 0;
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 121) }
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 122) 
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 123) static void *z_erofs_handle_inplace_io(struct z_erofs_decompress_req *rq,
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 124) 			void *inpage, unsigned int *inputmargin, int *maptype,
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 125) 			bool support_0padding)
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 126) {
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 127) 	unsigned int nrpages_in, nrpages_out;
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 128) 	unsigned int ofull, oend, inputsize, total, i, j;
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 129) 	struct page **in;
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 130) 	void *src, *tmp;
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 131) 
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 132) 	inputsize = rq->inputsize;
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 133) 	nrpages_in = PAGE_ALIGN(inputsize) >> PAGE_SHIFT;
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 134) 	oend = rq->pageofs_out + rq->outputsize;
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 135) 	ofull = PAGE_ALIGN(oend);
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 136) 	nrpages_out = ofull >> PAGE_SHIFT;
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 137) 
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 138) 	if (rq->inplace_io) {
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 139) 		if (rq->partial_decoding || !support_0padding ||
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 140) 		    ofull - oend < LZ4_DECOMPRESS_INPLACE_MARGIN(inputsize))
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 141) 			goto docopy;
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 142) 
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 143) 		for (i = 0; i < nrpages_in; ++i) {
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 144) 			DBG_BUGON(rq->in[i] == NULL);
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 145) 			for (j = 0; j < nrpages_out - nrpages_in + i; ++j)
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 146) 				if (rq->out[j] == rq->in[i])
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 147) 					goto docopy;
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 148) 		}
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 149) 	}
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 150) 
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 151) 	if (nrpages_in <= 1) {
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 152) 		*maptype = 0;
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 153) 		return inpage;
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 154) 	}
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 155) 	kunmap_atomic(inpage);
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 156) 	might_sleep();
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 157) 	src = erofs_vm_map_ram(rq->in, nrpages_in);
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 158) 	if (!src)
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 159) 		return ERR_PTR(-ENOMEM);
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 160) 	*maptype = 1;
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 161) 	return src;
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 162) 
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 163) docopy:
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 164) 	/* Or copy compressed data which can be overlapped to per-CPU buffer */
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 165) 	in = rq->in;
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 166) 	src = erofs_get_pcpubuf(nrpages_in);
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 167) 	if (!src) {
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 168) 		DBG_BUGON(1);
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 169) 		kunmap_atomic(inpage);
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 170) 		return ERR_PTR(-EFAULT);
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 171) 	}
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 172) 
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 173) 	tmp = src;
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 174) 	total = rq->inputsize;
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 175) 	while (total) {
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 176) 		unsigned int page_copycnt =
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 177) 			min_t(unsigned int, total, PAGE_SIZE - *inputmargin);
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 178) 
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 179) 		if (!inpage)
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 180) 			inpage = kmap_atomic(*in);
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 181) 		memcpy(tmp, inpage + *inputmargin, page_copycnt);
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 182) 		kunmap_atomic(inpage);
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 183) 		inpage = NULL;
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 184) 		tmp += page_copycnt;
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 185) 		total -= page_copycnt;
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 186) 		++in;
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 187) 		*inputmargin = 0;
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 188) 	}
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 189) 	*maptype = 2;
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 190) 	return src;
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 191) }
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 192) 
99634bf388db0 fs/erofs/decompressor.c              (Gao Xiang           2019-09-04 10:09:05 +0800 193) static int z_erofs_lz4_decompress(struct z_erofs_decompress_req *rq, u8 *out)
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 194) {
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 195) 	unsigned int inputmargin;
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 196) 	u8 *headpage, *src;
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 197) 	bool support_0padding;
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 198) 	int ret, maptype;
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 199) 
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 200) 	DBG_BUGON(*rq->in == NULL);
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 201) 	headpage = kmap_atomic(*rq->in);
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 202) 	inputmargin = 0;
0ffd71bcc3a03 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:56 +0800 203) 	support_0padding = false;
0ffd71bcc3a03 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:56 +0800 204) 
0ffd71bcc3a03 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:56 +0800 205) 	/* decompression inplace is only safe when 0padding is enabled */
de06a6a375414 fs/erofs/decompressor.c              (Gao Xiang           2021-03-29 09:23:05 +0800 206) 	if (erofs_sb_has_lz4_0padding(EROFS_SB(rq->sb))) {
0ffd71bcc3a03 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:56 +0800 207) 		support_0padding = true;
0ffd71bcc3a03 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:56 +0800 208) 
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 209) 		while (!headpage[inputmargin & ~PAGE_MASK])
0ffd71bcc3a03 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:56 +0800 210) 			if (!(++inputmargin & ~PAGE_MASK))
0ffd71bcc3a03 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:56 +0800 211) 				break;
0ffd71bcc3a03 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:56 +0800 212) 
0ffd71bcc3a03 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:56 +0800 213) 		if (inputmargin >= rq->inputsize) {
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 214) 			kunmap_atomic(headpage);
0ffd71bcc3a03 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:56 +0800 215) 			return -EIO;
0ffd71bcc3a03 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:56 +0800 216) 		}
0ffd71bcc3a03 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:56 +0800 217) 	}
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 218) 
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 219) 	rq->inputsize -= inputmargin;
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 220) 	src = z_erofs_handle_inplace_io(rq, headpage, &inputmargin, &maptype,
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 221) 					support_0padding);
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 222) 	if (IS_ERR(src))
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 223) 		return PTR_ERR(src);
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 224) 
af1038abbd144 fs/erofs/decompressor.c              (Gao Xiang           2020-02-26 16:10:07 +0800 225) 	/* legacy format could compress extra data in a pcluster. */
af1038abbd144 fs/erofs/decompressor.c              (Gao Xiang           2020-02-26 16:10:07 +0800 226) 	if (rq->partial_decoding || !support_0padding)
af1038abbd144 fs/erofs/decompressor.c              (Gao Xiang           2020-02-26 16:10:07 +0800 227) 		ret = LZ4_decompress_safe_partial(src + inputmargin, out,
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 228) 				rq->inputsize, rq->outputsize, rq->outputsize);
af1038abbd144 fs/erofs/decompressor.c              (Gao Xiang           2020-02-26 16:10:07 +0800 229) 	else
af1038abbd144 fs/erofs/decompressor.c              (Gao Xiang           2020-02-26 16:10:07 +0800 230) 		ret = LZ4_decompress_safe(src + inputmargin, out,
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 231) 					  rq->inputsize, rq->outputsize);
af1038abbd144 fs/erofs/decompressor.c              (Gao Xiang           2020-02-26 16:10:07 +0800 232) 
aa99a76b40d64 fs/erofs/decompressor.c              (Gao Xiang           2020-02-26 16:10:08 +0800 233) 	if (ret != rq->outputsize) {
aa99a76b40d64 fs/erofs/decompressor.c              (Gao Xiang           2020-02-26 16:10:08 +0800 234) 		erofs_err(rq->sb, "failed to decompress %d in[%u, %u] out[%u]",
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 235) 			  ret, rq->inputsize, inputmargin, rq->outputsize);
aa99a76b40d64 fs/erofs/decompressor.c              (Gao Xiang           2020-02-26 16:10:08 +0800 236) 
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 237) 		WARN_ON(1);
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 238) 		print_hex_dump(KERN_DEBUG, "[ in]: ", DUMP_PREFIX_OFFSET,
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 239) 			       16, 1, src + inputmargin, rq->inputsize, true);
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 240) 		print_hex_dump(KERN_DEBUG, "[out]: ", DUMP_PREFIX_OFFSET,
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 241) 			       16, 1, out, rq->outputsize, true);
aa99a76b40d64 fs/erofs/decompressor.c              (Gao Xiang           2020-02-26 16:10:08 +0800 242) 
aa99a76b40d64 fs/erofs/decompressor.c              (Gao Xiang           2020-02-26 16:10:08 +0800 243) 		if (ret >= 0)
aa99a76b40d64 fs/erofs/decompressor.c              (Gao Xiang           2020-02-26 16:10:08 +0800 244) 			memset(out + ret, 0, rq->outputsize - ret);
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 245) 		ret = -EIO;
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 246) 	}
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 247) 
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 248) 	if (maptype == 0) {
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 249) 		kunmap_atomic(src);
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 250) 	} else if (maptype == 1) {
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 251) 		vm_unmap_ram(src, PAGE_ALIGN(rq->inputsize) >> PAGE_SHIFT);
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 252) 	} else if (maptype == 2) {
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 253) 		erofs_put_pcpubuf(src);
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 254) 	} else {
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 255) 		DBG_BUGON(1);
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 256) 		return -EFAULT;
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 257) 	}
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 258) 	return ret;
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 259) }
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 260) 
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 261) static struct z_erofs_decompressor decompressors[] = {
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 262) 	[Z_EROFS_COMPRESSION_SHIFTED] = {
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 263) 		.name = "shifted"
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 264) 	},
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 265) 	[Z_EROFS_COMPRESSION_LZ4] = {
99634bf388db0 fs/erofs/decompressor.c              (Gao Xiang           2019-09-04 10:09:05 +0800 266) 		.prepare_destpages = z_erofs_lz4_prepare_destpages,
99634bf388db0 fs/erofs/decompressor.c              (Gao Xiang           2019-09-04 10:09:05 +0800 267) 		.decompress = z_erofs_lz4_decompress,
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 268) 		.name = "lz4"
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 269) 	},
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 270) };
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 271) 
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 272) static void copy_from_pcpubuf(struct page **out, const char *dst,
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 273) 			      unsigned short pageofs_out,
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 274) 			      unsigned int outputsize)
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 275) {
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 276) 	const char *end = dst + outputsize;
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 277) 	const unsigned int righthalf = PAGE_SIZE - pageofs_out;
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 278) 	const char *cur = dst - pageofs_out;
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 279) 
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 280) 	while (cur < end) {
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 281) 		struct page *const page = *out++;
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 282) 
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 283) 		if (page) {
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 284) 			char *buf = kmap_atomic(page);
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 285) 
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 286) 			if (cur >= dst) {
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 287) 				memcpy(buf, cur, min_t(uint, PAGE_SIZE,
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 288) 						       end - cur));
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 289) 			} else {
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 290) 				memcpy(buf + pageofs_out, cur + pageofs_out,
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 291) 				       min_t(uint, righthalf, end - cur));
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 292) 			}
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 293) 			kunmap_atomic(buf);
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 294) 		}
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 295) 		cur += PAGE_SIZE;
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 296) 	}
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 297) }
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 298) 
99634bf388db0 fs/erofs/decompressor.c              (Gao Xiang           2019-09-04 10:09:05 +0800 299) static int z_erofs_decompress_generic(struct z_erofs_decompress_req *rq,
99634bf388db0 fs/erofs/decompressor.c              (Gao Xiang           2019-09-04 10:09:05 +0800 300) 				      struct list_head *pagepool)
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 301) {
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 302) 	const unsigned int nrpages_out =
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 303) 		PAGE_ALIGN(rq->pageofs_out + rq->outputsize) >> PAGE_SHIFT;
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 304) 	const struct z_erofs_decompressor *alg = decompressors + rq->alg;
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 305) 	unsigned int dst_maptype;
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 306) 	void *dst;
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 307) 	int ret;
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 308) 
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 309) 	/* two optimized fast paths only for non bigpcluster cases yet */
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 310) 	if (rq->inputsize <= PAGE_SIZE) {
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 311) 		if (nrpages_out == 1 && !rq->inplace_io) {
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 312) 			DBG_BUGON(!*rq->out);
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 313) 			dst = kmap_atomic(*rq->out);
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 314) 			dst_maptype = 0;
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 315) 			goto dstmap_out;
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 316) 		}
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 317) 
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 318) 		/*
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 319) 		 * For the case of small output size (especially much less
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 320) 		 * than PAGE_SIZE), memcpy the decompressed data rather than
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 321) 		 * compressed data is preferred.
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 322) 		 */
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 323) 		if (rq->outputsize <= PAGE_SIZE * 7 / 8) {
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 324) 			dst = erofs_get_pcpubuf(1);
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 325) 			if (IS_ERR(dst))
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 326) 				return PTR_ERR(dst);
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 327) 
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 328) 			rq->inplace_io = false;
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 329) 			ret = alg->decompress(rq, dst);
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 330) 			if (!ret)
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 331) 				copy_from_pcpubuf(rq->out, dst, rq->pageofs_out,
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 332) 						  rq->outputsize);
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 333) 
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 334) 			erofs_put_pcpubuf(dst);
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 335) 			return ret;
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 336) 		}
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 337) 	}
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 338) 
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 339) 	/* general decoding path which can be used for all cases */
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 340) 	ret = alg->prepare_destpages(rq, pagepool);
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 341) 	if (ret < 0)
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 342) 		return ret;
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 343) 	if (ret) {
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 344) 		dst = page_address(*rq->out);
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 345) 		dst_maptype = 1;
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 346) 		goto dstmap_out;
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 347) 	}
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 348) 
598162d050801 fs/erofs/decompressor.c              (Gao Xiang           2021-04-07 12:39:26 +0800 349) 	dst = erofs_vm_map_ram(rq->out, nrpages_out);
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 350) 	if (!dst)
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 351) 		return -ENOMEM;
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 352) 	dst_maptype = 2;
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 353) 
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 354) dstmap_out:
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 355) 	ret = alg->decompress(rq, dst + rq->pageofs_out);
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 356) 
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 357) 	if (!dst_maptype)
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 358) 		kunmap_atomic(dst);
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 359) 	else if (dst_maptype == 2)
73d03931be2ff fs/erofs/decompressor.c              (Gao Xiang           2019-09-04 10:09:07 +0800 360) 		vm_unmap_ram(dst, nrpages_out);
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 361) 	return ret;
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 362) }
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 363) 
99634bf388db0 fs/erofs/decompressor.c              (Gao Xiang           2019-09-04 10:09:05 +0800 364) static int z_erofs_shifted_transform(const struct z_erofs_decompress_req *rq,
99634bf388db0 fs/erofs/decompressor.c              (Gao Xiang           2019-09-04 10:09:05 +0800 365) 				     struct list_head *pagepool)
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 366) {
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 367) 	const unsigned int nrpages_out =
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 368) 		PAGE_ALIGN(rq->pageofs_out + rq->outputsize) >> PAGE_SHIFT;
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 369) 	const unsigned int righthalf = PAGE_SIZE - rq->pageofs_out;
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 370) 	unsigned char *src, *dst;
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 371) 
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 372) 	if (nrpages_out > 2) {
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 373) 		DBG_BUGON(1);
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 374) 		return -EIO;
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 375) 	}
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 376) 
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 377) 	if (rq->out[0] == *rq->in) {
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 378) 		DBG_BUGON(nrpages_out != 1);
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 379) 		return 0;
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 380) 	}
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 381) 
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 382) 	src = kmap_atomic(*rq->in);
4d2024370d877 fs/erofs/decompressor.c              (Gao Xiang           2020-01-07 10:25:46 +0800 383) 	if (rq->out[0]) {
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 384) 		dst = kmap_atomic(rq->out[0]);
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 385) 		memcpy(dst + rq->pageofs_out, src, righthalf);
4d2024370d877 fs/erofs/decompressor.c              (Gao Xiang           2020-01-07 10:25:46 +0800 386) 		kunmap_atomic(dst);
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 387) 	}
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 388) 
4d2024370d877 fs/erofs/decompressor.c              (Gao Xiang           2020-01-07 10:25:46 +0800 389) 	if (nrpages_out == 2) {
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 390) 		DBG_BUGON(!rq->out[1]);
4d2024370d877 fs/erofs/decompressor.c              (Gao Xiang           2020-01-07 10:25:46 +0800 391) 		if (rq->out[1] == *rq->in) {
4d2024370d877 fs/erofs/decompressor.c              (Gao Xiang           2020-01-07 10:25:46 +0800 392) 			memmove(src, src + righthalf, rq->pageofs_out);
4d2024370d877 fs/erofs/decompressor.c              (Gao Xiang           2020-01-07 10:25:46 +0800 393) 		} else {
4d2024370d877 fs/erofs/decompressor.c              (Gao Xiang           2020-01-07 10:25:46 +0800 394) 			dst = kmap_atomic(rq->out[1]);
4d2024370d877 fs/erofs/decompressor.c              (Gao Xiang           2020-01-07 10:25:46 +0800 395) 			memcpy(dst, src + righthalf, rq->pageofs_out);
4d2024370d877 fs/erofs/decompressor.c              (Gao Xiang           2020-01-07 10:25:46 +0800 396) 			kunmap_atomic(dst);
4d2024370d877 fs/erofs/decompressor.c              (Gao Xiang           2020-01-07 10:25:46 +0800 397) 		}
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 398) 	}
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 399) 	kunmap_atomic(src);
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 400) 	return 0;
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 401) }
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 402) 
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 403) int z_erofs_decompress(struct z_erofs_decompress_req *rq,
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 404) 		       struct list_head *pagepool)
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 405) {
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 406) 	if (rq->alg == Z_EROFS_COMPRESSION_SHIFTED)
99634bf388db0 fs/erofs/decompressor.c              (Gao Xiang           2019-09-04 10:09:05 +0800 407) 		return z_erofs_shifted_transform(rq, pagepool);
99634bf388db0 fs/erofs/decompressor.c              (Gao Xiang           2019-09-04 10:09:05 +0800 408) 	return z_erofs_decompress_generic(rq, pagepool);
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 409) }
7fc45dbc938a2 drivers/staging/erofs/decompressor.c (Gao Xiang           2019-06-24 15:22:55 +0800 410)