mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-04 00:03:54 -06:00
migration_completion: Take current state
Soon we'll be in either ACTIVE or POSTCOPY_ACTIVE when we complete migration, and we need to know which we expect to be in to change state safely. Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com> Reviewed-by: Juan Quintela <quintela@redhat.com> Signed-off-by: Juan Quintela <quintela@redhat.com>
This commit is contained in:
parent
f3f491fcd6
commit
e0b266f01d
8 changed files with 354 additions and 3 deletions
|
@ -27,6 +27,24 @@
|
|||
#include "qemu/error-report.h"
|
||||
#include "trace.h"
|
||||
|
||||
/* Arbitrary limit on size of each discard command,
|
||||
* keeps them around ~200 bytes
|
||||
*/
|
||||
#define MAX_DISCARDS_PER_COMMAND 12
|
||||
|
||||
struct PostcopyDiscardState {
|
||||
const char *ramblock_name;
|
||||
uint64_t offset; /* Bitmap entry for the 1st bit of this RAMBlock */
|
||||
uint16_t cur_entry;
|
||||
/*
|
||||
* Start and length of a discard range (bytes)
|
||||
*/
|
||||
uint64_t start_list[MAX_DISCARDS_PER_COMMAND];
|
||||
uint64_t length_list[MAX_DISCARDS_PER_COMMAND];
|
||||
unsigned int nsentwords;
|
||||
unsigned int nsentcmds;
|
||||
};
|
||||
|
||||
/* Postcopy needs to detect accesses to pages that haven't yet been copied
|
||||
* across, and efficiently map new pages in, the techniques for doing this
|
||||
* are target OS specific.
|
||||
|
@ -145,6 +163,27 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* postcopy_ram_discard_range: Discard a range of memory.
|
||||
* We can assume that if we've been called postcopy_ram_hosttest returned true.
|
||||
*
|
||||
* @mis: Current incoming migration state.
|
||||
* @start, @length: range of memory to discard.
|
||||
*
|
||||
* returns: 0 on success.
|
||||
*/
|
||||
int postcopy_ram_discard_range(MigrationIncomingState *mis, uint8_t *start,
|
||||
size_t length)
|
||||
{
|
||||
trace_postcopy_ram_discard_range(start, length);
|
||||
if (madvise(start, length, MADV_DONTNEED)) {
|
||||
error_report("%s MADV_DONTNEED: %s", __func__, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
/* No target OS support, stubs just fail */
|
||||
bool postcopy_ram_supported_by_host(void)
|
||||
|
@ -153,5 +192,92 @@ bool postcopy_ram_supported_by_host(void)
|
|||
return false;
|
||||
}
|
||||
|
||||
int postcopy_ram_discard_range(MigrationIncomingState *mis, uint8_t *start,
|
||||
size_t length)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* postcopy_discard_send_init: Called at the start of each RAMBlock before
|
||||
* asking to discard individual ranges.
|
||||
*
|
||||
* @ms: The current migration state.
|
||||
* @offset: the bitmap offset of the named RAMBlock in the migration
|
||||
* bitmap.
|
||||
* @name: RAMBlock that discards will operate on.
|
||||
*
|
||||
* returns: a new PDS.
|
||||
*/
|
||||
PostcopyDiscardState *postcopy_discard_send_init(MigrationState *ms,
|
||||
unsigned long offset,
|
||||
const char *name)
|
||||
{
|
||||
PostcopyDiscardState *res = g_malloc0(sizeof(PostcopyDiscardState));
|
||||
|
||||
if (res) {
|
||||
res->ramblock_name = name;
|
||||
res->offset = offset;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* postcopy_discard_send_range: Called by the bitmap code for each chunk to
|
||||
* discard. May send a discard message, may just leave it queued to
|
||||
* be sent later.
|
||||
*
|
||||
* @ms: Current migration state.
|
||||
* @pds: Structure initialised by postcopy_discard_send_init().
|
||||
* @start,@length: a range of pages in the migration bitmap in the
|
||||
* RAM block passed to postcopy_discard_send_init() (length=1 is one page)
|
||||
*/
|
||||
void postcopy_discard_send_range(MigrationState *ms, PostcopyDiscardState *pds,
|
||||
unsigned long start, unsigned long length)
|
||||
{
|
||||
size_t tp_bits = qemu_target_page_bits();
|
||||
/* Convert to byte offsets within the RAM block */
|
||||
pds->start_list[pds->cur_entry] = (start - pds->offset) << tp_bits;
|
||||
pds->length_list[pds->cur_entry] = length << tp_bits;
|
||||
trace_postcopy_discard_send_range(pds->ramblock_name, start, length);
|
||||
pds->cur_entry++;
|
||||
pds->nsentwords++;
|
||||
|
||||
if (pds->cur_entry == MAX_DISCARDS_PER_COMMAND) {
|
||||
/* Full set, ship it! */
|
||||
qemu_savevm_send_postcopy_ram_discard(ms->file, pds->ramblock_name,
|
||||
pds->cur_entry,
|
||||
pds->start_list,
|
||||
pds->length_list);
|
||||
pds->nsentcmds++;
|
||||
pds->cur_entry = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* postcopy_discard_send_finish: Called at the end of each RAMBlock by the
|
||||
* bitmap code. Sends any outstanding discard messages, frees the PDS
|
||||
*
|
||||
* @ms: Current migration state.
|
||||
* @pds: Structure initialised by postcopy_discard_send_init().
|
||||
*/
|
||||
void postcopy_discard_send_finish(MigrationState *ms, PostcopyDiscardState *pds)
|
||||
{
|
||||
/* Anything unsent? */
|
||||
if (pds->cur_entry) {
|
||||
qemu_savevm_send_postcopy_ram_discard(ms->file, pds->ramblock_name,
|
||||
pds->cur_entry,
|
||||
pds->start_list,
|
||||
pds->length_list);
|
||||
pds->nsentcmds++;
|
||||
}
|
||||
|
||||
trace_postcopy_discard_send_finish(pds->ramblock_name, pds->nsentwords,
|
||||
pds->nsentcmds);
|
||||
|
||||
g_free(pds);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue