|
20 | 20 | #include "misc.h"
|
21 | 21 | #include "compression.h"
|
22 | 22 | #include "ctree.h"
|
| 23 | +#include "super.h" |
23 | 24 |
|
24 | 25 | #define ZSTD_BTRFS_MAX_WINDOWLOG 17
|
25 | 26 | #define ZSTD_BTRFS_MAX_INPUT (1 << ZSTD_BTRFS_MAX_WINDOWLOG)
|
@@ -618,80 +619,48 @@ int zstd_decompress_bio(struct list_head *ws, struct compressed_bio *cb)
|
618 | 619 | }
|
619 | 620 |
|
620 | 621 | int zstd_decompress(struct list_head *ws, const u8 *data_in,
|
621 |
| - struct page *dest_page, unsigned long start_byte, size_t srclen, |
| 622 | + struct page *dest_page, unsigned long dest_pgoff, size_t srclen, |
622 | 623 | size_t destlen)
|
623 | 624 | {
|
624 | 625 | struct workspace *workspace = list_entry(ws, struct workspace, list);
|
| 626 | + struct btrfs_fs_info *fs_info = btrfs_sb(dest_page->mapping->host->i_sb); |
| 627 | + const u32 sectorsize = fs_info->sectorsize; |
625 | 628 | zstd_dstream *stream;
|
626 | 629 | int ret = 0;
|
627 |
| - size_t ret2; |
628 |
| - unsigned long total_out = 0; |
629 |
| - unsigned long pg_offset = 0; |
| 630 | + unsigned long to_copy = 0; |
630 | 631 |
|
631 | 632 | stream = zstd_init_dstream(
|
632 | 633 | ZSTD_BTRFS_MAX_INPUT, workspace->mem, workspace->size);
|
633 | 634 | if (!stream) {
|
634 | 635 | pr_warn("BTRFS: zstd_init_dstream failed\n");
|
635 |
| - ret = -EIO; |
636 | 636 | goto finish;
|
637 | 637 | }
|
638 | 638 |
|
639 |
| - destlen = min_t(size_t, destlen, PAGE_SIZE); |
640 |
| - |
641 | 639 | workspace->in_buf.src = data_in;
|
642 | 640 | workspace->in_buf.pos = 0;
|
643 | 641 | workspace->in_buf.size = srclen;
|
644 | 642 |
|
645 | 643 | workspace->out_buf.dst = workspace->buf;
|
646 | 644 | workspace->out_buf.pos = 0;
|
647 |
| - workspace->out_buf.size = PAGE_SIZE; |
648 |
| - |
649 |
| - ret2 = 1; |
650 |
| - while (pg_offset < destlen |
651 |
| - && workspace->in_buf.pos < workspace->in_buf.size) { |
652 |
| - unsigned long buf_start; |
653 |
| - unsigned long buf_offset; |
654 |
| - unsigned long bytes; |
655 |
| - |
656 |
| - /* Check if the frame is over and we still need more input */ |
657 |
| - if (ret2 == 0) { |
658 |
| - pr_debug("BTRFS: zstd_decompress_stream ended early\n"); |
659 |
| - ret = -EIO; |
660 |
| - goto finish; |
661 |
| - } |
662 |
| - ret2 = zstd_decompress_stream(stream, &workspace->out_buf, |
663 |
| - &workspace->in_buf); |
664 |
| - if (zstd_is_error(ret2)) { |
665 |
| - pr_debug("BTRFS: zstd_decompress_stream returned %d\n", |
666 |
| - zstd_get_error_code(ret2)); |
667 |
| - ret = -EIO; |
668 |
| - goto finish; |
669 |
| - } |
670 |
| - |
671 |
| - buf_start = total_out; |
672 |
| - total_out += workspace->out_buf.pos; |
673 |
| - workspace->out_buf.pos = 0; |
674 |
| - |
675 |
| - if (total_out <= start_byte) |
676 |
| - continue; |
677 |
| - |
678 |
| - if (total_out > start_byte && buf_start < start_byte) |
679 |
| - buf_offset = start_byte - buf_start; |
680 |
| - else |
681 |
| - buf_offset = 0; |
682 |
| - |
683 |
| - bytes = min_t(unsigned long, destlen - pg_offset, |
684 |
| - workspace->out_buf.size - buf_offset); |
685 |
| - |
686 |
| - memcpy_to_page(dest_page, pg_offset, |
687 |
| - workspace->out_buf.dst + buf_offset, bytes); |
688 |
| - |
689 |
| - pg_offset += bytes; |
| 645 | + workspace->out_buf.size = sectorsize; |
| 646 | + |
| 647 | + /* |
| 648 | + * Since both input and output buffers should not exceed one sector, |
| 649 | + * one call should end the decompression. |
| 650 | + */ |
| 651 | + ret = zstd_decompress_stream(stream, &workspace->out_buf, &workspace->in_buf); |
| 652 | + if (zstd_is_error(ret)) { |
| 653 | + pr_warn_ratelimited("BTRFS: zstd_decompress_stream return %d\n", |
| 654 | + zstd_get_error_code(ret)); |
| 655 | + goto finish; |
690 | 656 | }
|
691 |
| - ret = 0; |
| 657 | + to_copy = workspace->out_buf.pos; |
| 658 | + memcpy_to_page(dest_page, dest_pgoff + to_copy, workspace->out_buf.dst, to_copy); |
692 | 659 | finish:
|
693 |
| - if (pg_offset < destlen) { |
694 |
| - memzero_page(dest_page, pg_offset, destlen - pg_offset); |
| 660 | + /* Error or early end. */ |
| 661 | + if (unlikely(to_copy < destlen)) { |
| 662 | + ret = -EIO; |
| 663 | + memzero_page(dest_page, dest_pgoff + to_copy, destlen - to_copy); |
695 | 664 | }
|
696 | 665 | return ret;
|
697 | 666 | }
|
|
0 commit comments