From 2fd08b787240eb88f4008a8a1cfbff53eff679f2 Mon Sep 17 00:00:00 2001 From: Alexey Kopytov Date: Sun, 11 Oct 2015 15:02:31 +0300 Subject: [PATCH] Fixed --validate for multi-treaded fileio test. Patch contributed by Dwight Engen --- sysbench/scripting/script_lua.c | 4 +- sysbench/sysbench.c | 2 +- sysbench/sysbench.h | 2 +- sysbench/tests/cpu/sb_cpu.c | 4 +- sysbench/tests/fileio/sb_fileio.c | 128 ++++++++++++++++++------------ 5 files changed, 84 insertions(+), 56 deletions(-) diff --git a/sysbench/scripting/script_lua.c b/sysbench/scripting/script_lua.c index 0ddd732..03c21e7 100644 --- a/sysbench/scripting/script_lua.c +++ b/sysbench/scripting/script_lua.c @@ -90,7 +90,7 @@ static unsigned int nevents; static int sb_lua_init(void); static int sb_lua_done(void); -static sb_request_t sb_lua_get_request(void); +static sb_request_t sb_lua_get_request(int thread_id); static int sb_lua_op_execute_request(sb_request_t *, int); static int sb_lua_op_thread_init(int); static int sb_lua_op_thread_done(int); @@ -234,7 +234,7 @@ int sb_lua_init(void) return 0; } -sb_request_t sb_lua_get_request(void) +sb_request_t sb_lua_get_request(int __attribute__((unused))thread_id) { sb_request_t req; diff --git a/sysbench/sysbench.c b/sysbench/sysbench.c index 316d03b..4cdd457 100644 --- a/sysbench/sysbench.c +++ b/sysbench/sysbench.c @@ -213,7 +213,7 @@ static sb_request_t get_request(sb_test_t *test, int thread_id) (void)thread_id; /* unused */ if (test->ops.get_request != NULL) - r = test->ops.get_request(); + r = test->ops.get_request(thread_id); else { log_text(LOG_ALERT, "Unsupported mode! Creating NULL request."); diff --git a/sysbench/sysbench.h b/sysbench/sysbench.h index 00f329f..74d9fb9 100644 --- a/sysbench/sysbench.h +++ b/sysbench/sysbench.h @@ -133,7 +133,7 @@ typedef int sb_op_init(void); typedef int sb_op_prepare(void); typedef int sb_op_thread_init(int); typedef void sb_op_print_mode(void); -typedef sb_request_t sb_op_get_request(void); +typedef sb_request_t sb_op_get_request(int); typedef int sb_op_execute_request(sb_request_t *, int); typedef void sb_op_print_stats(sb_stat_t); typedef int sb_op_thread_done(int); diff --git a/sysbench/tests/cpu/sb_cpu.c b/sysbench/tests/cpu/sb_cpu.c index 1749652..48da450 100644 --- a/sysbench/tests/cpu/sb_cpu.c +++ b/sysbench/tests/cpu/sb_cpu.c @@ -38,7 +38,7 @@ static sb_arg_t cpu_args[] = /* CPU test operations */ static int cpu_init(void); static void cpu_print_mode(void); -static sb_request_t cpu_get_request(void); +static sb_request_t cpu_get_request(int thread_id); static int cpu_execute_request(sb_request_t *, int); static int cpu_done(void); @@ -97,7 +97,7 @@ int cpu_init(void) } -sb_request_t cpu_get_request(void) +sb_request_t cpu_get_request(int __attribute__ ((unused)) thread_id) { sb_request_t req; diff --git a/sysbench/tests/fileio/sb_fileio.c b/sysbench/tests/fileio/sb_fileio.c index 42a43e0..1dff24d 100644 --- a/sysbench/tests/fileio/sb_fileio.c +++ b/sysbench/tests/fileio/sb_fileio.c @@ -138,6 +138,15 @@ typedef struct static sb_aio_context_t *aio_ctxts; #endif +typedef struct +{ + void *buffer; + unsigned int buffer_file_id; + long long buffer_pos; +} sb_per_thread_t; + +static sb_per_thread_t *per_thread; + /* Test options */ static unsigned int num_files; static long long total_size; @@ -184,9 +193,6 @@ static unsigned long file_page_mask; /* Array of file descriptors */ static FILE_DESCRIPTOR *files; -/* Buffer for all I/O operations */ -static void *buffer; - /* test mode type */ static file_test_mode_t test_mode; @@ -229,7 +235,7 @@ static int file_cmd_cleanup(void); static int file_init(void); static void file_print_mode(void); static int file_prepare(void); -static sb_request_t file_get_request(void); +static sb_request_t file_get_request(int thread_id); static int file_execute_request(sb_request_t *, int); #ifdef HAVE_LIBAIO static int file_thread_done(int); @@ -274,7 +280,7 @@ static int parse_arguments(void); static void clear_stats(void); static void init_vars(void); static sb_request_t file_get_seq_request(void); -static sb_request_t file_get_rnd_request(void); +static sb_request_t file_get_rnd_request(int thread_id); static void check_seq_req(sb_file_request_t *, sb_file_request_t *); static const char *get_io_mode_str(file_io_mode_t mode); static const char *get_test_mode_str(file_test_mode_t mode); @@ -389,22 +395,27 @@ int file_done(void) return 1; #endif - if (buffer != NULL) - sb_free_memaligned(buffer); + for (i = 0; i < sb_globals.num_threads; i++) + { + if (per_thread[i].buffer != NULL) + sb_free_memaligned(per_thread[i].buffer); + } + + free(per_thread); sb_percentile_done(&local_percentile); return 0; } -sb_request_t file_get_request(void) +sb_request_t file_get_request(int thread_id) { if (test_mode == MODE_WRITE || test_mode == MODE_REWRITE || test_mode == MODE_READ) return file_get_seq_request(); - return file_get_rnd_request(); + return file_get_rnd_request(thread_id); } @@ -499,25 +510,16 @@ sb_request_t file_get_seq_request(void) { current_file++; position=0; - - if (sb_globals.validate) - { - check_seq_req(&prev_req, file_req); - prev_req = *file_req; - } - - SB_THREAD_MUTEX_UNLOCK(); - return sb_req; /* This request is valid even for last file */ } - SB_THREAD_MUTEX_UNLOCK(); - if (sb_globals.validate) { check_seq_req(&prev_req, file_req); prev_req = *file_req; } + SB_THREAD_MUTEX_UNLOCK(); + return sb_req; } @@ -525,7 +527,7 @@ sb_request_t file_get_seq_request(void) /* Request generatior for random tests */ -sb_request_t file_get_rnd_request(void) +sb_request_t file_get_rnd_request(int thread_id) { sb_request_t sb_req; sb_file_request_t *file_req = &sb_req.u.file_request; @@ -533,7 +535,8 @@ sb_request_t file_get_rnd_request(void) unsigned long long tmppos; int real_mode = test_mode; int mode = test_mode; - + unsigned int i; + sb_req.type = SB_REQ_TYPE_FILE; SB_THREAD_MUTEX_LOCK(); @@ -598,18 +601,37 @@ sb_request_t file_get_rnd_request(void) } } - randnum=sb_rnd(); if (mode==MODE_RND_WRITE) /* mode shall be WRITE or RND_WRITE only */ file_req->operation = FILE_OP_TYPE_WRITE; - else + else file_req->operation = FILE_OP_TYPE_READ; - tmppos = (long long)((double)randnum / (double)SB_MAX_RND * (double)(total_size)); - tmppos = tmppos - (tmppos % (long long)file_block_size); - file_req->file_id = (int)(tmppos / (long long)file_size); - file_req->pos = (long long)(tmppos % (long long)file_size); +retry: + randnum = sb_rnd(); + + tmppos = (long long) ((double) randnum / SB_MAX_RND * total_size); + tmppos = tmppos - (tmppos % (long long) file_block_size); + file_req->file_id = (int) (tmppos / (long long) file_size); + file_req->pos = (long long) (tmppos % (long long) file_size); file_req->size = file_block_size; + if (sb_globals.validate) + { + /* + For the multi-threaded validation test we have to make sure the block is + not being used by another thread + */ + for (i = 0; i < sb_globals.num_threads; i++) + { + if (i != (unsigned) thread_id && per_thread[i].buffer_file_id == file_req->file_id && + per_thread[i].buffer_pos == file_req->pos) + goto retry; + } + } + + per_thread[thread_id].buffer_file_id = file_req->file_id; + per_thread[thread_id].buffer_pos = file_req->pos; + req_performed++; if (file_req->operation == FILE_OP_TYPE_WRITE) is_dirty = 1; @@ -661,11 +683,11 @@ int file_execute_request(sb_request_t *sb_req, int thread_id) /* Store checksum and offset in a buffer when in validation mode */ if (sb_globals.validate) - file_fill_buffer(buffer, file_req->size, file_req->pos); + file_fill_buffer(per_thread[thread_id].buffer, file_req->size, file_req->pos); LOG_EVENT_START(msg, thread_id); - if(file_pwrite(file_req->file_id, buffer, file_req->size, file_req->pos, - thread_id) + if(file_pwrite(file_req->file_id, per_thread[thread_id].buffer, + file_req->size, file_req->pos, thread_id) != (ssize_t)file_req->size) { log_errno(LOG_FATAL, "Failed to write file! file: " FD_FMT " pos: %lld", @@ -704,8 +726,8 @@ int file_execute_request(sb_request_t *sb_req, int thread_id) break; case FILE_OP_TYPE_READ: LOG_EVENT_START(msg, thread_id); - if(file_pread(file_req->file_id, buffer, file_req->size, file_req->pos, - thread_id) + if(file_pread(file_req->file_id, per_thread[thread_id].buffer, + file_req->size, file_req->pos, thread_id) != (ssize_t)file_req->size) { log_errno(LOG_FATAL, "Failed to read file! file: " FD_FMT " pos: %lld", @@ -719,7 +741,7 @@ int file_execute_request(sb_request_t *sb_req, int thread_id) /* Validate block if run with validation enabled */ if (sb_globals.validate && - file_validate_buffer(buffer, file_req->size, file_req->pos)) + file_validate_buffer(per_thread[thread_id].buffer, file_req->size, file_req->pos)) { log_text(LOG_FATAL, "Validation failed on file " FD_FMT ", block offset 0x%x, exiting...", @@ -1041,12 +1063,12 @@ int create_files(void) { /* If in validation mode, fill buffer with random values - and write checksum + and write checksum. Not called in parallel, so use per_thread[0]. */ if (sb_globals.validate) - file_fill_buffer(buffer, file_block_size, offset); + file_fill_buffer(per_thread[0].buffer, file_block_size, offset); - if (write(fd, buffer, file_block_size) < 0) + if (write(fd, per_thread[0].buffer, file_block_size) < 0) goto error; } @@ -1655,7 +1677,7 @@ ssize_t file_pread(unsigned int file_id, void *buf, ssize_t count, fd, page_addr); if (start == MAP_FAILED) return 0; - memcpy(buffer, (char *)start + page_offset, count); + memcpy(buf, (char *)start + page_offset, count); munmap(start, count + page_offset); return count; # else @@ -1664,7 +1686,7 @@ ssize_t file_pread(unsigned int file_id, void *buf, ssize_t count, (void)page_offset; /* unused */ /* We already have all files mapped on 64-bit platforms */ - memcpy(buffer, (char *)mmaps[file_id] + offset, count); + memcpy(buf, (char *)mmaps[file_id] + offset, count); return count; # endif @@ -1716,7 +1738,7 @@ ssize_t file_pwrite(unsigned int file_id, void *buf, ssize_t count, if (start == MAP_FAILED) return 0; - memcpy((char *)start + page_offset, buffer, count); + memcpy((char *)start + page_offset, buf, count); munmap(start, count + page_offset); return count; @@ -1726,7 +1748,7 @@ ssize_t file_pwrite(unsigned int file_id, void *buf, ssize_t count, (void)page_offset; /* unused */ /* We already have all files mapped on 64-bit platforms */ - memcpy((char *)mmaps[file_id] + offset, buffer, count); + memcpy((char *)mmaps[file_id] + offset, buf, count); return count; # endif @@ -1743,6 +1765,7 @@ ssize_t file_pwrite(unsigned int file_id, void *buf, ssize_t count, int parse_arguments(void) { char *mode; + unsigned int i; num_files = sb_get_value_int("file-num"); @@ -1898,13 +1921,17 @@ int parse_arguments(void) return 1; } - buffer = sb_memalign(file_max_request_size); + per_thread = malloc(sizeof(*per_thread) * sb_globals.num_threads); + for (i = 0; i < sb_globals.num_threads; i++) + { + per_thread[i].buffer = sb_memalign(file_max_request_size); + } return 0; } -/* check if two request given out are really sequential) */ +/* check if two requests are sequential */ void check_seq_req(sb_file_request_t *prev_req, sb_file_request_t *r) @@ -1916,7 +1943,8 @@ void check_seq_req(sb_file_request_t *prev_req, sb_file_request_t *r) if (prev_req->operation == FILE_OP_TYPE_NULL) return; /* check files */ - if (r->file_id - prev_req->file_id>1) + if (r->file_id - prev_req->file_id>1 && + !(r->file_id == 0 && prev_req->file_id == num_files-1)) { log_text(LOG_WARNING, "Discovered too large file difference in seq requests!"); @@ -2057,10 +2085,10 @@ void file_fill_buffer(unsigned char *buf, unsigned int len, buf[i] = sb_rnd() & 0xFF; /* Store the checksum */ - *(int *)(buf + i) = (int)crc32(0, (unsigned char *)buf, len - + *(int *)(void *)(buf + i) = (int)crc32(0, (unsigned char *)buf, len - (FILE_CHECKSUM_LENGTH + FILE_OFFSET_LENGTH)); /* Store the offset */ - *(long *)(buf + i + FILE_CHECKSUM_LENGTH) = offset; + *(long *)(void *)(buf + i + FILE_CHECKSUM_LENGTH) = offset; } @@ -2076,19 +2104,19 @@ int file_validate_buffer(unsigned char *buf, unsigned int len, size_t offset) checksum = (unsigned int)crc32(0, (unsigned char *)buf, cs_offset); - if (checksum != *(unsigned int *)(buf + cs_offset)) + if (checksum != *(unsigned int *)(void *)(buf + cs_offset)) { log_text(LOG_FATAL, "Checksum mismatch in block: ", offset); log_text(LOG_FATAL, " Calculated value: 0x%x Stored value: 0x%x", - checksum, *(unsigned int *)(buf + cs_offset)); + checksum, *(unsigned int *)(void *)(buf + cs_offset)); return 1; } - if (offset != *(size_t *)(buf + cs_offset + FILE_CHECKSUM_LENGTH)) + if (offset != *(size_t *)(void *)(buf + cs_offset + FILE_CHECKSUM_LENGTH)) { log_text(LOG_FATAL, "Offset mismatch in block:"); log_text(LOG_FATAL, " Actual offset: %ld Stored offset: %ld", - offset, *(size_t *)(buf + cs_offset + FILE_CHECKSUM_LENGTH)); + offset, *(size_t *)(void *)(buf + cs_offset + FILE_CHECKSUM_LENGTH)); return 1; }