*/
#include <stdio.h>
#include <stdlib.h>
-#include <libgen.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "flist.h"
#include "fio.h"
-#include "verify.h"
#include "trim.h"
#include "filelock.h"
#include "smalloc.h"
#include "blktrace.h"
#include "pshared.h"
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
static int iolog_flush(struct io_log *log);
static const char iolog_ver2[] = "fio version 2 iolog";
if (!td->o.write_iolog_file)
return;
- fprintf(td->iolog_f, "%s %s %llu %lu\n", io_u->file->file_name,
+ fprintf(td->iolog_f, "%s %s %llu %llu\n", io_u->file->file_name,
io_ddir_name(io_u->ddir),
io_u->offset, io_u->buflen);
}
static void iolog_delay(struct thread_data *td, unsigned long delay)
{
uint64_t usec = utime_since_now(&td->last_issue);
+ unsigned long orig_delay = delay;
uint64_t this_delay;
struct timespec ts;
}
usec = utime_since_now(&ts);
- if (usec > delay)
- td->time_offset = usec - delay;
+ if (usec > orig_delay)
+ td->time_offset = usec - orig_delay;
else
td->time_offset = 0;
}
io_u->buflen = ipo->len;
io_u->file = td->files[ipo->fileno];
get_file(io_u->file);
- dprint(FD_IO, "iolog: get %llu/%lu/%s\n", io_u->offset,
+ dprint(FD_IO, "iolog: get %llu/%llu/%s\n", io_u->offset,
io_u->buflen, io_u->file->file_name);
if (ipo->delay)
iolog_delay(td, ipo->delay);
struct fio_rb_node **p, *parent;
struct io_piece *ipo, *__ipo;
- ipo = malloc(sizeof(struct io_piece));
+ ipo = calloc(1, sizeof(struct io_piece));
init_ipo(ipo);
ipo->file = io_u->file;
ipo->offset = io_u->offset;
}
/*
- * We don't need to sort the entries if we only performed sequential
- * writes. In this case, just reading back data in the order we wrote
- * it out is the faster but still safe.
- *
- * One exception is if we don't have a random map in which case we need
+ * Only sort writes if we don't have a random map in which case we need
* to check for duplicate blocks and drop the old one, which we rely on
* the rb insert/lookup for handling.
*/
- if (((!td->o.verifysort) || !td_random(td)) &&
- file_randommap(td, ipo->file)) {
+ if (file_randommap(td, ipo->file)) {
INIT_FLIST_HEAD(&ipo->list);
flist_add_tail(&ipo->list, &td->io_hist_list);
ipo->flags |= IP_F_ONLIST;
td->io_hist_len--;
}
-void trim_io_piece(struct thread_data *td, const struct io_u *io_u)
+void trim_io_piece(const struct io_u *io_u)
{
struct io_piece *ipo = io_u->ipo;
* Read version 2 iolog data. It is enhanced to include per-file logging,
* syncs, etc.
*/
-static int read_iolog2(struct thread_data *td, FILE *f)
+static bool read_iolog2(struct thread_data *td, FILE *f)
{
unsigned long long offset;
unsigned int bytes;
/*
* Make note of file
*/
- ipo = malloc(sizeof(*ipo));
+ ipo = calloc(1, sizeof(*ipo));
init_ipo(ipo);
ipo->ddir = rw;
if (rw == DDIR_WAIT) {
}
if (!reads && !writes && !waits)
- return 1;
+ return false;
else if (reads && !writes)
td->o.td_ddir = TD_DDIR_READ;
else if (!reads && writes)
else
td->o.td_ddir = TD_DDIR_RW;
- return 0;
+ return true;
+}
+
+static bool is_socket(const char *path)
+{
+ struct stat buf;
+ int r = stat(path, &buf);
+ if (r == -1)
+ return false;
+
+ return S_ISSOCK(buf.st_mode);
+}
+
+static int open_socket(const char *path)
+{
+ int fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ struct sockaddr_un addr;
+ if (fd < 0)
+ return fd;
+ addr.sun_family = AF_UNIX;
+ strncpy(addr.sun_path, path, sizeof(addr.sun_path));
+ if (connect(fd, (const struct sockaddr *)&addr, strlen(path) + sizeof(addr.sun_family)) == 0)
+ return fd;
+ else
+ close(fd);
+ return -1;
}
/*
* open iolog, check version, and call appropriate parser
*/
-static int init_iolog_read(struct thread_data *td)
+static bool init_iolog_read(struct thread_data *td)
{
char buffer[256], *p;
- FILE *f;
- int ret;
-
- f = fopen(td->o.read_iolog_file, "r");
+ FILE *f = NULL;
+ bool ret;
+ if (is_socket(td->o.read_iolog_file)) {
+ int fd = open_socket(td->o.read_iolog_file);
+ if (fd >= 0) {
+ f = fdopen(fd, "r");
+ }
+ } else
+ f = fopen(td->o.read_iolog_file, "r");
if (!f) {
perror("fopen read iolog");
- return 1;
+ return false;
}
p = fgets(buffer, sizeof(buffer), f);
td_verror(td, errno, "iolog read");
log_err("fio: unable to read iolog\n");
fclose(f);
- return 1;
+ return false;
}
/*
ret = read_iolog2(td, f);
else {
log_err("fio: iolog version 1 is no longer supported\n");
- ret = 1;
+ ret = false;
}
fclose(f);
/*
* Set up a log for storing io patterns.
*/
-static int init_iolog_write(struct thread_data *td)
+static bool init_iolog_write(struct thread_data *td)
{
struct fio_file *ff;
FILE *f;
f = fopen(td->o.write_iolog_file, "a");
if (!f) {
perror("fopen write iolog");
- return 1;
+ return false;
}
/*
*/
if (fprintf(f, "%s\n", iolog_ver2) < 0) {
perror("iolog init\n");
- return 1;
+ return false;
}
/*
for_each_file(td, ff, i)
log_file(td, ff, FIO_LOG_ADD_FILE);
- return 0;
+ return true;
}
-int init_iolog(struct thread_data *td)
+bool init_iolog(struct thread_data *td)
{
- int ret = 0;
+ bool ret;
if (td->o.read_iolog_file) {
int need_swap;
ret = init_iolog_read(td);
} else if (td->o.write_iolog_file)
ret = init_iolog_write(td);
+ else
+ ret = true;
- if (ret)
+ if (!ret)
td_verror(td, EINVAL, "failed initializing iolog");
return ret;
}
if (l->td && l->td->o.io_submit_mode != IO_MODE_OFFLOAD) {
- struct io_logs *p;
+ struct io_logs *__p;
- p = calloc(1, sizeof(*l->pending));
- p->max_samples = DEF_LOG_ENTRIES;
- p->log = calloc(p->max_samples, log_entry_sz(l));
- l->pending = p;
+ __p = calloc(1, sizeof(*l->pending));
+ __p->max_samples = DEF_LOG_ENTRIES;
+ __p->log = calloc(__p->max_samples, log_entry_sz(l));
+ l->pending = __p;
}
if (l->log_offset)
entry_before = flist_first_entry(&entry->list, struct io_u_plat_entry, list);
io_u_plat_before = entry_before->io_u_plat;
- fprintf(f, "%lu, %u, %u, ", (unsigned long) s->time,
- io_sample_ddir(s), s->bs);
+ fprintf(f, "%lu, %u, %llu, ", (unsigned long) s->time,
+ io_sample_ddir(s), (unsigned long long) s->bs);
for (j = 0; j < FIO_IO_U_PLAT_NR - stride; j += stride) {
fprintf(f, "%llu, ", (unsigned long long)
hist_sum(j, stride, io_u_plat, io_u_plat_before));
s = __get_sample(samples, log_offset, i);
if (!log_offset) {
- fprintf(f, "%lu, %" PRId64 ", %u, %u\n",
+ fprintf(f, "%lu, %" PRId64 ", %u, %llu\n",
(unsigned long) s->time,
s->data.val,
- io_sample_ddir(s), s->bs);
+ io_sample_ddir(s), (unsigned long long) s->bs);
} else {
struct io_sample_offset *so = (void *) s;
- fprintf(f, "%lu, %" PRId64 ", %u, %u, %llu\n",
+ fprintf(f, "%lu, %" PRId64 ", %u, %llu, %llu\n",
(unsigned long) s->time,
s->data.val,
- io_sample_ddir(s), s->bs,
+ io_sample_ddir(s), (unsigned long long) s->bs,
(unsigned long long) so->offset);
}
}
struct iolog_compress ic;
z_stream stream;
struct stat sb;
- ssize_t ret;
+ size_t ret;
size_t total;
void *buf;
FILE *f;
ic.seq = 1;
ret = fread(ic.buf, ic.len, 1, f);
- if (ret < 0) {
+ if (ret == 0 && ferror(f)) {
perror("fread");
fclose(f);
free(buf);
return 1;
- } else if (ret != 1) {
+ } else if (ferror(f) || (!feof(f) && ret != 1)) {
log_err("fio: short read on reading log\n");
fclose(f);
free(buf);