9ae3a8
From da3039bc7ec4fda6719be3bdd10f4b0fdaceb17a Mon Sep 17 00:00:00 2001
9ae3a8
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
9ae3a8
Date: Fri, 16 Jan 2015 17:35:35 +0100
9ae3a8
Subject: [PATCH 03/16] socket shutdown
9ae3a8
9ae3a8
Message-id: <1421429737-23581-2-git-send-email-dgilbert@redhat.com>
9ae3a8
Patchwork-id: 63332
9ae3a8
O-Subject: [RHEL-7.2 qemu-kvm PATCH 1/3] socket shutdown
9ae3a8
Bugzilla: 1086168
9ae3a8
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
9ae3a8
RH-Acked-by: Amit Shah <amit.shah@redhat.com>
9ae3a8
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
9ae3a8
9ae3a8
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
9ae3a8
9ae3a8
Add QEMUFile interface to allow a socket to be 'shut down' - i.e. any
9ae3a8
reads/writes will fail (and any blocking read/write will be woken).
9ae3a8
9ae3a8
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
9ae3a8
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
9ae3a8
Reviewed-by: Amit Shah <amit.shah@redhat.com>
9ae3a8
Signed-off-by: Amit Shah <amit.shah@redhat.com>
9ae3a8
(cherry picked from commit e1a8c9b67fc97d293211773edcae9e8e2f3367ab)
9ae3a8
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
9ae3a8
9ae3a8
Conflicts:
9ae3a8
	include/migration/qemu-file.h
9ae3a8
	migration/qemu-file-unix.c
9ae3a8
	migration/qemu-file.c
9ae3a8
9ae3a8
   Because we split qemu-file.c out of savevm and moved it
9ae3a8
---
9ae3a8
 include/migration/qemu-file.h | 10 ++++++++++
9ae3a8
 include/qemu/sockets.h        |  7 +++++++
9ae3a8
 savevm.c                      | 33 +++++++++++++++++++++++++++++----
9ae3a8
 3 files changed, 46 insertions(+), 4 deletions(-)
9ae3a8
9ae3a8
diff --git a/include/migration/qemu-file.h b/include/migration/qemu-file.h
9ae3a8
index 0f757fb..032de47 100644
9ae3a8
--- a/include/migration/qemu-file.h
9ae3a8
+++ b/include/migration/qemu-file.h
9ae3a8
@@ -82,6 +82,14 @@ typedef size_t (QEMURamSaveFunc)(QEMUFile *f, void *opaque,
9ae3a8
                                size_t size,
9ae3a8
                                int *bytes_sent);
9ae3a8
 
9ae3a8
+/*
9ae3a8
+ * Stop any read or write (depending on flags) on the underlying
9ae3a8
+ * transport on the QEMUFile.
9ae3a8
+ * Existing blocking reads/writes must be woken
9ae3a8
+ * Returns 0 on success, -err on error
9ae3a8
+ */
9ae3a8
+typedef int (QEMUFileShutdownFunc)(void *opaque, bool rd, bool wr);
9ae3a8
+
9ae3a8
 typedef struct QEMUFileOps {
9ae3a8
     QEMUFilePutBufferFunc *put_buffer;
9ae3a8
     QEMUFileGetBufferFunc *get_buffer;
9ae3a8
@@ -92,6 +100,7 @@ typedef struct QEMUFileOps {
9ae3a8
     QEMURamHookFunc *after_ram_iterate;
9ae3a8
     QEMURamHookFunc *hook_ram_load;
9ae3a8
     QEMURamSaveFunc *save_page;
9ae3a8
+    QEMUFileShutdownFunc *shut_down;
9ae3a8
 } QEMUFileOps;
9ae3a8
 
9ae3a8
 QEMUFile *qemu_fopen_ops(void *opaque, const QEMUFileOps *ops);
9ae3a8
@@ -141,6 +150,7 @@ void qemu_file_reset_rate_limit(QEMUFile *f);
9ae3a8
 void qemu_file_set_rate_limit(QEMUFile *f, int64_t new_rate);
9ae3a8
 int64_t qemu_file_get_rate_limit(QEMUFile *f);
9ae3a8
 int qemu_file_get_error(QEMUFile *f);
9ae3a8
+int qemu_file_shutdown(QEMUFile *f);
9ae3a8
 void qemu_fflush(QEMUFile *f);
9ae3a8
 
9ae3a8
 static inline void qemu_put_be64s(QEMUFile *f, const uint64_t *pv)
9ae3a8
diff --git a/include/qemu/sockets.h b/include/qemu/sockets.h
9ae3a8
index c5174d7..729ff52 100644
9ae3a8
--- a/include/qemu/sockets.h
9ae3a8
+++ b/include/qemu/sockets.h
9ae3a8
@@ -42,6 +42,13 @@ void qemu_set_nonblock(int fd);
9ae3a8
 int send_all(int fd, const void *buf, int len1);
9ae3a8
 int recv_all(int fd, void *buf, int len1, bool single_read);
9ae3a8
 
9ae3a8
+#ifdef WIN32
9ae3a8
+/* Windows has different names for the same constants with the same values */
9ae3a8
+#define SHUT_RD   0
9ae3a8
+#define SHUT_WR   1
9ae3a8
+#define SHUT_RDWR 2
9ae3a8
+#endif
9ae3a8
+
9ae3a8
 /* callback function for nonblocking connect
9ae3a8
  * valid fd on success, negative error code on failure
9ae3a8
  */
9ae3a8
diff --git a/savevm.c b/savevm.c
9ae3a8
index 963dc7d..731d5c0 100644
9ae3a8
--- a/savevm.c
9ae3a8
+++ b/savevm.c
9ae3a8
@@ -204,6 +204,17 @@ static int socket_close(void *opaque)
9ae3a8
     return 0;
9ae3a8
 }
9ae3a8
 
9ae3a8
+static int socket_shutdown(void *opaque, bool rd, bool wr)
9ae3a8
+{
9ae3a8
+    QEMUFileSocket *s = opaque;
9ae3a8
+
9ae3a8
+    if (shutdown(s->fd, rd ? (wr ? SHUT_RDWR : SHUT_RD) : SHUT_WR)) {
9ae3a8
+        return -errno;
9ae3a8
+    } else {
9ae3a8
+        return 0;
9ae3a8
+    }
9ae3a8
+}
9ae3a8
+
9ae3a8
 static int stdio_get_fd(void *opaque)
9ae3a8
 {
9ae3a8
     QEMUFileStdio *s = opaque;
9ae3a8
@@ -448,17 +459,31 @@ QEMUFile *qemu_fdopen(int fd, const char *mode)
9ae3a8
 }
9ae3a8
 
9ae3a8
 static const QEMUFileOps socket_read_ops = {
9ae3a8
-    .get_fd =     socket_get_fd,
9ae3a8
+    .get_fd     = socket_get_fd,
9ae3a8
     .get_buffer = socket_get_buffer,
9ae3a8
-    .close =      socket_close
9ae3a8
+    .close      = socket_close,
9ae3a8
+    .shut_down  = socket_shutdown
9ae3a8
 };
9ae3a8
 
9ae3a8
 static const QEMUFileOps socket_write_ops = {
9ae3a8
-    .get_fd =     socket_get_fd,
9ae3a8
+    .get_fd        = socket_get_fd,
9ae3a8
     .writev_buffer = socket_writev_buffer,
9ae3a8
-    .close =      socket_close
9ae3a8
+    .close         = socket_close,
9ae3a8
+    .shut_down     = socket_shutdown
9ae3a8
 };
9ae3a8
 
9ae3a8
+/*
9ae3a8
+ * Stop a file from being read/written - not all backing files can do this
9ae3a8
+ * typically only sockets can.
9ae3a8
+ */
9ae3a8
+int qemu_file_shutdown(QEMUFile *f)
9ae3a8
+{
9ae3a8
+    if (!f->ops->shut_down) {
9ae3a8
+        return -ENOSYS;
9ae3a8
+    }
9ae3a8
+    return f->ops->shut_down(f->opaque, true, true);
9ae3a8
+}
9ae3a8
+
9ae3a8
 bool qemu_file_mode_is_not_valid(const char *mode)
9ae3a8
 {
9ae3a8
     if (mode == NULL ||
9ae3a8
-- 
9ae3a8
1.8.3.1
9ae3a8