diff options
Diffstat (limited to 'engines/binject.c')
-rw-r--r-- | engines/binject.c | 457 |
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); -} |