mirror of
https://gitlab.com/qemu-project/qemu
synced 2024-10-15 07:22:46 +00:00
io: add qio_channel_readv_full_all_eof & qio_channel_readv_full_all helpers
Adds qio_channel_readv_full_all_eof() and qio_channel_readv_full_all() to read both data and FDs. Refactors existing code to use these helpers. Signed-off-by: Elena Ufimtseva <elena.ufimtseva@oracle.com> Signed-off-by: John G Johnson <john.g.johnson@oracle.com> Signed-off-by: Jagannathan Raman <jag.raman@oracle.com> Acked-by: Daniel P. Berrangé <berrange@redhat.com> Message-id: b059c4cc0fb741e794d644c144cc21372cad877d.1611938319.git.jag.raman@oracle.com Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
parent
bfa4238750
commit
bebab91ebd
|
@ -777,6 +777,59 @@ void qio_channel_set_aio_fd_handler(QIOChannel *ioc,
|
||||||
IOHandler *io_write,
|
IOHandler *io_write,
|
||||||
void *opaque);
|
void *opaque);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* qio_channel_readv_full_all_eof:
|
||||||
|
* @ioc: the channel object
|
||||||
|
* @iov: the array of memory regions to read data to
|
||||||
|
* @niov: the length of the @iov array
|
||||||
|
* @fds: an array of file handles to read
|
||||||
|
* @nfds: number of file handles in @fds
|
||||||
|
* @errp: pointer to a NULL-initialized error object
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Performs same function as qio_channel_readv_all_eof.
|
||||||
|
* Additionally, attempts to read file descriptors shared
|
||||||
|
* over the channel. The function will wait for all
|
||||||
|
* requested data to be read, yielding from the current
|
||||||
|
* coroutine if required. data refers to both file
|
||||||
|
* descriptors and the iovs.
|
||||||
|
*
|
||||||
|
* Returns: 1 if all bytes were read, 0 if end-of-file
|
||||||
|
* occurs without data, or -1 on error
|
||||||
|
*/
|
||||||
|
|
||||||
|
int qio_channel_readv_full_all_eof(QIOChannel *ioc,
|
||||||
|
const struct iovec *iov,
|
||||||
|
size_t niov,
|
||||||
|
int **fds, size_t *nfds,
|
||||||
|
Error **errp);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* qio_channel_readv_full_all:
|
||||||
|
* @ioc: the channel object
|
||||||
|
* @iov: the array of memory regions to read data to
|
||||||
|
* @niov: the length of the @iov array
|
||||||
|
* @fds: an array of file handles to read
|
||||||
|
* @nfds: number of file handles in @fds
|
||||||
|
* @errp: pointer to a NULL-initialized error object
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Performs same function as qio_channel_readv_all_eof.
|
||||||
|
* Additionally, attempts to read file descriptors shared
|
||||||
|
* over the channel. The function will wait for all
|
||||||
|
* requested data to be read, yielding from the current
|
||||||
|
* coroutine if required. data refers to both file
|
||||||
|
* descriptors and the iovs.
|
||||||
|
*
|
||||||
|
* Returns: 0 if all bytes were read, or -1 on error
|
||||||
|
*/
|
||||||
|
|
||||||
|
int qio_channel_readv_full_all(QIOChannel *ioc,
|
||||||
|
const struct iovec *iov,
|
||||||
|
size_t niov,
|
||||||
|
int **fds, size_t *nfds,
|
||||||
|
Error **errp);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* qio_channel_writev_full_all:
|
* qio_channel_writev_full_all:
|
||||||
* @ioc: the channel object
|
* @ioc: the channel object
|
||||||
|
|
101
io/channel.c
101
io/channel.c
|
@ -91,20 +91,48 @@ int qio_channel_readv_all_eof(QIOChannel *ioc,
|
||||||
const struct iovec *iov,
|
const struct iovec *iov,
|
||||||
size_t niov,
|
size_t niov,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
|
{
|
||||||
|
return qio_channel_readv_full_all_eof(ioc, iov, niov, NULL, NULL, errp);
|
||||||
|
}
|
||||||
|
|
||||||
|
int qio_channel_readv_all(QIOChannel *ioc,
|
||||||
|
const struct iovec *iov,
|
||||||
|
size_t niov,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
return qio_channel_readv_full_all(ioc, iov, niov, NULL, NULL, errp);
|
||||||
|
}
|
||||||
|
|
||||||
|
int qio_channel_readv_full_all_eof(QIOChannel *ioc,
|
||||||
|
const struct iovec *iov,
|
||||||
|
size_t niov,
|
||||||
|
int **fds, size_t *nfds,
|
||||||
|
Error **errp)
|
||||||
{
|
{
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
struct iovec *local_iov = g_new(struct iovec, niov);
|
struct iovec *local_iov = g_new(struct iovec, niov);
|
||||||
struct iovec *local_iov_head = local_iov;
|
struct iovec *local_iov_head = local_iov;
|
||||||
unsigned int nlocal_iov = niov;
|
unsigned int nlocal_iov = niov;
|
||||||
|
int **local_fds = fds;
|
||||||
|
size_t *local_nfds = nfds;
|
||||||
bool partial = false;
|
bool partial = false;
|
||||||
|
|
||||||
|
if (nfds) {
|
||||||
|
*nfds = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fds) {
|
||||||
|
*fds = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
nlocal_iov = iov_copy(local_iov, nlocal_iov,
|
nlocal_iov = iov_copy(local_iov, nlocal_iov,
|
||||||
iov, niov,
|
iov, niov,
|
||||||
0, iov_size(iov, niov));
|
0, iov_size(iov, niov));
|
||||||
|
|
||||||
while (nlocal_iov > 0) {
|
while ((nlocal_iov > 0) || local_fds) {
|
||||||
ssize_t len;
|
ssize_t len;
|
||||||
len = qio_channel_readv(ioc, local_iov, nlocal_iov, errp);
|
len = qio_channel_readv_full(ioc, local_iov, nlocal_iov, local_fds,
|
||||||
|
local_nfds, errp);
|
||||||
if (len == QIO_CHANNEL_ERR_BLOCK) {
|
if (len == QIO_CHANNEL_ERR_BLOCK) {
|
||||||
if (qemu_in_coroutine()) {
|
if (qemu_in_coroutine()) {
|
||||||
qio_channel_yield(ioc, G_IO_IN);
|
qio_channel_yield(ioc, G_IO_IN);
|
||||||
|
@ -112,20 +140,50 @@ int qio_channel_readv_all_eof(QIOChannel *ioc,
|
||||||
qio_channel_wait(ioc, G_IO_IN);
|
qio_channel_wait(ioc, G_IO_IN);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
} else if (len < 0) {
|
}
|
||||||
goto cleanup;
|
|
||||||
} else if (len == 0) {
|
if (len == 0) {
|
||||||
if (partial) {
|
if (local_nfds && *local_nfds) {
|
||||||
error_setg(errp,
|
/*
|
||||||
"Unexpected end-of-file before all bytes were read");
|
* Got some FDs, but no data yet. This isn't an EOF
|
||||||
} else {
|
* scenario (yet), so carry on to try to read data
|
||||||
|
* on next loop iteration
|
||||||
|
*/
|
||||||
|
goto next_iter;
|
||||||
|
} else if (!partial) {
|
||||||
|
/* No fds and no data - EOF before any data read */
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
goto cleanup;
|
||||||
|
} else {
|
||||||
|
len = -1;
|
||||||
|
error_setg(errp,
|
||||||
|
"Unexpected end-of-file before all data were read");
|
||||||
|
/* Fallthrough into len < 0 handling */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len < 0) {
|
||||||
|
/* Close any FDs we previously received */
|
||||||
|
if (nfds && fds) {
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; i < (*nfds); i++) {
|
||||||
|
close((*fds)[i]);
|
||||||
|
}
|
||||||
|
g_free(*fds);
|
||||||
|
*fds = NULL;
|
||||||
|
*nfds = 0;
|
||||||
}
|
}
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (nlocal_iov) {
|
||||||
|
iov_discard_front(&local_iov, &nlocal_iov, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
next_iter:
|
||||||
partial = true;
|
partial = true;
|
||||||
iov_discard_front(&local_iov, &nlocal_iov, len);
|
local_fds = NULL;
|
||||||
|
local_nfds = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = 1;
|
ret = 1;
|
||||||
|
@ -135,20 +193,23 @@ int qio_channel_readv_all_eof(QIOChannel *ioc,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int qio_channel_readv_all(QIOChannel *ioc,
|
int qio_channel_readv_full_all(QIOChannel *ioc,
|
||||||
const struct iovec *iov,
|
const struct iovec *iov,
|
||||||
size_t niov,
|
size_t niov,
|
||||||
Error **errp)
|
int **fds, size_t *nfds,
|
||||||
|
Error **errp)
|
||||||
{
|
{
|
||||||
int ret = qio_channel_readv_all_eof(ioc, iov, niov, errp);
|
int ret = qio_channel_readv_full_all_eof(ioc, iov, niov, fds, nfds, errp);
|
||||||
|
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
ret = -1;
|
error_prepend(errp,
|
||||||
error_setg(errp,
|
"Unexpected end-of-file before all data were read.");
|
||||||
"Unexpected end-of-file before all bytes were read");
|
return -1;
|
||||||
} else if (ret == 1) {
|
|
||||||
ret = 0;
|
|
||||||
}
|
}
|
||||||
|
if (ret == 1) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue