migration/ram.c: add a notifier chain for precopy

This patch adds a notifier chain for the memory precopy. This enables various
precopy optimizations to be invoked at specific places.

Signed-off-by: Wei Wang <wei.w.wang@intel.com>
CC: Dr. David Alan Gilbert <dgilbert@redhat.com>
CC: Juan Quintela <quintela@redhat.com>
CC: Michael S. Tsirkin <mst@redhat.com>
CC: Peter Xu <peterx@redhat.com>
Reviewed-by: Peter Xu <peterx@redhat.com>
Message-Id: <1544516693-5395-6-git-send-email-wei.w.wang@intel.com>
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
This commit is contained in:
Wei Wang 2018-12-11 16:24:51 +08:00 committed by Dr. David Alan Gilbert
parent 6bcb05fc42
commit bd2270608f
4 changed files with 83 additions and 3 deletions

View File

@ -20,6 +20,25 @@
/* migration/ram.c */
typedef enum PrecopyNotifyReason {
PRECOPY_NOTIFY_SETUP = 0,
PRECOPY_NOTIFY_BEFORE_BITMAP_SYNC = 1,
PRECOPY_NOTIFY_AFTER_BITMAP_SYNC = 2,
PRECOPY_NOTIFY_COMPLETE = 3,
PRECOPY_NOTIFY_CLEANUP = 4,
PRECOPY_NOTIFY_MAX = 5,
} PrecopyNotifyReason;
typedef struct PrecopyNotifyData {
enum PrecopyNotifyReason reason;
Error **errp;
} PrecopyNotifyData;
void precopy_infrastructure_init(void);
void precopy_add_notifier(NotifierWithReturn *n);
void precopy_remove_notifier(NotifierWithReturn *n);
int precopy_notify(PrecopyNotifyReason reason, Error **errp);
void ram_mig_init(void);
void qemu_guest_free_page_hint(void *addr, size_t len);

View File

@ -354,6 +354,32 @@ typedef struct RAMState RAMState;
static RAMState *ram_state;
static NotifierWithReturnList precopy_notifier_list;
void precopy_infrastructure_init(void)
{
notifier_with_return_list_init(&precopy_notifier_list);
}
void precopy_add_notifier(NotifierWithReturn *n)
{
notifier_with_return_list_add(&precopy_notifier_list, n);
}
void precopy_remove_notifier(NotifierWithReturn *n)
{
notifier_with_return_remove(n);
}
int precopy_notify(PrecopyNotifyReason reason, Error **errp)
{
PrecopyNotifyData pnd;
pnd.reason = reason;
pnd.errp = errp;
return notifier_with_return_list_notify(&precopy_notifier_list, &pnd);
}
uint64_t ram_bytes_remaining(void)
{
return ram_state ? (ram_state->migration_dirty_pages * TARGET_PAGE_SIZE) :
@ -1741,6 +1767,25 @@ static void migration_bitmap_sync(RAMState *rs)
}
}
static void migration_bitmap_sync_precopy(RAMState *rs)
{
Error *local_err = NULL;
/*
* The current notifier usage is just an optimization to migration, so we
* don't stop the normal migration process in the error case.
*/
if (precopy_notify(PRECOPY_NOTIFY_BEFORE_BITMAP_SYNC, &local_err)) {
error_report_err(local_err);
}
migration_bitmap_sync(rs);
if (precopy_notify(PRECOPY_NOTIFY_AFTER_BITMAP_SYNC, &local_err)) {
error_report_err(local_err);
}
}
/**
* save_zero_page_to_file: send the zero page to the file
*
@ -3123,7 +3168,7 @@ static void ram_init_bitmaps(RAMState *rs)
ram_list_init_bitmaps();
memory_global_dirty_log_start();
migration_bitmap_sync(rs);
migration_bitmap_sync_precopy(rs);
rcu_read_unlock();
qemu_mutex_unlock_ramlist();
@ -3403,7 +3448,7 @@ static int ram_save_complete(QEMUFile *f, void *opaque)
rcu_read_lock();
if (!migration_in_postcopy()) {
migration_bitmap_sync(rs);
migration_bitmap_sync_precopy(rs);
}
ram_control_before_iterate(f, RAM_CONTROL_FINISH);
@ -3452,7 +3497,7 @@ static void ram_save_pending(QEMUFile *f, void *opaque, uint64_t max_size,
remaining_size < max_size) {
qemu_mutex_lock_iothread();
rcu_read_lock();
migration_bitmap_sync(rs);
migration_bitmap_sync_precopy(rs);
rcu_read_unlock();
qemu_mutex_unlock_iothread();
remaining_size = rs->migration_dirty_pages * TARGET_PAGE_SIZE;

View File

@ -1088,6 +1088,7 @@ void qemu_savevm_state_header(QEMUFile *f)
void qemu_savevm_state_setup(QEMUFile *f)
{
SaveStateEntry *se;
Error *local_err = NULL;
int ret;
trace_savevm_state_setup();
@ -1109,6 +1110,10 @@ void qemu_savevm_state_setup(QEMUFile *f)
break;
}
}
if (precopy_notify(PRECOPY_NOTIFY_SETUP, &local_err)) {
error_report_err(local_err);
}
}
int qemu_savevm_state_resume_prepare(MigrationState *s)
@ -1251,6 +1256,11 @@ int qemu_savevm_state_complete_precopy(QEMUFile *f, bool iterable_only,
SaveStateEntry *se;
int ret;
bool in_postcopy = migration_in_postcopy();
Error *local_err = NULL;
if (precopy_notify(PRECOPY_NOTIFY_COMPLETE, &local_err)) {
error_report_err(local_err);
}
trace_savevm_state_complete_precopy();
@ -1383,6 +1393,11 @@ void qemu_savevm_state_pending(QEMUFile *f, uint64_t threshold_size,
void qemu_savevm_state_cleanup(void)
{
SaveStateEntry *se;
Error *local_err = NULL;
if (precopy_notify(PRECOPY_NOTIFY_CLEANUP, &local_err)) {
error_report_err(local_err);
}
trace_savevm_state_cleanup();
QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {

1
vl.c
View File

@ -3039,6 +3039,7 @@ int main(int argc, char **argv, char **envp)
module_call_init(MODULE_INIT_OPTS);
runstate_init();
precopy_infrastructure_init();
postcopy_infrastructure_init();
monitor_init_globals();