All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH] Fix two XBZRLE corruption issues
@ 2014-02-13 19:44 Dr. David Alan Gilbert (git)
  2014-02-14  9:32 ` Gonglei (Arei)
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Dr. David Alan Gilbert (git) @ 2014-02-13 19:44 UTC (permalink / raw)
  To: qemu-devel; +Cc: owasserm, quintela

From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>

Push zero'd pages into the XBZRLE cache
    A page that was cached by XBZRLE, zero'd and then XBZRLE'd again
    was being compared against a stale cache value

Don't use 'qemu_put_buffer_async' to put pages from the XBZRLE cache
    Since the cache might change before the data hits the wire

Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
---
 arch_init.c                    | 64 ++++++++++++++++++++++++++++++++----------
 include/migration/page_cache.h |  2 +-
 page_cache.c                   |  2 +-
 3 files changed, 51 insertions(+), 17 deletions(-)

diff --git a/arch_init.c b/arch_init.c
index 80574a0..fe17279 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -122,7 +122,6 @@ static void check_guest_throttling(void);
 #define RAM_SAVE_FLAG_XBZRLE   0x40
 /* 0x80 is reserved in migration.h start with 0x100 next */
 
-
 static struct defconfig_file {
     const char *filename;
     /* Indicates it is an user config file (disabled by -no-user-config) */
@@ -133,6 +132,7 @@ static struct defconfig_file {
     { NULL }, /* end of list */
 };
 
+static const uint8_t ZERO_TARGET_PAGE[TARGET_PAGE_SIZE];
 
 int qemu_read_default_config_files(bool userconfig)
 {
@@ -273,6 +273,34 @@ static size_t save_block_hdr(QEMUFile *f, RAMBlock *block, ram_addr_t offset,
     return size;
 }
 
+/* This is the last block that we have visited serching for dirty pages
+ */
+static RAMBlock *last_seen_block;
+/* This is the last block from where we have sent data */
+static RAMBlock *last_sent_block;
+static ram_addr_t last_offset;
+static unsigned long *migration_bitmap;
+static uint64_t migration_dirty_pages;
+static uint32_t last_version;
+static bool ram_bulk_stage;
+
+/* Update the xbzrle cache to reflect a page that's been sent as all 0.
+ * The important thing is that a stale (not-yet-0'd) page be replaced
+ * by the new data.
+ * As a bonus, if the page wasn't in the cache it gets added so that
+ * when a small write is made into the 0'd page it gets XBZRLE sent
+ */
+static void xbzrle_cache_zero_page(ram_addr_t current_addr)
+{
+    if (ram_bulk_stage || !migrate_use_xbzrle()) {
+        return;
+    }
+
+    /* We don't care if this fails to allocate a new cache page
+     * as long as it updated an old one */
+    cache_insert(XBZRLE.cache, current_addr, ZERO_TARGET_PAGE);
+}
+
 #define ENCODING_FLAG_XBZRLE 0x1
 
 static int save_xbzrle_page(QEMUFile *f, uint8_t *current_data,
@@ -329,18 +357,6 @@ static int save_xbzrle_page(QEMUFile *f, uint8_t *current_data,
     return bytes_sent;
 }
 
-
-/* This is the last block that we have visited serching for dirty pages
- */
-static RAMBlock *last_seen_block;
-/* This is the last block from where we have sent data */
-static RAMBlock *last_sent_block;
-static ram_addr_t last_offset;
-static unsigned long *migration_bitmap;
-static uint64_t migration_dirty_pages;
-static uint32_t last_version;
-static bool ram_bulk_stage;
-
 static inline
 ram_addr_t migration_bitmap_find_and_reset_dirty(MemoryRegion *mr,
                                                  ram_addr_t start)
@@ -512,6 +528,7 @@ static int ram_save_block(QEMUFile *f, bool last_stage)
         } else {
             int ret;
             uint8_t *p;
+            bool send_async = true;
             int cont = (block == last_sent_block) ?
                 RAM_SAVE_FLAG_CONTINUE : 0;
 
@@ -522,6 +539,7 @@ static int ram_save_block(QEMUFile *f, bool last_stage)
             ret = ram_control_save_page(f, block->offset,
                                offset, TARGET_PAGE_SIZE, &bytes_sent);
 
+            current_addr = block->offset + offset;
             if (ret != RAM_SAVE_CONTROL_NOT_SUPP) {
                 if (ret != RAM_SAVE_CONTROL_DELAYED) {
                     if (bytes_sent > 0) {
@@ -536,19 +554,35 @@ static int ram_save_block(QEMUFile *f, bool last_stage)
                                             RAM_SAVE_FLAG_COMPRESS);
                 qemu_put_byte(f, 0);
                 bytes_sent++;
+                /* Must let xbzrle know, otherwise a previous (now 0'd) cached
+                 * page would be stale
+                 */
+                xbzrle_cache_zero_page(current_addr);
             } else if (!ram_bulk_stage && migrate_use_xbzrle()) {
-                current_addr = block->offset + offset;
                 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
+                     */
+                    send_async = false;
                 }
             }
 
             /* XBZRLE overflow or normal page */
             if (bytes_sent == -1) {
                 bytes_sent = save_block_hdr(f, block, offset, cont, RAM_SAVE_FLAG_PAGE);
-                qemu_put_buffer_async(f, p, TARGET_PAGE_SIZE);
+                if (send_async) {
+                    qemu_put_buffer_async(f, p, TARGET_PAGE_SIZE);
+                } else {
+                    qemu_put_buffer(f, p, TARGET_PAGE_SIZE);
+                }
                 bytes_sent += TARGET_PAGE_SIZE;
                 acct_info.norm_pages++;
             }
diff --git a/include/migration/page_cache.h b/include/migration/page_cache.h
index d156f0d..2d5ce2d 100644
--- a/include/migration/page_cache.h
+++ b/include/migration/page_cache.h
@@ -66,7 +66,7 @@ uint8_t *get_cached_data(const PageCache *cache, uint64_t addr);
  * @addr: page address
  * @pdata: pointer to the page
  */
-int cache_insert(PageCache *cache, uint64_t addr, uint8_t *pdata);
+int cache_insert(PageCache *cache, uint64_t addr, const uint8_t *pdata);
 
 /**
  * cache_resize: resize the page cache. In case of size reduction the extra
diff --git a/page_cache.c b/page_cache.c
index 3ef6ee7..b033681 100644
--- a/page_cache.c
+++ b/page_cache.c
@@ -150,7 +150,7 @@ uint8_t *get_cached_data(const PageCache *cache, uint64_t addr)
     return cache_get_by_addr(cache, addr)->it_data;
 }
 
-int cache_insert(PageCache *cache, uint64_t addr, uint8_t *pdata)
+int cache_insert(PageCache *cache, uint64_t addr, const uint8_t *pdata)
 {
 
     CacheItem *it = NULL;
-- 
1.8.5.3

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [Qemu-devel] [PATCH] Fix two XBZRLE corruption issues
  2014-02-13 19:44 [Qemu-devel] [PATCH] Fix two XBZRLE corruption issues Dr. David Alan Gilbert (git)
@ 2014-02-14  9:32 ` Gonglei (Arei)
  2014-02-14  9:35   ` Dr. David Alan Gilbert
  2014-02-14  9:52 ` Orit Wasserman
  2014-02-18 16:55 ` Juan Quintela
  2 siblings, 1 reply; 7+ messages in thread
From: Gonglei (Arei) @ 2014-02-14  9:32 UTC (permalink / raw)
  To: Dr. David Alan Gilbert (git), qemu-devel; +Cc: owasserm, quintela






Best regards,
-Gonglei


> -----Original Message-----
> From: qemu-devel-bounces+arei.gonglei=huawei.com@nongnu.org
> [mailto:qemu-devel-bounces+arei.gonglei=huawei.com@nongnu.org] On
> Behalf Of Dr. David Alan Gilbert (git)
> Sent: Friday, February 14, 2014 3:45 AM
> To: qemu-devel@nongnu.org
> Cc: owasserm@redhat.com; quintela@redhat.com
> Subject: [Qemu-devel] [PATCH] Fix two XBZRLE corruption issues
> 
> From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
> 
> Push zero'd pages into the XBZRLE cache
>     A page that was cached by XBZRLE, zero'd and then XBZRLE'd again
>     was being compared against a stale cache value
> 
> Don't use 'qemu_put_buffer_async' to put pages from the XBZRLE cache
>     Since the cache might change before the data hits the wire
> 
> Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
> ---
>  arch_init.c                    | 64
> ++++++++++++++++++++++++++++++++----------
>  include/migration/page_cache.h |  2 +-
>  page_cache.c                   |  2 +-
>  3 files changed, 51 insertions(+), 17 deletions(-)
> 
> diff --git a/arch_init.c b/arch_init.c
> index 80574a0..fe17279 100644
> --- a/arch_init.c
> +++ b/arch_init.c
> @@ -122,7 +122,6 @@ static void check_guest_throttling(void);
>  #define RAM_SAVE_FLAG_XBZRLE   0x40
>  /* 0x80 is reserved in migration.h start with 0x100 next */
> 
> -
>  static struct defconfig_file {
>      const char *filename;
>      /* Indicates it is an user config file (disabled by -no-user-config) */
> @@ -133,6 +132,7 @@ static struct defconfig_file {
>      { NULL }, /* end of list */
>  };
> 
> +static const uint8_t ZERO_TARGET_PAGE[TARGET_PAGE_SIZE];
> 
>  int qemu_read_default_config_files(bool userconfig)
>  {
> @@ -273,6 +273,34 @@ static size_t save_block_hdr(QEMUFile *f, RAMBlock
> *block, ram_addr_t offset,
>      return size;
>  }
> 
> +/* This is the last block that we have visited serching for dirty pages
> + */
> +static RAMBlock *last_seen_block;
> +/* This is the last block from where we have sent data */
> +static RAMBlock *last_sent_block;
> +static ram_addr_t last_offset;
> +static unsigned long *migration_bitmap;
> +static uint64_t migration_dirty_pages;
> +static uint32_t last_version;
> +static bool ram_bulk_stage;
> +
> +/* Update the xbzrle cache to reflect a page that's been sent as all 0.
> + * The important thing is that a stale (not-yet-0'd) page be replaced
> + * by the new data.
> + * As a bonus, if the page wasn't in the cache it gets added so that
> + * when a small write is made into the 0'd page it gets XBZRLE sent
> + */
> +static void xbzrle_cache_zero_page(ram_addr_t current_addr)
> +{
> +    if (ram_bulk_stage || !migrate_use_xbzrle()) {
> +        return;
> +    }
> +
> +    /* We don't care if this fails to allocate a new cache page
> +     * as long as it updated an old one */
> +    cache_insert(XBZRLE.cache, current_addr, ZERO_TARGET_PAGE);
> +}
> +
>  #define ENCODING_FLAG_XBZRLE 0x1
> 
>  static int save_xbzrle_page(QEMUFile *f, uint8_t *current_data,
> @@ -329,18 +357,6 @@ static int save_xbzrle_page(QEMUFile *f, uint8_t
> *current_data,
>      return bytes_sent;
>  }
> 
> -
> -/* This is the last block that we have visited serching for dirty pages
> - */
> -static RAMBlock *last_seen_block;
> -/* This is the last block from where we have sent data */
> -static RAMBlock *last_sent_block;
> -static ram_addr_t last_offset;
> -static unsigned long *migration_bitmap;
> -static uint64_t migration_dirty_pages;
> -static uint32_t last_version;
> -static bool ram_bulk_stage;
> -
>  static inline
>  ram_addr_t migration_bitmap_find_and_reset_dirty(MemoryRegion *mr,
>                                                   ram_addr_t
> start)
> @@ -512,6 +528,7 @@ static int ram_save_block(QEMUFile *f, bool
> last_stage)
>          } else {
>              int ret;
>              uint8_t *p;
> +            bool send_async = true;
>              int cont = (block == last_sent_block) ?
>                  RAM_SAVE_FLAG_CONTINUE : 0;
> 
> @@ -522,6 +539,7 @@ static int ram_save_block(QEMUFile *f, bool
> last_stage)
>              ret = ram_control_save_page(f, block->offset,
>                                 offset, TARGET_PAGE_SIZE,
> &bytes_sent);
> 
> +            current_addr = block->offset + offset;
>              if (ret != RAM_SAVE_CONTROL_NOT_SUPP) {
>                  if (ret != RAM_SAVE_CONTROL_DELAYED) {
>                      if (bytes_sent > 0) {
> @@ -536,19 +554,35 @@ static int ram_save_block(QEMUFile *f, bool
> last_stage)
> 
> RAM_SAVE_FLAG_COMPRESS);
>                  qemu_put_byte(f, 0);
>                  bytes_sent++;
> +                /* Must let xbzrle know, otherwise a previous (now 0'd)
> cached
> +                 * page would be stale
> +                 */
> +                xbzrle_cache_zero_page(current_addr);
>              } else if (!ram_bulk_stage && migrate_use_xbzrle()) {
> -                current_addr = block->offset + offset;
>                  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
> +                     */
> +                    send_async = false;
>                  }
>              }
> 
>              /* XBZRLE overflow or normal page */
>              if (bytes_sent == -1) {
>                  bytes_sent = save_block_hdr(f, block, offset, cont,
> RAM_SAVE_FLAG_PAGE);
> -                qemu_put_buffer_async(f, p, TARGET_PAGE_SIZE);
> +                if (send_async) {
> +                    qemu_put_buffer_async(f, p, TARGET_PAGE_SIZE);
> +                } else {
> +                    qemu_put_buffer(f, p, TARGET_PAGE_SIZE);
> +                }
>                  bytes_sent += TARGET_PAGE_SIZE;
>                  acct_info.norm_pages++;
>              }

if a page that was cached by XBZRLE but XBZRLE overflow,qemu should send the page in the cache rather then original page.Because the original page might change .

> diff --git a/include/migration/page_cache.h b/include/migration/page_cache.h
> index d156f0d..2d5ce2d 100644
> --- a/include/migration/page_cache.h
> +++ b/include/migration/page_cache.h
> @@ -66,7 +66,7 @@ uint8_t *get_cached_data(const PageCache *cache,
> uint64_t addr);
>   * @addr: page address
>   * @pdata: pointer to the page
>   */
> -int cache_insert(PageCache *cache, uint64_t addr, uint8_t *pdata);
> +int cache_insert(PageCache *cache, uint64_t addr, const uint8_t *pdata);
> 
>  /**
>   * cache_resize: resize the page cache. In case of size reduction the extra
> diff --git a/page_cache.c b/page_cache.c
> index 3ef6ee7..b033681 100644
> --- a/page_cache.c
> +++ b/page_cache.c
> @@ -150,7 +150,7 @@ uint8_t *get_cached_data(const PageCache *cache,
> uint64_t addr)
>      return cache_get_by_addr(cache, addr)->it_data;
>  }
> 
> -int cache_insert(PageCache *cache, uint64_t addr, uint8_t *pdata)
> +int cache_insert(PageCache *cache, uint64_t addr, const uint8_t *pdata)
>  {
> 
>      CacheItem *it = NULL;
> --
> 1.8.5.3
> 


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [Qemu-devel] [PATCH] Fix two XBZRLE corruption issues
  2014-02-14  9:32 ` Gonglei (Arei)
@ 2014-02-14  9:35   ` Dr. David Alan Gilbert
  2014-02-14  9:49     ` Gonglei (Arei)
  0 siblings, 1 reply; 7+ messages in thread
From: Dr. David Alan Gilbert @ 2014-02-14  9:35 UTC (permalink / raw)
  To: Gonglei (Arei); +Cc: owasserm, qemu-devel, quintela

* Gonglei (Arei) (arei.gonglei@huawei.com) wrote:
> 
> Best regards,
> -Gonglei
> 
> 

<snip>

> >              } else if (!ram_bulk_stage && migrate_use_xbzrle()) {
> > -                current_addr = block->offset + offset;
> >                  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
> > +                     */
> > +                    send_async = false;
> >                  }
> >              }
> > 
> >              /* XBZRLE overflow or normal page */
> >              if (bytes_sent == -1) {
> >                  bytes_sent = save_block_hdr(f, block, offset, cont,
> > RAM_SAVE_FLAG_PAGE);
> > -                qemu_put_buffer_async(f, p, TARGET_PAGE_SIZE);
> > +                if (send_async) {
> > +                    qemu_put_buffer_async(f, p, TARGET_PAGE_SIZE);
> > +                } else {
> > +                    qemu_put_buffer(f, p, TARGET_PAGE_SIZE);
> > +                }
> >                  bytes_sent += TARGET_PAGE_SIZE;
> >                  acct_info.norm_pages++;
> >              }
> 
> if a page that was cached by XBZRLE but XBZRLE overflow,qemu should send the page in the cache rather then original page.Because the original page might change .

Which it already does - see the line above which is:
    p = get_cached_data(XBZRLE.cache, current_addr);

That changes the 'p' to point to the page in the cache and thus forces that
qemu_put_buffer to send the page in the cache; my patch doesn't change that,
it just stops it using the qemu_put_buffer_async so that the cache is read
immediately not at some point in the future when the cache may have changed.

Dave
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [Qemu-devel] [PATCH] Fix two XBZRLE corruption issues
  2014-02-14  9:35   ` Dr. David Alan Gilbert
@ 2014-02-14  9:49     ` Gonglei (Arei)
  0 siblings, 0 replies; 7+ messages in thread
From: Gonglei (Arei) @ 2014-02-14  9:49 UTC (permalink / raw)
  To: Dr. David Alan Gilbert; +Cc: owasserm, qemu-devel, quintela


> -----Original Message-----
> From: Dr. David Alan Gilbert [mailto:dgilbert@redhat.com]
> Sent: Friday, February 14, 2014 5:35 PM
> To: Gonglei (Arei)
> Cc: qemu-devel@nongnu.org; owasserm@redhat.com; quintela@redhat.com
> Subject: Re: [Qemu-devel] [PATCH] Fix two XBZRLE corruption issues
> 
> * Gonglei (Arei) (arei.gonglei@huawei.com) wrote:
> >
> > Best regards,
> > -Gonglei
> >
> >
> 
> <snip>
> 
> > >              } else if (!ram_bulk_stage && migrate_use_xbzrle()) {
> > > -                current_addr = block->offset + offset;
> > >                  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
> > > +                     */
> > > +                    send_async = false;
> > >                  }
> > >              }
> > >
> > >              /* XBZRLE overflow or normal page */
> > >              if (bytes_sent == -1) {
> > >                  bytes_sent = save_block_hdr(f, block, offset, cont,
> > > RAM_SAVE_FLAG_PAGE);
> > > -                qemu_put_buffer_async(f, p, TARGET_PAGE_SIZE);
> > > +                if (send_async) {
> > > +                    qemu_put_buffer_async(f, p,
> TARGET_PAGE_SIZE);
> > > +                } else {
> > > +                    qemu_put_buffer(f, p, TARGET_PAGE_SIZE);
> > > +                }
> > >                  bytes_sent += TARGET_PAGE_SIZE;
> > >                  acct_info.norm_pages++;
> > >              }
> >
> > if a page that was cached by XBZRLE but XBZRLE overflow,qemu should send
> the page in the cache rather then original page.Because the original page
> might change .
> 
> Which it already does - see the line above which is:
>     p = get_cached_data(XBZRLE.cache, current_addr);
> 
> That changes the 'p' to point to the page in the cache and thus forces that
> qemu_put_buffer to send the page in the cache; my patch doesn't change that,
> it just stops it using the qemu_put_buffer_async so that the cache is read
> immediately not at some point in the future when the cache may have
> changed.
> 
> Dave
> --
> Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
Thanks, you are right.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [Qemu-devel] [PATCH] Fix two XBZRLE corruption issues
  2014-02-13 19:44 [Qemu-devel] [PATCH] Fix two XBZRLE corruption issues Dr. David Alan Gilbert (git)
  2014-02-14  9:32 ` Gonglei (Arei)
@ 2014-02-14  9:52 ` Orit Wasserman
  2014-02-18 16:55 ` Juan Quintela
  2 siblings, 0 replies; 7+ messages in thread
From: Orit Wasserman @ 2014-02-14  9:52 UTC (permalink / raw)
  To: Dr. David Alan Gilbert (git), qemu-devel; +Cc: quintela

On 02/13/2014 09:44 PM, Dr. David Alan Gilbert (git) wrote:
> From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
>
> Push zero'd pages into the XBZRLE cache
>      A page that was cached by XBZRLE, zero'd and then XBZRLE'd again
>      was being compared against a stale cache value
>
> Don't use 'qemu_put_buffer_async' to put pages from the XBZRLE cache
>      Since the cache might change before the data hits the wire
>
> Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
> ---
>   arch_init.c                    | 64 ++++++++++++++++++++++++++++++++----------
>   include/migration/page_cache.h |  2 +-
>   page_cache.c                   |  2 +-
>   3 files changed, 51 insertions(+), 17 deletions(-)
>
> diff --git a/arch_init.c b/arch_init.c
> index 80574a0..fe17279 100644
> --- a/arch_init.c
> +++ b/arch_init.c
> @@ -122,7 +122,6 @@ static void check_guest_throttling(void);
>   #define RAM_SAVE_FLAG_XBZRLE   0x40
>   /* 0x80 is reserved in migration.h start with 0x100 next */
>
> -
>   static struct defconfig_file {
>       const char *filename;
>       /* Indicates it is an user config file (disabled by -no-user-config) */
> @@ -133,6 +132,7 @@ static struct defconfig_file {
>       { NULL }, /* end of list */
>   };
>
> +static const uint8_t ZERO_TARGET_PAGE[TARGET_PAGE_SIZE];
>
>   int qemu_read_default_config_files(bool userconfig)
>   {
> @@ -273,6 +273,34 @@ static size_t save_block_hdr(QEMUFile *f, RAMBlock *block, ram_addr_t offset,
>       return size;
>   }
>
> +/* This is the last block that we have visited serching for dirty pages
> + */
> +static RAMBlock *last_seen_block;
> +/* This is the last block from where we have sent data */
> +static RAMBlock *last_sent_block;
> +static ram_addr_t last_offset;
> +static unsigned long *migration_bitmap;
> +static uint64_t migration_dirty_pages;
> +static uint32_t last_version;
> +static bool ram_bulk_stage;
> +
> +/* Update the xbzrle cache to reflect a page that's been sent as all 0.
> + * The important thing is that a stale (not-yet-0'd) page be replaced
> + * by the new data.
> + * As a bonus, if the page wasn't in the cache it gets added so that
> + * when a small write is made into the 0'd page it gets XBZRLE sent
> + */
> +static void xbzrle_cache_zero_page(ram_addr_t current_addr)
> +{
> +    if (ram_bulk_stage || !migrate_use_xbzrle()) {
> +        return;
> +    }
> +
> +    /* We don't care if this fails to allocate a new cache page
> +     * as long as it updated an old one */
> +    cache_insert(XBZRLE.cache, current_addr, ZERO_TARGET_PAGE);
> +}
> +
>   #define ENCODING_FLAG_XBZRLE 0x1
>
>   static int save_xbzrle_page(QEMUFile *f, uint8_t *current_data,
> @@ -329,18 +357,6 @@ static int save_xbzrle_page(QEMUFile *f, uint8_t *current_data,
>       return bytes_sent;
>   }
>
> -
> -/* This is the last block that we have visited serching for dirty pages
> - */
> -static RAMBlock *last_seen_block;
> -/* This is the last block from where we have sent data */
> -static RAMBlock *last_sent_block;
> -static ram_addr_t last_offset;
> -static unsigned long *migration_bitmap;
> -static uint64_t migration_dirty_pages;
> -static uint32_t last_version;
> -static bool ram_bulk_stage;
> -
>   static inline
>   ram_addr_t migration_bitmap_find_and_reset_dirty(MemoryRegion *mr,
>                                                    ram_addr_t start)
> @@ -512,6 +528,7 @@ static int ram_save_block(QEMUFile *f, bool last_stage)
>           } else {
>               int ret;
>               uint8_t *p;
> +            bool send_async = true;
>               int cont = (block == last_sent_block) ?
>                   RAM_SAVE_FLAG_CONTINUE : 0;
>
> @@ -522,6 +539,7 @@ static int ram_save_block(QEMUFile *f, bool last_stage)
>               ret = ram_control_save_page(f, block->offset,
>                                  offset, TARGET_PAGE_SIZE, &bytes_sent);
>
> +            current_addr = block->offset + offset;
>               if (ret != RAM_SAVE_CONTROL_NOT_SUPP) {
>                   if (ret != RAM_SAVE_CONTROL_DELAYED) {
>                       if (bytes_sent > 0) {
> @@ -536,19 +554,35 @@ static int ram_save_block(QEMUFile *f, bool last_stage)
>                                               RAM_SAVE_FLAG_COMPRESS);
>                   qemu_put_byte(f, 0);
>                   bytes_sent++;
> +                /* Must let xbzrle know, otherwise a previous (now 0'd) cached
> +                 * page would be stale
> +                 */
> +                xbzrle_cache_zero_page(current_addr);
>               } else if (!ram_bulk_stage && migrate_use_xbzrle()) {
> -                current_addr = block->offset + offset;
>                   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
> +                     */
> +                    send_async = false;
>                   }
>               }
>
>               /* XBZRLE overflow or normal page */
>               if (bytes_sent == -1) {
>                   bytes_sent = save_block_hdr(f, block, offset, cont, RAM_SAVE_FLAG_PAGE);
> -                qemu_put_buffer_async(f, p, TARGET_PAGE_SIZE);
> +                if (send_async) {
> +                    qemu_put_buffer_async(f, p, TARGET_PAGE_SIZE);
> +                } else {
> +                    qemu_put_buffer(f, p, TARGET_PAGE_SIZE);
> +                }
>                   bytes_sent += TARGET_PAGE_SIZE;
>                   acct_info.norm_pages++;
>               }
> diff --git a/include/migration/page_cache.h b/include/migration/page_cache.h
> index d156f0d..2d5ce2d 100644
> --- a/include/migration/page_cache.h
> +++ b/include/migration/page_cache.h
> @@ -66,7 +66,7 @@ uint8_t *get_cached_data(const PageCache *cache, uint64_t addr);
>    * @addr: page address
>    * @pdata: pointer to the page
>    */
> -int cache_insert(PageCache *cache, uint64_t addr, uint8_t *pdata);
> +int cache_insert(PageCache *cache, uint64_t addr, const uint8_t *pdata);
>
>   /**
>    * cache_resize: resize the page cache. In case of size reduction the extra
> diff --git a/page_cache.c b/page_cache.c
> index 3ef6ee7..b033681 100644
> --- a/page_cache.c
> +++ b/page_cache.c
> @@ -150,7 +150,7 @@ uint8_t *get_cached_data(const PageCache *cache, uint64_t addr)
>       return cache_get_by_addr(cache, addr)->it_data;
>   }
>
> -int cache_insert(PageCache *cache, uint64_t addr, uint8_t *pdata)
> +int cache_insert(PageCache *cache, uint64_t addr, const uint8_t *pdata)
>   {
>
>       CacheItem *it = NULL;
>

Reviewed-by: Orit Wasserman <owasserm@redhat.com>

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [Qemu-devel] [PATCH] Fix two XBZRLE corruption issues
  2014-02-13 19:44 [Qemu-devel] [PATCH] Fix two XBZRLE corruption issues Dr. David Alan Gilbert (git)
  2014-02-14  9:32 ` Gonglei (Arei)
  2014-02-14  9:52 ` Orit Wasserman
@ 2014-02-18 16:55 ` Juan Quintela
  2014-02-18 20:35   ` Dr. David Alan Gilbert
  2 siblings, 1 reply; 7+ messages in thread
From: Juan Quintela @ 2014-02-18 16:55 UTC (permalink / raw)
  To: Dr. David Alan Gilbert (git); +Cc: owasserm, qemu-devel

"Dr. David Alan Gilbert (git)" <dgilbert@redhat.com> wrote:
> From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
>
> Push zero'd pages into the XBZRLE cache
>     A page that was cached by XBZRLE, zero'd and then XBZRLE'd again
>     was being compared against a stale cache value
>
> Don't use 'qemu_put_buffer_async' to put pages from the XBZRLE cache
>     Since the cache might change before the data hits the wire
>
> Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
> ---
>  arch_init.c                    | 64 ++++++++++++++++++++++++++++++++----------
>  include/migration/page_cache.h |  2 +-
>  page_cache.c                   |  2 +-
>  3 files changed, 51 insertions(+), 17 deletions(-)
>
> diff --git a/arch_init.c b/arch_init.c
> index 80574a0..fe17279 100644
> --- a/arch_init.c
> +++ b/arch_init.c
> @@ -122,7 +122,6 @@ static void check_guest_throttling(void);
>  #define RAM_SAVE_FLAG_XBZRLE   0x40
>  /* 0x80 is reserved in migration.h start with 0x100 next */
>  
> -
>  static struct defconfig_file {
>      const char *filename;
>      /* Indicates it is an user config file (disabled by -no-user-config) */
> @@ -133,6 +132,7 @@ static struct defconfig_file {
>      { NULL }, /* end of list */
>  };
>  
> +static const uint8_t ZERO_TARGET_PAGE[TARGET_PAGE_SIZE];
>  
>  int qemu_read_default_config_files(bool userconfig)
>  {
> @@ -273,6 +273,34 @@ static size_t save_block_hdr(QEMUFile *f, RAMBlock *block, ram_addr_t offset,
>      return size;
>  }
>  
> +/* This is the last block that we have visited serching for dirty pages
> + */
> +static RAMBlock *last_seen_block;
> +/* This is the last block from where we have sent data */
> +static RAMBlock *last_sent_block;
> +static ram_addr_t last_offset;
> +static unsigned long *migration_bitmap;
> +static uint64_t migration_dirty_pages;
> +static uint32_t last_version;
> +static bool ram_bulk_stage;
> +
> +/* Update the xbzrle cache to reflect a page that's been sent as all 0.
> + * The important thing is that a stale (not-yet-0'd) page be replaced
> + * by the new data.
> + * As a bonus, if the page wasn't in the cache it gets added so that
> + * when a small write is made into the 0'd page it gets XBZRLE sent
> + */
> +static void xbzrle_cache_zero_page(ram_addr_t current_addr)
> +{
> +    if (ram_bulk_stage || !migrate_use_xbzrle()) {
> +        return;
> +    }
> +
> +    /* We don't care if this fails to allocate a new cache page
> +     * as long as it updated an old one */
> +    cache_insert(XBZRLE.cache, current_addr, ZERO_TARGET_PAGE);
> +}
> +

Can we use a cache_insert_zero() page to avoid the copy?

Right now, we are inserting a zero page on the cache

>  #define ENCODING_FLAG_XBZRLE 0x1
>  
>  static int save_xbzrle_page(QEMUFile *f, uint8_t *current_data,
> @@ -329,18 +357,6 @@ static int save_xbzrle_page(QEMUFile *f, uint8_t *current_data,
>      return bytes_sent;
>  }
>  
> -
> -/* This is the last block that we have visited serching for dirty pages
> - */
> -static RAMBlock *last_seen_block;
> -/* This is the last block from where we have sent data */
> -static RAMBlock *last_sent_block;
> -static ram_addr_t last_offset;
> -static unsigned long *migration_bitmap;
> -static uint64_t migration_dirty_pages;
> -static uint32_t last_version;
> -static bool ram_bulk_stage;
> -
>  static inline
>  ram_addr_t migration_bitmap_find_and_reset_dirty(MemoryRegion *mr,
>                                                   ram_addr_t start)
> @@ -512,6 +528,7 @@ static int ram_save_block(QEMUFile *f, bool last_stage)
>          } else {
>              int ret;
>              uint8_t *p;
> +            bool send_async = true;
>              int cont = (block == last_sent_block) ?
>                  RAM_SAVE_FLAG_CONTINUE : 0;
>  
> @@ -522,6 +539,7 @@ static int ram_save_block(QEMUFile *f, bool last_stage)
>              ret = ram_control_save_page(f, block->offset,
>                                 offset, TARGET_PAGE_SIZE, &bytes_sent);
>  
> +            current_addr = block->offset + offset;
>              if (ret != RAM_SAVE_CONTROL_NOT_SUPP) {
>                  if (ret != RAM_SAVE_CONTROL_DELAYED) {
>                      if (bytes_sent > 0) {
> @@ -536,19 +554,35 @@ static int ram_save_block(QEMUFile *f, bool last_stage)
>                                              RAM_SAVE_FLAG_COMPRESS);
>                  qemu_put_byte(f, 0);
>                  bytes_sent++;
> +                /* Must let xbzrle know, otherwise a previous (now 0'd) cached
> +                 * page would be stale
> +                 */
> +                xbzrle_cache_zero_page(current_addr);

Shouldn't it be easy to just create a:

cache_forget(current_addr)

function and call it a day?

I told that because if there is a different page on that slot on the
cache, we are dropping it for no help?

>              } else if (!ram_bulk_stage && migrate_use_xbzrle()) {
> -                current_addr = block->offset + offset;
>                  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.
> +                     */

The problem here wasn't that we weren't forgotten it?  If we forgot it,
data is not stalled to start with?


And yes, I understand that if next change to the page is just writting a
few bytes it is better to know that the page has been sent as all
zeros.  But if we don't resent the page, we have just dropped one item
in the cache for no good reason.

Ideas?


>From now on, this is about xbzrle, not about previous page.

Further thought of the day: perhaps it is a good idea when sending a
page to check if it is shorter from a zero page or from the previous
page?

And once that we are looking into this:

In function save_xbzrle_page()

    } else if (encoded_len == -1) {
        DPRINTF("Overflow\n");
        acct_info.xbzrle_overflows++;
        /* update data in the cache */
        memcpy(prev_cached_page, current_data, TARGET_PAGE_SIZE);
                                 ^^^^^^^^^^^^

        return -1;
    }

Why aren't we using XBZRLE.current_buf there?



>                      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
> +                     */
> +                    send_async = false;
>                  }
>              }
>  
>              /* XBZRLE overflow or normal page */
>              if (bytes_sent == -1) {
>                  bytes_sent = save_block_hdr(f, block, offset, cont, RAM_SAVE_FLAG_PAGE);
> -                qemu_put_buffer_async(f, p, TARGET_PAGE_SIZE);
> +                if (send_async) {
> +                    qemu_put_buffer_async(f, p, TARGET_PAGE_SIZE);
> +                } else {
> +                    qemu_put_buffer(f, p, TARGET_PAGE_SIZE);
> +                }
>                  bytes_sent += TARGET_PAGE_SIZE;
>                  acct_info.norm_pages++;
>              }
> diff --git a/include/migration/page_cache.h b/include/migration/page_cache.h
> index d156f0d..2d5ce2d 100644
> --- a/include/migration/page_cache.h
> +++ b/include/migration/page_cache.h
> @@ -66,7 +66,7 @@ uint8_t *get_cached_data(const PageCache *cache, uint64_t addr);
>   * @addr: page address
>   * @pdata: pointer to the page
>   */
> -int cache_insert(PageCache *cache, uint64_t addr, uint8_t *pdata);
> +int cache_insert(PageCache *cache, uint64_t addr, const uint8_t *pdata);
>  
>  /**
>   * cache_resize: resize the page cache. In case of size reduction the extra
> diff --git a/page_cache.c b/page_cache.c
> index 3ef6ee7..b033681 100644
> --- a/page_cache.c
> +++ b/page_cache.c
> @@ -150,7 +150,7 @@ uint8_t *get_cached_data(const PageCache *cache, uint64_t addr)
>      return cache_get_by_addr(cache, addr)->it_data;
>  }
>  
> -int cache_insert(PageCache *cache, uint64_t addr, uint8_t *pdata)
> +int cache_insert(PageCache *cache, uint64_t addr, const uint8_t *pdata)
>  {
>  
>      CacheItem *it = NULL;

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [Qemu-devel] [PATCH] Fix two XBZRLE corruption issues
  2014-02-18 16:55 ` Juan Quintela
@ 2014-02-18 20:35   ` Dr. David Alan Gilbert
  0 siblings, 0 replies; 7+ messages in thread
From: Dr. David Alan Gilbert @ 2014-02-18 20:35 UTC (permalink / raw)
  To: Juan Quintela; +Cc: owasserm, qemu-devel

* Juan Quintela (quintela@redhat.com) wrote:
> "Dr. David Alan Gilbert (git)" <dgilbert@redhat.com> wrote:
> > From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
> >
> > Push zero'd pages into the XBZRLE cache
> >     A page that was cached by XBZRLE, zero'd and then XBZRLE'd again
> >     was being compared against a stale cache value
> >
> > Don't use 'qemu_put_buffer_async' to put pages from the XBZRLE cache
> >     Since the cache might change before the data hits the wire
> >
> > Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
> > ---
> >  arch_init.c                    | 64 ++++++++++++++++++++++++++++++++----------
> >  include/migration/page_cache.h |  2 +-
> >  page_cache.c                   |  2 +-
> >  3 files changed, 51 insertions(+), 17 deletions(-)
> >
> > diff --git a/arch_init.c b/arch_init.c
> > index 80574a0..fe17279 100644
> > --- a/arch_init.c
> > +++ b/arch_init.c
> > @@ -122,7 +122,6 @@ static void check_guest_throttling(void);
> >  #define RAM_SAVE_FLAG_XBZRLE   0x40
> >  /* 0x80 is reserved in migration.h start with 0x100 next */
> >  
> > -
> >  static struct defconfig_file {
> >      const char *filename;
> >      /* Indicates it is an user config file (disabled by -no-user-config) */
> > @@ -133,6 +132,7 @@ static struct defconfig_file {
> >      { NULL }, /* end of list */
> >  };
> >  
> > +static const uint8_t ZERO_TARGET_PAGE[TARGET_PAGE_SIZE];
> >  
> >  int qemu_read_default_config_files(bool userconfig)
> >  {
> > @@ -273,6 +273,34 @@ static size_t save_block_hdr(QEMUFile *f, RAMBlock *block, ram_addr_t offset,
> >      return size;
> >  }
> >  
> > +/* This is the last block that we have visited serching for dirty pages
> > + */
> > +static RAMBlock *last_seen_block;
> > +/* This is the last block from where we have sent data */
> > +static RAMBlock *last_sent_block;
> > +static ram_addr_t last_offset;
> > +static unsigned long *migration_bitmap;
> > +static uint64_t migration_dirty_pages;
> > +static uint32_t last_version;
> > +static bool ram_bulk_stage;
> > +
> > +/* Update the xbzrle cache to reflect a page that's been sent as all 0.
> > + * The important thing is that a stale (not-yet-0'd) page be replaced
> > + * by the new data.
> > + * As a bonus, if the page wasn't in the cache it gets added so that
> > + * when a small write is made into the 0'd page it gets XBZRLE sent
> > + */
> > +static void xbzrle_cache_zero_page(ram_addr_t current_addr)
> > +{
> > +    if (ram_bulk_stage || !migrate_use_xbzrle()) {
> > +        return;
> > +    }
> > +
> > +    /* We don't care if this fails to allocate a new cache page
> > +     * as long as it updated an old one */
> > +    cache_insert(XBZRLE.cache, current_addr, ZERO_TARGET_PAGE);
> > +}
> > +
> 
> Can we use a cache_insert_zero() page to avoid the copy?
> 
> Right now, we are inserting a zero page on the cache

Yes, I think a 'cache_insert_zero' would be a great idea;
I don't see one in the code base yet though, and I thought
it would be overkill to add it for a fix to a corruption bug.

> >  #define ENCODING_FLAG_XBZRLE 0x1
> >  
> >  static int save_xbzrle_page(QEMUFile *f, uint8_t *current_data,
> > @@ -329,18 +357,6 @@ static int save_xbzrle_page(QEMUFile *f, uint8_t *current_data,
> >      return bytes_sent;
> >  }
> >  
> > -
> > -/* This is the last block that we have visited serching for dirty pages
> > - */
> > -static RAMBlock *last_seen_block;
> > -/* This is the last block from where we have sent data */
> > -static RAMBlock *last_sent_block;
> > -static ram_addr_t last_offset;
> > -static unsigned long *migration_bitmap;
> > -static uint64_t migration_dirty_pages;
> > -static uint32_t last_version;
> > -static bool ram_bulk_stage;
> > -
> >  static inline
> >  ram_addr_t migration_bitmap_find_and_reset_dirty(MemoryRegion *mr,
> >                                                   ram_addr_t start)
> > @@ -512,6 +528,7 @@ static int ram_save_block(QEMUFile *f, bool last_stage)
> >          } else {
> >              int ret;
> >              uint8_t *p;
> > +            bool send_async = true;
> >              int cont = (block == last_sent_block) ?
> >                  RAM_SAVE_FLAG_CONTINUE : 0;
> >  
> > @@ -522,6 +539,7 @@ static int ram_save_block(QEMUFile *f, bool last_stage)
> >              ret = ram_control_save_page(f, block->offset,
> >                                 offset, TARGET_PAGE_SIZE, &bytes_sent);
> >  
> > +            current_addr = block->offset + offset;
> >              if (ret != RAM_SAVE_CONTROL_NOT_SUPP) {
> >                  if (ret != RAM_SAVE_CONTROL_DELAYED) {
> >                      if (bytes_sent > 0) {
> > @@ -536,19 +554,35 @@ static int ram_save_block(QEMUFile *f, bool last_stage)
> >                                              RAM_SAVE_FLAG_COMPRESS);
> >                  qemu_put_byte(f, 0);
> >                  bytes_sent++;
> > +                /* Must let xbzrle know, otherwise a previous (now 0'd) cached
> > +                 * page would be stale
> > +                 */
> > +                xbzrle_cache_zero_page(current_addr);
> 
> Shouldn't it be easy to just create a:
> 
> cache_forget(current_addr)
> 
> function and call it a day?
> 
> I told that because if there is a different page on that slot on the
> cache, we are dropping it for no help?

Right, so I have two version of the code for xbzrle_cache_zero_page,
one that drops it, one that inserts the zero page - both work, but
I've not done any tests to see which has the best performance results.
Discussions with Orit came down to preferring this route, but I'm not
particularly tied to this way.

> >              } else if (!ram_bulk_stage && migrate_use_xbzrle()) {
> > -                current_addr = block->offset + offset;
> >                  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.
> > +                     */
> 
> The problem here wasn't that we weren't forgotten it?  If we forgot it,
> data is not stalled to start with?

This comment was just explaining why we're doing the cache fetch at
this point, since it wasn't obvious to me when I read the code, and
relates to the conditional async send, and not the zeroing.

> And yes, I understand that if next change to the page is just writting a
> few bytes it is better to know that the page has been sent as all
> zeros.  But if we don't resent the page, we have just dropped one item
> in the cache for no good reason.
> 
> Ideas?

If you think that inserting the zero page would be particularly
bad, I'm happy to send the version that just forgets the old page;
although I think it would be good then to try and get some performance
results to validate which is best.

We should initially get something in that fixes it so it doesn't
send stuff that's corrupt.

> From now on, this is about xbzrle, not about previous page.
> 
> Further thought of the day: perhaps it is a good idea when sending a
> page to check if it is shorter from a zero page or from the previous
> page?
> 
> And once that we are looking into this:
> 
> In function save_xbzrle_page()
> 
>     } else if (encoded_len == -1) {
>         DPRINTF("Overflow\n");
>         acct_info.xbzrle_overflows++;
>         /* update data in the cache */
>         memcpy(prev_cached_page, current_data, TARGET_PAGE_SIZE);
>                                  ^^^^^^^^^^^^
> 
>         return -1;
>     }
> 
> Why aren't we using XBZRLE.current_buf there?

Hmm - I'm not sure it matters, we could do, the code at current_data
was copied into current_data a few lines before, so current_data could
be a bit newer if the CPU is still writing to it, and thus using the
latest version has the lowest chance of having to send an update later;
however I don't think it effects correctness since anything
later is compared to what we copy into cache at this point.

Dave

> 
> >                      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
> > +                     */
> > +                    send_async = false;
> >                  }
> >              }
> >  
> >              /* XBZRLE overflow or normal page */
> >              if (bytes_sent == -1) {
> >                  bytes_sent = save_block_hdr(f, block, offset, cont, RAM_SAVE_FLAG_PAGE);
> > -                qemu_put_buffer_async(f, p, TARGET_PAGE_SIZE);
> > +                if (send_async) {
> > +                    qemu_put_buffer_async(f, p, TARGET_PAGE_SIZE);
> > +                } else {
> > +                    qemu_put_buffer(f, p, TARGET_PAGE_SIZE);
> > +                }
> >                  bytes_sent += TARGET_PAGE_SIZE;
> >                  acct_info.norm_pages++;
> >              }
> > diff --git a/include/migration/page_cache.h b/include/migration/page_cache.h
> > index d156f0d..2d5ce2d 100644
> > --- a/include/migration/page_cache.h
> > +++ b/include/migration/page_cache.h
> > @@ -66,7 +66,7 @@ uint8_t *get_cached_data(const PageCache *cache, uint64_t addr);
> >   * @addr: page address
> >   * @pdata: pointer to the page
> >   */
> > -int cache_insert(PageCache *cache, uint64_t addr, uint8_t *pdata);
> > +int cache_insert(PageCache *cache, uint64_t addr, const uint8_t *pdata);
> >  
> >  /**
> >   * cache_resize: resize the page cache. In case of size reduction the extra
> > diff --git a/page_cache.c b/page_cache.c
> > index 3ef6ee7..b033681 100644
> > --- a/page_cache.c
> > +++ b/page_cache.c
> > @@ -150,7 +150,7 @@ uint8_t *get_cached_data(const PageCache *cache, uint64_t addr)
> >      return cache_get_by_addr(cache, addr)->it_data;
> >  }
> >  
> > -int cache_insert(PageCache *cache, uint64_t addr, uint8_t *pdata)
> > +int cache_insert(PageCache *cache, uint64_t addr, const uint8_t *pdata)
> >  {
> >  
> >      CacheItem *it = NULL;
> 
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2014-02-18 20:35 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-02-13 19:44 [Qemu-devel] [PATCH] Fix two XBZRLE corruption issues Dr. David Alan Gilbert (git)
2014-02-14  9:32 ` Gonglei (Arei)
2014-02-14  9:35   ` Dr. David Alan Gilbert
2014-02-14  9:49     ` Gonglei (Arei)
2014-02-14  9:52 ` Orit Wasserman
2014-02-18 16:55 ` Juan Quintela
2014-02-18 20:35   ` Dr. David Alan Gilbert

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.