void save_cpr_snapshot(const char *file, const char *mode, Error **errp) { int ret = 0; QEMUFile *f; VMStateMode op; if (!strcmp(mode, "reboot")) { op = VMS_REBOOT; } else if (!strcmp(mode, "restart")) { op = VMS_RESTART; } else { error_setg(errp, "cprsave: bad mode %s", mode); return; } if (op == VMS_REBOOT && qemu_ram_volatile(errp)) { return; } if (op == VMS_RESTART && QEMU_MADV_DOEXEC == QEMU_MADV_INVALID) { error_setg(errp, "kernel does not support MADV_DOEXEC."); return; } if (op == VMS_RESTART && xen_enabled()) { error_setg(errp, "xen does not support cprsave restart"); return; } f = qf_file_open(file, O_CREAT | O_WRONLY | O_TRUNC, 0600, errp); if (!f) { return; } ret = global_state_store(); if (ret) { error_setg(errp, "Error saving global state"); qemu_fclose(f); return; } /* Update timers_state before saving. Suspend did not so do. */ if (runstate_check(RUN_STATE_SUSPENDED)) { cpu_disable_ticks(); } vm_stop(RUN_STATE_SAVE_VM); ret = qemu_savevm_state(f, op, errp); if ((ret < 0) && !*errp) { error_setg(errp, "qemu_savevm_state failed"); } qemu_fclose(f); if (op == VMS_REBOOT) { no_shutdown = 0; qemu_system_shutdown_request(); } else if (op == VMS_RESTART) { if (qemu_preserve_ram(errp)) { return; } save_chardev_fds(); save_vnc_fds(); save_named_fd("mntfd"); /* was received from qemu-cpr */ save_named_fd("ctlfd"); /* was received from qemu-cpr */ walkenv(FD_PREFIX, preserve_fd, 0); reset_vhost_devices(); save_qmp_negotiation_status(); qemu_term_exit(); qemu_system_exec_request(); putenv((char *)"QEMU_START_FREEZE="); } }