SCRIPTS = fio_generate_plots
OBJS = gettime.o fio.o ioengines.o init.o stat.o log.o time.o md5.o crc32.o \
filesetup.o eta.o verify.o memory.o io_u.o parse.o mutex.o options.o \
- rbtree.o diskutil.o blktrace.o
+ rbtree.o diskutil.o fifo.o blktrace.o
OBJS += engines/cpu.o
OBJS += engines/libaio.o
#include "fio.h"
#include "blktrace_api.h"
+#define TRACE_FIFO_SIZE (sizeof(struct blk_io_trace) * 1000)
+
+/*
+ * fifo refill frontend, to avoid reading data in trace sized bites
+ */
+static int refill_fifo(struct thread_data *td, struct fifo *fifo, int fd)
+{
+ char buf[TRACE_FIFO_SIZE];
+ unsigned int total, left;
+ void *ptr;
+ int ret;
+
+ total = 0;
+ ptr = buf;
+ while (total < TRACE_FIFO_SIZE) {
+ left = TRACE_FIFO_SIZE - total;
+
+ ret = read(fd, ptr, left);
+ if (ret < 0) {
+ td_verror(td, errno, "read blktrace file");
+ return -1;
+ } else if (!ret)
+ break;
+
+ fifo_put(fifo, ptr, ret);
+ ptr += ret;
+ total += ret;
+ }
+
+ return 0;
+}
+
+/*
+ * Retrieve 'len' bytes from the fifo, refilling if necessary.
+ */
+static int trace_fifo_get(struct thread_data *td, struct fifo *fifo, int fd,
+ void *buf, unsigned int len)
+{
+ int ret;
+
+ if (fifo_len(fifo) >= len)
+ return fifo_get(fifo, buf, len);
+
+ ret = refill_fifo(td, fifo, fd);
+ if (ret < 0)
+ return ret;
+
+ if (fifo_len(fifo) < len)
+ return 0;
+
+ return fifo_get(fifo, buf, len);
+}
+
/*
* Just discard the pdu by seeking past it.
*/
unsigned long ios[2];
unsigned int cpu;
unsigned int rw_bs[2];
+ struct fifo *fifo;
int fd;
fd = open(filename, O_RDONLY);
return 1;
}
+ fifo = fifo_alloc(TRACE_FIFO_SIZE);
+
td->o.size = 0;
cpu = 0;
ios[0] = ios[1] = 0;
rw_bs[0] = rw_bs[1] = 0;
do {
- /*
- * Once this is working fully, I'll add a layer between
- * here and read to cache trace data. Then we can avoid
- * doing itsy bitsy reads, but instead pull in a larger
- * chunk of data at the time.
- */
- int ret = read(fd, &t, sizeof(t));
+ int ret = trace_fifo_get(td, fifo, fd, &t, sizeof(t));
- if (ret < 0) {
- td_verror(td, errno, "read blktrace file");
+ if (ret < 0)
goto err;
- } else if (!ret) {
+ else if (!ret)
+ break;
+ else if (ret < (int) sizeof(t)) {
+ log_err("fio: short fifo get\n");
break;
- } else if (ret != sizeof(t)) {
- log_err("fio: short read on blktrace file\n");
- goto err;
}
if ((t.magic & 0xffffff00) != BLK_IO_TRACE_MAGIC) {
--- /dev/null
+/*
+ * A simple kernel FIFO implementation.
+ *
+ * Copyright (C) 2004 Stelian Pop <stelian@popies.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "fifo.h"
+
+struct fifo *fifo_alloc(unsigned int size)
+{
+ struct fifo *fifo;
+
+ fifo = malloc(sizeof(struct fifo));
+ if (!fifo)
+ return 0;
+
+ fifo->buffer = malloc(size);
+ fifo->size = size;
+ fifo->in = fifo->out = 0xffff0000;
+
+ return fifo;
+}
+
+void fifo_free(struct fifo *fifo)
+{
+ free(fifo->buffer);
+ free(fifo);
+}
+
+unsigned int fifo_put(struct fifo *fifo, void *buffer, unsigned int len)
+{
+ unsigned int l;
+
+ len = min(len, fifo->size - fifo->in + fifo->out);
+
+ /* first put the data starting from fifo->in to buffer end */
+ l = min(len, fifo->size - (fifo->in & (fifo->size - 1)));
+ memcpy(fifo->buffer + (fifo->in & (fifo->size - 1)), buffer, l);
+
+ /* then put the rest (if any) at the beginning of the buffer */
+ memcpy(fifo->buffer, buffer + l, len - l);
+
+ /*
+ * Ensure that we add the bytes to the fifo -before-
+ * we update the fifo->in index.
+ */
+
+ fifo->in += len;
+
+ return len;
+}
+
+unsigned int fifo_get(struct fifo *fifo, void *buffer, unsigned int len)
+{
+ unsigned int l;
+
+ len = min(len, fifo->in - fifo->out);
+
+ /* first get the data from fifo->out until the end of the buffer */
+ l = min(len, fifo->size - (fifo->out & (fifo->size - 1)));
+ memcpy(buffer, fifo->buffer + (fifo->out & (fifo->size - 1)), l);
+
+ /* then get the rest (if any) from the beginning of the buffer */
+ memcpy(buffer + l, fifo->buffer, len - l);
+
+ fifo->out += len;
+
+ return len;
+}
--- /dev/null
+/*
+ * A simple FIFO implementation.
+ *
+ * Copyright (C) 2004 Stelian Pop <stelian@popies.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+struct fifo {
+ unsigned char *buffer; /* the buffer holding the data */
+ unsigned int size; /* the size of the allocated buffer */
+ unsigned int in; /* data is added at offset (in % size) */
+ unsigned int out; /* data is extracted from off. (out % size) */
+};
+
+struct fifo *fifo_alloc(unsigned int);
+unsigned int fifo_put(struct fifo *, void *, unsigned int);
+unsigned int fifo_get(struct fifo *, void *, unsigned int);
+
+static inline unsigned int fifo_len(struct fifo *fifo)
+{
+ return fifo->in - fifo->out;
+}
+
+#define min(x,y) ({ \
+ typeof(x) _x = (x); \
+ typeof(y) _y = (y); \
+ (void) (&_x == &_y); \
+ _x < _y ? _x : _y; })
+
+#define max(x,y) ({ \
+ typeof(x) _x = (x); \
+ typeof(y) _y = (y); \
+ (void) (&_x == &_y); \
+ _x > _y ? _x : _y; })
+
#include "compiler/compiler.h"
#include "list.h"
+#include "fifo.h"
#include "rbtree.h"
#include "md5.h"
#include "crc32.h"
#define DISK_UTIL_MSEC (250)
-#ifndef min
-#define min(a, b) ((a) < (b) ? (a) : (b))
-#endif
-#ifndef max
-#define max(a, b) ((a) > (b) ? (a) : (b))
-#endif
-
/*
* Log exports
*/