mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-04 16:23:55 -06:00
QIOChannel: Add flags on io_writev and introduce io_flush callback
Add flags to io_writev and introduce io_flush as optional callback to QIOChannelClass, allowing the implementation of zero copy writes by subclasses. How to use them: - Write data using qio_channel_writev*(...,QIO_CHANNEL_WRITE_FLAG_ZERO_COPY), - Wait write completion with qio_channel_flush(). Notes: As some zero copy write implementations work asynchronously, it's recommended to keep the write buffer untouched until the return of qio_channel_flush(), to avoid the risk of sending an updated buffer instead of the buffer state during write. As io_flush callback is optional, if a subclass does not implement it, then: - io_flush will return 0 without changing anything. Also, some functions like qio_channel_writev_full_all() were adapted to receive a flag parameter. That allows shared code between zero copy and non-zero copy writev, and also an easier implementation on new flags. Signed-off-by: Leonardo Bras <leobras@redhat.com> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> Reviewed-by: Peter Xu <peterx@redhat.com> Reviewed-by: Juan Quintela <quintela@redhat.com> Message-Id: <20220513062836.965425-3-leobras@redhat.com> Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
This commit is contained in:
parent
354081d43d
commit
b88651cb4d
13 changed files with 88 additions and 14 deletions
49
io/channel.c
49
io/channel.c
|
@ -72,18 +72,32 @@ ssize_t qio_channel_writev_full(QIOChannel *ioc,
|
|||
size_t niov,
|
||||
int *fds,
|
||||
size_t nfds,
|
||||
int flags,
|
||||
Error **errp)
|
||||
{
|
||||
QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
|
||||
|
||||
if ((fds || nfds) &&
|
||||
!qio_channel_has_feature(ioc, QIO_CHANNEL_FEATURE_FD_PASS)) {
|
||||
if (fds || nfds) {
|
||||
if (!qio_channel_has_feature(ioc, QIO_CHANNEL_FEATURE_FD_PASS)) {
|
||||
error_setg_errno(errp, EINVAL,
|
||||
"Channel does not support file descriptor passing");
|
||||
return -1;
|
||||
}
|
||||
if (flags & QIO_CHANNEL_WRITE_FLAG_ZERO_COPY) {
|
||||
error_setg_errno(errp, EINVAL,
|
||||
"Zero Copy does not support file descriptor passing");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if ((flags & QIO_CHANNEL_WRITE_FLAG_ZERO_COPY) &&
|
||||
!qio_channel_has_feature(ioc, QIO_CHANNEL_FEATURE_WRITE_ZERO_COPY)) {
|
||||
error_setg_errno(errp, EINVAL,
|
||||
"Channel does not support file descriptor passing");
|
||||
"Requested Zero Copy feature is not available");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return klass->io_writev(ioc, iov, niov, fds, nfds, errp);
|
||||
return klass->io_writev(ioc, iov, niov, fds, nfds, flags, errp);
|
||||
}
|
||||
|
||||
|
||||
|
@ -217,14 +231,14 @@ int qio_channel_writev_all(QIOChannel *ioc,
|
|||
size_t niov,
|
||||
Error **errp)
|
||||
{
|
||||
return qio_channel_writev_full_all(ioc, iov, niov, NULL, 0, errp);
|
||||
return qio_channel_writev_full_all(ioc, iov, niov, NULL, 0, 0, errp);
|
||||
}
|
||||
|
||||
int qio_channel_writev_full_all(QIOChannel *ioc,
|
||||
const struct iovec *iov,
|
||||
size_t niov,
|
||||
int *fds, size_t nfds,
|
||||
Error **errp)
|
||||
int flags, Error **errp)
|
||||
{
|
||||
int ret = -1;
|
||||
struct iovec *local_iov = g_new(struct iovec, niov);
|
||||
|
@ -237,8 +251,10 @@ int qio_channel_writev_full_all(QIOChannel *ioc,
|
|||
|
||||
while (nlocal_iov > 0) {
|
||||
ssize_t len;
|
||||
len = qio_channel_writev_full(ioc, local_iov, nlocal_iov, fds, nfds,
|
||||
errp);
|
||||
|
||||
len = qio_channel_writev_full(ioc, local_iov, nlocal_iov, fds,
|
||||
nfds, flags, errp);
|
||||
|
||||
if (len == QIO_CHANNEL_ERR_BLOCK) {
|
||||
if (qemu_in_coroutine()) {
|
||||
qio_channel_yield(ioc, G_IO_OUT);
|
||||
|
@ -277,7 +293,7 @@ ssize_t qio_channel_writev(QIOChannel *ioc,
|
|||
size_t niov,
|
||||
Error **errp)
|
||||
{
|
||||
return qio_channel_writev_full(ioc, iov, niov, NULL, 0, errp);
|
||||
return qio_channel_writev_full(ioc, iov, niov, NULL, 0, 0, errp);
|
||||
}
|
||||
|
||||
|
||||
|
@ -297,7 +313,7 @@ ssize_t qio_channel_write(QIOChannel *ioc,
|
|||
Error **errp)
|
||||
{
|
||||
struct iovec iov = { .iov_base = (char *)buf, .iov_len = buflen };
|
||||
return qio_channel_writev_full(ioc, &iov, 1, NULL, 0, errp);
|
||||
return qio_channel_writev_full(ioc, &iov, 1, NULL, 0, 0, errp);
|
||||
}
|
||||
|
||||
|
||||
|
@ -473,6 +489,19 @@ off_t qio_channel_io_seek(QIOChannel *ioc,
|
|||
return klass->io_seek(ioc, offset, whence, errp);
|
||||
}
|
||||
|
||||
int qio_channel_flush(QIOChannel *ioc,
|
||||
Error **errp)
|
||||
{
|
||||
QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
|
||||
|
||||
if (!klass->io_flush ||
|
||||
!qio_channel_has_feature(ioc, QIO_CHANNEL_FEATURE_WRITE_ZERO_COPY)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return klass->io_flush(ioc, errp);
|
||||
}
|
||||
|
||||
|
||||
static void qio_channel_restart_read(void *opaque)
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue