On 20.08.25 16:43, Daniel P. Berrangé wrote:
On Wed, Aug 20, 2025 at 09:27:09AM -0400, Peter Xu wrote:
On Wed, Aug 13, 2025 at 07:48:47PM +0300, Vladimir Sementsov-Ogievskiy wrote:
Add a possibility to keep socket non-block status when passing
through qio channel. We need this to support migration of open
fds through migration channel.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsement...@yandex-team.ru>
---
include/io/channel-socket.h | 3 +++
io/channel-socket.c | 16 ++++++++++++----
2 files changed, 15 insertions(+), 4 deletions(-)
diff --git a/include/io/channel-socket.h b/include/io/channel-socket.h
index a88cf8b3a9..0a4327d745 100644
--- a/include/io/channel-socket.h
+++ b/include/io/channel-socket.h
@@ -49,6 +49,7 @@ struct QIOChannelSocket {
socklen_t remoteAddrLen;
ssize_t zero_copy_queued;
ssize_t zero_copy_sent;
+ bool keep_nonblock;
};
@@ -275,4 +276,6 @@ int qio_channel_socket_set_send_buffer(QIOChannelSocket *ioc,
size_t size,
Error **errp);
+void qio_channel_socket_keep_nonblock(QIOChannel *ioc);
+
#endif /* QIO_CHANNEL_SOCKET_H */
diff --git a/io/channel-socket.c b/io/channel-socket.c
index 3b7ca924ff..cd93d7f180 100644
--- a/io/channel-socket.c
+++ b/io/channel-socket.c
@@ -462,9 +462,16 @@ static void qio_channel_socket_finalize(Object *obj)
}
+void qio_channel_socket_keep_nonblock(QIOChannel *ioc)
+{
+ QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc);
+ sioc->keep_nonblock = true;
+}
+
+
#ifndef WIN32
static void qio_channel_socket_copy_fds(struct msghdr *msg,
- int **fds, size_t *nfds)
+ int **fds, size_t *nfds, bool
set_block)
{
struct cmsghdr *cmsg;
@@ -497,8 +504,9 @@ static void qio_channel_socket_copy_fds(struct msghdr *msg,
continue;
}
- /* O_NONBLOCK is preserved across SCM_RIGHTS so reset it */
- qemu_socket_set_block(fd);
+ if (set_block) {
+ qemu_socket_set_block(fd);
+ }
"keep_nonblock" as a feature in iochannel is slightly hard to digest. It
can also be read as "keep the fd to be always nonblocking".
Is this feature required, or can this also be done in a get() or
post_load() on the other side to set nonblock to whatever it should be
(that dest QEMU should be aware of)?
Either we preserve state of the flag when receiving the FD,
or every QEMU backend that we're receiving FDs on behalf of
needs to reset the flag when migration passes over the FD.
The latter might actually be a more robust scheme. If we're
migrating across QEMU versions, there is not a strict
guarantee that the new QEMU version's backend will want the
O_NONBLOCK flag in the same state as the old QEMU version.
The code might have been re-written to work in a different
way than previously.
What I dislike in the way, when we reset to blocking always, and set
non-blocking again where needed:
1. Extra fcntl calls for nothing (I think actually, in most cases, for fds
passed through migration stream(s) we'll want to keep fd as is)
2. When we reset to blocking on target, it's visible on source and may break
things.
In these series it's probably doesn't really matter, as at the time when we get
the descriptor on target, it should not be used anymore on source.
But for example, in CPR-transfer, where descriptors are passed in the
preliminary stage, and source is running and use the descriptors, we shouldn't
change the non-blocking status of fd on target. Probably, CPR-transfer for now
only works with fds which are blpcking, so we don't have a problem.
So, I think, that better default is preserve state of the flag for fds passed
through migration stream. And backends may modify it if needed (I think, in
most cases - they will not need).
--
Best regards,
Vladimir