[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH v7 09/13] vfio: Add save state functions to Save
From: |
Kirti Wankhede |
Subject: |
Re: [Qemu-devel] [PATCH v7 09/13] vfio: Add save state functions to SaveVMHandlers |
Date: |
Fri, 19 Jul 2019 00:15:15 +0530 |
On 7/12/2019 8:14 AM, Yan Zhao wrote:
> On Tue, Jul 09, 2019 at 05:49:16PM +0800, Kirti Wankhede wrote:
>> Added .save_live_pending, .save_live_iterate and .save_live_complete_precopy
>> functions. These functions handles pre-copy and stop-and-copy phase.
>>
>> In _SAVING|_RUNNING device state or pre-copy phase:
>> - read pending_bytes
>> - read data_offset - indicates kernel driver to write data to staging
>> buffer which is mmapped.
>> - read data_size - amount of data in bytes written by vendor driver in
>> migration
>> region.
>> - if data section is trapped, pread() from data_offset of data_size.
>> - if data section is mmaped, read mmaped buffer of data_size.
>> - Write data packet to file stream as below:
>> {VFIO_MIG_FLAG_DEV_DATA_STATE, data_size, actual data,
>> VFIO_MIG_FLAG_END_OF_STATE }
>>
>> In _SAVING device state or stop-and-copy phase
>> a. read config space of device and save to migration file stream. This
>> doesn't need to be from vendor driver. Any other special config state
>> from driver can be saved as data in following iteration.
>> b. read pending_bytes
>> c. read data_offset - indicates kernel driver to write data to staging
>> buffer which is mmapped.
>> d. read data_size - amount of data in bytes written by vendor driver in
>> migration region.
>> e. if data section is trapped, pread() from data_offset of data_size.
>> f. if data section is mmaped, read mmaped buffer of data_size.
>> g. Write data packet as below:
>> {VFIO_MIG_FLAG_DEV_DATA_STATE, data_size, actual data}
>> h. iterate through steps b to g while (pending_bytes > 0)
>> i. Write {VFIO_MIG_FLAG_END_OF_STATE}
>>
>> When data region is mapped, its user's responsibility to read data from
>> data_offset of data_size before moving to next steps.
>>
>> .save_live_iterate runs outside the iothread lock in the migration case,
>> which
>> could race with asynchronous call to get dirty page list causing data
>> corruption
>> in mapped migration region. Mutex added here to serial migration buffer read
>> operation.
>>
>> Signed-off-by: Kirti Wankhede <address@hidden>
>> Reviewed-by: Neo Jia <address@hidden>
>> ---
>> hw/vfio/migration.c | 246
>> +++++++++++++++++++++++++++++++++++++++++++++++++++
>> hw/vfio/trace-events | 6 ++
>> 2 files changed, 252 insertions(+)
>>
>> diff --git a/hw/vfio/migration.c b/hw/vfio/migration.c
>> index 0597a45fda2d..4e9b4cce230b 100644
>> --- a/hw/vfio/migration.c
>> +++ b/hw/vfio/migration.c
>> @@ -117,6 +117,138 @@ static int vfio_migration_set_state(VFIODevice
>> *vbasedev, uint32_t state)
>> return 0;
>> }
>>
>> +static void *find_data_region(VFIORegion *region,
>> + uint64_t data_offset,
>> + uint64_t data_size)
>> +{
>> + void *ptr = NULL;
>> + int i;
>> +
>> + for (i = 0; i < region->nr_mmaps; i++) {
>> + if ((data_offset >= region->mmaps[i].offset) &&
>> + (data_offset < region->mmaps[i].offset + region->mmaps[i].size)
>> &&
>> + (data_size <= region->mmaps[i].size)) {
>> + ptr = region->mmaps[i].mmap + (data_offset -
>> + region->mmaps[i].offset);
>> + break;
>> + }
>> + }
>> + return ptr;
>> +}
>> +
>> +static int vfio_save_buffer(QEMUFile *f, VFIODevice *vbasedev)
>> +{
>> + VFIOMigration *migration = vbasedev->migration;
>> + VFIORegion *region = &migration->region.buffer;
>> + uint64_t data_offset = 0, data_size = 0;
>> + int ret;
>> +
>> + ret = pread(vbasedev->fd, &data_offset, sizeof(data_offset),
>> + region->fd_offset + offsetof(struct
>> vfio_device_migration_info,
>> + data_offset));
>> + if (ret != sizeof(data_offset)) {
>> + error_report("%s: Failed to get migration buffer data offset %d",
>> + vbasedev->name, ret);
>> + return -EINVAL;
>> + }
>> +
>> + ret = pread(vbasedev->fd, &data_size, sizeof(data_size),
>> + region->fd_offset + offsetof(struct
>> vfio_device_migration_info,
>> + data_size));
>> + if (ret != sizeof(data_size)) {
>> + error_report("%s: Failed to get migration buffer data size %d",
>> + vbasedev->name, ret);
>> + return -EINVAL;
>> + }
>> +
>> + if (data_size > 0) {
>> + void *buf = NULL;
>> + bool buffer_mmaped;
>> +
>> + if (region->mmaps) {
>> + buf = find_data_region(region, data_offset, data_size);
>> + }
>> +
>> + buffer_mmaped = (buf != NULL) ? true : false;
>> +
>> + if (!buffer_mmaped) {
>> + buf = g_try_malloc0(data_size);
>> + if (!buf) {
>> + error_report("%s: Error allocating buffer ", __func__);
>> + return -ENOMEM;
>> + }
>> +
>> + ret = pread(vbasedev->fd, buf, data_size,
>> + region->fd_offset + data_offset);
>> + if (ret != data_size) {
>> + error_report("%s: Failed to get migration data %d",
>> + vbasedev->name, ret);
>> + g_free(buf);
>> + return -EINVAL;
>> + }
>> + }
>> +
>> + qemu_put_be64(f, data_size);
>> + qemu_put_buffer(f, buf, data_size);
>> +
>> + if (!buffer_mmaped) {
>> + g_free(buf);
>> + }
>> + migration->pending_bytes -= data_size;
> This line "migration->pending_bytes -= data_size;" is not necessary, as
> it will be updated anyway in vfio_update_pending()
>
Right, removing it.
Thanks,
Kirti
- Re: [Qemu-devel] [PATCH v7 06/13] vfio: Add VM state change handler to know state of VM, (continued)
Re: [Qemu-devel] [PATCH v7 06/13] vfio: Add VM state change handler to know state of VM, Alex Williamson, 2019/07/16
Re: [Qemu-devel] [PATCH v7 06/13] vfio: Add VM state change handler to know state of VM, Yan Zhao, 2019/07/22
[Qemu-devel] [PATCH v7 07/13] vfio: Add migration state change notifier, Kirti Wankhede, 2019/07/09
[Qemu-devel] [PATCH v7 08/13] vfio: Register SaveVMHandlers for VFIO device, Kirti Wankhede, 2019/07/09
[Qemu-devel] [PATCH v7 09/13] vfio: Add save state functions to SaveVMHandlers, Kirti Wankhede, 2019/07/09
[Qemu-devel] [PATCH v7 10/13] vfio: Add load state functions to SaveVMHandlers, Kirti Wankhede, 2019/07/09
[Qemu-devel] [PATCH v7 11/13] vfio: Add function to get dirty page list, Kirti Wankhede, 2019/07/09