qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: "Cédric Le Goater" <clg@redhat.com>
To: "Maciej S. Szmigiero" <mail@maciej.szmigiero.name>,
	Peter Xu <peterx@redhat.com>, Fabiano Rosas <farosas@suse.de>
Cc: "Alex Williamson" <alex.williamson@redhat.com>,
	"Eric Blake" <eblake@redhat.com>,
	"Markus Armbruster" <armbru@redhat.com>,
	"Daniel P . Berrangé" <berrange@redhat.com>,
	"Avihai Horon" <avihaih@nvidia.com>,
	"Joao Martins" <joao.m.martins@oracle.com>,
	qemu-devel@nongnu.org
Subject: Re: [PATCH v3 08/24] migration: Add thread pool of optional load threads
Date: Wed, 27 Nov 2024 10:13:10 +0100	[thread overview]
Message-ID: <9a229308-2c80-4ee2-8c49-5fec2207ad74@redhat.com> (raw)
In-Reply-To: <877b7108c9cb9064615606d4c731cb12c549b7f9.1731773021.git.maciej.szmigiero@oracle.com>

On 11/17/24 20:20, Maciej S. Szmigiero wrote:
> From: "Maciej S. Szmigiero" <maciej.szmigiero@oracle.com>
> 
> Some drivers might want to make use of auxiliary helper threads during VM
> state loading, for example to make sure that their blocking (sync) I/O
> operations don't block the rest of the migration process.
> 
> Add a migration core managed thread pool to facilitate this use case.
> 
> The migration core will wait for these threads to finish before
> (re)starting the VM at destination.
> 
> Signed-off-by: Maciej S. Szmigiero <maciej.szmigiero@oracle.com>
> ---
>   include/migration/misc.h |  3 ++
>   include/qemu/typedefs.h  |  1 +
>   migration/savevm.c       | 77 ++++++++++++++++++++++++++++++++++++++++
>   3 files changed, 81 insertions(+)
> 
> diff --git a/include/migration/misc.h b/include/migration/misc.h
> index 804eb23c0607..c92ca018ab3b 100644
> --- a/include/migration/misc.h
> +++ b/include/migration/misc.h
> @@ -45,9 +45,12 @@ bool migrate_ram_is_ignored(RAMBlock *block);
>   /* migration/block.c */
>   
>   AnnounceParameters *migrate_announce_params(void);
> +
>   /* migration/savevm.c */
>   
>   void dump_vmstate_json_to_file(FILE *out_fp);
> +void qemu_loadvm_start_load_thread(MigrationLoadThread function,
> +                                   void *opaque);
>   
>   /* migration/migration.c */
>   void migration_object_init(void);
> diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h
> index 3d84efcac47a..8c8ea5c2840d 100644
> --- a/include/qemu/typedefs.h
> +++ b/include/qemu/typedefs.h
> @@ -131,5 +131,6 @@ typedef struct IRQState *qemu_irq;
>    * Function types
>    */
>   typedef void (*qemu_irq_handler)(void *opaque, int n, int level);
> +typedef int (*MigrationLoadThread)(bool *abort_flag, void *opaque);
>   
>   #endif /* QEMU_TYPEDEFS_H */
> diff --git a/migration/savevm.c b/migration/savevm.c
> index 1f58a2fa54ae..6ea9054c4083 100644
> --- a/migration/savevm.c
> +++ b/migration/savevm.c
> @@ -54,6 +54,7 @@
>   #include "qemu/job.h"
>   #include "qemu/main-loop.h"
>   #include "block/snapshot.h"
> +#include "block/thread-pool.h"
>   #include "qemu/cutils.h"
>   #include "io/channel-buffer.h"
>   #include "io/channel-file.h"
> @@ -71,6 +72,10 @@
>   
>   const unsigned int postcopy_ram_discard_version;
>   
> +static ThreadPool *load_threads;
> +static int load_threads_ret;
> +static bool load_threads_abort;
> +
>   /* Subcommands for QEMU_VM_COMMAND */
>   enum qemu_vm_cmd {
>       MIG_CMD_INVALID = 0,   /* Must be 0 */
> @@ -2788,6 +2793,12 @@ static int qemu_loadvm_state_setup(QEMUFile *f, Error **errp)
>       int ret;
>   
>       trace_loadvm_state_setup();
> +
> +    assert(!load_threads);
> +    load_threads = thread_pool_new();
> +    load_threads_ret = 0;
> +    load_threads_abort = false;

I would introduce a qemu_loadvm_thread_pool_create() helper.

Why is the thead pool always created ? Might be OK.


> +
>       QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
>           if (!se->ops || !se->ops->load_setup) {
>               continue;
> @@ -2806,19 +2817,72 @@ static int qemu_loadvm_state_setup(QEMUFile *f, Error **errp)
>               return ret;
>           }
>       }
> +
> +    return 0;
> +}
> +
> +struct LoadThreadData {
> +    MigrationLoadThread function;
> +    void *opaque;
> +};
> +
> +static int qemu_loadvm_load_thread(void *thread_opaque)
> +{
> +    struct LoadThreadData *data = thread_opaque;
> +    int ret;
> +
> +    ret = data->function(&load_threads_abort, data->opaque);
> +    if (ret && !qatomic_read(&load_threads_ret)) {
> +        /*
> +         * Racy with the above read but that's okay - which thread error
> +         * return we report is purely arbitrary anyway.
> +         */
> +        qatomic_set(&load_threads_ret, ret);
> +    }
> +
>       return 0;>   }
>   
> +void qemu_loadvm_start_load_thread(MigrationLoadThread function,
> +                                   void *opaque)
> +{> +    struct LoadThreadData *data;
> +
> +    /* We only set it from this thread so it's okay to read it directly */
> +    assert(!load_threads_abort);
> +
> +    data = g_new(struct LoadThreadData, 1);
> +    data->function = function;
> +    data->opaque = opaque;
> +
> +    thread_pool_submit(load_threads, qemu_loadvm_load_thread,
> +                       data, g_free);
> +    thread_pool_adjust_max_threads_to_work(load_threads);
> +}> +>   void qemu_loadvm_state_cleanup(void)
>   {
>       SaveStateEntry *se;
>   
>       trace_loadvm_state_cleanup();
> +
>       QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
>           if (se->ops && se->ops->load_cleanup) {
>               se->ops->load_cleanup(se->opaque);
>           }
>       }
> +
> +    /*
> +     * We might be called even without earlier qemu_loadvm_state_setup()
> +     * call if qemu_loadvm_state() fails very early.
> +     */
> +    if (load_threads) {
> +        qatomic_set(&load_threads_abort, true);
> +        bql_unlock(); /* Load threads might be waiting for BQL */
> +        thread_pool_wait(load_threads);
> +        bql_lock();
> +        g_clear_pointer(&load_threads, thread_pool_free);
> +    }

I would introduce a qemu_loadvm_thread_pool_destroy() helper

>   }
>   
>   /* Return true if we should continue the migration, or false. */
> @@ -3007,6 +3071,19 @@ int qemu_loadvm_state(QEMUFile *f)
>           return ret;
>       }
>   
> +    if (ret == 0) {
> +        bql_unlock(); /* Let load threads do work requiring BQL */
> +        thread_pool_wait(load_threads);
> +        bql_lock();
> +
> +        ret = load_threads_ret;
> +    }
> +    /*
> +     * Set this flag unconditionally so we'll catch further attempts to
> +     * start additional threads via an appropriate assert()
> +     */
> +    qatomic_set(&load_threads_abort, true);
> +


I would introduce a qemu_loadvm_thread_pool_wait() helper

>       if (ret == 0) {
>           ret = qemu_file_get_error(f);
>       }
> 

I think we could hide the implementation in a new component of
the migration subsystem or, at least, we could group the
implementation at the top the file. It would help the uninitiated
reader to become familiar with the migration area.

Thanks,

C.



  parent reply	other threads:[~2024-11-27  9:13 UTC|newest]

Thread overview: 140+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-11-17 19:19 [PATCH v3 00/24] Multifd 🔀 device state transfer support with VFIO consumer Maciej S. Szmigiero
2024-11-17 19:19 ` [PATCH v3 01/24] migration: Clarify that {load, save}_cleanup handlers can run without setup Maciej S. Szmigiero
2024-11-25 19:08   ` Fabiano Rosas
2024-11-26 16:25   ` [PATCH v3 01/24] migration: Clarify that {load,save}_cleanup " Cédric Le Goater
2024-11-17 19:19 ` [PATCH v3 02/24] thread-pool: Remove thread_pool_submit() function Maciej S. Szmigiero
2024-11-25 19:13   ` Fabiano Rosas
2024-11-26 16:25   ` Cédric Le Goater
2024-12-04 19:24   ` Peter Xu
2024-12-06 21:11     ` Maciej S. Szmigiero
2024-11-17 19:19 ` [PATCH v3 03/24] thread-pool: Rename AIO pool functions to *_aio() and data types to *Aio Maciej S. Szmigiero
2024-11-25 19:15   ` Fabiano Rosas
2024-11-26 16:26   ` Cédric Le Goater
2024-12-04 19:26   ` Peter Xu
2024-11-17 19:19 ` [PATCH v3 04/24] thread-pool: Implement generic (non-AIO) pool support Maciej S. Szmigiero
2024-11-25 19:41   ` Fabiano Rosas
2024-11-25 19:55     ` Maciej S. Szmigiero
2024-11-25 20:51       ` Fabiano Rosas
2024-11-26 19:25       ` Cédric Le Goater
2024-11-26 21:21         ` Maciej S. Szmigiero
2024-11-26 19:29   ` Cédric Le Goater
2024-11-26 21:22     ` Maciej S. Szmigiero
2024-12-05 13:10       ` Cédric Le Goater
2024-11-28 10:08   ` Avihai Horon
2024-11-28 12:11     ` Maciej S. Szmigiero
2024-12-04 20:04   ` Peter Xu
2024-11-17 19:20 ` [PATCH v3 05/24] migration: Add MIG_CMD_SWITCHOVER_START and its load handler Maciej S. Szmigiero
2024-11-25 19:46   ` Fabiano Rosas
2024-11-26 19:37   ` Cédric Le Goater
2024-11-26 21:22     ` Maciej S. Szmigiero
2024-12-04 21:29   ` Peter Xu
2024-12-05 19:46     ` Zhang Chen
2024-12-06 18:24       ` Maciej S. Szmigiero
2024-12-06 22:12         ` Peter Xu
2024-12-09  1:43           ` Zhang Chen
2024-11-17 19:20 ` [PATCH v3 06/24] migration: Add qemu_loadvm_load_state_buffer() and its handler Maciej S. Szmigiero
2024-12-04 21:32   ` Peter Xu
2024-12-06 21:12     ` Maciej S. Szmigiero
2024-11-17 19:20 ` [PATCH v3 07/24] migration: Document the BQL behavior of load SaveVMHandlers Maciej S. Szmigiero
2024-12-04 21:38   ` Peter Xu
2024-12-06 18:40     ` Maciej S. Szmigiero
2024-12-06 22:15       ` Peter Xu
2024-11-17 19:20 ` [PATCH v3 08/24] migration: Add thread pool of optional load threads Maciej S. Szmigiero
2024-11-25 19:58   ` Fabiano Rosas
2024-11-27  9:13   ` Cédric Le Goater [this message]
2024-11-27 20:16     ` Maciej S. Szmigiero
2024-12-04 22:48       ` Peter Xu
2024-12-05 16:15         ` Peter Xu
2024-12-10 23:05           ` Maciej S. Szmigiero
2024-12-10 23:05         ` Maciej S. Szmigiero
2024-12-12 16:38           ` Peter Xu
2024-12-12 22:53             ` Maciej S. Szmigiero
2024-12-16 16:29               ` Peter Xu
2024-12-16 23:15                 ` Maciej S. Szmigiero
2024-12-17 14:50                   ` Peter Xu
2024-11-28 10:26   ` Avihai Horon
2024-11-28 12:11     ` Maciej S. Szmigiero
2024-12-04 22:43       ` Peter Xu
2024-12-10 23:05         ` Maciej S. Szmigiero
2024-12-12 16:55           ` Peter Xu
2024-12-12 22:53             ` Maciej S. Szmigiero
2024-12-16 16:33               ` Peter Xu
2024-12-16 23:15                 ` Maciej S. Szmigiero
2024-11-17 19:20 ` [PATCH v3 09/24] migration/multifd: Split packet into header and RAM data Maciej S. Szmigiero
2024-11-26 14:34   ` Fabiano Rosas
2024-12-05 15:29   ` Peter Xu
2024-11-17 19:20 ` [PATCH v3 10/24] migration/multifd: Device state transfer support - receive side Maciej S. Szmigiero
2024-12-05 16:06   ` Peter Xu
2024-12-06 21:12     ` Maciej S. Szmigiero
2024-12-06 21:57       ` Peter Xu
2024-11-17 19:20 ` [PATCH v3 11/24] migration/multifd: Make multifd_send() thread safe Maciej S. Szmigiero
2024-12-05 16:17   ` Peter Xu
2024-12-06 21:12     ` Maciej S. Szmigiero
2024-11-17 19:20 ` [PATCH v3 12/24] migration/multifd: Add an explicit MultiFDSendData destructor Maciej S. Szmigiero
2024-12-05 16:23   ` Peter Xu
2024-11-17 19:20 ` [PATCH v3 13/24] migration/multifd: Device state transfer support - send side Maciej S. Szmigiero
2024-11-26 19:58   ` Fabiano Rosas
2024-11-26 21:22     ` Maciej S. Szmigiero
2024-11-17 19:20 ` [PATCH v3 14/24] migration/multifd: Make MultiFDSendData a struct Maciej S. Szmigiero
2024-11-17 19:20 ` [PATCH v3 15/24] migration/multifd: Add migration_has_device_state_support() Maciej S. Szmigiero
2024-11-26 20:05   ` Fabiano Rosas
2024-11-28 10:33   ` Avihai Horon
2024-11-28 12:12     ` Maciej S. Szmigiero
2024-12-05 16:44       ` Peter Xu
2024-11-17 19:20 ` [PATCH v3 16/24] migration/multifd: Send final SYNC only after device state is complete Maciej S. Szmigiero
2024-11-26 20:52   ` Fabiano Rosas
2024-11-26 21:22     ` Maciej S. Szmigiero
2024-12-05 19:02       ` Peter Xu
2024-12-10 23:05         ` Maciej S. Szmigiero
2024-12-11 13:20           ` Peter Xu
2024-11-17 19:20 ` [PATCH v3 17/24] migration: Add save_live_complete_precopy_thread handler Maciej S. Szmigiero
2024-11-29 14:03   ` Cédric Le Goater
2024-11-29 17:14     ` Maciej S. Szmigiero
2024-11-17 19:20 ` [PATCH v3 18/24] vfio/migration: Don't run load cleanup if load setup didn't run Maciej S. Szmigiero
2024-11-29 14:08   ` Cédric Le Goater
2024-11-29 17:15     ` Maciej S. Szmigiero
2024-12-03 15:09       ` Avihai Horon
2024-12-10 23:04         ` Maciej S. Szmigiero
2024-12-12 14:30           ` Avihai Horon
2024-12-12 22:52             ` Maciej S. Szmigiero
2024-12-19  9:19               ` Cédric Le Goater
2024-11-17 19:20 ` [PATCH v3 19/24] vfio/migration: Add x-migration-multifd-transfer VFIO property Maciej S. Szmigiero
2024-11-29 14:11   ` Cédric Le Goater
2024-11-29 17:15     ` Maciej S. Szmigiero
2024-12-19  9:37       ` Cédric Le Goater
2024-11-17 19:20 ` [PATCH v3 20/24] vfio/migration: Add load_device_config_state_start trace event Maciej S. Szmigiero
2024-11-29 14:26   ` Cédric Le Goater
2024-11-17 19:20 ` [PATCH v3 21/24] vfio/migration: Convert bytes_transferred counter to atomic Maciej S. Szmigiero
2024-11-17 19:20 ` [PATCH v3 22/24] vfio/migration: Multifd device state transfer support - receive side Maciej S. Szmigiero
2024-12-02 17:56   ` Cédric Le Goater
2024-12-10 23:04     ` Maciej S. Szmigiero
2024-12-19 14:13       ` Cédric Le Goater
2024-12-09  9:13   ` Avihai Horon
2024-12-10 23:06     ` Maciej S. Szmigiero
2024-12-12 14:33       ` Avihai Horon
2024-11-17 19:20 ` [PATCH v3 23/24] migration/qemu-file: Define g_autoptr() cleanup function for QEMUFile Maciej S. Szmigiero
2024-11-26 21:01   ` Fabiano Rosas
2024-12-05 19:49   ` Peter Xu
2024-11-17 19:20 ` [PATCH v3 24/24] vfio/migration: Multifd device state transfer support - send side Maciej S. Szmigiero
2024-12-09  9:28   ` Avihai Horon
2024-12-10 23:06     ` Maciej S. Szmigiero
2024-12-12 11:10       ` Cédric Le Goater
2024-12-12 22:52         ` Maciej S. Szmigiero
2024-12-13 11:08           ` Cédric Le Goater
2024-12-13 18:25             ` Maciej S. Szmigiero
2024-12-12 14:54       ` Avihai Horon
2024-12-12 22:53         ` Maciej S. Szmigiero
2024-12-16 17:33           ` Peter Xu
2024-12-19  9:50             ` Cédric Le Goater
2024-12-04 19:10 ` [PATCH v3 00/24] Multifd 🔀 device state transfer support with VFIO consumer Peter Xu
2024-12-06 18:03   ` Maciej S. Szmigiero
2024-12-06 22:20     ` Peter Xu
2024-12-10 23:06       ` Maciej S. Szmigiero
2024-12-12 17:35         ` Peter Xu
2024-12-19  7:55           ` Yanghang Liu
2024-12-19  8:53             ` Cédric Le Goater
2024-12-19 13:00               ` Yanghang Liu
2024-12-05 21:27 ` Cédric Le Goater
2024-12-05 21:42   ` Peter Xu
2024-12-06 10:24     ` Cédric Le Goater
2024-12-06 18:44   ` Maciej S. Szmigiero

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=9a229308-2c80-4ee2-8c49-5fec2207ad74@redhat.com \
    --to=clg@redhat.com \
    --cc=alex.williamson@redhat.com \
    --cc=armbru@redhat.com \
    --cc=avihaih@nvidia.com \
    --cc=berrange@redhat.com \
    --cc=eblake@redhat.com \
    --cc=farosas@suse.de \
    --cc=joao.m.martins@oracle.com \
    --cc=mail@maciej.szmigiero.name \
    --cc=peterx@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).