From nobody Fri Nov 14 21:05:54 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=yandex-team.ru ARC-Seal: i=1; a=rsa-sha256; t=1761693368; cv=none; d=zohomail.com; s=zohoarc; b=XE2JrJ72hPUOPMZDXx8o00qxDZt/z7SVVKVPeYPL3zWXZjzHi4efE8HGIc6oZs+eoqTbBISOIlGxOMuNPEUHlCxUQt0S5/ivdzq1gLIaKz5QKUpjU5IZHtdChz0HGbYhrP8/RXMAWPryA9p/sHompmSxPHge+5Gj7Ac9VSc/hnY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1761693368; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=p+nRtrNPovY55BdLG50N9jkuwP8uMv1quoi1fFi1LL4=; b=NoJGbBjSFy756ZVS7HByEYhLAPqQ48jy2if6RAm8q2Ey/oUKkGCYuFq0YSmCM9jMac7MIORV2jjb9yUiGpGwuJpNDcglHFbVCg5/+cTgcOStgwhPz1TM+P7Pj6Pon0wKEtlSueSKL6vUv16HqsBzGrcfqt8NsixmOS/x9R+yo3o= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1761693368036753.9303382505751; Tue, 28 Oct 2025 16:16:08 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vDstW-0002yT-AI; Tue, 28 Oct 2025 19:14:26 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vDstT-0002we-Uu for qemu-devel@nongnu.org; Tue, 28 Oct 2025 19:14:24 -0400 Received: from forwardcorp1b.mail.yandex.net ([2a02:6b8:c02:900:1:45:d181:df01]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vDstL-00017L-2v for qemu-devel@nongnu.org; Tue, 28 Oct 2025 19:14:23 -0400 Received: from mail-nwsmtp-smtp-corp-canary-81.sas.yp-c.yandex.net (mail-nwsmtp-smtp-corp-canary-81.sas.yp-c.yandex.net [IPv6:2a02:6b8:c10:49f:0:640:b99a:0]) by forwardcorp1b.mail.yandex.net (Yandex) with ESMTPS id 4887F81765; Wed, 29 Oct 2025 02:14:00 +0300 (MSK) Received: from vsementsov-lin.. (unknown [2a02:6bf:8080:582::1:19]) by mail-nwsmtp-smtp-corp-canary-81.sas.yp-c.yandex.net (smtpcorp/Yandex) with ESMTPSA id oDnXpg2bCW20-CMWkYUWR; Wed, 29 Oct 2025 02:13:59 +0300 X-Yandex-Fwd: 1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yandex-team.ru; s=default; t=1761693239; bh=p+nRtrNPovY55BdLG50N9jkuwP8uMv1quoi1fFi1LL4=; h=Message-ID:Date:In-Reply-To:Cc:Subject:References:To:From; b=RKL/BrIqwq6WUN4kJdnyWEOkzi2suqmvqAo22/xkimWjBgbq8GTp7yHY6r4Tj2b6g j/emSDPUlsFf2J3tY8HXnZOpqDrp2geqT3WgUE5iQurLCFh4okIbiEPL3PoB1QEp2x OxlpC3EBHm+OQ0S1s8xjR+kIh/aJbjRbw4waZ/9o= Authentication-Results: mail-nwsmtp-smtp-corp-canary-81.sas.yp-c.yandex.net; dkim=pass header.i=@yandex-team.ru From: Vladimir Sementsov-Ogievskiy To: peterx@redhat.com Cc: armbru@redhat.com, vsementsov@yandex-team.ru, qemu-devel@nongnu.org Subject: [RFC 12/22] hw/virtio: move to new migration APIs Date: Wed, 29 Oct 2025 02:13:36 +0300 Message-ID: <20251028231347.194844-13-vsementsov@yandex-team.ru> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20251028231347.194844-1-vsementsov@yandex-team.ru> References: <20251028231347.194844-1-vsementsov@yandex-team.ru> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2a02:6b8:c02:900:1:45:d181:df01; envelope-from=vsementsov@yandex-team.ru; helo=forwardcorp1b.mail.yandex.net X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @yandex-team.ru) X-ZM-MESSAGEID: 1761693371510158500 Content-Type: text/plain; charset="utf-8" Signed-off-by: Vladimir Sementsov-Ogievskiy --- hw/virtio/vhost-user-fs.c | 65 ++++++++++++++-------------- hw/virtio/virtio-mmio.c | 10 +++-- hw/virtio/virtio-pci.c | 10 +++-- hw/virtio/virtio.c | 78 ++++++++++++++++++++-------------- include/hw/virtio/virtio-bus.h | 4 +- include/hw/virtio/virtio.h | 2 - 6 files changed, 94 insertions(+), 75 deletions(-) diff --git a/hw/virtio/vhost-user-fs.c b/hw/virtio/vhost-user-fs.c index e77c69eb12..84a7663ea8 100644 --- a/hw/virtio/vhost-user-fs.c +++ b/hw/virtio/vhost-user-fs.c @@ -306,9 +306,11 @@ static struct vhost_dev *vuf_get_vhost(VirtIODevice *v= dev) /** * Fetch the internal state from virtiofsd and save it to `f`. */ -static int vuf_save_state(QEMUFile *f, void *pv, size_t size, - const VMStateField *field, JSONWriter *vmdesc) +static bool vuf_save_state(QEMUFile *f, void *pv, size_t size, + const VMStateField *field, JSONWriter *vmdesc, + Error **errp) { + ERRP_GUARD(); VirtIODevice *vdev =3D pv; VHostUserFS *fs =3D VHOST_USER_FS(vdev); Error *local_error =3D NULL; @@ -316,39 +318,39 @@ static int vuf_save_state(QEMUFile *f, void *pv, size= _t size, =20 ret =3D vhost_save_backend_state(&fs->vhost_dev, f, &local_error); if (ret < 0) { - error_reportf_err(local_error, - "Error saving back-end state of %s device %s " - "(tag: \"%s\"): ", - vdev->name, vdev->parent_obj.canonical_path, - fs->conf.tag ?: ""); - return ret; + error_prepend(errp, + "Error saving back-end state of %s device %s " + "(tag: \"%s\"): ", + vdev->name, vdev->parent_obj.canonical_path, + fs->conf.tag ?: ""); + return false; } =20 - return 0; + return true; } =20 /** * Load virtiofsd's internal state from `f` and send it over to virtiofsd. */ -static int vuf_load_state(QEMUFile *f, void *pv, size_t size, - const VMStateField *field) +static bool vuf_load_state(QEMUFile *f, void *pv, size_t size, + const VMStateField *field, Error **errp) { + ERRP_GUARD(); VirtIODevice *vdev =3D pv; VHostUserFS *fs =3D VHOST_USER_FS(vdev); - Error *local_error =3D NULL; int ret; =20 - ret =3D vhost_load_backend_state(&fs->vhost_dev, f, &local_error); + ret =3D vhost_load_backend_state(&fs->vhost_dev, f, errp); if (ret < 0) { - error_reportf_err(local_error, - "Error loading back-end state of %s device %s " - "(tag: \"%s\"): ", - vdev->name, vdev->parent_obj.canonical_path, - fs->conf.tag ?: ""); - return ret; + error_prepend(errp, + "Error loading back-end state of %s device %s " + "(tag: \"%s\"): ", + vdev->name, vdev->parent_obj.canonical_path, + fs->conf.tag ?: ""); + return false; } =20 - return 0; + return true; } =20 static bool vuf_is_internal_migration(void *opaque) @@ -357,20 +359,21 @@ static bool vuf_is_internal_migration(void *opaque) return true; } =20 -static int vuf_check_migration_support(void *opaque) +static bool vuf_check_migration_support(void *opaque, Error **errp) { VirtIODevice *vdev =3D opaque; VHostUserFS *fs =3D VHOST_USER_FS(vdev); =20 if (!vhost_supports_device_state(&fs->vhost_dev)) { - error_report("Back-end of %s device %s (tag: \"%s\") does not supp= ort " - "migration through qemu", - vdev->name, vdev->parent_obj.canonical_path, - fs->conf.tag ?: ""); - return -ENOTSUP; + error_setg(errp, + "Back-end of %s device %s (tag: \"%s\") does not suppor= t " + "migration through qemu", + vdev->name, vdev->parent_obj.canonical_path, + fs->conf.tag ?: ""); + return false; } =20 - return 0; + return true; } =20 static const VMStateDescription vuf_backend_vmstate; @@ -392,15 +395,15 @@ static const VMStateDescription vuf_backend_vmstate = =3D { .name =3D "vhost-user-fs-backend", .version_id =3D 0, .needed =3D vuf_is_internal_migration, - .pre_load =3D vuf_check_migration_support, - .pre_save =3D vuf_check_migration_support, + .pre_load_errp =3D vuf_check_migration_support, + .pre_save_errp =3D vuf_check_migration_support, .fields =3D (const VMStateField[]) { { .name =3D "back-end", .info =3D &(const VMStateInfo) { .name =3D "virtio-fs back-end state", - .get =3D vuf_load_state, - .put =3D vuf_save_state, + .load =3D vuf_load_state, + .save =3D vuf_save_state, }, }, VMSTATE_END_OF_LIST() diff --git a/hw/virtio/virtio-mmio.c b/hw/virtio/virtio-mmio.c index fb58c36452..9d37ee029b 100644 --- a/hw/virtio/virtio-mmio.c +++ b/hw/virtio/virtio-mmio.c @@ -609,18 +609,20 @@ static const VMStateDescription vmstate_virtio_mmio = =3D { } }; =20 -static void virtio_mmio_save_extra_state(DeviceState *opaque, QEMUFile *f) +static bool virtio_mmio_save_extra_state(DeviceState *opaque, QEMUFile *f, + Error **errp) { VirtIOMMIOProxy *proxy =3D VIRTIO_MMIO(opaque); =20 - vmstate_save_state(f, &vmstate_virtio_mmio, proxy, NULL, &error_fatal); + return vmstate_save_vmsd(f, &vmstate_virtio_mmio, proxy, NULL, errp); } =20 -static int virtio_mmio_load_extra_state(DeviceState *opaque, QEMUFile *f) +static bool virtio_mmio_load_extra_state(DeviceState *opaque, QEMUFile *f, + Error **errp) { VirtIOMMIOProxy *proxy =3D VIRTIO_MMIO(opaque); =20 - return vmstate_load_state(f, &vmstate_virtio_mmio, proxy, 1, &error_fa= tal); + return vmstate_load_vmsd(f, &vmstate_virtio_mmio, proxy, 1, errp); } =20 static bool virtio_mmio_has_extra_state(DeviceState *opaque) diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index 937e22f08a..95faa84a58 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -184,18 +184,20 @@ static bool virtio_pci_has_extra_state(DeviceState *d) return true; } =20 -static void virtio_pci_save_extra_state(DeviceState *d, QEMUFile *f) +static bool virtio_pci_save_extra_state(DeviceState *d, QEMUFile *f, + Error **errp) { VirtIOPCIProxy *proxy =3D to_virtio_pci_proxy(d); =20 - vmstate_save_state(f, &vmstate_virtio_pci, proxy, NULL, &error_fatal); + return vmstate_save_vmsd(f, &vmstate_virtio_pci, proxy, NULL, errp); } =20 -static int virtio_pci_load_extra_state(DeviceState *d, QEMUFile *f) +static bool virtio_pci_load_extra_state(DeviceState *d, QEMUFile *f, + Error **errp) { VirtIOPCIProxy *proxy =3D to_virtio_pci_proxy(d); =20 - return vmstate_load_state(f, &vmstate_virtio_pci, proxy, 1, &error_fat= al); + return vmstate_load_vmsd(f, &vmstate_virtio_pci, proxy, 1, errp); } =20 static void virtio_pci_save_queue(DeviceState *d, int n, QEMUFile *f) diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index 153ee0a0cf..36e0493344 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -2873,35 +2873,37 @@ static const VMStateDescription vmstate_virtio_ring= size =3D { } }; =20 -static int get_extra_state(QEMUFile *f, void *pv, size_t size, - const VMStateField *field) +static bool load_extra_state(QEMUFile *f, void *pv, size_t size, + const VMStateField *field, + Error **errp) { VirtIODevice *vdev =3D pv; BusState *qbus =3D qdev_get_parent_bus(DEVICE(vdev)); VirtioBusClass *k =3D VIRTIO_BUS_GET_CLASS(qbus); =20 if (!k->load_extra_state) { - return -1; + error_setg(errp, "extra state is unsupported"); + return false; } else { - return k->load_extra_state(qbus->parent, f); + return k->load_extra_state(qbus->parent, f, errp); } } =20 -static int put_extra_state(QEMUFile *f, void *pv, size_t size, - const VMStateField *field, JSONWriter *vmdesc) +static bool save_extra_state(QEMUFile *f, void *pv, size_t size, + const VMStateField *field, JSONWriter *vmdesc, + Error **errp) { VirtIODevice *vdev =3D pv; BusState *qbus =3D qdev_get_parent_bus(DEVICE(vdev)); VirtioBusClass *k =3D VIRTIO_BUS_GET_CLASS(qbus); =20 - k->save_extra_state(qbus->parent, f); - return 0; + return k->save_extra_state(qbus->parent, f, errp); } =20 static const VMStateInfo vmstate_info_extra_state =3D { .name =3D "virtqueue_extra_state", - .get =3D get_extra_state, - .put =3D put_extra_state, + .load =3D load_extra_state, + .save =3D save_extra_state, }; =20 static const VMStateDescription vmstate_virtio_extra_state =3D { @@ -3024,14 +3026,13 @@ static const VMStateDescription vmstate_virtio =3D { } }; =20 -int virtio_save(VirtIODevice *vdev, QEMUFile *f) +static bool virtio_save(VirtIODevice *vdev, QEMUFile *f, Error **errp) { BusState *qbus =3D qdev_get_parent_bus(DEVICE(vdev)); VirtioBusClass *k =3D VIRTIO_BUS_GET_CLASS(qbus); VirtioDeviceClass *vdc =3D VIRTIO_DEVICE_GET_CLASS(vdev); uint32_t guest_features_lo =3D (vdev->guest_features & 0xffffffff); int i; - Error *local_err =3D NULL; =20 if (k->save_config) { k->save_config(qbus->parent, f); @@ -3075,39 +3076,54 @@ int virtio_save(VirtIODevice *vdev, QEMUFile *f) } =20 if (vdc->vmsd) { - int ret =3D vmstate_save_state(f, vdc->vmsd, vdev, NULL, &local_er= r); - if (ret) { - error_report_err(local_err); - return ret; + if (!vmstate_save_vmsd(f, vdc->vmsd, vdev, NULL, errp)) { + return false; } } =20 /* Subsections */ - return vmstate_save_state(f, &vmstate_virtio, vdev, NULL, &error_fatal= ); + return vmstate_save_vmsd(f, &vmstate_virtio, vdev, NULL, &error_fatal); } =20 /* A wrapper for use as a VMState .put function */ -static int virtio_device_put(QEMUFile *f, void *opaque, size_t size, - const VMStateField *field, JSONWriter *vmdes= c) +static bool virtio_device_save(QEMUFile *f, void *opaque, size_t size, + const VMStateField *field, JSONWriter *vmde= sc, + Error **errp) { - return virtio_save(VIRTIO_DEVICE(opaque), f); + return virtio_save(VIRTIO_DEVICE(opaque), f, errp); } =20 /* A wrapper for use as a VMState .get function */ -static int coroutine_mixed_fn -virtio_device_get(QEMUFile *f, void *opaque, size_t size, - const VMStateField *field) +static bool coroutine_mixed_fn +virtio_device_load(QEMUFile *f, void *opaque, size_t size, + const VMStateField *field, Error **errp) { VirtIODevice *vdev =3D VIRTIO_DEVICE(opaque); DeviceClass *dc =3D DEVICE_CLASS(VIRTIO_DEVICE_GET_CLASS(vdev)); =20 - return virtio_load(vdev, f, dc->vmsd->version_id); + /* TODO: update virtio_load() to set errp and return bool */ + int ret =3D virtio_load(vdev, f, dc->vmsd->version_id); + + if (ret < 0) { + /* + * Using error_setg_errn or strerror would be incorrect, + * because virtio_load may mix simple -1 with -errno + * values on different paths. + * + * TODO: update virtio_load and all related callbacks + * to "errp + boolean return value" API. + */ + error_setg(errp, "virtio_load failed: %d", ret); + return false; + } + + return true; } =20 const VMStateInfo virtio_vmstate_info =3D { .name =3D "virtio", - .get =3D virtio_device_get, - .put =3D virtio_device_put, + .load =3D virtio_device_load, + .save =3D virtio_device_save, }; =20 static int virtio_set_features_nocheck(VirtIODevice *vdev, const uint64_t = *val) @@ -3387,18 +3403,16 @@ virtio_load(VirtIODevice *vdev, QEMUFile *f, int ve= rsion_id) } =20 if (vdc->vmsd) { - ret =3D vmstate_load_state(f, vdc->vmsd, vdev, version_id, &local_= err); - if (ret) { + if (!vmstate_load_vmsd(f, vdc->vmsd, vdev, version_id, &local_err)= ) { error_report_err(local_err); - return ret; + return -EINVAL; } } =20 /* Subsections */ - ret =3D vmstate_load_state(f, &vmstate_virtio, vdev, 1, &local_err); - if (ret) { + if (!vmstate_load_vmsd(f, &vmstate_virtio, vdev, 1, &local_err)) { error_report_err(local_err); - return ret; + return -EINVAL; } =20 if (vdev->device_endian =3D=3D VIRTIO_DEVICE_ENDIAN_UNKNOWN) { diff --git a/include/hw/virtio/virtio-bus.h b/include/hw/virtio/virtio-bus.h index 7ab8c9dab0..31bf2cd607 100644 --- a/include/hw/virtio/virtio-bus.h +++ b/include/hw/virtio/virtio-bus.h @@ -42,11 +42,11 @@ struct VirtioBusClass { void (*notify)(DeviceState *d, uint16_t vector); void (*save_config)(DeviceState *d, QEMUFile *f); void (*save_queue)(DeviceState *d, int n, QEMUFile *f); - void (*save_extra_state)(DeviceState *d, QEMUFile *f); + bool (*save_extra_state)(DeviceState *d, QEMUFile *f, Error **errp); int (*load_config)(DeviceState *d, QEMUFile *f); int (*load_queue)(DeviceState *d, int n, QEMUFile *f); int (*load_done)(DeviceState *d, QEMUFile *f); - int (*load_extra_state)(DeviceState *d, QEMUFile *f); + bool (*load_extra_state)(DeviceState *d, QEMUFile *f, Error **errp); bool (*has_extra_state)(DeviceState *d); bool (*query_guest_notifiers)(DeviceState *d); int (*set_guest_notifiers)(DeviceState *d, int nvqs, bool assign); diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index d97529c3f1..d729502eca 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -296,8 +296,6 @@ int virtqueue_get_avail_bytes(VirtQueue *vq, unsigned i= nt *in_bytes, =20 void virtio_notify(VirtIODevice *vdev, VirtQueue *vq); =20 -int virtio_save(VirtIODevice *vdev, QEMUFile *f); - extern const VMStateInfo virtio_vmstate_info; =20 #define VMSTATE_VIRTIO_DEVICE \ --=20 2.48.1