All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
To: Peter Xu <peterx@redhat.com>
Cc: Leonardo Bras Soares Passos <lsoaresp@redhat.com>,
	qemu-devel@nongnu.org, Juan Quintela <quintela@redhat.com>
Subject: Re: [PATCH 19/20] migration: Postcopy recover with preempt enabled
Date: Tue, 22 Feb 2022 11:32:10 +0000	[thread overview]
Message-ID: <YhTJuvhEvdxnINPu@work-vm> (raw)
In-Reply-To: <20220216062809.57179-20-peterx@redhat.com>

* Peter Xu (peterx@redhat.com) wrote:
> To allow postcopy recovery, the ram fast load (preempt-only) dest QEMU thread
> needs similar handling on fault tolerance.  When ram_load_postcopy() fails,
> instead of stopping the thread it halts with a semaphore, preparing to be
> kicked again when recovery is detected.
> 
> A mutex is introduced to make sure there's no concurrent operation upon the
> socket.  To make it simple, the fast ram load thread will take the mutex during
> its whole procedure, and only release it if it's paused.  The fast-path socket
> will be properly released by the main loading thread safely when there's
> network failures during postcopy with that mutex held.

I *think* this is mostly OK; but I worry I don't understand all the
cases; e.g.
  a) If the postcopy channel errors first
  b) If the main channel errors first

Can you add some docs to walk through those and explain the locking ?

Dave

> Signed-off-by: Peter Xu <peterx@redhat.com>
> ---
>  migration/migration.c    | 17 +++++++++++++++--
>  migration/migration.h    |  3 +++
>  migration/postcopy-ram.c | 24 ++++++++++++++++++++++--
>  migration/savevm.c       | 17 +++++++++++++++++
>  migration/trace-events   |  2 ++
>  5 files changed, 59 insertions(+), 4 deletions(-)
> 
> diff --git a/migration/migration.c b/migration/migration.c
> index d20db04097..c68a281406 100644
> --- a/migration/migration.c
> +++ b/migration/migration.c
> @@ -215,9 +215,11 @@ void migration_object_init(void)
>      current_incoming->postcopy_remote_fds =
>          g_array_new(FALSE, TRUE, sizeof(struct PostCopyFD));
>      qemu_mutex_init(&current_incoming->rp_mutex);
> +    qemu_mutex_init(&current_incoming->postcopy_prio_thread_mutex);
>      qemu_event_init(&current_incoming->main_thread_load_event, false);
>      qemu_sem_init(&current_incoming->postcopy_pause_sem_dst, 0);
>      qemu_sem_init(&current_incoming->postcopy_pause_sem_fault, 0);
> +    qemu_sem_init(&current_incoming->postcopy_pause_sem_fast_load, 0);
>      qemu_mutex_init(&current_incoming->page_request_mutex);
>      current_incoming->page_requested = g_tree_new(page_request_addr_cmp);
>  
> @@ -697,9 +699,9 @@ static bool postcopy_try_recover(void)
>  
>          /*
>           * Here, we only wake up the main loading thread (while the
> -         * fault thread will still be waiting), so that we can receive
> +         * rest threads will still be waiting), so that we can receive
>           * commands from source now, and answer it if needed. The
> -         * fault thread will be woken up afterwards until we are sure
> +         * rest threads will be woken up afterwards until we are sure
>           * that source is ready to reply to page requests.
>           */
>          qemu_sem_post(&mis->postcopy_pause_sem_dst);
> @@ -3466,6 +3468,17 @@ static MigThrError postcopy_pause(MigrationState *s)
>          qemu_file_shutdown(file);
>          qemu_fclose(file);
>  
> +        /*
> +         * Do the same to postcopy fast path socket too if there is.  No
> +         * locking needed because no racer as long as we do this before setting
> +         * status to paused.
> +         */
> +        if (s->postcopy_qemufile_src) {
> +            migration_ioc_unregister_yank_from_file(s->postcopy_qemufile_src);

Shouldn't this do a qemu_file_shutdown on here first?

> +            qemu_fclose(s->postcopy_qemufile_src);
> +            s->postcopy_qemufile_src = NULL;
> +        }
> +
>          migrate_set_state(&s->state, s->state,
>                            MIGRATION_STATUS_POSTCOPY_PAUSED);
>  
> diff --git a/migration/migration.h b/migration/migration.h
> index b8aacfe3af..945088064a 100644
> --- a/migration/migration.h
> +++ b/migration/migration.h
> @@ -118,6 +118,8 @@ struct MigrationIncomingState {
>      /* Postcopy priority thread is used to receive postcopy requested pages */
>      QemuThread postcopy_prio_thread;
>      bool postcopy_prio_thread_created;
> +    /* Used to sync with the prio thread */
> +    QemuMutex postcopy_prio_thread_mutex;
>      /*
>       * An array of temp host huge pages to be used, one for each postcopy
>       * channel.
> @@ -147,6 +149,7 @@ struct MigrationIncomingState {
>      /* notify PAUSED postcopy incoming migrations to try to continue */
>      QemuSemaphore postcopy_pause_sem_dst;
>      QemuSemaphore postcopy_pause_sem_fault;
> +    QemuSemaphore postcopy_pause_sem_fast_load;
>  
>      /* List of listening socket addresses  */
>      SocketAddressList *socket_address_list;
> diff --git a/migration/postcopy-ram.c b/migration/postcopy-ram.c
> index 30eddaacd1..b3d23804bc 100644
> --- a/migration/postcopy-ram.c
> +++ b/migration/postcopy-ram.c
> @@ -1575,6 +1575,15 @@ int postcopy_preempt_setup(MigrationState *s, Error **errp)
>      return 0;
>  }
>  
> +static void postcopy_pause_ram_fast_load(MigrationIncomingState *mis)
> +{
> +    trace_postcopy_pause_fast_load();
> +    qemu_mutex_unlock(&mis->postcopy_prio_thread_mutex);
> +    qemu_sem_wait(&mis->postcopy_pause_sem_fast_load);
> +    qemu_mutex_lock(&mis->postcopy_prio_thread_mutex);
> +    trace_postcopy_pause_fast_load_continued();
> +}
> +
>  void *postcopy_preempt_thread(void *opaque)
>  {
>      MigrationIncomingState *mis = opaque;
> @@ -1587,11 +1596,22 @@ void *postcopy_preempt_thread(void *opaque)
>      qemu_sem_post(&mis->thread_sync_sem);
>  
>      /* Sending RAM_SAVE_FLAG_EOS to terminate this thread */
> -    ret = ram_load_postcopy(mis->postcopy_qemufile_dst, RAM_CHANNEL_POSTCOPY);
> +    qemu_mutex_lock(&mis->postcopy_prio_thread_mutex);
> +    while (1) {
> +        ret = ram_load_postcopy(mis->postcopy_qemufile_dst, RAM_CHANNEL_POSTCOPY);
> +        /* If error happened, go into recovery routine */
> +        if (ret) {
> +            postcopy_pause_ram_fast_load(mis);
> +        } else {
> +            /* We're done */
> +            break;
> +        }
> +    }
> +    qemu_mutex_unlock(&mis->postcopy_prio_thread_mutex);
>  
>      rcu_unregister_thread();
>  
>      trace_postcopy_preempt_thread_exit();
>  
> -    return ret == 0 ? NULL : (void *)-1;
> +    return NULL;
>  }
> diff --git a/migration/savevm.c b/migration/savevm.c
> index 254aa78234..2d32340d28 100644
> --- a/migration/savevm.c
> +++ b/migration/savevm.c
> @@ -2152,6 +2152,13 @@ static int loadvm_postcopy_handle_resume(MigrationIncomingState *mis)
>       */
>      qemu_sem_post(&mis->postcopy_pause_sem_fault);
>  
> +    if (migrate_postcopy_preempt()) {
> +        /* The channel should already be setup again; make sure of it */
> +        assert(mis->postcopy_qemufile_dst);
> +        /* Kick the fast ram load thread too */
> +        qemu_sem_post(&mis->postcopy_pause_sem_fast_load);
> +    }
> +
>      return 0;
>  }
>  
> @@ -2607,6 +2614,16 @@ static bool postcopy_pause_incoming(MigrationIncomingState *mis)
>      mis->to_src_file = NULL;
>      qemu_mutex_unlock(&mis->rp_mutex);
>  
> +    if (mis->postcopy_qemufile_dst) {
> +        qemu_file_shutdown(mis->postcopy_qemufile_dst);
> +        /* Take the mutex to make sure the fast ram load thread halted */
> +        qemu_mutex_lock(&mis->postcopy_prio_thread_mutex);
> +        migration_ioc_unregister_yank_from_file(mis->postcopy_qemufile_dst);
> +        qemu_fclose(mis->postcopy_qemufile_dst);
> +        mis->postcopy_qemufile_dst = NULL;
> +        qemu_mutex_unlock(&mis->postcopy_prio_thread_mutex);
> +    }
> +
>      migrate_set_state(&mis->state, MIGRATION_STATUS_POSTCOPY_ACTIVE,
>                        MIGRATION_STATUS_POSTCOPY_PAUSED);
>  
> diff --git a/migration/trace-events b/migration/trace-events
> index b1155d9da0..dfe36a3340 100644
> --- a/migration/trace-events
> +++ b/migration/trace-events
> @@ -270,6 +270,8 @@ mark_postcopy_blocktime_begin(uint64_t addr, void *dd, uint32_t time, int cpu, i
>  mark_postcopy_blocktime_end(uint64_t addr, void *dd, uint32_t time, int affected_cpu) "addr: 0x%" PRIx64 ", dd: %p, time: %u, affected_cpu: %d"
>  postcopy_pause_fault_thread(void) ""
>  postcopy_pause_fault_thread_continued(void) ""
> +postcopy_pause_fast_load(void) ""
> +postcopy_pause_fast_load_continued(void) ""
>  postcopy_ram_fault_thread_entry(void) ""
>  postcopy_ram_fault_thread_exit(void) ""
>  postcopy_ram_fault_thread_fds_core(int baseufd, int quitfd) "ufd: %d quitfd: %d"
> -- 
> 2.32.0
> 
-- 
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK



  reply	other threads:[~2022-02-22 11:33 UTC|newest]

Thread overview: 54+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-02-16  6:27 [PATCH 00/20] migration: Postcopy Preemption Peter Xu
2022-02-16  6:27 ` [PATCH 01/20] migration: Dump sub-cmd name in loadvm_process_command tp Peter Xu
2022-02-16 15:42   ` Dr. David Alan Gilbert
2022-02-16  6:27 ` [PATCH 02/20] migration: Finer grained tracepoints for POSTCOPY_LISTEN Peter Xu
2022-02-16 15:43   ` Dr. David Alan Gilbert
2022-02-16  6:27 ` [PATCH 03/20] migration: Tracepoint change in postcopy-run bottom half Peter Xu
2022-02-16 19:00   ` Dr. David Alan Gilbert
2022-02-16  6:27 ` [PATCH 04/20] migration: Introduce postcopy channels on dest node Peter Xu
2022-02-21 15:49   ` Dr. David Alan Gilbert
2022-02-16  6:27 ` [PATCH 05/20] migration: Dump ramblock and offset too when non-same-page detected Peter Xu
2022-02-16  6:27 ` [PATCH 06/20] migration: Add postcopy_thread_create() Peter Xu
2022-02-21 16:00   ` Dr. David Alan Gilbert
2022-02-16  6:27 ` [PATCH 07/20] migration: Move static var in ram_block_from_stream() into global Peter Xu
2022-02-16  6:27 ` [PATCH 08/20] migration: Add pss.postcopy_requested status Peter Xu
2022-02-16  6:27 ` [PATCH 09/20] migration: Move migrate_allow_multifd and helpers into migration.c Peter Xu
2022-02-16  6:27 ` [PATCH 10/20] migration: Enlarge postcopy recovery to capture !-EIO too Peter Xu
2022-02-21 16:15   ` Dr. David Alan Gilbert
2022-02-16  6:28 ` [PATCH 11/20] migration: postcopy_pause_fault_thread() never fails Peter Xu
2022-02-21 16:16   ` Dr. David Alan Gilbert
2022-02-16  6:28 ` [PATCH 12/20] migration: Export ram_load_postcopy() Peter Xu
2022-02-21 16:17   ` Dr. David Alan Gilbert
2022-02-16  6:28 ` [PATCH 13/20] migration: Move channel setup out of postcopy_try_recover() Peter Xu
2022-02-22 10:57   ` Dr. David Alan Gilbert
2022-02-23  6:40     ` Peter Xu
2022-02-23  9:47       ` Dr. David Alan Gilbert
2022-02-23 12:55         ` Peter Xu
2022-02-16  6:28 ` [PATCH 14/20] migration: Add migration_incoming_transport_cleanup() Peter Xu
2022-02-21 16:56   ` Dr. David Alan Gilbert
2022-02-16  6:28 ` [PATCH 15/20] migration: Allow migrate-recover to run multiple times Peter Xu
2022-02-21 17:03   ` Dr. David Alan Gilbert
2022-02-22  2:51     ` Peter Xu
2022-02-16  6:28 ` [PATCH 16/20] migration: Add postcopy-preempt capability Peter Xu
2022-02-16  6:28 ` [PATCH 17/20] migration: Postcopy preemption preparation on channel creation Peter Xu
2022-02-21 18:39   ` Dr. David Alan Gilbert
2022-02-22  8:34     ` Peter Xu
2022-02-22 10:19       ` Dr. David Alan Gilbert
2022-02-16  6:28 ` [PATCH 18/20] migration: Postcopy preemption enablement Peter Xu
2022-02-22 10:52   ` Dr. David Alan Gilbert
2022-02-23  7:01     ` Peter Xu
2022-02-23  9:56       ` Dr. David Alan Gilbert
2022-02-23 13:05         ` Peter Xu
2022-02-16  6:28 ` [PATCH 19/20] migration: Postcopy recover with preempt enabled Peter Xu
2022-02-22 11:32   ` Dr. David Alan Gilbert [this message]
2022-02-23  7:45     ` Peter Xu
2022-02-23  9:52       ` Dr. David Alan Gilbert
2022-02-23 13:14         ` Peter Xu
2022-02-23 18:53           ` Dr. David Alan Gilbert
2022-02-16  6:28 ` [PATCH 20/20] tests: Add postcopy preempt test Peter Xu
2022-02-22 12:51   ` Dr. David Alan Gilbert
2022-02-23  7:50     ` Peter Xu
2022-03-01  5:34       ` Peter Xu
2022-03-01 17:00         ` Dr. David Alan Gilbert
2022-03-02  6:41           ` Peter Xu
2022-02-16  9:28 ` [PATCH 00/20] migration: Postcopy Preemption Peter Xu

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=YhTJuvhEvdxnINPu@work-vm \
    --to=dgilbert@redhat.com \
    --cc=lsoaresp@redhat.com \
    --cc=peterx@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.