@@ -1299,6 +1299,15 @@ static inline int vmstate_register_named(const char *instance_name,
void vmstate_unregister(VMStateIf *obj, const VMStateDescription *vmsd,
void *opaque);
+/**
+ * Delete the VMSD handler for the object with name "vmsd_name/instance_name"
+ * and matching instance_id. If instance_id is VMSTATE_INSTANCE_ID_ANY,
+ * delete all instances matching name.
+ */
+void vmstate_unregister_named(const char *vmsd_name,
+ const char *instance_name,
+ int instance_id);
+
void vmstate_register_ram(struct MemoryRegion *memory, DeviceState *dev);
void vmstate_unregister_ram(struct MemoryRegion *memory, DeviceState *dev);
void vmstate_register_ram_global(struct MemoryRegion *memory);
@@ -964,6 +964,8 @@ void vmstate_unregister(VMStateIf *obj, const VMStateDescription *vmsd,
SAVEVM_FOREACH_SAFE_ALL(se, entry, new_se) {
if (se->vmsd == vmsd && se->opaque == opaque) {
+ trace_vmstate_unregister(se->idstr, se->instance_id, (void *)vmsd,
+ opaque);
savevm_state_handler_remove(se);
g_free(se->compat);
g_free(se);
@@ -971,6 +973,31 @@ void vmstate_unregister(VMStateIf *obj, const VMStateDescription *vmsd,
}
}
+void vmstate_unregister_named(const char *vmsd_name,
+ const char *instance_name,
+ int instance_id)
+{
+ SaveStateEntry *se, *new_se;
+ VMStateId idstr;
+
+ snprintf(idstr, sizeof(idstr), "%s/%s", vmsd_name, instance_name);
+
+ SAVEVM_FOREACH_SAFE_ALL(se, entry, new_se) {
+ if (!strcmp(se->idstr, idstr) &&
+ (instance_id == VMSTATE_INSTANCE_ID_ANY ||
+ se->instance_id == instance_id)) {
+ trace_vmstate_unregister(idstr, se->instance_id, (void *)se->vmsd,
+ se->opaque);
+ savevm_state_handler_remove(se);
+ g_free(se->compat);
+ g_free(se);
+ if (instance_id != VMSTATE_INSTANCE_ID_ANY) {
+ return;
+ }
+ }
+ }
+}
+
static int vmstate_load(QEMUFile *f, SaveStateEntry *se)
{
trace_vmstate_load(se->idstr, se->vmsd ? se->vmsd->name : "(old)");
@@ -54,6 +54,7 @@ postcopy_pause_incoming(void) ""
postcopy_pause_incoming_continued(void) ""
postcopy_page_req_sync(void *host_addr) "sync page req %p"
vmstate_register(const char *idstr, int id, void *vmsd, void *opaque) "%s, %d, vmsd %p, opaque %p"
+vmstate_unregister(const char *idstr, int id, void *vmsd, void *opaque) "%s, %d, vmsd %p, opaque %p"
# vmstate.c
vmstate_load_field_error(const char *field, int ret) "field \"%s\" load failed, ret = %d"
@@ -18,6 +18,12 @@ void vmstate_unregister(VMStateIf *obj,
{
}
+void vmstate_unregister_named(const char *vmsd_name,
+ const char *instance_name,
+ int instance_id)
+{
+}
+
bool vmstate_check_only_migratable(const VMStateDescription *vmsd)
{
return true;
Define an accessor to find vmstate state handler by name and id and unregister it. This is needed to unregister a specific instance of an object that is not an Object, since it lacks the VMStateIf get_id hook. Signed-off-by: Steve Sistare <steven.sistare@oracle.com> --- include/migration/vmstate.h | 9 +++++++++ migration/savevm.c | 27 +++++++++++++++++++++++++++ migration/trace-events | 1 + stubs/vmstate.c | 6 ++++++ 4 files changed, 43 insertions(+)