2
0

migration-tcp.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. /*
  2. * QEMU live migration
  3. *
  4. * Copyright IBM, Corp. 2008
  5. *
  6. * Authors:
  7. * Anthony Liguori <aliguori@us.ibm.com>
  8. *
  9. * This work is licensed under the terms of the GNU GPL, version 2. See
  10. * the COPYING file in the top-level directory.
  11. *
  12. * Contributions after 2012-01-13 are licensed under the terms of the
  13. * GNU GPL, version 2 or (at your option) any later version.
  14. */
  15. #include "qemu-common.h"
  16. #include "qemu_socket.h"
  17. #include "migration.h"
  18. #include "qemu-char.h"
  19. #include "buffered_file.h"
  20. #include "block.h"
  21. //#define DEBUG_MIGRATION_TCP
  22. #ifdef DEBUG_MIGRATION_TCP
  23. #define DPRINTF(fmt, ...) \
  24. do { printf("migration-tcp: " fmt, ## __VA_ARGS__); } while (0)
  25. #else
  26. #define DPRINTF(fmt, ...) \
  27. do { } while (0)
  28. #endif
  29. static int socket_errno(MigrationState *s)
  30. {
  31. return socket_error();
  32. }
  33. static int socket_write(MigrationState *s, const void * buf, size_t size)
  34. {
  35. return send(s->fd, buf, size, 0);
  36. }
  37. static int tcp_close(MigrationState *s)
  38. {
  39. int r = 0;
  40. DPRINTF("tcp_close\n");
  41. if (s->fd != -1) {
  42. if (close(s->fd) < 0) {
  43. r = -errno;
  44. }
  45. s->fd = -1;
  46. }
  47. return r;
  48. }
  49. static void tcp_wait_for_connect(void *opaque)
  50. {
  51. MigrationState *s = opaque;
  52. int val, ret;
  53. socklen_t valsize = sizeof(val);
  54. DPRINTF("connect completed\n");
  55. do {
  56. ret = getsockopt(s->fd, SOL_SOCKET, SO_ERROR, (void *) &val, &valsize);
  57. } while (ret == -1 && (socket_error()) == EINTR);
  58. if (ret < 0) {
  59. migrate_fd_error(s);
  60. return;
  61. }
  62. qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
  63. if (val == 0)
  64. migrate_fd_connect(s);
  65. else {
  66. DPRINTF("error connecting %d\n", val);
  67. migrate_fd_error(s);
  68. }
  69. }
  70. int tcp_start_outgoing_migration(MigrationState *s, const char *host_port,
  71. Error **errp)
  72. {
  73. s->get_error = socket_errno;
  74. s->write = socket_write;
  75. s->close = tcp_close;
  76. s->fd = inet_connect(host_port, false, errp);
  77. if (!error_is_set(errp)) {
  78. migrate_fd_connect(s);
  79. } else if (error_is_type(*errp, QERR_SOCKET_CONNECT_IN_PROGRESS)) {
  80. DPRINTF("connect in progress\n");
  81. qemu_set_fd_handler2(s->fd, NULL, NULL, tcp_wait_for_connect, s);
  82. } else if (error_is_type(*errp, QERR_SOCKET_CREATE_FAILED)) {
  83. DPRINTF("connect failed\n");
  84. return -1;
  85. } else if (error_is_type(*errp, QERR_SOCKET_CONNECT_FAILED)) {
  86. DPRINTF("connect failed\n");
  87. migrate_fd_error(s);
  88. return -1;
  89. } else {
  90. DPRINTF("unknown error\n");
  91. return -1;
  92. }
  93. return 0;
  94. }
  95. static void tcp_accept_incoming_migration(void *opaque)
  96. {
  97. struct sockaddr_in addr;
  98. socklen_t addrlen = sizeof(addr);
  99. int s = (intptr_t)opaque;
  100. QEMUFile *f;
  101. int c;
  102. do {
  103. c = qemu_accept(s, (struct sockaddr *)&addr, &addrlen);
  104. } while (c == -1 && socket_error() == EINTR);
  105. DPRINTF("accepted migration\n");
  106. if (c == -1) {
  107. fprintf(stderr, "could not accept migration connection\n");
  108. goto out2;
  109. }
  110. f = qemu_fopen_socket(c);
  111. if (f == NULL) {
  112. fprintf(stderr, "could not qemu_fopen socket\n");
  113. goto out;
  114. }
  115. process_incoming_migration(f);
  116. qemu_fclose(f);
  117. out:
  118. close(c);
  119. out2:
  120. qemu_set_fd_handler2(s, NULL, NULL, NULL, NULL);
  121. close(s);
  122. }
  123. int tcp_start_incoming_migration(const char *host_port, Error **errp)
  124. {
  125. int s;
  126. s = inet_listen(host_port, NULL, 256, SOCK_STREAM, 0, errp);
  127. if (s < 0) {
  128. return -1;
  129. }
  130. qemu_set_fd_handler2(s, NULL, tcp_accept_incoming_migration, NULL,
  131. (void *)(intptr_t)s);
  132. return 0;
  133. }