@samitouri / QOSamiQemu / commits / 2a092db9cb

io: invert the return semantics of qio_channel_flush

With the kernel's zerocopy notification mechanism, the caller can determine whether * All syscalls successfully used zero copy * At least one syscall failed to use zero copy But, as of now QEMU's IO channel flush function semantics are like * 1 => all syscalls failed to use zero copy * 0 => at least one syscall successfully used zero copy This is not aligned with what the kernel reports, and ends up reporting false negatives for cases like when there's just a single successful zerocopy amongst a collection of deferred zero-copies during a flush. Fix this by inverting the return semantics of the IO flush function. Suggested-by: Peter Xu <peterx@redhat.com> Suggested-by: Daniel P. Berrangé <berrange@redhat.com> Signed-off-by: Tejus GK <tejus.gk@nutanix.com> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>

Tejus GK committed Mar 20, 2026 at 08:39 UTC 2a092db9cb89a58027c143ef25d2f2350176c225
3 files changed +11 -15
include/io/channel-socket.h
+1 -5
@@ -50,11 +50,7 @@ struct QIOChannelSocket {
50 ssize_t zero_copy_queued;
51 ssize_t zero_copy_sent;
52 bool blocking;
53 - /**
54 - * This flag indicates whether any new data was successfully sent with
55 - * zerocopy since the last qio_channel_socket_flush() call.
56 - */
57 - bool new_zero_copy_sent_success;
53 + bool zero_copy_fallback;
54 };
55
56
include/io/channel.h
+2 -2
@@ -1147,8 +1147,8 @@ int coroutine_mixed_fn qio_channel_writev_full_all(QIOChannel *ioc,
1147 * If not implemented, acts as a no-op, and returns 0.
1148 *
1149 * Returns -1 if any error is found,
1150 - * 1 if every send failed to use zero copy.
1151 - * 0 otherwise.
1150 + * 1 if at least one send failed to use zero copy.
1151 + * 0 if every send successfully used zero copy.
1152 */
1153
1154 int qio_channel_flush(QIOChannel *ioc,
io/channel-socket.c
+8 -8
@@ -72,7 +72,7 @@ qio_channel_socket_new(void)
72 sioc->zero_copy_queued = 0;
73 sioc->zero_copy_sent = 0;
74 sioc->blocking = false;
75 - sioc->new_zero_copy_sent_success = false;
75 + sioc->zero_copy_fallback = false;
76
77 ioc = QIO_CHANNEL(sioc);
78 qio_channel_set_feature(ioc, QIO_CHANNEL_FEATURE_SHUTDOWN);
@@ -880,9 +880,9 @@ static int qio_channel_socket_flush_internal(QIOChannel *ioc,
880 /* No errors, count successfully finished sendmsg()*/
881 sioc->zero_copy_sent += serr->ee_data - serr->ee_info + 1;
882
883 - /* If any sendmsg() succeeded using zero copy, mark zerocopy success */
884 - if (serr->ee_code != SO_EE_CODE_ZEROCOPY_COPIED) {
885 - sioc->new_zero_copy_sent_success = true;
883 + if (serr->ee_code == SO_EE_CODE_ZEROCOPY_COPIED) {
884 + /* If any sendmsg() fell back to a copy, mark fallback as true */
885 + sioc->zero_copy_fallback = true;
886 }
887 }
888
@@ -900,12 +900,12 @@ static int qio_channel_socket_flush(QIOChannel *ioc,
900 return ret;
901 }
902
903 - if (sioc->new_zero_copy_sent_success) {
904 - sioc->new_zero_copy_sent_success = false;
905 - return 0;
903 + if (sioc->zero_copy_fallback) {
904 + sioc->zero_copy_fallback = false;
905 + return 1;
906 }
907
908 - return 1;
908 + return 0;
909 }
910
911 #endif /* QEMU_MSG_ZEROCOPY */