X-Git-Url: https://git.kernel.dk/?p=fio.git;a=blobdiff_plain;f=engines%2Fnet.c;h=0efd3369ab3ae6b9caf4f327682a9d30ffcb71bd;hp=4936cc24fbc74c9c3b538bbbb382c5214f970ba6;hb=5921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373;hpb=9cce02e89e01984a5bf58e730fb9311dc5273554 diff --git a/engines/net.c b/engines/net.c index 4936cc24..0efd3369 100644 --- a/engines/net.c +++ b/engines/net.c @@ -28,7 +28,6 @@ struct netio_data { static int fio_netio_prep(struct thread_data *td, struct io_u *io_u) { struct netio_data *nd = td->io_ops->data; - struct fio_file *f = io_u->file; /* * Make sure we don't see spurious reads to a receiver, and vice versa @@ -39,31 +38,16 @@ static int fio_netio_prep(struct thread_data *td, struct io_u *io_u) return 1; } - if (io_u->ddir == DDIR_SYNC) - return 0; - if (io_u->offset == f->last_completed_pos) - return 0; - - /* - * If offset is different from last end position, it's a seek. - * As network io is purely sequential, we don't allow seeks. - */ - td_verror(td, EINVAL, "cannot seek"); - return 1; + return 0; } -/* - * Receive bytes from a socket and fill them into the internal pipe - */ -static int splice_in(struct thread_data *td, struct io_u *io_u) +#ifdef FIO_HAVE_SPLICE +static int splice_io_u(int fdin, int fdout, unsigned int len) { - struct netio_data *nd = td->io_ops->data; - unsigned int len = io_u->xfer_buflen; - struct fio_file *f = io_u->file; int bytes = 0; while (len) { - int ret = splice(nd->pipes[1], NULL, f->fd, NULL, len, 0); + int ret = splice(fdin, NULL, fdout, NULL, len, 0); if (ret < 0) { if (!bytes) @@ -74,11 +58,22 @@ static int splice_in(struct thread_data *td, struct io_u *io_u) break; bytes += ret; + len -= ret; } return bytes; } +/* + * Receive bytes from a socket and fill them into the internal pipe + */ +static int splice_in(struct thread_data *td, struct io_u *io_u) +{ + struct netio_data *nd = td->io_ops->data; + + return splice_io_u(io_u->file->fd, nd->pipes[1], io_u->xfer_buflen); +} + /* * Transmit 'len' bytes from the internal pipe */ @@ -86,25 +81,35 @@ static int splice_out(struct thread_data *td, struct io_u *io_u, unsigned int len) { struct netio_data *nd = td->io_ops->data; - struct fio_file *f = io_u->file; + + return splice_io_u(nd->pipes[0], io_u->file->fd, len); +} + +static int vmsplice_io_u(struct io_u *io_u, int fd, unsigned int len) +{ + struct iovec iov = { + .iov_base = io_u->xfer_buf, + .iov_len = len, + }; int bytes = 0; - while (len) { - int ret = splice(nd->pipes[0], NULL, f->fd, NULL, len, 0); + while (iov.iov_len) { + int ret = vmsplice(fd, &iov, 1, SPLICE_F_MOVE); if (ret < 0) { if (!bytes) bytes = ret; - break; } else if (!ret) break; + iov.iov_len -= ret; + iov.iov_base += ret; bytes += ret; - len -= ret; } return bytes; + } /* @@ -114,28 +119,8 @@ static int vmsplice_io_u_out(struct thread_data *td, struct io_u *io_u, unsigned int len) { struct netio_data *nd = td->io_ops->data; - struct iovec iov = { - .iov_base = io_u->xfer_buf, - .iov_len = len, - }; - int bytes = 0; - - while (iov.iov_len) { - int ret = vmsplice(nd->pipes[0], &iov, 1, 0); - - if (ret < 0) { - if (!bytes) - bytes = ret; - break; - } else if (!ret) - break; - iov.iov_len -= ret; - if (iov.iov_len) - iov.iov_base += ret; - } - - return bytes; + return vmsplice_io_u(io_u, nd->pipes[0], len); } /* @@ -144,50 +129,52 @@ static int vmsplice_io_u_out(struct thread_data *td, struct io_u *io_u, static int vmsplice_io_u_in(struct thread_data *td, struct io_u *io_u) { struct netio_data *nd = td->io_ops->data; - struct iovec iov = { - .iov_base = io_u->xfer_buf, - .iov_len = io_u->xfer_buflen, - }; - unsigned int bytes = 0; - - while (iov.iov_len) { - int ret = vmsplice(nd->pipes[1], &iov, 1, 0); - if (ret < 0) - return -1; - else if (!ret) - return bytes; - - iov.iov_len -= ret; - bytes += ret; - if (iov.iov_len) - iov.iov_base += ret; - } - - return bytes; + return vmsplice_io_u(io_u, nd->pipes[1], io_u->xfer_buflen); } +/* + * splice receive - transfer socket data into a pipe using splice, then map + * that pipe data into the io_u using vmsplice. + */ static int fio_netio_splice_in(struct thread_data *td, struct io_u *io_u) { int ret; ret = splice_in(td, io_u); - if (ret <= 0) - return ret; + if (ret > 0) + return vmsplice_io_u_out(td, io_u, ret); - return vmsplice_io_u_out(td, io_u, ret); + return ret; } +/* + * splice transmit - map data from the io_u into a pipe by using vmsplice, + * then transfer that pipe to a socket using splice. + */ static int fio_netio_splice_out(struct thread_data *td, struct io_u *io_u) { int ret; ret = vmsplice_io_u_in(td, io_u); - if (ret <= 0) - return ret; + if (ret > 0) + return splice_out(td, io_u, ret); + + return ret; +} +#else +static int fio_netio_splice_in(struct thread_data *td, struct io_u *io_u) +{ + errno = -EOPNOTSUPP; + return -1; +} - return splice_out(td, io_u, ret); +static int fio_netio_splice_out(struct thread_data *td, struct io_u *io_u) +{ + errno = -EOPNOTSUPP; + return -1; } +#endif static int fio_netio_send(struct thread_data *td, struct io_u *io_u) { @@ -196,8 +183,10 @@ static int fio_netio_send(struct thread_data *td, struct io_u *io_u) /* * if we are going to write more, set MSG_MORE */ +#ifdef MSG_MORE if (td->this_io_bytes[DDIR_WRITE] + io_u->xfer_buflen < td->o.size) flags = MSG_MORE; +#endif return send(io_u->file->fd, io_u->xfer_buf, io_u->xfer_buflen, flags); } @@ -214,6 +203,8 @@ static int fio_netio_queue(struct thread_data *td, struct io_u *io_u) struct netio_data *nd = td->io_ops->data; int ret; + fio_ro_check(td, io_u); + if (io_u->ddir == DDIR_WRITE) { if (nd->use_splice) ret = fio_netio_splice_out(td, io_u); @@ -304,7 +295,6 @@ static int fio_netio_accept(struct thread_data *td, struct fio_file *f) return 0; } - static int fio_netio_open_file(struct thread_data *td, struct fio_file *f) { if (td_read(td)) @@ -379,7 +369,7 @@ static int fio_netio_setup_listen(struct thread_data *td, short port) static int fio_netio_init(struct thread_data *td) { struct netio_data *nd = td->io_ops->data; - unsigned short port; + unsigned int port; char host[64], buf[128]; char *sep; int ret; @@ -396,15 +386,18 @@ static int fio_netio_init(struct thread_data *td) strcpy(buf, td->o.filename); sep = strchr(buf, '/'); - if (!sep) { - log_err("fio: bad network host/port <<%s>>\n", td->o.filename); - return 1; - } + if (!sep) + goto bad_host; *sep = '\0'; sep++; strcpy(host, buf); - port = atoi(sep); + if (!strlen(host)) + goto bad_host; + + port = strtol(sep, NULL, 10); + if (!port || port > 65535) + goto bad_host; if (td_read(td)) { nd->send_to_net = 0; @@ -415,6 +408,9 @@ static int fio_netio_init(struct thread_data *td) } return ret; +bad_host: + log_err("fio: bad network host/port: %s\n", td->o.filename); + return 1; } static void fio_netio_cleanup(struct thread_data *td) @@ -422,6 +418,13 @@ static void fio_netio_cleanup(struct thread_data *td) struct netio_data *nd = td->io_ops->data; if (nd) { + if (nd->listenfd != -1) + close(nd->listenfd); + if (nd->pipes[0] != -1) + close(nd->pipes[0]); + if (nd->pipes[1] != -1) + close(nd->pipes[1]); + free(nd); td->io_ops->data = NULL; } @@ -436,12 +439,14 @@ static int fio_netio_setup(struct thread_data *td) memset(nd, 0, sizeof(*nd)); nd->listenfd = -1; + nd->pipes[0] = nd->pipes[1] = -1; td->io_ops->data = nd; } return 0; } +#ifdef FIO_HAVE_SPLICE static int fio_netio_setup_splice(struct thread_data *td) { struct netio_data *nd; @@ -460,40 +465,47 @@ static int fio_netio_setup_splice(struct thread_data *td) return 1; } -static struct ioengine_ops ioengine_rw = { - .name = "net", +static struct ioengine_ops ioengine_splice = { + .name = "netsplice", .version = FIO_IOOPS_VERSION, .prep = fio_netio_prep, .queue = fio_netio_queue, - .setup = fio_netio_setup, + .setup = fio_netio_setup_splice, .init = fio_netio_init, .cleanup = fio_netio_cleanup, .open_file = fio_netio_open_file, .close_file = generic_close_file, - .flags = FIO_SYNCIO | FIO_DISKLESSIO, + .flags = FIO_SYNCIO | FIO_DISKLESSIO | FIO_UNIDIR | + FIO_SIGQUIT, }; +#endif -static struct ioengine_ops ioengine_splice = { - .name = "netsplice", +static struct ioengine_ops ioengine_rw = { + .name = "net", .version = FIO_IOOPS_VERSION, .prep = fio_netio_prep, .queue = fio_netio_queue, - .setup = fio_netio_setup_splice, + .setup = fio_netio_setup, .init = fio_netio_init, .cleanup = fio_netio_cleanup, .open_file = fio_netio_open_file, .close_file = generic_close_file, - .flags = FIO_SYNCIO | FIO_DISKLESSIO, + .flags = FIO_SYNCIO | FIO_DISKLESSIO | FIO_UNIDIR | + FIO_SIGQUIT, }; static void fio_init fio_netio_register(void) { register_ioengine(&ioengine_rw); +#ifdef FIO_HAVE_SPLICE register_ioengine(&ioengine_splice); +#endif } static void fio_exit fio_netio_unregister(void) { unregister_ioengine(&ioengine_rw); +#ifdef FIO_HAVE_SPLICE unregister_ioengine(&ioengine_splice); +#endif }