This commit is contained in:
2026-03-09 07:53:06 +00:00
parent 975afaf3f0
commit 470412a1c2
82 changed files with 7094 additions and 5234 deletions

View File

@@ -0,0 +1,43 @@
# SPDX-License-Identifier: BSD-3-Clause
SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../spdk)
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
include $(SPDK_ROOT_DIR)/mk/spdk.modules.mk
include $(SPDK_ROOT_DIR)/mk/spdk.app_vars.mk
# 输出目录
BIN_DIR := $(abspath $(CURDIR)/../bin)
TEST_BINS := \
ioengine_single_blob_test \
ioengine_multi_blob_test \
ioengine_same_blob_mt_test
COMMON_SRCS := \
test_common.c \
../../src/spdk_engine/io_engine.c \
../../src/common/utils.c
SPDK_LIB_LIST = $(ALL_MODULES_LIST) event event_bdev
LIBS += $(SPDK_LIB_LINKER_ARGS)
CFLAGS += -I$(abspath $(CURDIR)/../../src) -I$(CURDIR)
.PHONY: all clean
all: $(BIN_DIR) $(addprefix $(BIN_DIR)/,$(TEST_BINS))
# 创建 bin 目录
$(BIN_DIR):
mkdir -p $(BIN_DIR)
$(BIN_DIR)/ioengine_single_blob_test: ioengine_single_blob_test.c $(COMMON_SRCS) $(SPDK_LIB_FILES) $(ENV_LIBS)
$(CC) $(CFLAGS) -o $@ $< $(COMMON_SRCS) $(LDFLAGS) $(LIBS) $(ENV_LDFLAGS) $(SYS_LIBS)
$(BIN_DIR)/ioengine_multi_blob_test: ioengine_multi_blob_test.c $(COMMON_SRCS) $(SPDK_LIB_FILES) $(ENV_LIBS)
$(CC) $(CFLAGS) -o $@ $< $(COMMON_SRCS) $(LDFLAGS) $(LIBS) $(ENV_LDFLAGS) $(SYS_LIBS)
$(BIN_DIR)/ioengine_same_blob_mt_test: ioengine_same_blob_mt_test.c $(COMMON_SRCS) $(SPDK_LIB_FILES) $(ENV_LIBS)
$(CC) $(CFLAGS) -o $@ $< $(COMMON_SRCS) $(LDFLAGS) $(LIBS) $(ENV_LDFLAGS) $(SYS_LIBS)
clean:
rm -f $(addprefix $(BIN_DIR)/,$(TEST_BINS))

View File

@@ -0,0 +1,106 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "spdk_engine/io_engine.h"
#include "test_common.h"
#define MULTI_BLOB_COUNT 3
int main(void) {
int rc = 0;
const char *bdev_name = getenv("SPDK_BDEV_NAME");
struct zvfs_blob_handle *handles[MULTI_BLOB_COUNT] = {0};
uint64_t ids[MULTI_BLOB_COUNT] = {0};
uint64_t cluster = 0;
void *wbuf = NULL;
void *rbuf = NULL;
int i = 0;
if (!bdev_name) {
bdev_name = "Malloc0";
}
if (io_engine_init(bdev_name) != 0) {
fprintf(stderr, "TEST2: io_engine_init failed (bdev=%s)\n", bdev_name);
return 1;
}
printf("[TEST2] single thread / multi blob\n");
handles[0] = blob_create(0);
if (!handles[0]) {
fprintf(stderr, "TEST2: create first blob failed\n");
return 1;
}
ids[0] = handles[0]->id;
cluster = handles[0]->size;
if (cluster == 0) {
fprintf(stderr, "TEST2: invalid cluster size\n");
rc = 1;
goto out;
}
if (blob_resize(handles[0], cluster * 2) != 0) {
fprintf(stderr, "TEST2: resize first blob failed\n");
rc = 1;
goto out;
}
for (i = 1; i < MULTI_BLOB_COUNT; i++) {
handles[i] = blob_create(cluster * 2);
if (!handles[i]) {
fprintf(stderr, "TEST2: create blob %d failed\n", i);
rc = 1;
goto out;
}
ids[i] = handles[i]->id;
}
if (alloc_aligned_buf(&wbuf, cluster) != 0 || alloc_aligned_buf(&rbuf, cluster) != 0) {
fprintf(stderr, "TEST2: alloc aligned buffer failed\n");
rc = 1;
goto out;
}
for (i = 0; i < MULTI_BLOB_COUNT; i++) {
fill_pattern((uint8_t *)wbuf, cluster, (uint8_t)(0x20 + i));
memset(rbuf, 0, cluster);
if (blob_write(handles[i], 0, wbuf, cluster) != 0) {
fprintf(stderr, "TEST2: blob_write[%d] failed\n", i);
rc = 1;
goto out;
}
if (blob_read(handles[i], 0, rbuf, cluster) != 0) {
fprintf(stderr, "TEST2: blob_read[%d] failed\n", i);
rc = 1;
goto out;
}
if (memcmp(wbuf, rbuf, cluster) != 0) {
fprintf(stderr, "TEST2: blob[%d] readback mismatch\n", i);
rc = 1;
goto out;
}
}
out:
for (i = 0; i < MULTI_BLOB_COUNT; i++) {
if (handles[i]) {
(void)blob_close(handles[i]);
}
}
for (i = 0; i < MULTI_BLOB_COUNT; i++) {
if (ids[i] != 0) {
(void)blob_delete(ids[i]);
}
}
free(wbuf);
free(rbuf);
if (rc == 0) {
printf("[TEST2] PASS\n");
return 0;
}
printf("[TEST2] FAIL\n");
return 1;
}

View File

@@ -0,0 +1,147 @@
#include <pthread.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "spdk_engine/io_engine.h"
#include "test_common.h"
#define THREAD_COUNT 4
struct mt_case_arg {
struct zvfs_blob_handle *handle;
uint64_t cluster_size;
uint64_t offset;
uint8_t seed;
pthread_barrier_t *barrier;
int rc;
};
static void *mt_case_worker(void *arg) {
struct mt_case_arg *ctx = (struct mt_case_arg *)arg;
void *wbuf = NULL;
void *rbuf = NULL;
if (alloc_aligned_buf(&wbuf, ctx->cluster_size) != 0 ||
alloc_aligned_buf(&rbuf, ctx->cluster_size) != 0) {
free(wbuf);
free(rbuf);
ctx->rc = 1;
return NULL;
}
fill_pattern((uint8_t *)wbuf, ctx->cluster_size, ctx->seed);
(void)pthread_barrier_wait(ctx->barrier);
if (blob_write(ctx->handle, ctx->offset, wbuf, ctx->cluster_size) != 0) {
ctx->rc = 1;
goto out;
}
if (blob_read(ctx->handle, ctx->offset, rbuf, ctx->cluster_size) != 0) {
ctx->rc = 1;
goto out;
}
if (memcmp(wbuf, rbuf, ctx->cluster_size) != 0) {
ctx->rc = 1;
goto out;
}
ctx->rc = 0;
out:
free(wbuf);
free(rbuf);
return NULL;
}
int main(void) {
int rc = 0;
const char *bdev_name = getenv("SPDK_BDEV_NAME");
int i = 0;
struct zvfs_blob_handle *h = NULL;
uint64_t blob_id = 0;
uint64_t cluster = 0;
pthread_t tids[THREAD_COUNT];
struct mt_case_arg args[THREAD_COUNT];
pthread_barrier_t barrier;
int barrier_inited = 0;
if (!bdev_name) {
bdev_name = "Malloc0";
}
if (io_engine_init(bdev_name) != 0) {
fprintf(stderr, "TEST3: io_engine_init failed (bdev=%s)\n", bdev_name);
return 1;
}
printf("[TEST3] multi thread / same blob\n");
h = blob_create(0);
if (!h) {
fprintf(stderr, "TEST3: blob_create failed\n");
return 1;
}
blob_id = h->id;
cluster = h->size;
if (cluster == 0) {
fprintf(stderr, "TEST3: invalid cluster size\n");
rc = 1;
goto out;
}
if (blob_resize(h, cluster * THREAD_COUNT) != 0) {
fprintf(stderr, "TEST3: blob_resize failed\n");
rc = 1;
goto out;
}
if (pthread_barrier_init(&barrier, NULL, THREAD_COUNT) != 0) {
fprintf(stderr, "TEST3: barrier init failed\n");
rc = 1;
goto out;
}
barrier_inited = 1;
for (i = 0; i < THREAD_COUNT; i++) {
args[i].handle = h;
args[i].cluster_size = cluster;
args[i].offset = cluster * (uint64_t)i;
args[i].seed = (uint8_t)(0x40 + i);
args[i].barrier = &barrier;
args[i].rc = 1;
if (pthread_create(&tids[i], NULL, mt_case_worker, &args[i]) != 0) {
fprintf(stderr, "TEST3: pthread_create[%d] failed\n", i);
rc = 1;
while (--i >= 0) {
pthread_join(tids[i], NULL);
}
goto out;
}
}
for (i = 0; i < THREAD_COUNT; i++) {
pthread_join(tids[i], NULL);
if (args[i].rc != 0) {
fprintf(stderr, "TEST3: worker[%d] failed\n", i);
rc = 1;
}
}
out:
if (barrier_inited) {
(void)pthread_barrier_destroy(&barrier);
}
if (h) {
(void)blob_close(h);
}
if (blob_id != 0) {
(void)blob_delete(blob_id);
}
if (rc == 0) {
printf("[TEST3] PASS\n");
return 0;
}
printf("[TEST3] FAIL\n");
return 1;
}

View File

@@ -0,0 +1,136 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "spdk_engine/io_engine.h"
#include "test_common.h"
int main(void) {
int rc = 0;
const char *bdev_name = getenv("SPDK_BDEV_NAME");
struct zvfs_blob_handle *h = NULL;
struct zvfs_blob_handle *reopen = NULL;
uint64_t blob_id = 0;
uint64_t cluster = 0;
void *wbuf = NULL;
void *rbuf = NULL;
if (!bdev_name) {
bdev_name = "Malloc0";
}
if (io_engine_init(bdev_name) != 0) {
fprintf(stderr, "TEST1: io_engine_init failed (bdev=%s)\n", bdev_name);
return 1;
}
printf("[TEST1] single thread / single blob\n");
h = blob_create(0);
if (!h) {
fprintf(stderr, "TEST1: blob_create failed\n");
return 1;
}
blob_id = h->id;
cluster = h->size;
if (cluster == 0) {
fprintf(stderr, "TEST1: invalid cluster size\n");
rc = 1;
goto out;
}
rc = blob_resize(h, cluster * 2);
if (rc != 0) {
fprintf(stderr, "TEST1: blob_resize failed: %d\n", rc);
rc = 1;
goto out;
}
rc = alloc_aligned_buf(&wbuf, cluster);
if (rc != 0) {
fprintf(stderr, "TEST1: alloc write buf failed: %d\n", rc);
rc = 1;
goto out;
}
rc = alloc_aligned_buf(&rbuf, cluster);
if (rc != 0) {
fprintf(stderr, "TEST1: alloc read buf failed: %d\n", rc);
rc = 1;
goto out;
}
fill_pattern((uint8_t *)wbuf, cluster, 0x11);
rc = blob_write(h, 0, wbuf, cluster);
if (rc != 0) {
fprintf(stderr, "TEST1: blob_write failed: %d\n", rc);
rc = 1;
goto out;
}
rc = blob_read(h, 0, rbuf, cluster);
if (rc != 0) {
fprintf(stderr, "TEST1: blob_read failed: %d\n", rc);
rc = 1;
goto out;
}
if (memcmp(wbuf, rbuf, cluster) != 0) {
fprintf(stderr, "TEST1: readback mismatch\n");
rc = 1;
goto out;
}
rc = blob_sync_md(h);
if (rc != 0) {
fprintf(stderr, "TEST1: blob_sync_md failed: %d\n", rc);
rc = 1;
goto out;
}
rc = blob_close(h);
if (rc != 0) {
fprintf(stderr, "TEST1: blob_close failed: %d\n", rc);
rc = 1;
goto out;
}
h = NULL;
reopen = blob_open(blob_id);
if (!reopen) {
fprintf(stderr, "TEST1: blob_open(reopen) failed\n");
rc = 1;
goto out;
}
memset(rbuf, 0, cluster);
rc = blob_read(reopen, 0, rbuf, cluster);
if (rc != 0) {
fprintf(stderr, "TEST1: reopen blob_read failed: %d\n", rc);
rc = 1;
goto out;
}
if (memcmp(wbuf, rbuf, cluster) != 0) {
fprintf(stderr, "TEST1: reopen readback mismatch\n");
rc = 1;
goto out;
}
out:
if (reopen) {
(void)blob_close(reopen);
}
if (h) {
(void)blob_close(h);
}
if (blob_id != 0) {
(void)blob_delete(blob_id);
}
free(wbuf);
free(rbuf);
if (rc == 0) {
printf("[TEST1] PASS\n");
return 0;
}
printf("[TEST1] FAIL\n");
return 1;
}

View File

@@ -0,0 +1,20 @@
#include "test_common.h"
#include <stdlib.h>
#include <string.h>
int alloc_aligned_buf(void **buf, size_t len) {
int rc = posix_memalign(buf, 4096, len);
if (rc != 0) {
return -rc;
}
memset(*buf, 0, len);
return 0;
}
void fill_pattern(uint8_t *buf, size_t len, uint8_t seed) {
size_t i = 0;
for (i = 0; i < len; i++) {
buf[i] = (uint8_t)(seed + (uint8_t)i);
}
}

View File

@@ -0,0 +1,10 @@
#ifndef __IOENGINE_TEST_COMMON_H__
#define __IOENGINE_TEST_COMMON_H__
#include <stddef.h>
#include <stdint.h>
int alloc_aligned_buf(void **buf, size_t len);
void fill_pattern(uint8_t *buf, size_t len, uint8_t seed);
#endif // __IOENGINE_TEST_COMMON_H__