From 03dbb20594acbb611ffb4124ac4e496c0fe6c3bb Mon Sep 17 00:00:00 2001 From: "Julian M. Kunkel" Date: Mon, 29 Jun 2020 20:15:14 +0100 Subject: [PATCH 1/3] MDTest changed verification pattern. Read now always checks the first byte/8 bytes for the signature (item number). Added also --verify-write option which performs a read immediately after a write. Supports #206 --- src/mdtest.c | 70 ++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 51 insertions(+), 19 deletions(-) diff --git a/src/mdtest.c b/src/mdtest.c index 0e407a6..85e081f 100644 --- a/src/mdtest.c +++ b/src/mdtest.c @@ -106,8 +106,6 @@ static char unique_read_dir[MAX_PATHLEN]; static char unique_rm_dir[MAX_PATHLEN]; static char unique_rm_uni_dir[MAX_PATHLEN]; static char *write_buffer; -static char *read_buffer; -static char *verify_read_buffer; static char *stoneWallingStatusFile; @@ -116,6 +114,7 @@ static int create_only; static int stat_only; static int read_only; static int verify_read; +static int verify_write; static int verification_error; static int remove_only; static int leaf_only; @@ -213,7 +212,8 @@ void VerboseMessage (int root_level, int any_level, int line, char * format, ... } void generate_memory_pattern(char * buffer, size_t bytes){ - for(int i=0; i < bytes; i++){ + // the first byte is set to the item number + for(int i=1; i < bytes; i++){ buffer[i] = i + 1; } } @@ -344,6 +344,22 @@ static void remove_file (const char *path, uint64_t itemNum) { } } +void mdtest_verify_data(int item, char * buffer, size_t bytes){ + if((bytes >= 8 && ((uint64_t*) buffer)[0] != item) || (bytes < 8 && buffer[0] != (char) item)){ + VERBOSE(2, -1, "Error verifying first element for item: %d", item); + verification_error++; + } + + size_t i = bytes < 8 ? 1 : 8; // the first byte + + for( ; i < bytes; i++){ + if(buffer[i] != (char) (i + 1)){ + VERBOSE(0, -1, "Error verifying byte %zu for item %d", i, item); + verification_error++; + } + } +} + static void create_file (const char *path, uint64_t itemNum) { char curr_item[MAX_PATHLEN]; aiori_fd_t *aiori_fh = NULL; @@ -392,9 +408,22 @@ static void create_file (const char *path, uint64_t itemNum) { * offset 0 (zero). */ hints.fsyncPerWrite = sync_file; - if ( write_bytes != (size_t) backend->xfer (WRITE, aiori_fh, (IOR_size_t *) write_buffer, write_bytes, 0, backend_options)) { + if(write_bytes >= 8){ // set the item number as first element of the buffer to be as much unique as possible + ((uint64_t*) write_buffer)[0] = itemNum; + }else{ + write_buffer[0] = (char) itemNum; + } + if ( write_bytes != (size_t) backend->xfer(WRITE, aiori_fh, (IOR_size_t *) write_buffer, write_bytes, 0, backend_options)) { FAIL("unable to write file %s", curr_item); } + + if (verify_write) { + write_buffer[0] = 42; + if (write_bytes != (size_t) backend->xfer(READ, aiori_fh, (IOR_size_t *) write_buffer, write_bytes, 0, backend_options)) { + FAIL("unable to verify write (read/back) file %s", curr_item); + } + mdtest_verify_data(itemNum, write_buffer, write_bytes); + } } VERBOSE(3,5,"create_remove_items_helper: close..." ); @@ -616,7 +645,6 @@ void mdtest_stat(const int random, const int dirs, const long dir_iter, const ch } } - /* reads all of the items created as specified by the input parameters */ void mdtest_read(int random, int dirs, const long dir_iter, char *path) { uint64_t parent_dir, item_num = 0; @@ -624,6 +652,7 @@ void mdtest_read(int random, int dirs, const long dir_iter, char *path) { aiori_fd_t *aiori_fh; VERBOSE(1,-1,"Entering mdtest_read on %s", path ); + char *read_buffer; /* allocate read buffer */ if (read_bytes > 0) { @@ -631,14 +660,6 @@ void mdtest_read(int random, int dirs, const long dir_iter, char *path) { if (alloc_res) { FAIL("out of memory"); } - - if (verify_read > 0) { - verify_read_buffer = (char *)malloc(read_bytes); - if (verify_read_buffer == NULL) { - FAIL("out of memory"); - } - generate_memory_pattern(verify_read_buffer, read_bytes); - } } uint64_t stop_items = items; @@ -714,21 +735,24 @@ void mdtest_read(int random, int dirs, const long dir_iter, char *path) { /* read file */ if (read_bytes > 0) { - read_buffer[0] = 42; /* use a random value to ensure that the read_buffer is now different from the expected buffer and read isn't sometimes NOOP */ - if (read_bytes != (size_t) backend->xfer (READ, aiori_fh, (IOR_size_t *) read_buffer, read_bytes, 0, backend_options)) { + read_buffer[0] = 42; + if (read_bytes != (size_t) backend->xfer(READ, aiori_fh, (IOR_size_t *) read_buffer, read_bytes, 0, backend_options)) { FAIL("unable to read file %s", item); } if(verify_read){ - if (memcmp(read_buffer, verify_read_buffer, read_bytes) != 0){ - VERBOSE(2, -1, "Error verifying %s", item); - verification_error++; - } + mdtest_verify_data(item_num, read_buffer, read_bytes); + }else if((read_bytes >= 8 && ((uint64_t*) read_buffer)[0] != item_num) || (read_bytes < 8 && read_buffer[0] != (char) item_num)){ + // do a lightweight check, which cost is neglectable + verification_error++; } } /* close file */ backend->close (aiori_fh, backend_options); } + if(read_bytes){ + free(read_buffer); + } } /* This method should be called by rank 0. It subsequently does all of @@ -1471,6 +1495,9 @@ void md_validate_tests() { if(read_only && read_bytes <= 0) WARN("Read bytes is 0, thus, a read test will actually just open/close"); + + if(create_only && read_only && read_bytes > write_bytes) + FAIL("When writing and reading files, read bytes must be smaller than write bytes"); } void show_file_system_size(char *file_system) { @@ -1954,6 +1981,7 @@ mdtest_results_t * mdtest_run(int argc, char **argv, MPI_Comm world_com, FILE * {'W', NULL, "number in seconds; stonewall timer, write as many seconds and ensure all processes did the same number of operations (currently only stops during create phase)", OPTION_OPTIONAL_ARGUMENT, 'd', & stone_wall_timer_seconds}, {'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}, + {0, "verify-write", "Verify the data after a write by reading it back immediately", OPTION_FLAG, 'd', & verify_write}, {'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}, @@ -2277,5 +2305,9 @@ mdtest_results_t * mdtest_run(int argc, char **argv, MPI_Comm world_com, FILE * backend->finalize(backend_options); } + if (write_bytes > 0) { + free(write_buffer); + } + return summary_table; } From 3e6bfd2db76011d029d76893a6f6a331c0361609 Mon Sep 17 00:00:00 2001 From: "Julian M. Kunkel" Date: Mon, 29 Jun 2020 20:58:45 +0100 Subject: [PATCH 2/3] Added missing header info. --- src/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile.am b/src/Makefile.am index 567d9ce..7cbd448 100755 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -5,7 +5,7 @@ if USE_CAPS bin_PROGRAMS += IOR MDTEST endif -noinst_HEADERS = ior.h utilities.h parse_options.h aiori.h iordef.h ior-internal.h option.h mdtest.h +noinst_HEADERS = ior.h utilities.h parse_options.h aiori.h iordef.h ior-internal.h option.h mdtest.h aiori-debug.h lib_LIBRARIES = libaiori.a libaiori_a_SOURCES = ior.c mdtest.c utilities.c parse_options.c ior-output.c option.c From 5a5b90cdaa8cb47b55f02ad65fd556480dbec2b6 Mon Sep 17 00:00:00 2001 From: "Julian M. Kunkel" Date: Tue, 30 Jun 2020 11:17:46 +0100 Subject: [PATCH 3/3] Run existing check to allow only supported backends in mdtest. --- src/mdtest.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/mdtest.c b/src/mdtest.c index 85e081f..ce07981 100644 --- a/src/mdtest.c +++ b/src/mdtest.c @@ -1994,6 +1994,8 @@ mdtest_results_t * mdtest_run(int argc, char **argv, MPI_Comm world_com, FILE * backend = aiori_select(api); if (backend == NULL) ERR("Unrecognized I/O API"); + if (! backend->enable_mdtest) + ERR("Backend doesn't support MDTest"); backend_options = airoi_update_module_options(backend, global_options); free(global_options->modules);