60e705c51c
Currently the QIOTaskFunc signature takes an Object * for the source, and an Error * for any error. We also need to be able to provide a result pointer. Rather than continue to add parameters to QIOTaskFunc, remove the existing ones and simply pass the QIOTask object instead. This has methods to access all the other data items required in the callback impl. Reviewed-by: Eric Blake <eblake@redhat.com> Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
92 lines
2.8 KiB
C
92 lines
2.8 KiB
C
/*
|
|
* Copyright (C) 2005 Anthony Liguori <anthony@codemonkey.ws>
|
|
*
|
|
* Network Block Device Common Code
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; under version 2 of the License.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "qemu/osdep.h"
|
|
#include "qapi/error.h"
|
|
#include "nbd-internal.h"
|
|
|
|
ssize_t nbd_wr_syncv(QIOChannel *ioc,
|
|
struct iovec *iov,
|
|
size_t niov,
|
|
size_t length,
|
|
bool do_read)
|
|
{
|
|
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;
|
|
|
|
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, &local_err);
|
|
} else {
|
|
len = qio_channel_writev(ioc, local_iov, nlocal_iov, &local_err);
|
|
}
|
|
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 if (done) {
|
|
/* XXX this is needed by nbd_reply_ready. */
|
|
qio_channel_wait(ioc,
|
|
do_read ? G_IO_IN : G_IO_OUT);
|
|
} else {
|
|
return -EAGAIN;
|
|
}
|
|
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;
|
|
}
|
|
|
|
if (do_read && len == 0) {
|
|
break;
|
|
}
|
|
|
|
iov_discard_front(&local_iov, &nlocal_iov, len);
|
|
done += len;
|
|
}
|
|
|
|
cleanup:
|
|
g_free(local_iov_head);
|
|
return done;
|
|
}
|
|
|
|
|
|
void nbd_tls_handshake(QIOTask *task,
|
|
void *opaque)
|
|
{
|
|
struct NBDTLSHandshakeData *data = opaque;
|
|
|
|
if (qio_task_propagate_error(task, &data->error)) {
|
|
TRACE("TLS failed %s", error_get_pretty(data->error));
|
|
}
|
|
data->complete = true;
|
|
g_main_loop_quit(data->loop);
|
|
}
|