|
@@ -72,18 +72,32 @@ ssize_t qio_channel_writev_full(QIOChannel *ioc,
|
|
size_t niov,
|
|
size_t niov,
|
|
int *fds,
|
|
int *fds,
|
|
size_t nfds,
|
|
size_t nfds,
|
|
|
|
+ int flags,
|
|
Error **errp)
|
|
Error **errp)
|
|
{
|
|
{
|
|
QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
|
|
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,
|
|
error_setg_errno(errp, EINVAL,
|
|
- "Channel does not support file descriptor passing");
|
|
|
|
|
|
+ "Requested Zero Copy feature is not available");
|
|
return -1;
|
|
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,
|
|
size_t niov,
|
|
Error **errp)
|
|
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,
|
|
int qio_channel_writev_full_all(QIOChannel *ioc,
|
|
const struct iovec *iov,
|
|
const struct iovec *iov,
|
|
size_t niov,
|
|
size_t niov,
|
|
int *fds, size_t nfds,
|
|
int *fds, size_t nfds,
|
|
- Error **errp)
|
|
|
|
|
|
+ int flags, 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);
|
|
@@ -237,8 +251,10 @@ int qio_channel_writev_full_all(QIOChannel *ioc,
|
|
|
|
|
|
while (nlocal_iov > 0) {
|
|
while (nlocal_iov > 0) {
|
|
ssize_t len;
|
|
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 (len == QIO_CHANNEL_ERR_BLOCK) {
|
|
if (qemu_in_coroutine()) {
|
|
if (qemu_in_coroutine()) {
|
|
qio_channel_yield(ioc, G_IO_OUT);
|
|
qio_channel_yield(ioc, G_IO_OUT);
|
|
@@ -277,7 +293,7 @@ ssize_t qio_channel_writev(QIOChannel *ioc,
|
|
size_t niov,
|
|
size_t niov,
|
|
Error **errp)
|
|
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)
|
|
Error **errp)
|
|
{
|
|
{
|
|
struct iovec iov = { .iov_base = (char *)buf, .iov_len = buflen };
|
|
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);
|
|
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)
|
|
static void qio_channel_restart_read(void *opaque)
|
|
{
|
|
{
|