mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-02-17 16:00:38 -05:00
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>
This commit is contained in:
@@ -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 @@ int btrfs_alloc_compress_wsm(struct btrfs_fs_info *fs_info)
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user