diff options
| author | Qu Wenruo <wqu@suse.com> | 2026-01-29 13:53:43 +1030 |
|---|---|---|
| committer | David Sterba <dsterba@suse.com> | 2026-02-03 07:59:07 +0100 |
| commit | 26902be0cd0997b34ef13593e35ef3501a3c70b5 (patch) | |
| tree | f5f2406556d37e0e2422729dc066d2f19fe5775b | |
| parent | 6f706f34fc4cc0ce180c293f9e793302fa00e4d8 (diff) | |
btrfs: remove the old btrfs_compress_folios() infrastructure
Since it's been replaced by btrfs_compress_bio(), remove all involved
functions.
Reviewed-by: Boris Burkov <boris@bur.io>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
| -rw-r--r-- | fs/btrfs/compression.c | 70 | ||||
| -rw-r--r-- | fs/btrfs/compression.h | 12 | ||||
| -rw-r--r-- | fs/btrfs/inode.c | 2 | ||||
| -rw-r--r-- | fs/btrfs/lzo.c | 188 | ||||
| -rw-r--r-- | fs/btrfs/zlib.c | 189 | ||||
| -rw-r--r-- | fs/btrfs/zstd.c | 189 |
6 files changed, 1 insertions, 649 deletions
diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c index 83d6103eb788..875e0d2bcb5d 100644 --- a/fs/btrfs/compression.c +++ b/fs/btrfs/compression.c @@ -86,37 +86,6 @@ bool btrfs_compress_is_valid_type(const char *str, size_t len) return false; } -static int compression_compress_pages(int type, struct list_head *ws, - struct btrfs_inode *inode, u64 start, - struct folio **folios, unsigned long *out_folios, - unsigned long *total_in, unsigned long *total_out) -{ - switch (type) { - case BTRFS_COMPRESS_ZLIB: - return zlib_compress_folios(ws, inode, start, folios, - out_folios, total_in, total_out); - case BTRFS_COMPRESS_LZO: - return lzo_compress_folios(ws, inode, start, folios, - out_folios, total_in, total_out); - case BTRFS_COMPRESS_ZSTD: - return zstd_compress_folios(ws, inode, start, folios, - out_folios, total_in, total_out); - case BTRFS_COMPRESS_NONE: - default: - /* - * This can happen when compression races with remount setting - * it to 'no compress', while caller doesn't call - * inode_need_compress() to check if we really need to - * compress. - * - * Not a big deal, just need to inform caller that we - * haven't allocated any pages yet. - */ - *out_folios = 0; - return -E2BIG; - } -} - static int compression_decompress_bio(struct list_head *ws, struct compressed_bio *cb) { @@ -1024,45 +993,6 @@ int btrfs_compress_filemap_get_folio(struct address_space *mapping, u64 start, } /* - * Given an address space and start and length, compress the bytes into @pages - * that are allocated on demand. - * - * @type_level is encoded algorithm and level, where level 0 means whatever - * default the algorithm chooses and is opaque here; - * - compression algo are 0-3 - * - the level are bits 4-7 - * - * @out_folios is an in/out parameter, holds maximum number of folios to allocate - * and returns number of actually allocated folios - * - * @total_in is used to return the number of bytes actually read. It - * may be smaller than the input length if we had to exit early because we - * ran out of room in the folios array or because we cross the - * max_out threshold. - * - * @total_out is an in/out parameter, must be set to the input length and will - * be also used to return the total number of compressed bytes - */ -int btrfs_compress_folios(unsigned int type, int level, struct btrfs_inode *inode, - u64 start, struct folio **folios, unsigned long *out_folios, - unsigned long *total_in, unsigned long *total_out) -{ - struct btrfs_fs_info *fs_info = inode->root->fs_info; - const unsigned long orig_len = *total_out; - struct list_head *workspace; - int ret; - - level = btrfs_compress_set_level(type, level); - workspace = get_workspace(fs_info, type, level); - ret = compression_compress_pages(type, workspace, inode, start, folios, - out_folios, total_in, total_out); - /* The total read-in bytes should be no larger than the input. */ - ASSERT(*total_in <= orig_len); - put_workspace(fs_info, type, workspace); - return ret; -} - -/* * Given an address space and start and length, compress the page cache * contents into @cb. * diff --git a/fs/btrfs/compression.h b/fs/btrfs/compression.h index fd0cce5d07cf..7dc48e556313 100644 --- a/fs/btrfs/compression.h +++ b/fs/btrfs/compression.h @@ -91,9 +91,6 @@ int __init btrfs_init_compress(void); void __cold btrfs_exit_compress(void); bool btrfs_compress_level_valid(unsigned int type, int level); -int btrfs_compress_folios(unsigned int type, int level, struct btrfs_inode *inode, - u64 start, struct folio **folios, unsigned long *out_folios, - unsigned long *total_in, unsigned long *total_out); int btrfs_decompress(int type, const u8 *data_in, struct folio *dest_folio, unsigned long dest_pgoff, size_t srclen, size_t destlen); int btrfs_decompress_buf2page(const char *buf, u32 buf_len, @@ -160,9 +157,6 @@ static inline void cleanup_compressed_bio(struct compressed_bio *cb) bio_put(bio); } -int zlib_compress_folios(struct list_head *ws, struct btrfs_inode *inode, - u64 start, struct folio **folios, unsigned long *out_folios, - unsigned long *total_in, unsigned long *total_out); int zlib_compress_bio(struct list_head *ws, struct compressed_bio *cb); int zlib_decompress_bio(struct list_head *ws, struct compressed_bio *cb); int zlib_decompress(struct list_head *ws, const u8 *data_in, @@ -172,9 +166,6 @@ struct list_head *zlib_alloc_workspace(struct btrfs_fs_info *fs_info, unsigned i void zlib_free_workspace(struct list_head *ws); struct list_head *zlib_get_workspace(struct btrfs_fs_info *fs_info, unsigned int level); -int lzo_compress_folios(struct list_head *ws, struct btrfs_inode *inode, - u64 start, struct folio **folios, unsigned long *out_folios, - unsigned long *total_in, unsigned long *total_out); int lzo_compress_bio(struct list_head *ws, struct compressed_bio *cb); int lzo_decompress_bio(struct list_head *ws, struct compressed_bio *cb); int lzo_decompress(struct list_head *ws, const u8 *data_in, @@ -183,9 +174,6 @@ int lzo_decompress(struct list_head *ws, const u8 *data_in, struct list_head *lzo_alloc_workspace(struct btrfs_fs_info *fs_info); void lzo_free_workspace(struct list_head *ws); -int zstd_compress_folios(struct list_head *ws, struct btrfs_inode *inode, - u64 start, struct folio **folios, unsigned long *out_folios, - unsigned long *total_in, unsigned long *total_out); int zstd_compress_bio(struct list_head *ws, struct compressed_bio *cb); int zstd_decompress_bio(struct list_head *ws, struct compressed_bio *cb); int zstd_decompress(struct list_head *ws, const u8 *data_in, diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 61b5eef7feb6..279e04892288 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -966,7 +966,7 @@ static void compress_file_range(struct btrfs_work *work) /* * All the folios should have been locked thus no failure. * - * And even if some folios are missing, btrfs_compress_folios() + * And even if some folios are missing, btrfs_compress_bio() * would handle them correctly, so here just do an ASSERT() check for * early logic errors. */ diff --git a/fs/btrfs/lzo.c b/fs/btrfs/lzo.c index 96e408add9b8..8e20497afffe 100644 --- a/fs/btrfs/lzo.c +++ b/fs/btrfs/lzo.c @@ -123,98 +123,6 @@ static inline size_t read_compress_length(const char *buf) } /* - * Will do: - * - * - Write a segment header into the destination - * - Copy the compressed buffer into the destination - * - Make sure we have enough space in the last sector to fit a segment header - * If not, we will pad at most (LZO_LEN (4)) - 1 bytes of zeros. - * - * Will allocate new pages when needed. - */ -static int copy_compressed_data_to_page(struct btrfs_fs_info *fs_info, - char *compressed_data, - size_t compressed_size, - struct folio **out_folios, - unsigned long max_nr_folio, - u32 *cur_out) -{ - const u32 sectorsize = fs_info->sectorsize; - const u32 min_folio_shift = PAGE_SHIFT + fs_info->block_min_order; - u32 sector_bytes_left; - u32 orig_out; - struct folio *cur_folio; - char *kaddr; - - if ((*cur_out >> min_folio_shift) >= max_nr_folio) - return -E2BIG; - - /* - * We never allow a segment header crossing sector boundary, previous - * run should ensure we have enough space left inside the sector. - */ - ASSERT((*cur_out / sectorsize) == (*cur_out + LZO_LEN - 1) / sectorsize); - - cur_folio = out_folios[*cur_out >> min_folio_shift]; - /* Allocate a new page */ - if (!cur_folio) { - cur_folio = btrfs_alloc_compr_folio(fs_info); - if (!cur_folio) - return -ENOMEM; - out_folios[*cur_out >> min_folio_shift] = cur_folio; - } - - kaddr = kmap_local_folio(cur_folio, offset_in_folio(cur_folio, *cur_out)); - write_compress_length(kaddr, compressed_size); - *cur_out += LZO_LEN; - - orig_out = *cur_out; - - /* Copy compressed data */ - while (*cur_out - orig_out < compressed_size) { - u32 copy_len = min_t(u32, sectorsize - *cur_out % sectorsize, - orig_out + compressed_size - *cur_out); - - kunmap_local(kaddr); - - if ((*cur_out >> min_folio_shift) >= max_nr_folio) - return -E2BIG; - - cur_folio = out_folios[*cur_out >> min_folio_shift]; - /* Allocate a new page */ - if (!cur_folio) { - cur_folio = btrfs_alloc_compr_folio(fs_info); - if (!cur_folio) - return -ENOMEM; - out_folios[*cur_out >> min_folio_shift] = cur_folio; - } - kaddr = kmap_local_folio(cur_folio, 0); - - memcpy(kaddr + offset_in_folio(cur_folio, *cur_out), - compressed_data + *cur_out - orig_out, copy_len); - - *cur_out += copy_len; - } - - /* - * Check if we can fit the next segment header into the remaining space - * of the sector. - */ - sector_bytes_left = round_up(*cur_out, sectorsize) - *cur_out; - if (sector_bytes_left >= LZO_LEN || sector_bytes_left == 0) - goto out; - - /* The remaining size is not enough, pad it with zeros */ - memset(kaddr + offset_in_page(*cur_out), 0, - sector_bytes_left); - *cur_out += sector_bytes_left; - -out: - kunmap_local(kaddr); - return 0; -} - -/* * Write data into @out_folio and queue it into @out_bio. * * Return 0 if everything is fine and @total_out will be increased. @@ -365,102 +273,6 @@ static int copy_compressed_data_to_bio(struct btrfs_fs_info *fs_info, return write_and_queue_folio(out_bio, out_folio, total_out, sector_bytes_left); } -int lzo_compress_folios(struct list_head *ws, struct btrfs_inode *inode, - u64 start, struct folio **folios, unsigned long *out_folios, - unsigned long *total_in, unsigned long *total_out) -{ - struct btrfs_fs_info *fs_info = inode->root->fs_info; - struct workspace *workspace = list_entry(ws, struct workspace, list); - const u32 sectorsize = fs_info->sectorsize; - const u32 min_folio_size = btrfs_min_folio_size(fs_info); - struct address_space *mapping = inode->vfs_inode.i_mapping; - struct folio *folio_in = NULL; - char *sizes_ptr; - const unsigned long max_nr_folio = *out_folios; - int ret = 0; - /* Points to the file offset of input data */ - u64 cur_in = start; - /* Points to the current output byte */ - u32 cur_out = 0; - u32 len = *total_out; - - ASSERT(max_nr_folio > 0); - *out_folios = 0; - *total_out = 0; - *total_in = 0; - - /* - * Skip the header for now, we will later come back and write the total - * compressed size - */ - cur_out += LZO_LEN; - while (cur_in < start + len) { - char *data_in; - const u32 sectorsize_mask = sectorsize - 1; - u32 sector_off = (cur_in - start) & sectorsize_mask; - u32 in_len; - size_t out_len; - - /* Get the input page first */ - if (!folio_in) { - ret = btrfs_compress_filemap_get_folio(mapping, cur_in, &folio_in); - if (ret < 0) - goto out; - } - - /* Compress at most one sector of data each time */ - in_len = min_t(u32, start + len - cur_in, sectorsize - sector_off); - ASSERT(in_len); - data_in = kmap_local_folio(folio_in, offset_in_folio(folio_in, cur_in)); - ret = lzo1x_1_compress(data_in, in_len, - workspace->cbuf, &out_len, - workspace->mem); - kunmap_local(data_in); - if (unlikely(ret < 0)) { - /* lzo1x_1_compress never fails. */ - ret = -EIO; - goto out; - } - - ret = copy_compressed_data_to_page(fs_info, workspace->cbuf, out_len, - folios, max_nr_folio, - &cur_out); - if (ret < 0) - goto out; - - cur_in += in_len; - - /* - * Check if we're making it bigger after two sectors. And if - * it is so, give up. - */ - if (cur_in - start > sectorsize * 2 && cur_in - start < cur_out) { - ret = -E2BIG; - goto out; - } - - /* Check if we have reached folio boundary. */ - if (IS_ALIGNED(cur_in, min_folio_size)) { - folio_put(folio_in); - folio_in = NULL; - } - } - - /* Store the size of all chunks of compressed data */ - sizes_ptr = kmap_local_folio(folios[0], 0); - write_compress_length(sizes_ptr, cur_out); - kunmap_local(sizes_ptr); - - ret = 0; - *total_out = cur_out; - *total_in = cur_in - start; -out: - if (folio_in) - folio_put(folio_in); - *out_folios = DIV_ROUND_UP(cur_out, min_folio_size); - return ret; -} - int lzo_compress_bio(struct list_head *ws, struct compressed_bio *cb) { struct btrfs_inode *inode = cb->bbio.inode; diff --git a/fs/btrfs/zlib.c b/fs/btrfs/zlib.c index fa463e0e8527..0a8fcee16428 100644 --- a/fs/btrfs/zlib.c +++ b/fs/btrfs/zlib.c @@ -145,195 +145,6 @@ static int copy_data_into_buffer(struct address_space *mapping, return 0; } -int zlib_compress_folios(struct list_head *ws, struct btrfs_inode *inode, - u64 start, struct folio **folios, unsigned long *out_folios, - unsigned long *total_in, unsigned long *total_out) -{ - struct btrfs_fs_info *fs_info = inode->root->fs_info; - struct workspace *workspace = list_entry(ws, struct workspace, list); - struct address_space *mapping = inode->vfs_inode.i_mapping; - const u32 min_folio_shift = PAGE_SHIFT + fs_info->block_min_order; - const u32 min_folio_size = btrfs_min_folio_size(fs_info); - int ret; - char *data_in = NULL; - char *cfolio_out; - int nr_folios = 0; - struct folio *in_folio = NULL; - struct folio *out_folio = NULL; - unsigned long len = *total_out; - unsigned long nr_dest_folios = *out_folios; - const unsigned long max_out = nr_dest_folios << min_folio_shift; - const u32 blocksize = fs_info->sectorsize; - const u64 orig_end = start + len; - - *out_folios = 0; - *total_out = 0; - *total_in = 0; - - ret = zlib_deflateInit(&workspace->strm, workspace->level); - if (unlikely(ret != Z_OK)) { - btrfs_err(fs_info, - "zlib compression init failed, error %d root %llu inode %llu offset %llu", - ret, btrfs_root_id(inode->root), btrfs_ino(inode), start); - ret = -EIO; - goto out; - } - - workspace->strm.total_in = 0; - workspace->strm.total_out = 0; - - out_folio = btrfs_alloc_compr_folio(fs_info); - if (out_folio == NULL) { - ret = -ENOMEM; - goto out; - } - cfolio_out = folio_address(out_folio); - folios[0] = out_folio; - nr_folios = 1; - - workspace->strm.next_in = workspace->buf; - workspace->strm.avail_in = 0; - workspace->strm.next_out = cfolio_out; - workspace->strm.avail_out = min_folio_size; - - while (workspace->strm.total_in < len) { - /* - * Get next input pages and copy the contents to - * the workspace buffer if required. - */ - if (workspace->strm.avail_in == 0) { - unsigned long bytes_left = len - workspace->strm.total_in; - unsigned int copy_length = min(bytes_left, workspace->buf_size); - - /* - * For s390 hardware accelerated zlib, and our folio is smaller - * than the copy_length, we need to fill the buffer so that - * we can take full advantage of hardware acceleration. - */ - if (need_special_buffer(fs_info)) { - ret = copy_data_into_buffer(mapping, workspace, - start, copy_length); - if (ret < 0) - goto out; - start += copy_length; - workspace->strm.next_in = workspace->buf; - workspace->strm.avail_in = copy_length; - } else { - unsigned int cur_len; - - if (data_in) { - kunmap_local(data_in); - folio_put(in_folio); - data_in = NULL; - } - ret = btrfs_compress_filemap_get_folio(mapping, - start, &in_folio); - if (ret < 0) - goto out; - cur_len = btrfs_calc_input_length(in_folio, orig_end, start); - data_in = kmap_local_folio(in_folio, - offset_in_folio(in_folio, start)); - start += cur_len; - workspace->strm.next_in = data_in; - workspace->strm.avail_in = cur_len; - } - } - - ret = zlib_deflate(&workspace->strm, Z_SYNC_FLUSH); - if (unlikely(ret != Z_OK)) { - btrfs_warn(fs_info, - "zlib compression failed, error %d root %llu inode %llu offset %llu", - ret, btrfs_root_id(inode->root), btrfs_ino(inode), - start); - zlib_deflateEnd(&workspace->strm); - ret = -EIO; - goto out; - } - - /* we're making it bigger, give up */ - if (workspace->strm.total_in > blocksize * 2 && - workspace->strm.total_in < - workspace->strm.total_out) { - ret = -E2BIG; - goto out; - } - /* we need another page for writing out. Test this - * before the total_in so we will pull in a new page for - * the stream end if required - */ - if (workspace->strm.avail_out == 0) { - if (nr_folios == nr_dest_folios) { - ret = -E2BIG; - goto out; - } - out_folio = btrfs_alloc_compr_folio(fs_info); - if (out_folio == NULL) { - ret = -ENOMEM; - goto out; - } - cfolio_out = folio_address(out_folio); - folios[nr_folios] = out_folio; - nr_folios++; - workspace->strm.avail_out = min_folio_size; - workspace->strm.next_out = cfolio_out; - } - /* we're all done */ - if (workspace->strm.total_in >= len) - break; - if (workspace->strm.total_out > max_out) - break; - } - workspace->strm.avail_in = 0; - /* - * Call deflate with Z_FINISH flush parameter providing more output - * space but no more input data, until it returns with Z_STREAM_END. - */ - while (ret != Z_STREAM_END) { - ret = zlib_deflate(&workspace->strm, Z_FINISH); - if (ret == Z_STREAM_END) - break; - if (unlikely(ret != Z_OK && ret != Z_BUF_ERROR)) { - zlib_deflateEnd(&workspace->strm); - ret = -EIO; - goto out; - } else if (workspace->strm.avail_out == 0) { - /* Get another folio for the stream end. */ - if (nr_folios == nr_dest_folios) { - ret = -E2BIG; - goto out; - } - out_folio = btrfs_alloc_compr_folio(fs_info); - if (out_folio == NULL) { - ret = -ENOMEM; - goto out; - } - cfolio_out = folio_address(out_folio); - folios[nr_folios] = out_folio; - nr_folios++; - workspace->strm.avail_out = min_folio_size; - workspace->strm.next_out = cfolio_out; - } - } - zlib_deflateEnd(&workspace->strm); - - if (workspace->strm.total_out >= workspace->strm.total_in) { - ret = -E2BIG; - goto out; - } - - ret = 0; - *total_out = workspace->strm.total_out; - *total_in = workspace->strm.total_in; -out: - *out_folios = nr_folios; - if (data_in) { - kunmap_local(data_in); - folio_put(in_folio); - } - - return ret; -} - int zlib_compress_bio(struct list_head *ws, struct compressed_bio *cb) { struct btrfs_inode *inode = cb->bbio.inode; diff --git a/fs/btrfs/zstd.c b/fs/btrfs/zstd.c index 135b0b32579f..32fd7f5454d3 100644 --- a/fs/btrfs/zstd.c +++ b/fs/btrfs/zstd.c @@ -396,195 +396,6 @@ fail: return ERR_PTR(-ENOMEM); } -int zstd_compress_folios(struct list_head *ws, struct btrfs_inode *inode, - u64 start, struct folio **folios, unsigned long *out_folios, - unsigned long *total_in, unsigned long *total_out) -{ - struct btrfs_fs_info *fs_info = inode->root->fs_info; - struct workspace *workspace = list_entry(ws, struct workspace, list); - struct address_space *mapping = inode->vfs_inode.i_mapping; - zstd_cstream *stream; - int ret = 0; - int nr_folios = 0; - struct folio *in_folio = NULL; /* The current folio to read. */ - struct folio *out_folio = NULL; /* The current folio to write to. */ - unsigned long tot_in = 0; - unsigned long tot_out = 0; - unsigned long len = *total_out; - const unsigned long nr_dest_folios = *out_folios; - const u64 orig_end = start + len; - const u32 blocksize = fs_info->sectorsize; - const u32 min_folio_size = btrfs_min_folio_size(fs_info); - unsigned long max_out = nr_dest_folios * min_folio_size; - unsigned int cur_len; - - workspace->params = zstd_get_btrfs_parameters(workspace->req_level, len); - *out_folios = 0; - *total_out = 0; - *total_in = 0; - - /* Initialize the stream */ - stream = zstd_init_cstream(&workspace->params, len, workspace->mem, - workspace->size); - if (unlikely(!stream)) { - btrfs_err(fs_info, - "zstd compression init level %d failed, root %llu inode %llu offset %llu", - workspace->req_level, btrfs_root_id(inode->root), - btrfs_ino(inode), start); - ret = -EIO; - goto out; - } - - /* map in the first page of input data */ - ret = btrfs_compress_filemap_get_folio(mapping, start, &in_folio); - if (ret < 0) - goto out; - cur_len = btrfs_calc_input_length(in_folio, orig_end, start); - workspace->in_buf.src = kmap_local_folio(in_folio, offset_in_folio(in_folio, start)); - workspace->in_buf.pos = 0; - workspace->in_buf.size = cur_len; - - /* Allocate and map in the output buffer */ - out_folio = btrfs_alloc_compr_folio(fs_info); - if (out_folio == NULL) { - ret = -ENOMEM; - goto out; - } - folios[nr_folios++] = out_folio; - workspace->out_buf.dst = folio_address(out_folio); - workspace->out_buf.pos = 0; - workspace->out_buf.size = min_t(size_t, max_out, min_folio_size); - - while (1) { - size_t ret2; - - ret2 = zstd_compress_stream(stream, &workspace->out_buf, - &workspace->in_buf); - if (unlikely(zstd_is_error(ret2))) { - btrfs_warn(fs_info, -"zstd compression level %d failed, error %d root %llu inode %llu offset %llu", - workspace->req_level, zstd_get_error_code(ret2), - btrfs_root_id(inode->root), btrfs_ino(inode), - start); - ret = -EIO; - goto out; - } - - /* Check to see if we are making it bigger */ - if (tot_in + workspace->in_buf.pos > blocksize * 2 && - tot_in + workspace->in_buf.pos < - tot_out + workspace->out_buf.pos) { - ret = -E2BIG; - goto out; - } - - /* We've reached the end of our output range */ - if (workspace->out_buf.pos >= max_out) { - tot_out += workspace->out_buf.pos; - ret = -E2BIG; - goto out; - } - - /* Check if we need more output space */ - if (workspace->out_buf.pos == workspace->out_buf.size) { - tot_out += min_folio_size; - max_out -= min_folio_size; - if (nr_folios == nr_dest_folios) { - ret = -E2BIG; - goto out; - } - out_folio = btrfs_alloc_compr_folio(fs_info); - if (out_folio == NULL) { - ret = -ENOMEM; - goto out; - } - folios[nr_folios++] = out_folio; - workspace->out_buf.dst = folio_address(out_folio); - workspace->out_buf.pos = 0; - workspace->out_buf.size = min_t(size_t, max_out, min_folio_size); - } - - /* We've reached the end of the input */ - if (workspace->in_buf.pos >= len) { - tot_in += workspace->in_buf.pos; - break; - } - - /* Check if we need more input */ - if (workspace->in_buf.pos == workspace->in_buf.size) { - tot_in += workspace->in_buf.size; - kunmap_local(workspace->in_buf.src); - workspace->in_buf.src = NULL; - folio_put(in_folio); - start += cur_len; - len -= cur_len; - ret = btrfs_compress_filemap_get_folio(mapping, start, &in_folio); - if (ret < 0) - goto out; - cur_len = btrfs_calc_input_length(in_folio, orig_end, start); - workspace->in_buf.src = kmap_local_folio(in_folio, - offset_in_folio(in_folio, start)); - workspace->in_buf.pos = 0; - workspace->in_buf.size = cur_len; - } - } - while (1) { - size_t ret2; - - ret2 = zstd_end_stream(stream, &workspace->out_buf); - if (unlikely(zstd_is_error(ret2))) { - btrfs_err(fs_info, -"zstd compression end level %d failed, error %d root %llu inode %llu offset %llu", - workspace->req_level, zstd_get_error_code(ret2), - btrfs_root_id(inode->root), btrfs_ino(inode), - start); - ret = -EIO; - goto out; - } - if (ret2 == 0) { - tot_out += workspace->out_buf.pos; - break; - } - if (workspace->out_buf.pos >= max_out) { - tot_out += workspace->out_buf.pos; - ret = -E2BIG; - goto out; - } - - tot_out += min_folio_size; - max_out -= min_folio_size; - if (nr_folios == nr_dest_folios) { - ret = -E2BIG; - goto out; - } - out_folio = btrfs_alloc_compr_folio(fs_info); - if (out_folio == NULL) { - ret = -ENOMEM; - goto out; - } - folios[nr_folios++] = out_folio; - workspace->out_buf.dst = folio_address(out_folio); - workspace->out_buf.pos = 0; - workspace->out_buf.size = min_t(size_t, max_out, min_folio_size); - } - - if (tot_out >= tot_in) { - ret = -E2BIG; - goto out; - } - - ret = 0; - *total_in = tot_in; - *total_out = tot_out; -out: - *out_folios = nr_folios; - if (workspace->in_buf.src) { - kunmap_local(workspace->in_buf.src); - folio_put(in_folio); - } - return ret; -} - int zstd_compress_bio(struct list_head *ws, struct compressed_bio *cb) { struct btrfs_inode *inode = cb->bbio.inode; |
