Commit 80eb4f62 authored by Gao Xiang's avatar Gao Xiang

erofs: avoid allocating DEFLATE streams before mounting

Currently, each DEFLATE stream takes one 32 KiB permanent internal
window buffer even if there is no running instance which uses DEFLATE
algorithm.

It's unexpected and wasteful on embedded devices with limited resources
and servers with hundreds of CPU cores if DEFLATE is enabled but unused.

Fixes: ffa09b3b ("erofs: DEFLATE compression support")
Cc: <stable@vger.kernel.org> # 6.6+
Reviewed-by: default avatarSandeep Dhavale <dhavale@google.com>
Signed-off-by: default avatarGao Xiang <hsiangkao@linux.alibaba.com>
Link: https://lore.kernel.org/r/20240520090106.2898681-1-hsiangkao@linux.alibaba.com
parent 5587a817
...@@ -46,39 +46,15 @@ int __init z_erofs_deflate_init(void) ...@@ -46,39 +46,15 @@ int __init z_erofs_deflate_init(void)
/* by default, use # of possible CPUs instead */ /* by default, use # of possible CPUs instead */
if (!z_erofs_deflate_nstrms) if (!z_erofs_deflate_nstrms)
z_erofs_deflate_nstrms = num_possible_cpus(); z_erofs_deflate_nstrms = num_possible_cpus();
for (; z_erofs_deflate_avail_strms < z_erofs_deflate_nstrms;
++z_erofs_deflate_avail_strms) {
struct z_erofs_deflate *strm;
strm = kzalloc(sizeof(*strm), GFP_KERNEL);
if (!strm)
goto out_failed;
/* XXX: in-kernel zlib cannot shrink windowbits currently */
strm->z.workspace = vmalloc(zlib_inflate_workspacesize());
if (!strm->z.workspace) {
kfree(strm);
goto out_failed;
}
spin_lock(&z_erofs_deflate_lock);
strm->next = z_erofs_deflate_head;
z_erofs_deflate_head = strm;
spin_unlock(&z_erofs_deflate_lock);
}
return 0; return 0;
out_failed:
erofs_err(NULL, "failed to allocate zlib workspace");
z_erofs_deflate_exit();
return -ENOMEM;
} }
int z_erofs_load_deflate_config(struct super_block *sb, int z_erofs_load_deflate_config(struct super_block *sb,
struct erofs_super_block *dsb, void *data, int size) struct erofs_super_block *dsb, void *data, int size)
{ {
struct z_erofs_deflate_cfgs *dfl = data; struct z_erofs_deflate_cfgs *dfl = data;
static DEFINE_MUTEX(deflate_resize_mutex);
static bool inited;
if (!dfl || size < sizeof(struct z_erofs_deflate_cfgs)) { if (!dfl || size < sizeof(struct z_erofs_deflate_cfgs)) {
erofs_err(sb, "invalid deflate cfgs, size=%u", size); erofs_err(sb, "invalid deflate cfgs, size=%u", size);
...@@ -89,9 +65,36 @@ int z_erofs_load_deflate_config(struct super_block *sb, ...@@ -89,9 +65,36 @@ int z_erofs_load_deflate_config(struct super_block *sb,
erofs_err(sb, "unsupported windowbits %u", dfl->windowbits); erofs_err(sb, "unsupported windowbits %u", dfl->windowbits);
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
mutex_lock(&deflate_resize_mutex);
if (!inited) {
for (; z_erofs_deflate_avail_strms < z_erofs_deflate_nstrms;
++z_erofs_deflate_avail_strms) {
struct z_erofs_deflate *strm;
strm = kzalloc(sizeof(*strm), GFP_KERNEL);
if (!strm)
goto failed;
/* XXX: in-kernel zlib cannot customize windowbits */
strm->z.workspace = vmalloc(zlib_inflate_workspacesize());
if (!strm->z.workspace) {
kfree(strm);
goto failed;
}
spin_lock(&z_erofs_deflate_lock);
strm->next = z_erofs_deflate_head;
z_erofs_deflate_head = strm;
spin_unlock(&z_erofs_deflate_lock);
}
inited = true;
}
mutex_unlock(&deflate_resize_mutex);
erofs_info(sb, "EXPERIMENTAL DEFLATE feature in use. Use at your own risk!"); erofs_info(sb, "EXPERIMENTAL DEFLATE feature in use. Use at your own risk!");
return 0; return 0;
failed:
mutex_unlock(&deflate_resize_mutex);
z_erofs_deflate_exit();
return -ENOMEM;
} }
int z_erofs_deflate_decompress(struct z_erofs_decompress_req *rq, int z_erofs_deflate_decompress(struct z_erofs_decompress_req *rq,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment