X-Git-Url: https://git.kernel.dk/?p=fio.git;a=blobdiff_plain;f=engines%2Fnet.c;h=137c5799169fa10fbdbaeb597c87f0c7c17f0b95;hp=bc3946d588f4c389d448ca4c3c36cb1d4c1d0b84;hb=443662efa60d9082bc820641e7d1d31dd58d3ae1;hpb=4d94c275d2344b9231d9dc4585bd42b8e9fb7794 diff --git a/engines/net.c b/engines/net.c index bc3946d5..137c5799 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,15 @@ 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) +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(f->fd, NULL, nd->pipes[1], NULL, len, 0); + int ret = splice(fdin, NULL, fdout, NULL, len, 0); if (ret < 0) { if (!bytes) @@ -81,40 +64,28 @@ static int splice_in(struct thread_data *td, struct io_u *io_u) } /* - * Transmit 'len' bytes from the internal pipe + * Receive bytes from a socket and fill them into the internal pipe */ -static int splice_out(struct thread_data *td, struct io_u *io_u, - unsigned int len) +static int splice_in(struct thread_data *td, struct io_u *io_u) { struct netio_data *nd = td->io_ops->data; - struct fio_file *f = io_u->file; - int bytes = 0; - - while (len) { - int ret = splice(nd->pipes[0], NULL, f->fd, NULL, len, 0); - if (ret < 0) { - if (!bytes) - bytes = ret; - - break; - } else if (!ret) - break; - - bytes += ret; - len -= ret; - } - - return bytes; + return splice_io_u(io_u->file->fd, nd->pipes[1], io_u->xfer_buflen); } /* - * vmsplice() pipe to io_u buffer + * Transmit 'len' bytes from the internal pipe */ -static int vmsplice_io_u_out(struct thread_data *td, struct io_u *io_u, - unsigned int len) +static int splice_out(struct thread_data *td, struct io_u *io_u, + unsigned int len) { struct netio_data *nd = td->io_ops->data; + + 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, @@ -122,7 +93,7 @@ static int vmsplice_io_u_out(struct thread_data *td, struct io_u *io_u, int bytes = 0; while (iov.iov_len) { - int ret = vmsplice(nd->pipes[0], &iov, 1, SPLICE_F_MOVE); + int ret = vmsplice(fd, &iov, 1, SPLICE_F_MOVE); if (ret < 0) { if (!bytes) @@ -132,63 +103,63 @@ static int vmsplice_io_u_out(struct thread_data *td, struct io_u *io_u, break; iov.iov_len -= ret; + iov.iov_base += ret; bytes += ret; - if (iov.iov_len) - iov.iov_base += ret; } return bytes; + } /* - * vmsplice() io_u to pipe + * vmsplice() pipe to io_u buffer */ -static int vmsplice_io_u_in(struct thread_data *td, struct io_u *io_u) +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 = io_u->xfer_buflen, - }; - unsigned int bytes = 0; - while (iov.iov_len) { - int ret = vmsplice(nd->pipes[1], &iov, 1, SPLICE_F_MOVE); - - if (ret < 0) - return -1; - else if (!ret) - return bytes; + return vmsplice_io_u(io_u, nd->pipes[0], len); +} - iov.iov_len -= ret; - bytes += ret; - if (iov.iov_len) - iov.iov_base += ret; - } +/* + * vmsplice() io_u to pipe + */ +static int vmsplice_io_u_in(struct thread_data *td, struct io_u *io_u) +{ + struct netio_data *nd = td->io_ops->data; - 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 splice_out(td, io_u, ret); + return ret; } static int fio_netio_send(struct thread_data *td, struct io_u *io_u) @@ -216,6 +187,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); @@ -306,7 +279,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)) @@ -381,7 +353,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; @@ -398,15 +370,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; @@ -417,6 +392,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) @@ -424,6 +402,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; } @@ -438,6 +423,7 @@ 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; } @@ -472,7 +458,8 @@ static struct ioengine_ops ioengine_rw = { .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 struct ioengine_ops ioengine_splice = { @@ -485,7 +472,8 @@ static struct ioengine_ops ioengine_splice = { .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)