decompressor.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (C) 2019 HUAWEI, Inc.
  4. * https://www.huawei.com/
  5. * Copyright (C) 2024 Alibaba Cloud
  6. */
  7. #include "compress.h"
  8. #include <linux/lz4.h>
  9. #define LZ4_MAX_DISTANCE_PAGES (DIV_ROUND_UP(LZ4_DISTANCE_MAX, PAGE_SIZE) + 1)
  10. static int z_erofs_load_lz4_config(struct super_block *sb,
  11. struct erofs_super_block *dsb, void *data, int size)
  12. {
  13. struct erofs_sb_info *sbi = EROFS_SB(sb);
  14. struct z_erofs_lz4_cfgs *lz4 = data;
  15. u16 distance;
  16. if (lz4) {
  17. if (size < sizeof(struct z_erofs_lz4_cfgs)) {
  18. erofs_err(sb, "invalid lz4 cfgs, size=%u", size);
  19. return -EINVAL;
  20. }
  21. distance = le16_to_cpu(lz4->max_distance);
  22. sbi->lz4.max_pclusterblks = le16_to_cpu(lz4->max_pclusterblks);
  23. if (!sbi->lz4.max_pclusterblks) {
  24. sbi->lz4.max_pclusterblks = 1; /* reserved case */
  25. } else if (sbi->lz4.max_pclusterblks >
  26. erofs_blknr(sb, Z_EROFS_PCLUSTER_MAX_SIZE)) {
  27. erofs_err(sb, "too large lz4 pclusterblks %u",
  28. sbi->lz4.max_pclusterblks);
  29. return -EINVAL;
  30. }
  31. } else {
  32. distance = le16_to_cpu(dsb->u1.lz4_max_distance);
  33. if (!distance && !erofs_sb_has_lz4_0padding(sbi))
  34. return 0;
  35. sbi->lz4.max_pclusterblks = 1;
  36. sbi->available_compr_algs = 1 << Z_EROFS_COMPRESSION_LZ4;
  37. }
  38. sbi->lz4.max_distance_pages = distance ?
  39. DIV_ROUND_UP(distance, PAGE_SIZE) + 1 :
  40. LZ4_MAX_DISTANCE_PAGES;
  41. return z_erofs_gbuf_growsize(sbi->lz4.max_pclusterblks);
  42. }
  43. /*
  44. * Fill all gaps with bounce pages if it's a sparse page list. Also check if
  45. * all physical pages are consecutive, which can be seen for moderate CR.
  46. */
  47. static int z_erofs_lz4_prepare_dstpages(struct z_erofs_decompress_req *rq,
  48. struct page **pagepool)
  49. {
  50. struct page *availables[LZ4_MAX_DISTANCE_PAGES] = { NULL };
  51. unsigned long bounced[DIV_ROUND_UP(LZ4_MAX_DISTANCE_PAGES,
  52. BITS_PER_LONG)] = { 0 };
  53. unsigned int lz4_max_distance_pages =
  54. EROFS_SB(rq->sb)->lz4.max_distance_pages;
  55. void *kaddr = NULL;
  56. unsigned int i, j, top;
  57. top = 0;
  58. for (i = j = 0; i < rq->outpages; ++i, ++j) {
  59. struct page *const page = rq->out[i];
  60. struct page *victim;
  61. if (j >= lz4_max_distance_pages)
  62. j = 0;
  63. /* 'valid' bounced can only be tested after a complete round */
  64. if (!rq->fillgaps && test_bit(j, bounced)) {
  65. DBG_BUGON(i < lz4_max_distance_pages);
  66. DBG_BUGON(top >= lz4_max_distance_pages);
  67. availables[top++] = rq->out[i - lz4_max_distance_pages];
  68. }
  69. if (page) {
  70. __clear_bit(j, bounced);
  71. if (!PageHighMem(page)) {
  72. if (!i) {
  73. kaddr = page_address(page);
  74. continue;
  75. }
  76. if (kaddr &&
  77. kaddr + PAGE_SIZE == page_address(page)) {
  78. kaddr += PAGE_SIZE;
  79. continue;
  80. }
  81. }
  82. kaddr = NULL;
  83. continue;
  84. }
  85. kaddr = NULL;
  86. __set_bit(j, bounced);
  87. if (top) {
  88. victim = availables[--top];
  89. } else {
  90. victim = __erofs_allocpage(pagepool, rq->gfp, true);
  91. if (!victim)
  92. return -ENOMEM;
  93. set_page_private(victim, Z_EROFS_SHORTLIVED_PAGE);
  94. }
  95. rq->out[i] = victim;
  96. }
  97. return kaddr ? 1 : 0;
  98. }
  99. static void *z_erofs_lz4_handle_overlap(const struct z_erofs_decompress_req *rq,
  100. void *inpage, void *out, unsigned int *inputmargin,
  101. int *maptype, bool may_inplace)
  102. {
  103. unsigned int oend, omargin, cnt, i;
  104. struct page **in;
  105. void *src;
  106. /*
  107. * If in-place I/O isn't used, for example, the bounce compressed cache
  108. * can hold data for incomplete read requests. Just map the compressed
  109. * buffer as well and decompress directly.
  110. */
  111. if (!rq->inplace_io) {
  112. if (rq->inpages <= 1) {
  113. *maptype = 0;
  114. return inpage;
  115. }
  116. kunmap_local(inpage);
  117. src = erofs_vm_map_ram(rq->in, rq->inpages);
  118. if (!src)
  119. return ERR_PTR(-ENOMEM);
  120. *maptype = 1;
  121. return src;
  122. }
  123. /*
  124. * Then, deal with in-place I/Os. The reasons why in-place I/O is useful
  125. * are: (1) It minimizes memory footprint during the I/O submission,
  126. * which is useful for slow storage (including network devices and
  127. * low-end HDDs/eMMCs) but with a lot inflight I/Os; (2) If in-place
  128. * decompression can also be applied, it will reuse the unique buffer so
  129. * that no extra CPU D-cache is polluted with temporary compressed data
  130. * for extreme performance.
  131. */
  132. oend = rq->pageofs_out + rq->outputsize;
  133. omargin = PAGE_ALIGN(oend) - oend;
  134. if (!rq->partial_decoding && may_inplace &&
  135. omargin >= LZ4_DECOMPRESS_INPLACE_MARGIN(rq->inputsize)) {
  136. for (i = 0; i < rq->inpages; ++i)
  137. if (rq->out[rq->outpages - rq->inpages + i] !=
  138. rq->in[i])
  139. break;
  140. if (i >= rq->inpages) {
  141. kunmap_local(inpage);
  142. *maptype = 3;
  143. return out + ((rq->outpages - rq->inpages) << PAGE_SHIFT);
  144. }
  145. }
  146. /*
  147. * If in-place decompression can't be applied, copy compressed data that
  148. * may potentially overlap during decompression to a per-CPU buffer.
  149. */
  150. src = z_erofs_get_gbuf(rq->inpages);
  151. if (!src) {
  152. DBG_BUGON(1);
  153. kunmap_local(inpage);
  154. return ERR_PTR(-EFAULT);
  155. }
  156. for (i = 0, in = rq->in; i < rq->inputsize; i += cnt, ++in) {
  157. cnt = min_t(u32, rq->inputsize - i, PAGE_SIZE - *inputmargin);
  158. if (!inpage)
  159. inpage = kmap_local_page(*in);
  160. memcpy(src + i, inpage + *inputmargin, cnt);
  161. kunmap_local(inpage);
  162. inpage = NULL;
  163. *inputmargin = 0;
  164. }
  165. *maptype = 2;
  166. return src;
  167. }
  168. /*
  169. * Get the exact on-disk size of the compressed data:
  170. * - For LZ4, it should apply if the zero_padding feature is on (5.3+);
  171. * - For others, zero_padding is enabled all the time.
  172. */
  173. const char *z_erofs_fixup_insize(struct z_erofs_decompress_req *rq,
  174. const char *padbuf, unsigned int padbufsize)
  175. {
  176. const char *padend;
  177. padend = memchr_inv(padbuf, 0, padbufsize);
  178. if (!padend)
  179. return "compressed data start not found";
  180. rq->inputsize -= padend - padbuf;
  181. rq->pageofs_in += padend - padbuf;
  182. return NULL;
  183. }
  184. static const char *__z_erofs_lz4_decompress(struct z_erofs_decompress_req *rq,
  185. u8 *dst)
  186. {
  187. bool may_inplace = false;
  188. unsigned int inputmargin;
  189. u8 *out, *headpage, *src;
  190. const char *reason;
  191. int ret, maptype;
  192. headpage = kmap_local_page(*rq->in);
  193. reason = z_erofs_fixup_insize(rq, headpage + rq->pageofs_in,
  194. min_t(unsigned int, rq->inputsize,
  195. rq->sb->s_blocksize - rq->pageofs_in));
  196. if (reason) {
  197. kunmap_local(headpage);
  198. return reason;
  199. }
  200. may_inplace = !((rq->pageofs_in + rq->inputsize) &
  201. (rq->sb->s_blocksize - 1));
  202. inputmargin = rq->pageofs_in;
  203. src = z_erofs_lz4_handle_overlap(rq, headpage, dst, &inputmargin,
  204. &maptype, may_inplace);
  205. if (IS_ERR(src))
  206. return ERR_CAST(src);
  207. out = dst + rq->pageofs_out;
  208. if (rq->partial_decoding)
  209. ret = LZ4_decompress_safe_partial(src + inputmargin, out,
  210. rq->inputsize, rq->outputsize, rq->outputsize);
  211. else
  212. ret = LZ4_decompress_safe(src + inputmargin, out,
  213. rq->inputsize, rq->outputsize);
  214. if (ret == rq->outputsize)
  215. reason = NULL;
  216. else if (ret < 0)
  217. reason = "corrupted compressed data";
  218. else
  219. reason = "unexpected end of stream";
  220. if (!maptype) {
  221. kunmap_local(headpage);
  222. } else if (maptype == 1) {
  223. vm_unmap_ram(src, rq->inpages);
  224. } else if (maptype == 2) {
  225. z_erofs_put_gbuf(src);
  226. } else if (maptype != 3) {
  227. DBG_BUGON(1);
  228. return ERR_PTR(-EFAULT);
  229. }
  230. return reason;
  231. }
  232. static const char *z_erofs_lz4_decompress(struct z_erofs_decompress_req *rq,
  233. struct page **pagepool)
  234. {
  235. unsigned int dst_maptype;
  236. const char *reason;
  237. void *dst;
  238. int ret;
  239. /* one optimized fast path only for non bigpcluster cases yet */
  240. if (rq->inpages == 1 && rq->outpages == 1 && !rq->inplace_io) {
  241. DBG_BUGON(!*rq->out);
  242. dst = kmap_local_page(*rq->out);
  243. dst_maptype = 0;
  244. } else {
  245. /* general decoding path which can be used for all cases */
  246. ret = z_erofs_lz4_prepare_dstpages(rq, pagepool);
  247. if (ret < 0)
  248. return ERR_PTR(ret);
  249. if (ret > 0) {
  250. dst = page_address(*rq->out);
  251. dst_maptype = 1;
  252. } else {
  253. dst = erofs_vm_map_ram(rq->out, rq->outpages);
  254. if (!dst)
  255. return ERR_PTR(-ENOMEM);
  256. dst_maptype = 2;
  257. }
  258. }
  259. reason = __z_erofs_lz4_decompress(rq, dst);
  260. if (!dst_maptype)
  261. kunmap_local(dst);
  262. else if (dst_maptype == 2)
  263. vm_unmap_ram(dst, rq->outpages);
  264. return reason;
  265. }
  266. static const char *z_erofs_transform_plain(struct z_erofs_decompress_req *rq,
  267. struct page **pagepool)
  268. {
  269. const unsigned int nrpages_in = rq->inpages, nrpages_out = rq->outpages;
  270. const unsigned int bs = rq->sb->s_blocksize;
  271. unsigned int cur = 0, ni = 0, no, pi, po, insz, cnt;
  272. u8 *kin;
  273. if (rq->outputsize > rq->inputsize)
  274. return ERR_PTR(-EOPNOTSUPP);
  275. if (rq->alg == Z_EROFS_COMPRESSION_INTERLACED) {
  276. cur = bs - (rq->pageofs_out & (bs - 1));
  277. pi = (rq->pageofs_in + rq->inputsize - cur) & ~PAGE_MASK;
  278. cur = min(cur, rq->outputsize);
  279. if (cur && rq->out[0]) {
  280. kin = kmap_local_page(rq->in[nrpages_in - 1]);
  281. if (rq->out[0] == rq->in[nrpages_in - 1])
  282. memmove(kin + rq->pageofs_out, kin + pi, cur);
  283. else
  284. memcpy_to_page(rq->out[0], rq->pageofs_out,
  285. kin + pi, cur);
  286. kunmap_local(kin);
  287. }
  288. rq->outputsize -= cur;
  289. }
  290. for (; rq->outputsize; rq->pageofs_in = 0, cur += insz, ni++) {
  291. insz = min(PAGE_SIZE - rq->pageofs_in, rq->outputsize);
  292. rq->outputsize -= insz;
  293. if (!rq->in[ni])
  294. continue;
  295. kin = kmap_local_page(rq->in[ni]);
  296. pi = 0;
  297. do {
  298. no = (rq->pageofs_out + cur + pi) >> PAGE_SHIFT;
  299. po = (rq->pageofs_out + cur + pi) & ~PAGE_MASK;
  300. DBG_BUGON(no >= nrpages_out);
  301. cnt = min(insz - pi, PAGE_SIZE - po);
  302. if (rq->out[no] == rq->in[ni])
  303. memmove(kin + po,
  304. kin + rq->pageofs_in + pi, cnt);
  305. else if (rq->out[no])
  306. memcpy_to_page(rq->out[no], po,
  307. kin + rq->pageofs_in + pi, cnt);
  308. pi += cnt;
  309. } while (pi < insz);
  310. kunmap_local(kin);
  311. }
  312. DBG_BUGON(ni > nrpages_in);
  313. return NULL;
  314. }
  315. const char *z_erofs_stream_switch_bufs(struct z_erofs_stream_dctx *dctx,
  316. void **dst, void **src, struct page **pgpl)
  317. {
  318. struct z_erofs_decompress_req *rq = dctx->rq;
  319. struct page **pgo, *tmppage;
  320. unsigned int j;
  321. if (!dctx->avail_out) {
  322. if (++dctx->no >= rq->outpages || !rq->outputsize)
  323. return "insufficient space for decompressed data";
  324. if (dctx->kout)
  325. kunmap_local(dctx->kout);
  326. dctx->avail_out = min(rq->outputsize, PAGE_SIZE - rq->pageofs_out);
  327. rq->outputsize -= dctx->avail_out;
  328. pgo = &rq->out[dctx->no];
  329. if (!*pgo && rq->fillgaps) { /* deduped */
  330. *pgo = erofs_allocpage(pgpl, rq->gfp);
  331. if (!*pgo) {
  332. dctx->kout = NULL;
  333. return ERR_PTR(-ENOMEM);
  334. }
  335. set_page_private(*pgo, Z_EROFS_SHORTLIVED_PAGE);
  336. }
  337. if (*pgo) {
  338. dctx->kout = kmap_local_page(*pgo);
  339. *dst = dctx->kout + rq->pageofs_out;
  340. } else {
  341. *dst = dctx->kout = NULL;
  342. }
  343. rq->pageofs_out = 0;
  344. }
  345. if (dctx->inbuf_pos == dctx->inbuf_sz && rq->inputsize) {
  346. if (++dctx->ni >= rq->inpages)
  347. return "invalid compressed data";
  348. if (dctx->kout) /* unlike kmap(), take care of the orders */
  349. kunmap_local(dctx->kout);
  350. kunmap_local(dctx->kin);
  351. dctx->inbuf_sz = min_t(u32, rq->inputsize, PAGE_SIZE);
  352. rq->inputsize -= dctx->inbuf_sz;
  353. dctx->kin = kmap_local_page(rq->in[dctx->ni]);
  354. *src = dctx->kin;
  355. dctx->bounced = false;
  356. if (dctx->kout) {
  357. j = (u8 *)*dst - dctx->kout;
  358. dctx->kout = kmap_local_page(rq->out[dctx->no]);
  359. *dst = dctx->kout + j;
  360. }
  361. dctx->inbuf_pos = 0;
  362. }
  363. /*
  364. * Handle overlapping: Use the given bounce buffer if the input data is
  365. * under processing; Or utilize short-lived pages from the on-stack page
  366. * pool, where pages are shared among the same request. Note that only
  367. * a few inplace I/O pages need to be doubled.
  368. */
  369. if (!dctx->bounced && rq->out[dctx->no] == rq->in[dctx->ni]) {
  370. memcpy(dctx->bounce, *src, dctx->inbuf_sz);
  371. *src = dctx->bounce;
  372. dctx->bounced = true;
  373. }
  374. for (j = dctx->ni + 1; j < rq->inpages; ++j) {
  375. if (rq->out[dctx->no] != rq->in[j])
  376. continue;
  377. tmppage = erofs_allocpage(pgpl, rq->gfp);
  378. if (!tmppage)
  379. return ERR_PTR(-ENOMEM);
  380. set_page_private(tmppage, Z_EROFS_SHORTLIVED_PAGE);
  381. copy_highpage(tmppage, rq->in[j]);
  382. rq->in[j] = tmppage;
  383. }
  384. return NULL;
  385. }
  386. const struct z_erofs_decompressor *z_erofs_decomp[] = {
  387. [Z_EROFS_COMPRESSION_SHIFTED] = &(const struct z_erofs_decompressor) {
  388. .decompress = z_erofs_transform_plain,
  389. .name = "shifted"
  390. },
  391. [Z_EROFS_COMPRESSION_INTERLACED] = &(const struct z_erofs_decompressor) {
  392. .decompress = z_erofs_transform_plain,
  393. .name = "interlaced"
  394. },
  395. [Z_EROFS_COMPRESSION_LZ4] = &(const struct z_erofs_decompressor) {
  396. .config = z_erofs_load_lz4_config,
  397. .decompress = z_erofs_lz4_decompress,
  398. .init = z_erofs_gbuf_init,
  399. .exit = z_erofs_gbuf_exit,
  400. .name = "lz4"
  401. },
  402. #ifdef CONFIG_EROFS_FS_ZIP_LZMA
  403. [Z_EROFS_COMPRESSION_LZMA] = &z_erofs_lzma_decomp,
  404. #endif
  405. #ifdef CONFIG_EROFS_FS_ZIP_DEFLATE
  406. [Z_EROFS_COMPRESSION_DEFLATE] = &z_erofs_deflate_decomp,
  407. #endif
  408. #ifdef CONFIG_EROFS_FS_ZIP_ZSTD
  409. [Z_EROFS_COMPRESSION_ZSTD] = &z_erofs_zstd_decomp,
  410. #endif
  411. };
  412. int z_erofs_parse_cfgs(struct super_block *sb, struct erofs_super_block *dsb)
  413. {
  414. struct erofs_sb_info *sbi = EROFS_SB(sb);
  415. struct erofs_buf buf = __EROFS_BUF_INITIALIZER;
  416. unsigned long algs, alg;
  417. erofs_off_t offset;
  418. int size, ret = 0;
  419. if (!erofs_sb_has_compr_cfgs(sbi))
  420. return z_erofs_load_lz4_config(sb, dsb, NULL, 0);
  421. algs = le16_to_cpu(dsb->u1.available_compr_algs);
  422. sbi->available_compr_algs = algs;
  423. if (algs & ~Z_EROFS_ALL_COMPR_ALGS) {
  424. erofs_err(sb, "unidentified algorithms %lx, please upgrade kernel",
  425. algs & ~Z_EROFS_ALL_COMPR_ALGS);
  426. return -EOPNOTSUPP;
  427. }
  428. (void)erofs_init_metabuf(&buf, sb, false);
  429. offset = EROFS_SUPER_OFFSET + sbi->sb_size;
  430. for_each_set_bit(alg, &algs, Z_EROFS_COMPRESSION_MAX) {
  431. const struct z_erofs_decompressor *dec = z_erofs_decomp[alg];
  432. void *data;
  433. data = erofs_read_metadata(sb, &buf, &offset, &size);
  434. if (IS_ERR(data)) {
  435. ret = PTR_ERR(data);
  436. break;
  437. }
  438. if (dec && dec->config) {
  439. ret = dec->config(sb, dsb, data, size);
  440. } else {
  441. erofs_err(sb, "algorithm %ld isn't enabled on this kernel",
  442. alg);
  443. ret = -EOPNOTSUPP;
  444. }
  445. kfree(data);
  446. if (ret)
  447. break;
  448. }
  449. erofs_put_metabuf(&buf);
  450. return ret;
  451. }
  452. int __init z_erofs_init_decompressor(void)
  453. {
  454. int i, err;
  455. for (i = 0; i < Z_EROFS_COMPRESSION_MAX; ++i) {
  456. err = z_erofs_decomp[i] ? z_erofs_decomp[i]->init() : 0;
  457. if (err) {
  458. while (i--)
  459. if (z_erofs_decomp[i])
  460. z_erofs_decomp[i]->exit();
  461. return err;
  462. }
  463. }
  464. return 0;
  465. }
  466. void z_erofs_exit_decompressor(void)
  467. {
  468. int i;
  469. for (i = 0; i < Z_EROFS_COMPRESSION_MAX; ++i)
  470. if (z_erofs_decomp[i])
  471. z_erofs_decomp[i]->exit();
  472. }