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:
parent
6bcb05fc42
commit
bd2270608f
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user