summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorQu Wenruo <wqu@suse.com>2026-01-29 13:53:43 +1030
committerDavid Sterba <dsterba@suse.com>2026-02-03 07:59:07 +0100
commit26902be0cd0997b34ef13593e35ef3501a3c70b5 (patch)
treef5f2406556d37e0e2422729dc066d2f19fe5775b
parent6f706f34fc4cc0ce180c293f9e793302fa00e4d8 (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.c70
-rw-r--r--fs/btrfs/compression.h12
-rw-r--r--fs/btrfs/inode.c2
-rw-r--r--fs/btrfs/lzo.c188
-rw-r--r--fs/btrfs/zlib.c189
-rw-r--r--fs/btrfs/zstd.c189
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;