In vhost_user_blk_stop() on incoming migration make force_stop = true,
so GET_VRING_BASE will not be executed.

Signed-off-by: Alexandr Moshkov <[email protected]>
---
 hw/block/vhost-user-blk.c | 52 +++++++++++++++++++++++++++++++++++++++
 migration/options.c       |  7 ++++++
 migration/options.h       |  1 +
 qapi/migration.json       |  9 +++++--
 4 files changed, 67 insertions(+), 2 deletions(-)

diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c
index c0cc5f6942..49f67d0451 100644
--- a/hw/block/vhost-user-blk.c
+++ b/hw/block/vhost-user-blk.c
@@ -31,6 +31,7 @@
 #include "hw/virtio/virtio-access.h"
 #include "system/system.h"
 #include "system/runstate.h"
+#include "migration/options.h"
 
 static const int user_feature_bits[] = {
     VIRTIO_BLK_F_SIZE_MAX,
@@ -224,6 +225,11 @@ static int vhost_user_blk_stop(VirtIODevice *vdev)
     force_stop = s->skip_get_vring_base_on_force_shutdown &&
                  qemu_force_shutdown_requested();
 
+    if (migrate_inflight_vhost_user_blk() &&
+        runstate_check(RUN_STATE_FINISH_MIGRATE)) {
+        force_stop = true;
+    }
+
     ret = force_stop ? vhost_dev_force_stop(&s->dev, vdev, true) :
                        vhost_dev_stop(&s->dev, vdev, true);
 
@@ -568,12 +574,58 @@ static struct vhost_dev 
*vhost_user_blk_get_vhost(VirtIODevice *vdev)
     return &s->dev;
 }
 
+static int vhost_user_blk_save(QEMUFile *f, void *pv, size_t size,
+                               const VMStateField *field, JSONWriter *vmdesc)
+{
+    VirtIODevice *vdev = pv;
+    VHostUserBlk *s = VHOST_USER_BLK(vdev);
+
+    if (!migrate_inflight_vhost_user_blk()) {
+        return 0;
+    }
+
+    vhost_dev_save_inflight(s->inflight, f);
+
+    return 0;
+}
+
+static int vhost_user_blk_load(QEMUFile *f, void *pv, size_t size,
+                               const VMStateField *field)
+{
+    VirtIODevice *vdev = pv;
+    VHostUserBlk *s = VHOST_USER_BLK(vdev);
+    int ret;
+
+    if (!migrate_inflight_vhost_user_blk()) {
+        return 0;
+    }
+
+    ret = vhost_dev_load_inflight(s->inflight, f);
+    if (ret < 0) {
+        g_autofree char *path = object_get_canonical_path(OBJECT(vdev));
+        error_report("%s [%s]: can't load in-flight requests",
+                     path, TYPE_VHOST_USER_BLK);
+        return ret;
+    }
+
+    return 0;
+}
+
 static const VMStateDescription vmstate_vhost_user_blk = {
     .name = "vhost-user-blk",
     .minimum_version_id = 1,
     .version_id = 1,
     .fields = (const VMStateField[]) {
         VMSTATE_VIRTIO_DEVICE,
+        {
+            .name = "backend state",
+            .info = &(const VMStateInfo) {
+                .name = "vhost-user-blk backend state",
+                .get = vhost_user_blk_load,
+                .put = vhost_user_blk_save,
+            },
+            .flags = VMS_SINGLE,
+        },
         VMSTATE_END_OF_LIST()
     },
 };
diff --git a/migration/options.c b/migration/options.c
index 5183112775..fcae2b4559 100644
--- a/migration/options.c
+++ b/migration/options.c
@@ -262,6 +262,13 @@ bool migrate_mapped_ram(void)
     return s->capabilities[MIGRATION_CAPABILITY_MAPPED_RAM];
 }
 
+bool migrate_inflight_vhost_user_blk(void)
+{
+    MigrationState *s = migrate_get_current();
+
+    return s->capabilities[MIGRATION_CAPABILITY_INFLIGHT_VHOST_USER_BLK];
+}
+
 bool migrate_ignore_shared(void)
 {
     MigrationState *s = migrate_get_current();
diff --git a/migration/options.h b/migration/options.h
index 82d839709e..eab1485d1a 100644
--- a/migration/options.h
+++ b/migration/options.h
@@ -30,6 +30,7 @@ bool migrate_colo(void);
 bool migrate_dirty_bitmaps(void);
 bool migrate_events(void);
 bool migrate_mapped_ram(void);
+bool migrate_inflight_vhost_user_blk(void);
 bool migrate_ignore_shared(void);
 bool migrate_late_block_activate(void);
 bool migrate_multifd(void);
diff --git a/qapi/migration.json b/qapi/migration.json
index be0f3fcc12..c9fea59515 100644
--- a/qapi/migration.json
+++ b/qapi/migration.json
@@ -517,9 +517,13 @@
 #     each RAM page.  Requires a migration URI that supports seeking,
 #     such as a file.  (since 9.0)
 #
+# @inflight-vhost-user-blk: If enabled, QEMU will migrate inflight
+#    region for vhost-user-blk.  (since 10.2)
+#
 # Features:
 #
-# @unstable: Members @x-colo and @x-ignore-shared are experimental.
+# @unstable: Members @x-colo and @x-ignore-shared,
+#     @inflight-vhost-user-blk are experimental.
 # @deprecated: Member @zero-blocks is deprecated as being part of
 #     block migration which was already removed.
 #
@@ -536,7 +540,8 @@
            { 'name': 'x-ignore-shared', 'features': [ 'unstable' ] },
            'validate-uuid', 'background-snapshot',
            'zero-copy-send', 'postcopy-preempt', 'switchover-ack',
-           'dirty-limit', 'mapped-ram'] }
+           'dirty-limit', 'mapped-ram',
+           { 'name': 'inflight-vhost-user-blk', 'features': [ 'unstable' ] } ] 
}
 
 ##
 # @MigrationCapabilityStatus:
-- 
2.34.1


Reply via email to