Make funksync work again and make file verification at startup optional

Signed-off-by: Chris Mason <clm@fb.com>
diff --git a/simoop.c b/simoop.c
index 3b9b88b..dbb7794 100644
--- a/simoop.c
+++ b/simoop.c
@@ -80,7 +80,7 @@
 static int du_threads = 0;
 /* memory to allocate and use during each task */
 static int thinking_mem = 128 * 1024 * 1024;
-/* should we do a truncate and fsync after every write */
+/* should we fsync sometimes? */
 static int funksync = 0;
 /* are we just appending bytes onto the ends of the working set files */
 static int append_mode = 0;
@@ -89,6 +89,9 @@
 /* use odirect sometimes */
 static int odirect = 0;
 
+/* check contents at startup */
+static int check_initial_files = 0;
+
 /* -M how much memory we allocate to benchmark allocations */
 static int mmap_size = 64 * 1024 * 1024;
 
@@ -415,7 +418,7 @@
 	return ret;
 }
 
-char *option_string = "t:s:C:c:r:n:f:FR:T:m:W:M:w:i:D:oaO";
+char *option_string = "t:s:C:c:r:n:f:FR:T:m:W:M:w:i:D:oaOV";
 static struct option long_options[] = {
 	{"appendmode", required_argument, 0, 'a'},
 	{"mmapsize", required_argument, 0, 'M'},
@@ -436,6 +439,7 @@
 	{"funksync", no_argument, 0, 'F'},
 	{"oddsizes", no_argument, 0, 'o'},
 	{"odirect", no_argument, 0, 'O'},
+	{"verifystartup", no_argument, 0, 'V'},
 	{"help", no_argument, 0, HELP_LONG_OPT},
 	{0, 0, 0, 0}
 };
@@ -450,6 +454,7 @@
 		"\t-r (--runtime): How long to run before exiting (seconds, def: 30)\n"
 		"\t-w (--warmuptime): How long to warmup before resetting the stats (seconds, def: 60)\n"
 		"\t-i (--interval): Sleep time in seconds between latency reports (sec, def: 120\n"
+		"\t-V (--verify-startup): Verify all files on startup (def: no)\n"
 		"\t-s (--sleeptime): Sleep time in usecs between worker loops (usec, def: 10000\n"
 		"\t-c (--cputime): How long to think during each worker loop (seconds, def: 3)\n"
 		"\t-C (--cputhreads): How many threads do the cpu time loop (24)\n"
@@ -459,7 +464,7 @@
 		"\t-W (--writesize): amount to write to tmp files (2M)\n"
 		"\t-T (--rwthreads): how many threads to read/write (8)\n"
 		"\t-D (--duthraeds): how many threads to scanning the working dirs (0)\n"
-		"\t-F (--funksync): should we fsync;truncate(0);fsync after writes\n"
+		"\t-F (--funksync): fsync sometimes\n"
 		"\t-o (--oddsizes): randomize sizes to unaligned values\n"
 		"\t-O (--odirect): use O_DIRECT sometimes\n"
 		"\t dir1 [dir2 ... dirN]\n"
@@ -516,7 +521,7 @@
 			interval_seconds = atoi(optarg);
 			break;
 		case 'F':
-			funksync = 0;
+			funksync = 1;
 			break;
 		case 'f':
 			file_size = parse_size(optarg);
@@ -546,6 +551,9 @@
 		case 'O':
 			odirect = 1;
 			break;
+		case 'V':
+			check_initial_files = 1;
+			break;
 		case '?':
 		case HELP_LONG_OPT:
 			print_usage();
@@ -890,14 +898,16 @@
 	int ret;
 
 	join_path(name, path, seq, RESULT_FILE);
-	read_whole_file(path, seq, RESULT_FILE, buf, buf_size);
+	if (check_initial_files)
+		read_whole_file(path, seq, RESULT_FILE, buf, buf_size);
 	ret = unlink(name);
 	if (ret < 0 && errno != ENOENT) {
 		perror("unlink");
 		exit(1);
 	}
 	join_path(name, path, seq, TMP_FILE);
-	read_whole_file(path, seq, TMP_FILE, buf, buf_size);
+	if (check_initial_files)
+		read_whole_file(path, seq, TMP_FILE, buf, buf_size);
 	ret = unlink(name);
 	if (ret < 0 && errno != ENOENT) {
 		perror("unlink");
@@ -928,6 +938,25 @@
 	return rand() % sz;
 }
 
+static void maybe_fsync(int fd)
+{
+	int ret;
+	if (!funksync)
+		return;
+	ret = sync_file_range(fd, 0, 0, SYNC_FILE_RANGE_WRITE);
+	if (ret < 0) {
+		perror("sync_file_range");
+		exit(1);
+	}
+	if ((rand() % 5) != 0)
+		return;
+	ret = fsync(fd);
+	if (ret < 0) {
+		perror("fsync");
+		exit(1);
+	}
+}
+
 static void maybe_toggle_odirect(int fd, unsigned long start,
 				 unsigned long len)
 {
@@ -997,6 +1026,7 @@
 			this_write -= ret;
 			buf += ret;
 		}
+		maybe_fsync(fd);
 		if (bytes == 0)
 			break;
 	}
@@ -1011,6 +1041,7 @@
 		bytes -= ret;
 		buf += ret;
 	}
+	maybe_fsync(fd);
 }
 
 static void write_pattern(int fd, void *xxhash_state, char *buf,
@@ -1325,7 +1356,7 @@
 
 
 	for (seq = seq_start; seq < seq_start + seq_num; seq++) {
-		if (read_size)
+		if (read_size && check_initial_files)
 			read_whole_file(path, seq, DATA_FILE, buf, BUF_SIZE);
 
 		fd = open_path(path, seq, DATA_FILE, O_APPEND);
@@ -1775,7 +1806,7 @@
 		}
 
 		instant_work_done = work_done;
-		if (delta < runtime_usec)
+		if (runtime_usec == 0 || delta < runtime_usec)
 			sleep(interval_seconds);
 		else
 			break;