static void fio_exit fio_syncio_unregister(void) { unregister_ioengine(&ioengine_rw); unregister_ioengine(&ioengine_prw); unregister_ioengine(&ioengine_vrw); #ifdef CONFIG_PWRITEV unregister_ioengine(&ioengine_pvrw); #endif }
static void fio_exit fio_pmemblk_unregister(void) { unregister_ioengine(&ioengine); }
static void fio_exit fio_libpmem_unregister(void) { unregister_ioengine(&ioengine); }
static void fio_exit fio_ioring_unregister(void) { unregister_ioengine(&ioengine); }
static void fio_exit fio_solarisaio_unregister(void) { unregister_ioengine(&ioengine); }
static void fio_exit fio_mtd_unregister(void) { unregister_ioengine(&ioengine); libmtd_close(desc); desc = NULL; }
static void fio_exit fio_mmapio_unregister(void) { unregister_ioengine(&ioengine); }
/* * For splice writing, we can vmsplice our data buffer directly into a * pipe and then splice that to a file. */ static int fio_splice_write(struct thread_data *td, struct io_u *io_u) { struct spliceio_data *sd = td->io_ops->data; struct iovec iov = { .iov_base = io_u->xfer_buf, .iov_len = io_u->xfer_buflen, }; struct pollfd pfd = { .fd = sd->pipe[1], .events = POLLOUT, }; struct fio_file *f = io_u->file; off_t off = io_u->offset; int ret, ret2; while (iov.iov_len) { if (poll(&pfd, 1, -1) < 0) return errno; ret = vmsplice(sd->pipe[1], &iov, 1, SPLICE_F_NONBLOCK); if (ret < 0) return -errno; iov.iov_len -= ret; iov.iov_base += ret; while (ret) { ret2 = splice(sd->pipe[0], NULL, f->fd, &off, ret, 0); if (ret2 < 0) return -errno; ret -= ret2; } } return io_u->xfer_buflen; } static int fio_spliceio_queue(struct thread_data *td, struct io_u *io_u) { struct spliceio_data *sd = td->io_ops->data; int uninitialized_var(ret); fio_ro_check(td, io_u); if (io_u->ddir == DDIR_READ) { if (sd->vmsplice_to_user) { ret = fio_splice_read(td, io_u); /* * This kernel doesn't support vmsplice to user * space. Reset the vmsplice_to_user flag, so that * we retry below and don't hit this path again. */ if (ret == -EBADF) sd->vmsplice_to_user = 0; } if (!sd->vmsplice_to_user) ret = fio_splice_read_old(td, io_u); } else if (io_u->ddir == DDIR_WRITE) ret = fio_splice_write(td, io_u); else ret = fsync(io_u->file->fd); if (ret != (int) io_u->xfer_buflen) { if (ret >= 0) { io_u->resid = io_u->xfer_buflen - ret; io_u->error = 0; return FIO_Q_COMPLETED; } else io_u->error = errno; } if (io_u->error) { td_verror(td, io_u->error, "xfer"); if (io_u->error == EINVAL) log_err("fio: looks like splice doesn't work on this" " file system\n"); } return FIO_Q_COMPLETED; } static void fio_spliceio_cleanup(struct thread_data *td) { struct spliceio_data *sd = td->io_ops->data; if (sd) { close(sd->pipe[0]); close(sd->pipe[1]); free(sd); } } static int fio_spliceio_init(struct thread_data *td) { struct spliceio_data *sd = malloc(sizeof(*sd)); if (pipe(sd->pipe) < 0) { td_verror(td, errno, "pipe"); free(sd); return 1; } /* * Assume this work, we'll reset this if it doesn't */ sd->vmsplice_to_user = 1; /* * Works with "real" vmsplice to user, eg mapping pages directly. * Reset if we fail. */ sd->vmsplice_to_user_map = 1; /* * And if vmsplice_to_user works, we definitely need aligned * buffers. Just set ->odirect to force that. */ if (td_read(td)) td->o.odirect = 1; td->io_ops->data = sd; return 0; } static struct ioengine_ops ioengine = { .name = "splice", .version = FIO_IOOPS_VERSION, .init = fio_spliceio_init, .queue = fio_spliceio_queue, .cleanup = fio_spliceio_cleanup, .open_file = generic_open_file, .close_file = generic_close_file, .get_file_size = generic_get_file_size, .flags = FIO_SYNCIO | FIO_PIPEIO, }; #else /* FIO_HAVE_SPLICE */ /* * 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_spliceio_init(struct thread_data fio_unused *td) { fprintf(stderr, "fio: splice not available\n"); return 1; } static struct ioengine_ops ioengine = { .name = "splice", .version = FIO_IOOPS_VERSION, .init = fio_spliceio_init, }; #endif static void fio_init fio_spliceio_register(void) { register_ioengine(&ioengine); } static void fio_exit fio_spliceio_unregister(void) { unregister_ioengine(&ioengine); }
static void fio_exit fio_syncio_unregister(void) { unregister_ioengine(&ioengine_rw); unregister_ioengine(&ioengine_prw); unregister_ioengine(&ioengine_vrw); }
static void fio_exit fio_syslet_unregister(void) { unregister_ioengine(&ioengine); }
static void fio_exit fio_guasi_unregister(void) { unregister_ioengine(&ioengine); }
static void fio_exit fio_null_unregister(void) { unregister_ioengine(&ioengine); }