diff options
author | ChenLiang <chenliang88@huawei.com> | 2014-04-04 17:57:53 +0800 |
---|---|---|
committer | Juan Quintela <quintela@redhat.com> | 2014-05-05 22:15:03 +0200 |
commit | 1534ee93cc6be992c05577886b24bd44c37ecff6 (patch) | |
tree | 6f3963b2c5bb289fa2a5ff6878bd933118206356 /arch_init.c | |
parent | 21a246a43b606ee833f907d589d8dcbb54a2761e (diff) | |
download | qemu-1534ee93cc6be992c05577886b24bd44c37ecff6.tar.gz qemu-1534ee93cc6be992c05577886b24bd44c37ecff6.tar.bz2 qemu-1534ee93cc6be992c05577886b24bd44c37ecff6.zip |
XBZRLE: Fix one XBZRLE corruption issues
The page may not be inserted into cache after executing save_xbzrle_page.
In case of failure to insert, the original page should be sent rather
than the page in the cache.
Signed-off-by: ChenLiang <chenliang88@huawei.com>
Signed-off-by: Gonglei <arei.gonglei@huawei.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
Diffstat (limited to 'arch_init.c')
-rw-r--r-- | arch_init.c | 25 |
1 files changed, 13 insertions, 12 deletions
diff --git a/arch_init.c b/arch_init.c index 15a706eb32..0ffecee7fb 100644 --- a/arch_init.c +++ b/arch_init.c @@ -341,7 +341,7 @@ static void xbzrle_cache_zero_page(ram_addr_t current_addr) #define ENCODING_FLAG_XBZRLE 0x1 -static int save_xbzrle_page(QEMUFile *f, uint8_t *current_data, +static int save_xbzrle_page(QEMUFile *f, uint8_t **current_data, ram_addr_t current_addr, RAMBlock *block, ram_addr_t offset, int cont, bool last_stage) { @@ -349,19 +349,23 @@ static int save_xbzrle_page(QEMUFile *f, uint8_t *current_data, uint8_t *prev_cached_page; if (!cache_is_cached(XBZRLE.cache, current_addr)) { + acct_info.xbzrle_cache_miss++; if (!last_stage) { - if (cache_insert(XBZRLE.cache, current_addr, current_data) == -1) { + if (cache_insert(XBZRLE.cache, current_addr, *current_data) == -1) { return -1; + } else { + /* update *current_data when the page has been + inserted into cache */ + *current_data = get_cached_data(XBZRLE.cache, current_addr); } } - acct_info.xbzrle_cache_miss++; return -1; } prev_cached_page = get_cached_data(XBZRLE.cache, current_addr); /* save current buffer into memory */ - memcpy(XBZRLE.current_buf, current_data, TARGET_PAGE_SIZE); + memcpy(XBZRLE.current_buf, *current_data, TARGET_PAGE_SIZE); /* XBZRLE encoding (if there is no overflow) */ encoded_len = xbzrle_encode_buffer(prev_cached_page, XBZRLE.current_buf, @@ -374,7 +378,10 @@ static int save_xbzrle_page(QEMUFile *f, uint8_t *current_data, DPRINTF("Overflow\n"); acct_info.xbzrle_overflows++; /* update data in the cache */ - memcpy(prev_cached_page, current_data, TARGET_PAGE_SIZE); + if (!last_stage) { + memcpy(prev_cached_page, *current_data, TARGET_PAGE_SIZE); + *current_data = prev_cached_page; + } return -1; } @@ -599,15 +606,9 @@ static int ram_save_block(QEMUFile *f, bool last_stage) */ xbzrle_cache_zero_page(current_addr); } else if (!ram_bulk_stage && migrate_use_xbzrle()) { - bytes_sent = save_xbzrle_page(f, p, current_addr, block, + bytes_sent = save_xbzrle_page(f, &p, current_addr, block, offset, cont, last_stage); if (!last_stage) { - /* We must send exactly what's in the xbzrle cache - * even if the page wasn't xbzrle compressed, so that - * it's right next time. - */ - p = get_cached_data(XBZRLE.cache, current_addr); - /* Can't send this cached data async, since the cache page * might get updated before it gets to the wire */ |