Skip to content

Commit 4589682

Browse files
adam900710kdave
authored andcommitted
btrfs: reduce compression workspace buffer space to block size
Currently the compression workspace buffer size is always based on PAGE_SIZE, but btrfs has support subpage sized block size for some time. This means for one-shot compression algorithm like lzo, we're wasting quite some memory if the block size is smaller than page size, as the LZO only works on one block (thus one-shot). On 64K page sized systems with 4K block size, it means we only need at most 8K buffer space for lzo, but in reality we're allocating 64K buffer. So to reduce the memory usage, change all workspace buffer to base its size based on block size other than page size. Signed-off-by: Qu Wenruo <[email protected]> Reviewed-by: David Sterba <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent 83a5db6 commit 4589682

File tree

3 files changed

+20
-11
lines changed

3 files changed

+20
-11
lines changed

fs/btrfs/lzo.c

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -58,16 +58,22 @@
5858
* 0x1000 | SegHdr N+1| Data payload N+1 ... |
5959
*/
6060

61-
#define WORKSPACE_BUF_LENGTH (lzo1x_worst_compress(PAGE_SIZE))
62-
#define WORKSPACE_CBUF_LENGTH (lzo1x_worst_compress(PAGE_SIZE))
63-
6461
struct workspace {
6562
void *mem;
6663
void *buf; /* where decompressed data goes */
6764
void *cbuf; /* where compressed data goes */
6865
struct list_head list;
6966
};
7067

68+
static u32 workspace_buf_length(const struct btrfs_fs_info *fs_info)
69+
{
70+
return lzo1x_worst_compress(fs_info->sectorsize);
71+
}
72+
static u32 workspace_cbuf_length(const struct btrfs_fs_info *fs_info)
73+
{
74+
return lzo1x_worst_compress(fs_info->sectorsize);
75+
}
76+
7177
void lzo_free_workspace(struct list_head *ws)
7278
{
7379
struct workspace *workspace = list_entry(ws, struct workspace, list);
@@ -87,8 +93,8 @@ struct list_head *lzo_alloc_workspace(struct btrfs_fs_info *fs_info)
8793
return ERR_PTR(-ENOMEM);
8894

8995
workspace->mem = kvmalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL | __GFP_NOWARN);
90-
workspace->buf = kvmalloc(WORKSPACE_BUF_LENGTH, GFP_KERNEL | __GFP_NOWARN);
91-
workspace->cbuf = kvmalloc(WORKSPACE_CBUF_LENGTH, GFP_KERNEL | __GFP_NOWARN);
96+
workspace->buf = kvmalloc(workspace_buf_length(fs_info), GFP_KERNEL | __GFP_NOWARN);
97+
workspace->cbuf = kvmalloc(workspace_cbuf_length(fs_info), GFP_KERNEL | __GFP_NOWARN);
9298
if (!workspace->mem || !workspace->buf || !workspace->cbuf)
9399
goto fail;
94100

@@ -384,7 +390,7 @@ int lzo_decompress_bio(struct list_head *ws, struct compressed_bio *cb)
384390
kunmap_local(kaddr);
385391
cur_in += LZO_LEN;
386392

387-
if (unlikely(seg_len > WORKSPACE_CBUF_LENGTH)) {
393+
if (unlikely(seg_len > workspace_cbuf_length(fs_info))) {
388394
struct btrfs_inode *inode = cb->bbio.inode;
389395

390396
/*
@@ -444,7 +450,7 @@ int lzo_decompress(struct list_head *ws, const u8 *data_in,
444450
const u32 sectorsize = fs_info->sectorsize;
445451
size_t in_len;
446452
size_t out_len;
447-
size_t max_segment_len = WORKSPACE_BUF_LENGTH;
453+
size_t max_segment_len = workspace_buf_length(fs_info);
448454
int ret = 0;
449455

450456
if (srclen < LZO_LEN || srclen > max_segment_len + LZO_LEN * 2)

fs/btrfs/zlib.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ void zlib_free_workspace(struct list_head *ws)
5555

5656
struct list_head *zlib_alloc_workspace(struct btrfs_fs_info *fs_info, unsigned int level)
5757
{
58+
const u32 blocksize = fs_info->sectorsize;
5859
struct workspace *workspace;
5960
int workspacesize;
6061

@@ -78,8 +79,8 @@ struct list_head *zlib_alloc_workspace(struct btrfs_fs_info *fs_info, unsigned i
7879
workspace->buf_size = ZLIB_DFLTCC_BUF_SIZE;
7980
}
8081
if (!workspace->buf) {
81-
workspace->buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
82-
workspace->buf_size = PAGE_SIZE;
82+
workspace->buf = kmalloc(blocksize, GFP_KERNEL);
83+
workspace->buf_size = blocksize;
8384
}
8485
if (!workspace->strm.workspace || !workspace->buf)
8586
goto fail;

fs/btrfs/zstd.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,7 @@ void zstd_free_workspace(struct list_head *ws)
370370

371371
struct list_head *zstd_alloc_workspace(struct btrfs_fs_info *fs_info, int level)
372372
{
373+
const u32 blocksize = fs_info->sectorsize;
373374
struct workspace *workspace;
374375

375376
workspace = kzalloc(sizeof(*workspace), GFP_KERNEL);
@@ -382,7 +383,7 @@ struct list_head *zstd_alloc_workspace(struct btrfs_fs_info *fs_info, int level)
382383
workspace->req_level = level;
383384
workspace->last_used = jiffies;
384385
workspace->mem = kvmalloc(workspace->size, GFP_KERNEL | __GFP_NOWARN);
385-
workspace->buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
386+
workspace->buf = kmalloc(blocksize, GFP_KERNEL);
386387
if (!workspace->mem || !workspace->buf)
387388
goto fail;
388389

@@ -590,6 +591,7 @@ int zstd_decompress_bio(struct list_head *ws, struct compressed_bio *cb)
590591
size_t srclen = cb->compressed_len;
591592
zstd_dstream *stream;
592593
int ret = 0;
594+
const u32 blocksize = cb_to_fs_info(cb)->sectorsize;
593595
unsigned long folio_in_index = 0;
594596
unsigned long total_folios_in = DIV_ROUND_UP(srclen, PAGE_SIZE);
595597
unsigned long buf_start;
@@ -613,7 +615,7 @@ int zstd_decompress_bio(struct list_head *ws, struct compressed_bio *cb)
613615

614616
workspace->out_buf.dst = workspace->buf;
615617
workspace->out_buf.pos = 0;
616-
workspace->out_buf.size = PAGE_SIZE;
618+
workspace->out_buf.size = blocksize;
617619

618620
while (1) {
619621
size_t ret2;

0 commit comments

Comments
 (0)