0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/bio.h>
0009 #include <linux/bitmap.h>
0010 #include <linux/err.h>
0011 #include <linux/init.h>
0012 #include <linux/kernel.h>
0013 #include <linux/mm.h>
0014 #include <linux/sched/mm.h>
0015 #include <linux/pagemap.h>
0016 #include <linux/refcount.h>
0017 #include <linux/sched.h>
0018 #include <linux/slab.h>
0019 #include <linux/zstd.h>
0020 #include "misc.h"
0021 #include "compression.h"
0022 #include "ctree.h"
0023
0024 #define ZSTD_BTRFS_MAX_WINDOWLOG 17
0025 #define ZSTD_BTRFS_MAX_INPUT (1 << ZSTD_BTRFS_MAX_WINDOWLOG)
0026 #define ZSTD_BTRFS_DEFAULT_LEVEL 3
0027 #define ZSTD_BTRFS_MAX_LEVEL 15
0028
0029 #define ZSTD_BTRFS_RECLAIM_JIFFIES (307 * HZ)
0030
0031 static zstd_parameters zstd_get_btrfs_parameters(unsigned int level,
0032 size_t src_len)
0033 {
0034 zstd_parameters params = zstd_get_params(level, src_len);
0035
0036 if (params.cParams.windowLog > ZSTD_BTRFS_MAX_WINDOWLOG)
0037 params.cParams.windowLog = ZSTD_BTRFS_MAX_WINDOWLOG;
0038 WARN_ON(src_len > ZSTD_BTRFS_MAX_INPUT);
0039 return params;
0040 }
0041
0042 struct workspace {
0043 void *mem;
0044 size_t size;
0045 char *buf;
0046 unsigned int level;
0047 unsigned int req_level;
0048 unsigned long last_used;
0049 struct list_head list;
0050 struct list_head lru_list;
0051 zstd_in_buffer in_buf;
0052 zstd_out_buffer out_buf;
0053 };
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075 struct zstd_workspace_manager {
0076 const struct btrfs_compress_op *ops;
0077 spinlock_t lock;
0078 struct list_head lru_list;
0079 struct list_head idle_ws[ZSTD_BTRFS_MAX_LEVEL];
0080 unsigned long active_map;
0081 wait_queue_head_t wait;
0082 struct timer_list timer;
0083 };
0084
0085 static struct zstd_workspace_manager wsm;
0086
0087 static size_t zstd_ws_mem_sizes[ZSTD_BTRFS_MAX_LEVEL];
0088
0089 static inline struct workspace *list_to_workspace(struct list_head *list)
0090 {
0091 return container_of(list, struct workspace, list);
0092 }
0093
0094 void zstd_free_workspace(struct list_head *ws);
0095 struct list_head *zstd_alloc_workspace(unsigned int level);
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107 static void zstd_reclaim_timer_fn(struct timer_list *timer)
0108 {
0109 unsigned long reclaim_threshold = jiffies - ZSTD_BTRFS_RECLAIM_JIFFIES;
0110 struct list_head *pos, *next;
0111
0112 spin_lock(&wsm.lock);
0113
0114 if (list_empty(&wsm.lru_list)) {
0115 spin_unlock(&wsm.lock);
0116 return;
0117 }
0118
0119 list_for_each_prev_safe(pos, next, &wsm.lru_list) {
0120 struct workspace *victim = container_of(pos, struct workspace,
0121 lru_list);
0122 unsigned int level;
0123
0124 if (time_after(victim->last_used, reclaim_threshold))
0125 break;
0126
0127
0128 if (victim->req_level)
0129 continue;
0130
0131 level = victim->level;
0132 list_del(&victim->lru_list);
0133 list_del(&victim->list);
0134 zstd_free_workspace(&victim->list);
0135
0136 if (list_empty(&wsm.idle_ws[level - 1]))
0137 clear_bit(level - 1, &wsm.active_map);
0138
0139 }
0140
0141 if (!list_empty(&wsm.lru_list))
0142 mod_timer(&wsm.timer, jiffies + ZSTD_BTRFS_RECLAIM_JIFFIES);
0143
0144 spin_unlock(&wsm.lock);
0145 }
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156 static void zstd_calc_ws_mem_sizes(void)
0157 {
0158 size_t max_size = 0;
0159 unsigned int level;
0160
0161 for (level = 1; level <= ZSTD_BTRFS_MAX_LEVEL; level++) {
0162 zstd_parameters params =
0163 zstd_get_btrfs_parameters(level, ZSTD_BTRFS_MAX_INPUT);
0164 size_t level_size =
0165 max_t(size_t,
0166 zstd_cstream_workspace_bound(¶ms.cParams),
0167 zstd_dstream_workspace_bound(ZSTD_BTRFS_MAX_INPUT));
0168
0169 max_size = max_t(size_t, max_size, level_size);
0170 zstd_ws_mem_sizes[level - 1] = max_size;
0171 }
0172 }
0173
0174 void zstd_init_workspace_manager(void)
0175 {
0176 struct list_head *ws;
0177 int i;
0178
0179 zstd_calc_ws_mem_sizes();
0180
0181 wsm.ops = &btrfs_zstd_compress;
0182 spin_lock_init(&wsm.lock);
0183 init_waitqueue_head(&wsm.wait);
0184 timer_setup(&wsm.timer, zstd_reclaim_timer_fn, 0);
0185
0186 INIT_LIST_HEAD(&wsm.lru_list);
0187 for (i = 0; i < ZSTD_BTRFS_MAX_LEVEL; i++)
0188 INIT_LIST_HEAD(&wsm.idle_ws[i]);
0189
0190 ws = zstd_alloc_workspace(ZSTD_BTRFS_MAX_LEVEL);
0191 if (IS_ERR(ws)) {
0192 pr_warn(
0193 "BTRFS: cannot preallocate zstd compression workspace\n");
0194 } else {
0195 set_bit(ZSTD_BTRFS_MAX_LEVEL - 1, &wsm.active_map);
0196 list_add(ws, &wsm.idle_ws[ZSTD_BTRFS_MAX_LEVEL - 1]);
0197 }
0198 }
0199
0200 void zstd_cleanup_workspace_manager(void)
0201 {
0202 struct workspace *workspace;
0203 int i;
0204
0205 spin_lock_bh(&wsm.lock);
0206 for (i = 0; i < ZSTD_BTRFS_MAX_LEVEL; i++) {
0207 while (!list_empty(&wsm.idle_ws[i])) {
0208 workspace = container_of(wsm.idle_ws[i].next,
0209 struct workspace, list);
0210 list_del(&workspace->list);
0211 list_del(&workspace->lru_list);
0212 zstd_free_workspace(&workspace->list);
0213 }
0214 }
0215 spin_unlock_bh(&wsm.lock);
0216
0217 del_timer_sync(&wsm.timer);
0218 }
0219
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231 static struct list_head *zstd_find_workspace(unsigned int level)
0232 {
0233 struct list_head *ws;
0234 struct workspace *workspace;
0235 int i = level - 1;
0236
0237 spin_lock_bh(&wsm.lock);
0238 for_each_set_bit_from(i, &wsm.active_map, ZSTD_BTRFS_MAX_LEVEL) {
0239 if (!list_empty(&wsm.idle_ws[i])) {
0240 ws = wsm.idle_ws[i].next;
0241 workspace = list_to_workspace(ws);
0242 list_del_init(ws);
0243
0244 workspace->req_level = level;
0245 if (level == workspace->level)
0246 list_del(&workspace->lru_list);
0247 if (list_empty(&wsm.idle_ws[i]))
0248 clear_bit(i, &wsm.active_map);
0249 spin_unlock_bh(&wsm.lock);
0250 return ws;
0251 }
0252 }
0253 spin_unlock_bh(&wsm.lock);
0254
0255 return NULL;
0256 }
0257
0258
0259
0260
0261
0262
0263
0264
0265
0266
0267 struct list_head *zstd_get_workspace(unsigned int level)
0268 {
0269 struct list_head *ws;
0270 unsigned int nofs_flag;
0271
0272
0273 if (!level)
0274 level = 1;
0275
0276 again:
0277 ws = zstd_find_workspace(level);
0278 if (ws)
0279 return ws;
0280
0281 nofs_flag = memalloc_nofs_save();
0282 ws = zstd_alloc_workspace(level);
0283 memalloc_nofs_restore(nofs_flag);
0284
0285 if (IS_ERR(ws)) {
0286 DEFINE_WAIT(wait);
0287
0288 prepare_to_wait(&wsm.wait, &wait, TASK_UNINTERRUPTIBLE);
0289 schedule();
0290 finish_wait(&wsm.wait, &wait);
0291
0292 goto again;
0293 }
0294
0295 return ws;
0296 }
0297
0298
0299
0300
0301
0302
0303
0304
0305
0306
0307
0308 void zstd_put_workspace(struct list_head *ws)
0309 {
0310 struct workspace *workspace = list_to_workspace(ws);
0311
0312 spin_lock_bh(&wsm.lock);
0313
0314
0315 if (workspace->req_level == workspace->level) {
0316
0317 if (list_empty(&wsm.idle_ws[ZSTD_BTRFS_MAX_LEVEL - 1])) {
0318 INIT_LIST_HEAD(&workspace->lru_list);
0319 } else {
0320 workspace->last_used = jiffies;
0321 list_add(&workspace->lru_list, &wsm.lru_list);
0322 if (!timer_pending(&wsm.timer))
0323 mod_timer(&wsm.timer,
0324 jiffies + ZSTD_BTRFS_RECLAIM_JIFFIES);
0325 }
0326 }
0327
0328 set_bit(workspace->level - 1, &wsm.active_map);
0329 list_add(&workspace->list, &wsm.idle_ws[workspace->level - 1]);
0330 workspace->req_level = 0;
0331
0332 spin_unlock_bh(&wsm.lock);
0333
0334 if (workspace->level == ZSTD_BTRFS_MAX_LEVEL)
0335 cond_wake_up(&wsm.wait);
0336 }
0337
0338 void zstd_free_workspace(struct list_head *ws)
0339 {
0340 struct workspace *workspace = list_entry(ws, struct workspace, list);
0341
0342 kvfree(workspace->mem);
0343 kfree(workspace->buf);
0344 kfree(workspace);
0345 }
0346
0347 struct list_head *zstd_alloc_workspace(unsigned int level)
0348 {
0349 struct workspace *workspace;
0350
0351 workspace = kzalloc(sizeof(*workspace), GFP_KERNEL);
0352 if (!workspace)
0353 return ERR_PTR(-ENOMEM);
0354
0355 workspace->size = zstd_ws_mem_sizes[level - 1];
0356 workspace->level = level;
0357 workspace->req_level = level;
0358 workspace->last_used = jiffies;
0359 workspace->mem = kvmalloc(workspace->size, GFP_KERNEL);
0360 workspace->buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
0361 if (!workspace->mem || !workspace->buf)
0362 goto fail;
0363
0364 INIT_LIST_HEAD(&workspace->list);
0365 INIT_LIST_HEAD(&workspace->lru_list);
0366
0367 return &workspace->list;
0368 fail:
0369 zstd_free_workspace(&workspace->list);
0370 return ERR_PTR(-ENOMEM);
0371 }
0372
0373 int zstd_compress_pages(struct list_head *ws, struct address_space *mapping,
0374 u64 start, struct page **pages, unsigned long *out_pages,
0375 unsigned long *total_in, unsigned long *total_out)
0376 {
0377 struct workspace *workspace = list_entry(ws, struct workspace, list);
0378 zstd_cstream *stream;
0379 int ret = 0;
0380 int nr_pages = 0;
0381 struct page *in_page = NULL;
0382 struct page *out_page = NULL;
0383 unsigned long tot_in = 0;
0384 unsigned long tot_out = 0;
0385 unsigned long len = *total_out;
0386 const unsigned long nr_dest_pages = *out_pages;
0387 unsigned long max_out = nr_dest_pages * PAGE_SIZE;
0388 zstd_parameters params = zstd_get_btrfs_parameters(workspace->req_level,
0389 len);
0390
0391 *out_pages = 0;
0392 *total_out = 0;
0393 *total_in = 0;
0394
0395
0396 stream = zstd_init_cstream(¶ms, len, workspace->mem,
0397 workspace->size);
0398 if (!stream) {
0399 pr_warn("BTRFS: zstd_init_cstream failed\n");
0400 ret = -EIO;
0401 goto out;
0402 }
0403
0404
0405 in_page = find_get_page(mapping, start >> PAGE_SHIFT);
0406 workspace->in_buf.src = kmap_local_page(in_page);
0407 workspace->in_buf.pos = 0;
0408 workspace->in_buf.size = min_t(size_t, len, PAGE_SIZE);
0409
0410
0411
0412 out_page = alloc_page(GFP_NOFS);
0413 if (out_page == NULL) {
0414 ret = -ENOMEM;
0415 goto out;
0416 }
0417 pages[nr_pages++] = out_page;
0418 workspace->out_buf.dst = page_address(out_page);
0419 workspace->out_buf.pos = 0;
0420 workspace->out_buf.size = min_t(size_t, max_out, PAGE_SIZE);
0421
0422 while (1) {
0423 size_t ret2;
0424
0425 ret2 = zstd_compress_stream(stream, &workspace->out_buf,
0426 &workspace->in_buf);
0427 if (zstd_is_error(ret2)) {
0428 pr_debug("BTRFS: zstd_compress_stream returned %d\n",
0429 zstd_get_error_code(ret2));
0430 ret = -EIO;
0431 goto out;
0432 }
0433
0434
0435 if (tot_in + workspace->in_buf.pos > 8192 &&
0436 tot_in + workspace->in_buf.pos <
0437 tot_out + workspace->out_buf.pos) {
0438 ret = -E2BIG;
0439 goto out;
0440 }
0441
0442
0443 if (workspace->out_buf.pos >= max_out) {
0444 tot_out += workspace->out_buf.pos;
0445 ret = -E2BIG;
0446 goto out;
0447 }
0448
0449
0450 if (workspace->out_buf.pos == workspace->out_buf.size) {
0451 tot_out += PAGE_SIZE;
0452 max_out -= PAGE_SIZE;
0453 if (nr_pages == nr_dest_pages) {
0454 ret = -E2BIG;
0455 goto out;
0456 }
0457 out_page = alloc_page(GFP_NOFS);
0458 if (out_page == NULL) {
0459 ret = -ENOMEM;
0460 goto out;
0461 }
0462 pages[nr_pages++] = out_page;
0463 workspace->out_buf.dst = page_address(out_page);
0464 workspace->out_buf.pos = 0;
0465 workspace->out_buf.size = min_t(size_t, max_out,
0466 PAGE_SIZE);
0467 }
0468
0469
0470 if (workspace->in_buf.pos >= len) {
0471 tot_in += workspace->in_buf.pos;
0472 break;
0473 }
0474
0475
0476 if (workspace->in_buf.pos == workspace->in_buf.size) {
0477 tot_in += PAGE_SIZE;
0478 kunmap_local(workspace->in_buf.src);
0479 put_page(in_page);
0480 start += PAGE_SIZE;
0481 len -= PAGE_SIZE;
0482 in_page = find_get_page(mapping, start >> PAGE_SHIFT);
0483 workspace->in_buf.src = kmap_local_page(in_page);
0484 workspace->in_buf.pos = 0;
0485 workspace->in_buf.size = min_t(size_t, len, PAGE_SIZE);
0486 }
0487 }
0488 while (1) {
0489 size_t ret2;
0490
0491 ret2 = zstd_end_stream(stream, &workspace->out_buf);
0492 if (zstd_is_error(ret2)) {
0493 pr_debug("BTRFS: zstd_end_stream returned %d\n",
0494 zstd_get_error_code(ret2));
0495 ret = -EIO;
0496 goto out;
0497 }
0498 if (ret2 == 0) {
0499 tot_out += workspace->out_buf.pos;
0500 break;
0501 }
0502 if (workspace->out_buf.pos >= max_out) {
0503 tot_out += workspace->out_buf.pos;
0504 ret = -E2BIG;
0505 goto out;
0506 }
0507
0508 tot_out += PAGE_SIZE;
0509 max_out -= PAGE_SIZE;
0510 if (nr_pages == nr_dest_pages) {
0511 ret = -E2BIG;
0512 goto out;
0513 }
0514 out_page = alloc_page(GFP_NOFS);
0515 if (out_page == NULL) {
0516 ret = -ENOMEM;
0517 goto out;
0518 }
0519 pages[nr_pages++] = out_page;
0520 workspace->out_buf.dst = page_address(out_page);
0521 workspace->out_buf.pos = 0;
0522 workspace->out_buf.size = min_t(size_t, max_out, PAGE_SIZE);
0523 }
0524
0525 if (tot_out >= tot_in) {
0526 ret = -E2BIG;
0527 goto out;
0528 }
0529
0530 ret = 0;
0531 *total_in = tot_in;
0532 *total_out = tot_out;
0533 out:
0534 *out_pages = nr_pages;
0535 if (workspace->in_buf.src) {
0536 kunmap_local(workspace->in_buf.src);
0537 put_page(in_page);
0538 }
0539 return ret;
0540 }
0541
0542 int zstd_decompress_bio(struct list_head *ws, struct compressed_bio *cb)
0543 {
0544 struct workspace *workspace = list_entry(ws, struct workspace, list);
0545 struct page **pages_in = cb->compressed_pages;
0546 size_t srclen = cb->compressed_len;
0547 zstd_dstream *stream;
0548 int ret = 0;
0549 unsigned long page_in_index = 0;
0550 unsigned long total_pages_in = DIV_ROUND_UP(srclen, PAGE_SIZE);
0551 unsigned long buf_start;
0552 unsigned long total_out = 0;
0553
0554 stream = zstd_init_dstream(
0555 ZSTD_BTRFS_MAX_INPUT, workspace->mem, workspace->size);
0556 if (!stream) {
0557 pr_debug("BTRFS: zstd_init_dstream failed\n");
0558 ret = -EIO;
0559 goto done;
0560 }
0561
0562 workspace->in_buf.src = kmap_local_page(pages_in[page_in_index]);
0563 workspace->in_buf.pos = 0;
0564 workspace->in_buf.size = min_t(size_t, srclen, PAGE_SIZE);
0565
0566 workspace->out_buf.dst = workspace->buf;
0567 workspace->out_buf.pos = 0;
0568 workspace->out_buf.size = PAGE_SIZE;
0569
0570 while (1) {
0571 size_t ret2;
0572
0573 ret2 = zstd_decompress_stream(stream, &workspace->out_buf,
0574 &workspace->in_buf);
0575 if (zstd_is_error(ret2)) {
0576 pr_debug("BTRFS: zstd_decompress_stream returned %d\n",
0577 zstd_get_error_code(ret2));
0578 ret = -EIO;
0579 goto done;
0580 }
0581 buf_start = total_out;
0582 total_out += workspace->out_buf.pos;
0583 workspace->out_buf.pos = 0;
0584
0585 ret = btrfs_decompress_buf2page(workspace->out_buf.dst,
0586 total_out - buf_start, cb, buf_start);
0587 if (ret == 0)
0588 break;
0589
0590 if (workspace->in_buf.pos >= srclen)
0591 break;
0592
0593
0594 if (ret2 == 0)
0595 break;
0596
0597 if (workspace->in_buf.pos == workspace->in_buf.size) {
0598 kunmap_local(workspace->in_buf.src);
0599 page_in_index++;
0600 if (page_in_index >= total_pages_in) {
0601 workspace->in_buf.src = NULL;
0602 ret = -EIO;
0603 goto done;
0604 }
0605 srclen -= PAGE_SIZE;
0606 workspace->in_buf.src = kmap_local_page(pages_in[page_in_index]);
0607 workspace->in_buf.pos = 0;
0608 workspace->in_buf.size = min_t(size_t, srclen, PAGE_SIZE);
0609 }
0610 }
0611 ret = 0;
0612 zero_fill_bio(cb->orig_bio);
0613 done:
0614 if (workspace->in_buf.src)
0615 kunmap_local(workspace->in_buf.src);
0616 return ret;
0617 }
0618
0619 int zstd_decompress(struct list_head *ws, unsigned char *data_in,
0620 struct page *dest_page, unsigned long start_byte, size_t srclen,
0621 size_t destlen)
0622 {
0623 struct workspace *workspace = list_entry(ws, struct workspace, list);
0624 zstd_dstream *stream;
0625 int ret = 0;
0626 size_t ret2;
0627 unsigned long total_out = 0;
0628 unsigned long pg_offset = 0;
0629
0630 stream = zstd_init_dstream(
0631 ZSTD_BTRFS_MAX_INPUT, workspace->mem, workspace->size);
0632 if (!stream) {
0633 pr_warn("BTRFS: zstd_init_dstream failed\n");
0634 ret = -EIO;
0635 goto finish;
0636 }
0637
0638 destlen = min_t(size_t, destlen, PAGE_SIZE);
0639
0640 workspace->in_buf.src = data_in;
0641 workspace->in_buf.pos = 0;
0642 workspace->in_buf.size = srclen;
0643
0644 workspace->out_buf.dst = workspace->buf;
0645 workspace->out_buf.pos = 0;
0646 workspace->out_buf.size = PAGE_SIZE;
0647
0648 ret2 = 1;
0649 while (pg_offset < destlen
0650 && workspace->in_buf.pos < workspace->in_buf.size) {
0651 unsigned long buf_start;
0652 unsigned long buf_offset;
0653 unsigned long bytes;
0654
0655
0656 if (ret2 == 0) {
0657 pr_debug("BTRFS: zstd_decompress_stream ended early\n");
0658 ret = -EIO;
0659 goto finish;
0660 }
0661 ret2 = zstd_decompress_stream(stream, &workspace->out_buf,
0662 &workspace->in_buf);
0663 if (zstd_is_error(ret2)) {
0664 pr_debug("BTRFS: zstd_decompress_stream returned %d\n",
0665 zstd_get_error_code(ret2));
0666 ret = -EIO;
0667 goto finish;
0668 }
0669
0670 buf_start = total_out;
0671 total_out += workspace->out_buf.pos;
0672 workspace->out_buf.pos = 0;
0673
0674 if (total_out <= start_byte)
0675 continue;
0676
0677 if (total_out > start_byte && buf_start < start_byte)
0678 buf_offset = start_byte - buf_start;
0679 else
0680 buf_offset = 0;
0681
0682 bytes = min_t(unsigned long, destlen - pg_offset,
0683 workspace->out_buf.size - buf_offset);
0684
0685 memcpy_to_page(dest_page, pg_offset,
0686 workspace->out_buf.dst + buf_offset, bytes);
0687
0688 pg_offset += bytes;
0689 }
0690 ret = 0;
0691 finish:
0692 if (pg_offset < destlen) {
0693 memzero_page(dest_page, pg_offset, destlen - pg_offset);
0694 }
0695 return ret;
0696 }
0697
0698 const struct btrfs_compress_op btrfs_zstd_compress = {
0699
0700 .workspace_manager = NULL,
0701 .max_level = ZSTD_BTRFS_MAX_LEVEL,
0702 .default_level = ZSTD_BTRFS_DEFAULT_LEVEL,
0703 };