Merge branch 'master' into gfio

Conflicts:
	iolog.h
	stat.c

Signed-off-by: Jens Axboe <axboe@kernel.dk>
diff --git a/FIO-VERSION-GEN b/FIO-VERSION-GEN
index bd73b9e..ee017f0 100755
--- a/FIO-VERSION-GEN
+++ b/FIO-VERSION-GEN
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=FIO-VERSION-FILE
-DEF_VER=2.0.7
+DEF_VER=fio-2.0.8
 
 LF='
 '
diff --git a/Makefile b/Makefile
index 5165cd9..5d4e3e7 100644
--- a/Makefile
+++ b/Makefile
@@ -65,6 +65,7 @@
   LIBS	 += -lpthread -lpsapi -lws2_32
   CFLAGS += -DPSAPI_VERSION=1 -Ios/windows/posix/include -Wno-format
   CC	  = x86_64-w64-mingw32-gcc
+  #CC	  = i686-w64-mingw32-gcc
 endif
 
 OBJS = $(SOURCE:.c=.o)
diff --git a/arch/arch.h b/arch/arch.h
index 4ad49a4..3ee5ac4 100644
--- a/arch/arch.h
+++ b/arch/arch.h
@@ -19,6 +19,7 @@
 	arch_arm,
 	arch_sh,
 	arch_hppa,
+	arch_mips,
 
 	arch_generic,
 
diff --git a/backend.c b/backend.c
index 38efc23..dcc6fba 100644
--- a/backend.c
+++ b/backend.c
@@ -50,6 +50,7 @@
 #include "server.h"
 
 static pthread_t disk_util_thread;
+static struct fio_mutex *disk_thread_mutex;
 static struct fio_mutex *startup_mutex;
 static struct fio_mutex *writeout_mutex;
 static struct flist_head *cgroup_list;
@@ -1599,20 +1600,28 @@
 	update_io_ticks();
 }
 
+void wait_for_disk_thread_exit(void)
+{
+	fio_mutex_down(disk_thread_mutex);
+}
+
 static void *disk_thread_main(void *data)
 {
+	int ret = 0;
+
 	fio_mutex_up(startup_mutex);
 
-	while (threads) {
+	while (threads && !ret) {
 		usleep(DISK_UTIL_MSEC * 1000);
 		if (!threads)
 			break;
-		update_io_ticks();
+		ret = update_io_ticks();
 
 		if (!is_backend)
 			print_thread_status();
 	}
 
+	fio_mutex_up(disk_thread_mutex);
 	return NULL;
 }
 
@@ -1620,14 +1629,20 @@
 {
 	int ret;
 
+	setup_disk_util();
+
+	disk_thread_mutex = fio_mutex_init(0);
+
 	ret = pthread_create(&disk_util_thread, NULL, disk_thread_main, NULL);
 	if (ret) {
+		fio_mutex_remove(disk_thread_mutex);
 		log_err("Can't create disk util thread: %s\n", strerror(ret));
 		return 1;
 	}
 
 	ret = pthread_detach(disk_util_thread);
 	if (ret) {
+		fio_mutex_remove(disk_thread_mutex);
 		log_err("Can't detatch disk util thread: %s\n", strerror(ret));
 		return 1;
 	}
@@ -1691,5 +1706,6 @@
 
 	fio_mutex_remove(startup_mutex);
 	fio_mutex_remove(writeout_mutex);
+	fio_mutex_remove(disk_thread_mutex);
 	return exit_value;
 }
diff --git a/blktrace.c b/blktrace.c
index 1b9bf3b..e195f7f 100644
--- a/blktrace.c
+++ b/blktrace.c
@@ -163,7 +163,7 @@
 #define FMAJOR(dev)	((unsigned int) ((dev) >> FMINORBITS))
 #define FMINOR(dev)	((unsigned int) ((dev) & FMINORMASK))
 
-static void trace_add_open_event(struct thread_data *td, int fileno)
+static void trace_add_open_close_event(struct thread_data *td, int fileno, enum file_log_act action)
 {
 	struct io_piece *ipo;
 
@@ -172,13 +172,13 @@
 
 	ipo->ddir = DDIR_INVAL;
 	ipo->fileno = fileno;
-	ipo->file_action = FIO_LOG_OPEN_FILE;
+	ipo->file_action = action;
 	flist_add_tail(&ipo->list, &td->io_log_list);
 }
 
-static void trace_add_file(struct thread_data *td, __u32 device)
+static int trace_add_file(struct thread_data *td, __u32 device)
 {
-	static unsigned int last_maj, last_min;
+	static unsigned int last_maj, last_min, last_fileno;
 	unsigned int maj = FMAJOR(device);
 	unsigned int min = FMINOR(device);
 	struct fio_file *f;
@@ -186,7 +186,7 @@
 	unsigned int i;
 
 	if (last_maj == maj && last_min == min)
-		return;
+		return last_fileno;
 
 	last_maj = maj;
 	last_min = min;
@@ -195,8 +195,10 @@
 	 * check for this file in our list
 	 */
 	for_each_file(td, f, i)
-		if (f->major == maj && f->minor == min)
-			return;
+		if (f->major == maj && f->minor == min) {
+			last_fileno = f->fileno;
+			return last_fileno;
+		}
 
 	strcpy(dev, "/dev");
 	if (lookup_device(td, dev, maj, min)) {
@@ -204,15 +206,18 @@
 
 		dprint(FD_BLKTRACE, "add devices %s\n", dev);
 		fileno = add_file_exclusive(td, dev);
-		trace_add_open_event(td, fileno);
+		trace_add_open_close_event(td, fileno, FIO_LOG_OPEN_FILE);
+		last_fileno = fileno;
 	}
+	return last_fileno;
 }
 
 /*
  * Store blk_io_trace data in an ipo for later retrieval.
  */
 static void store_ipo(struct thread_data *td, unsigned long long offset,
-		      unsigned int bytes, int rw, unsigned long long ttime)
+		      unsigned int bytes, int rw, unsigned long long ttime,
+		      int fileno)
 {
 	struct io_piece *ipo = malloc(sizeof(*ipo));
 
@@ -228,6 +233,7 @@
 		ipo->ddir = DDIR_WRITE;
 	else
 		ipo->ddir = DDIR_READ;
+	ipo->fileno = fileno;
 
 	dprint(FD_BLKTRACE, "store ddir=%d, off=%llu, len=%lu, delay=%lu\n",
 							ipo->ddir, ipo->offset,
@@ -256,9 +262,10 @@
 				 unsigned long long ttime, unsigned long *ios)
 {
 	struct io_piece *ipo = malloc(sizeof(*ipo));
+	int fileno;
 
 	init_ipo(ipo);
-	trace_add_file(td, t->device);
+	fileno = trace_add_file(td, t->device);
 
 	ios[DDIR_WRITE]++;
 	td->o.size += t->bytes;
@@ -273,6 +280,7 @@
 	ipo->len = t->bytes;
 	ipo->delay = ttime / 1000;
 	ipo->ddir = DDIR_TRIM;
+	ipo->fileno = fileno;
 
 	dprint(FD_BLKTRACE, "store discard, off=%llu, len=%lu, delay=%lu\n",
 							ipo->offset, ipo->len,
@@ -285,8 +293,9 @@
 			    unsigned int *bs)
 {
 	int rw;
+	int fileno;
 
-	trace_add_file(td, t->device);
+	fileno = trace_add_file(td, t->device);
 
 	rw = (t->action & BLK_TC_ACT(BLK_TC_WRITE)) != 0;
 
@@ -295,7 +304,7 @@
 
 	ios[rw]++;
 	td->o.size += t->bytes;
-	store_ipo(td, t->sector, t->bytes, rw, ttime);
+	store_ipo(td, t->sector, t->bytes, rw, ttime, fileno);
 }
 
 /*
@@ -331,7 +340,8 @@
 	unsigned int cpu;
 	unsigned int rw_bs[2];
 	struct fifo *fifo;
-	int fd;
+	int fd, i;
+	struct fio_file *f;
 
 	fd = open(filename, O_RDONLY);
 	if (fd < 0) {
@@ -408,6 +418,11 @@
 		}
 	} while (1);
 
+	for (i = 0; i < td->files_index; i++) {
+		f= td->files[i];
+		trace_add_open_close_event(td, f->fileno, FIO_LOG_CLOSE_FILE);
+	}
+
 	fifo_free(fifo);
 	close(fd);
 
diff --git a/diskutil.c b/diskutil.c
index feb8852..32616b7 100644
--- a/diskutil.c
+++ b/diskutil.c
@@ -14,6 +14,9 @@
 static int last_majdev, last_mindev;
 static struct disk_util *last_du;
 
+static struct fio_mutex *disk_util_mutex;
+static int disk_util_exit;
+
 FLIST_HEAD(disk_list);
 
 static struct disk_util *__init_per_file_disk_util(struct thread_data *td,
@@ -102,17 +105,26 @@
 	memcpy(ldus, &__dus, sizeof(__dus));
 }
 
-void update_io_ticks(void)
+int update_io_ticks(void)
 {
 	struct flist_head *entry;
 	struct disk_util *du;
+	int ret = 0;
 
 	dprint(FD_DISKUTIL, "update io ticks\n");
 
-	flist_for_each(entry, &disk_list) {
-		du = flist_entry(entry, struct disk_util, list);
-		update_io_tick_disk(du);
-	}
+	fio_mutex_down(disk_util_mutex);
+
+	if (!disk_util_exit) {
+		flist_for_each(entry, &disk_list) {
+			du = flist_entry(entry, struct disk_util, list);
+			update_io_tick_disk(du);
+		}
+	} else
+		ret = 1;
+
+	fio_mutex_up(disk_util_mutex);
+	return ret;
 }
 
 static struct disk_util *disk_util_exists(int major, int minor)
@@ -276,6 +288,8 @@
 	du->lock = fio_mutex_init(1);
 	du->users = 0;
 
+	fio_mutex_down(disk_util_mutex);
+
 	flist_for_each(entry, &disk_list) {
 		__du = flist_entry(entry, struct disk_util, list);
 
@@ -283,6 +297,7 @@
 
 		if (!strcmp((char *) du->dus.name, (char *) __du->dus.name)) {
 			disk_util_free(du);
+			fio_mutex_up(disk_util_mutex);
 			return __du;
 		}
 	}
@@ -294,6 +309,7 @@
 
 	flist_add_tail(&du->list, &disk_list);
 	find_add_disk_slaves(td, path, du);
+	fio_mutex_up(disk_util_mutex);
 	return du;
 }
 
@@ -521,6 +537,11 @@
 {
 	struct disk_util *du;
 
+	disk_util_exit = 1;
+	wait_for_disk_thread_exit();
+
+	fio_mutex_down(disk_util_mutex);
+
 	while (!flist_empty(&disk_list)) {
 		du = flist_entry(disk_list.next, struct disk_util, list);
 		flist_del(&du->list);
@@ -528,6 +549,8 @@
 	}
 
 	last_majdev = last_mindev = -1;
+	fio_mutex_up(disk_util_mutex);
+	fio_mutex_remove(disk_util_mutex);
 }
 
 void print_disk_util(struct disk_util_stat *dus, struct disk_util_agg *agg,
@@ -573,8 +596,12 @@
 	struct flist_head *entry;
 	struct disk_util *du;
 
-	if (flist_empty(&disk_list))
+	fio_mutex_down(disk_util_mutex);
+
+	if (flist_empty(&disk_list)) {
+		fio_mutex_up(disk_util_mutex);
 		return;
+	}
 
 	if (!terse)
 		log_info("\nDisk stats (read/write):\n");
@@ -585,4 +612,11 @@
 		aggregate_slaves_stats(du);
 		print_disk_util(&du->dus, &du->agg, terse);
 	}
+
+	fio_mutex_up(disk_util_mutex);
+}
+
+void setup_disk_util(void)
+{
+	disk_util_mutex = fio_mutex_init(1);
 }
diff --git a/diskutil.h b/diskutil.h
index 5a9b079..88dde55 100644
--- a/diskutil.h
+++ b/diskutil.h
@@ -94,6 +94,8 @@
 
 extern struct flist_head disk_list;
 
+extern void wait_for_disk_thread_exit(void);
+
 /*
  * disk util stuff
  */
@@ -102,13 +104,18 @@
 extern void show_disk_util(int terse);
 extern void free_disk_util(void);
 extern void init_disk_util(struct thread_data *);
-extern void update_io_ticks(void);
+extern int update_io_ticks(void);
+extern void setup_disk_util(void);
 #else
 #define print_disk_util(dus, agg, terse)
 #define show_disk_util(terse)
 #define free_disk_util()
 #define init_disk_util(td)
-#define update_io_ticks()
+#define setup_disk_util()
+static inline int update_io_ticks(void)
+{
+	return 0;
+}
 #endif
 
 #endif
diff --git a/file.h b/file.h
index 1d6624e..51df839 100644
--- a/file.h
+++ b/file.h
@@ -72,6 +72,7 @@
 	 */
 	char *file_name;
 	unsigned int major, minor;
+	int fileno;
 
 	void *mmap_ptr;
 	size_t mmap_sz;
diff --git a/filesetup.c b/filesetup.c
index d30b616..76e142a 100644
--- a/filesetup.c
+++ b/filesetup.c
@@ -526,6 +526,11 @@
 
 		snprintf(buf, sizeof(buf) - 1, "open(%s)", f->file_name);
 
+		if (__e == EINVAL && (flags & OS_O_DIRECT)) {
+			log_err("fio: looks like your file system does not " \
+				"support direct=1/buffered=0\n");
+		}
+
 		td_verror(td, __e, buf);
 	}
 
@@ -974,6 +979,7 @@
 		td->files_size = new_size;
 	}
 	td->files[cur_files] = f;
+	f->fileno = cur_files;
 
 	/*
 	 * init function, io engine may not be loaded yet
diff --git a/helpers.c b/helpers.c
index 9562567..5be45cc 100644
--- a/helpers.c
+++ b/helpers.c
@@ -9,11 +9,13 @@
 #include "arch/arch.h"
 #include "os/os.h"
 
+#ifndef FIO_HAVE_LINUX_FALLOCATE 
 int _weak fallocate(int fd, int mode, off_t offset, off_t len)
 {
 	errno = ENOSYS;
 	return -1;
 }
+#endif
 
 #ifndef __NR_fallocate
 int _weak posix_fallocate(int fd, off_t offset, off_t len)
diff --git a/iolog.h b/iolog.h
index 0d6b506..122a982 100644
--- a/iolog.h
+++ b/iolog.h
@@ -119,7 +119,6 @@
 extern void add_iops_sample(struct thread_data *, enum fio_ddir, struct timeval *);
 extern void init_disk_util(struct thread_data *);
 extern void update_rusage_stat(struct thread_data *);
-extern void update_io_ticks(void);
 extern void setup_log(struct io_log **, unsigned long, int);
 extern void finish_log(struct thread_data *, struct io_log *, const char *);
 extern void finish_log_named(struct thread_data *, struct io_log *, const char *, const char *);
diff --git a/os/windows/install.wxs b/os/windows/install.wxs
index 69753ba..f8da8fc 100755
--- a/os/windows/install.wxs
+++ b/os/windows/install.wxs
@@ -7,10 +7,10 @@
 		<?define ProgramDirectory = ProgramFiles64Folder ?>

 	<?endif?>

 

-	<Product Id="CCE88492-8C5A-4EAF-8B82-E22A90CEC47B"

+	<Product Id="2BA394F9-0D9E-4597-BB9D-6B18097D64BB"

 	  Codepage="1252" Language="1033"

 	  Manufacturer="fio" Name="fio"

-	  UpgradeCode="2338A332-5511-43cf-b9BD-5C60496CCFCC" Version="2.0.7">

+	  UpgradeCode="2338A332-5511-43cf-b9BD-5C60496CCFCC" Version="2.0.8">

 		<Package 

 		  Comments="Contact: Your local administrator"

 		  Description="Flexible IO Tester"

diff --git a/os/windows/posix.c b/os/windows/posix.c
index 9ef369e..41bcb2d 100755
--- a/os/windows/posix.c
+++ b/os/windows/posix.c
@@ -393,7 +393,9 @@
 int shmget(key_t key, size_t size, int shmflg)
 {
 	int mapid = -1;
-	HANDLE hMapping = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, (PAGE_EXECUTE_READWRITE | SEC_RESERVE), size >> 32, size & 0xFFFFFFFF, NULL);
+	uint32_t size_low = size & 0xFFFFFFFF;
+	uint32_t size_high = ((uint64_t)size) >> 32;
+	HANDLE hMapping = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, (PAGE_EXECUTE_READWRITE | SEC_RESERVE), size_high, size_low, NULL);
 	if (hMapping != NULL) {
 		fileMappings[nFileMappings] = hMapping;
 		mapid = nFileMappings;
diff --git a/stat.c b/stat.c
index ee495ff..ef447b1 100644
--- a/stat.c
+++ b/stat.c
@@ -485,19 +485,26 @@
 	double usr_cpu, sys_cpu;
 	unsigned long runtime;
 	double io_u_dist[FIO_IO_U_MAP_NR];
+	time_t time_p;
+	char time_buf[64];
+
 
 	if (!(ts->io_bytes[0] + ts->io_bytes[1]) &&
 	    !(ts->total_io_u[0] + ts->total_io_u[1]))
 		return;
 
+	time(&time_p);
+	ctime_r((const time_t *) &time_p, time_buf);
+
 	if (!ts->error) {
-		log_info("%s: (groupid=%d, jobs=%d): err=%2d: pid=%d\n",
+		log_info("%s: (groupid=%d, jobs=%d): err=%2d: pid=%d: %s",
 					ts->name, ts->groupid, ts->members,
-					ts->error, (int) ts->pid);
+					ts->error, (int) ts->pid, time_buf);
 	} else {
-		log_info("%s: (groupid=%d, jobs=%d): err=%2d (%s): pid=%d\n",
+		log_info("%s: (groupid=%d, jobs=%d): err=%2d (%s): pid=%d: %s",
 					ts->name, ts->groupid, ts->members,
-					ts->error, ts->verror, (int) ts->pid);
+					ts->error, ts->verror, (int) ts->pid,
+					time_buf);
 	}
 
 	if (strlen(ts->description))