zstd.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (c) 2016-present, Facebook, Inc.
  4. * All rights reserved.
  5. *
  6. */
  7. #include <linux/bio.h>
  8. #include <linux/bitmap.h>
  9. #include <linux/err.h>
  10. #include <linux/init.h>
  11. #include <linux/kernel.h>
  12. #include <linux/mm.h>
  13. #include <linux/sched/mm.h>
  14. #include <linux/pagemap.h>
  15. #include <linux/refcount.h>
  16. #include <linux/sched.h>
  17. #include <linux/slab.h>
  18. #include <linux/zstd.h>
  19. #include "misc.h"
  20. #include "fs.h"
  21. #include "btrfs_inode.h"
  22. #include "compression.h"
  23. #include "super.h"
  24. #define ZSTD_BTRFS_MAX_WINDOWLOG 17
  25. #define ZSTD_BTRFS_MAX_INPUT (1U << ZSTD_BTRFS_MAX_WINDOWLOG)
  26. #define ZSTD_BTRFS_DEFAULT_LEVEL 3
  27. #define ZSTD_BTRFS_MAX_LEVEL 15
  28. /* 307s to avoid pathologically clashing with transaction commit */
  29. #define ZSTD_BTRFS_RECLAIM_JIFFIES (307 * HZ)
  30. static zstd_parameters zstd_get_btrfs_parameters(unsigned int level,
  31. size_t src_len)
  32. {
  33. zstd_parameters params = zstd_get_params(level, src_len);
  34. if (params.cParams.windowLog > ZSTD_BTRFS_MAX_WINDOWLOG)
  35. params.cParams.windowLog = ZSTD_BTRFS_MAX_WINDOWLOG;
  36. WARN_ON(src_len > ZSTD_BTRFS_MAX_INPUT);
  37. return params;
  38. }
  39. struct workspace {
  40. void *mem;
  41. size_t size;
  42. char *buf;
  43. unsigned int level;
  44. unsigned int req_level;
  45. unsigned long last_used; /* jiffies */
  46. struct list_head list;
  47. struct list_head lru_list;
  48. zstd_in_buffer in_buf;
  49. zstd_out_buffer out_buf;
  50. };
  51. /*
  52. * Zstd Workspace Management
  53. *
  54. * Zstd workspaces have different memory requirements depending on the level.
  55. * The zstd workspaces are managed by having individual lists for each level
  56. * and a global lru. Forward progress is maintained by protecting a max level
  57. * workspace.
  58. *
  59. * Getting a workspace is done by using the bitmap to identify the levels that
  60. * have available workspaces and scans up. This lets us recycle higher level
  61. * workspaces because of the monotonic memory guarantee. A workspace's
  62. * last_used is only updated if it is being used by the corresponding memory
  63. * level. Putting a workspace involves adding it back to the appropriate places
  64. * and adding it back to the lru if necessary.
  65. *
  66. * A timer is used to reclaim workspaces if they have not been used for
  67. * ZSTD_BTRFS_RECLAIM_JIFFIES. This helps keep only active workspaces around.
  68. * The upper bound is provided by the workqueue limit which is 2 (percpu limit).
  69. */
  70. struct zstd_workspace_manager {
  71. const struct btrfs_compress_op *ops;
  72. spinlock_t lock;
  73. struct list_head lru_list;
  74. struct list_head idle_ws[ZSTD_BTRFS_MAX_LEVEL];
  75. unsigned long active_map;
  76. wait_queue_head_t wait;
  77. struct timer_list timer;
  78. };
  79. static struct zstd_workspace_manager wsm;
  80. static size_t zstd_ws_mem_sizes[ZSTD_BTRFS_MAX_LEVEL];
  81. static inline struct workspace *list_to_workspace(struct list_head *list)
  82. {
  83. return container_of(list, struct workspace, list);
  84. }
  85. void zstd_free_workspace(struct list_head *ws);
  86. struct list_head *zstd_alloc_workspace(unsigned int level);
  87. /*
  88. * Timer callback to free unused workspaces.
  89. *
  90. * @t: timer
  91. *
  92. * This scans the lru_list and attempts to reclaim any workspace that hasn't
  93. * been used for ZSTD_BTRFS_RECLAIM_JIFFIES.
  94. *
  95. * The context is softirq and does not need the _bh locking primitives.
  96. */
  97. static void zstd_reclaim_timer_fn(struct timer_list *timer)
  98. {
  99. unsigned long reclaim_threshold = jiffies - ZSTD_BTRFS_RECLAIM_JIFFIES;
  100. struct list_head *pos, *next;
  101. spin_lock(&wsm.lock);
  102. if (list_empty(&wsm.lru_list)) {
  103. spin_unlock(&wsm.lock);
  104. return;
  105. }
  106. list_for_each_prev_safe(pos, next, &wsm.lru_list) {
  107. struct workspace *victim = container_of(pos, struct workspace,
  108. lru_list);
  109. unsigned int level;
  110. if (time_after(victim->last_used, reclaim_threshold))
  111. break;
  112. /* workspace is in use */
  113. if (victim->req_level)
  114. continue;
  115. level = victim->level;
  116. list_del(&victim->lru_list);
  117. list_del(&victim->list);
  118. zstd_free_workspace(&victim->list);
  119. if (list_empty(&wsm.idle_ws[level - 1]))
  120. clear_bit(level - 1, &wsm.active_map);
  121. }
  122. if (!list_empty(&wsm.lru_list))
  123. mod_timer(&wsm.timer, jiffies + ZSTD_BTRFS_RECLAIM_JIFFIES);
  124. spin_unlock(&wsm.lock);
  125. }
  126. /*
  127. * Calculate monotonic memory bounds.
  128. *
  129. * It is possible based on the level configurations that a higher level
  130. * workspace uses less memory than a lower level workspace. In order to reuse
  131. * workspaces, this must be made a monotonic relationship. This precomputes
  132. * the required memory for each level and enforces the monotonicity between
  133. * level and memory required.
  134. */
  135. static void zstd_calc_ws_mem_sizes(void)
  136. {
  137. size_t max_size = 0;
  138. unsigned int level;
  139. for (level = 1; level <= ZSTD_BTRFS_MAX_LEVEL; level++) {
  140. zstd_parameters params =
  141. zstd_get_btrfs_parameters(level, ZSTD_BTRFS_MAX_INPUT);
  142. size_t level_size =
  143. max_t(size_t,
  144. zstd_cstream_workspace_bound(&params.cParams),
  145. zstd_dstream_workspace_bound(ZSTD_BTRFS_MAX_INPUT));
  146. max_size = max_t(size_t, max_size, level_size);
  147. zstd_ws_mem_sizes[level - 1] = max_size;
  148. }
  149. }
  150. void zstd_init_workspace_manager(void)
  151. {
  152. struct list_head *ws;
  153. int i;
  154. zstd_calc_ws_mem_sizes();
  155. wsm.ops = &btrfs_zstd_compress;
  156. spin_lock_init(&wsm.lock);
  157. init_waitqueue_head(&wsm.wait);
  158. timer_setup(&wsm.timer, zstd_reclaim_timer_fn, 0);
  159. INIT_LIST_HEAD(&wsm.lru_list);
  160. for (i = 0; i < ZSTD_BTRFS_MAX_LEVEL; i++)
  161. INIT_LIST_HEAD(&wsm.idle_ws[i]);
  162. ws = zstd_alloc_workspace(ZSTD_BTRFS_MAX_LEVEL);
  163. if (IS_ERR(ws)) {
  164. pr_warn(
  165. "BTRFS: cannot preallocate zstd compression workspace\n");
  166. } else {
  167. set_bit(ZSTD_BTRFS_MAX_LEVEL - 1, &wsm.active_map);
  168. list_add(ws, &wsm.idle_ws[ZSTD_BTRFS_MAX_LEVEL - 1]);
  169. }
  170. }
  171. void zstd_cleanup_workspace_manager(void)
  172. {
  173. struct workspace *workspace;
  174. int i;
  175. spin_lock_bh(&wsm.lock);
  176. for (i = 0; i < ZSTD_BTRFS_MAX_LEVEL; i++) {
  177. while (!list_empty(&wsm.idle_ws[i])) {
  178. workspace = container_of(wsm.idle_ws[i].next,
  179. struct workspace, list);
  180. list_del(&workspace->list);
  181. list_del(&workspace->lru_list);
  182. zstd_free_workspace(&workspace->list);
  183. }
  184. }
  185. spin_unlock_bh(&wsm.lock);
  186. del_timer_sync(&wsm.timer);
  187. }
  188. /*
  189. * Find workspace for given level.
  190. *
  191. * @level: compression level
  192. *
  193. * This iterates over the set bits in the active_map beginning at the requested
  194. * compression level. This lets us utilize already allocated workspaces before
  195. * allocating a new one. If the workspace is of a larger size, it is used, but
  196. * the place in the lru_list and last_used times are not updated. This is to
  197. * offer the opportunity to reclaim the workspace in favor of allocating an
  198. * appropriately sized one in the future.
  199. */
  200. static struct list_head *zstd_find_workspace(unsigned int level)
  201. {
  202. struct list_head *ws;
  203. struct workspace *workspace;
  204. int i = level - 1;
  205. spin_lock_bh(&wsm.lock);
  206. for_each_set_bit_from(i, &wsm.active_map, ZSTD_BTRFS_MAX_LEVEL) {
  207. if (!list_empty(&wsm.idle_ws[i])) {
  208. ws = wsm.idle_ws[i].next;
  209. workspace = list_to_workspace(ws);
  210. list_del_init(ws);
  211. /* keep its place if it's a lower level using this */
  212. workspace->req_level = level;
  213. if (level == workspace->level)
  214. list_del(&workspace->lru_list);
  215. if (list_empty(&wsm.idle_ws[i]))
  216. clear_bit(i, &wsm.active_map);
  217. spin_unlock_bh(&wsm.lock);
  218. return ws;
  219. }
  220. }
  221. spin_unlock_bh(&wsm.lock);
  222. return NULL;
  223. }
  224. /*
  225. * Zstd get_workspace for level.
  226. *
  227. * @level: compression level
  228. *
  229. * If @level is 0, then any compression level can be used. Therefore, we begin
  230. * scanning from 1. We first scan through possible workspaces and then after
  231. * attempt to allocate a new workspace. If we fail to allocate one due to
  232. * memory pressure, go to sleep waiting for the max level workspace to free up.
  233. */
  234. struct list_head *zstd_get_workspace(unsigned int level)
  235. {
  236. struct list_head *ws;
  237. unsigned int nofs_flag;
  238. /* level == 0 means we can use any workspace */
  239. if (!level)
  240. level = 1;
  241. again:
  242. ws = zstd_find_workspace(level);
  243. if (ws)
  244. return ws;
  245. nofs_flag = memalloc_nofs_save();
  246. ws = zstd_alloc_workspace(level);
  247. memalloc_nofs_restore(nofs_flag);
  248. if (IS_ERR(ws)) {
  249. DEFINE_WAIT(wait);
  250. prepare_to_wait(&wsm.wait, &wait, TASK_UNINTERRUPTIBLE);
  251. schedule();
  252. finish_wait(&wsm.wait, &wait);
  253. goto again;
  254. }
  255. return ws;
  256. }
  257. /*
  258. * Zstd put_workspace.
  259. *
  260. * @ws: list_head for the workspace
  261. *
  262. * When putting back a workspace, we only need to update the LRU if we are of
  263. * the requested compression level. Here is where we continue to protect the
  264. * max level workspace or update last_used accordingly. If the reclaim timer
  265. * isn't set, it is also set here. Only the max level workspace tries and wakes
  266. * up waiting workspaces.
  267. */
  268. void zstd_put_workspace(struct list_head *ws)
  269. {
  270. struct workspace *workspace = list_to_workspace(ws);
  271. spin_lock_bh(&wsm.lock);
  272. /* A node is only taken off the lru if we are the corresponding level */
  273. if (workspace->req_level == workspace->level) {
  274. /* Hide a max level workspace from reclaim */
  275. if (list_empty(&wsm.idle_ws[ZSTD_BTRFS_MAX_LEVEL - 1])) {
  276. INIT_LIST_HEAD(&workspace->lru_list);
  277. } else {
  278. workspace->last_used = jiffies;
  279. list_add(&workspace->lru_list, &wsm.lru_list);
  280. if (!timer_pending(&wsm.timer))
  281. mod_timer(&wsm.timer,
  282. jiffies + ZSTD_BTRFS_RECLAIM_JIFFIES);
  283. }
  284. }
  285. set_bit(workspace->level - 1, &wsm.active_map);
  286. list_add(&workspace->list, &wsm.idle_ws[workspace->level - 1]);
  287. workspace->req_level = 0;
  288. spin_unlock_bh(&wsm.lock);
  289. if (workspace->level == ZSTD_BTRFS_MAX_LEVEL)
  290. cond_wake_up(&wsm.wait);
  291. }
  292. void zstd_free_workspace(struct list_head *ws)
  293. {
  294. struct workspace *workspace = list_entry(ws, struct workspace, list);
  295. kvfree(workspace->mem);
  296. kfree(workspace->buf);
  297. kfree(workspace);
  298. }
  299. struct list_head *zstd_alloc_workspace(unsigned int level)
  300. {
  301. struct workspace *workspace;
  302. workspace = kzalloc(sizeof(*workspace), GFP_KERNEL);
  303. if (!workspace)
  304. return ERR_PTR(-ENOMEM);
  305. workspace->size = zstd_ws_mem_sizes[level - 1];
  306. workspace->level = level;
  307. workspace->req_level = level;
  308. workspace->last_used = jiffies;
  309. workspace->mem = kvmalloc(workspace->size, GFP_KERNEL | __GFP_NOWARN);
  310. workspace->buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
  311. if (!workspace->mem || !workspace->buf)
  312. goto fail;
  313. INIT_LIST_HEAD(&workspace->list);
  314. INIT_LIST_HEAD(&workspace->lru_list);
  315. return &workspace->list;
  316. fail:
  317. zstd_free_workspace(&workspace->list);
  318. return ERR_PTR(-ENOMEM);
  319. }
  320. int zstd_compress_folios(struct list_head *ws, struct address_space *mapping,
  321. u64 start, struct folio **folios, unsigned long *out_folios,
  322. unsigned long *total_in, unsigned long *total_out)
  323. {
  324. struct workspace *workspace = list_entry(ws, struct workspace, list);
  325. zstd_cstream *stream;
  326. int ret = 0;
  327. int nr_folios = 0;
  328. struct folio *in_folio = NULL; /* The current folio to read. */
  329. struct folio *out_folio = NULL; /* The current folio to write to. */
  330. unsigned long tot_in = 0;
  331. unsigned long tot_out = 0;
  332. unsigned long len = *total_out;
  333. const unsigned long nr_dest_folios = *out_folios;
  334. const u64 orig_end = start + len;
  335. unsigned long max_out = nr_dest_folios * PAGE_SIZE;
  336. unsigned int pg_off;
  337. unsigned int cur_len;
  338. zstd_parameters params = zstd_get_btrfs_parameters(workspace->req_level,
  339. len);
  340. *out_folios = 0;
  341. *total_out = 0;
  342. *total_in = 0;
  343. /* Initialize the stream */
  344. stream = zstd_init_cstream(&params, len, workspace->mem,
  345. workspace->size);
  346. if (unlikely(!stream)) {
  347. struct btrfs_inode *inode = BTRFS_I(mapping->host);
  348. btrfs_err(inode->root->fs_info,
  349. "zstd compression init level %d failed, root %llu inode %llu offset %llu",
  350. workspace->req_level, btrfs_root_id(inode->root),
  351. btrfs_ino(inode), start);
  352. ret = -EIO;
  353. goto out;
  354. }
  355. /* map in the first page of input data */
  356. ret = btrfs_compress_filemap_get_folio(mapping, start, &in_folio);
  357. if (ret < 0)
  358. goto out;
  359. pg_off = offset_in_page(start);
  360. cur_len = btrfs_calc_input_length(orig_end, start);
  361. workspace->in_buf.src = kmap_local_folio(in_folio, pg_off);
  362. workspace->in_buf.pos = 0;
  363. workspace->in_buf.size = cur_len;
  364. /* Allocate and map in the output buffer */
  365. out_folio = btrfs_alloc_compr_folio();
  366. if (out_folio == NULL) {
  367. ret = -ENOMEM;
  368. goto out;
  369. }
  370. folios[nr_folios++] = out_folio;
  371. workspace->out_buf.dst = folio_address(out_folio);
  372. workspace->out_buf.pos = 0;
  373. workspace->out_buf.size = min_t(size_t, max_out, PAGE_SIZE);
  374. while (1) {
  375. size_t ret2;
  376. ret2 = zstd_compress_stream(stream, &workspace->out_buf,
  377. &workspace->in_buf);
  378. if (unlikely(zstd_is_error(ret2))) {
  379. struct btrfs_inode *inode = BTRFS_I(mapping->host);
  380. btrfs_warn(inode->root->fs_info,
  381. "zstd compression level %d failed, error %d root %llu inode %llu offset %llu",
  382. workspace->req_level, zstd_get_error_code(ret2),
  383. btrfs_root_id(inode->root), btrfs_ino(inode),
  384. start);
  385. ret = -EIO;
  386. goto out;
  387. }
  388. /* Check to see if we are making it bigger */
  389. if (tot_in + workspace->in_buf.pos > 8192 &&
  390. tot_in + workspace->in_buf.pos <
  391. tot_out + workspace->out_buf.pos) {
  392. ret = -E2BIG;
  393. goto out;
  394. }
  395. /* We've reached the end of our output range */
  396. if (workspace->out_buf.pos >= max_out) {
  397. tot_out += workspace->out_buf.pos;
  398. ret = -E2BIG;
  399. goto out;
  400. }
  401. /* Check if we need more output space */
  402. if (workspace->out_buf.pos == workspace->out_buf.size) {
  403. tot_out += PAGE_SIZE;
  404. max_out -= PAGE_SIZE;
  405. if (nr_folios == nr_dest_folios) {
  406. ret = -E2BIG;
  407. goto out;
  408. }
  409. out_folio = btrfs_alloc_compr_folio();
  410. if (out_folio == NULL) {
  411. ret = -ENOMEM;
  412. goto out;
  413. }
  414. folios[nr_folios++] = out_folio;
  415. workspace->out_buf.dst = folio_address(out_folio);
  416. workspace->out_buf.pos = 0;
  417. workspace->out_buf.size = min_t(size_t, max_out,
  418. PAGE_SIZE);
  419. }
  420. /* We've reached the end of the input */
  421. if (workspace->in_buf.pos >= len) {
  422. tot_in += workspace->in_buf.pos;
  423. break;
  424. }
  425. /* Check if we need more input */
  426. if (workspace->in_buf.pos == workspace->in_buf.size) {
  427. tot_in += PAGE_SIZE;
  428. kunmap_local(workspace->in_buf.src);
  429. workspace->in_buf.src = NULL;
  430. folio_put(in_folio);
  431. start += cur_len;
  432. len -= cur_len;
  433. ret = btrfs_compress_filemap_get_folio(mapping, start, &in_folio);
  434. if (ret < 0)
  435. goto out;
  436. pg_off = offset_in_page(start);
  437. cur_len = btrfs_calc_input_length(orig_end, start);
  438. workspace->in_buf.src = kmap_local_folio(in_folio, pg_off);
  439. workspace->in_buf.pos = 0;
  440. workspace->in_buf.size = cur_len;
  441. }
  442. }
  443. while (1) {
  444. size_t ret2;
  445. ret2 = zstd_end_stream(stream, &workspace->out_buf);
  446. if (unlikely(zstd_is_error(ret2))) {
  447. struct btrfs_inode *inode = BTRFS_I(mapping->host);
  448. btrfs_err(inode->root->fs_info,
  449. "zstd compression end level %d failed, error %d root %llu inode %llu offset %llu",
  450. workspace->req_level, zstd_get_error_code(ret2),
  451. btrfs_root_id(inode->root), btrfs_ino(inode),
  452. start);
  453. ret = -EIO;
  454. goto out;
  455. }
  456. if (ret2 == 0) {
  457. tot_out += workspace->out_buf.pos;
  458. break;
  459. }
  460. if (workspace->out_buf.pos >= max_out) {
  461. tot_out += workspace->out_buf.pos;
  462. ret = -E2BIG;
  463. goto out;
  464. }
  465. tot_out += PAGE_SIZE;
  466. max_out -= PAGE_SIZE;
  467. if (nr_folios == nr_dest_folios) {
  468. ret = -E2BIG;
  469. goto out;
  470. }
  471. out_folio = btrfs_alloc_compr_folio();
  472. if (out_folio == NULL) {
  473. ret = -ENOMEM;
  474. goto out;
  475. }
  476. folios[nr_folios++] = out_folio;
  477. workspace->out_buf.dst = folio_address(out_folio);
  478. workspace->out_buf.pos = 0;
  479. workspace->out_buf.size = min_t(size_t, max_out, PAGE_SIZE);
  480. }
  481. if (tot_out >= tot_in) {
  482. ret = -E2BIG;
  483. goto out;
  484. }
  485. ret = 0;
  486. *total_in = tot_in;
  487. *total_out = tot_out;
  488. out:
  489. *out_folios = nr_folios;
  490. if (workspace->in_buf.src) {
  491. kunmap_local(workspace->in_buf.src);
  492. folio_put(in_folio);
  493. }
  494. return ret;
  495. }
  496. int zstd_decompress_bio(struct list_head *ws, struct compressed_bio *cb)
  497. {
  498. struct workspace *workspace = list_entry(ws, struct workspace, list);
  499. struct folio **folios_in = cb->compressed_folios;
  500. size_t srclen = cb->compressed_len;
  501. zstd_dstream *stream;
  502. int ret = 0;
  503. unsigned long folio_in_index = 0;
  504. unsigned long total_folios_in = DIV_ROUND_UP(srclen, PAGE_SIZE);
  505. unsigned long buf_start;
  506. unsigned long total_out = 0;
  507. stream = zstd_init_dstream(
  508. ZSTD_BTRFS_MAX_INPUT, workspace->mem, workspace->size);
  509. if (unlikely(!stream)) {
  510. struct btrfs_inode *inode = cb->bbio.inode;
  511. btrfs_err(inode->root->fs_info,
  512. "zstd decompression init failed, root %llu inode %llu offset %llu",
  513. btrfs_root_id(inode->root), btrfs_ino(inode), cb->start);
  514. ret = -EIO;
  515. goto done;
  516. }
  517. workspace->in_buf.src = kmap_local_folio(folios_in[folio_in_index], 0);
  518. workspace->in_buf.pos = 0;
  519. workspace->in_buf.size = min_t(size_t, srclen, PAGE_SIZE);
  520. workspace->out_buf.dst = workspace->buf;
  521. workspace->out_buf.pos = 0;
  522. workspace->out_buf.size = PAGE_SIZE;
  523. while (1) {
  524. size_t ret2;
  525. ret2 = zstd_decompress_stream(stream, &workspace->out_buf,
  526. &workspace->in_buf);
  527. if (unlikely(zstd_is_error(ret2))) {
  528. struct btrfs_inode *inode = cb->bbio.inode;
  529. btrfs_err(inode->root->fs_info,
  530. "zstd decompression failed, error %d root %llu inode %llu offset %llu",
  531. zstd_get_error_code(ret2), btrfs_root_id(inode->root),
  532. btrfs_ino(inode), cb->start);
  533. ret = -EIO;
  534. goto done;
  535. }
  536. buf_start = total_out;
  537. total_out += workspace->out_buf.pos;
  538. workspace->out_buf.pos = 0;
  539. ret = btrfs_decompress_buf2page(workspace->out_buf.dst,
  540. total_out - buf_start, cb, buf_start);
  541. if (ret == 0)
  542. break;
  543. if (workspace->in_buf.pos >= srclen)
  544. break;
  545. /* Check if we've hit the end of a frame */
  546. if (ret2 == 0)
  547. break;
  548. if (workspace->in_buf.pos == workspace->in_buf.size) {
  549. kunmap_local(workspace->in_buf.src);
  550. folio_in_index++;
  551. if (folio_in_index >= total_folios_in) {
  552. workspace->in_buf.src = NULL;
  553. ret = -EIO;
  554. goto done;
  555. }
  556. srclen -= PAGE_SIZE;
  557. workspace->in_buf.src =
  558. kmap_local_folio(folios_in[folio_in_index], 0);
  559. workspace->in_buf.pos = 0;
  560. workspace->in_buf.size = min_t(size_t, srclen, PAGE_SIZE);
  561. }
  562. }
  563. ret = 0;
  564. done:
  565. if (workspace->in_buf.src)
  566. kunmap_local(workspace->in_buf.src);
  567. return ret;
  568. }
  569. int zstd_decompress(struct list_head *ws, const u8 *data_in,
  570. struct folio *dest_folio, unsigned long dest_pgoff, size_t srclen,
  571. size_t destlen)
  572. {
  573. struct workspace *workspace = list_entry(ws, struct workspace, list);
  574. struct btrfs_fs_info *fs_info = btrfs_sb(folio_inode(dest_folio)->i_sb);
  575. const u32 sectorsize = fs_info->sectorsize;
  576. zstd_dstream *stream;
  577. int ret = 0;
  578. unsigned long to_copy = 0;
  579. stream = zstd_init_dstream(
  580. ZSTD_BTRFS_MAX_INPUT, workspace->mem, workspace->size);
  581. if (unlikely(!stream)) {
  582. struct btrfs_inode *inode = folio_to_inode(dest_folio);
  583. btrfs_err(inode->root->fs_info,
  584. "zstd decompression init failed, root %llu inode %llu offset %llu",
  585. btrfs_root_id(inode->root), btrfs_ino(inode),
  586. folio_pos(dest_folio));
  587. ret = -EIO;
  588. goto finish;
  589. }
  590. workspace->in_buf.src = data_in;
  591. workspace->in_buf.pos = 0;
  592. workspace->in_buf.size = srclen;
  593. workspace->out_buf.dst = workspace->buf;
  594. workspace->out_buf.pos = 0;
  595. workspace->out_buf.size = sectorsize;
  596. /*
  597. * Since both input and output buffers should not exceed one sector,
  598. * one call should end the decompression.
  599. */
  600. ret = zstd_decompress_stream(stream, &workspace->out_buf, &workspace->in_buf);
  601. if (unlikely(zstd_is_error(ret))) {
  602. struct btrfs_inode *inode = folio_to_inode(dest_folio);
  603. btrfs_err(inode->root->fs_info,
  604. "zstd decompression failed, error %d root %llu inode %llu offset %llu",
  605. zstd_get_error_code(ret), btrfs_root_id(inode->root),
  606. btrfs_ino(inode), folio_pos(dest_folio));
  607. goto finish;
  608. }
  609. to_copy = workspace->out_buf.pos;
  610. memcpy_to_folio(dest_folio, dest_pgoff, workspace->out_buf.dst, to_copy);
  611. finish:
  612. /* Error or early end. */
  613. if (unlikely(to_copy < destlen)) {
  614. ret = -EIO;
  615. folio_zero_range(dest_folio, dest_pgoff + to_copy, destlen - to_copy);
  616. }
  617. return ret;
  618. }
  619. const struct btrfs_compress_op btrfs_zstd_compress = {
  620. /* ZSTD uses own workspace manager */
  621. .workspace_manager = NULL,
  622. .max_level = ZSTD_BTRFS_MAX_LEVEL,
  623. .default_level = ZSTD_BTRFS_DEFAULT_LEVEL,
  624. };