From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:49809) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Yi4Gf-0006Ah-2L for qemu-devel@nongnu.org; Tue, 14 Apr 2015 13:04:58 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Yi4Gb-0002JC-Gx for qemu-devel@nongnu.org; Tue, 14 Apr 2015 13:04:56 -0400 Received: from mx1.redhat.com ([209.132.183.28]:43924) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Yi4Gb-0002Ig-79 for qemu-devel@nongnu.org; Tue, 14 Apr 2015 13:04:53 -0400 From: "Dr. David Alan Gilbert (git)" Date: Tue, 14 Apr 2015 18:03:37 +0100 Message-Id: <1429031053-4454-12-git-send-email-dgilbert@redhat.com> In-Reply-To: <1429031053-4454-1-git-send-email-dgilbert@redhat.com> References: <1429031053-4454-1-git-send-email-dgilbert@redhat.com> Subject: [Qemu-devel] [PATCH v6 11/47] Return path: Open a return path on QEMUFile for sockets List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: aarcange@redhat.com, yamahata@private.email.ne.jp, quintela@redhat.com, amit.shah@redhat.com, pbonzini@redhat.com, david@gibson.dropbear.id.au, yayanghy@cn.fujitsu.com From: "Dr. David Alan Gilbert" Postcopy needs a method to send messages from the destination back to the source, this is the 'return path'. Wire it up for 'socket' QEMUFile's using a dup'd fd. Signed-off-by: Dr. David Alan Gilbert --- include/migration/qemu-file.h | 7 +++++ migration/qemu-file-unix.c | 65 +++++++++++++++++++++++++++++++++++++------ migration/qemu-file.c | 12 ++++++++ 3 files changed, 75 insertions(+), 9 deletions(-) diff --git a/include/migration/qemu-file.h b/include/migration/qemu-file.h index c14555d..1ff8fbc 100644 --- a/include/migration/qemu-file.h +++ b/include/migration/qemu-file.h @@ -85,6 +85,11 @@ typedef size_t (QEMURamSaveFunc)(QEMUFile *f, void *opaque, uint64_t *bytes_sent); /* + * Return a QEMUFile for comms in the opposite direction + */ +typedef QEMUFile *(QEMURetPathFunc)(void *opaque); + +/* * Stop any read or write (depending on flags) on the underlying * transport on the QEMUFile. * Existing blocking reads/writes must be woken @@ -102,6 +107,7 @@ typedef struct QEMUFileOps { QEMURamHookFunc *after_ram_iterate; QEMURamHookFunc *hook_ram_load; QEMURamSaveFunc *save_page; + QEMURetPathFunc *get_return_path; QEMUFileShutdownFunc *shut_down; } QEMUFileOps; @@ -189,6 +195,7 @@ 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); int qemu_file_shutdown(QEMUFile *f); +QEMUFile *qemu_file_get_return_path(QEMUFile *f); void qemu_fflush(QEMUFile *f); void qemu_file_change_blocking(QEMUFile *f, bool block); diff --git a/migration/qemu-file-unix.c b/migration/qemu-file-unix.c index bfbc086..1e7de7b 100644 --- a/migration/qemu-file-unix.c +++ b/migration/qemu-file-unix.c @@ -96,6 +96,52 @@ static int socket_shutdown(void *opaque, bool rd, bool wr) } } +/* + * Give a QEMUFile* off the same socket but data in the opposite + * direction. + */ +static QEMUFile *socket_dup_return_path(void *opaque) +{ + QEMUFileSocket *qfs = opaque; + int revfd; + bool this_is_read; + QEMUFile *result; + + if (qemu_file_get_error(qfs->file)) { + /* If the forward file is in error, don't try and open a return */ + return NULL; + } + + /* I don't think there's a better way to tell which direction 'this' is */ + this_is_read = qfs->file->ops->get_buffer != NULL; + + revfd = dup(qfs->fd); + if (revfd == -1) { + error_report("Error duplicating fd for return path: %s", + strerror(errno)); + return NULL; + } + + result = qemu_fopen_socket(revfd, this_is_read ? "wb" : "rb"); + + if (!result) { + close(revfd); + } + + if (this_is_read) { + /* The qemu_fopen_socket "wb" will mark the socket blocking, + * which would be OK for the return path, but the semantics + * of non-blocking is that it follows the underlying connection + * not the fd number, and thus setting the return path non-blocking + * ends up setting the forward path blocking, which we don't want + */ + qemu_set_nonblock(revfd); + } + + + return result; +} + static ssize_t unix_writev_buffer(void *opaque, struct iovec *iov, int iovcnt, int64_t pos) { @@ -204,18 +250,19 @@ 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, - .shut_down = socket_shutdown - + .get_fd = socket_get_fd, + .get_buffer = socket_get_buffer, + .close = socket_close, + .shut_down = socket_shutdown, + .get_return_path = socket_dup_return_path }; static const QEMUFileOps socket_write_ops = { - .get_fd = socket_get_fd, - .writev_buffer = socket_writev_buffer, - .close = socket_close, - .shut_down = socket_shutdown + .get_fd = socket_get_fd, + .writev_buffer = socket_writev_buffer, + .close = socket_close, + .shut_down = socket_shutdown, + .get_return_path = socket_dup_return_path }; QEMUFile *qemu_fopen_socket(int fd, const char *mode) diff --git a/migration/qemu-file.c b/migration/qemu-file.c index d84830f..8b2ae8d 100644 --- a/migration/qemu-file.c +++ b/migration/qemu-file.c @@ -42,6 +42,18 @@ int qemu_file_shutdown(QEMUFile *f) return f->ops->shut_down(f->opaque, true, true); } +/* + * Result: QEMUFile* for a 'return path' for comms in the opposite direction + * NULL if not available + */ +QEMUFile *qemu_file_get_return_path(QEMUFile *f) +{ + if (!f->ops->get_return_path) { + return NULL; + } + return f->ops->get_return_path(f->opaque); +} + bool qemu_file_mode_is_not_valid(const char *mode) { if (mode == NULL || -- 2.1.0