From b0706fb6c979c85c5b19cc9554e3ebea449f66f0 Mon Sep 17 00:00:00 2001 From: Yan Lan Date: Wed, 26 Nov 2025 11:14:43 +0800 Subject: [PATCH] feat: support zondafs --- Makefile | 16 +++ configure | 73 ++++++++++++++ engines/zondafs.c | 249 ++++++++++++++++++++++++++++++++++++++++++++++ optgroup.h | 2 + options.c | 5 + 5 files changed, 345 insertions(+) create mode 100644 engines/zondafs.c diff --git a/Makefile b/Makefile index 7393a32729..6f67aee68b 100644 --- a/Makefile +++ b/Makefile @@ -150,6 +150,22 @@ ifdef CONFIG_DFS dfs_LIBS = -luuid -ldaos -ldfs ENGINES += dfs endif +ifdef CONFIG_ZONDAFS + zondafs_SRCS = engines/zondafs.c + zondafs_LIBS = $(FIO_ZONDAFS_PATH)/deps/file_client/lib/libfile_client.a \ + $(FIO_ZONDAFS_PATH)/deps/brpc/lib/libbrpc.a \ + $(FIO_ZONDAFS_PATH)/deps/fmt/lib/libfmt.a \ + $(FIO_ZONDAFS_PATH)/deps/isal/lib/libisal.a \ + $(FIO_ZONDAFS_PATH)/deps/gflags/lib/libgflags.a \ + -lprotobuf -lrt -lcrypto -lssl -lleveldb + zondafs_CFLAGS = -I$(FIO_ZONDAFS_PATH)/deps/brpc/include \ + -I$(FIO_ZONDAFS_PATH)/deps/file_client/include \ + -I$(FIO_ZONDAFS_PATH)/deps/fmt/include \ + -I$(FIO_ZONDAFS_PATH)/deps/isal/include \ + -I$(FIO_ZONDAFS_PATH)/deps/gflags/include \ + -I$(FIO_ZONDAFS_PATH) + ENGINES += zondafs +endif SOURCE += oslib/asprintf.c ifndef CONFIG_STRSEP SOURCE += oslib/strsep.c diff --git a/configure b/configure index 134501185a..5401bb1f9b 100755 --- a/configure +++ b/configure @@ -195,6 +195,7 @@ isal64="" libblkio="" libzbc="" dfs="" +zondafs="" seed_buckets="" dynamic_engines="no" prefix=/usr/local @@ -283,6 +284,10 @@ for opt do ;; --disable-dfs) dfs="no" ;; + --enable-zondafs) zondafs="yes" + ;; + --disable-zondafs) zondafs="no" + ;; --enable-asan) asan="yes" ;; --seed-buckets=*) seed_buckets="$optarg" @@ -338,6 +343,8 @@ if test "$show_help" = "yes" ; then echo "--disable-tcmalloc Disable tcmalloc support" echo "--dynamic-libengines Lib-based ioengines as dynamic libraries" echo "--disable-dfs Disable DAOS File System support even if found" + echo "--enable-zondafs Enable zondafs (Zonda2 File System) support" + echo "--disable-zondafs Disable zondafs support even if found" echo "--enable-asan Enable address sanitizer" echo "--seed-buckets= Number of seed buckets for the refill-buffer" echo "--disable-tls Disable __thread local storage" @@ -2343,6 +2350,68 @@ EOF fi print_config "DAOS File System (dfs) Engine" "$dfs" +########################################## +# check for zondafs (Zonda2 File System) +if test "$zondafs" != "no" ; then + if test "$FIO_ZONDAFS_PATH" = "" ; then + FIO_ZONDAFS_PATH="/home/lanyan/zonda2" + fi + + zondafs_base_path="$FIO_ZONDAFS_PATH" + zondafs_lib_path="$zondafs_base_path/deps" + zondafs_include_path="$zondafs_base_path/deps/file_client/include" + + # Check if required library files exist + if test ! -f "$zondafs_lib_path/file_client/lib/libfile_client.a" ; then + if test "$zondafs" = "yes" ; then + feature_not_found "zondafs" "libfile_client.a not found at $zondafs_lib_path/file_client/lib/" + fi + zondafs="no" + elif test ! -f "$zondafs_lib_path/brpc/lib/libbrpc.a" ; then + if test "$zondafs" = "yes" ; then + feature_not_found "zondafs" "libbrpc.a not found at $zondafs_lib_path/brpc/lib/" + fi + zondafs="no" + elif test ! -d "$zondafs_include_path" ; then + if test "$zondafs" = "yes" ; then + feature_not_found "zondafs" "include directory not found at $zondafs_include_path" + fi + zondafs="no" + else + # Try to compile a test program + cat > $TMPC << EOF +#include + +int main(int argc, char **argv) +{ + zonda_fs_client_t *client = NULL; + zonda_fs_conn_config_t config = {0}; + zonda_error_code_t code; + + code = zonda_fs_client_new(&config, &client); + if (code == 0 && client != NULL) { + zonda_fs_client_destroy(client); + } + + return 0; +} +EOF + zondafs_cflags="-I$zondafs_base_path/deps/brpc/include -I$zondafs_base_path/deps/file_client/include -I$zondafs_base_path/deps/fmt/include -I$zondafs_base_path/deps/isal/include -I$zondafs_base_path/deps/gflags/include -I$zondafs_base_path" + zondafs_ldflags="$zondafs_lib_path/file_client/lib/libfile_client.a $zondafs_lib_path/brpc/lib/libbrpc.a $zondafs_lib_path/fmt/lib/libfmt.a $zondafs_lib_path/isal/lib/libisal.a $zondafs_lib_path/gflags/lib/libgflags.a -lprotobuf -lrt -lcrypto -lssl -lleveldb" + + if compile_prog "$zondafs_cflags" "$zondafs_ldflags" "zondafs"; then + zondafs="yes" + FIO_ZONDAFS_PATH="$zondafs_base_path" + else + if test "$zondafs" = "yes" ; then + feature_not_found "zondafs" "compilation test failed" + fi + zondafs="no" + fi + fi +fi +print_config "Zonda2 File System (zondafs) Engine" "$zondafs" + ########################################## # Check if we have libnfs (for userspace nfs support). if test "$libnfs" != "no" ; then @@ -3310,6 +3379,10 @@ fi if test "$dfs" = "yes" ; then output_sym "CONFIG_DFS" fi +if test "$zondafs" = "yes" ; then + output_sym "CONFIG_ZONDAFS" + echo "FIO_ZONDAFS_PATH=$FIO_ZONDAFS_PATH" >> $config_host_mak +fi if test "$march_set" = "no" && test "$build_native" = "yes" ; then output_sym "CONFIG_BUILD_NATIVE" fi diff --git a/engines/zondafs.c b/engines/zondafs.c new file mode 100644 index 0000000000..2bc9474d51 --- /dev/null +++ b/engines/zondafs.c @@ -0,0 +1,249 @@ +#include +#include + +#include "../fio.h" +#include "../optgroup.h" + +/* zonda_fs client headers */ +#include "zonda_fs_c.h" + +struct zondafsio_data { + zonda_fs_client_t* client; + zonda_fs_file_t* file; +}; + +struct zondafsio_options { + char *master; + char *cluster; + char *client; + char *fence_dir; + char *log_path; + char *role; + char *ip; +}; + +static struct fio_option options[] = { + { + .name = "master", + .lname = "zonda2 fs master addr", + .type = FIO_OPT_STR_STORE, + .off1 = offsetof(struct zondafsio_options, master), + .def = "", + .help = "Master addr of the zonda2 fs", + .category = FIO_OPT_C_ENGINE, + .group = FIO_OPT_G_ZONDAFS, + }, + { + .name = "cluster", + .lname = "zonda2 cluster id", + .type = FIO_OPT_STR_STORE, + .off1 = offsetof(struct zondafsio_options, cluster), + .def = "", + .help = "Cluster id of the zonda2 fs", + .category = FIO_OPT_C_ENGINE, + .group = FIO_OPT_G_ZONDAFS, + }, + { + .name = "client", + .lname = "zonda2 client id", + .type = FIO_OPT_STR_STORE, + .off1 = offsetof(struct zondafsio_options, client), + .def = "fio_client", + .help = "Client id of the zonda2 fs", + .category = FIO_OPT_C_ENGINE, + .group = FIO_OPT_G_ZONDAFS, + }, + { + .name = "fence_dir", + .lname = "zonda2 read/write fence_dir", + .type = FIO_OPT_STR_STORE, + .off1 = offsetof(struct zondafsio_options, fence_dir), + .def = "", + .help = "Fence dir id of the zonda2 fs", + .category = FIO_OPT_C_ENGINE, + .group = FIO_OPT_G_ZONDAFS, + }, + { + .name = "log_path", + .lname = "zonda2 cpp client log path", + .type = FIO_OPT_STR_STORE, + .off1 = offsetof(struct zondafsio_options, log_path), + .def = "./logs", + .help = "Log path of the zonda2 fs", + .category = FIO_OPT_C_ENGINE, + .group = FIO_OPT_G_ZONDAFS, + }, + { + .name = "role", + .lname = "zonda2 cpp client role", + .type = FIO_OPT_STR_STORE, + .off1 = offsetof(struct zondafsio_options, role), + .def = "fio_role", + .help = "Role of the zonda2 fs", + .category = FIO_OPT_C_ENGINE, + .group = FIO_OPT_G_ZONDAFS, + }, + { + .name = "ip", + .lname = "zonda2 ip used by io fence", + .type = FIO_OPT_STR_STORE, + .off1 = offsetof(struct zondafsio_options, ip), + .def = "127.0.0.1", + .help = "The host ip of the zonda2 fence", + .category = FIO_OPT_C_ENGINE, + .group = FIO_OPT_G_ZONDAFS, + }, + { + .name = NULL, + }, +}; + +static enum fio_q_status fio_zondafs_queue(struct thread_data *td, + struct io_u *io_u) +{ + struct zondafsio_data *zd = td->io_ops_data; + zonda_fs_file_t* file = NULL; + zonda_error_code_t code; + int ret; + unsigned long offset; + unsigned long bytes_written = 0, bytes_read = 0; + file = zd->file; + + if (io_u->ddir == DDIR_READ) { + code = zonda_fs_file_read_at(file, io_u->xfer_buflen, io_u->offset, io_u->xfer_buflen, &bytes_read); + if(code != 0 && code != 23014) { + io_u->error = EIO; + return FIO_Q_COMPLETED; + } + if(bytes_read != io_u->xfer_buflen) { + if(code != 23014) { + io_u->error = EIO; + } + } + } else if (io_u->ddir == DDIR_WRITE) { + code = zonda_fs_file_append(file, io_u->xfer_buflen, io_u->xfer_buf, &bytes_written); + if(code != 0 || bytes_written != io_u->xfer_buflen) { + io_u->error = EIO; + } + } else { + log_err("zondafs: Invalid I/O Operation: %d\n", io_u->ddir); + io_u->error = EINVAL; + } + if (io_u->error) + td_verror(td, io_u->error, "xfer"); + + return FIO_Q_COMPLETED; +} + +int fio_zondafs_open_file(struct thread_data *td, struct fio_file *f) +{ + struct zondafsio_data *zd = td->io_ops_data; + + zonda_fs_file_t* file = NULL; + zonda_error_code_t code; + + uint32_t flags = ZONDA_FS_OPEN_FLAGS_RDWR | ZONDA_FS_OPEN_FLAGS_CREAT; + code = zonda_fs_client_open(zd->client, f->file_name, flags, &file); + if(code != 0) { + log_err("zondafs: unable to open"); + return code; + } + zd->file = file; + return 0; +} + +int fio_zondafs_close_file(struct thread_data *td, struct fio_file *f) +{ + struct zondafsio_data *zd = td->io_ops_data; + + zonda_fs_file_close(zd->file); + zonda_fs_file_destroy(zd->file); + zonda_fs_client_destroy(zd->client); + return 0; +} + +static int fio_zondafs_setup(struct thread_data *td) +{ + struct zondafsio_data *zd; + struct fio_file *f; + int i; + uint64_t file_size, total_file_size; + + if (!td->io_ops_data) { + zd = calloc(1, sizeof(*zd)); + td->io_ops_data = zd; + } + + total_file_size = 0; + file_size = 0; + + for_each_file(td, f, i) { + if(!td->o.file_size_low) { + file_size = floor(td->o.size / td->o.nr_files); + total_file_size += file_size; + } + else if (td->o.file_size_low == td->o.file_size_high) + file_size = td->o.file_size_low; + else { + file_size = get_rand_file_size(td); + } + f->real_file_size = file_size; + } + return 0; +} + +static int fio_zondafs_init(struct thread_data *td) +{ + struct zondafsio_data *zd = td->io_ops_data; + struct zondafsio_options *option = td->eo; + + zonda_fs_client_t* client = NULL; + zonda_error_code_t code; + + zonda_fs_conn_config_t config = { + .master_addr = option->master, + .cluster_id = option->cluster, + .client_id = option->client, + .fence_dir = option->fence_dir, + .log_path = option->log_path, + .role = option->role, + .ip = option->ip, + }; + + code = zonda_fs_client_new(&config, &client); + if(code != 0) { + log_err("zondafs: unable to new client\n"); + return EINVAL; + } + zd->client = client; + + code = zonda_fs_client_fence_directory(client, option->fence_dir); + if(code != 0) { + log_err("zondafs: unable to fence dir\n"); + return EINVAL; + } + return 0; +} + +FIO_STATIC struct ioengine_ops ioengine = { + .name = "zondafs", + .version = FIO_IOOPS_VERSION, + .flags = FIO_SYNCIO | FIO_DISKLESSIO | FIO_NODISKUTIL, + .setup = fio_zondafs_setup, + .init = fio_zondafs_init, + .queue = fio_zondafs_queue, + .open_file = fio_zondafs_open_file, + .close_file = fio_zondafs_close_file, + .option_struct_size = sizeof(struct zondafsio_options), + .options = options, +}; + +static void fio_init fio_zondafs_register(void) +{ + register_ioengine(&ioengine); +} + +static void fio_exit fio_zondafs_unregister(void) +{ + unregister_ioengine(&ioengine); +} \ No newline at end of file diff --git a/optgroup.h b/optgroup.h index eb5e6f35eb..e0d8365c54 100644 --- a/optgroup.h +++ b/optgroup.h @@ -73,6 +73,7 @@ enum opt_category_group { __FIO_OPT_G_WINDOWSAIO, __FIO_OPT_G_XNVME, __FIO_OPT_G_LIBBLKIO, + __FIO_OPT_G_ZONDAFS, FIO_OPT_G_RATE = (1ULL << __FIO_OPT_G_RATE), FIO_OPT_G_ZONE = (1ULL << __FIO_OPT_G_ZONE), @@ -120,6 +121,7 @@ enum opt_category_group { FIO_OPT_G_WINDOWSAIO = (1ULL << __FIO_OPT_G_WINDOWSAIO), FIO_OPT_G_XNVME = (1ULL << __FIO_OPT_G_XNVME), FIO_OPT_G_LIBBLKIO = (1ULL << __FIO_OPT_G_LIBBLKIO), + FIO_OPT_G_ZONDAFS = (1ULL << __FIO_OPT_G_ZONDAFS), }; extern const struct opt_group *opt_group_from_mask(uint64_t *mask); diff --git a/options.c b/options.c index 8e3de528bb..012c5df220 100644 --- a/options.c +++ b/options.c @@ -2276,6 +2276,11 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .help = "DAOS File System (dfs) IO engine", }, #endif +#ifdef CONFIG_ZONDAFS + { .ival = "zondafs", + .help = "Zonda2 File System (zondafs) IO engine", + }, +#endif #ifdef CONFIG_LIBNFS { .ival = "nfs", .help = "NFS IO engine",