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 8 #include "qemu/osdep.h" 9 #include "qapi/error.h" 10 #include "hw/vfio/vfio-device.h" 11 #include "migration/cpr.h" 12 #include "migration/misc.h" 13 #include "migration/options.h" 14 #include "migration/qemu-file.h" 15 #include "migration/savevm.h" 16 #include "migration/vmstate.h" 17 #include "monitor/monitor.h" 18 #include "system/runstate.h" 19 #include "trace.h" 20 21 /*************************************************************************/ 22 /* cpr state container for all information to be saved. */ 23 24 CprState cpr_state; 25 26 /****************************************************************************/ 27 28 typedef struct CprFd { 29 char *name; 30 unsigned int namelen; 31 int id; 32 int fd; 33 QLIST_ENTRY(CprFd) next; 34 } CprFd; 35 36 static const VMStateDescription vmstate_cpr_fd = { 37 .name = "cpr fd", 38 .version_id = 1, 39 .minimum_version_id = 1, 40 .fields = (VMStateField[]) { 41 VMSTATE_UINT32(namelen, CprFd), 42 VMSTATE_VBUFFER_ALLOC_UINT32(name, CprFd, 0, NULL, namelen), 43 VMSTATE_INT32(id, CprFd), 44 VMSTATE_FD(fd, CprFd), 45 VMSTATE_END_OF_LIST() 46 } 47 }; 48 49 void cpr_save_fd(const char *name, int id, int fd) 50 { 51 CprFd *elem = g_new0(CprFd, 1); 52 53 trace_cpr_save_fd(name, id, fd); 54 elem->name = g_strdup(name); 55 elem->namelen = strlen(name) + 1; 56 elem->id = id; 57 elem->fd = fd; 58 QLIST_INSERT_HEAD(&cpr_state.fds, elem, next); 59 } 60 61 static CprFd *find_fd(CprFdList *head, const char *name, int id) 62 { 63 CprFd *elem; 64 65 QLIST_FOREACH(elem, head, next) { 66 if (!strcmp(elem->name, name) && elem->id == id) { 67 return elem; 68 } 69 } 70 return NULL; 71 } 72 73 void cpr_delete_fd(const char *name, int id) 74 { 75 CprFd *elem = find_fd(&cpr_state.fds, name, id); 76 77 if (elem) { 78 QLIST_REMOVE(elem, next); 79 g_free(elem->name); 80 g_free(elem); 81 } 82 83 trace_cpr_delete_fd(name, id); 84 } 85 86 int cpr_find_fd(const char *name, int id) 87 { 88 CprFd *elem = find_fd(&cpr_state.fds, name, id); 89 int fd = elem ? elem->fd : -1; 90 91 trace_cpr_find_fd(name, id, fd); 92 return fd; 93 } 94 95 void cpr_resave_fd(const char *name, int id, int fd) 96 { 97 CprFd *elem = find_fd(&cpr_state.fds, name, id); 98 int old_fd = elem ? elem->fd : -1; 99 100 if (old_fd < 0) { 101 cpr_save_fd(name, id, fd); 102 } else if (old_fd != fd) { 103 error_setg(&error_fatal, 104 "internal error: cpr fd '%s' id %d value %d " 105 "already saved with a different value %d", 106 name, id, fd, old_fd); 107 } 108 } 109 110 int cpr_open_fd(const char *path, int flags, const char *name, int id, 111 Error **errp) 112 { 113 int fd = cpr_find_fd(name, id); 114 115 if (fd < 0) { 116 fd = qemu_open(path, flags, errp); 117 if (fd >= 0) { 118 cpr_save_fd(name, id, fd); 119 } 120 } 121 return fd; 122 } 123 124 /*************************************************************************/ 125 static const VMStateDescription vmstate_cpr_state = { 126 .name = CPR_STATE, 127 .version_id = 1, 128 .minimum_version_id = 1, 129 .fields = (VMStateField[]) { 130 VMSTATE_QLIST_V(fds, CprState, 1, vmstate_cpr_fd, CprFd, next), 131 VMSTATE_END_OF_LIST() 132 }, 133 .subsections = (const VMStateDescription * const []) { 134 &vmstate_cpr_vfio_devices, 135 NULL 136 } 137 }; 138 /*************************************************************************/ 139 140 static QEMUFile *cpr_state_file; 141 142 QIOChannel *cpr_state_ioc(void) 143 { 144 return qemu_file_get_ioc(cpr_state_file); 145 } 146 147 static MigMode incoming_mode = MIG_MODE_NONE; 148 149 MigMode cpr_get_incoming_mode(void) 150 { 151 return incoming_mode; 152 } 153 154 void cpr_set_incoming_mode(MigMode mode) 155 { 156 incoming_mode = mode; 157 } 158 159 bool cpr_is_incoming(void) 160 { 161 return incoming_mode != MIG_MODE_NONE; 162 } 163 164 int cpr_state_save(MigrationChannel *channel, Error **errp) 165 { 166 int ret; 167 QEMUFile *f; 168 MigMode mode = migrate_mode(); 169 170 trace_cpr_state_save(MigMode_str(mode)); 171 172 if (mode == MIG_MODE_CPR_TRANSFER) { 173 g_assert(channel); 174 f = cpr_transfer_output(channel, errp); 175 } else { 176 return 0; 177 } 178 if (!f) { 179 return -1; 180 } 181 182 qemu_put_be32(f, QEMU_CPR_FILE_MAGIC); 183 qemu_put_be32(f, QEMU_CPR_FILE_VERSION); 184 185 ret = vmstate_save_state(f, &vmstate_cpr_state, &cpr_state, 0); 186 if (ret) { 187 error_setg(errp, "vmstate_save_state error %d", ret); 188 qemu_fclose(f); 189 return ret; 190 } 191 192 /* 193 * Close the socket only partially so we can later detect when the other 194 * end closes by getting a HUP event. 195 */ 196 qemu_fflush(f); 197 qio_channel_shutdown(qemu_file_get_ioc(f), QIO_CHANNEL_SHUTDOWN_WRITE, 198 NULL); 199 cpr_state_file = f; 200 return 0; 201 } 202 203 int cpr_state_load(MigrationChannel *channel, Error **errp) 204 { 205 int ret; 206 uint32_t v; 207 QEMUFile *f; 208 MigMode mode = 0; 209 210 if (channel) { 211 mode = MIG_MODE_CPR_TRANSFER; 212 cpr_set_incoming_mode(mode); 213 f = cpr_transfer_input(channel, errp); 214 } else { 215 return 0; 216 } 217 if (!f) { 218 return -1; 219 } 220 221 trace_cpr_state_load(MigMode_str(mode)); 222 223 v = qemu_get_be32(f); 224 if (v != QEMU_CPR_FILE_MAGIC) { 225 error_setg(errp, "Not a migration stream (bad magic %x)", v); 226 qemu_fclose(f); 227 return -EINVAL; 228 } 229 v = qemu_get_be32(f); 230 if (v != QEMU_CPR_FILE_VERSION) { 231 error_setg(errp, "Unsupported migration stream version %d", v); 232 qemu_fclose(f); 233 return -ENOTSUP; 234 } 235 236 ret = vmstate_load_state(f, &vmstate_cpr_state, &cpr_state, 1); 237 if (ret) { 238 error_setg(errp, "vmstate_load_state error %d", ret); 239 qemu_fclose(f); 240 return ret; 241 } 242 243 /* 244 * Let the caller decide when to close the socket (and generate a HUP event 245 * for the sending side). 246 */ 247 cpr_state_file = f; 248 249 return ret; 250 } 251 252 void cpr_state_close(void) 253 { 254 if (cpr_state_file) { 255 qemu_fclose(cpr_state_file); 256 cpr_state_file = NULL; 257 } 258 } 259 260 bool cpr_incoming_needed(void *opaque) 261 { 262 MigMode mode = migrate_mode(); 263 return mode == MIG_MODE_CPR_TRANSFER; 264 } 265 266 /* 267 * cpr_get_fd_param: find a descriptor and return its value. 268 * 269 * @name: CPR name for the descriptor 270 * @fdname: An integer-valued string, or a name passed to a getfd command 271 * @index: CPR index of the descriptor 272 * @errp: returned error message 273 * 274 * If CPR is not being performed, then use @fdname to find the fd. 275 * If CPR is being performed, then ignore @fdname, and look for @name 276 * and @index in CPR state. 277 * 278 * On success returns the fd value, else returns -1. 279 */ 280 int cpr_get_fd_param(const char *name, const char *fdname, int index, 281 Error **errp) 282 { 283 ERRP_GUARD(); 284 int fd; 285 286 if (cpr_is_incoming()) { 287 fd = cpr_find_fd(name, index); 288 if (fd < 0) { 289 error_setg(errp, "cannot find saved value for fd %s", fdname); 290 } 291 } else { 292 fd = monitor_fd_param(monitor_cur(), fdname, errp); 293 if (fd >= 0) { 294 cpr_save_fd(name, index, fd); 295 } else { 296 error_prepend(errp, "Could not parse object fd %s:", fdname); 297 } 298 } 299 return fd; 300 } 301