summaryrefslogtreecommitdiff
path: root/engines/binject.c
diff options
context:
space:
mode:
Diffstat (limited to 'engines/binject.c')
-rw-r--r--engines/binject.c457
1 files changed, 0 insertions, 457 deletions
diff --git a/engines/binject.c b/engines/binject.c
deleted file mode 100644
index 932534a0..00000000
--- a/engines/binject.c
+++ /dev/null
@@ -1,457 +0,0 @@
-/*
- * binject engine
- *
- * IO engine that uses the Linux binject interface to directly inject
- * bio's to block devices.
- *
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-#include <assert.h>
-#include <string.h>
-#include <sys/poll.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include "../fio.h"
-
-#ifdef FIO_HAVE_BINJECT
-
-struct binject_data {
- struct b_user_cmd *cmds;
- struct io_u **events;
- struct pollfd *pfds;
- int *fd_flags;
-};
-
-struct binject_file {
- unsigned int bs;
- int minor;
- int fd;
-};
-
-static void binject_buc_init(struct binject_data *bd, struct io_u *io_u)
-{
- struct b_user_cmd *buc = &io_u->buc;
-
- memset(buc, 0, sizeof(*buc));
- binject_buc_set_magic(buc);
-
- buc->buf = (unsigned long) io_u->xfer_buf;
- buc->len = io_u->xfer_buflen;
- buc->offset = io_u->offset;
- buc->usr_ptr = (unsigned long) io_u;
-
- buc->flags = B_FLAG_NOIDLE | B_FLAG_UNPLUG;
- assert(buc->buf);
-}
-
-static int pollin_events(struct pollfd *pfds, int fds)
-{
- int i;
-
- for (i = 0; i < fds; i++)
- if (pfds[i].revents & POLLIN)
- return 1;
-
- return 0;
-}
-
-static unsigned int binject_read_commands(struct thread_data *td, void *p,
- int left, int *err)
-{
- struct fio_file *f;
- int i, ret, events;
-
-one_more:
- events = 0;
- for_each_file(td, f, i) {
- struct binject_file *bf = FILE_ENG_DATA(f);
-
- ret = read(bf->fd, p, left * sizeof(struct b_user_cmd));
- if (ret < 0) {
- if (errno == EAGAIN)
- continue;
- *err = -errno;
- td_verror(td, errno, "read");
- break;
- } else if (ret) {
- p += ret;
- events += ret / sizeof(struct b_user_cmd);
- }
- }
-
- if (*err || events)
- return events;
-
- usleep(1000);
- goto one_more;
-}
-
-static int fio_binject_getevents(struct thread_data *td, unsigned int min,
- unsigned int max,
- const struct timespec fio_unused *t)
-{
- struct binject_data *bd = td->io_ops_data;
- int left = max, ret, r = 0, ev_index = 0;
- void *buf = bd->cmds;
- unsigned int i, events;
- struct fio_file *f;
-
- /*
- * Fill in the file descriptors
- */
- for_each_file(td, f, i) {
- struct binject_file *bf = FILE_ENG_DATA(f);
-
- /*
- * don't block for min events == 0
- */
- if (!min)
- bd->fd_flags[i] = fio_set_fd_nonblocking(bf->fd, "binject");
- else
- bd->fd_flags[i] = -1;
-
- bd->pfds[i].fd = bf->fd;
- bd->pfds[i].events = POLLIN;
- }
-
- while (left) {
- while (!min) {
- ret = poll(bd->pfds, td->o.nr_files, -1);
- if (ret < 0) {
- if (!r)
- r = -errno;
- td_verror(td, errno, "poll");
- break;
- } else if (!ret)
- continue;
-
- if (pollin_events(bd->pfds, td->o.nr_files))
- break;
- }
-
- if (r < 0)
- break;
-
- events = binject_read_commands(td, buf, left, &r);
-
- if (r < 0)
- break;
-
- left -= events;
- r += events;
-
- for (i = 0; i < events; i++) {
- struct b_user_cmd *buc = (struct b_user_cmd *) buf + i;
-
- bd->events[ev_index] = (struct io_u *) (unsigned long) buc->usr_ptr;
- ev_index++;
- }
- }
-
- if (!min) {
- for_each_file(td, f, i) {
- struct binject_file *bf = FILE_ENG_DATA(f);
-
- if (bd->fd_flags[i] == -1)
- continue;
-
- if (fcntl(bf->fd, F_SETFL, bd->fd_flags[i]) < 0)
- log_err("fio: binject failed to restore fcntl flags: %s\n", strerror(errno));
- }
- }
-
- if (r > 0)
- assert(ev_index == r);
-
- return r;
-}
-
-static int fio_binject_doio(struct thread_data *td, struct io_u *io_u)
-{
- struct b_user_cmd *buc = &io_u->buc;
- struct binject_file *bf = FILE_ENG_DATA(io_u->file);
- int ret;
-
- ret = write(bf->fd, buc, sizeof(*buc));
- if (ret < 0)
- return ret;
-
- return FIO_Q_QUEUED;
-}
-
-static int fio_binject_prep(struct thread_data *td, struct io_u *io_u)
-{
- struct binject_data *bd = td->io_ops_data;
- struct b_user_cmd *buc = &io_u->buc;
- struct binject_file *bf = FILE_ENG_DATA(io_u->file);
-
- if (io_u->xfer_buflen & (bf->bs - 1)) {
- log_err("read/write not sector aligned\n");
- return EINVAL;
- }
-
- if (io_u->ddir == DDIR_READ) {
- binject_buc_init(bd, io_u);
- buc->type = B_TYPE_READ;
- } else if (io_u->ddir == DDIR_WRITE) {
- binject_buc_init(bd, io_u);
- if (io_u->flags & IO_U_F_BARRIER)
- buc->type = B_TYPE_WRITEBARRIER;
- else
- buc->type = B_TYPE_WRITE;
- } else if (io_u->ddir == DDIR_TRIM) {
- binject_buc_init(bd, io_u);
- buc->type = B_TYPE_DISCARD;
- } else {
- assert(0);
- }
-
- return 0;
-}
-
-static int fio_binject_queue(struct thread_data *td, struct io_u *io_u)
-{
- int ret;
-
- fio_ro_check(td, io_u);
-
- ret = fio_binject_doio(td, io_u);
-
- if (ret < 0)
- io_u->error = errno;
-
- if (io_u->error) {
- td_verror(td, io_u->error, "xfer");
- return FIO_Q_COMPLETED;
- }
-
- return ret;
-}
-
-static struct io_u *fio_binject_event(struct thread_data *td, int event)
-{
- struct binject_data *bd = td->io_ops_data;
-
- return bd->events[event];
-}
-
-static int binject_open_ctl(struct thread_data *td)
-{
- int fd;
-
- fd = open("/dev/binject-ctl", O_RDWR);
- if (fd < 0)
- td_verror(td, errno, "open binject-ctl");
-
- return fd;
-}
-
-static void binject_unmap_dev(struct thread_data *td, struct binject_file *bf)
-{
- struct b_ioctl_cmd bic;
- int fdb;
-
- if (bf->fd >= 0) {
- close(bf->fd);
- bf->fd = -1;
- }
-
- fdb = binject_open_ctl(td);
- if (fdb < 0)
- return;
-
- bic.minor = bf->minor;
-
- if (ioctl(fdb, B_IOCTL_DEL, &bic) < 0)
- td_verror(td, errno, "binject dev unmap");
-
- close(fdb);
-}
-
-static int binject_map_dev(struct thread_data *td, struct binject_file *bf,
- int fd)
-{
- struct b_ioctl_cmd bic;
- char name[80];
- struct stat sb;
- int fdb, dev_there, loops;
-
- fdb = binject_open_ctl(td);
- if (fdb < 0)
- return 1;
-
- bic.fd = fd;
-
- if (ioctl(fdb, B_IOCTL_ADD, &bic) < 0) {
- td_verror(td, errno, "binject dev map");
- close(fdb);
- return 1;
- }
-
- bf->minor = bic.minor;
-
- sprintf(name, "/dev/binject%u", bf->minor);
-
- /*
- * Wait for udev to create the node...
- */
- dev_there = loops = 0;
- do {
- if (!stat(name, &sb)) {
- dev_there = 1;
- break;
- }
-
- usleep(10000);
- } while (++loops < 100);
-
- close(fdb);
-
- if (!dev_there) {
- log_err("fio: timed out waiting for binject dev\n");
- goto err_unmap;
- }
-
- bf->fd = open(name, O_RDWR);
- if (bf->fd < 0) {
- td_verror(td, errno, "binject dev open");
-err_unmap:
- binject_unmap_dev(td, bf);
- return 1;
- }
-
- return 0;
-}
-
-static int fio_binject_close_file(struct thread_data *td, struct fio_file *f)
-{
- struct binject_file *bf = FILE_ENG_DATA(f);
-
- if (bf) {
- binject_unmap_dev(td, bf);
- free(bf);
- FILE_SET_ENG_DATA(f, NULL);
- return generic_close_file(td, f);
- }
-
- return 0;
-}
-
-static int fio_binject_open_file(struct thread_data *td, struct fio_file *f)
-{
- struct binject_file *bf;
- unsigned int bs;
- int ret;
-
- ret = generic_open_file(td, f);
- if (ret)
- return 1;
-
- if (f->filetype != FIO_TYPE_BLOCK) {
- log_err("fio: binject only works with block devices\n");
- goto err_close;
- }
- if (ioctl(f->fd, BLKSSZGET, &bs) < 0) {
- td_verror(td, errno, "BLKSSZGET");
- goto err_close;
- }
-
- bf = malloc(sizeof(*bf));
- bf->bs = bs;
- bf->minor = bf->fd = -1;
- FILE_SET_ENG_DATA(f, bf);
-
- if (binject_map_dev(td, bf, f->fd)) {
-err_close:
- ret = generic_close_file(td, f);
- return 1;
- }
-
- return 0;
-}
-
-static void fio_binject_cleanup(struct thread_data *td)
-{
- struct binject_data *bd = td->io_ops_data;
-
- if (bd) {
- free(bd->events);
- free(bd->cmds);
- free(bd->fd_flags);
- free(bd->pfds);
- free(bd);
- }
-}
-
-static int fio_binject_init(struct thread_data *td)
-{
- struct binject_data *bd;
-
- bd = malloc(sizeof(*bd));
- memset(bd, 0, sizeof(*bd));
-
- bd->cmds = malloc(td->o.iodepth * sizeof(struct b_user_cmd));
- memset(bd->cmds, 0, td->o.iodepth * sizeof(struct b_user_cmd));
-
- bd->events = malloc(td->o.iodepth * sizeof(struct io_u *));
- memset(bd->events, 0, td->o.iodepth * sizeof(struct io_u *));
-
- bd->pfds = malloc(sizeof(struct pollfd) * td->o.nr_files);
- memset(bd->pfds, 0, sizeof(struct pollfd) * td->o.nr_files);
-
- bd->fd_flags = malloc(sizeof(int) * td->o.nr_files);
- memset(bd->fd_flags, 0, sizeof(int) * td->o.nr_files);
-
- td->io_ops_data = bd;
- return 0;
-}
-
-static struct ioengine_ops ioengine = {
- .name = "binject",
- .version = FIO_IOOPS_VERSION,
- .init = fio_binject_init,
- .prep = fio_binject_prep,
- .queue = fio_binject_queue,
- .getevents = fio_binject_getevents,
- .event = fio_binject_event,
- .cleanup = fio_binject_cleanup,
- .open_file = fio_binject_open_file,
- .close_file = fio_binject_close_file,
- .get_file_size = generic_get_file_size,
- .flags = FIO_RAWIO | FIO_BARRIER | FIO_MEMALIGN,
-};
-
-#else /* FIO_HAVE_BINJECT */
-
-/*
- * When we have a proper configure system in place, we simply wont build
- * and install this io engine. For now install a crippled version that
- * just complains and fails to load.
- */
-static int fio_binject_init(struct thread_data fio_unused *td)
-{
- log_err("fio: ioengine binject not available\n");
- return 1;
-}
-
-static struct ioengine_ops ioengine = {
- .name = "binject",
- .version = FIO_IOOPS_VERSION,
- .init = fio_binject_init,
-};
-
-#endif
-
-static void fio_init fio_binject_register(void)
-{
- register_ioengine(&ioengine);
-}
-
-static void fio_exit fio_binject_unregister(void)
-{
- unregister_ioengine(&ioengine);
-}