Recent changes (master)

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

 



The following changes since commit 78a6aad70b54fbf6eb63f14c60b292bcf6a5605e:

  act: fixes (2013-05-23 00:29:38 +0200)

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

Jens Axboe (7):
      act: bring closer to real ACT
      act: basic reporting
      Fix segfault is bool option is used on command line and fails parsing
      Better catch arguments with required options and none passed
      Make group_reporting be a string-set option again
      parse: if profile is set, only show options relevant to the profile
      Always exit if do_exit is set after parse

 backend.c      |    1 +
 init.c         |   21 ++++--
 options.c      |    2 +-
 parse.c        |    2 +
 profiles/act.c |  256 ++++++++++++++++++++++++++++++++++++++++++++++++++-----
 5 files changed, 251 insertions(+), 31 deletions(-)

---

Diff of recent changes:

diff --git a/backend.c b/backend.c
index 6b6da67..8787cce 100644
--- a/backend.c
+++ b/backend.c
@@ -1554,6 +1554,7 @@ reaped:
 			exit_value++;
 
 		done_secs += mtime_since_now(&td->epoch) / 1000;
+		profile_td_exit(td);
 	}
 
 	if (*nr_running == cputhreads && !pending && realthreads)
diff --git a/init.c b/init.c
index 7246bd8..c44fa67 100644
--- a/init.c
+++ b/init.c
@@ -1725,9 +1725,20 @@ int parse_cmd_line(int argc, char *argv[], int client_type)
 				fio_options_set_ioengine_opts(l_opts, td);
 			}
 
-			ret = fio_cmd_option_parse(td, opt, val);
-			if (ret)
+			if ((!val || !strlen(val)) &&
+			    l_opts[lidx].has_arg == required_argument) {
+				log_err("fio: option %s requires an argument\n", opt);
+				ret = 1;
+			} else
+				ret = fio_cmd_option_parse(td, opt, val);
+
+			if (ret) {
+				if (td) {
+					put_job(td);
+					td = NULL;
+				}
 				do_exit++;
+			}
 
 			if (!ret && !strcmp(opt, "ioengine")) {
 				free_ioengine(td);
@@ -1833,10 +1844,8 @@ int parse_cmd_line(int argc, char *argv[], int client_type)
 			break;
 	}
 
-	if (do_exit) {
-		if (exit_val && !(is_backend || nr_clients))
-			exit(exit_val);
-	}
+	if (do_exit && !(is_backend || nr_clients))
+		exit(exit_val);
 
 	if (nr_clients && fio_clients_connect()) {
 		do_exit++;
diff --git a/options.c b/options.c
index e9df6a8..d0c53b6 100644
--- a/options.c
+++ b/options.c
@@ -2824,7 +2824,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
 	{
 		.name	= "group_reporting",
 		.lname	= "Group reporting",
-		.type	= FIO_OPT_BOOL,
+		.type	= FIO_OPT_STR_SET,
 		.off1	= td_var_offset(group_reporting),
 		.help	= "Do reporting on a per-group basis",
 		.category = FIO_OPT_C_STAT,
diff --git a/parse.c b/parse.c
index b8ec3aa..f54dae6 100644
--- a/parse.c
+++ b/parse.c
@@ -1086,6 +1086,8 @@ int show_cmd_help(struct fio_option *options, const char *name)
 			continue;
 		if (!exec_profile && o->prof_name)
 			continue;
+		if (exec_profile && !(o->prof_name && !strcmp(exec_profile, o->prof_name)))
+			continue;
 
 		if (name) {
 			if (!strcmp(name, o->name) ||
diff --git a/profiles/act.c b/profiles/act.c
index e5b31d7..2080602 100644
--- a/profiles/act.c
+++ b/profiles/act.c
@@ -2,9 +2,9 @@
 #include "../profile.h"
 #include "../parse.h"
 
-#define OBJ_SIZE	1536		/* each object */
-#define W_BUF_SIZE	128 * 1024	/* write coalescing */
-
+/*
+ * 1x loads
+ */
 #define R_LOAD		2000
 #define W_LOAD		1000
 
@@ -31,28 +31,43 @@ static struct act_pass_criteria act_pass[ACT_MAX_CRIT] = {
 	},
 };
 
+struct act_run_data {
+	struct fio_mutex *mutex;
+	unsigned int pending;
+
+	uint64_t lat_buckets[ACT_MAX_CRIT];
+	uint64_t total_ios;
+};
+static struct act_run_data *act_run_data;
+
 struct act_prof_data {
 	struct timeval sample_tv;
 	uint64_t lat_buckets[ACT_MAX_CRIT];
 	uint64_t total_ios;
+	uint64_t cum_lat_buckets[ACT_MAX_CRIT];
+	uint64_t cum_total_ios;
 };
 
 static char *device_names;
 static unsigned int load = 1;
+static unsigned int prep;
+static unsigned int threads_per_queue;
+static unsigned int num_read_blocks;
+static unsigned int write_size;
 
-static const char *act_opts[128] = {
+#define ACT_MAX_OPTS	128
+static const char *act_opts[ACT_MAX_OPTS] = {
 	"direct=1",
-	"ioengine=libaio",
-	"iodepth=32",
+	"ioengine=sync",
 	"random_generator=lfsr",
-	"runtime=24h",
-	"time_based=1",
+	"group_reporting=1",
+	"thread",
 	NULL,
 };
-static unsigned int opt_idx = 6;
+static unsigned int opt_idx = 5;
 static unsigned int org_idx;
 
-static void act_add_opt(const char *format, ...) __attribute__ ((__format__ (__printf__, 1, 2)));
+static int act_add_opt(const char *format, ...) __attribute__ ((__format__ (__printf__, 1, 2)));
 
 static struct fio_option options[] = {
 	{
@@ -70,6 +85,46 @@ static struct fio_option options[] = {
 		.type	= FIO_OPT_INT,
 		.roff1	= &load,
 		.help	= "ACT load multipler (default 1x)",
+		.def	= "1",
+		.category = FIO_OPT_C_PROFILE,
+		.group	= FIO_OPT_G_ACT,
+	},
+	{
+		.name	= "threads-per-queue",
+		.lname	= "Number of read IO threads per device",
+		.type	= FIO_OPT_INT,
+		.roff1	= &threads_per_queue,
+		.help	= "Number of read IO threads per device",
+		.def	= "8",
+		.category = FIO_OPT_C_PROFILE,
+		.group	= FIO_OPT_G_ACT,
+	},
+	{
+		.name	= "read-req-num-512-blocks",
+		.lname	= "Number of 512b blocks to read",
+		.type	= FIO_OPT_INT,
+		.roff1	= &num_read_blocks,
+		.help	= "Number of 512b blocks to read at the time",
+		.def	= "3",
+		.category = FIO_OPT_C_PROFILE,
+		.group	= FIO_OPT_G_ACT,
+	},
+	{
+		.name	= "large-block-op-kbytes",
+		.lname	= "Size of large block ops (writes)",
+		.type	= FIO_OPT_INT,
+		.roff1	= &write_size,
+		.help	= "Size of large block ops (writes)",
+		.def	= "128k",
+		.category = FIO_OPT_C_PROFILE,
+		.group	= FIO_OPT_G_ACT,
+	},
+	{
+		.name	= "prep",
+		.lname	= "Run ACT prep phase",
+		.type	= FIO_OPT_STR_SET,
+		.roff1	= &prep,
+		.help	= "Set to run ACT prep phase",
 		.category = FIO_OPT_C_PROFILE,
 		.group	= FIO_OPT_G_ACT,
 	},
@@ -78,31 +133,106 @@ static struct fio_option options[] = {
 	},
 };
 
-static void act_add_opt(const char *str, ...)
+static int act_add_opt(const char *str, ...)
 {
 	char buffer[512];
 	va_list args;
 	size_t len;
 
+	if (opt_idx == ACT_MAX_OPTS) {
+		log_err("act: ACT_MAX_OPTS is too small\n");
+		return 1;
+	}
+
 	va_start(args, str);
 	len = vsnprintf(buffer, sizeof(buffer), str, args);
 	va_end(args);
 
 	if (len)
 		act_opts[opt_idx++] = strdup(buffer);
+
+	return 0;
+}
+
+static int act_add_rw(const char *dev, int reads)
+{
+	if (act_add_opt("name=act-%s-%s", reads ? "read" : "write", dev))
+		return 1;
+	if (act_add_opt("filename=%s", dev))
+		return 1;
+	if (act_add_opt("rw=%s", reads ? "randread" : "randwrite"))
+		return 1;
+	if (reads) {
+		int rload = load * R_LOAD / threads_per_queue;
+
+		if (act_add_opt("numjobs=%u", threads_per_queue))
+			return 1;
+		if (act_add_opt("rate_iops=%u", rload))
+			return 1;
+		if (act_add_opt("bs=%u", num_read_blocks * 512))
+			return 1;
+	} else {
+		const int rsize = write_size / (num_read_blocks * 512);
+		int wload = (load * W_LOAD + rsize - 1) / rsize;
+
+		if (act_add_opt("rate_iops=%u", wload))
+			return 1;
+		if (act_add_opt("bs=%u", write_size))
+			return 1;
+	}
+
+	return 0;
+}
+
+static int act_add_dev_prep(const char *dev)
+{
+	/* Add sequential zero phase */
+	if (act_add_opt("name=act-prep-zeroes-%s", dev))
+		return 1;
+	if (act_add_opt("filename=%s", dev))
+		return 1;
+	if (act_add_opt("bs=1M"))
+		return 1;
+	if (act_add_opt("zero_buffers"))
+		return 1;
+	if (act_add_opt("rw=write"))
+		return 1;
+
+	/* Randomly overwrite device */
+	if (act_add_opt("name=act-prep-salt-%s", dev))
+		return 1;
+	if (act_add_opt("stonewall"))
+		return 1;
+	if (act_add_opt("filename=%s", dev))
+		return 1;
+	if (act_add_opt("bs=4k"))
+		return 1;
+	if (act_add_opt("ioengine=libaio"))
+		return 1;
+	if (act_add_opt("iodepth=64"))
+		return 1;
+	if (act_add_opt("rw=randwrite"))
+		return 1;
+
+	return 0;
 }
 
-static void act_add_dev(const char *dev)
+static int act_add_dev(const char *dev)
 {
-	act_add_opt("name=act-read-%s", dev);
-	act_add_opt("filename=%s", dev);
-	act_add_opt("rw=randread");
-	act_add_opt("rate_iops=%u", load * R_LOAD);
-
-	act_add_opt("name=act-write-%s", dev);
-	act_add_opt("filename=%s", dev);
-	act_add_opt("rw=randwrite");
-	act_add_opt("rate_iops=%u", load * W_LOAD);
+	if (prep)
+		return act_add_dev_prep(dev);
+
+	if (act_add_opt("runtime=24h"))
+		return 1;
+	if (act_add_opt("time_based=1"))
+		return 1;
+
+	if (act_add_rw(dev, 1))
+		return 1;
+	if (act_add_rw(dev, 0))
+		return 1;
+
+	return 0;
 }
 
 /*
@@ -116,7 +246,6 @@ static int act_prep_cmdline(void)
 	}
 
 	org_idx = opt_idx;
-	act_add_opt("bs=%u", OBJ_SIZE);
 
 	do {
 		char *dev;
@@ -125,7 +254,10 @@ static int act_prep_cmdline(void)
 		if (!dev)
 			break;
 
-		act_add_dev(dev);
+		if (act_add_dev(dev)) {
+			log_err("act: failed adding device to the mix\n");
+			break;
+		}
 	} while (1);
 
 	return 0;
@@ -137,6 +269,9 @@ static int act_io_u_lat(struct thread_data *td, uint64_t usec)
 	int i, ret = 0;
 	double perm;
 
+	if (prep)
+		return 0;
+
 	apd->total_ios++;
 
 	for (i = ACT_MAX_CRIT - 1; i >= 0; i--) {
@@ -160,17 +295,83 @@ static int act_io_u_lat(struct thread_data *td, uint64_t usec)
 		break;
 	}
 
-	memset(apd->lat_buckets, 0, sizeof(apd->lat_buckets));
+	for (i = 0; i < ACT_MAX_CRIT; i++) {
+		apd->cum_lat_buckets[i] += apd->lat_buckets[i];
+		apd->lat_buckets[i] = 0;
+	}
+
+	apd->cum_total_ios += apd->total_ios;
 	apd->total_ios = 0;
 
 	fio_gettime(&apd->sample_tv, NULL);
 	return ret;
 }
 
+static void get_act_ref(void)
+{
+	fio_mutex_down(act_run_data->mutex);
+	act_run_data->pending++;
+	fio_mutex_up(act_run_data->mutex);
+}
+
+static void act_show_all_stats(void)
+{
+	unsigned int i;
+
+	log_info("         trans                  device\n");
+	log_info("         %%>(ms)                 %%>(ms)\n");
+	log_info(" slice");
+
+	for (i = 0; i < ACT_MAX_CRIT; i++)
+		log_info("\t%2u", act_pass[i].max_usec / 1000);
+	for (i = 0; i < ACT_MAX_CRIT; i++)
+		log_info("\t%2u", act_pass[i].max_usec / 1000);
+
+	log_info("\n");
+	log_info(" -----   ------ ------ ------   ------ ------ ------\n");
+	log_info("     1");
+
+	for (i = 0; i < ACT_MAX_CRIT; i++) {
+		double perc;
+
+		perc = 100.0 * (double) act_run_data->lat_buckets[i] / (double) act_run_data->total_ios;
+		log_info("\t%2.2f", perc);
+	}
+	for (i = 0; i < ACT_MAX_CRIT; i++) {
+		double perc;
+
+		perc = 100.0 * (double) act_run_data->lat_buckets[i] / (double) act_run_data->total_ios;
+		log_info("\t%2.2f", perc);
+	}
+
+}
+
+static void put_act_ref(struct thread_data *td)
+{
+	struct act_prof_data *apd = td->prof_data;
+	unsigned int i;
+
+	fio_mutex_down(act_run_data->mutex);
+
+	for (i = 0; i < ACT_MAX_CRIT; i++) {
+		act_run_data->lat_buckets[i] += apd->cum_lat_buckets[i];
+		act_run_data->lat_buckets[i] += apd->lat_buckets[i];
+	}
+
+	act_run_data->total_ios += apd->cum_total_ios + apd->total_ios;
+
+	if (!--act_run_data->pending)
+		act_show_all_stats();
+
+	fio_mutex_up(act_run_data->mutex);
+}
+
 static int act_td_init(struct thread_data *td)
 {
 	struct act_prof_data *apd;
 
+	get_act_ref();
+
 	apd = calloc(sizeof(*apd), 1);
 	fio_gettime(&apd->sample_tv, NULL);
 	td->prof_data = apd;
@@ -179,6 +380,7 @@ static int act_td_init(struct thread_data *td)
 
 static void act_td_exit(struct thread_data *td)
 {
+	put_act_ref(td);
 	free(td->prof_data);
 	td->prof_data = NULL;
 }
@@ -200,6 +402,9 @@ static struct profile_ops act_profile = {
 
 static void fio_init act_register(void)
 {
+	act_run_data = calloc(sizeof(*act_run_data), 1);
+	act_run_data->mutex = fio_mutex_init(FIO_MUTEX_UNLOCKED);
+
 	if (register_profile(&act_profile))
 		log_err("fio: failed to register profile 'act'\n");
 }
@@ -210,4 +415,7 @@ static void fio_exit act_unregister(void)
 		free((void *) act_opts[++org_idx]);
 
 	unregister_profile(&act_profile);
+	fio_mutex_remove(act_run_data->mutex);
+	free(act_run_data);
+	act_run_data = NULL;
 }
--
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