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