Fixed --validate for multi-treaded fileio test.

Patch contributed by Dwight Engen <dwight.engen@oracle.com>
This commit is contained in:
Alexey Kopytov
2015-10-11 15:02:31 +03:00
parent 6d813225e6
commit 2fd08b7872
5 changed files with 84 additions and 56 deletions

View File

@ -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;

View File

@ -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.");

View File

@ -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);

View File

@ -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;

View File

@ -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;
}