All of lore.kernel.org
 help / color / mirror / Atom feed
From: Orit Wasserman <owasserm@redhat.com>
To: Juan Quintela <quintela@redhat.com>
Cc: qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH 08/12] savevm: split save_live into stage2 and stage3
Date: Mon, 02 Jul 2012 14:57:28 +0300	[thread overview]
Message-ID: <4FF18CA8.7090804@redhat.com> (raw)
In-Reply-To: <d1e17271bb9fdc52dbd0b591e471b096aca2e721.1340910651.git.quintela@redhat.com>

On 06/28/2012 10:22 PM, Juan Quintela wrote:
> We split it into 2 functions, foo_live_iterate, and foo_live_complete.
> At this point, we only remove the bits that are for the other stage,
> functionally this is equivalent to previous code.
> 
> Signed-off-by: Juan Quintela <quintela@redhat.com>
> ---
>  arch_init.c       |   71 +++++++++++++++++++++++++++++---------
>  block-migration.c |   99 ++++++++++++++++++++++++++++++++---------------------
>  savevm.c          |   10 +++---
>  vmstate.h         |    3 +-
>  4 files changed, 121 insertions(+), 62 deletions(-)
> 
> diff --git a/arch_init.c b/arch_init.c
> index b296e17..d5d7a78 100644
> --- a/arch_init.c
> +++ b/arch_init.c
> @@ -373,12 +373,13 @@ static int ram_save_setup(QEMUFile *f, void *opaque)
>      return 0;
>  }
> 
> -static int ram_save_live(QEMUFile *f, int stage, void *opaque)
> +static int ram_save_iterate(QEMUFile *f, void *opaque)
>  {
>      uint64_t bytes_transferred_last;
>      double bwidth = 0;
>      int ret;
>      int i;
> +    uint64_t expected_time;
> 
>      memory_global_sync_dirty_bitmap(get_system_memory());
> 
> @@ -422,28 +423,63 @@ static int ram_save_live(QEMUFile *f, int stage, void *opaque)
>          bwidth = 0.000001;
>      }
> 
> -    /* try transferring iterative blocks of memory */
> -    if (stage == 3) {
> -        int bytes_sent;
> +    qemu_put_be64(f, RAM_SAVE_FLAG_EOS);
> +
> +    expected_time = ram_save_remaining() * TARGET_PAGE_SIZE / bwidth;
> +
> +    DPRINTF("ram_save_live: expected(%ld) <= max(%ld)?\n", expected_time,
> +            migrate_max_downtime());
> +
> +    return expected_time <= migrate_max_downtime();
> +}
> +
> +static int ram_save_complete(QEMUFile *f, void *opaque)
> +{
> +    double bwidth = 0;
> +    int ret;
> +    int i;
> +    int bytes_sent;
> 
> -        /* flush all remaining blocks regardless of rate limiting */
> -        while ((bytes_sent = ram_save_block(f)) != 0) {
> -            bytes_transferred += bytes_sent;
> +    memory_global_sync_dirty_bitmap(get_system_memory());
> +
> +    bwidth = qemu_get_clock_ns(rt_clock);
> +
> +    i = 0;
> +    while ((ret = qemu_file_rate_limit(f)) == 0) {
> +        bytes_sent = ram_save_block(f);
> +        bytes_transferred += bytes_sent;
> +        if (bytes_sent == 0) { /* no more blocks */
> +            break;
> +        }
> +        /* we want to check in the 1st loop, just in case it was the 1st time
> +           and we had to sync the dirty bitmap.
> +           qemu_get_clock_ns() is a bit expensive, so we only check each some
> +           iterations
> +        */
> +        if ((i & 63) == 0) {
> +            uint64_t t1 = (qemu_get_clock_ns(rt_clock) - bwidth) / 1000000;
> +            if (t1 > MAX_WAIT) {
> +                DPRINTF("big wait: %ld milliseconds, %d iterations\n", t1, i);
> +                break;
> +            }
>          }
> -        memory_global_dirty_log_stop();
> +        i++;
>      }
> 
> -    qemu_put_be64(f, RAM_SAVE_FLAG_EOS);
> -
> -    if (stage == 2) {
> -        uint64_t expected_time;
> -        expected_time = ram_save_remaining() * TARGET_PAGE_SIZE / bwidth;
> +    if (ret < 0) {
> +        return ret;
> +    }
> 
> -        DPRINTF("ram_save_live: expected(%ld) <= max(%ld)?\n", expected_time,
> -                migrate_max_downtime());
> +    /* try transferring iterative blocks of memory */
> 
> -        return expected_time <= migrate_max_downtime();
> +    /* flush all remaining blocks regardless of rate limiting */
> +    while ((bytes_sent = ram_save_block(f)) != 0) {
> +        bytes_transferred += bytes_sent;
>      }
> +    memory_global_dirty_log_stop();
> +
> +    qemu_put_be64(f, RAM_SAVE_FLAG_EOS);
> +
>      return 0;
>  }
> 
> @@ -576,7 +612,8 @@ done:
> 
>  SaveVMHandlers savevm_ram_handlers = {
>      .save_live_setup = ram_save_setup,
> -    .save_live_state = ram_save_live,
> +    .save_live_iterate = ram_save_iterate,
> +    .save_live_complete = ram_save_complete,
>      .load_state = ram_load,
>      .cancel = ram_migration_cancel,
>  };
> diff --git a/block-migration.c b/block-migration.c
> index fc3d1f4..7def8ab 100644
> --- a/block-migration.c
> +++ b/block-migration.c
> @@ -568,12 +568,12 @@ static int block_save_setup(QEMUFile *f, void *opaque)
>      return 0;
>  }
> 
> -static int block_save_live(QEMUFile *f, int stage, void *opaque)
> +static int block_save_iterate(QEMUFile *f, void *opaque)
>  {
>      int ret;
> 
> -    DPRINTF("Enter save live stage %d submitted %d transferred %d\n",
> -            stage, block_mig_state.submitted, block_mig_state.transferred);
> +    DPRINTF("Enter save live iterate submitted %d transferred %d\n",
> +            block_mig_state.submitted, block_mig_state.transferred);
> 
>      flush_blks(f);
> 
> @@ -585,56 +585,76 @@ static int block_save_live(QEMUFile *f, int stage, void *opaque)
> 
>      blk_mig_reset_dirty_cursor();
> 
> -    if (stage == 2) {
> -        /* control the rate of transfer */
> -        while ((block_mig_state.submitted +
> -                block_mig_state.read_done) * BLOCK_SIZE <
> -               qemu_file_get_rate_limit(f)) {
> -            if (block_mig_state.bulk_completed == 0) {
> -                /* first finish the bulk phase */
> -                if (blk_mig_save_bulked_block(f) == 0) {
> -                    /* finished saving bulk on all devices */
> -                    block_mig_state.bulk_completed = 1;
> -                }
> -            } else {
> -                if (blk_mig_save_dirty_block(f, 1) == 0) {
> -                    /* no more dirty blocks */
> -                    break;
> -                }
> +    /* control the rate of transfer */
> +    while ((block_mig_state.submitted +
> +            block_mig_state.read_done) * BLOCK_SIZE <
> +           qemu_file_get_rate_limit(f)) {
> +        if (block_mig_state.bulk_completed == 0) {
> +            /* first finish the bulk phase */
> +            if (blk_mig_save_bulked_block(f) == 0) {
> +                /* finished saving bulk on all devices */
> +                block_mig_state.bulk_completed = 1;
> +            }
> +        } else {
> +            if (blk_mig_save_dirty_block(f, 1) == 0) {
> +                /* no more dirty blocks */
> +                break;
>              }
>          }
> +    }
> 
> -        flush_blks(f);
> +    flush_blks(f);
> 
> -        ret = qemu_file_get_error(f);
> -        if (ret) {
> -            blk_mig_cleanup();
> -            return ret;
> -        }
> +    ret = qemu_file_get_error(f);
> +    if (ret) {
> +        blk_mig_cleanup();
> +        return ret;
>      }
> 
> -    if (stage == 3) {
> -        /* we know for sure that save bulk is completed and
> -           all async read completed */
> -        assert(block_mig_state.submitted == 0);
> +    qemu_put_be64(f, BLK_MIG_FLAG_EOS);
> +
> +    return is_stage2_completed();
> +}
> +
> +static int block_save_complete(QEMUFile *f, void *opaque)
> +{
> +    int ret;
> +
> +    DPRINTF("Enter save live complete submitted %d transferred %d\n",
> +            block_mig_state.submitted, block_mig_state.transferred);
> +
> +    flush_blks(f);
> 
> -        while (blk_mig_save_dirty_block(f, 0) != 0);
> +    ret = qemu_file_get_error(f);
> +    if (ret) {
>          blk_mig_cleanup();
> +        return ret;
> +    }
> 
> -        /* report completion */
> -        qemu_put_be64(f, (100 << BDRV_SECTOR_BITS) | BLK_MIG_FLAG_PROGRESS);
> +    blk_mig_reset_dirty_cursor();
> 
> -        ret = qemu_file_get_error(f);
> -        if (ret) {
> -            return ret;
> -        }
> +    /* we know for sure that save bulk is completed and
> +       all async read completed */
> +    assert(block_mig_state.submitted == 0);
> +
> +    while (blk_mig_save_dirty_block(f, 0) != 0) {
> +        /* Do nothing */
> +    }
> +    blk_mig_cleanup();
> +
> +    /* report completion */
> +    qemu_put_be64(f, (100 << BDRV_SECTOR_BITS) | BLK_MIG_FLAG_PROGRESS);
> 
> -        DPRINTF("Block migration completed\n");
> +    ret = qemu_file_get_error(f);
> +    if (ret) {
> +        return ret;
>      }
> 
> +    DPRINTF("Block migration completed\n");
> +
>      qemu_put_be64(f, BLK_MIG_FLAG_EOS);
> 
> -    return ((stage == 2) && is_stage2_completed());
> +    return 0;
>  }
> 
>  static int block_load(QEMUFile *f, void *opaque, int version_id)
> @@ -731,7 +751,8 @@ static bool block_is_active(void *opaque)
>  SaveVMHandlers savevm_block_handlers = {
>      .set_params = block_set_params,
>      .save_live_setup = block_save_setup,
> -    .save_live_state = block_save_live,
> +    .save_live_iterate = block_save_iterate,
> +    .save_live_complete = block_save_complete,
>      .load_state = block_load,
>      .cancel = block_migration_cancel,
>      .is_active = block_is_active,
> diff --git a/savevm.c b/savevm.c
> index 0b80a94..6e82b2d 100644
> --- a/savevm.c
> +++ b/savevm.c
> @@ -1236,7 +1236,7 @@ int register_savevm_live(DeviceState *dev,
>      se->vmsd = NULL;
>      se->no_migrate = 0;
>      /* if this is a live_savem then set is_ram */
> -    if (ops->save_live_state != NULL) {
> +    if (ops->save_live_setup != NULL) {
>          se->is_ram = 1;
>      }
> 
> @@ -1620,7 +1620,7 @@ int qemu_savevm_state_iterate(QEMUFile *f)
>      int ret = 1;
> 
>      QTAILQ_FOREACH(se, &savevm_handlers, entry) {
> -        if (!se->ops || !se->ops->save_live_state) {
> +        if (!se->ops || !se->ops->save_live_iterate) {
>              continue;
>          }
>          if (se->ops && se->ops->is_active) {
> @@ -1636,7 +1636,7 @@ int qemu_savevm_state_iterate(QEMUFile *f)
>          qemu_put_byte(f, QEMU_VM_SECTION_PART);
>          qemu_put_be32(f, se->section_id);
> 
> -        ret = se->ops->save_live_state(f, QEMU_VM_SECTION_PART, se->opaque);
> +        ret = se->ops->save_live_iterate(f, se->opaque);
>          trace_savevm_section_end(se->section_id);
> 
>          if (ret <= 0) {
> @@ -1665,7 +1665,7 @@ int qemu_savevm_state_complete(QEMUFile *f)
>      cpu_synchronize_all_states();
> 
>      QTAILQ_FOREACH(se, &savevm_handlers, entry) {
> -        if (!se->ops || !se->ops->save_live_state) {
> +        if (!se->ops || !se->ops->save_live_complete) {
>              continue;
>          }
>          if (se->ops && se->ops->is_active) {
> @@ -1678,7 +1678,7 @@ int qemu_savevm_state_complete(QEMUFile *f)
>          qemu_put_byte(f, QEMU_VM_SECTION_END);
>          qemu_put_be32(f, se->section_id);
> 
> -        ret = se->ops->save_live_state(f, QEMU_VM_SECTION_END, se->opaque);
> +        ret = se->ops->save_live_complete(f, se->opaque);
>          trace_savevm_section_end(se->section_id);
>          if (ret < 0) {
>              return ret;
> diff --git a/vmstate.h b/vmstate.h
> index 049f2b7..5bd2b76 100644
> --- a/vmstate.h
> +++ b/vmstate.h
> @@ -33,7 +33,8 @@ typedef struct SaveVMHandlers {
>      void (*set_params)(const MigrationParams *params, void * opaque);
>      SaveStateHandler *save_state;
>      int (*save_live_setup)(QEMUFile *f, void *opaque);
> -    int (*save_live_state)(QEMUFile *f, int stage, void *opaque);
> +    int (*save_live_iterate)(QEMUFile *f, void *opaque);
> +    int (*save_live_complete)(QEMUFile *f, void *opaque);
>      void (*cancel)(void *opaque);
>      LoadStateHandler *load_state;
>      bool (*is_active)(void *opaque);
> 
Reviewed-by: Orit Wasserman <owasserm@redhat.com>

  parent reply	other threads:[~2012-07-02 11:57 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <cover.1340910651.git.quintela@redhat.com>
     [not found] ` <39651e275488caec46861cb5b11ba1c7961a429c.1340910651.git.quintela@redhat.com>
2012-07-01  8:05   ` [Qemu-devel] [PATCH 01/12] savevm: Use a struct to pass all handlers Orit Wasserman
     [not found]   ` <4FEF3843.1000907@weilnetz.de>
2012-07-01 10:16     ` [Qemu-devel] Bad mail header? Juan Quintela
2012-07-01 10:56       ` Peter Maydell
2012-07-13  7:26         ` Juan Quintela
     [not found] ` <620debbcb9bc99dc6db54d87a8683efbc00c2b66.1340910651.git.quintela@redhat.com>
2012-07-01  8:19   ` [Qemu-devel] [PATCH 02/12] savevm: Live migration handlers register the struct directly Orit Wasserman
2012-07-01 10:20     ` Juan Quintela
2012-07-01 11:24       ` Orit Wasserman
2012-07-11 17:01         ` Juan Quintela
2012-07-11 17:28           ` Orit Wasserman
     [not found] ` <704b60a0d2b32fbf6bf229b115082c2b929a4731.1340910651.git.quintela@redhat.com>
2012-07-01  9:40   ` [Qemu-devel] [PATCH 03/12] savevm: remove SaveSetParamsHandler Orit Wasserman
     [not found] ` <509b501d09f18212b4165ee116ddef4ceba59097.1340910651.git.quintela@redhat.com>
2012-07-01  9:40   ` [Qemu-devel] [PATCH 04/12] savevm: remove SaveLiveStateHandler Orit Wasserman
     [not found] ` <3dad4b557fac0c11eb6fdb06121859d16247e4f0.1340910651.git.quintela@redhat.com>
2012-07-01  9:47   ` [Qemu-devel] [PATCH 05/12] savevm: Refactor cancel operation in its own operation Orit Wasserman
     [not found] ` <1e9e8749f384425d04c74bc76fc502621e226352.1340910651.git.quintela@redhat.com>
     [not found]   ` <4FEF7C5F.5010700@gmail.com>
2012-07-01 10:44     ` [Qemu-devel] [PATCH 06/12] savevm: introduce is_active method Juan Quintela
     [not found] ` <5a3139cd92ad66e5028ad0120e4de63c1a089d65.1340910651.git.quintela@redhat.com>
2012-07-01 12:14   ` [Qemu-devel] [PATCH 07/12] savevm: split save_live_setup from save_live_state Orit Wasserman
     [not found] ` <cd73a246dbbb7a688e0000204f5af2040afe6578.1340910651.git.quintela@redhat.com>
2012-07-01 12:17   ` [Qemu-devel] [PATCH 11/12] ram: iterate phase Igor Mitsyanko
2012-07-03 10:48     ` Juan Quintela
     [not found] ` <d1e17271bb9fdc52dbd0b591e471b096aca2e721.1340910651.git.quintela@redhat.com>
2012-07-02 11:57   ` Orit Wasserman [this message]
     [not found] ` <07c8945d9b633bc509ebec0ff6646834ec974ccb.1340910651.git.quintela@redhat.com>
2012-07-02 12:00   ` [Qemu-devel] [PATCH 09/12] ram: save_live_setup() don't need to sent pages Orit Wasserman
     [not found] ` <be6bed86c792fb6f237f016aadfb3fcbda746f15.1340910651.git.quintela@redhat.com>
2012-07-02 12:00   ` [Qemu-devel] [PATCH 10/12] ram: save_live_complete() only do one loop Orit Wasserman
     [not found] ` <ab1ca756b1cfe67df94f7c6674ea86f6d7232a2f.1340910651.git.quintela@redhat.com>
2012-07-02 12:05   ` [Qemu-devel] [PATCH 12/12] ram: save_live_setup() we don't need to synchronize the dirty bitmap Orit Wasserman

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=4FF18CA8.7090804@redhat.com \
    --to=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.