From: "Dr. David Alan Gilbert" <dgilb...@redhat.com> Add QEMUFile interface to allow a socket to be 'shut down' - i.e. any reads/writes will fail (and any blocking read/write will be woken).
Add qemu_socket wrapper to let OS dependencies be extracted out. Signed-off-by: Dr. David Alan Gilbert <dgilb...@redhat.com> --- include/migration/qemu-file.h | 10 ++++++++++ include/qemu/sockets.h | 1 + qemu-file.c | 27 +++++++++++++++++++++++++-- util/qemu-sockets.c | 28 ++++++++++++++++++++++++++++ 4 files changed, 64 insertions(+), 2 deletions(-) diff --git a/include/migration/qemu-file.h b/include/migration/qemu-file.h index e50d696..ca8fbdc 100644 --- a/include/migration/qemu-file.h +++ b/include/migration/qemu-file.h @@ -84,6 +84,14 @@ typedef size_t (QEMURamSaveFunc)(QEMUFile *f, void *opaque, size_t size, int *bytes_sent); +/* + * Stop any read or write (depending on flags) on the underlying + * transport on the QEMUFile. + * Existing blocking reads/writes must be woken + * Returns 0 on success, -err on error + */ +typedef int (QEMUFileShutdownFunc)(void *opaque, bool rd, bool wr); + typedef struct QEMUFileOps { QEMUFilePutBufferFunc *put_buffer; QEMUFileGetBufferFunc *get_buffer; @@ -94,6 +102,7 @@ typedef struct QEMUFileOps { QEMURamHookFunc *after_ram_iterate; QEMURamHookFunc *hook_ram_load; QEMURamSaveFunc *save_page; + QEMUFileShutdownFunc *shut_down; } QEMUFileOps; struct QEMUSizedBuffer { @@ -178,6 +187,7 @@ void qemu_file_set_rate_limit(QEMUFile *f, int64_t new_rate); int64_t qemu_file_get_rate_limit(QEMUFile *f); int qemu_file_get_error(QEMUFile *f); void qemu_file_set_error(QEMUFile *f, int ret); +void qemu_file_shutdown(QEMUFile *f); void qemu_fflush(QEMUFile *f); static inline void qemu_put_be64s(QEMUFile *f, const uint64_t *pv) diff --git a/include/qemu/sockets.h b/include/qemu/sockets.h index fdbb196..ea8ffc6 100644 --- a/include/qemu/sockets.h +++ b/include/qemu/sockets.h @@ -41,6 +41,7 @@ int socket_set_nodelay(int fd); void qemu_set_block(int fd); void qemu_set_nonblock(int fd); int socket_set_fast_reuse(int fd); +int socket_shutdown(int fd, bool rd, bool wr); int send_all(int fd, const void *buf, int len1); int recv_all(int fd, void *buf, int len1, bool single_read); diff --git a/qemu-file.c b/qemu-file.c index f6d64ce..d7401fa 100644 --- a/qemu-file.c +++ b/qemu-file.c @@ -90,6 +90,14 @@ static int socket_close(void *opaque) return 0; } +/* qemufile_ to disambiguate from the qemu-sockets.c code which it uses */ +static int qemufile_socket_shutdown(void *opaque, bool rd, bool wr) +{ + QEMUFileSocket *s = opaque; + + return socket_shutdown(s->fd, rd, wr); +} + static int stdio_get_fd(void *opaque) { QEMUFileStdio *s = opaque; @@ -337,15 +345,30 @@ QEMUFile *qemu_fdopen(int fd, const char *mode) static const QEMUFileOps socket_read_ops = { .get_fd = socket_get_fd, .get_buffer = socket_get_buffer, - .close = socket_close + .close = socket_close, + .shut_down = qemufile_socket_shutdown + }; static const QEMUFileOps socket_write_ops = { .get_fd = socket_get_fd, .writev_buffer = socket_writev_buffer, - .close = socket_close + .close = socket_close, + .shut_down = qemufile_socket_shutdown + }; +/* + * Stop a file from being read/written - not all backing files can do this + * typically only sockets can. The caller should make sure they only + * call this for things that can. + */ +void qemu_file_shutdown(QEMUFile *f) +{ + assert(f->ops->shut_down); + f->ops->shut_down(f, true, true); +} + bool qemu_file_mode_is_not_valid(const char *mode) { if (mode == NULL || diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c index 5d38395..c68cb52 100644 --- a/util/qemu-sockets.c +++ b/util/qemu-sockets.c @@ -982,3 +982,31 @@ int socket_dgram(SocketAddress *remote, SocketAddress *local, Error **errp) qemu_opts_del(opts); return fd; } + +int socket_shutdown(int fd, bool rd, bool wr) +{ + int how = 0; + +#ifndef WIN32 + if (rd) { + how = SHUT_RD; + } + + if (wr) { + how = rd ? SHUT_RDWR : SHUT_WR; + } + +#else + /* Untested */ + if (rd) { + how = SD_RECEIVE; + } + + if (wr) { + how = rd ? SD_BOTH : SD_SEND; + } + +#endif + + return shutdown(fd, how); +} -- 1.9.3