qemu/migration/global_state.c
<<
>>
Prefs
   1/*
   2 * Global State configuration
   3 *
   4 * Copyright (c) 2014-2017 Red Hat Inc
   5 *
   6 * Authors:
   7 *  Juan Quintela <quintela@redhat.com>
   8 *
   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.
  11 */
  12
  13#include "qemu/osdep.h"
  14#include "qemu/cutils.h"
  15#include "qemu/error-report.h"
  16#include "qapi/error.h"
  17#include "qapi/util.h"
  18#include "migration.h"
  19#include "migration/global_state.h"
  20#include "migration/vmstate.h"
  21#include "trace.h"
  22
  23typedef struct {
  24    uint32_t size;
  25    uint8_t runstate[100];
  26    RunState state;
  27    bool received;
  28} GlobalState;
  29
  30static GlobalState global_state;
  31
  32int global_state_store(void)
  33{
  34    if (!runstate_store((char *)global_state.runstate,
  35                        sizeof(global_state.runstate))) {
  36        error_report("runstate name too big: %s", global_state.runstate);
  37        trace_migrate_state_too_big();
  38        return -EINVAL;
  39    }
  40    return 0;
  41}
  42
  43void global_state_store_running(void)
  44{
  45    const char *state = RunState_lookup[RUN_STATE_RUNNING];
  46    strncpy((char *)global_state.runstate,
  47           state, sizeof(global_state.runstate));
  48}
  49
  50bool global_state_received(void)
  51{
  52    return global_state.received;
  53}
  54
  55RunState global_state_get_runstate(void)
  56{
  57    return global_state.state;
  58}
  59
  60static bool global_state_needed(void *opaque)
  61{
  62    GlobalState *s = opaque;
  63    char *runstate = (char *)s->runstate;
  64
  65    /* If it is not optional, it is mandatory */
  66
  67    if (migrate_get_current()->store_global_state) {
  68        return true;
  69    }
  70
  71    /* If state is running or paused, it is not needed */
  72
  73    if (strcmp(runstate, "running") == 0 ||
  74        strcmp(runstate, "paused") == 0) {
  75        return false;
  76    }
  77
  78    /* for any other state it is needed */
  79    return true;
  80}
  81
  82static int global_state_post_load(void *opaque, int version_id)
  83{
  84    GlobalState *s = opaque;
  85    Error *local_err = NULL;
  86    int r;
  87    char *runstate = (char *)s->runstate;
  88
  89    s->received = true;
  90    trace_migrate_global_state_post_load(runstate);
  91
  92    r = qapi_enum_parse(RunState_lookup, runstate, RUN_STATE__MAX,
  93                                -1, &local_err);
  94
  95    if (r == -1) {
  96        if (local_err) {
  97            error_report_err(local_err);
  98        }
  99        return -EINVAL;
 100    }
 101    s->state = r;
 102
 103    return 0;
 104}
 105
 106static void global_state_pre_save(void *opaque)
 107{
 108    GlobalState *s = opaque;
 109
 110    trace_migrate_global_state_pre_save((char *)s->runstate);
 111    s->size = strlen((char *)s->runstate) + 1;
 112}
 113
 114static const VMStateDescription vmstate_globalstate = {
 115    .name = "globalstate",
 116    .version_id = 1,
 117    .minimum_version_id = 1,
 118    .post_load = global_state_post_load,
 119    .pre_save = global_state_pre_save,
 120    .needed = global_state_needed,
 121    .fields = (VMStateField[]) {
 122        VMSTATE_UINT32(size, GlobalState),
 123        VMSTATE_BUFFER(runstate, GlobalState),
 124        VMSTATE_END_OF_LIST()
 125    },
 126};
 127
 128void register_global_state(void)
 129{
 130    /* We would use it independently that we receive it */
 131    strcpy((char *)&global_state.runstate, "");
 132    global_state.received = false;
 133    vmstate_register(NULL, 0, &vmstate_globalstate, &global_state);
 134}
 135