From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:44114) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aH9Yb-0007ue-5X for qemu-devel@nongnu.org; Thu, 07 Jan 2016 07:20:46 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1aH9YY-0004Kn-AG for qemu-devel@nongnu.org; Thu, 07 Jan 2016 07:20:45 -0500 Received: from szxga03-in.huawei.com ([119.145.14.66]:36982) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aH9YX-0004JR-MJ for qemu-devel@nongnu.org; Thu, 07 Jan 2016 07:20:42 -0500 From: zhanghailiang Date: Thu, 7 Jan 2016 20:20:05 +0800 Message-ID: <1452169208-840-11-git-send-email-zhang.zhanghailiang@huawei.com> In-Reply-To: <1452169208-840-1-git-send-email-zhang.zhanghailiang@huawei.com> References: <1452169208-840-1-git-send-email-zhang.zhanghailiang@huawei.com> MIME-Version: 1.0 Content-Type: text/plain Subject: [Qemu-devel] [RFC 10/13] snapshot: Enable the write-protect notification capability for VM's RAM List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: aarcange@redhat.com, zhanghailiang , hanweidong@huawei.com, quintela@redhat.com, peter.huangpeng@huawei.com, dgilbert@redhat.com, amit.shah@redhat.com For live memory snapshot, we need to save the page before it is dirtied, With the help of userfaultfd's write-protect notification capability, we can get notification when the page is going to be dirtied, and save the page before it is written. We need to enable VM's ram write-protect notification capability with VM is paused, and here we add UserfaultState parameter for struct MigrationState. Signed-off-by: zhanghailiang --- include/migration/migration.h | 3 +++ include/migration/postcopy-ram.h | 3 +++ migration/migration.c | 6 +++++- migration/postcopy-ram.c | 34 ++++++++++++++++++++++++++++++---- 4 files changed, 41 insertions(+), 5 deletions(-) diff --git a/include/migration/migration.h b/include/migration/migration.h index 2312c73..ef4c071 100644 --- a/include/migration/migration.h +++ b/include/migration/migration.h @@ -173,6 +173,9 @@ struct MigrationState QSIMPLEQ_HEAD(src_page_requests, MigrationSrcPageRequest) src_page_requests; /* The RAMBlock used in the last src_page_request */ RAMBlock *last_req_rb; + + UserfaultState userfault_state; + bool in_snapshot; /* for snapshot */ }; diff --git a/include/migration/postcopy-ram.h b/include/migration/postcopy-ram.h index 568cbdd..978a8d7 100644 --- a/include/migration/postcopy-ram.h +++ b/include/migration/postcopy-ram.h @@ -96,4 +96,7 @@ int postcopy_place_page_zero(MigrationIncomingState *mis, void *host); */ void *postcopy_get_tmp_page(MigrationIncomingState *mis); +int postcopy_ram_disable_notify(UserfaultState *us); + +void qemu_mlock_all_memory(void); #endif diff --git a/migration/migration.c b/migration/migration.c index fd234eb..2001490 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -1751,6 +1751,8 @@ static void *snapshot_thread(void *opaque) error_report("snapshot only support 'tcg' accel for now"); goto error; } + /* userfaultfd's write-protected capability need all pages to be exist */ + qemu_mlock_all_memory(); qemu_savevm_state_header(ms->file); qemu_savevm_state_begin(ms->file, &ms->params); @@ -1766,7 +1768,7 @@ static void *snapshot_thread(void *opaque) goto error; } } - + postcopy_ram_enable_notify(&ms->userfault_state, UFFDIO_REGISTER_MODE_WP); buffer = qemu_save_device_buffer(); if (old_vm_running) { @@ -1789,6 +1791,8 @@ static void *snapshot_thread(void *opaque) MIGRATION_STATUS_COMPLETED); } + postcopy_ram_disable_notify(&ms->userfault_state); + qemu_mutex_lock_iothread(); qemu_savevm_state_cleanup(); qemu_bh_schedule(ms->cleanup_bh); diff --git a/migration/postcopy-ram.c b/migration/postcopy-ram.c index 370197e..9cd854b 100644 --- a/migration/postcopy-ram.c +++ b/migration/postcopy-ram.c @@ -279,7 +279,7 @@ int postcopy_ram_incoming_init(MigrationIncomingState *mis, size_t ram_pages) return 0; } -static int postcopy_ram_disable_notify(UserfaultState *us) +int postcopy_ram_disable_notify(UserfaultState *us) { if (us->have_fault_thread) { uint64_t tmp64; @@ -370,9 +370,7 @@ static int nhp_range(const char *block_name, void *host_addr, */ int postcopy_ram_prepare_discard(MigrationIncomingState *mis) { - if (qemu_ram_foreach_block(nhp_range, mis)) { - return -1; - } + postcopy_state_set(POSTCOPY_INCOMING_DISCARD); @@ -586,6 +584,9 @@ int postcopy_ram_enable_notify(UserfaultState *us, int mode) return -1; } + if (qemu_ram_foreach_block(nhp_range, us)) { + return -1; + } /* * Ballooning can mark pages as absent while we're postcopying * that would cause false userfaults. @@ -816,3 +817,28 @@ void postcopy_discard_send_finish(MigrationState *ms, PostcopyDiscardState *pds) g_free(pds); } + +static int ram_block_mlock(const char *block_name, void *host_addr, + ram_addr_t offset, ram_addr_t length, + void *opaque) +{ + int ret; + + ret = mlock(host_addr, length); + if (ret < 0) { + error_report("%s mlock failed: %s", __func__, strerror(errno)); + return -1; + } + return 0; +} + +void qemu_mlock_all_memory(void) +{ + /* Users have configured mlock, so don't do it again */ + if (enable_mlock) { + return; + } + if (qemu_ram_foreach_block(ram_block_mlock, NULL)) { + error_report("mlock all VM's memory failed"); + } +} -- 1.8.3.1