All of lore.kernel.org
 help / color / mirror / Atom feed
From: Fabiano Rosas <farosas@suse.de>
To: Arun Menon <armenon@redhat.com>, qemu-devel@nongnu.org
Cc: "Peter Xu" <peterx@redhat.com>,
	"Alex Bennée" <alex.bennee@linaro.org>,
	"Akihiko Odaki" <odaki@rsg.ci.i.u-tokyo.ac.jp>,
	"Dmitry Osipenko" <dmitry.osipenko@collabora.com>,
	"Michael S. Tsirkin" <mst@redhat.com>,
	"Marcel Apfelbaum" <marcel.apfelbaum@gmail.com>,
	"Cornelia Huck" <cohuck@redhat.com>,
	"Halil Pasic" <pasic@linux.ibm.com>,
	"Eric Farman" <farman@linux.ibm.com>,
	"Thomas Huth" <thuth@redhat.com>,
	"Christian Borntraeger" <borntraeger@linux.ibm.com>,
	"Matthew Rosato" <mjrosato@linux.ibm.com>,
	"Richard Henderson" <richard.henderson@linaro.org>,
	"David Hildenbrand" <david@redhat.com>,
	"Ilya Leoshkevich" <iii@linux.ibm.com>,
	"Nicholas Piggin" <npiggin@gmail.com>,
	"Harsh Prateek Bora" <harshpb@linux.ibm.com>,
	"Paolo Bonzini" <pbonzini@redhat.com>,
	"Fam Zheng" <fam@euphon.net>,
	"Alex Williamson" <alex.williamson@redhat.com>,
	"Cédric Le Goater" <clg@redhat.com>,
	"Steve Sistare" <steven.sistare@oracle.com>,
	"Marc-André Lureau" <marcandre.lureau@redhat.com>,
	qemu-s390x@nongnu.org, qemu-ppc@nongnu.org,
	"Hailiang Zhang" <zhanghailiang@xfusion.com>,
	"Stefan Berger" <stefanb@linux.vnet.ibm.com>,
	"Peter Maydell" <peter.maydell@linaro.org>,
	qemu-arm@nongnu.org, "Arun Menon" <armenon@redhat.com>
Subject: Re: [PATCH v11 02/27] migration: push Error **errp into vmstate_load_state()
Date: Fri, 15 Aug 2025 12:41:50 -0300	[thread overview]
Message-ID: <87o6sgzj5t.fsf@suse.de> (raw)
In-Reply-To: <20250813-propagate_tpm_error-v11-2-b470a374b42d@redhat.com>

Arun Menon <armenon@redhat.com> writes:

> This is an incremental step in converting vmstate loading
> code to report error via Error objects instead of directly
> printing it to console/monitor.
> It is ensured that vmstate_load_state() must report an error
> in errp, in case of failure.
>
> Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> Signed-off-by: Arun Menon <armenon@redhat.com>
> ---
>  hw/display/virtio-gpu.c     |  2 +-
>  hw/pci/pci.c                |  3 ++-
>  hw/s390x/virtio-ccw.c       |  2 +-
>  hw/scsi/spapr_vscsi.c       |  2 +-
>  hw/vfio/pci.c               |  3 ++-
>  hw/virtio/virtio-mmio.c     |  3 ++-
>  hw/virtio/virtio-pci.c      |  2 +-
>  hw/virtio/virtio.c          |  4 +--
>  include/migration/vmstate.h |  2 +-
>  migration/cpr.c             |  5 ++--
>  migration/savevm.c          |  6 +++--
>  migration/vmstate-types.c   | 22 ++++++++++++----
>  migration/vmstate.c         | 61 ++++++++++++++++++++++++++++++-------------
>  tests/unit/test-vmstate.c   | 63 ++++++++++++++++++++++++++++++++++++++-------
>  ui/vdagent.c                |  3 ++-
>  15 files changed, 136 insertions(+), 47 deletions(-)
>
> diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
> index 0a1a625b0ea6cf26cb0d799171a57ed3d3ab2442..5dc31bc6bfb0272e29a4364ab10de2595a4bedf7 100644
> --- a/hw/display/virtio-gpu.c
> +++ b/hw/display/virtio-gpu.c
> @@ -1343,7 +1343,7 @@ static int virtio_gpu_load(QEMUFile *f, void *opaque, size_t size,
>      }
>  
>      /* load & apply scanout state */
> -    vmstate_load_state(f, &vmstate_virtio_gpu_scanouts, g, 1);
> +    vmstate_load_state(f, &vmstate_virtio_gpu_scanouts, g, 1, &error_fatal);
>  
>      return 0;
>  }
> diff --git a/hw/pci/pci.c b/hw/pci/pci.c
> index c70b5ceebaf1f2b10768bd030526cbb518da2b8d..6be932d3bb67ff0c4808707db2a7b6378a90e82b 100644
> --- a/hw/pci/pci.c
> +++ b/hw/pci/pci.c
> @@ -934,7 +934,8 @@ void pci_device_save(PCIDevice *s, QEMUFile *f)
>  int pci_device_load(PCIDevice *s, QEMUFile *f)
>  {
>      int ret;
> -    ret = vmstate_load_state(f, &vmstate_pci_device, s, s->version_id);
> +    ret = vmstate_load_state(f, &vmstate_pci_device, s, s->version_id,
> +                             &error_fatal);
>      /* Restore the interrupt status bit. */
>      pci_update_irq_status(s);
>      return ret;
> diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
> index d2f85b39f30f7fc82e0c600144c0a958e1269b2c..6a9641a03d5d3a38a4de7ceb9deffc0cc303bcff 100644
> --- a/hw/s390x/virtio-ccw.c
> +++ b/hw/s390x/virtio-ccw.c
> @@ -1136,7 +1136,7 @@ static void virtio_ccw_save_config(DeviceState *d, QEMUFile *f)
>  static int virtio_ccw_load_config(DeviceState *d, QEMUFile *f)
>  {
>      VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
> -    return vmstate_load_state(f, &vmstate_virtio_ccw_dev, dev, 1);
> +    return vmstate_load_state(f, &vmstate_virtio_ccw_dev, dev, 1, &error_fatal);
>  }
>  
>  static void virtio_ccw_pre_plugged(DeviceState *d, Error **errp)
> diff --git a/hw/scsi/spapr_vscsi.c b/hw/scsi/spapr_vscsi.c
> index 20f70fb2729de78b9636a6b8c869695dab4f8902..8c896022d324f51962605288d6d6df1648c83cde 100644
> --- a/hw/scsi/spapr_vscsi.c
> +++ b/hw/scsi/spapr_vscsi.c
> @@ -648,7 +648,7 @@ static void *vscsi_load_request(QEMUFile *f, SCSIRequest *sreq)
>      assert(!req->active);
>  
>      memset(req, 0, sizeof(*req));
> -    rc = vmstate_load_state(f, &vmstate_spapr_vscsi_req, req, 1);
> +    rc = vmstate_load_state(f, &vmstate_spapr_vscsi_req, req, 1, &error_fatal);
>      if (rc) {
>          fprintf(stderr, "VSCSI: failed loading request tag#%u\n", sreq->tag);
>          return NULL;
> diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
> index 4fa692c1a32bcfa4e4939e5fcb64f2bf19905b3b..0be54762cdcbdb4780b8228b0bdf7fc6bd74dd57 100644
> --- a/hw/vfio/pci.c
> +++ b/hw/vfio/pci.c
> @@ -2795,7 +2795,8 @@ static int vfio_pci_load_config(VFIODevice *vbasedev, QEMUFile *f)
>          old_addr[bar] = pdev->io_regions[bar].addr;
>      }
>  
> -    ret = vmstate_load_state(f, &vmstate_vfio_pci_config, vdev, 1);
> +    ret = vmstate_load_state(f, &vmstate_vfio_pci_config, vdev, 1,
> +                             &error_fatal);
>      if (ret) {
>          return ret;
>      }
> diff --git a/hw/virtio/virtio-mmio.c b/hw/virtio/virtio-mmio.c
> index 532c67107ba1d2978a76cf49f9cdc1de1dea3e11..0a688909fc606a3c9fde933667ae8c309ab527d0 100644
> --- a/hw/virtio/virtio-mmio.c
> +++ b/hw/virtio/virtio-mmio.c
> @@ -34,6 +34,7 @@
>  #include "qemu/error-report.h"
>  #include "qemu/log.h"
>  #include "trace.h"
> +#include "qapi/error.h"
>  
>  static bool virtio_mmio_ioeventfd_enabled(DeviceState *d)
>  {
> @@ -619,7 +620,7 @@ static int virtio_mmio_load_extra_state(DeviceState *opaque, QEMUFile *f)
>  {
>      VirtIOMMIOProxy *proxy = VIRTIO_MMIO(opaque);
>  
> -    return vmstate_load_state(f, &vmstate_virtio_mmio, proxy, 1);
> +    return vmstate_load_state(f, &vmstate_virtio_mmio, proxy, 1, &error_fatal);
>  }
>  
>  static bool virtio_mmio_has_extra_state(DeviceState *opaque)
> diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
> index 767216d795998708f5716a23ae16c79cd90ff489..b04faa1e5c91b5cef40e54ec41d92422d16bfc13 100644
> --- a/hw/virtio/virtio-pci.c
> +++ b/hw/virtio/virtio-pci.c
> @@ -161,7 +161,7 @@ static int virtio_pci_load_extra_state(DeviceState *d, QEMUFile *f)
>  {
>      VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
>  
> -    return vmstate_load_state(f, &vmstate_virtio_pci, proxy, 1);
> +    return vmstate_load_state(f, &vmstate_virtio_pci, proxy, 1, &error_fatal);
>  }
>  
>  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 9a81ad912e013fc254899c4e55cff1f76a6112a4..6bcafb338d1b5becadcacf092ba33a6ae4c3d194 100644
> --- a/hw/virtio/virtio.c
> +++ b/hw/virtio/virtio.c
> @@ -3327,14 +3327,14 @@ virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id)
>      }
>  
>      if (vdc->vmsd) {
> -        ret = vmstate_load_state(f, vdc->vmsd, vdev, version_id);
> +        ret = vmstate_load_state(f, vdc->vmsd, vdev, version_id, &error_fatal);
>          if (ret) {
>              return ret;
>          }
>      }
>  
>      /* Subsections */
> -    ret = vmstate_load_state(f, &vmstate_virtio, vdev, 1);
> +    ret = vmstate_load_state(f, &vmstate_virtio, vdev, 1, &error_fatal);
>      if (ret) {
>          return ret;
>      }
> diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
> index 1ff7bd9ac425ba67cd5ca7ad97bcf570f9e19abe..056781b1c21e737583f081594d9f88b32adfd674 100644
> --- a/include/migration/vmstate.h
> +++ b/include/migration/vmstate.h
> @@ -1196,7 +1196,7 @@ extern const VMStateInfo vmstate_info_qlist;
>      }
>  
>  int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
> -                       void *opaque, int version_id);
> +                       void *opaque, int version_id, Error **errp);
>  int vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
>                         void *opaque, JSONWriter *vmdesc);
>  int vmstate_save_state_with_err(QEMUFile *f, const VMStateDescription *vmsd,
> diff --git a/migration/cpr.c b/migration/cpr.c
> index 42ad0b0d500e5de57faf0c6517e216b2d1c0cacf..bdb24736f44e91ba59b6e622a315597c97e7f64d 100644
> --- a/migration/cpr.c
> +++ b/migration/cpr.c
> @@ -202,6 +202,7 @@ int cpr_state_save(MigrationChannel *channel, Error **errp)
>  
>  int cpr_state_load(MigrationChannel *channel, Error **errp)
>  {
> +    ERRP_GUARD();
>      int ret;
>      uint32_t v;
>      QEMUFile *f;
> @@ -233,9 +234,9 @@ int cpr_state_load(MigrationChannel *channel, Error **errp)
>          return -ENOTSUP;
>      }
>  
> -    ret = vmstate_load_state(f, &vmstate_cpr_state, &cpr_state, 1);
> +    ret = vmstate_load_state(f, &vmstate_cpr_state, &cpr_state, 1, errp);
>      if (ret) {
> -        error_setg(errp, "vmstate_load_state error %d", ret);
> +        error_prepend(errp, "vmstate_load_state error %d: ", ret);
>          qemu_fclose(f);
>          return ret;
>      }
> diff --git a/migration/savevm.c b/migration/savevm.c
> index fabbeb296ae987d0c06ba6dafda63720205fecfd..cb64f2855d46aaa7c617b3e4079a2c9e566079b2 100644
> --- a/migration/savevm.c
> +++ b/migration/savevm.c
> @@ -969,7 +969,8 @@ static int vmstate_load(QEMUFile *f, SaveStateEntry *se)
>      if (!se->vmsd) {         /* Old style */
>          return se->ops->load_state(f, se->opaque, se->load_version_id);
>      }
> -    return vmstate_load_state(f, se->vmsd, se->opaque, se->load_version_id);
> +    return vmstate_load_state(f, se->vmsd, se->opaque, se->load_version_id,
> +                              &error_fatal);
>  }
>  
>  static void vmstate_save_old_style(QEMUFile *f, SaveStateEntry *se,
> @@ -2839,7 +2840,8 @@ static int qemu_loadvm_state_header(QEMUFile *f)
>              error_report("Configuration section missing");
>              return -EINVAL;
>          }
> -        ret = vmstate_load_state(f, &vmstate_configuration, &savevm_state, 0);
> +        ret = vmstate_load_state(f, &vmstate_configuration, &savevm_state, 0,
> +                                 &error_fatal);
>  
>          if (ret) {
>              return ret;
> diff --git a/migration/vmstate-types.c b/migration/vmstate-types.c
> index 741a588b7e18c6d37724b08a0101edc8bc74a0a5..f41670cc853c5b41ccc8def354886a8e5c1451fd 100644
> --- a/migration/vmstate-types.c
> +++ b/migration/vmstate-types.c
> @@ -19,6 +19,7 @@
>  #include "qemu/error-report.h"
>  #include "qemu/queue.h"
>  #include "trace.h"
> +#include "qapi/error.h"
>  
>  /* bool */
>  
> @@ -543,13 +544,17 @@ static int get_tmp(QEMUFile *f, void *pv, size_t size,
>                     const VMStateField *field)
>  {
>      int ret;
> +    Error *local_err = NULL;
>      const VMStateDescription *vmsd = field->vmsd;
>      int version_id = field->version_id;
>      void *tmp = g_malloc(size);
>  
>      /* Writes the parent field which is at the start of the tmp */
>      *(void **)tmp = pv;
> -    ret = vmstate_load_state(f, vmsd, tmp, version_id);
> +    ret = vmstate_load_state(f, vmsd, tmp, version_id, &local_err);
> +    if (ret < 0) {
> +        warn_report_err(local_err);
> +    }
>      g_free(tmp);
>      return ret;
>  }
> @@ -626,6 +631,7 @@ static int get_qtailq(QEMUFile *f, void *pv, size_t unused_size,
>                        const VMStateField *field)
>  {
>      int ret = 0;
> +    Error *local_err = NULL;
>      const VMStateDescription *vmsd = field->vmsd;
>      /* size of a QTAILQ element */
>      size_t size = field->size;
> @@ -649,8 +655,9 @@ static int get_qtailq(QEMUFile *f, void *pv, size_t unused_size,
>  
>      while (qemu_get_byte(f)) {
>          elm = g_malloc(size);
> -        ret = vmstate_load_state(f, vmsd, elm, version_id);
> +        ret = vmstate_load_state(f, vmsd, elm, version_id, &local_err);
>          if (ret) {
> +            warn_report_err(local_err);
>              return ret;
>          }
>          QTAILQ_RAW_INSERT_TAIL(pv, elm, entry_offset);
> @@ -772,6 +779,7 @@ static int get_gtree(QEMUFile *f, void *pv, size_t unused_size,
>      GTree *tree = *pval;
>      void *key, *val;
>      int ret = 0;
> +    Error *local_err = NULL;
>  
>      /* in case of direct key, the key vmsd can be {}, ie. check fields */
>      if (!direct_key && version_id > key_vmsd->version_id) {
> @@ -803,18 +811,20 @@ static int get_gtree(QEMUFile *f, void *pv, size_t unused_size,
>              key = (void *)(uintptr_t)qemu_get_be64(f);
>          } else {
>              key = g_malloc0(key_size);
> -            ret = vmstate_load_state(f, key_vmsd, key, version_id);
> +            ret = vmstate_load_state(f, key_vmsd, key, version_id, &local_err);
>              if (ret) {
>                  error_report("%s : failed to load %s (%d)",
>                               field->name, key_vmsd->name, ret);
> +                warn_report_err(local_err);
>                  goto key_error;
>              }
>          }
>          val = g_malloc0(val_size);
> -        ret = vmstate_load_state(f, val_vmsd, val, version_id);
> +        ret = vmstate_load_state(f, val_vmsd, val, version_id, &local_err);
>          if (ret) {
>              error_report("%s : failed to load %s (%d)",
>                           field->name, val_vmsd->name, ret);
> +            warn_report_err(local_err);
>              goto val_error;
>          }
>          g_tree_insert(tree, key, val);
> @@ -872,6 +882,7 @@ static int get_qlist(QEMUFile *f, void *pv, size_t unused_size,
>                       const VMStateField *field)
>  {
>      int ret = 0;
> +    Error *local_err = NULL;
>      const VMStateDescription *vmsd = field->vmsd;
>      /* size of a QLIST element */
>      size_t size = field->size;
> @@ -892,10 +903,11 @@ static int get_qlist(QEMUFile *f, void *pv, size_t unused_size,
>  
>      while (qemu_get_byte(f)) {
>          elm = g_malloc(size);
> -        ret = vmstate_load_state(f, vmsd, elm, version_id);
> +        ret = vmstate_load_state(f, vmsd, elm, version_id, &local_err);
>          if (ret) {
>              error_report("%s: failed to load %s (%d)", field->name,
>                           vmsd->name, ret);
> +            warn_report_err(local_err);
>              g_free(elm);
>              return ret;
>          }
> diff --git a/migration/vmstate.c b/migration/vmstate.c
> index 6108c7fe283a5013ce42ea9987723c489aef26a2..1cd609a1d598995af1e51d1f4d58d68133f1426d 100644
> --- a/migration/vmstate.c
> +++ b/migration/vmstate.c
> @@ -132,29 +132,34 @@ static void vmstate_handle_alloc(void *ptr, const VMStateField *field,
>  }
>  
>  int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
> -                       void *opaque, int version_id)
> +                       void *opaque, int version_id, Error **errp)
>  {
> +    ERRP_GUARD();
>      const VMStateField *field = vmsd->fields;
>      int ret = 0;
>  
>      trace_vmstate_load_state(vmsd->name, version_id);
>      if (version_id > vmsd->version_id) {
> -        error_report("%s: incoming version_id %d is too new "
> -                     "for local version_id %d",
> -                     vmsd->name, version_id, vmsd->version_id);
> +        error_setg(errp, "%s: incoming version_id %d is too new "
> +                   "for local version_id %d",
> +                   vmsd->name, version_id, vmsd->version_id);
>          trace_vmstate_load_state_end(vmsd->name, "too new", -EINVAL);
>          return -EINVAL;
>      }
>      if  (version_id < vmsd->minimum_version_id) {
> -        error_report("%s: incoming version_id %d is too old "
> -                     "for local minimum version_id  %d",
> -                     vmsd->name, version_id, vmsd->minimum_version_id);
> +        error_setg(errp, "%s: incoming version_id %d is too old "
> +                   "for local minimum version_id %d",
> +                   vmsd->name, version_id, vmsd->minimum_version_id);
>          trace_vmstate_load_state_end(vmsd->name, "too old", -EINVAL);
>          return -EINVAL;
>      }
>      if (vmsd->pre_load) {
>          ret = vmsd->pre_load(opaque);
>          if (ret) {
> +            error_setg(errp, "VM pre load failed for: '%s', "

"VM" pre load is a little ambiguous. Simply "pre load" or "pre load
hook" is better.

> +                       "version_id: %d, minimum version_id: %d, ret: %d",
> +                       vmsd->name, vmsd->version_id, vmsd->minimum_version_id,
> +                       ret);
>              return ret;
>          }
>      }
> @@ -192,13 +197,20 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
>  
>                  if (inner_field->flags & VMS_STRUCT) {
>                      ret = vmstate_load_state(f, inner_field->vmsd, curr_elem,
> -                                             inner_field->vmsd->version_id);
> +                                             inner_field->vmsd->version_id,
> +                                             errp);
>                  } else if (inner_field->flags & VMS_VSTRUCT) {
>                      ret = vmstate_load_state(f, inner_field->vmsd, curr_elem,
> -                                             inner_field->struct_version_id);
> +                                             inner_field->struct_version_id,
> +                                             errp);
>                  } else {
>                      ret = inner_field->info->get(f, curr_elem, size,
>                                                   inner_field);
> +                    if (ret < 0) {
> +                        error_setg(errp,
> +                                   "Failed to get info for %s: %d",
> +                                   inner_field->name, ret);

"get info" is not correct. This is the type-specific getter
invocation. Because the migration (for the most part) is a stream, each
type provides it's own getter which knows about the size of the field
and any particularities such as magic values. So:

error_setg(errp, "Failed to load element of type %s for %s: %d",
           info->name, inner_field->name, ret);

> +                    }
>                  }
>  
>                  /* If we used a fake temp field.. free it now */
> @@ -208,30 +220,42 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
>  
>                  if (ret >= 0) {
>                      ret = qemu_file_get_error(f);
> +                    if (ret < 0) {
> +                        error_setg(errp, "Failed to load %s state: %d",
> +                                   vmsd->name, ret);

We could go a little more specific here, it's useful to know whether the
error was on the transport side, rather than something logical with the
migrated data. I don't really care about the actual string, but one
suggestion is "stream error":

error_setg(errp, "Failed to load %s state: stream error: %d",
           vmsd->name, ret);

> +                    }
>                  }
>                  if (ret < 0) {
>                      qemu_file_set_error(f, ret);
> -                    error_report("Failed to load %s:%s", vmsd->name,
> -                                 field->name);
> +                    error_prepend(errp,
> +                                  "Failed to load %s:%s version_id: %d: ",

Usage of : is inconsistent with below /

> +                                   vmsd->name, field->name, vmsd->version_id);
>                      trace_vmstate_load_field_error(field->name, ret);
>                      return ret;
>                  }
>              }
>          } else if (field->flags & VMS_MUST_EXIST) {
> -            error_report("Input validation failed: %s/%s",
> -                         vmsd->name, field->name);
> +            error_setg(errp, "Input validation failed: %s/%s version_id: %d",

here

> +                       vmsd->name, field->name, vmsd->version_id);
>              return -1;
>          }
>          field++;
>      }
>      assert(field->flags == VMS_END);
> -    ret = vmstate_subsection_load(f, vmsd, opaque, &error_fatal);
> +    ret = vmstate_subsection_load(f, vmsd, opaque, errp);
>      if (ret != 0) {
>          qemu_file_set_error(f, ret);
>          return ret;
>      }
>      if (vmsd->post_load) {
>          ret = vmsd->post_load(opaque, version_id);
> +        if (ret < 0) {
> +            error_setg(errp,
> +                       "VM Post load failed for: %s, version_id: %d, "
> +                       "minimum_version: %d, ret: %d",
> +                       vmsd->name, vmsd->version_id, vmsd->minimum_version_id,
> +                       ret);
> +        }
>      }
>      trace_vmstate_load_state_end(vmsd->name, "end", ret);
>      return ret;
> @@ -568,6 +592,7 @@ vmstate_get_subsection(const VMStateDescription * const *sub,
>  static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd,
>                                     void *opaque, Error **errp)
>  {
> +    ERRP_GUARD();
>      trace_vmstate_subsection_load(vmsd->name);
>  
>      while (qemu_peek_byte(f, 0) == QEMU_VM_SUBSECTION) {
> @@ -607,12 +632,12 @@ static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd,
>          qemu_file_skip(f, len); /* idstr */
>          version_id = qemu_get_be32(f);
>  
> -        ret = vmstate_load_state(f, sub_vmsd, opaque, version_id);
> +        ret = vmstate_load_state(f, sub_vmsd, opaque, version_id, errp);
>          if (ret) {
>              trace_vmstate_subsection_load_bad(vmsd->name, idstr, "(child)");
> -            error_setg(errp,
> -                       "Loading VM subsection '%s' in '%s' failed: %d",
> -                       idstr, vmsd->name, ret);
> +            error_prepend(errp,
> +                          "Loading VM subsection '%s' in '%s' failed: %d: ",
> +                          idstr, vmsd->name, ret);
>              return ret;
>          }
>      }
> diff --git a/tests/unit/test-vmstate.c b/tests/unit/test-vmstate.c
> index 63f28f26f45691a70936d33e7341d16477a3471f..cfab58c7f45ba50f70af164c3e58b01aaf9cc656 100644
> --- a/tests/unit/test-vmstate.c
> +++ b/tests/unit/test-vmstate.c
> @@ -30,6 +30,7 @@
>  #include "../migration/savevm.h"
>  #include "qemu/module.h"
>  #include "io/channel-file.h"
> +#include "qapi/error.h"
>  
>  static int temp_fd;
>  
> @@ -108,14 +109,16 @@ static int load_vmstate_one(const VMStateDescription *desc, void *obj,
>  {
>      QEMUFile *f;
>      int ret;
> +    Error *local_err = NULL;
>  
>      f = open_test_file(true);
>      qemu_put_buffer(f, wire, size);
>      qemu_fclose(f);
>  
>      f = open_test_file(false);
> -    ret = vmstate_load_state(f, desc, obj, version);
> +    ret = vmstate_load_state(f, desc, obj, version, &local_err);
>      if (ret) {
> +        warn_report_err(local_err);
>          g_assert(qemu_file_get_error(f));
>      } else{
>          g_assert(!qemu_file_get_error(f));
> @@ -355,6 +358,8 @@ static const VMStateDescription vmstate_versioned = {
>  
>  static void test_load_v1(void)
>  {
> +    Error *local_err = NULL;
> +    int ret;
>      uint8_t buf[] = {
>          0, 0, 0, 10,             /* a */
>          0, 0, 0, 30,             /* c */
> @@ -365,7 +370,10 @@ static void test_load_v1(void)
>  
>      QEMUFile *loading = open_test_file(false);
>      TestStruct obj = { .b = 200, .e = 500, .f = 600 };
> -    vmstate_load_state(loading, &vmstate_versioned, &obj, 1);
> +    ret = vmstate_load_state(loading, &vmstate_versioned, &obj, 1, &local_err);
> +    if (ret < 0) {
> +        warn_report_err(local_err);
> +    }
>      g_assert(!qemu_file_get_error(loading));
>      g_assert_cmpint(obj.a, ==, 10);
>      g_assert_cmpint(obj.b, ==, 200);
> @@ -378,6 +386,8 @@ static void test_load_v1(void)
>  
>  static void test_load_v2(void)
>  {
> +    Error *local_err = NULL;
> +    int ret;
>      uint8_t buf[] = {
>          0, 0, 0, 10,             /* a */
>          0, 0, 0, 20,             /* b */
> @@ -391,7 +401,10 @@ static void test_load_v2(void)
>  
>      QEMUFile *loading = open_test_file(false);
>      TestStruct obj;
> -    vmstate_load_state(loading, &vmstate_versioned, &obj, 2);
> +    ret = vmstate_load_state(loading, &vmstate_versioned, &obj, 2, &local_err);
> +    if (ret < 0) {
> +        warn_report_err(local_err);
> +    }
>      g_assert_cmpint(obj.a, ==, 10);
>      g_assert_cmpint(obj.b, ==, 20);
>      g_assert_cmpint(obj.c, ==, 30);
> @@ -467,6 +480,8 @@ static void test_save_skip(void)
>  
>  static void test_load_noskip(void)
>  {
> +    Error *local_err = NULL;
> +    int ret;
>      uint8_t buf[] = {
>          0, 0, 0, 10,             /* a */
>          0, 0, 0, 20,             /* b */
> @@ -480,7 +495,10 @@ static void test_load_noskip(void)
>  
>      QEMUFile *loading = open_test_file(false);
>      TestStruct obj = { .skip_c_e = false };
> -    vmstate_load_state(loading, &vmstate_skipping, &obj, 2);
> +    ret = vmstate_load_state(loading, &vmstate_skipping, &obj, 2, &local_err);
> +    if (ret < 0) {
> +        warn_report_err(local_err);
> +    }
>      g_assert(!qemu_file_get_error(loading));
>      g_assert_cmpint(obj.a, ==, 10);
>      g_assert_cmpint(obj.b, ==, 20);
> @@ -493,6 +511,8 @@ static void test_load_noskip(void)
>  
>  static void test_load_skip(void)
>  {
> +    Error *local_err = NULL;
> +    int ret;
>      uint8_t buf[] = {
>          0, 0, 0, 10,             /* a */
>          0, 0, 0, 20,             /* b */
> @@ -504,7 +524,10 @@ static void test_load_skip(void)
>  
>      QEMUFile *loading = open_test_file(false);
>      TestStruct obj = { .skip_c_e = true, .c = 300, .e = 500 };
> -    vmstate_load_state(loading, &vmstate_skipping, &obj, 2);
> +    ret = vmstate_load_state(loading, &vmstate_skipping, &obj, 2, &local_err);
> +    if (ret < 0) {
> +        warn_report_err(local_err);
> +    }
>      g_assert(!qemu_file_get_error(loading));
>      g_assert_cmpint(obj.a, ==, 10);
>      g_assert_cmpint(obj.b, ==, 20);
> @@ -744,6 +767,8 @@ static void test_save_q(void)
>  
>  static void test_load_q(void)
>  {
> +    int ret;
> +    Error *local_err = NULL;
>      TestQtailq obj_q = {
>          .i16 = -512,
>          .i32 = 70000,
> @@ -773,7 +798,10 @@ static void test_load_q(void)
>      TestQtailq tgt;
>  
>      QTAILQ_INIT(&tgt.q);
> -    vmstate_load_state(fload, &vmstate_q, &tgt, 1);
> +    ret = vmstate_load_state(fload, &vmstate_q, &tgt, 1, &local_err);
> +    if (ret < 0) {
> +        warn_report_err(local_err);
> +    }
>      char eof = qemu_get_byte(fload);
>      g_assert(!qemu_file_get_error(fload));
>      g_assert_cmpint(tgt.i16, ==, obj_q.i16);
> @@ -1115,6 +1143,8 @@ static void diff_iommu(TestGTreeIOMMU *iommu1, TestGTreeIOMMU *iommu2)
>  
>  static void test_gtree_load_domain(void)
>  {
> +    Error *local_err = NULL;
> +    int ret;
>      TestGTreeDomain *dest_domain = g_new0(TestGTreeDomain, 1);
>      TestGTreeDomain *orig_domain = create_first_domain();
>      QEMUFile *fload, *fsave;
> @@ -1127,7 +1157,11 @@ static void test_gtree_load_domain(void)
>  
>      fload = open_test_file(false);
>  
> -    vmstate_load_state(fload, &vmstate_domain, dest_domain, 1);
> +    ret = vmstate_load_state(fload, &vmstate_domain, dest_domain, 1,
> +                             &local_err);
> +    if (ret < 0) {
> +        warn_report_err(local_err);
> +    }
>      eof = qemu_get_byte(fload);
>      g_assert(!qemu_file_get_error(fload));
>      g_assert_cmpint(orig_domain->id, ==, dest_domain->id);
> @@ -1230,6 +1264,8 @@ static void test_gtree_save_iommu(void)
>  
>  static void test_gtree_load_iommu(void)
>  {
> +    Error *local_err = NULL;
> +    int ret;
>      TestGTreeIOMMU *dest_iommu = g_new0(TestGTreeIOMMU, 1);
>      TestGTreeIOMMU *orig_iommu = create_iommu();
>      QEMUFile *fsave, *fload;
> @@ -1241,7 +1277,10 @@ static void test_gtree_load_iommu(void)
>      qemu_fclose(fsave);
>  
>      fload = open_test_file(false);
> -    vmstate_load_state(fload, &vmstate_iommu, dest_iommu, 1);
> +    ret = vmstate_load_state(fload, &vmstate_iommu, dest_iommu, 1, &local_err);
> +    if (ret < 0) {
> +        warn_report_err(local_err);
> +    }
>      eof = qemu_get_byte(fload);
>      g_assert(!qemu_file_get_error(fload));
>      g_assert_cmpint(orig_iommu->id, ==, dest_iommu->id);
> @@ -1363,6 +1402,8 @@ static void test_save_qlist(void)
>  
>  static void test_load_qlist(void)
>  {
> +    Error *local_err = NULL;
> +    int ret;
>      QEMUFile *fsave, *fload;
>      TestQListContainer *orig_container = alloc_container();
>      TestQListContainer *dest_container = g_new0(TestQListContainer, 1);
> @@ -1376,7 +1417,11 @@ static void test_load_qlist(void)
>      qemu_fclose(fsave);
>  
>      fload = open_test_file(false);
> -    vmstate_load_state(fload, &vmstate_container, dest_container, 1);
> +    ret = vmstate_load_state(fload, &vmstate_container, dest_container, 1,
> +                             &local_err);
> +    if (ret < 0) {
> +        warn_report_err(local_err);
> +    }
>      eof = qemu_get_byte(fload);
>      g_assert(!qemu_file_get_error(fload));
>      g_assert_cmpint(eof, ==, QEMU_VM_EOF);
> diff --git a/ui/vdagent.c b/ui/vdagent.c
> index c0746fe5b168fdc7aeb4866de2ba0c3387566649..b699658c06cc3765bae2e5effa34f66b7cfd4ead 100644
> --- a/ui/vdagent.c
> +++ b/ui/vdagent.c
> @@ -1008,7 +1008,8 @@ static int get_cbinfo(QEMUFile *f, void *pv, size_t size,
>  
>      vdagent_clipboard_peer_register(vd);
>  
> -    ret = vmstate_load_state(f, &vmstate_cbinfo_array, &cbinfo, 0);
> +    ret = vmstate_load_state(f, &vmstate_cbinfo_array, &cbinfo, 0,
> +                             &error_fatal);
>      if (ret) {
>          return ret;
>      }

Unreachable?


  parent reply	other threads:[~2025-08-15 15:43 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20250813-propagate_tpm_error-v11-0-b470a374b42d@redhat.com>
     [not found] ` <20250813-propagate_tpm_error-v11-1-b470a374b42d@redhat.com>
2025-08-15 14:44   ` [PATCH v11 01/27] migration: push Error **errp into vmstate_subsection_load() Fabiano Rosas
2025-08-15 20:06     ` Fabiano Rosas
2025-08-20 17:43       ` Arun Menon
     [not found] ` <20250813-propagate_tpm_error-v11-2-b470a374b42d@redhat.com>
2025-08-15 15:41   ` Fabiano Rosas [this message]
2025-08-20  8:12     ` [PATCH v11 02/27] migration: push Error **errp into vmstate_load_state() Arun Menon
2025-08-20 15:24       ` Fabiano Rosas
2025-08-20 17:07         ` Arun Menon
     [not found] ` <20250813-propagate_tpm_error-v11-3-b470a374b42d@redhat.com>
2025-08-15 15:58   ` [PATCH v11 03/27] migration: push Error **errp into qemu_loadvm_state_header() Fabiano Rosas
     [not found] ` <20250813-propagate_tpm_error-v11-4-b470a374b42d@redhat.com>
2025-08-15 16:41   ` [PATCH v11 04/27] migration: push Error **errp into vmstate_load() Fabiano Rosas
2025-08-20 17:31     ` Arun Menon
     [not found] ` <20250813-propagate_tpm_error-v11-5-b470a374b42d@redhat.com>
2025-08-15 18:35   ` [PATCH v11 05/27] migration: push Error **errp into loadvm_process_command() Fabiano Rosas
2025-08-20  9:08     ` Arun Menon
2025-08-20 13:42     ` Arun Menon
     [not found] ` <20250813-propagate_tpm_error-v11-6-b470a374b42d@redhat.com>
2025-08-15 18:39   ` [PATCH v11 06/27] migration: push Error **errp into loadvm_handle_cmd_packaged() Fabiano Rosas
     [not found] ` <20250813-propagate_tpm_error-v11-7-b470a374b42d@redhat.com>
2025-08-15 18:55   ` [PATCH v11 07/27] migration: push Error **errp into qemu_loadvm_state() Fabiano Rosas
2025-08-20 17:36     ` Arun Menon
     [not found] ` <20250813-propagate_tpm_error-v11-8-b470a374b42d@redhat.com>
2025-08-15 18:58   ` [PATCH v11 08/27] migration: push Error **errp into qemu_load_device_state() Fabiano Rosas
2025-08-20 17:36     ` Arun Menon
     [not found] ` <20250813-propagate_tpm_error-v11-9-b470a374b42d@redhat.com>
2025-08-15 19:23   ` [PATCH v11 09/27] migration: push Error **errp into qemu_loadvm_state_main() Fabiano Rosas
2025-08-20 17:27     ` Arun Menon
     [not found] ` <20250813-propagate_tpm_error-v11-10-b470a374b42d@redhat.com>
2025-08-15 19:29   ` [PATCH v11 10/27] migration: push Error **errp into qemu_loadvm_section_start_full() Fabiano Rosas
2025-08-20 17:35     ` Arun Menon
     [not found] ` <20250813-propagate_tpm_error-v11-11-b470a374b42d@redhat.com>
2025-08-15 19:35   ` [PATCH v11 11/27] migration: push Error **errp into qemu_loadvm_section_part_end() Fabiano Rosas
2025-08-20 17:34     ` Arun Menon
     [not found] ` <20250813-propagate_tpm_error-v11-14-b470a374b42d@redhat.com>
2025-08-15 19:37   ` [PATCH v11 14/27] migration: push Error **errp into ram_postcopy_incoming_init() Fabiano Rosas
     [not found] ` <20250813-propagate_tpm_error-v11-15-b470a374b42d@redhat.com>
2025-08-15 19:40   ` [PATCH v11 15/27] migration: push Error **errp into loadvm_postcopy_handle_advise() Fabiano Rosas
     [not found] ` <20250813-propagate_tpm_error-v11-16-b470a374b42d@redhat.com>
2025-08-15 19:41   ` [PATCH v11 16/27] migration: push Error **errp into loadvm_postcopy_handle_listen() Fabiano Rosas
     [not found] ` <20250813-propagate_tpm_error-v11-17-b470a374b42d@redhat.com>
2025-08-15 19:41   ` [PATCH v11 17/27] migration: push Error **errp into loadvm_postcopy_handle_run() Fabiano Rosas
     [not found] ` <20250813-propagate_tpm_error-v11-18-b470a374b42d@redhat.com>
2025-08-15 19:42   ` [PATCH v11 18/27] migration: push Error **errp into loadvm_postcopy_ram_handle_discard() Fabiano Rosas
     [not found] ` <20250813-propagate_tpm_error-v11-19-b470a374b42d@redhat.com>
2025-08-15 19:51   ` [PATCH v11 19/27] migration: push Error **errp into loadvm_handle_recv_bitmap() Fabiano Rosas
2025-08-20 17:32     ` Arun Menon
     [not found] ` <20250813-propagate_tpm_error-v11-20-b470a374b42d@redhat.com>
2025-08-15 19:51   ` [PATCH v11 20/27] migration: Return -1 on memory allocation failure in ram.c Fabiano Rosas
     [not found] ` <20250813-propagate_tpm_error-v11-21-b470a374b42d@redhat.com>
2025-08-15 19:53   ` [PATCH v11 21/27] migration: push Error **errp into loadvm_process_enable_colo() Fabiano Rosas
     [not found] ` <20250813-propagate_tpm_error-v11-22-b470a374b42d@redhat.com>
2025-08-15 19:53   ` [PATCH v11 22/27] migration: push Error **errp into loadvm_postcopy_handle_switchover_start() Fabiano Rosas
     [not found] ` <20250813-propagate_tpm_error-v11-23-b470a374b42d@redhat.com>
2025-08-15 19:57   ` [PATCH v11 23/27] migration: Capture error in postcopy_ram_listen_thread() Fabiano Rosas
2025-08-20 17:37     ` Arun Menon

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87o6sgzj5t.fsf@suse.de \
    --to=farosas@suse.de \
    --cc=alex.bennee@linaro.org \
    --cc=alex.williamson@redhat.com \
    --cc=armenon@redhat.com \
    --cc=borntraeger@linux.ibm.com \
    --cc=clg@redhat.com \
    --cc=cohuck@redhat.com \
    --cc=david@redhat.com \
    --cc=dmitry.osipenko@collabora.com \
    --cc=fam@euphon.net \
    --cc=farman@linux.ibm.com \
    --cc=harshpb@linux.ibm.com \
    --cc=iii@linux.ibm.com \
    --cc=marcandre.lureau@redhat.com \
    --cc=marcel.apfelbaum@gmail.com \
    --cc=mjrosato@linux.ibm.com \
    --cc=mst@redhat.com \
    --cc=npiggin@gmail.com \
    --cc=odaki@rsg.ci.i.u-tokyo.ac.jp \
    --cc=pasic@linux.ibm.com \
    --cc=pbonzini@redhat.com \
    --cc=peter.maydell@linaro.org \
    --cc=peterx@redhat.com \
    --cc=qemu-arm@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    --cc=qemu-ppc@nongnu.org \
    --cc=qemu-s390x@nongnu.org \
    --cc=richard.henderson@linaro.org \
    --cc=stefanb@linux.vnet.ibm.com \
    --cc=steven.sistare@oracle.com \
    --cc=thuth@redhat.com \
    --cc=zhanghailiang@xfusion.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.