2 * Global State configuration
4 * Copyright (c) 2014-2017 Red Hat Inc
7 * Juan Quintela <quintela@redhat.com>
9 * This work is licensed under the terms of the GNU GPL, version 2 or later.
10 * See the COPYING file in the top-level directory.
13 #include "qemu/osdep.h"
14 #include "qemu/cutils.h"
15 #include "qemu/error-report.h"
16 #include "sysemu/runstate.h"
17 #include "qapi/error.h"
18 #include "migration.h"
19 #include "migration/global_state.h"
20 #include "migration/vmstate.h"
25 uint8_t runstate
[100];
30 static GlobalState global_state
;
32 static void global_state_do_store(RunState state
)
34 const char *state_str
= RunState_str(state
);
35 assert(strlen(state_str
) < sizeof(global_state
.runstate
));
36 strpadcpy((char *)global_state
.runstate
, sizeof(global_state
.runstate
),
40 void global_state_store(void)
42 global_state_do_store(runstate_get());
45 void global_state_store_running(void)
47 global_state_do_store(RUN_STATE_RUNNING
);
50 bool global_state_received(void)
52 return global_state
.received
;
55 RunState
global_state_get_runstate(void)
57 return global_state
.state
;
60 static bool global_state_needed(void *opaque
)
62 GlobalState
*s
= opaque
;
63 char *runstate
= (char *)s
->runstate
;
65 /* If it is not optional, it is mandatory */
67 if (migrate_get_current()->store_global_state
) {
71 /* If state is running or paused, it is not needed */
73 if (strcmp(runstate
, "running") == 0 ||
74 strcmp(runstate
, "paused") == 0) {
78 /* for any other state it is needed */
82 static int global_state_post_load(void *opaque
, int version_id
)
84 GlobalState
*s
= opaque
;
85 Error
*local_err
= NULL
;
87 char *runstate
= (char *)s
->runstate
;
90 trace_migrate_global_state_post_load(runstate
);
92 if (strnlen((char *)s
->runstate
,
93 sizeof(s
->runstate
)) == sizeof(s
->runstate
)) {
95 * This condition should never happen during migration, because
96 * all runstate names are shorter than 100 bytes (the size of
97 * s->runstate). However, a malicious stream could overflow
98 * the qapi_enum_parse() call, so we force the last character
101 s
->runstate
[sizeof(s
->runstate
) - 1] = '\0';
103 r
= qapi_enum_parse(&RunState_lookup
, runstate
, -1, &local_err
);
107 error_report_err(local_err
);
116 static int global_state_pre_save(void *opaque
)
118 GlobalState
*s
= opaque
;
120 trace_migrate_global_state_pre_save((char *)s
->runstate
);
121 s
->size
= strnlen((char *)s
->runstate
, sizeof(s
->runstate
)) + 1;
122 assert(s
->size
<= sizeof(s
->runstate
));
127 static const VMStateDescription vmstate_globalstate
= {
128 .name
= "globalstate",
130 .minimum_version_id
= 1,
131 .post_load
= global_state_post_load
,
132 .pre_save
= global_state_pre_save
,
133 .needed
= global_state_needed
,
134 .fields
= (VMStateField
[]) {
135 VMSTATE_UINT32(size
, GlobalState
),
136 VMSTATE_BUFFER(runstate
, GlobalState
),
137 VMSTATE_END_OF_LIST()
141 void register_global_state(void)
143 /* We would use it independently that we receive it */
144 strcpy((char *)&global_state
.runstate
, "");
145 global_state
.received
= false;
146 vmstate_register(NULL
, 0, &vmstate_globalstate
, &global_state
);