[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH v2 06/20] vfio/common: Abort migration if dirty log start/stop/sy
From: |
Avihai Horon |
Subject: |
[PATCH v2 06/20] vfio/common: Abort migration if dirty log start/stop/sync fails |
Date: |
Wed, 22 Feb 2023 19:49:01 +0200 |
If VFIO dirty pages log start/stop/sync fails during migration,
migration should be aborted as pages dirtied by VFIO devices might not
be reported properly.
This is not the case today, where in such scenario only an error is
printed.
Fix it by aborting migration in the above scenario.
Fixes: 758b96b61d5c ("vfio/migrate: Move switch of dirty tracking into
vfio_memory_listener")
Fixes: b6dd6504e303 ("vfio: Add vfio_listener_log_sync to mark dirty pages")
Fixes: 9e7b0442f23a ("vfio: Add ioctl to get dirty pages bitmap during dma
unmap")
Signed-off-by: Avihai Horon <avihaih@nvidia.com>
Reviewed-by: Cédric Le Goater <clg@redhat.com>
---
hw/vfio/common.c | 53 ++++++++++++++++++++++++++++++++++++++++--------
1 file changed, 45 insertions(+), 8 deletions(-)
diff --git a/hw/vfio/common.c b/hw/vfio/common.c
index 930eda40a1..ac93b85632 100644
--- a/hw/vfio/common.c
+++ b/hw/vfio/common.c
@@ -42,6 +42,7 @@
#include "migration/migration.h"
#include "migration/misc.h"
#include "migration/blocker.h"
+#include "migration/qemu-file.h"
#include "sysemu/tpm.h"
VFIOGroupList vfio_group_list =
@@ -390,6 +391,19 @@ void vfio_unblock_multiple_devices_migration(void)
multiple_devices_migration_blocker = NULL;
}
+static void vfio_set_migration_error(int err)
+{
+ MigrationState *ms = migrate_get_current();
+
+ if (migration_is_setup_or_active(ms->state)) {
+ WITH_QEMU_LOCK_GUARD(&ms->qemu_file_lock) {
+ if (ms->to_dst_file) {
+ qemu_file_set_error(ms->to_dst_file, err);
+ }
+ }
+ }
+}
+
static bool vfio_devices_all_dirty_tracking(VFIOContainer *container)
{
VFIOGroup *group;
@@ -682,6 +696,7 @@ static void vfio_iommu_map_notify(IOMMUNotifier *n,
IOMMUTLBEntry *iotlb)
if (iotlb->target_as != &address_space_memory) {
error_report("Wrong target AS \"%s\", only system memory is allowed",
iotlb->target_as->name ? iotlb->target_as->name : "none");
+ vfio_set_migration_error(-EINVAL);
return;
}
@@ -716,6 +731,7 @@ static void vfio_iommu_map_notify(IOMMUNotifier *n,
IOMMUTLBEntry *iotlb)
"0x%"HWADDR_PRIx") = %d (%s)",
container, iova,
iotlb->addr_mask + 1, ret, strerror(-ret));
+ vfio_set_migration_error(ret);
}
}
out:
@@ -1261,7 +1277,7 @@ static void vfio_listener_region_del(MemoryListener
*listener,
}
}
-static void vfio_set_dirty_page_tracking(VFIOContainer *container, bool start)
+static int vfio_set_dirty_page_tracking(VFIOContainer *container, bool start)
{
int ret;
struct vfio_iommu_type1_dirty_bitmap dirty = {
@@ -1269,7 +1285,7 @@ static void vfio_set_dirty_page_tracking(VFIOContainer
*container, bool start)
};
if (!container->dirty_pages_supported) {
- return;
+ return 0;
}
if (start) {
@@ -1280,23 +1296,34 @@ static void vfio_set_dirty_page_tracking(VFIOContainer
*container, bool start)
ret = ioctl(container->fd, VFIO_IOMMU_DIRTY_PAGES, &dirty);
if (ret) {
+ ret = -errno;
error_report("Failed to set dirty tracking flag 0x%x errno: %d",
dirty.flags, errno);
}
+
+ return ret;
}
static void vfio_listener_log_global_start(MemoryListener *listener)
{
VFIOContainer *container = container_of(listener, VFIOContainer, listener);
+ int ret;
- vfio_set_dirty_page_tracking(container, true);
+ ret = vfio_set_dirty_page_tracking(container, true);
+ if (ret) {
+ vfio_set_migration_error(ret);
+ }
}
static void vfio_listener_log_global_stop(MemoryListener *listener)
{
VFIOContainer *container = container_of(listener, VFIOContainer, listener);
+ int ret;
- vfio_set_dirty_page_tracking(container, false);
+ ret = vfio_set_dirty_page_tracking(container, false);
+ if (ret) {
+ vfio_set_migration_error(ret);
+ }
}
static int vfio_get_dirty_bitmap(VFIOContainer *container, uint64_t iova,
@@ -1372,19 +1399,18 @@ static void vfio_iommu_map_dirty_notify(IOMMUNotifier
*n, IOMMUTLBEntry *iotlb)
VFIOContainer *container = giommu->container;
hwaddr iova = iotlb->iova + giommu->iommu_offset;
ram_addr_t translated_addr;
+ int ret = -EINVAL;
trace_vfio_iommu_map_dirty_notify(iova, iova + iotlb->addr_mask);
if (iotlb->target_as != &address_space_memory) {
error_report("Wrong target AS \"%s\", only system memory is allowed",
iotlb->target_as->name ? iotlb->target_as->name : "none");
- return;
+ goto out;
}
rcu_read_lock();
if (vfio_get_xlat_addr(iotlb, NULL, &translated_addr, NULL)) {
- int ret;
-
ret = vfio_get_dirty_bitmap(container, iova, iotlb->addr_mask + 1,
translated_addr);
if (ret) {
@@ -1395,6 +1421,11 @@ static void vfio_iommu_map_dirty_notify(IOMMUNotifier
*n, IOMMUTLBEntry *iotlb)
}
}
rcu_read_unlock();
+
+out:
+ if (ret) {
+ vfio_set_migration_error(ret);
+ }
}
static int vfio_ram_discard_get_dirty_bitmap(MemoryRegionSection *section,
@@ -1487,13 +1518,19 @@ static void vfio_listener_log_sync(MemoryListener
*listener,
MemoryRegionSection *section)
{
VFIOContainer *container = container_of(listener, VFIOContainer, listener);
+ int ret;
if (vfio_listener_skipped_section(section)) {
return;
}
if (vfio_devices_all_dirty_tracking(container)) {
- vfio_sync_dirty_bitmap(container, section);
+ ret = vfio_sync_dirty_bitmap(container, section);
+ if (ret) {
+ error_report("vfio: Failed to sync dirty bitmap, err: %d (%s)",
ret,
+ strerror(-ret));
+ vfio_set_migration_error(ret);
+ }
}
}
--
2.26.3
- [PATCH v2 01/20] migration: Pass threshold_size to .state_pending_{estimate, exact}(), (continued)
- [PATCH v2 01/20] migration: Pass threshold_size to .state_pending_{estimate, exact}(), Avihai Horon, 2023/02/22
- [PATCH v2 02/20] vfio/migration: Refactor vfio_save_block() to return saved data size, Avihai Horon, 2023/02/22
- [PATCH v2 04/20] vfio/common: Fix error reporting in vfio_get_dirty_bitmap(), Avihai Horon, 2023/02/22
- [PATCH v2 07/20] vfio/common: Add VFIOBitmap and (de)alloc functions, Avihai Horon, 2023/02/22
- [PATCH v2 09/20] util: Extend iova_tree_foreach() to take data argument, Avihai Horon, 2023/02/22
- [PATCH v2 05/20] vfio/common: Fix wrong %m usages, Avihai Horon, 2023/02/22
- [PATCH v2 06/20] vfio/common: Abort migration if dirty log start/stop/sync fails,
Avihai Horon <=
- [PATCH v2 03/20] vfio/migration: Add VFIO migration pre-copy support, Avihai Horon, 2023/02/22
- Re: [PATCH v2 03/20] vfio/migration: Add VFIO migration pre-copy support, Alex Williamson, 2023/02/22
- Re: [PATCH v2 03/20] vfio/migration: Add VFIO migration pre-copy support, Avihai Horon, 2023/02/23
- Re: [PATCH v2 03/20] vfio/migration: Add VFIO migration pre-copy support, Alex Williamson, 2023/02/23
- Re: [PATCH v2 03/20] vfio/migration: Add VFIO migration pre-copy support, Avihai Horon, 2023/02/26
- Re: [PATCH v2 03/20] vfio/migration: Add VFIO migration pre-copy support, Alex Williamson, 2023/02/27
- Re: [PATCH v2 03/20] vfio/migration: Add VFIO migration pre-copy support, Jason Gunthorpe, 2023/02/27
- Re: [PATCH v2 03/20] vfio/migration: Add VFIO migration pre-copy support, Alex Williamson, 2023/02/27
[PATCH v2 08/20] util: Add iova_tree_nnodes(), Avihai Horon, 2023/02/22
[PATCH v2 11/20] vfio/common: Add device dirty page tracking start/stop, Avihai Horon, 2023/02/22