flashbench: allow finding the FAT using CLI

Recompiling flashbench every time to run it
with different arguments sucks, so allow
the find-fat test to be run from the command
line, with all necessary args for tuning.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
diff --git a/dev.c b/dev.c
index e0c5313..b9468ce 100644
--- a/dev.c
+++ b/dev.c
@@ -124,7 +124,7 @@
 
 	dev->fd = open(filename, O_RDWR | O_DIRECT | O_SYNC | O_NOATIME);
 	if (dev->fd < 0) {
-		perror("open");
+		perror(filename);
 		return -errno;
 	}
 
diff --git a/flashbench.c b/flashbench.c
index ce4f233..bfb9975 100644
--- a/flashbench.c
+++ b/flashbench.c
@@ -460,12 +460,28 @@
 	call(program, dev, 0, 4 * 1024 * 1024, 0);
 #endif
 
-#if 0
+	return 0;
+}
+
+static unsigned int find_order(unsigned int large, unsigned int small)
+{
+	unsigned int o;
+
+	for (o=1; small < large; small <<= 1)
+		o++;
+
+	return o;
+}
+
+static int try_find_fat(struct device *dev, unsigned int erasesize,
+				unsigned int blocksize,
+				unsigned int count,
+				bool random)
+{
 	/* Find FAT Units */
 	struct operation program[] = {
             /* loop through power of two multiple of one sector */
-//            {O_LEN_POW2, 7, -(64 * 1024)},
-            {O_LEN_POW2, 14, -512},
+            {O_LEN_POW2, find_order(erasesize, blocksize), - (long long)blocksize},
             {O_SEQUENCE, 3},
                 /* print block size */
                 {O_DROP},
@@ -475,22 +491,22 @@
                 /* print one line of aggregated
                     per second results */
                 {O_PRINTF}, {O_FORMAT},
-		    {O_OFF_LIN, 3, 4 * 1024 * 1024},
+		    {random ? O_OFF_RAND : O_OFF_LIN, count, erasesize},
                         /* linear write 0x5a */
                         {O_REDUCE, .aggregate = A_MAXIMUM}, {O_REPEAT, 1},
                             {O_REDUCE, .aggregate = A_AVERAGE},
-                            {O_OFF_LIN, 8192, -1},
+                            {O_OFF_LIN, erasesize / blocksize, -1},
                             {O_BPS},{O_WRITE_RAND},
                 {O_NEWLINE},
                 {O_END},
             {O_END},
 	};
-	call(program, dev, 0, 4 * 1024 * 1024, 0);
-#endif
+	call(program, dev, 0, erasesize, 0);
 
 	return 0;
 }
 
+
 static void print_help(const char *name)
 {
 	printf("%s [OPTION]... [DEVICE]\n", name);
@@ -499,22 +515,27 @@
 	printf("-s, --scatter	run scatter read test\n");
 	printf("    --scatter-order=N scatter across 2^N blocks\n");
 	printf("    --scatter-span=N span each write across N blocks\n");
+	printf("-f, --find-fat	analyse first few erase blocks\n");
+	printf("    --fat-nr=N	look through first N erase blocks (default: 6)\n");
+	printf("-r, --random	use pseudorandom access with erase block\n");
 	printf("-v, --verbose	increase verbosity of output\n");
 	printf("-c, --count=N	run each test N times (default: 8\n");
 	printf("-b, --blocksize=N use a blocksize of N (default:16K)\n");
-	printf("-e, --erasesize=N use a eraseblocksize of N (default:4M)\n");
+	printf("-e, --erasesize=N use a eraseblock size of N (default:4M)\n");
 }
 
 struct arguments {
 	const char *dev;
 	const char *out;
-	bool scatter, interval, program;
+	bool scatter, interval, program, fat;
+	bool random;
 	int count;
 	int blocksize;
 	int erasesize;
 	int scatter_order;
 	int scatter_span;
 	int interval_order;
+	int fat_nr;
 };
 
 static int parse_arguments(int argc, char **argv, struct arguments *args)
@@ -526,6 +547,9 @@
 		{ "scatter-span", 1, NULL, '$' },
 		{ "interval", 0, NULL, 'i' },
 		{ "interval-order", 1, NULL, 'I' },
+		{ "findfat", 0, NULL, 'f' },
+		{ "fat-nr", 1, NULL, 'F' },
+		{ "random", 0, NULL, 'r' },
 		{ "verbose", 0, NULL, 'v' },
 		{ "count", 1, NULL, 'c' },
 		{ "blocksize", 1, NULL, 'b' },
@@ -543,7 +567,7 @@
 	while (1) {
 		int c;
 
-		c = getopt_long(argc, argv, "o:sraivc:b:p", long_options, &optind);
+		c = getopt_long(argc, argv, "o:sifF:vrc:b:e:p", long_options, &optind);
 
 		if (c == -1)
 			break;
@@ -573,6 +597,17 @@
 			args->interval_order = atoi(optarg);
 			break;
 
+		case 'f':
+			args->fat = 1;
+			break;
+
+		case 'F':
+			args->fat_nr = atoi(optarg);
+			break;
+
+		case 'r':
+			args->random = 1;
+
 		case 'p':
 			args->program = 1;
 			break;
@@ -607,7 +642,8 @@
 
 	args->dev = argv[optind];
 
-	if (!(args->scatter || args->interval || args->program)) {
+	if (!(args->scatter || args->interval || args->program ||
+	      args->fat)) {
 		fprintf(stderr, "%s: need at least one action\n", argv[0]);
 		return -EINVAL;
 	}
@@ -660,6 +696,16 @@
 		}
 	}
 
+	if (args.fat) {
+		ret = try_find_fat(&dev, args.erasesize, args.blocksize,
+				   args.count, args.random);
+		if (ret < 0) {
+			errno = -ret;
+			perror("find_fat");
+			return ret;
+		}
+	}
+
 	if (args.interval) {
 		ret = try_intervals(&dev, args.count, args.interval_order);
 		if (ret < 0) {