mirror of https://gitee.com/openkylin/qemu.git
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,
|
||||
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:
|
||||
* @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,
|
||||
size_t niov,
|
||||
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;
|
||||
struct iovec *local_iov = g_new(struct iovec, niov);
|
||||
struct iovec *local_iov_head = local_iov;
|
||||
unsigned int nlocal_iov = niov;
|
||||
int **local_fds = fds;
|
||||
size_t *local_nfds = nfds;
|
||||
bool partial = false;
|
||||
|
||||
if (nfds) {
|
||||
*nfds = 0;
|
||||
}
|
||||
|
||||
if (fds) {
|
||||
*fds = NULL;
|
||||
}
|
||||
|
||||
nlocal_iov = iov_copy(local_iov, nlocal_iov,
|
||||
iov, niov,
|
||||
0, iov_size(iov, niov));
|
||||
|
||||
while (nlocal_iov > 0) {
|
||||
while ((nlocal_iov > 0) || local_fds) {
|
||||
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 (qemu_in_coroutine()) {
|
||||
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);
|
||||
}
|
||||
continue;
|
||||
} else if (len < 0) {
|
||||
goto cleanup;
|
||||
} else if (len == 0) {
|
||||
if (partial) {
|
||||
error_setg(errp,
|
||||
"Unexpected end-of-file before all bytes were read");
|
||||
} else {
|
||||
}
|
||||
|
||||
if (len == 0) {
|
||||
if (local_nfds && *local_nfds) {
|
||||
/*
|
||||
* Got some FDs, but no data yet. This isn't an EOF
|
||||
* 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;
|
||||
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;
|
||||
}
|
||||
|
||||
if (nlocal_iov) {
|
||||
iov_discard_front(&local_iov, &nlocal_iov, len);
|
||||
}
|
||||
|
||||
next_iter:
|
||||
partial = true;
|
||||
iov_discard_front(&local_iov, &nlocal_iov, len);
|
||||
local_fds = NULL;
|
||||
local_nfds = NULL;
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
|
@ -135,20 +193,23 @@ int qio_channel_readv_all_eof(QIOChannel *ioc,
|
|||
return ret;
|
||||
}
|
||||
|
||||
int qio_channel_readv_all(QIOChannel *ioc,
|
||||
const struct iovec *iov,
|
||||
size_t niov,
|
||||
Error **errp)
|
||||
int qio_channel_readv_full_all(QIOChannel *ioc,
|
||||
const struct iovec *iov,
|
||||
size_t niov,
|
||||
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) {
|
||||
ret = -1;
|
||||
error_setg(errp,
|
||||
"Unexpected end-of-file before all bytes were read");
|
||||
} else if (ret == 1) {
|
||||
ret = 0;
|
||||
error_prepend(errp,
|
||||
"Unexpected end-of-file before all data were read.");
|
||||
return -1;
|
||||
}
|
||||
if (ret == 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue