aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/fs/btrfs/compression.c
diff options
context:
space:
mode:
authorQu Wenruo <wqu@suse.com>2025-08-13 16:36:57 +0930
committerDavid Sterba <dsterba@suse.com>2025-09-23 08:49:15 +0200
commit6f9c3f48acffaffe7bb643b3bc04f8a99021179a (patch)
treefd8468dddbb574c7eebd6e58a7e3391567be66e8 /fs/btrfs/compression.c
parentbtrfs: add workspace manager initialization for zstd (diff)
downloadwireguard-linux-6f9c3f48acffaffe7bb643b3bc04f8a99021179a.tar.xz
wireguard-linux-6f9c3f48acffaffe7bb643b3bc04f8a99021179a.zip
btrfs: add generic workspace manager initialization
This involves: - Add (alloc|free)_workspace_manager helpers. These are the helper to alloc/free workspace_manager structure. The allocator will allocate a workspace_manager structure, initialize it, and pre-allocate one workspace for it. The freer will do the cleanup and set the manager pointer to NULL. - Call alloc_workspace_manager() inside btrfs_alloc_compress_wsm() - Call alloc_workspace_manager() inside btrfs_free_compress_wsm() For none, zlib and lzo compression algorithms. For now the generic per-fs workspace managers won't really have any effect, and all compression is still going through the global workspace manager. Signed-off-by: Qu Wenruo <wqu@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
Diffstat (limited to 'fs/btrfs/compression.c')
-rw-r--r--fs/btrfs/compression.c66
1 files changed, 66 insertions, 0 deletions
diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c
index d019a00055fd..26c632f0a20c 100644
--- a/fs/btrfs/compression.c
+++ b/fs/btrfs/compression.c
@@ -773,6 +773,40 @@ static void free_workspace(int type, struct list_head *ws)
}
}
+static int alloc_workspace_manager(struct btrfs_fs_info *fs_info,
+ enum btrfs_compression_type type)
+{
+ struct workspace_manager *gwsm;
+ struct list_head *workspace;
+
+ ASSERT(fs_info->compr_wsm[type] == NULL);
+ gwsm = kzalloc(sizeof(*gwsm), GFP_KERNEL);
+ if (!gwsm)
+ return -ENOMEM;
+
+ INIT_LIST_HEAD(&gwsm->idle_ws);
+ spin_lock_init(&gwsm->ws_lock);
+ atomic_set(&gwsm->total_ws, 0);
+ init_waitqueue_head(&gwsm->ws_wait);
+ fs_info->compr_wsm[type] = gwsm;
+
+ /*
+ * Preallocate one workspace for each compression type so we can
+ * guarantee forward progress in the worst case
+ */
+ workspace = alloc_workspace(fs_info, type, 0);
+ if (IS_ERR(workspace)) {
+ btrfs_warn(fs_info,
+ "cannot preallocate compression workspace for %s, will try later",
+ btrfs_compress_type2str(type));
+ } else {
+ atomic_set(&gwsm->total_ws, 1);
+ gwsm->free_ws = 1;
+ list_add(workspace, &gwsm->idle_ws);
+ }
+ return 0;
+}
+
static void btrfs_init_workspace_manager(struct btrfs_fs_info *fs_info, int type)
{
struct workspace_manager *wsm;
@@ -799,6 +833,26 @@ static void btrfs_init_workspace_manager(struct btrfs_fs_info *fs_info, int type
}
}
+static void free_workspace_manager(struct btrfs_fs_info *fs_info,
+ enum btrfs_compression_type type)
+{
+ struct list_head *ws;
+ struct workspace_manager *gwsm = fs_info->compr_wsm[type];
+
+ /* ZSTD uses its own workspace manager, should enter here. */
+ ASSERT(type != BTRFS_COMPRESS_ZSTD && type < BTRFS_NR_COMPRESS_TYPES);
+ if (!gwsm)
+ return;
+ fs_info->compr_wsm[type] = NULL;
+ while (!list_empty(&gwsm->idle_ws)) {
+ ws = gwsm->idle_ws.next;
+ list_del(ws);
+ free_workspace(type, ws);
+ atomic_dec(&gwsm->total_ws);
+ }
+ kfree(gwsm);
+}
+
static void btrfs_cleanup_workspace_manager(int type)
{
struct workspace_manager *wsman;
@@ -1101,6 +1155,15 @@ int btrfs_alloc_compress_wsm(struct btrfs_fs_info *fs_info)
{
int ret;
+ ret = alloc_workspace_manager(fs_info, BTRFS_COMPRESS_NONE);
+ if (ret < 0)
+ goto error;
+ ret = alloc_workspace_manager(fs_info, BTRFS_COMPRESS_ZLIB);
+ if (ret < 0)
+ goto error;
+ ret = alloc_workspace_manager(fs_info, BTRFS_COMPRESS_LZO);
+ if (ret < 0)
+ goto error;
ret = zstd_alloc_workspace_manager(fs_info);
if (ret < 0)
goto error;
@@ -1112,6 +1175,9 @@ error:
void btrfs_free_compress_wsm(struct btrfs_fs_info *fs_info)
{
+ free_workspace_manager(fs_info, BTRFS_COMPRESS_NONE);
+ free_workspace_manager(fs_info, BTRFS_COMPRESS_ZLIB);
+ free_workspace_manager(fs_info, BTRFS_COMPRESS_LZO);
zstd_free_workspace_manager(fs_info);
}