Revision 7685ee6a

b/savevm.c
72 72

  
73 73
#include "qemu-common.h"
74 74
#include "hw/hw.h"
75
#include "hw/qdev.h"
75 76
#include "net.h"
76 77
#include "monitor.h"
77 78
#include "sysemu.h"
......
985 986
    .put  = put_unused_buffer,
986 987
};
987 988

  
989
typedef struct CompatEntry {
990
    char idstr[256];
991
    int instance_id;
992
} CompatEntry;
993

  
988 994
typedef struct SaveStateEntry {
989 995
    QTAILQ_ENTRY(SaveStateEntry) entry;
990 996
    char idstr[256];
......
998 1004
    LoadStateHandler *load_state;
999 1005
    const VMStateDescription *vmsd;
1000 1006
    void *opaque;
1007
    CompatEntry *compat;
1001 1008
} SaveStateEntry;
1002 1009

  
1003 1010

  
......
1019 1026
    return instance_id;
1020 1027
}
1021 1028

  
1029
static int calculate_compat_instance_id(const char *idstr)
1030
{
1031
    SaveStateEntry *se;
1032
    int instance_id = 0;
1033

  
1034
    QTAILQ_FOREACH(se, &savevm_handlers, entry) {
1035
        if (!se->compat)
1036
            continue;
1037

  
1038
        if (strcmp(idstr, se->compat->idstr) == 0
1039
            && instance_id <= se->compat->instance_id) {
1040
            instance_id = se->compat->instance_id + 1;
1041
        }
1042
    }
1043
    return instance_id;
1044
}
1045

  
1022 1046
/* TODO: Individual devices generally have very little idea about the rest
1023 1047
   of the system, so instance_id should be removed/replaced.
1024 1048
   Meanwhile pass -1 as instance_id if you do not already have a clearly
......
1036 1060
    SaveStateEntry *se;
1037 1061

  
1038 1062
    se = qemu_mallocz(sizeof(SaveStateEntry));
1039
    pstrcpy(se->idstr, sizeof(se->idstr), idstr);
1040 1063
    se->version_id = version_id;
1041 1064
    se->section_id = global_section_id++;
1042 1065
    se->set_params = set_params;
......
1046 1069
    se->opaque = opaque;
1047 1070
    se->vmsd = NULL;
1048 1071

  
1072
    if (dev && dev->parent_bus && dev->parent_bus->info->get_dev_path) {
1073
        char *id = dev->parent_bus->info->get_dev_path(dev);
1074
        if (id) {
1075
            pstrcpy(se->idstr, sizeof(se->idstr), id);
1076
            pstrcat(se->idstr, sizeof(se->idstr), "/");
1077
            qemu_free(id);
1078

  
1079
            se->compat = qemu_mallocz(sizeof(CompatEntry));
1080
            pstrcpy(se->compat->idstr, sizeof(se->compat->idstr), idstr);
1081
            se->compat->instance_id = instance_id == -1 ?
1082
                         calculate_compat_instance_id(idstr) : instance_id;
1083
            instance_id = -1;
1084
        }
1085
    }
1086
    pstrcat(se->idstr, sizeof(se->idstr), idstr);
1087

  
1049 1088
    if (instance_id == -1) {
1050
        se->instance_id = calculate_new_instance_id(idstr);
1089
        se->instance_id = calculate_new_instance_id(se->idstr);
1051 1090
    } else {
1052 1091
        se->instance_id = instance_id;
1053 1092
    }
1093
    assert(!se->compat || se->instance_id == 0);
1054 1094
    /* add at the end of list */
1055 1095
    QTAILQ_INSERT_TAIL(&savevm_handlers, se, entry);
1056 1096
    return 0;
......
1071 1111
void unregister_savevm(DeviceState *dev, const char *idstr, void *opaque)
1072 1112
{
1073 1113
    SaveStateEntry *se, *new_se;
1114
    char id[256] = "";
1115

  
1116
    if (dev && dev->parent_bus && dev->parent_bus->info->get_dev_path) {
1117
        char *path = dev->parent_bus->info->get_dev_path(dev);
1118
        if (path) {
1119
            pstrcpy(id, sizeof(id), path);
1120
            pstrcat(id, sizeof(id), "/");
1121
            qemu_free(path);
1122
        }
1123
    }
1124
    pstrcat(id, sizeof(id), idstr);
1074 1125

  
1075 1126
    QTAILQ_FOREACH_SAFE(se, &savevm_handlers, entry, new_se) {
1076
        if (strcmp(se->idstr, idstr) == 0 && se->opaque == opaque) {
1127
        if (strcmp(se->idstr, id) == 0 && se->opaque == opaque) {
1077 1128
            QTAILQ_REMOVE(&savevm_handlers, se, entry);
1078 1129
            qemu_free(se);
1079 1130
        }
......
1091 1142
    assert(alias_id == -1 || required_for_version >= vmsd->minimum_version_id);
1092 1143

  
1093 1144
    se = qemu_mallocz(sizeof(SaveStateEntry));
1094
    pstrcpy(se->idstr, sizeof(se->idstr), vmsd->name);
1095 1145
    se->version_id = vmsd->version_id;
1096 1146
    se->section_id = global_section_id++;
1097 1147
    se->save_live_state = NULL;
......
1101 1151
    se->vmsd = vmsd;
1102 1152
    se->alias_id = alias_id;
1103 1153

  
1154
    if (dev && dev->parent_bus && dev->parent_bus->info->get_dev_path) {
1155
        char *id = dev->parent_bus->info->get_dev_path(dev);
1156
        if (id) {
1157
            pstrcpy(se->idstr, sizeof(se->idstr), id);
1158
            pstrcat(se->idstr, sizeof(se->idstr), "/");
1159
            qemu_free(id);
1160

  
1161
            se->compat = qemu_mallocz(sizeof(CompatEntry));
1162
            pstrcpy(se->compat->idstr, sizeof(se->compat->idstr), vmsd->name);
1163
            se->compat->instance_id = instance_id == -1 ?
1164
                         calculate_compat_instance_id(vmsd->name) : instance_id;
1165
            instance_id = -1;
1166
        }
1167
    }
1168
    pstrcat(se->idstr, sizeof(se->idstr), vmsd->name);
1169

  
1104 1170
    if (instance_id == -1) {
1105
        se->instance_id = calculate_new_instance_id(vmsd->name);
1171
        se->instance_id = calculate_new_instance_id(se->idstr);
1106 1172
    } else {
1107 1173
        se->instance_id = instance_id;
1108 1174
    }
1175
    assert(!se->compat || se->instance_id == 0);
1109 1176
    /* add at the end of list */
1110 1177
    QTAILQ_INSERT_TAIL(&savevm_handlers, se, entry);
1111 1178
    return 0;
......
1451 1518
            (instance_id == se->instance_id ||
1452 1519
             instance_id == se->alias_id))
1453 1520
            return se;
1521
        /* Migrating from an older version? */
1522
        if (strstr(se->idstr, idstr) && se->compat) {
1523
            if (!strcmp(se->compat->idstr, idstr) &&
1524
                (instance_id == se->compat->instance_id ||
1525
                 instance_id == se->alias_id))
1526
                return se;
1527
        }
1454 1528
    }
1455 1529
    return NULL;
1456 1530
}

Also available in: Unified diff