lkml.org 
[lkml]   [2019]   [Feb]   [4]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 11/12] btrfs: make zstd memory requirements monotonic
    Date
    It is possible based on the level configurations that a higher level
    workspace uses less memory than a lower level workspace. In order to
    reuse workspaces, this must be made a monotonic relationship. This
    precomputes the required memory for each level and enforces the
    monotonicity between level and memory required. This is also done
    in upstream zstd in [1].

    [1] https://github.com/facebook/zstd/commit/a68b76afefec6876f8e8a538155109a5aeac0143

    Signed-off-by: Dennis Zhou <dennis@kernel.org>
    Cc: Nick Terrell <terrelln@fb.com>
    ---
    fs/btrfs/zstd.c | 38 +++++++++++++++++++++++++++++++++-----
    1 file changed, 33 insertions(+), 5 deletions(-)

    diff --git a/fs/btrfs/zstd.c b/fs/btrfs/zstd.c
    index a951d4fe77f7..2231123fedbe 100644
    --- a/fs/btrfs/zstd.c
    +++ b/fs/btrfs/zstd.c
    @@ -20,6 +20,7 @@
    #define ZSTD_BTRFS_MAX_WINDOWLOG 17
    #define ZSTD_BTRFS_MAX_INPUT (1 << ZSTD_BTRFS_MAX_WINDOWLOG)
    #define ZSTD_BTRFS_DEFAULT_LEVEL 3
    +#define ZSTD_BTRFS_MAX_LEVEL 15

    static ZSTD_parameters zstd_get_btrfs_parameters(unsigned int level,
    size_t src_len)
    @@ -44,8 +45,39 @@ struct workspace {

    static struct workspace_manager wsm;

    +static size_t zstd_ws_mem_sizes[ZSTD_BTRFS_MAX_LEVEL];
    +
    +/*
    + * zstd_calc_ws_mem_sizes - calculate monotonic memory bounds
    + *
    + * It is possible based on the level configurations that a higher level
    + * workspace uses less memory than a lower level workspace. In order to
    + * reuse workspaces, this must be made a monotonic relationship. This
    + * precomputes the required memory for each level and enforces the
    + * monotonicity between level and memory required.
    + */
    +static void zstd_calc_ws_mem_sizes(void)
    +{
    + size_t max_size = 0;
    + unsigned int level;
    +
    + for (level = 1; level <= ZSTD_BTRFS_MAX_LEVEL; level++) {
    + ZSTD_parameters params =
    + zstd_get_btrfs_parameters(level, ZSTD_BTRFS_MAX_INPUT);
    + size_t level_size =
    + max_t(size_t,
    + ZSTD_CStreamWorkspaceBound(params.cParams),
    + ZSTD_DStreamWorkspaceBound(ZSTD_BTRFS_MAX_INPUT));
    +
    + max_size = max_t(size_t, max_size, level_size);
    + zstd_ws_mem_sizes[level - 1] = max_size;
    + }
    +}
    +
    static void zstd_init_workspace_manager(void)
    {
    + zstd_calc_ws_mem_sizes();
    +
    btrfs_init_workspace_manager(&wsm, &btrfs_zstd_compress);
    }

    @@ -80,17 +112,13 @@ static void zstd_free_workspace(struct list_head *ws)

    static struct list_head *zstd_alloc_workspace(unsigned int level)
    {
    - ZSTD_parameters params =
    - zstd_get_btrfs_parameters(level, ZSTD_BTRFS_MAX_INPUT);
    struct workspace *workspace;

    workspace = kzalloc(sizeof(*workspace), GFP_KERNEL);
    if (!workspace)
    return ERR_PTR(-ENOMEM);

    - workspace->size = max_t(size_t,
    - ZSTD_CStreamWorkspaceBound(params.cParams),
    - ZSTD_DStreamWorkspaceBound(ZSTD_BTRFS_MAX_INPUT));
    + workspace->size = zstd_ws_mem_sizes[level - 1];
    workspace->mem = kvmalloc(workspace->size, GFP_KERNEL);
    workspace->buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
    if (!workspace->mem || !workspace->buf)
    --
    2.17.1
    \
     
     \ /
      Last update: 2019-02-04 21:22    [W:4.075 / U:0.192 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site