struct fio_file *f;
int i;
- if (td->ddir == DDIR_READ && !td_rw(td))
+ if (!td_write(td))
return 0;
/*
return 1;
}
- if (td->iomix) {
+ if (td_rw(td)) {
log_err("fio: network connections must be read OR write\n");
return 1;
}
strcpy(host, buf);
port = atoi(sep);
- if (td->ddir == DDIR_READ) {
+ if (td_read(td)) {
send_to_net(td) = 0;
ret = fio_netio_setup_listen(td, port);
} else {
break;
case TD_RUNNING:
if (td_rw(td)) {
- if (td->sequential)
- c = 'M';
- else
+ if (td_random(td))
c = 'm';
- } else if (td_read(td)) {
- if (td->sequential)
- c = 'R';
else
+ c = 'M';
+ } else if (td_read(td)) {
+ if (td_random(td))
c = 'r';
- } else {
- if (td->sequential)
- c = 'W';
else
+ c = 'R';
+ } else {
+ if (td_random(td))
c = 'w';
+ else
+ c = 'W';
}
break;
case TD_VERIFYING:
for_each_file(td, f, i) {
int file_there = !file_ok(td, f);
- if (file_there && td->ddir == DDIR_WRITE &&
- !td->overwrite) {
+ if (file_there && td_write(td) && !td->overwrite) {
unlink(f->file_name);
file_there = 0;
}
if (td->invalidate_cache && file_invalidate_cache(td, f))
return 1;
- if (td->sequential) {
+ if (!td_random(td)) {
if (madvise(f->mmap, f->file_size, MADV_SEQUENTIAL) < 0) {
td_verror(td, errno, "madvise");
return 1;
if (td->invalidate_cache && file_invalidate_cache(td, f))
return 1;
- if (td->sequential) {
+ if (!td_random(td)) {
if (fadvise(f->fd, f->file_offset, f->file_size, POSIX_FADV_SEQUENTIAL) < 0) {
td_verror(td, errno, "fadvise");
return 1;
{
unsigned long spent;
unsigned long rate;
- int ddir = td->ddir;
/*
* allow a 2 second settle period in the beginning
* if rate blocks is set, sample is running
*/
if (td->rate_bytes) {
+ unsigned long long bytes = 0;
+
spent = mtime_since(&td->lastrate, now);
if (spent < td->ratecycle)
return 0;
- rate = (td->this_io_bytes[ddir] - td->rate_bytes) / spent;
- if (rate < td->ratemin) {
- fprintf(f_out, "%s: min rate %u not met, got %luKiB/sec\n", td->name, td->ratemin, rate);
+ if (td_read(td))
+ bytes += td->this_io_bytes[DDIR_READ];
+ if (td_write(td))
+ bytes += td->this_io_bytes[DDIR_WRITE];
+
+ if (bytes < td->rate_bytes) {
+ fprintf(f_out, "%s: min rate %u not met\n", td->name, td->ratemin);
return 1;
+ } else {
+ rate = (bytes - td->rate_bytes) / spent;
+ if (rate < td->ratemin || bytes < td->rate_bytes) {
+ fprintf(f_out, "%s: min rate %u not met, got %luKiB/sec\n", td->name, td->ratemin, rate);
+ return 1;
+ }
}
+ td->rate_bytes = bytes;
}
- td->rate_bytes = td->this_io_bytes[ddir];
memcpy(&td->lastrate, now, sizeof(*now));
return 0;
}
*/
usec = utime_since(&s, &comp_time);
- rate_throttle(td, usec, bytes_done, td->ddir);
+ rate_throttle(td, usec, bytes_done);
if (check_min_rate(td, &comp_time)) {
if (exitall_on_terminate)
else
do_io(td);
- runtime[td->ddir] += utime_since_now(&td->start);
- if (td_rw(td) && td->io_bytes[td->ddir ^ 1])
- runtime[td->ddir ^ 1] = runtime[td->ddir];
-
+ if (td_read(td) && td->io_bytes[DDIR_READ])
+ runtime[DDIR_READ] += utime_since_now(&td->start);
+ if (td_write(td) && td->io_bytes[DDIR_WRITE])
+ runtime[DDIR_WRITE] += utime_since_now(&td->start);
+
if (td->error || td->terminate)
break;
DDIR_SYNC,
};
+enum td_ddir {
+ TD_DDIR_READ = 1 << 0,
+ TD_DDIR_WRITE = 1 << 1,
+ TD_DDIR_RAND = 1 << 2,
+ TD_DDIR_RW = TD_DDIR_READ | TD_DDIR_WRITE,
+};
+
/*
* Use for maintaining statistics
*/
size_t orig_buffer_size;
volatile int terminate;
volatile int runstate;
- enum fio_ddir ddir;
- unsigned int iomix;
+ enum td_ddir td_ddir;
unsigned int ioprio;
unsigned int last_was_sync;
- unsigned int sequential;
unsigned int odirect;
unsigned int invalidate_cache;
unsigned int create_serialize;
extern struct thread_data *threads;
-#define td_read(td) ((td)->ddir == DDIR_READ)
-#define td_write(td) ((td)->ddir == DDIR_WRITE)
-#define td_rw(td) ((td)->iomix != 0)
+#define td_read(td) ((td)->td_ddir & TD_DDIR_READ)
+#define td_write(td) ((td)->td_ddir & TD_DDIR_WRITE)
+#define td_rw(td) (((td)->td_ddir & TD_DDIR_RW) == TD_DDIR_RW)
+#define td_random(td) ((td)->td_ddir & TD_DDIR_RAND)
#define BLOCKS_PER_MAP (8 * sizeof(long))
#define TO_MAP_BLOCK(td, f, b) ((b) - ((f)->file_offset / (td)->rw_min_bs))
extern unsigned long mtime_since_genesis(void);
extern void __usec_sleep(unsigned int);
extern void usec_sleep(struct thread_data *, unsigned long);
-extern void rate_throttle(struct thread_data *, unsigned long, unsigned int, int);
+extern void rate_throttle(struct thread_data *, unsigned long, unsigned int);
extern void fill_start_time(struct timeval *);
extern void fio_gettime(struct timeval *, void *);
extern void set_genesis_time(void);
/*
* only really works for sequential io for now, and with 1 file
*/
- if (td->zone_size && !td->sequential && td->nr_files == 1)
+ if (td->zone_size && td_random(td) && td->nr_files == 1)
td->zone_size = 0;
/*
*/
static int add_job(struct thread_data *td, const char *jobname, int job_add_num)
{
- const char *ddir_str[] = { "read", "write", "randread", "randwrite",
- "rw", NULL, "randrw" };
+ const char *ddir_str[] = { NULL, "read", "write", "rw", NULL,
+ "randread", "randwrite", "randrw" };
struct stat sb;
- int numjobs, ddir, i;
+ int numjobs, i;
struct fio_file *f;
/*
if (!td->name)
td->name = strdup(jobname);
- ddir = td->ddir + (!td->sequential << 1) + (td->iomix << 2);
-
if (!terse_output) {
if (!job_add_num) {
if (td->io_ops->flags & FIO_CPUIO)
c3 = to_kmg(td->min_bs[DDIR_WRITE]);
c4 = to_kmg(td->max_bs[DDIR_WRITE]);
- fprintf(f_out, "%s: (g=%d): rw=%s, bs=%s-%s/%s-%s, ioengine=%s, iodepth=%u\n", td->name, td->groupid, ddir_str[ddir], c1, c2, c3, c4, td->io_ops->name, td->iodepth);
+ fprintf(f_out, "%s: (g=%d): rw=%s, bs=%s-%s/%s-%s, ioengine=%s, iodepth=%u\n", td->name, td->groupid, ddir_str[td->td_ddir], c1, c2, c3, c4, td->io_ops->name, td->iodepth);
free(c1);
free(c2);
os_random_seed(seeds[0], &td->bsrange_state);
os_random_seed(seeds[1], &td->verify_state);
os_random_seed(seeds[2], &td->rwmix_state);
- os_random_seed(seeds[3], &td->next_file_state);
- if (td->sequential)
+ if (td->file_service_type == FIO_FSERVICE_RANDOM)
+ os_random_seed(seeds[3], &td->next_file_state);
+
+ if (!td_random(td))
return 0;
if (td->rand_repeatable)
struct thread_data *td = data;
if (!strncmp(mem, "read", 4) || !strncmp(mem, "0", 1)) {
- td->ddir = DDIR_READ;
- td->sequential = 1;
+ td->td_ddir = TD_DDIR_READ;
return 0;
} else if (!strncmp(mem, "randread", 8)) {
- td->ddir = DDIR_READ;
- td->sequential = 0;
+ td->td_ddir = TD_DDIR_READ | TD_DDIR_RAND;
return 0;
} else if (!strncmp(mem, "write", 5) || !strncmp(mem, "1", 1)) {
- td->ddir = DDIR_WRITE;
- td->sequential = 1;
+ td->td_ddir = TD_DDIR_WRITE;
return 0;
} else if (!strncmp(mem, "randwrite", 9)) {
- td->ddir = DDIR_WRITE;
- td->sequential = 0;
+ td->td_ddir = TD_DDIR_WRITE | TD_DDIR_RAND;
return 0;
} else if (!strncmp(mem, "rw", 2)) {
- td->ddir = DDIR_READ;
- td->iomix = 1;
- td->sequential = 1;
+ td->td_ddir = TD_DDIR_RW;
return 0;
} else if (!strncmp(mem, "randrw", 6)) {
- td->ddir = DDIR_READ;
- td->iomix = 1;
- td->sequential = 0;
+ td->td_ddir = TD_DDIR_RW | TD_DDIR_RAND;
return 0;
}
unsigned long long b, rb;
long r;
- if (!td->sequential) {
+ if (td_random(td)) {
unsigned long long max_blocks = f->file_size / td->min_bs[ddir];
int loops = 5;
/*
* mark entry before potentially trimming io_u
*/
- if (!td->read_iolog && !td->sequential && !td->norandommap)
+ if (!td->read_iolog && td_random(td) && !td->norandommap)
mark_random_map(td, f, io_u);
/*
* be laid out with the block scattered as written. it's faster to
* read them in in that order again, so don't sort
*/
- if (td->sequential || !td->overwrite) {
+ if (!td_random(td) || !td->overwrite) {
list_add_tail(&ipo->list, &td->io_hist_list);
return;
}
if (!reads && !writes)
return 1;
else if (reads && !writes)
- td->ddir = DDIR_READ;
+ td->td_ddir = TD_DDIR_READ;
else if (!reads && writes)
- td->ddir = DDIR_READ;
+ td->td_ddir = TD_DDIR_READ;
else
- td->iomix = 1;
+ td->td_ddir = TD_DDIR_RW;
return 0;
}
else
fprintf(f_out, "%s: (groupid=%d): err=%2d (%s): pid=%d\n",td->name, td->groupid, td->error, td->verror, td->pid);
- show_ddir_status(td, rs, td->ddir);
- if (td->io_bytes[td->ddir ^ 1])
- show_ddir_status(td, rs, td->ddir ^ 1);
+ if (td_read(td))
+ show_ddir_status(td, rs, DDIR_READ);
+ if (td_write(td))
+ show_ddir_status(td, rs, DDIR_WRITE);
runtime = mtime_since(&td->epoch, &td->end_time);
if (runtime) {
}
void rate_throttle(struct thread_data *td, unsigned long time_spent,
- unsigned int bytes, int ddir)
+ unsigned int bytes)
{
unsigned long usec_cycle;
if (!td->rate)
return;
- usec_cycle = td->rate_usec_cycle * (bytes / td->min_bs[ddir]);
+ usec_cycle = td->rate_usec_cycle * (bytes / td->rw_min_bs);
if (time_spent < usec_cycle) {
unsigned long s = usec_cycle - time_spent;