All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Gonglei (Arei)" <arei.gonglei@huawei.com>
To: "Dr. David Alan Gilbert (git)" <dgilbert@redhat.com>,
	"qemu-devel@nongnu.org" <qemu-devel@nongnu.org>
Cc: "owasserm@redhat.com" <owasserm@redhat.com>,
	"quintela@redhat.com" <quintela@redhat.com>
Subject: Re: [Qemu-devel] [PATCH] Fix two XBZRLE corruption issues
Date: Fri, 14 Feb 2014 09:32:17 +0000	[thread overview]
Message-ID: <33183CC9F5247A488A2544077AF19020815C26F8@SZXEMA503-MBS.china.huawei.com> (raw)
In-Reply-To: <1392320685-20609-1-git-send-email-dgilbert@redhat.com>






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
> 


  reply	other threads:[~2014-02-14  9:32 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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) [this message]
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

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=33183CC9F5247A488A2544077AF19020815C26F8@SZXEMA503-MBS.china.huawei.com \
    --to=arei.gonglei@huawei.com \
    --cc=dgilbert@redhat.com \
    --cc=owasserm@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=quintela@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.