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>,
	Avihai Horon <avihaih@nvidia.com>
Cc: "Alex Williamson" <alex.williamson@redhat.com>,
	"Peter Xu" <peterx@redhat.com>, "Fabiano Rosas" <farosas@suse.de>,
	"Eric Blake" <eblake@redhat.com>,
	"Markus Armbruster" <armbru@redhat.com>,
	"Daniel P . Berrangé" <berrange@redhat.com>,
	"Joao Martins" <joao.m.martins@oracle.com>,
	qemu-devel@nongnu.org
Subject: Re: [PATCH v3 24/24] vfio/migration: Multifd device state transfer support - send side
Date: Thu, 12 Dec 2024 12:10:50 +0100	[thread overview]
Message-ID: <80c9dfc4-4105-4e48-bcae-4fa9780a43c8@redhat.com> (raw)
In-Reply-To: <06360868-95e3-46e2-8960-51348025a1b7@maciej.szmigiero.name>

On 12/11/24 00:06, Maciej S. Szmigiero wrote:
> On 9.12.2024 10:28, Avihai Horon wrote:
>>
>> On 17/11/2024 21:20, Maciej S. Szmigiero wrote:
>>> External email: Use caution opening links or attachments
>>>
>>>
>>> From: "Maciej S. Szmigiero" <maciej.szmigiero@oracle.com>
>>>
>>> Implement the multifd device state transfer via additional per-device
>>> thread inside save_live_complete_precopy_thread handler.
>>>
>>> Switch between doing the data transfer in the new handler and doing it
>>> in the old save_state handler depending on the
>>> x-migration-multifd-transfer device property value.
>>>
>>> Signed-off-by: Maciej S. Szmigiero <maciej.szmigiero@oracle.com>
>>> ---
>>>   hw/vfio/migration.c  | 155 +++++++++++++++++++++++++++++++++++++++++++
>>>   hw/vfio/trace-events |   2 +
>>>   2 files changed, 157 insertions(+)
>>>
>>> diff --git a/hw/vfio/migration.c b/hw/vfio/migration.c
>>> index b54879fe6209..8709672ada48 100644
>>> --- a/hw/vfio/migration.c
>>> +++ b/hw/vfio/migration.c
>>> @@ -771,6 +771,24 @@ static int vfio_save_setup(QEMUFile *f, void *opaque, Error **errp)
>>>       uint64_t stop_copy_size = VFIO_MIG_DEFAULT_DATA_BUFFER_SIZE;
>>>       int ret;
>>>
>>> +    /*
>>> +     * Make a copy of this setting at the start in case it is changed
>>> +     * mid-migration.
>>> +     */
>>> +    if (vbasedev->migration_multifd_transfer == ON_OFF_AUTO_AUTO) {
>>> +        migration->multifd_transfer = vfio_multifd_transfer_supported();
>>> +    } else {
>>> +        migration->multifd_transfer =
>>> +            vbasedev->migration_multifd_transfer == ON_OFF_AUTO_ON;
>>> +    }
>>> +
>>> +    if (migration->multifd_transfer && !vfio_multifd_transfer_supported()) {
>>> +        error_setg(errp,
>>> +                   "%s: Multifd device transfer requested but unsupported in the current config",
>>> +                   vbasedev->name);
>>> +        return -EINVAL;
>>> +    }
>>> +
>>>       qemu_put_be64(f, VFIO_MIG_FLAG_DEV_SETUP_STATE);
>>>
>>>       vfio_query_stop_copy_size(vbasedev, &stop_copy_size);
>>> @@ -942,13 +960,32 @@ static int vfio_save_iterate(QEMUFile *f, void *opaque)
>>>       return !migration->precopy_init_size && !migration->precopy_dirty_size;
>>>   }
>>>
>>> +static void vfio_save_multifd_emit_dummy_eos(VFIODevice *vbasedev, QEMUFile *f)
>>> +{
>>> +    VFIOMigration *migration = vbasedev->migration;
>>> +
>>> +    assert(migration->multifd_transfer);
>>> +
>>> +    /*
>>> +     * Emit dummy NOP data on the main migration channel since the actual
>>> +     * device state transfer is done via multifd channels.
>>> +     */
>>> +    qemu_put_be64(f, VFIO_MIG_FLAG_END_OF_STATE);
>>> +}
>>> +
>>>   static int vfio_save_complete_precopy(QEMUFile *f, void *opaque)
>>>   {
>>>       VFIODevice *vbasedev = opaque;
>>> +    VFIOMigration *migration = vbasedev->migration;
>>>       ssize_t data_size;
>>>       int ret;
>>>       Error *local_err = NULL;
>>>
>>> +    if (migration->multifd_transfer) {
>>> +        vfio_save_multifd_emit_dummy_eos(vbasedev, f);
>>> +        return 0;
>>> +    }
>>
>> I wonder whether we should add a .save_live_use_thread SaveVMHandlers through which a device can indicate if it wants to save its data with the async or sync handler.
>> This will allow migration layer (i.e., qemu_savevm_state_complete_precopy_iterable) to know which handler to call instead of calling both of them and letting each device implicitly decide.
>> IMHO it will make the code clearer and will allow us to drop vfio_save_multifd_emit_dummy_eos().
> 
> I think that it's not worth adding a new SaveVMHandler just for this specific
> use case, considering that it's easy to handle it inside driver by emitting that
> FLAG_END_OF_STATE.
> 
> Especially considering that for compatibility with other drivers that do not
> define that hypothetical new SaveVMHandler not having it defined would need to
> have the same effect as it always returning "false".
> 
>>> +
>>>       trace_vfio_save_complete_precopy_start(vbasedev->name);
>>>
>>>       /* We reach here with device state STOP or STOP_COPY only */
>>> @@ -974,12 +1011,129 @@ static int vfio_save_complete_precopy(QEMUFile *f, void *opaque)
>>>       return ret;
>>>   }
>>>
>>> +static int
>>> +vfio_save_complete_precopy_async_thread_config_state(VFIODevice *vbasedev,
>>> +                                                     char *idstr,
>>> +                                                     uint32_t instance_id,
>>> +                                                     uint32_t idx)
>>> +{
>>> +    g_autoptr(QIOChannelBuffer) bioc = NULL;
>>> +    g_autoptr(QEMUFile) f = NULL;
>>> +    int ret;
>>> +    g_autofree VFIODeviceStatePacket *packet = NULL;
>>> +    size_t packet_len;
>>> +
>>> +    bioc = qio_channel_buffer_new(0);
>>> +    qio_channel_set_name(QIO_CHANNEL(bioc), "vfio-device-config-save");
>>> +
>>> +    f = qemu_file_new_output(QIO_CHANNEL(bioc));
>>> +
>>> +    ret = vfio_save_device_config_state(f, vbasedev, NULL);
>>> +    if (ret) {
>>> +        return ret;
>>> +    }
>>> +
>>> +    ret = qemu_fflush(f);
>>> +    if (ret) {
>>> +        return ret;
>>> +    }
>>> +
>>> +    packet_len = sizeof(*packet) + bioc->usage;
>>> +    packet = g_malloc0(packet_len);
>>> +    packet->idx = idx;
>>> +    packet->flags = VFIO_DEVICE_STATE_CONFIG_STATE;
>>> +    memcpy(&packet->data, bioc->data, bioc->usage);
>>> +
>>> +    if (!multifd_queue_device_state(idstr, instance_id,
>>> +                                    (char *)packet, packet_len)) {
>>> +        return -1;
>>> +    }
>>> +
>>> +    qatomic_add(&bytes_transferred, packet_len);
>>> +
>>> +    return 0;
>>> +}
>>> +
>>> +static int vfio_save_complete_precopy_thread(char *idstr,
>>> +                                             uint32_t instance_id,
>>> +                                             bool *abort_flag,
>>> +                                             void *opaque)
>>> +{
>>> +    VFIODevice *vbasedev = opaque;
>>> +    VFIOMigration *migration = vbasedev->migration;
>>> +    int ret;
>>> +    g_autofree VFIODeviceStatePacket *packet = NULL;
>>> +    uint32_t idx;
>>> +
>>> +    if (!migration->multifd_transfer) {
>>> +        /* Nothing to do, vfio_save_complete_precopy() does the transfer. */
>>> +        return 0;
>>> +    }
>>> +
>>> +    trace_vfio_save_complete_precopy_thread_start(vbasedev->name,
>>> +                                                  idstr, instance_id);
>>> +
>>> +    /* We reach here with device state STOP or STOP_COPY only */
>>> +    ret = vfio_migration_set_state(vbasedev, VFIO_DEVICE_STATE_STOP_COPY,
>>> +                                   VFIO_DEVICE_STATE_STOP, NULL);
>>> +    if (ret) {
>>> +        goto ret_finish;
>>> +    }
>>> +
>>> +    packet = g_malloc0(sizeof(*packet) + migration->data_buffer_size);
>>> +
>>> +    for (idx = 0; ; idx++) {
>>> +        ssize_t data_size;
>>> +        size_t packet_size;
>>> +
>>> +        if (qatomic_read(abort_flag)) {
>>> +            ret = -ECANCELED;
>>> +            goto ret_finish;
>>> +        }
>>> +
>>> +        data_size = read(migration->data_fd, &packet->data,
>>> +                         migration->data_buffer_size);
>>> +        if (data_size < 0) {
>>> +            ret = -errno;
>>> +            goto ret_finish;
>>> +        } else if (data_size == 0) {
>>> +            break;
>>> +        }
>>> +
>>> +        packet->idx = idx;
>>> +        packet_size = sizeof(*packet) + data_size;
>>> +
>>> +        if (!multifd_queue_device_state(idstr, instance_id,
>>> +                                        (char *)packet, packet_size)) {
>>> +            ret = -1;
>>> +            goto ret_finish;
>>> +        }
>>> +
>>> +        qatomic_add(&bytes_transferred, packet_size);
>>> +    }
>>> +
>>> +    ret = vfio_save_complete_precopy_async_thread_config_state(vbasedev, idstr,
>>> +                                                               instance_id,
>>> +                                                               idx);
>>
>> I am not sure it's safe to save the config space asyncly in the thread, as it might be dependent on other device's non-iterable state being loaded first.
>> See commit d329f5032e17 ("vfio: Move the saving of the config space to the right place in VFIO migration") which moved config space saving to the non-iterable state saving.
> 
> That's an important information - thanks for pointing this out.
> 
> Since we don't want to lose this config state saving parallelism
> (and the future config state saving parallelism) on unaffected platform
> we'll probably need to disable this functionality for ARM64.
> 
> By the way, this kind of an implicit dependency in VMState between devices
> is really hard to manage, there should be a way to specify it in code somehow..

vmstate has a MigrationPriority field to order loading between
devices. Maybe we could extend but I think it is better to handle
ordering at the device level when there are no external dependencies.
It should be well documented though in the code.



Thanks,

C.


> 
>> Thanks.
> 
> Thanks,
> Maciej
> 



  reply	other threads:[~2024-12-12 11:11 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
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 [this message]
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=80c9dfc4-4105-4e48-bcae-4fa9780a43c8@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).