From 26848d1dff6999320748770c3c8c9dbd4357effc Mon Sep 17 00:00:00 2001 From: Jinshan Xiong Date: Sun, 1 Mar 2026 00:37:12 +0000 Subject: [PATCH] Add AIO and Direct IO support for IOR phases This commit introduces a set of features and fixes to improve IOR execution flexibility and overall test stability: IOR Execution Enhancements: - Added '--with-aio' to IOR configuration in prepare.sh to enable AIO. - Introduced 'direct' option for IOR phases to support '--posix.odirect'. - Added 'iteration' option to the IOR easy read phase. Phase Execution & Validation: - Added should_run_phase() check in main.c to properly skip disabled phases. - Improved the stonewall condition validation logic in phase_dbg.c. Bug Fixes: - Added CFLAGS="-fPIC" for pfind compilation in prepare.sh. - Fixed missing return value validation for fread() in phase_mdworkbench.c. Signed-off-by: Jinshan Xiong --- prepare.sh | 6 +++--- src/main.c | 15 +++++++++++++++ src/phase_dbg.c | 4 ++-- src/phase_ior.h | 3 ++- src/phase_ior_easy.c | 7 ++++++- src/phase_ior_easy_read.c | 16 ++++++++++++---- src/phase_ior_easy_write.c | 8 ++++---- src/phase_ior_rnd_read4k-easywrite.c | 5 ++++- src/phase_mdworkbench.c | 4 +++- 9 files changed, 51 insertions(+), 17 deletions(-) diff --git a/prepare.sh b/prepare.sh index ad29321..bde54b9 100755 --- a/prepare.sh +++ b/prepare.sh @@ -87,8 +87,8 @@ function get_schema_tools { function build_ior { pushd "$BUILD"/ior ./bootstrap - # Add here extra flags - ./configure --prefix="$INSTALL_DIR" + # Add here extra flags (e.g., --with-aio for asynchronous I/O support) + ./configure --prefix="$INSTALL_DIR" --with-aio cd src $MAKE clean $MAKE install @@ -99,7 +99,7 @@ function build_ior { function build_pfind { pushd "$BUILD"/pfind - ./prepare.sh + CFLAGS="-fPIC" ./prepare.sh ./compile.sh ln -sf "$BUILD"/pfind/pfind "$BIN"/pfind echo "Pfind: OK" diff --git a/src/main.c b/src/main.c index 389f507..2eba3f6 100644 --- a/src/main.c +++ b/src/main.c @@ -169,6 +169,17 @@ static const char * io500_mode_str(io500_mode mode){ } } +static int should_run_phase(u_phase_t * phase){ + if(phase->options){ + for(ini_option_t * o = phase->options; o->name != NULL; o++){ + if(o->type == INI_BOOL && o->var != NULL && strcmp(o->name, "run") == 0){ + return *(int*) o->var; + } + } + } + return 1; +} + int main(int argc, char ** argv){ int mpi_init = 0; file_out = stdout; @@ -378,6 +389,10 @@ int main(int argc, char ** argv){ continue; } + if(! should_run_phase(phase)){ + continue; + } + if(opt.drop_caches && ! (phase->type & IO500_PHASE_DUMMY) ){ DEBUG_INFO("Dropping cache\n"); if(opt.rank == 0) diff --git a/src/phase_dbg.c b/src/phase_dbg.c index 4c3f42d..a86bb88 100644 --- a/src/phase_dbg.c +++ b/src/phase_dbg.c @@ -11,8 +11,8 @@ static ini_option_t option[] = { static void validate(void){ - if(opt.stonewall != opt.minwrite && opt.rank == 0){ - INVALID("stonewall-time < %us\n", opt.minwrite); + if(opt.stonewall < opt.minwrite && opt.rank == 0){ + INVALID("stonewall-time: %us < %us\n", opt.stonewall, opt.minwrite); } } diff --git a/src/phase_ior.h b/src/phase_ior.h index 3df6888..fa5e8de 100644 --- a/src/phase_ior.h +++ b/src/phase_ior.h @@ -13,6 +13,7 @@ typedef struct{ char * transferSize; char * blockSize; int verbosity; + int direct; } opt_ior_easy; extern opt_ior_easy ior_easy_o; @@ -41,7 +42,7 @@ extern opt_ior_rnd ior_rnd4K_o; extern opt_ior_rnd ior_rnd1MB_o; -void ior_easy_add_params(u_argv_t * argv, int addStdFlags); +void ior_easy_add_params(u_argv_t * argv, int addStdFlags, int direct); void ior_hard_add_params(u_argv_t * argv); void ior_rnd4K_add_params(u_argv_t * argv); void ior_rnd1MB_add_params(u_argv_t * argv); diff --git a/src/phase_ior_easy.c b/src/phase_ior_easy.c index 3b224a2..6df16cb 100644 --- a/src/phase_ior_easy.c +++ b/src/phase_ior_easy.c @@ -14,6 +14,7 @@ static ini_option_t option[] = { {"uniqueDir", "Use unique directory per file per process", 0, INI_BOOL, "FALSE", & ior_easy_o.uniqueDir}, {"run", "Run this phase", 0, INI_BOOL, "TRUE", & ior_easy_o.run}, {"verbosity", "The verbosity level", 0, INI_INT, 0, & ior_easy_o.verbosity}, + {"direct", "Use direct IO (posix.odirect)", 0, INI_BOOL, "TRUE", & ior_easy_o.direct}, {NULL} }; static void validate(void){ @@ -42,7 +43,7 @@ static void cleanup(void){ } } -void ior_easy_add_params(u_argv_t * argv, int addStdFlags){ +void ior_easy_add_params(u_argv_t * argv, int addStdFlags, int direct){ opt_ior_easy d = ior_easy_o; u_argv_push(argv, "./ior"); @@ -82,6 +83,10 @@ void ior_easy_add_params(u_argv_t * argv, int addStdFlags){ if(ior_easy_o.filePerProc){ u_argv_push(argv, "-F"); /* write a separate file per process */ } + + if(direct){ + u_argv_push(argv, "--posix.odirect"); /* read&write file with direct IO */ + } } u_phase_t p_ior_easy = { diff --git a/src/phase_ior_easy_read.c b/src/phase_ior_easy_read.c index 543885d..07d1b1b 100644 --- a/src/phase_ior_easy_read.c +++ b/src/phase_ior_easy_read.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include @@ -8,6 +9,8 @@ typedef struct{ int run; char * api; + int direct; + int iteration; char * command; IOR_point_t * res; @@ -18,6 +21,8 @@ static opt_ior_easy_read o; static ini_option_t option[] = { {"API", "The API to be used", 0, INI_STRING, NULL, & o.api}, {"run", "Run this phase", 0, INI_BOOL, "TRUE", & o.run}, + {"direct", "Use direct IO (posix.odirect)", 0, INI_BOOL, NULL, & o.direct}, + {"iteration", "Number of iterations", 0, INI_INT, "1", & o.iteration}, {NULL} }; @@ -30,17 +35,20 @@ static double run(void){ opt_ior_easy d = ior_easy_o; u_argv_t * argv = u_argv_create(); - ior_easy_add_params(argv, 1); + int direct = (o.direct != INI_UNSET_BOOL) ? o.direct : d.direct; + ior_easy_add_params(argv, 1, direct); u_argv_push(argv, "-r"); /* read existing file */ + if (o.iteration != INI_UNSET_INT) { + u_argv_push(argv, "-i"); + u_argv_push_printf(argv, "%d", o.iteration); + } u_argv_push(argv, "-R"); /* verify data read */ + u_argv_push_default_if_set_api_options(argv, "-a", d.api, o.api); u_argv_push(argv, "-O"); u_argv_push_printf(argv, "saveRankPerformanceDetailsCSV=%s/ior-easy-read.csv", opt.resdir); // u_argv_push_default_if_set(argv, "-U", /* use hints file */ // d.hintsFileName, o.hintsFileName); -// u_argv_push_default_if_set_api_options(argv, "-a", /* backend API */ -// d.api, o.api); -// u_argv_push_default_if_set_bool(argv, "--posix.odirect", d.odirect, o.odirect); o.command = u_flatten_argv(argv); diff --git a/src/phase_ior_easy_write.c b/src/phase_ior_easy_write.c index 87e97b5..9527f3e 100644 --- a/src/phase_ior_easy_write.c +++ b/src/phase_ior_easy_write.c @@ -9,6 +9,7 @@ typedef struct{ int run; char * api; + int direct; char * command; IOR_point_t * res; @@ -19,6 +20,7 @@ static opt_ior_easy_write o; static ini_option_t option[] = { {"API", "The API to be used", 0, INI_STRING, NULL, & o.api}, {"run", "Run this phase", 0, INI_BOOL, "TRUE", & o.run}, + {"direct", "Use direct IO (posix.odirect)", 0, INI_BOOL, NULL, & o.direct}, {NULL} }; static void validate(void){ @@ -29,7 +31,8 @@ static double run(void){ opt_ior_easy d = ior_easy_o; u_argv_t * argv = u_argv_create(); - ior_easy_add_params(argv, 1); + int direct = (o.direct != INI_UNSET_BOOL) ? o.direct : d.direct; + ior_easy_add_params(argv, 1, direct); u_argv_push(argv, "-w"); /* write file */ u_argv_push(argv, "-D"); /* deadline for stonewall in seconds */ u_argv_push_printf(argv, "%d", opt.stonewall); @@ -40,9 +43,6 @@ static double run(void){ u_argv_push_printf(argv, "saveRankPerformanceDetailsCSV=%s/ior-easy-write.csv", opt.resdir); // u_argv_push_default_if_set(argv, "-U", /* use hints file */ // d.hintsFileName, o.hintsFileName); -// u_argv_push_default_if_set_api_options(argv, "-a", /* backend API */ -// d.api, o.api); -// u_argv_push_default_if_set_bool(argv, "--posix.odirect", d.odirect, o.odirect); o.command = u_flatten_argv(argv); diff --git a/src/phase_ior_rnd_read4k-easywrite.c b/src/phase_ior_rnd_read4k-easywrite.c index 8715bc0..ae10e04 100644 --- a/src/phase_ior_rnd_read4k-easywrite.c +++ b/src/phase_ior_rnd_read4k-easywrite.c @@ -8,6 +8,7 @@ typedef struct{ int run; char * api; + int direct; char * command; IOR_point_t * res; @@ -18,6 +19,7 @@ static opt_ior_rnd_read o; static ini_option_t option[] = { {"API", "The API to be used", 0, INI_STRING, NULL, & o.api}, {"run", "Run this phase", 0, INI_BOOL, "TRUE", & o.run}, + {"direct", "Use direct IO (posix.odirect)", 0, INI_BOOL, NULL, & o.direct}, {NULL} }; @@ -30,7 +32,8 @@ static double run(void){ opt_ior_rnd_read d = o; u_argv_t * argv = u_argv_create(); - ior_easy_add_params(argv, 0); + int direct = (o.direct != INI_UNSET_BOOL) ? o.direct : ior_easy_o.direct; + ior_easy_add_params(argv, 0, direct); u_argv_push(argv, "-r"); u_argv_push(argv, "-D"); u_argv_push_printf(argv, "%d", opt.stonewall); diff --git a/src/phase_mdworkbench.c b/src/phase_mdworkbench.c index 1b14970..e01e5db 100644 --- a/src/phase_mdworkbench.c +++ b/src/phase_mdworkbench.c @@ -94,7 +94,9 @@ void mdworkbench_add_params(u_argv_t * argv, int is_create){ if(! f){ WARNING("Couldn't open mdworkbench-file: %s\n", file); }else{ - fread(& mdtest->rate, sizeof(mdtest->rate), 1, f); + if (fread(& mdtest->rate, sizeof(mdtest->rate), 1, f) != 1) { + WARNING("Failed to read mdworkbench-file: %s\n", file); + } } fclose(f); }