mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-03 07:43:54 -06:00
nbd: convert to using I/O channels for actual socket I/O
Now that all callers are converted to use I/O channels for initial connection setup, it is possible to switch the core NBD protocol handling core over to use QIOChannel APIs for actual sockets I/O. Signed-off-by: Daniel P. Berrange <berrange@redhat.com> Message-Id: <1455129674-17255-7-git-send-email-berrange@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
ae39827802
commit
1c778ef729
8 changed files with 180 additions and 151 deletions
68
nbd/common.c
68
nbd/common.c
|
@ -19,47 +19,59 @@
|
|||
#include "qemu/osdep.h"
|
||||
#include "nbd-internal.h"
|
||||
|
||||
ssize_t nbd_wr_sync(int fd, void *buffer, size_t size, bool do_read)
|
||||
ssize_t nbd_wr_syncv(QIOChannel *ioc,
|
||||
struct iovec *iov,
|
||||
size_t niov,
|
||||
size_t offset,
|
||||
size_t length,
|
||||
bool do_read)
|
||||
{
|
||||
size_t offset = 0;
|
||||
int err;
|
||||
ssize_t done = 0;
|
||||
Error *local_err = NULL;
|
||||
struct iovec *local_iov = g_new(struct iovec, niov);
|
||||
struct iovec *local_iov_head = local_iov;
|
||||
unsigned int nlocal_iov = niov;
|
||||
|
||||
if (qemu_in_coroutine()) {
|
||||
if (do_read) {
|
||||
return qemu_co_recv(fd, buffer, size);
|
||||
} else {
|
||||
return qemu_co_send(fd, buffer, size);
|
||||
}
|
||||
}
|
||||
nlocal_iov = iov_copy(local_iov, nlocal_iov,
|
||||
iov, niov,
|
||||
offset, length);
|
||||
|
||||
while (offset < size) {
|
||||
while (nlocal_iov > 0) {
|
||||
ssize_t len;
|
||||
|
||||
if (do_read) {
|
||||
len = qemu_recv(fd, buffer + offset, size - offset, 0);
|
||||
len = qio_channel_readv(ioc, local_iov, nlocal_iov, &local_err);
|
||||
} else {
|
||||
len = send(fd, buffer + offset, size - offset, 0);
|
||||
len = qio_channel_writev(ioc, local_iov, nlocal_iov, &local_err);
|
||||
}
|
||||
|
||||
if (len < 0) {
|
||||
err = socket_error();
|
||||
|
||||
/* recoverable error */
|
||||
if (err == EINTR || (offset > 0 && (err == EAGAIN || err == EWOULDBLOCK))) {
|
||||
continue;
|
||||
if (len == QIO_CHANNEL_ERR_BLOCK) {
|
||||
if (qemu_in_coroutine()) {
|
||||
/* XXX figure out if we can create a variant on
|
||||
* qio_channel_yield() that works with AIO contexts
|
||||
* and consider using that in this branch */
|
||||
qemu_coroutine_yield();
|
||||
} else {
|
||||
qio_channel_wait(ioc,
|
||||
do_read ? G_IO_IN : G_IO_OUT);
|
||||
}
|
||||
|
||||
/* unrecoverable error */
|
||||
return -err;
|
||||
continue;
|
||||
}
|
||||
if (len < 0) {
|
||||
TRACE("I/O error: %s", error_get_pretty(local_err));
|
||||
error_free(local_err);
|
||||
/* XXX handle Error objects */
|
||||
done = -EIO;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* eof */
|
||||
if (len == 0) {
|
||||
if (do_read && len == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
offset += len;
|
||||
iov_discard_front(&local_iov, &nlocal_iov, len);
|
||||
done += len;
|
||||
}
|
||||
|
||||
return offset;
|
||||
cleanup:
|
||||
g_free(local_iov_head);
|
||||
return done;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue