#include <errno.h>
#include <signal.h>
#include <time.h>
+#include <ctype.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
static int timeout = TIMEOUT;
static int odirect = 1;
static int global_bs = BS;
+static char *ini_file;
static int shm_id;
int odirect;
int delay_sleep;
- int rate;
- int rate_usec_cycle;
- int rate_pending_usleep;
+ unsigned int rate;
+ unsigned int rate_usec_cycle;
+ unsigned int rate_pending_usleep;
unsigned long max_latency; /* msec */
unsigned long min_latency; /* msec */
return 1;
}
- if (read(fd, &seed, sizeof(seed)) < sizeof(seed)) {
+ if (read(fd, &seed, sizeof(seed)) < (int) sizeof(seed)) {
td->error = EIO;
close(fd);
return 1;
return b * td->bs;
}
-void add_stat_sample(struct thread_data *td, unsigned long block, unsigned long msec)
+void add_stat_sample(struct thread_data *td, unsigned long msec)
{
char sample[256];
if (td->rate)
rate_throttle(td, usec);
- add_stat_sample(td, offset / td->bs, msec);
+ add_stat_sample(td, msec);
td->blocks_read++;
sprintf(argv[0], "%s%d\n", argv[0], offset);
- if (td->ddir == DDIR_READ)
- flags = O_RDONLY;
- else
- flags = O_WRONLY | O_CREAT | O_TRUNC;
-
+ flags = 0;
if (td->odirect)
flags |= O_DIRECT;
- td->fd = open(td->file_name, flags);
+ if (td->ddir == DDIR_READ)
+ td->fd = open(td->file_name, flags | O_RDONLY);
+ else
+ td->fd = open(td->file_name, flags | O_WRONLY | O_CREAT | O_TRUNC, 0644);
+
if (td->fd == -1) {
td->error = errno;
goto err;
if (rate)
setup_rate(td, rate);
+
+ printf("Client%d: file=%s, rw=%d, prio=%d, seq=%d, odir=%d, bs=%d, rate=%d\n", thread_number, filename, rw, prio, !random, direct, bs, rate);
}
void fill_option(const char *input, char *output)
* rw=
* direct=
*/
-int parse_jobs(int argc, char *argv[], int index)
+int parse_jobs_cmd(int argc, char *argv[], int index)
{
int rw, bs, direct, prio, random, prioclass, delay, rate;
char *string, *filename, *p, *c;
add_job(filename, rw, bs, direct, (prioclass << IOPRIO_CLASS_SHIFT) | prio, random, delay, rate);
}
+ free(string);
+ free(filename);
return thread_number;
}
+int check_int(char *p, char *name, int *val)
+{
+ char str[128];
+
+ sprintf(str, "%s=%%d", name);
+ if (sscanf(p, str, val) == 1)
+ return 0;
+
+ sprintf(str, "%s = %%d", name);
+ if (sscanf(p, str, val) == 1)
+ return 0;
+
+ return 1;
+}
+
+int is_empty(char *line)
+{
+ unsigned int i;
+
+ for (i = 0; i < strlen(line); i++)
+ if (!isspace(line[i]) && !iscntrl(line[i]))
+ return 0;
+
+ return 1;
+}
+
+int parse_jobs_ini(char *file)
+{
+ int rw, bs, direct, prio, random, prioclass, delay, rate, jobs;
+ char *string, *name;
+ fpos_t off;
+ FILE *f;
+ char *p;
+
+ f = fopen(file, "r");
+ if (!f) {
+ perror("fopen");
+ return 0;
+ }
+
+ string = malloc(4096);
+ name = malloc(256);
+
+ jobs = 0;
+
+ while ((p = fgets(string, 4096, f)) != NULL) {
+ if (sscanf(p, "[%s]", name) != 1)
+ continue;
+
+ name[strlen(name) - 1] = '\0';
+
+ rw = DDIR_READ;
+ bs = global_bs;
+ direct = 1;
+ prio = 4;
+ random = !sequential;
+ prioclass = 2;
+ delay = 0;
+ rate = 0;
+
+ fgetpos(f, &off);
+ while ((p = fgets(string, 4096, f)) != NULL) {
+ if (is_empty(p))
+ break;
+ if (!check_int(p, "bs", &bs)) {
+ bs <<= 10;
+ fgetpos(f, &off);
+ continue;
+ }
+ if (!check_int(p, "rw", &rw)) {
+ fgetpos(f, &off);
+ continue;
+ }
+ if (!check_int(p, "prio", &prio)) {
+ fgetpos(f, &off);
+ continue;
+ }
+ if (!check_int(p, "prioclass", &prioclass)) {
+ fgetpos(f, &off);
+ continue;
+ }
+ if (!check_int(p, "direct", &direct)) {
+ fgetpos(f, &off);
+ continue;
+ }
+ if (!check_int(p, "rate", &rate)) {
+ fgetpos(f, &off);
+ continue;
+ }
+ if (!check_int(p, "delay", &delay)) {
+ fgetpos(f, &off);
+ continue;
+ }
+ if (!strcmp(p, "sequential")) {
+ sequential = 1;
+ fgetpos(f, &off);
+ continue;
+ }
+ if (!strcmp(p, "random")) {
+ sequential = 0;
+ fgetpos(f, &off);
+ continue;
+ }
+ }
+ fsetpos(f, &off);
+
+ add_job(name, rw, bs, direct, (prioclass << IOPRIO_CLASS_SHIFT) | prio, random, delay, rate);
+ jobs++;
+ }
+
+ free(string);
+ free(name);
+ return jobs;
+}
+
int parse_options(int argc, char *argv[])
{
int i;
parm++;
odirect = !!atoi(parm);
break;
+ case 'f':
+ if (i + 1 >= argc) {
+ printf("-f needs file as arg\n");
+ break;
+ }
+ ini_file = strdup(argv[i+1]);
+ break;
default:
- printf("bad option %s\n", argv[1]);
+ printf("bad option %s\n", argv[i]);
break;
}
}
- if (global_bs <= 0)
- global_bs = BS;
- if (timeout <= 0)
- timeout = TIMEOUT;
-
- printf("%s: %s, bs=%uKiB, timeo=%u, write_stat=%u, odirect=%d\n", argv[0], sequential ? "sequential" : "random", global_bs >> 10, timeout, write_stat, odirect);
return i;
}
atexit(free_shm);
i = parse_options(argc, argv);
- jobs = parse_jobs(argc, argv, i);
-
+
+ if (ini_file)
+ jobs = parse_jobs_ini(ini_file);
+ else
+ jobs = parse_jobs_cmd(argc, argv, i);
+
+ if (global_bs <= 0)
+ global_bs = BS;
+ if (timeout <= 0)
+ timeout = TIMEOUT;
+
+ printf("%s: %s, bs=%uKiB, timeo=%u, write_stat=%u, odirect=%d\n", argv[0], sequential ? "sequential" : "random", global_bs >> 10, timeout, write_stat, odirect);
+
if (!jobs) {
printf("Nothing to do\n");
return 1;
- }
+ } else
+ printf("%d Clients configured\n", jobs);
for (i = 0; i < jobs; i++) {
sem_init(&startup_sem, 1, 1);
unsigned long bw = 0;
if (td->error)
- continue;
+ goto show_stat;
if (td->runtime < min_run[td->ddir])
min_run[td->ddir] = td->runtime;
write_agg += (td->blocks_read * td->bs) / td->runtime;
}
+show_stat:
show_thread_status(td);
}