Recent changes (master)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The following changes since commit d5e3f5d8ef7fab70288aa57c8660bc3d2199655f:

  Add info log on whether tsc is reliable or not for --cpuclock-test (2013-01-18 20:13:45 +0100)

are available in the git repository at:
  git://git.kernel.dk/fio.git master

Bruce Cran (1):
      Fix _SC_NPROCESSORS_ONLN on Windows

Jens Axboe (9):
      gettime: use proper uint64_t types where needed
      lfsr: add lfsr_reset()
      axmap: clear map->first_free when we reset it
      Re-seed random generator when a file is reset
      verify: add new experimental mode that requires no meta data
      Add generic hweight helpers
      Add hweight64()
      windows: use hweight64(), it's a 64-bit type
      Use unsigned long long for the uint64_t type

 Makefile           |    2 +-
 backend.c          |   46 +++++++++++++++++++++++++++++++++-------------
 file.h             |    9 +--------
 filesetup.c        |   14 ++++++++++++--
 fio.h              |    1 +
 gettime.c          |   16 ++++++++--------
 io_u.c             |   14 +++++++++++---
 ioengines.c        |    2 +-
 lib/axmap.c        |    3 ++-
 lib/hweight.c      |   33 +++++++++++++++++++++++++++++++++
 lib/hweight.h      |   10 ++++++++++
 lib/lfsr.c         |   18 +++++++++++++-----
 lib/lfsr.h         |    1 +
 libfio.c           |    2 +-
 options.c          |    5 +++++
 os/windows/posix.c |   45 +++++++++++++++++++++++++++++++++++++++------
 verify.c           |    9 +--------
 17 files changed, 173 insertions(+), 57 deletions(-)
 create mode 100644 lib/hweight.c
 create mode 100644 lib/hweight.h

---

Diff of recent changes:

diff --git a/Makefile b/Makefile
index 03e46fa..967996d 100644
--- a/Makefile
+++ b/Makefile
@@ -29,7 +29,7 @@ SOURCE := gettime.c fio.c ioengines.c init.c stat.c log.c time.c filesetup.c \
 		engines/mmap.c engines/sync.c engines/null.c engines/net.c \
 		memalign.c server.c client.c iolog.c backend.c libfio.c flow.c \
 		json.c lib/zipf.c lib/axmap.c lib/lfsr.c gettime-thread.c \
-		helpers.c lib/flist_sort.c
+		helpers.c lib/flist_sort.c lib/hweight.c
 
 ifdef CONFIG_64BIT_LLP64
   CFLAGS += -DBITS_PER_LONG=32
diff --git a/backend.c b/backend.c
index 7cebf4d..507faa9 100644
--- a/backend.c
+++ b/backend.c
@@ -393,11 +393,12 @@ static int break_on_this_error(struct thread_data *td, enum fio_ddir ddir,
  * The main verify engine. Runs over the writes we previously submitted,
  * reads the blocks back in, and checks the crc/md5 of the data.
  */
-static void do_verify(struct thread_data *td)
+static void do_verify(struct thread_data *td, uint64_t verify_bytes)
 {
 	struct fio_file *f;
 	struct io_u *io_u;
 	int ret, min_events;
+	uint64_t io_bytes;
 	unsigned int i;
 
 	dprint(FD_VERIFY, "starting loop\n");
@@ -421,6 +422,7 @@ static void do_verify(struct thread_data *td)
 	td_set_runstate(td, TD_VERIFYING);
 
 	io_u = NULL;
+	io_bytes = 0;
 	while (!td->terminate) {
 		enum fio_ddir ddir;
 		int ret2, full;
@@ -438,18 +440,27 @@ static void do_verify(struct thread_data *td)
 		if (flow_threshold_exceeded(td))
 			continue;
 
-		io_u = __get_io_u(td);
-		if (!io_u)
-			break;
+		if (!td->o.experimental_verify) {
+			io_u = __get_io_u(td);
+			if (!io_u)
+				break;
 
-		if (get_next_verify(td, io_u)) {
-			put_io_u(td, io_u);
-			break;
-		}
+			if (get_next_verify(td, io_u)) {
+				put_io_u(td, io_u);
+				break;
+			}
 
-		if (td_io_prep(td, io_u)) {
-			put_io_u(td, io_u);
-			break;
+			if (td_io_prep(td, io_u)) {
+				put_io_u(td, io_u);
+				break;
+			}
+		} else {
+			io_u = get_io_u(td);
+			if (!io_u)
+				break;
+
+			if (io_u->buflen + io_bytes > verify_bytes)
+				break;
 		}
 
 		if (td->o.verify_async)
@@ -480,6 +491,7 @@ static void do_verify(struct thread_data *td)
 				io_u->xfer_buflen = io_u->resid;
 				io_u->xfer_buf += bytes;
 				io_u->offset += bytes;
+				io_bytes += bytes;
 
 				if (ddir_rw(io_u->ddir))
 					td->ts.short_io_u[io_u->ddir]++;
@@ -495,6 +507,7 @@ sync_done:
 				if (ret < 0)
 					break;
 			}
+			io_bytes += io_u->xfer_buflen;
 			continue;
 		case FIO_Q_QUEUED:
 			break;
@@ -529,15 +542,18 @@ sync_done:
 				min_events = 1;
 
 			do {
+				unsigned long bytes = 0;
+
 				/*
 				 * Reap required number of io units, if any,
 				 * and do the verification on them through
 				 * the callback handler
 				 */
-				if (io_u_queued_complete(td, min_events, NULL) < 0) {
+				if (io_u_queued_complete(td, min_events, &bytes) < 0) {
 					ret = -1;
 					break;
 				}
+				io_bytes += bytes;
 			} while (full && (td->cur_depth > td->o.iodepth_low));
 		}
 		if (ret < 0)
@@ -1174,6 +1190,8 @@ static void *thread_main(void *data)
 
 	clear_state = 0;
 	while (keep_running(td)) {
+		uint64_t write_bytes;
+
 		fio_gettime(&td->start, NULL);
 		memcpy(&td->bw_sample_time, &td->start, sizeof(td->start));
 		memcpy(&td->iops_sample_time, &td->start, sizeof(td->start));
@@ -1194,7 +1212,9 @@ static void *thread_main(void *data)
 
 		prune_io_piece_log(td);
 
+		write_bytes = td->io_bytes[DDIR_WRITE];
 		do_io(td);
+		write_bytes = td->io_bytes[DDIR_WRITE] - write_bytes;
 
 		clear_state = 1;
 
@@ -1223,7 +1243,7 @@ static void *thread_main(void *data)
 
 		fio_gettime(&td->start, NULL);
 
-		do_verify(td);
+		do_verify(td, write_bytes);
 
 		td->ts.runtime[DDIR_READ] += utime_since_now(&td->start);
 
diff --git a/file.h b/file.h
index 5f125c3..95ecefe 100644
--- a/file.h
+++ b/file.h
@@ -175,13 +175,6 @@ extern int init_random_map(struct thread_data *);
 extern void dup_files(struct thread_data *, struct thread_data *);
 extern int get_fileno(struct thread_data *, const char *);
 extern void free_release_files(struct thread_data *);
-
-static inline void fio_file_reset(struct fio_file *f)
-{
-	f->last_pos = f->file_offset;
-	f->last_start = -1ULL;
-	if (f->io_axmap)
-		axmap_reset(f->io_axmap);
-}
+void fio_file_reset(struct thread_data *, struct fio_file *);
 
 #endif
diff --git a/filesetup.c b/filesetup.c
index 478bda8..d0aef21 100644
--- a/filesetup.c
+++ b/filesetup.c
@@ -1073,7 +1073,7 @@ int add_file(struct thread_data *td, const char *fname)
 
 	f->fd = -1;
 	f->shadow_fd = -1;
-	fio_file_reset(f);
+	fio_file_reset(td, f);
 
 	if (td->files_size <= td->files_index) {
 		unsigned int new_size = td->o.nr_files + 1;
@@ -1319,7 +1319,7 @@ void dup_files(struct thread_data *td, struct thread_data *org)
 			assert(0);
 		}
 		__f->fd = -1;
-		fio_file_reset(__f);
+		fio_file_reset(td, __f);
 
 		if (f->file_name) {
 			__f->file_name = smalloc_strdup(f->file_name);
@@ -1359,3 +1359,13 @@ void free_release_files(struct thread_data *td)
 	td->files_index = 0;
 	td->nr_normal_files = 0;
 }
+
+void fio_file_reset(struct thread_data *td, struct fio_file *f)
+{
+	f->last_pos = f->file_offset;
+	f->last_start = -1ULL;
+	if (f->io_axmap)
+		axmap_reset(f->io_axmap);
+	if (td->o.random_generator == FIO_RAND_GEN_LFSR)
+		lfsr_reset(&f->lfsr, td->rand_seeds[FIO_RAND_BLOCK_OFF]);
+}
diff --git a/fio.h b/fio.h
index c5e2bf1..ed793ae 100644
--- a/fio.h
+++ b/fio.h
@@ -159,6 +159,7 @@ struct thread_options {
 	unsigned int verify_async;
 	unsigned long long verify_backlog;
 	unsigned int verify_batch;
+	unsigned int experimental_verify;
 	unsigned int use_thread;
 	unsigned int unlink;
 	unsigned int do_disk_util;
diff --git a/gettime.c b/gettime.c
index f29edcb..cc9dcb7 100644
--- a/gettime.c
+++ b/gettime.c
@@ -21,8 +21,8 @@ int tsc_reliable = 0;
 
 struct tv_valid {
 	struct timeval last_tv;
+	uint64_t last_cycles;
 	int last_tv_valid;
-	unsigned long last_cycles;
 };
 #ifdef CONFIG_TLS_THREAD
 static struct tv_valid __thread static_tv_valid;
@@ -168,7 +168,7 @@ static void *__fio_gettime(struct timeval *tp)
 #endif
 #ifdef ARCH_HAVE_CPU_CLOCK
 	case CS_CPUCLOCK: {
-		unsigned long long usecs, t;
+		uint64_t usecs, t;
 
 		t = get_cpu_clock();
 		if (tv && t < tv->last_cycles) {
@@ -233,7 +233,7 @@ void fio_gettime(struct timeval *tp, void fio_unused *caller)
 static unsigned long get_cycles_per_usec(void)
 {
 	struct timeval s, e;
-	unsigned long long c_s, c_e;
+	uint64_t c_s, c_e;
 	enum fio_cs old_cs = fio_clock_source;
 
 #ifdef CONFIG_CLOCK_GETTIME
@@ -245,7 +245,7 @@ static unsigned long get_cycles_per_usec(void)
 
 	c_s = get_cpu_clock();
 	do {
-		unsigned long long elapsed;
+		uint64_t elapsed;
 
 		__fio_gettime(&e);
 
@@ -265,7 +265,7 @@ static unsigned long get_cycles_per_usec(void)
 static void calibrate_cpu_clock(void)
 {
 	double delta, mean, S;
-	unsigned long avg, cycles[NR_TIME_ITERS];
+	uint64_t avg, cycles[NR_TIME_ITERS];
 	int i, samples;
 
 	cycles[0] = get_cycles_per_usec();
@@ -429,9 +429,9 @@ uint64_t time_since_now(struct timeval *s)
 #define CLOCK_ENTRIES	100000
 
 struct clock_entry {
-	unsigned long seq;
-	unsigned long tsc;
-	unsigned long cpu;
+	uint64_t seq;
+	uint64_t tsc;
+	uint64_t cpu;
 };
 
 struct clock_thread {
diff --git a/io_u.c b/io_u.c
index 3de04ef..f020cac 100644
--- a/io_u.c
+++ b/io_u.c
@@ -183,7 +183,8 @@ static int get_next_rand_offset(struct thread_data *td, struct fio_file *f,
 	 * any stored write metadata, just return a random offset
 	 */
 	if (!td->o.verifysort_nr || !(ddir == DDIR_READ && td->o.do_verify &&
-	    td->o.verify != VERIFY_NONE && td_random(td)))
+	    td->o.verify != VERIFY_NONE && td_random(td)) ||
+	    td->o.random_generator == FIO_RAND_GEN_TAUSWORTHE)
 		return get_off_from_method(td, f, ddir, b);
 
 	if (!flist_empty(&td->next_rand_list)) {
@@ -223,7 +224,7 @@ static int get_next_rand_block(struct thread_data *td, struct fio_file *f,
 		return 0;
 
 	if (td->o.time_based) {
-		fio_file_reset(f);
+		fio_file_reset(td, f);
 		if (!get_next_rand_offset(td, f, ddir, b))
 			return 0;
 	}
@@ -545,6 +546,12 @@ static enum fio_ddir get_rw_ddir(struct thread_data *td)
 	enum fio_ddir ddir;
 
 	/*
+	 * If verify phase started, it's always a READ
+	 */
+	if (td->runstate == TD_VERIFYING)
+		return DDIR_READ;
+
+	/*
 	 * see if it's time to fsync
 	 */
 	if (td->o.fsync_blocks &&
@@ -1418,7 +1425,8 @@ static void io_completed(struct thread_data *td, struct io_u *io_u,
 
 		if (td_write(td) && idx == DDIR_WRITE &&
 		    td->o.do_verify &&
-		    td->o.verify != VERIFY_NONE)
+		    td->o.verify != VERIFY_NONE &&
+		    !td->o.experimental_verify)
 			log_io_piece(td, io_u);
 
 		icd->bytes_done[idx] += bytes;
diff --git a/ioengines.c b/ioengines.c
index a87175a..f81c46f 100644
--- a/ioengines.c
+++ b/ioengines.c
@@ -397,7 +397,7 @@ int td_io_open_file(struct thread_data *td, struct fio_file *f)
 		return 1;
 	}
 
-	fio_file_reset(f);
+	fio_file_reset(td, f);
 	fio_file_set_open(f);
 	fio_file_clear_closing(f);
 	disk_util_inc(f->du);
diff --git a/lib/axmap.c b/lib/axmap.c
index a44e0ec..d9ad30b 100644
--- a/lib/axmap.c
+++ b/lib/axmap.c
@@ -67,6 +67,8 @@ void axmap_reset(struct axmap *axmap)
 
 		memset(al->map, 0, al->map_size * sizeof(unsigned long));
 	}
+
+	axmap->first_free = 0;
 }
 
 void axmap_free(struct axmap *axmap)
@@ -101,7 +103,6 @@ struct axmap *axmap_new(unsigned long nr_bits)
 
 	axmap->nr_levels = levels;
 	axmap->levels = smalloc(axmap->nr_levels * sizeof(struct axmap_level));
-	axmap->first_free = 0;
 
 	for (i = 0; i < axmap->nr_levels; i++) {
 		struct axmap_level *al = &axmap->levels[i];
diff --git a/lib/hweight.c b/lib/hweight.c
new file mode 100644
index 0000000..2c819d6
--- /dev/null
+++ b/lib/hweight.c
@@ -0,0 +1,33 @@
+#include "hweight.h"
+
+unsigned int hweight8(uint8_t w)
+{
+	unsigned int res = w - ((w >> 1) & 0x55);
+
+	res = (res & 0x33) + ((res >> 2) & 0x33);
+	return (res + (res >> 4)) & 0x0F;
+}
+
+unsigned int hweight32(uint32_t w)
+{
+	unsigned int res = w - ((w >> 1) & 0x55555555);
+
+	res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
+	res = (res + (res >> 4)) & 0x0F0F0F0F;
+	res = res + (res >> 8);
+	return (res + (res >> 16)) & 0x000000FF;
+}
+
+unsigned int hweight64(uint64_t w)
+{
+#if BITS_PER_LONG == 32
+	return hweight32((unsigned int)(w >> 32)) + hweight32((unsigned int)w);
+#else
+	uint64_t res = w - ((w >> 1) & 0x5555555555555555ULL);
+	res = (res & 0x3333333333333333ULL) + ((res >> 2) & 0x3333333333333333ULL);
+	res = (res + (res >> 4)) & 0x0F0F0F0F0F0F0F0FULL;
+	res = res + (res >> 8);
+	res = res + (res >> 16);
+	return (res + (res >> 32)) & 0x00000000000000FFULL;
+#endif
+}
diff --git a/lib/hweight.h b/lib/hweight.h
new file mode 100644
index 0000000..68861dd
--- /dev/null
+++ b/lib/hweight.h
@@ -0,0 +1,10 @@
+#ifndef FIO_HWEIGHT_H
+#define FIO_HWEIGHT_H
+
+#include <inttypes.h>
+
+unsigned int hweight8(uint8_t w);
+unsigned int hweight32(uint32_t w);
+unsigned int hweight64(uint64_t w);
+
+#endif
diff --git a/lib/lfsr.c b/lib/lfsr.c
index 975c6a5..61a3aaf 100644
--- a/lib/lfsr.c
+++ b/lib/lfsr.c
@@ -244,6 +244,17 @@ static struct lfsr_taps *find_lfsr(uint64_t size)
 	return NULL;
 }
 
+void lfsr_reset(struct fio_lfsr *fl, unsigned long seed)
+{
+	unsigned int i;
+
+	fl->last_val = seed;
+	fl->num_vals = 0;
+
+	for (i = 0; i < FIO_LFSR_CRANKS; i++)
+		fl->last_val = __lfsr_next(fl->last_val, &fl->taps);
+}
+
 int lfsr_init(struct fio_lfsr *fl, uint64_t size, unsigned long seed)
 {
 	struct lfsr_taps *tap;
@@ -253,18 +264,15 @@ int lfsr_init(struct fio_lfsr *fl, uint64_t size, unsigned long seed)
 	if (!tap)
 		return 1;
 
-	fl->last_val = seed;
 	fl->max_val = size - 1;
-	fl->num_vals = 0;
 	fl->taps.length = tap->length;
+
 	for (i = 0; i < FIO_MAX_TAPS; i++) {
 		fl->taps.taps[i] = tap->taps[i];
 		if (!fl->taps.taps[i])
 			break;
 	}
 
-	for (i = 0; i < FIO_LFSR_CRANKS; i++)
-		fl->last_val = __lfsr_next(fl->last_val, &fl->taps);
-
+	lfsr_reset(fl, seed);
 	return 0;
 }
diff --git a/lib/lfsr.h b/lib/lfsr.h
index 898646e..45d7028 100644
--- a/lib/lfsr.h
+++ b/lib/lfsr.h
@@ -20,5 +20,6 @@ struct fio_lfsr {
 
 int lfsr_next(struct fio_lfsr *fl, uint64_t *off, uint64_t);
 int lfsr_init(struct fio_lfsr *fl, uint64_t size, unsigned long seed);
+void lfsr_reset(struct fio_lfsr *fl, unsigned long seed);
 
 #endif
diff --git a/libfio.c b/libfio.c
index 96ae814..8255072 100644
--- a/libfio.c
+++ b/libfio.c
@@ -82,7 +82,7 @@ static void reset_io_counters(struct thread_data *td)
 	/*
 	 * reset file done count if we are to start over
 	 */
-	if (td->o.time_based || td->o.loops)
+	if (td->o.time_based || td->o.loops || td->o.do_verify)
 		td->nr_done_files = 0;
 }
 
diff --git a/options.c b/options.c
index 8d460be..2b71abd 100644
--- a/options.c
+++ b/options.c
@@ -1961,6 +1961,11 @@ static struct fio_option options[FIO_MAX_OPTS] = {
 		.parent	= "verify_async",
 	},
 #endif
+	{
+		.name	= "experimental_verify",
+		.off1	= td_var_offset(experimental_verify),
+		.type	= FIO_OPT_BOOL,
+	},
 #ifdef FIO_HAVE_TRIM
 	{
 		.name	= "trim_percentage",
diff --git a/os/windows/posix.c b/os/windows/posix.c
index 8b45147..f5d5300 100755
--- a/os/windows/posix.c
+++ b/os/windows/posix.c
@@ -20,6 +20,7 @@
 #include <sys/poll.h>
 
 #include "../os-windows.h"
+#include "../../lib/hweight.h"
 
 extern unsigned long mtime_since_now(struct timeval *);
 extern void fio_gettime(struct timeval *, void *);
@@ -42,20 +43,52 @@ int vsprintf_s(
   const char *format,
   va_list argptr);
 
+int GetNumLogicalProcessors(void)
+{
+	SYSTEM_LOGICAL_PROCESSOR_INFORMATION *processor_info = NULL;
+	DWORD len = 0;
+	DWORD num_processors = 0;
+	DWORD error = 0;
+	DWORD i;
+
+	while (!GetLogicalProcessorInformation(processor_info, &len)) {
+		error = GetLastError();
+		if (error == ERROR_INSUFFICIENT_BUFFER)
+			processor_info = malloc(len);
+		else {
+			log_err("Error: GetLogicalProcessorInformation failed: %d\n", error);
+			return -1;
+		}
+
+		if (processor_info == NULL) {
+			log_err("Error: failed to allocate memory for GetLogicalProcessorInformation");
+			return -1;
+		}
+	}
+
+	for (i = 0; i < len / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION); i++)
+	{
+		if (processor_info[i].Relationship == RelationProcessorCore)
+			num_processors += hweight64(processor_info[i].ProcessorMask);
+	}
+
+	free(processor_info);
+	return num_processors;
+}
+
 long sysconf(int name)
 {
-	long long val = -1;
-	DWORD len;
-	SYSTEM_LOGICAL_PROCESSOR_INFORMATION processorInfo;
+	long val = -1;
 	SYSTEM_INFO sysInfo;
 	MEMORYSTATUSEX status;
 
 	switch (name)
 	{
 	case _SC_NPROCESSORS_ONLN:
-		len = sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
-		GetLogicalProcessorInformation(&processorInfo, &len);
-		val = len / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
+		val = GetNumLogicalProcessors();
+		if (val == -1)
+			log_err("_SC_NPROCESSORS_ONLN failed\n");
+
 		break;
 
 	case _SC_PAGESIZE:
diff --git a/verify.c b/verify.c
index c0485d5..cb13b62 100644
--- a/verify.c
+++ b/verify.c
@@ -13,6 +13,7 @@
 #include "smalloc.h"
 #include "trim.h"
 #include "lib/rand.h"
+#include "lib/hweight.h"
 
 #include "crc/md5.h"
 #include "crc/crc64.h"
@@ -308,14 +309,6 @@ static inline void *io_u_verify_off(struct verify_header *hdr, struct vcont *vc)
 	return vc->io_u->buf + vc->hdr_num * hdr->len + hdr_size(hdr);
 }
 
-static unsigned int hweight8(unsigned int w)
-{
-	unsigned int res = w - ((w >> 1) & 0x55);
-
-	res = (res & 0x33) + ((res >> 2) & 0x33);
-	return (res + (res >> 4)) & 0x0F;
-}
-
 static int verify_io_u_pattern(struct verify_header *hdr, struct vcont *vc)
 {
 	struct thread_data *td = vc->td;
--
To unsubscribe from this list: send the line "unsubscribe fio" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Kernel]     [Linux SCSI]     [Linux IDE]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux SCSI]

  Powered by Linux