From a4068be551c38e327fb9b054a91cbeb778a9bd76 Mon Sep 17 00:00:00 2001 From: "Julian M. Kunkel" Date: Mon, 26 Aug 2019 15:57:13 +0100 Subject: [PATCH 1/4] Improved help for fsync. --- src/parse_options.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/parse_options.c b/src/parse_options.c index af30c36..47f9920 100755 --- a/src/parse_options.c +++ b/src/parse_options.c @@ -477,7 +477,7 @@ option_help * createGlobalOptions(IOR_param_t * params){ {.help=" -O stoneWallingWearOut=1 -- once the stonewalling timout is over, all process finish to access the amount of data", .arg = OPTION_OPTIONAL_ARGUMENT}, {.help=" -O stoneWallingWearOutIterations=N -- stop after processing this number of iterations, needed for reading data back written with stoneWallingWearOut", .arg = OPTION_OPTIONAL_ARGUMENT}, {.help=" -O stoneWallingStatusFile=FILE -- this file keeps the number of iterations from stonewalling during write and allows to use them for read", .arg = OPTION_OPTIONAL_ARGUMENT}, - {'e', NULL, "fsync -- perform sync operation after each block write", OPTION_FLAG, 'd', & params->fsync}, + {'e', NULL, "fsync -- perform a fsync() operation at the end of each read/write phase", OPTION_FLAG, 'd', & params->fsync}, {'E', NULL, "useExistingTestFile -- do not remove test file before write access", OPTION_FLAG, 'd', & params->useExistingTestFile}, {'f', NULL, "scriptFile -- test script name", OPTION_OPTIONAL_ARGUMENT, 's', & params->testscripts}, {'F', NULL, "filePerProc -- file-per-process", OPTION_FLAG, 'd', & params->filePerProc}, From 4df051bf283675faefcb8523dc034b7f817419c6 Mon Sep 17 00:00:00 2001 From: "Julian M. Kunkel" Date: Mon, 26 Aug 2019 18:57:14 +0100 Subject: [PATCH 2/4] New option -Y to invoke the sync command. --- src/mdtest.c | 47 ++++++++++++++++++++++------------------------- src/utilities.c | 17 ++++++++++++----- src/utilities.h | 1 + 3 files changed, 35 insertions(+), 30 deletions(-) diff --git a/src/mdtest.c b/src/mdtest.c index 77b2759..e07613b 100644 --- a/src/mdtest.c +++ b/src/mdtest.c @@ -148,6 +148,7 @@ static size_t write_bytes; static int stone_wall_timer_seconds; static size_t read_bytes; static int sync_file; +static int call_sync; static int path_count; static int nstride; /* neighbor stride */ static int make_node = 0; @@ -263,6 +264,16 @@ static void prep_testdir(int j, int dir_iter){ pos += sprintf(& testdir[pos], ".%d-%d", j, dir_iter); } +static void phase_end(){ + if (call_sync){ + call_sync_cmd(); + } + + if (barriers) { + MPI_Barrier(testComm); + } +} + /* * This function copies the unique directory name for a given option to * the "to" parameter. Some memory must be allocated to the "to" parameter. @@ -836,9 +847,7 @@ void directory_test(const int iteration, const int ntasks, const char *path, ran } } - if (barriers) { - MPI_Barrier(testComm); - } + phase_end(); t[1] = GetTimeStamp(); /* stat phase */ @@ -864,10 +873,7 @@ void directory_test(const int iteration, const int ntasks, const char *path, ran } } } - - if (barriers) { - MPI_Barrier(testComm); - } + phase_end(); t[2] = GetTimeStamp(); /* read phase */ @@ -894,9 +900,7 @@ void directory_test(const int iteration, const int ntasks, const char *path, ran } } - if (barriers) { - MPI_Barrier(testComm); - } + phase_end(); t[3] = GetTimeStamp(); if (remove_only) { @@ -924,9 +928,7 @@ void directory_test(const int iteration, const int ntasks, const char *path, ran } } - if (barriers) { - MPI_Barrier(testComm); - } + phase_end(); t[4] = GetTimeStamp(); if (remove_only) { @@ -1082,9 +1084,7 @@ void file_test(const int iteration, const int ntasks, const char *path, rank_pro } } - if (barriers) { - MPI_Barrier(testComm); - } + phase_end(); t[1] = GetTimeStamp(); /* stat phase */ @@ -1107,9 +1107,7 @@ void file_test(const int iteration, const int ntasks, const char *path, rank_pro } } - if (barriers) { - MPI_Barrier(testComm); - } + phase_end(); t[2] = GetTimeStamp(); /* read phase */ @@ -1136,9 +1134,7 @@ void file_test(const int iteration, const int ntasks, const char *path, rank_pro } } - if (barriers) { - MPI_Barrier(testComm); - } + phase_end(); t[3] = GetTimeStamp(); if (remove_only) { @@ -1168,9 +1164,7 @@ void file_test(const int iteration, const int ntasks, const char *path, rank_pro } } - if (barriers) { - MPI_Barrier(testComm); - } + phase_end(); t[4] = GetTimeStamp(); if (remove_only) { if (unique_dir_per_task) { @@ -1853,6 +1847,7 @@ void mdtest_init_args(){ stone_wall_timer_seconds = 0; read_bytes = 0; sync_file = 0; + call_sync = 0; path_count = 0; nstride = 0; make_node = 0; @@ -1925,6 +1920,7 @@ mdtest_results_t * mdtest_run(int argc, char **argv, MPI_Comm world_com, FILE * {'x', NULL, "StoneWallingStatusFile; contains the number of iterations of the creation phase, can be used to split phases across runs", OPTION_OPTIONAL_ARGUMENT, 's', & stoneWallingStatusFile}, {'X', "verify-read", "Verify the data read", OPTION_FLAG, 'd', & verify_read}, {'y', NULL, "sync file after writing", OPTION_FLAG, 'd', & sync_file}, + {'Y', NULL, "call the sync command after each phase (included in the timing; note it causes all IO to be flushed from your node)", OPTION_FLAG, 'd', & call_sync}, {'z', NULL, "depth of hierarchical directory structure", OPTION_OPTIONAL_ARGUMENT, 'd', & depth}, {'Z', NULL, "print time instead of rate", OPTION_FLAG, 'd', & print_time}, LAST_OPTION @@ -2008,6 +2004,7 @@ mdtest_results_t * mdtest_run(int argc, char **argv, MPI_Comm world_com, FILE * VERBOSE(1,-1, "unique_dir_per_task : %s", ( unique_dir_per_task ? "True" : "False" )); VERBOSE(1,-1, "write_bytes : "LLU"", write_bytes ); VERBOSE(1,-1, "sync_file : %s", ( sync_file ? "True" : "False" )); + VERBOSE(1,-1, "call_sync : %s", ( call_sync ? "True" : "False" )); VERBOSE(1,-1, "depth : %d", depth ); VERBOSE(1,-1, "make_node : %d", make_node ); diff --git a/src/utilities.c b/src/utilities.c index cdb090e..a2e4b0d 100755 --- a/src/utilities.c +++ b/src/utilities.c @@ -77,15 +77,15 @@ void* safeMalloc(uint64_t size){ } void FailMessage(int rank, const char *location, char *format, ...) { - char msg[4096]; + char msg[4096]; va_list args; va_start(args, format); vsnprintf(msg, 4096, format, args); va_end(args); - fprintf(out_logfile, "%s: Process %d: FAILED in %s, %s: %s\n", - PrintTimestamp(), rank, location, msg, strerror(errno)); - fflush(out_logfile); - MPI_Abort(testComm, 1); + fprintf(out_logfile, "%s: Process %d: FAILED in %s, %s: %s\n", + PrintTimestamp(), rank, location, msg, strerror(errno)); + fflush(out_logfile); + MPI_Abort(testComm, 1); } size_t NodeMemoryStringToBytes(char *size_str) @@ -809,3 +809,10 @@ char *HumanReadable(IOR_offset_t value, int base) } return valueStr; } + +void call_sync_cmd(){ + int ret = system("sync"); + if (ret != 0){ + FAIL("Error executing the sync command, ensure it exists."); + } +} diff --git a/src/utilities.h b/src/utilities.h index d2c9962..b85f957 100755 --- a/src/utilities.h +++ b/src/utilities.h @@ -60,6 +60,7 @@ int QueryNodeMapping(MPI_Comm comm, int print_nodemap); void DelaySecs(int delay); void updateParsedOptions(IOR_param_t * options, options_all_t * global_options); size_t NodeMemoryStringToBytes(char *size_str); +void call_sync_cmd(); /* Returns -1, if cannot be read */ int64_t ReadStoneWallingIterations(char * const filename); From e3db1759b2736aaef826dae756283bfd7e58a1ee Mon Sep 17 00:00:00 2001 From: "Julian M. Kunkel" Date: Sun, 1 Sep 2019 15:47:42 +0100 Subject: [PATCH 3/4] Moded sync() to aiori backend. --- src/aiori-POSIX.c | 12 ++++++++++++ src/aiori.h | 1 + src/mdtest.c | 5 ++++- src/utilities.c | 7 ------- src/utilities.h | 1 - 5 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/aiori-POSIX.c b/src/aiori-POSIX.c index 00e974c..99a68f1 100755 --- a/src/aiori-POSIX.c +++ b/src/aiori-POSIX.c @@ -71,6 +71,7 @@ static IOR_offset_t POSIX_Xfer(int, void *, IOR_size_t *, IOR_offset_t, IOR_param_t *); static void POSIX_Fsync(void *, IOR_param_t *); +static void POSIX_Sync(IOR_param_t * ); /************************** O P T I O N S *****************************/ typedef struct{ @@ -122,6 +123,7 @@ ior_aiori_t posix_aiori = { .stat = aiori_posix_stat, .get_options = POSIX_options, .enable_mdtest = true, + .sync = POSIX_Sync }; /***************************** F U N C T I O N S ******************************/ @@ -588,6 +590,16 @@ static void POSIX_Fsync(void *fd, IOR_param_t * param) EWARNF("fsync(%d) failed", *(int *)fd); } + +static void POSIX_Sync(IOR_param_t * param) +{ + int ret = system("sync"); + if (ret != 0){ + FAIL("Error executing the sync command, ensure it exists."); + } +} + + /* * Close a file through the POSIX interface. */ diff --git a/src/aiori.h b/src/aiori.h index c2074c2..8a5e207 100755 --- a/src/aiori.h +++ b/src/aiori.h @@ -86,6 +86,7 @@ typedef struct ior_aiori { void (*finalize)(); /* called once per program after MPI is shutdown */ option_help * (*get_options)(void ** init_backend_options, void* init_values); /* initializes the backend options as well and returns the pointer to the option help structure */ bool enable_mdtest; + void (*sync)(IOR_param_t * ); /* synchronize every pending operation for this storage */ } ior_aiori_t; enum bench_type { diff --git a/src/mdtest.c b/src/mdtest.c index e34496a..52efa34 100644 --- a/src/mdtest.c +++ b/src/mdtest.c @@ -266,7 +266,10 @@ static void prep_testdir(int j, int dir_iter){ static void phase_end(){ if (call_sync){ - call_sync_cmd(); + if(! backend->sync){ + FAIL("Error, backend does not provide the sync method, but your requested to use sync."); + } + backend->sync(& param); } if (barriers) { diff --git a/src/utilities.c b/src/utilities.c index a2e4b0d..c7e1c8c 100755 --- a/src/utilities.c +++ b/src/utilities.c @@ -809,10 +809,3 @@ char *HumanReadable(IOR_offset_t value, int base) } return valueStr; } - -void call_sync_cmd(){ - int ret = system("sync"); - if (ret != 0){ - FAIL("Error executing the sync command, ensure it exists."); - } -} diff --git a/src/utilities.h b/src/utilities.h index b85f957..d2c9962 100755 --- a/src/utilities.h +++ b/src/utilities.h @@ -60,7 +60,6 @@ int QueryNodeMapping(MPI_Comm comm, int print_nodemap); void DelaySecs(int delay); void updateParsedOptions(IOR_param_t * options, options_all_t * global_options); size_t NodeMemoryStringToBytes(char *size_str); -void call_sync_cmd(); /* Returns -1, if cannot be read */ int64_t ReadStoneWallingIterations(char * const filename); From c83edfe39b49481db7472dce85f1dbe972e6bfc6 Mon Sep 17 00:00:00 2001 From: "Julian M. Kunkel" Date: Sun, 1 Sep 2019 15:59:52 +0100 Subject: [PATCH 4/4] Extracted check function into aiori. #24. #177 --- src/aiori-DUMMY.c | 5 +++++ src/aiori-S3.c | 21 ++++++++++++++++++++- src/aiori.h | 1 + src/ior.c | 15 ++++++--------- 4 files changed, 32 insertions(+), 10 deletions(-) diff --git a/src/aiori-DUMMY.c b/src/aiori-DUMMY.c index 0494cb4..90fec9a 100755 --- a/src/aiori-DUMMY.c +++ b/src/aiori-DUMMY.c @@ -143,6 +143,10 @@ static int DUMMY_stat (const char *path, struct stat *buf, IOR_param_t * param){ return 0; } +static int DUMMY_check_params(IOR_param_t * test){ + return 1; +} + ior_aiori_t dummy_aiori = { .name = "DUMMY", .name_legacy = NULL, @@ -163,4 +167,5 @@ ior_aiori_t dummy_aiori = { .finalize = NULL, .get_options = DUMMY_options, .enable_mdtest = true, + .check_params = DUMMY_check_params }; diff --git a/src/aiori-S3.c b/src/aiori-S3.c index 3fc1208..2c9a9af 100755 --- a/src/aiori-S3.c +++ b/src/aiori-S3.c @@ -159,6 +159,8 @@ static void S3_Fsync(void*, IOR_param_t*); static IOR_offset_t S3_GetFileSize(IOR_param_t*, MPI_Comm, char*); static void S3_init(); static void S3_finalize(); +static int S3_check_params(IOR_param_t *); + /************************** D E C L A R A T I O N S ***************************/ @@ -177,7 +179,8 @@ ior_aiori_t s3_aiori = { .fsync = S3_Fsync, .get_file_size = S3_GetFileSize, .initialize = S3_init, - .finalize = S3_finalize + .finalize = S3_finalize, + .check_params = S3_check_params }; // "S3", plus EMC-extensions enabled @@ -228,6 +231,22 @@ static void S3_finalize(){ aws_cleanup(); } +static int S3_check_params(IOR_param_t * test){ + /* N:1 and N:N */ + IOR_offset_t NtoN = test->filePerProc; + IOR_offset_t Nto1 = ! NtoN; + IOR_offset_t s = test->segmentCount; + IOR_offset_t t = test->transferSize; + IOR_offset_t b = test->blockSize; + + if (Nto1 && (s != 1) && (b != t)) { + ERR("N:1 (strided) requires xfer-size == block-size"); + return 0; + } + + return 1; +} + /* modelled on similar macros in iordef.h */ #define CURL_ERR(MSG, CURL_ERRNO, PARAM) \ do { \ diff --git a/src/aiori.h b/src/aiori.h index 8a5e207..06f9b31 100755 --- a/src/aiori.h +++ b/src/aiori.h @@ -86,6 +86,7 @@ typedef struct ior_aiori { void (*finalize)(); /* called once per program after MPI is shutdown */ option_help * (*get_options)(void ** init_backend_options, void* init_values); /* initializes the backend options as well and returns the pointer to the option help structure */ bool enable_mdtest; + int (*check_params)(IOR_param_t *); /* check if the provided parameters for the given test and the module options are correct, if they aren't print a message and exit(1) or return 1*/ void (*sync)(IOR_param_t * ); /* synchronize every pending operation for this storage */ } ior_aiori_t; diff --git a/src/ior.c b/src/ior.c index 1e66387..123a4b5 100755 --- a/src/ior.c +++ b/src/ior.c @@ -1677,15 +1677,12 @@ static void ValidateTests(IOR_param_t * test) if (test->useExistingTestFile && test->lustre_set_striping) ERR("Lustre stripe options are incompatible with useExistingTestFile"); - /* N:1 and N:N */ - IOR_offset_t NtoN = test->filePerProc; - IOR_offset_t Nto1 = ! NtoN; - IOR_offset_t s = test->segmentCount; - IOR_offset_t t = test->transferSize; - IOR_offset_t b = test->blockSize; - - if (Nto1 && (s != 1) && (b != t)) { - ERR("N:1 (strided) requires xfer-size == block-size"); + /* allow the backend to validate the options */ + if(test->backend->check_params){ + int check = test->backend->check_params(test); + if (check == 0){ + ERR("The backend returned that the test parameters are invalid."); + } } }