On 21.10.25 02:51, Raphael Norwitz wrote:
> For now a naming nit and a question.
>
> On Thu, Oct 16, 2025 at 7:44 AM Vladimir Sementsov-Ogievskiy
> <vsementsov@yandex-team.ru> wrote:
>>
>> Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
>> ---
>> hw/virtio/vhost-user.c | 95 ++++++++++++++++++++++++++++++++++
>> include/hw/virtio/vhost-user.h | 4 ++
>> 2 files changed, 99 insertions(+)
>>
>> diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
>> index c5cb5ed528..a820214188 100644
>> --- a/hw/virtio/vhost-user.c
>> +++ b/hw/virtio/vhost-user.c
>> @@ -28,6 +28,8 @@
>> #include "system/runstate.h"
>> #include "system/cryptodev.h"
>> #include "migration/postcopy-ram.h"
>> +#include "migration/qemu-file-types.h"
>> +#include "migration/qemu-file.h"
>> #include "trace.h"
>> #include "system/ramblock.h"
>>
>> @@ -3137,6 +3139,99 @@ void vhost_user_qmp_status(struct vhost_dev *dev, VirtioStatus *status)
>> qmp_decode_protocols(u->protocol_features);
>> }
>>
>> +typedef struct VhostUserMigTmp {
>> + struct vhost_dev *parent;
>> + bool has_backend_channel;
>> + int backend_fd;
>> + uint32_t memory_slots;
>> + uint64_t protocol_features;
>> +} VhostUserMigTmp;
>> +
>> +static int vhost_user_tmp_pre_save(void *opaque)
>> +{
>> + VhostUserMigTmp *tmp = opaque;
>> + struct vhost_dev *dev = tmp->parent;
>> + struct vhost_user *u = dev->opaque;
>> + QIOChannelSocket *sioc = u->backend_sioc;
>> +
>> + if (sioc && sioc->fd < 0) {
>> + return -EINVAL;
>> + }
>> +
>> + tmp->backend_fd = sioc ? sioc->fd : -1;
>> + tmp->has_backend_channel = !!sioc;
>> + tmp->memory_slots = u->user->memory_slots;
>> + tmp->protocol_features = u->protocol_features;
>> +
>> + return 0;
>> +}
>> +
>> +static int vhost_user_tmp_post_load(void *opaque, int version_id)
>> +{
>> + struct VhostUserMigTmp *tmp = opaque;
>> + struct vhost_dev *dev = tmp->parent;
>> + struct vhost_user *u = dev->opaque;
>> + Error *local_err = NULL;
>> +
>> + if (tmp->has_backend_channel) {
>> + u->backend_sioc = qio_channel_socket_new_fd(tmp->backend_fd,
>> + &local_err);
>> + if (!u->backend_sioc) {
>> + error_report_err(local_err);
>> + return -EINVAL;
>> + }
>> + u->backend_src = qio_channel_add_watch_source(
>> + QIO_CHANNEL(u->backend_sioc), G_IO_IN | G_IO_HUP,
>> + backend_read, u->dev, NULL, NULL);
>> + }
>> +
>> + u->user->memory_slots = tmp->memory_slots;
>> + u->protocol_features = tmp->protocol_features;
>> +
>> + return 0;
>> +}
>> +
>> +static bool vhost_user_tmp_test_fd(void *opaque, int version_id)
>> +{
>> + struct VhostUserMigTmp *tmp = opaque;
>> +
>> + return tmp->has_backend_channel;
>> +}
>> +
>
> Will this be vhost-user-blk specific? It should probably be something
> like vhost_user_backend_transfer_tmp?
>
Oh right. a mistake.
>> +static const VMStateDescription vmstate_vhost_user_blk_tmp = {
>> + .name = "vhost-user-blk-tmp",
>> + .pre_save = vhost_user_tmp_pre_save,
>> + .post_load = vhost_user_tmp_post_load,
>> + .fields = (const VMStateField[]) {
>> + VMSTATE_UINT64(protocol_features, VhostUserMigTmp),
>> + VMSTATE_UINT32(memory_slots, VhostUserMigTmp),
>> + VMSTATE_BOOL(has_backend_channel, VhostUserMigTmp),
>> + VMSTATE_FD_TEST(backend_fd, VhostUserMigTmp, vhost_user_tmp_test_fd),
>> + VMSTATE_END_OF_LIST()
>> + },
>> +};
>> +
>> +static int vhost_user_post_load(void *opaque, int version_id)
>> +{
>> + struct vhost_dev *dev = opaque;
>> + struct vhost_user *u = dev->opaque;
>> +
>> + u->postcopy_notifier.notify = vhost_user_postcopy_notifier;
>> + postcopy_add_notifier(&u->postcopy_notifier);
>> +
>> + return 0;
>> +}
>> +
>
> Why do we need a second post_load() callback here? Why can't
> u->postcopy_notifier.notify be set in vhost_user_tmp_post_load()?
Hmm.. Yes, looks strange, I don't remember. Will try to merge.
>
>
>> +const VMStateDescription vmstate_vhost_user = {
>> + .name = "vhost-user",
>> + .post_load = vhost_user_post_load,
>> + .fields = (const VMStateField[]) {
>> + VMSTATE_WITH_TMP(struct vhost_dev, VhostUserMigTmp,
>> + vmstate_vhost_user_blk_tmp),
>> + VMSTATE_END_OF_LIST()
>> + }
>> +};
>> +
>> const VhostOps user_ops = {
>> .backend_type = VHOST_BACKEND_TYPE_USER,
>> .vhost_backend_init = vhost_user_backend_init,
>> diff --git a/include/hw/virtio/vhost-user.h b/include/hw/virtio/vhost-user.h
>> index 36d96296a3..fb89268de2 100644
>> --- a/include/hw/virtio/vhost-user.h
>> +++ b/include/hw/virtio/vhost-user.h
>> @@ -114,4 +114,8 @@ void vhost_user_async_close(DeviceState *d,
>>
>> void vhost_user_qmp_status(struct vhost_dev *dev, VirtioStatus *status);
>>
>> +extern const VMStateDescription vmstate_vhost_user;
>> +#define VMSTATE_BACKEND_TRANSFER_VHOST_USER(_field, _state) \
>> + VMSTATE_STRUCT(_field, _state, 0, vmstate_vhost_user, struct vhost_dev)
>> +
>> #endif
>> --
>> 2.48.1
>>
>>
--
Best regards,
Vladimir