2
0

cpr.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. /*
  2. * Copyright (c) 2021-2024 Oracle and/or its affiliates.
  3. *
  4. * This work is licensed under the terms of the GNU GPL, version 2 or later.
  5. * See the COPYING file in the top-level directory.
  6. */
  7. #include "qemu/osdep.h"
  8. #include "qapi/error.h"
  9. #include "migration/cpr.h"
  10. #include "migration/misc.h"
  11. #include "migration/options.h"
  12. #include "migration/qemu-file.h"
  13. #include "migration/savevm.h"
  14. #include "migration/vmstate.h"
  15. #include "system/runstate.h"
  16. #include "trace.h"
  17. /*************************************************************************/
  18. /* cpr state container for all information to be saved. */
  19. typedef QLIST_HEAD(CprFdList, CprFd) CprFdList;
  20. typedef struct CprState {
  21. CprFdList fds;
  22. } CprState;
  23. static CprState cpr_state;
  24. /****************************************************************************/
  25. typedef struct CprFd {
  26. char *name;
  27. unsigned int namelen;
  28. int id;
  29. int fd;
  30. QLIST_ENTRY(CprFd) next;
  31. } CprFd;
  32. static const VMStateDescription vmstate_cpr_fd = {
  33. .name = "cpr fd",
  34. .version_id = 1,
  35. .minimum_version_id = 1,
  36. .fields = (VMStateField[]) {
  37. VMSTATE_UINT32(namelen, CprFd),
  38. VMSTATE_VBUFFER_ALLOC_UINT32(name, CprFd, 0, NULL, namelen),
  39. VMSTATE_INT32(id, CprFd),
  40. VMSTATE_FD(fd, CprFd),
  41. VMSTATE_END_OF_LIST()
  42. }
  43. };
  44. void cpr_save_fd(const char *name, int id, int fd)
  45. {
  46. CprFd *elem = g_new0(CprFd, 1);
  47. trace_cpr_save_fd(name, id, fd);
  48. elem->name = g_strdup(name);
  49. elem->namelen = strlen(name) + 1;
  50. elem->id = id;
  51. elem->fd = fd;
  52. QLIST_INSERT_HEAD(&cpr_state.fds, elem, next);
  53. }
  54. static CprFd *find_fd(CprFdList *head, const char *name, int id)
  55. {
  56. CprFd *elem;
  57. QLIST_FOREACH(elem, head, next) {
  58. if (!strcmp(elem->name, name) && elem->id == id) {
  59. return elem;
  60. }
  61. }
  62. return NULL;
  63. }
  64. void cpr_delete_fd(const char *name, int id)
  65. {
  66. CprFd *elem = find_fd(&cpr_state.fds, name, id);
  67. if (elem) {
  68. QLIST_REMOVE(elem, next);
  69. g_free(elem->name);
  70. g_free(elem);
  71. }
  72. trace_cpr_delete_fd(name, id);
  73. }
  74. int cpr_find_fd(const char *name, int id)
  75. {
  76. CprFd *elem = find_fd(&cpr_state.fds, name, id);
  77. int fd = elem ? elem->fd : -1;
  78. trace_cpr_find_fd(name, id, fd);
  79. return fd;
  80. }
  81. /*************************************************************************/
  82. #define CPR_STATE "CprState"
  83. static const VMStateDescription vmstate_cpr_state = {
  84. .name = CPR_STATE,
  85. .version_id = 1,
  86. .minimum_version_id = 1,
  87. .fields = (VMStateField[]) {
  88. VMSTATE_QLIST_V(fds, CprState, 1, vmstate_cpr_fd, CprFd, next),
  89. VMSTATE_END_OF_LIST()
  90. }
  91. };
  92. /*************************************************************************/
  93. static QEMUFile *cpr_state_file;
  94. QIOChannel *cpr_state_ioc(void)
  95. {
  96. return qemu_file_get_ioc(cpr_state_file);
  97. }
  98. static MigMode incoming_mode = MIG_MODE_NONE;
  99. MigMode cpr_get_incoming_mode(void)
  100. {
  101. return incoming_mode;
  102. }
  103. void cpr_set_incoming_mode(MigMode mode)
  104. {
  105. incoming_mode = mode;
  106. }
  107. bool cpr_is_incoming(void)
  108. {
  109. return incoming_mode != MIG_MODE_NONE;
  110. }
  111. int cpr_state_save(MigrationChannel *channel, Error **errp)
  112. {
  113. int ret;
  114. QEMUFile *f;
  115. MigMode mode = migrate_mode();
  116. trace_cpr_state_save(MigMode_str(mode));
  117. if (mode == MIG_MODE_CPR_TRANSFER) {
  118. g_assert(channel);
  119. f = cpr_transfer_output(channel, errp);
  120. } else {
  121. return 0;
  122. }
  123. if (!f) {
  124. return -1;
  125. }
  126. qemu_put_be32(f, QEMU_CPR_FILE_MAGIC);
  127. qemu_put_be32(f, QEMU_CPR_FILE_VERSION);
  128. ret = vmstate_save_state(f, &vmstate_cpr_state, &cpr_state, 0);
  129. if (ret) {
  130. error_setg(errp, "vmstate_save_state error %d", ret);
  131. qemu_fclose(f);
  132. return ret;
  133. }
  134. /*
  135. * Close the socket only partially so we can later detect when the other
  136. * end closes by getting a HUP event.
  137. */
  138. qemu_fflush(f);
  139. qio_channel_shutdown(qemu_file_get_ioc(f), QIO_CHANNEL_SHUTDOWN_WRITE,
  140. NULL);
  141. cpr_state_file = f;
  142. return 0;
  143. }
  144. int cpr_state_load(MigrationChannel *channel, Error **errp)
  145. {
  146. int ret;
  147. uint32_t v;
  148. QEMUFile *f;
  149. MigMode mode = 0;
  150. if (channel) {
  151. mode = MIG_MODE_CPR_TRANSFER;
  152. cpr_set_incoming_mode(mode);
  153. f = cpr_transfer_input(channel, errp);
  154. } else {
  155. return 0;
  156. }
  157. if (!f) {
  158. return -1;
  159. }
  160. trace_cpr_state_load(MigMode_str(mode));
  161. v = qemu_get_be32(f);
  162. if (v != QEMU_CPR_FILE_MAGIC) {
  163. error_setg(errp, "Not a migration stream (bad magic %x)", v);
  164. qemu_fclose(f);
  165. return -EINVAL;
  166. }
  167. v = qemu_get_be32(f);
  168. if (v != QEMU_CPR_FILE_VERSION) {
  169. error_setg(errp, "Unsupported migration stream version %d", v);
  170. qemu_fclose(f);
  171. return -ENOTSUP;
  172. }
  173. ret = vmstate_load_state(f, &vmstate_cpr_state, &cpr_state, 1);
  174. if (ret) {
  175. error_setg(errp, "vmstate_load_state error %d", ret);
  176. qemu_fclose(f);
  177. return ret;
  178. }
  179. /*
  180. * Let the caller decide when to close the socket (and generate a HUP event
  181. * for the sending side).
  182. */
  183. cpr_state_file = f;
  184. return ret;
  185. }
  186. void cpr_state_close(void)
  187. {
  188. if (cpr_state_file) {
  189. qemu_fclose(cpr_state_file);
  190. cpr_state_file = NULL;
  191. }
  192. }