mirror of
https://git.kernel.org/pub/scm/utils/kernel/kmod/kmod.git
synced 2024-11-30 07:13:42 +08:00
72c0aa37fe
Unlike the other two decompressions, zstd supports streaming bufferless mode. Meaning we don't need to read and realloc in a loop. Some strace numbers: $ strace -e read ./before/depmod -o /tmp/throaway | wc -l 35265 $ strace -e fstat ./before/depmod -o /tmp/throaway | wc -l 1110 $ strace -e read ./after/depmod -o /tmp/throaway | wc -l 5677 $ strace -e fstat ./after/depmod -o /tmp/throaway | wc -l 6642 .. and valgrind total heap usage statistics: before: 1,039,426 allocs, 1,039,426 frees, 3,679,232,922 bytes allocated after: 1,020,643 allocs, 1,020,643 frees, 1,157,922,357 bytes allocated The actual runtime is within the error margin. v2: - use ZSTD_decompress(), which allocates ZSTD_DCtx internally Signed-off-by: Emil Velikov <emil.l.velikov@gmail.com> Link: https://github.com/kmod-project/kmod/pull/142 Signed-off-by: Lucas De Marchi <lucas.de.marchi@gmail.com>
87 lines
1.6 KiB
C
87 lines
1.6 KiB
C
// SPDX-License-Identifier: LGPL-2.1-or-later
|
|
/*
|
|
* Copyright © 2024 Intel Corporation
|
|
*/
|
|
|
|
#include <errno.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/mman.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/types.h>
|
|
#include <unistd.h>
|
|
#include <zstd.h>
|
|
|
|
#include <shared/util.h>
|
|
|
|
#include "libkmod.h"
|
|
#include "libkmod-internal.h"
|
|
#include "libkmod-internal-file.h"
|
|
|
|
int kmod_file_load_zstd(struct kmod_file *file)
|
|
{
|
|
void *src_buf = MAP_FAILED, *dst_buf = NULL;
|
|
size_t src_size, dst_size, ret;
|
|
unsigned long long frame_size;
|
|
struct stat st;
|
|
|
|
if (fstat(file->fd, &st) < 0) {
|
|
ret = -errno;
|
|
ERR(file->ctx, "zstd: %m\n");
|
|
goto out;
|
|
}
|
|
|
|
if ((uintmax_t)st.st_size > SIZE_MAX) {
|
|
ret = -ENOMEM;
|
|
goto out;
|
|
}
|
|
|
|
src_size = st.st_size;
|
|
src_buf = mmap(NULL, src_size, PROT_READ, MAP_PRIVATE, file->fd, 0);
|
|
if (src_buf == MAP_FAILED) {
|
|
ret = -errno;
|
|
goto out;
|
|
}
|
|
|
|
frame_size = ZSTD_getFrameContentSize(src_buf, src_size);
|
|
if (frame_size == 0 || frame_size == ZSTD_CONTENTSIZE_UNKNOWN ||
|
|
frame_size == ZSTD_CONTENTSIZE_ERROR) {
|
|
ret = -EINVAL;
|
|
ERR(file->ctx, "zstd: Failed to determine decompression size\n");
|
|
goto out;
|
|
}
|
|
|
|
if (frame_size > SIZE_MAX) {
|
|
ret = -ENOMEM;
|
|
goto out;
|
|
}
|
|
|
|
dst_size = frame_size;
|
|
dst_buf = malloc(dst_size);
|
|
if (dst_buf == NULL) {
|
|
ret = -errno;
|
|
goto out;
|
|
}
|
|
|
|
ret = ZSTD_decompress(dst_buf, dst_size, src_buf, src_size);
|
|
if (ZSTD_isError(ret)) {
|
|
ERR(file->ctx, "zstd: %s\n", ZSTD_getErrorName(ret));
|
|
goto out;
|
|
}
|
|
|
|
file->memory = dst_buf;
|
|
file->size = dst_size;
|
|
|
|
ret = 0;
|
|
dst_buf = NULL;
|
|
|
|
out:
|
|
free(dst_buf);
|
|
|
|
if (src_buf != MAP_FAILED)
|
|
munmap(src_buf, src_size);
|
|
|
|
return ret;
|
|
}
|