On Tue, Sep 05, 2017 at 02:11:14PM -0500, Eric Blake wrote: > Rather than open-coding our own read/write-all functions, we > can make use of the recently-added qio code. It slightly > changes the error message in one of the iotests. > > Signed-off-by: Eric Blake <ebl...@redhat.com> > --- > include/block/nbd.h | 2 -- > nbd/nbd-internal.h | 41 +++++++---------------------------------- > block/nbd-client.c | 15 +++++++-------- > nbd/common.c | 45 --------------------------------------------- > tests/qemu-iotests/083.out | 8 ++++---- > 5 files changed, 18 insertions(+), 93 deletions(-) > > diff --git a/include/block/nbd.h b/include/block/nbd.h > index 040cdd2e60..707fd37575 100644 > --- a/include/block/nbd.h > +++ b/include/block/nbd.h > @@ -155,8 +155,6 @@ struct NBDExportInfo { > }; > typedef struct NBDExportInfo NBDExportInfo; > > -ssize_t nbd_rwv(QIOChannel *ioc, struct iovec *iov, size_t niov, size_t > length, > - bool do_read, Error **errp); > int nbd_receive_negotiate(QIOChannel *ioc, const char *name, > QCryptoTLSCreds *tlscreds, const char *hostname, > QIOChannel **outioc, NBDExportInfo *info, > diff --git a/nbd/nbd-internal.h b/nbd/nbd-internal.h > index 03549e3f39..8a609a227f 100644 > --- a/nbd/nbd-internal.h > +++ b/nbd/nbd-internal.h > @@ -85,28 +85,14 @@ > static inline int nbd_read_eof(QIOChannel *ioc, void *buffer, size_t size, > Error **errp) > { > - struct iovec iov = { .iov_base = buffer, .iov_len = size }; > - ssize_t ret; > - > - /* Sockets are kept in blocking mode in the negotiation phase. After > - * that, a non-readable socket simply means that another thread stole > - * our request/reply. Synchronization is done with recv_coroutine, so > - * that this is coroutine-safe. > - */ > + int ret; > > assert(size); > - > - ret = nbd_rwv(ioc, &iov, 1, size, true, errp); > - if (ret <= 0) { > - return ret; > + ret = qio_channel_read_all_eof(ioc, buffer, size, errp); > + if (ret < 0) { > + ret = -EIO; > } > - > - if (ret != size) { > - error_setg(errp, "End of file"); > - return -EINVAL; > - } > - > - return 1; > + return ret; > } > > /* nbd_read > @@ -115,14 +101,7 @@ static inline int nbd_read_eof(QIOChannel *ioc, void > *buffer, size_t size, > static inline int nbd_read(QIOChannel *ioc, void *buffer, size_t size, > Error **errp) > { > - int ret = nbd_read_eof(ioc, buffer, size, errp); > - > - if (ret == 0) { > - ret = -EINVAL; > - error_setg(errp, "End of file"); > - } > - > - return ret < 0 ? ret : 0; > + return qio_channel_read_all(ioc, buffer, size, errp) < 0 ? -EIO : 0; > } > > /* nbd_write > @@ -131,13 +110,7 @@ static inline int nbd_read(QIOChannel *ioc, void > *buffer, size_t size, > static inline int nbd_write(QIOChannel *ioc, const void *buffer, size_t size, > Error **errp) > { > - struct iovec iov = { .iov_base = (void *) buffer, .iov_len = size }; > - > - ssize_t ret = nbd_rwv(ioc, &iov, 1, size, false, errp); > - > - assert(ret < 0 || ret == size); > - > - return ret < 0 ? ret : 0; > + return qio_channel_write_all(ioc, buffer, size, errp) < 0 ? -EIO : 0; > } > > struct NBDTLSHandshakeData { > diff --git a/block/nbd-client.c b/block/nbd-client.c > index f0dbea24d3..ee7f758e68 100644 > --- a/block/nbd-client.c > +++ b/block/nbd-client.c > @@ -121,7 +121,7 @@ static int nbd_co_send_request(BlockDriverState *bs, > QEMUIOVector *qiov) > { > NBDClientSession *s = nbd_get_client_session(bs); > - int rc, ret, i; > + int rc, i; > > qemu_co_mutex_lock(&s->send_mutex); > while (s->in_flight == MAX_NBD_REQUESTS) { > @@ -156,9 +156,9 @@ static int nbd_co_send_request(BlockDriverState *bs, > qio_channel_set_cork(s->ioc, true); > rc = nbd_send_request(s->ioc, request); > if (rc >= 0 && !s->quit) { > - ret = nbd_rwv(s->ioc, qiov->iov, qiov->niov, request->len, false, > - NULL); > - if (ret != request->len) { > + assert(request->len == iov_size(qiov->iov, qiov->niov)); > + if (qio_channel_writev_all(s->ioc, qiov->iov, qiov->niov, > + NULL) < 0) { > rc = -EIO; > } > } > @@ -184,7 +184,6 @@ static void nbd_co_receive_reply(NBDClientSession *s, > QEMUIOVector *qiov) > { > int i = HANDLE_TO_INDEX(s, request->handle); > - int ret; > > /* Wait until we're woken up by nbd_read_reply_entry. */ > s->requests[i].receiving = true; > @@ -195,9 +194,9 @@ static void nbd_co_receive_reply(NBDClientSession *s, > reply->error = EIO; > } else { > if (qiov && reply->error == 0) { > - ret = nbd_rwv(s->ioc, qiov->iov, qiov->niov, request->len, true, > - NULL); > - if (ret != request->len) { > + assert(request->len == iov_size(qiov->iov, qiov->niov)); > + if (qio_channel_readv_all(s->ioc, qiov->iov, qiov->niov, > + NULL) < 0) { > reply->error = EIO; > s->quit = true; > } > diff --git a/nbd/common.c b/nbd/common.c > index e288d1b972..59a5316be9 100644 > --- a/nbd/common.c > +++ b/nbd/common.c > @@ -20,51 +20,6 @@ > #include "qapi/error.h" > #include "nbd-internal.h" > > -/* nbd_wr_syncv > - * The function may be called from coroutine or from non-coroutine context. > - * When called from non-coroutine context @ioc must be in blocking mode. > - */ > -ssize_t nbd_rwv(QIOChannel *ioc, struct iovec *iov, size_t niov, size_t > length, > - bool do_read, Error **errp) > -{ > - ssize_t done = 0; > - struct iovec *local_iov = g_new(struct iovec, niov); > - struct iovec *local_iov_head = local_iov; > - unsigned int nlocal_iov = niov; > - > - nlocal_iov = iov_copy(local_iov, nlocal_iov, iov, niov, 0, length); > - > - while (nlocal_iov > 0) { > - ssize_t len; > - if (do_read) { > - len = qio_channel_readv(ioc, local_iov, nlocal_iov, errp); > - } else { > - len = qio_channel_writev(ioc, local_iov, nlocal_iov, errp); > - } > - if (len == QIO_CHANNEL_ERR_BLOCK) { > - /* errp should not be set */ > - assert(qemu_in_coroutine()); > - qio_channel_yield(ioc, do_read ? G_IO_IN : G_IO_OUT); > - continue; > - } > - if (len < 0) { > - done = -EIO; > - goto cleanup; > - } > - > - if (do_read && len == 0) { > - break; > - } > - > - iov_discard_front(&local_iov, &nlocal_iov, len); > - done += len; > - } > - > - cleanup: > - g_free(local_iov_head); > - return done; > -} > - > /* Discard length bytes from channel. Return -errno on failure and 0 on > * success */ > int nbd_drop(QIOChannel *ioc, size_t size, Error **errp) > diff --git a/tests/qemu-iotests/083.out b/tests/qemu-iotests/083.out > index fb71b6f8ad..25dde519e3 100644 > --- a/tests/qemu-iotests/083.out > +++ b/tests/qemu-iotests/083.out > @@ -69,12 +69,12 @@ read failed: Input/output error > > === Check disconnect 4 reply === > > -End of file > +Unexpected end-of-file before all bytes were read > read failed: Input/output error > > === Check disconnect 8 reply === > > -End of file > +Unexpected end-of-file before all bytes were read > read failed: Input/output error > > === Check disconnect before data === > @@ -180,12 +180,12 @@ read failed: Input/output error > > === Check disconnect 4 reply === > > -End of file > +Unexpected end-of-file before all bytes were read > read failed: Input/output error > > === Check disconnect 8 reply === > > -End of file > +Unexpected end-of-file before all bytes were read > read failed: Input/output error > > === Check disconnect before data ===
Reviewed-by: Daniel P. Berrange <berra...@redhat.com> Regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|