#include #include #include #include #include #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; }