From nobody Sat Nov 15 05:12:46 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=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1755766052; cv=none; d=zohomail.com; s=zohoarc; b=aT/5VAw6Sy3u51Dbu7HL4idEUTJ9PIXEhR8GFNcxqf6lhKl3acvuH5XS8jlSgwz5aqIsVOgatKVKDA8wt8e4Cf+iJ8iOwr5Zhq3VEGeUXj7umFBlkrRA1waNhaIyaXnA1IVoLtGpAUDyt44tlDWjLxRv4GtIvJMgkmt74PKRCTc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1755766052; h=Content-Type: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=P2FPdADMEMHNFhxXzuVtDKfuv8H3gugQt9Ko65fK9pw=; b=nk9+0TB1s+/FzgK1xzuu+zI2a9ea1VZWlR2tBlOeFsyPiC38i33gnNvczZbDC85jphQE8hzC93p0nZHkkzJL0qzgu6u8H2vv2AsL+G/pqcG2UdIXf632y7W1gYDSVTWvltMkbQrvHuBmtVCn+d+yuEr17QcIP+GAu/MaA2I1dX8= 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=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1755766052922159.39918049149026; Thu, 21 Aug 2025 01:47:32 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1up0vv-0002tD-8V; Thu, 21 Aug 2025 04:46:07 -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 1up0vC-0002Q0-9j for qemu-devel@nongnu.org; Thu, 21 Aug 2025 04:45:31 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1up0uz-0000nC-NF for qemu-devel@nongnu.org; Thu, 21 Aug 2025 04:45:17 -0400 Received: from mail-pl1-f200.google.com (mail-pl1-f200.google.com [209.85.214.200]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-635-jXcm9PyOMJCM_1ktU_ORhQ-1; Thu, 21 Aug 2025 04:44:55 -0400 Received: by mail-pl1-f200.google.com with SMTP id d9443c01a7336-24458027f67so17415915ad.1 for ; Thu, 21 Aug 2025 01:44:55 -0700 (PDT) Received: from armenon-kvm.bengluru.csb ([49.47.192.65]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-245ed33e05dsm48789985ad.3.2025.08.21.01.44.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 21 Aug 2025 01:44:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1755765896; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=P2FPdADMEMHNFhxXzuVtDKfuv8H3gugQt9Ko65fK9pw=; b=jALVSIOFTNPQXNF/CHEK6TFt01rf+BIligtN81DQB8RRTrcZgyRCsJu0MDwn1rWkXm1KK/ L5nk7/4TYVoeTkBx9+IolAcyUriIpzRb4ZiUAf4ge/mXbnEx1JFxXlZ4JudD9rk/9l6pXq zPVN/Vx7Tm/+xXTc5XtkA5Hjylst2fc= X-MC-Unique: jXcm9PyOMJCM_1ktU_ORhQ-1 X-Mimecast-MFC-AGG-ID: jXcm9PyOMJCM_1ktU_ORhQ_1755765894 X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1755765893; x=1756370693; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=P2FPdADMEMHNFhxXzuVtDKfuv8H3gugQt9Ko65fK9pw=; b=GOQqKtTtco0vtdollOCB5B3ADSB+7v0tu4RsGr35LEfekZn0AMnY9KaHT+F3fUipAE QwFoJ9Lc9j4n3Q7LaXDUp1f6tk3HbFTlA/K4AekR5LMvNJ1Jp6IsvXdBBM8JCDHmw5/d 8nuPoQqwF0aV1iofZ4es/mB7bkqPdzzWsdMqTe0jOXY1bqKnR3M1E+QCNz8bx5FuhndF elv0WhkWONu/3czC/8uXFEEUcYx3JFQjT1qTXzPhKCeDfMRAdyWojfcbs0P+F9Tc+4fT cyXPTOMIkwVWsto/6kVKO7NvDnFtIA76beHsfvGtSgG5UhJ82Ouo+co8nZ/DAGpvUQQI lyKg== X-Gm-Message-State: AOJu0YzhCFZzeFSPlF5jL+3K9nv8N7XCCWgQsiuosuHEDq9P7qckvpXJ Swgrv4qKJH0fa0RM2lPcyW4eLCb8TB5rBEThviHp8rHwDoHMYUZIbuhc/rQT+20FaMWwz/mNSLJ aouUYknaWnR2fd+XaZVDQKvN2o5/lgt5Jz/FchkzQdow1q/ue/jZ8pZzG X-Gm-Gg: ASbGncvJsSeYQujcXMO7k9TNxLMLxHHR2j+Icme81P31OK9UvBH5AEUkyxWcHTeNZ5i a7hHFJJISD1C/ybVlkoFpeKZCKS4/C5r4bpH/xq0K13fQJkk0KdSSCG4GntLo4iI3cZlu3G9XTf eWnGlToB8algXJp0wMtdAyrqEwOnw5mslHGIIhyed6fGgAMNGiCPef03dsMW4aWp1vQg3jI7/SO zUACcH0PcZPg3HZW5QJYcuHpqcNrhxl2RCbGFiVvKbnK6L0zj96hk3udQw+PVZ5VfivpbcTvCjT VrIxFCXI0W6jvpuZnBTfNO0F59PfKVGaJkqElUP2+ShaxYCtpqND X-Received: by 2002:a17:902:ce88:b0:240:8cec:4823 with SMTP id d9443c01a7336-245fedd00e8mr20738095ad.41.1755765892761; Thu, 21 Aug 2025 01:44:52 -0700 (PDT) X-Google-Smtp-Source: AGHT+IG9fNSfctYIAjAJ6cSV0NJJg4L74WBW3lxCcdX9jcHZDhcjwAe27dHBn7VBA6tiMbbjfMAcYg== X-Received: by 2002:a17:902:ce88:b0:240:8cec:4823 with SMTP id d9443c01a7336-245fedd00e8mr20737785ad.41.1755765892177; Thu, 21 Aug 2025 01:44:52 -0700 (PDT) From: Arun Menon Date: Thu, 21 Aug 2025 14:13:56 +0530 Subject: [PATCH v12 02/27] migration: push Error **errp into vmstate_load_state() MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250821-propagate_tpm_error-v12-2-72b803e707dc@redhat.com> References: <20250821-propagate_tpm_error-v12-0-72b803e707dc@redhat.com> In-Reply-To: <20250821-propagate_tpm_error-v12-0-72b803e707dc@redhat.com> To: qemu-devel@nongnu.org Cc: Peter Xu , Fabiano Rosas , =?utf-8?q?Alex_Benn=C3=A9e?= , Akihiko Odaki , Dmitry Osipenko , "Michael S. Tsirkin" , Marcel Apfelbaum , Cornelia Huck , Halil Pasic , Eric Farman , Thomas Huth , Christian Borntraeger , Matthew Rosato , Richard Henderson , David Hildenbrand , Ilya Leoshkevich , Nicholas Piggin , Harsh Prateek Bora , Paolo Bonzini , Fam Zheng , Alex Williamson , =?utf-8?q?C=C3=A9dric_Le_Goater?= , Steve Sistare , =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , qemu-s390x@nongnu.org, qemu-ppc@nongnu.org, Hailiang Zhang , Stefan Berger , Peter Maydell , qemu-arm@nongnu.org, Arun Menon X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=28913; i=armenon@redhat.com; h=from:subject:message-id; bh=++rhMn5BRu5/6ldMZ/sKwurDc5PN18dU+iSJxVKP9Vs=; b=owGbwMvMwCWWVaVqcZPfqI/xtFoSQ8ayO8mFz7bveCImfYIzzMaV94XJlcWX5nZYPFkbWq955 +f7qmdnO0pZGMS4GGTFFFkavgbINgUURkTavrwOM4eVCWQIAxenAEykoJHhf5JDissUb5//Sx4p X40+tZO3UHb3jc1XU9N2nnoY/+64sTHDX9lHMzqmH2bMfL3bzct3Q5Z9/eFVd7sUJpxXeKh8qZr Fig0A X-Developer-Key: i=armenon@redhat.com; a=openpgp; fpr=80F5501D82507158593DE9D76A7A2538D90F328E 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=170.10.129.124; envelope-from=armenon@redhat.com; helo=us-smtp-delivery-124.mimecast.com 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, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=unavailable 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 @redhat.com) X-ZM-MESSAGEID: 1755766056396124100 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. The errors are temporarily reported using warn_report_err(). This is removed in the subsequent patches in this series, when we are actually able to propagate the error to the calling function using errp. Whereas, if we want the function to exit on error, then error_fatal is passed. Reviewed-by: Marc-Andr=C3=A9 Lureau Signed-off-by: Arun Menon Reviewed-by: Fabiano Rosas Reviewed-by: more easily. --- hw/display/virtio-gpu.c | 2 +- hw/pci/pci.c | 3 ++- hw/s390x/virtio-ccw.c | 2 +- hw/scsi/spapr_vscsi.c | 4 ++- hw/vfio/pci.c | 5 +++- hw/virtio/virtio-mmio.c | 3 ++- hw/virtio/virtio-pci.c | 2 +- hw/virtio/virtio.c | 7 +++-- include/migration/vmstate.h | 2 +- migration/cpr.c | 3 +-- migration/savevm.c | 8 ++++-- migration/vmstate-types.c | 22 +++++++++++---- migration/vmstate.c | 65 +++++++++++++++++++++++++++++++----------= ---- tests/unit/test-vmstate.c | 63 ++++++++++++++++++++++++++++++++++++-----= -- ui/vdagent.c | 5 +++- 15 files changed, 147 insertions(+), 49 deletions(-) diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c index 0a1a625b0ea6cf26cb0d799171a57ed3d3ab2442..5dc31bc6bfb0272e29a4364ab10= de2595a4bedf7 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, } =20 /* 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= ); =20 return 0; } diff --git a/hw/pci/pci.c b/hw/pci/pci.c index c70b5ceebaf1f2b10768bd030526cbb518da2b8d..6be932d3bb67ff0c4808707db2a= 7b6378a90e82b 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 =3D vmstate_load_state(f, &vmstate_pci_device, s, s->version_id); + ret =3D 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..6a9641a03d5d3a38a4de7ceb9de= ffc0cc303bcff 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, QE= MUFile *f) static int virtio_ccw_load_config(DeviceState *d, QEMUFile *f) { VirtioCcwDevice *dev =3D 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_f= atal); } =20 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..8622419497db650523d51bcb415= 57bbca254eaa3 100644 --- a/hw/scsi/spapr_vscsi.c +++ b/hw/scsi/spapr_vscsi.c @@ -642,15 +642,17 @@ static void *vscsi_load_request(QEMUFile *f, SCSIRequ= est *sreq) VSCSIState *s =3D VIO_SPAPR_VSCSI_DEVICE(bus->qbus.parent); vscsi_req *req; int rc; + Error *local_err =3D NULL; =20 assert(sreq->tag < VSCSI_REQ_LIMIT); req =3D &s->reqs[sreq->tag]; assert(!req->active); =20 memset(req, 0, sizeof(*req)); - rc =3D vmstate_load_state(f, &vmstate_spapr_vscsi_req, req, 1); + rc =3D vmstate_load_state(f, &vmstate_spapr_vscsi_req, req, 1, &local_= err); if (rc) { fprintf(stderr, "VSCSI: failed loading request tag#%u\n", sreq->ta= g); + warn_report_err(local_err); return NULL; } assert(req->active); diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c index 4fa692c1a32bcfa4e4939e5fcb64f2bf19905b3b..a65e34b6979eadfa0851666aeae= 7cf731a00fa40 100644 --- a/hw/vfio/pci.c +++ b/hw/vfio/pci.c @@ -2790,13 +2790,16 @@ static int vfio_pci_load_config(VFIODevice *vbasede= v, QEMUFile *f) PCIDevice *pdev =3D &vdev->pdev; pcibus_t old_addr[PCI_NUM_REGIONS - 1]; int bar, ret; + Error *local_err =3D NULL; =20 for (bar =3D 0; bar < PCI_ROM_SLOT; bar++) { old_addr[bar] =3D pdev->io_regions[bar].addr; } =20 - ret =3D vmstate_load_state(f, &vmstate_vfio_pci_config, vdev, 1); + ret =3D vmstate_load_state(f, &vmstate_vfio_pci_config, vdev, 1, + &local_err); if (ret) { + warn_report_err(local_err); return ret; } =20 diff --git a/hw/virtio/virtio-mmio.c b/hw/virtio/virtio-mmio.c index 532c67107ba1d2978a76cf49f9cdc1de1dea3e11..0a688909fc606a3c9fde933667a= e8c309ab527d0 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" =20 static bool virtio_mmio_ioeventfd_enabled(DeviceState *d) { @@ -619,7 +620,7 @@ static int virtio_mmio_load_extra_state(DeviceState *op= aque, QEMUFile *f) { VirtIOMMIOProxy *proxy =3D VIRTIO_MMIO(opaque); =20 - return vmstate_load_state(f, &vmstate_virtio_mmio, proxy, 1); + return vmstate_load_state(f, &vmstate_virtio_mmio, proxy, 1, &error_fa= tal); } =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 767216d795998708f5716a23ae16c79cd90ff489..b04faa1e5c91b5cef40e54ec41d= 92422d16bfc13 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 =3D to_virtio_pci_proxy(d); =20 - return vmstate_load_state(f, &vmstate_virtio_pci, proxy, 1); + return vmstate_load_state(f, &vmstate_virtio_pci, proxy, 1, &error_fat= al); } =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 9a81ad912e013fc254899c4e55cff1f76a6112a4..419f3516c9f0a3df43831eebc77= aa1e6dfcd0f41 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -3235,6 +3235,7 @@ virtio_load(VirtIODevice *vdev, QEMUFile *f, int vers= ion_id) 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); + Error *local_err =3D NULL; =20 /* * We poison the endianness to ensure it does not get used before @@ -3327,15 +3328,17 @@ 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); + ret =3D vmstate_load_state(f, vdc->vmsd, vdev, version_id, &local_= err); if (ret) { + warn_report_err(local_err); return ret; } } =20 /* Subsections */ - ret =3D vmstate_load_state(f, &vmstate_virtio, vdev, 1); + ret =3D vmstate_load_state(f, &vmstate_virtio, vdev, 1, &local_err); if (ret) { + warn_report_err(local_err); return ret; } =20 diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h index 1ff7bd9ac425ba67cd5ca7ad97bcf570f9e19abe..056781b1c21e737583f081594d9= f88b32adfd674 100644 --- a/include/migration/vmstate.h +++ b/include/migration/vmstate.h @@ -1196,7 +1196,7 @@ extern const VMStateInfo vmstate_info_qlist; } =20 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 *vms= d, diff --git a/migration/cpr.c b/migration/cpr.c index 42ad0b0d500e5de57faf0c6517e216b2d1c0cacf..8abb6db76d2474157f804ece4c3= 5ebfc8c22d21a 100644 --- a/migration/cpr.c +++ b/migration/cpr.c @@ -233,9 +233,8 @@ int cpr_state_load(MigrationChannel *channel, Error **e= rrp) return -ENOTSUP; } =20 - ret =3D vmstate_load_state(f, &vmstate_cpr_state, &cpr_state, 1); + ret =3D vmstate_load_state(f, &vmstate_cpr_state, &cpr_state, 1, errp); if (ret) { - error_setg(errp, "vmstate_load_state error %d", ret); qemu_fclose(f); return ret; } diff --git a/migration/savevm.c b/migration/savevm.c index fabbeb296ae987d0c06ba6dafda63720205fecfd..464e8b778404a642bf60f368205= f5e6fa59118ba 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); } =20 static void vmstate_save_old_style(QEMUFile *f, SaveStateEntry *se, @@ -2817,6 +2818,7 @@ static int qemu_loadvm_state_header(QEMUFile *f) { unsigned int v; int ret; + Error *local_err =3D NULL; =20 v =3D qemu_get_be32(f); if (v !=3D QEMU_VM_FILE_MAGIC) { @@ -2839,9 +2841,11 @@ static int qemu_loadvm_state_header(QEMUFile *f) error_report("Configuration section missing"); return -EINVAL; } - ret =3D vmstate_load_state(f, &vmstate_configuration, &savevm_stat= e, 0); + ret =3D vmstate_load_state(f, &vmstate_configuration, &savevm_stat= e, 0, + &local_err); =20 if (ret) { + warn_report_err(local_err); return ret; } } diff --git a/migration/vmstate-types.c b/migration/vmstate-types.c index 741a588b7e18c6d37724b08a0101edc8bc74a0a5..f41670cc853c5b41ccc8def3548= 86a8e5c1451fd 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" =20 /* bool */ =20 @@ -543,13 +544,17 @@ static int get_tmp(QEMUFile *f, void *pv, size_t size, const VMStateField *field) { int ret; + Error *local_err =3D NULL; const VMStateDescription *vmsd =3D field->vmsd; int version_id =3D field->version_id; void *tmp =3D g_malloc(size); =20 /* Writes the parent field which is at the start of the tmp */ *(void **)tmp =3D pv; - ret =3D vmstate_load_state(f, vmsd, tmp, version_id); + ret =3D 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 unu= sed_size, const VMStateField *field) { int ret =3D 0; + Error *local_err =3D NULL; const VMStateDescription *vmsd =3D field->vmsd; /* size of a QTAILQ element */ size_t size =3D field->size; @@ -649,8 +655,9 @@ static int get_qtailq(QEMUFile *f, void *pv, size_t unu= sed_size, =20 while (qemu_get_byte(f)) { elm =3D g_malloc(size); - ret =3D vmstate_load_state(f, vmsd, elm, version_id); + ret =3D 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 unus= ed_size, GTree *tree =3D *pval; void *key, *val; int ret =3D 0; + Error *local_err =3D NULL; =20 /* 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 un= used_size, key =3D (void *)(uintptr_t)qemu_get_be64(f); } else { key =3D g_malloc0(key_size); - ret =3D vmstate_load_state(f, key_vmsd, key, version_id); + ret =3D vmstate_load_state(f, key_vmsd, key, version_id, &loca= l_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 =3D g_malloc0(val_size); - ret =3D vmstate_load_state(f, val_vmsd, val, version_id); + ret =3D vmstate_load_state(f, val_vmsd, val, version_id, &local_er= r); 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 unus= ed_size, const VMStateField *field) { int ret =3D 0; + Error *local_err =3D NULL; const VMStateDescription *vmsd =3D field->vmsd; /* size of a QLIST element */ size_t size =3D field->size; @@ -892,10 +903,11 @@ static int get_qlist(QEMUFile *f, void *pv, size_t un= used_size, =20 while (qemu_get_byte(f)) { elm =3D g_malloc(size); - ret =3D vmstate_load_state(f, vmsd, elm, version_id); + ret =3D 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 3d9f284700368e2fd573d5d77b7f7ab88008cc91..6324e5b17addcd1b4f2fcdddbd4= 7c3e4befc1d50 100644 --- a/migration/vmstate.c +++ b/migration/vmstate.c @@ -132,30 +132,34 @@ static void vmstate_handle_alloc(void *ptr, const VMS= tateField *field, } =20 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 =3D vmsd->fields; int ret =3D 0; - Error *local_err =3D NULL; =20 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 =3D vmsd->pre_load(opaque); if (ret) { + error_setg(errp, "pre load hook failed for: '%s', " + "version_id: %d, minimum version_id: %d, ret: %d", + vmsd->name, vmsd->version_id, vmsd->minimum_version= _id, + ret); return ret; } } @@ -193,13 +197,21 @@ int vmstate_load_state(QEMUFile *f, const VMStateDesc= ription *vmsd, =20 if (inner_field->flags & VMS_STRUCT) { ret =3D 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 =3D vmstate_load_state(f, inner_field->vmsd, curr_= elem, - inner_field->struct_version_i= d); + inner_field->struct_version_i= d, + errp); } else { ret =3D inner_field->info->get(f, curr_elem, size, inner_field); + if (ret < 0) { + error_setg(errp, + "Failed to load element of type %s for = %s: " + "%d", inner_field->info->name, + inner_field->name, ret); + } } =20 /* If we used a fake temp field.. free it now */ @@ -209,31 +221,43 @@ int vmstate_load_state(QEMUFile *f, const VMStateDesc= ription *vmsd, =20 if (ret >=3D 0) { ret =3D qemu_file_get_error(f); + if (ret < 0) { + 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: ", + vmsd->name, field->name, vmsd->version_i= d); 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", + vmsd->name, field->name, vmsd->version_id); return -1; } field++; } assert(field->flags =3D=3D VMS_END); - ret =3D vmstate_subsection_load(f, vmsd, opaque, &local_err); + ret =3D vmstate_subsection_load(f, vmsd, opaque, errp); if (ret !=3D 0) { qemu_file_set_error(f, ret); - warn_report_err(local_err); return ret; } if (vmsd->post_load) { ret =3D vmsd->post_load(opaque, version_id); + if (ret < 0) { + error_setg(errp, + "post load hook 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; @@ -570,6 +594,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); =20 while (qemu_peek_byte(f, 0) =3D=3D QEMU_VM_SUBSECTION) { @@ -609,12 +634,12 @@ static int vmstate_subsection_load(QEMUFile *f, const= VMStateDescription *vmsd, qemu_file_skip(f, len); /* idstr */ version_id =3D qemu_get_be32(f); =20 - ret =3D vmstate_load_state(f, sub_vmsd, opaque, version_id); + ret =3D 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..cfab58c7f45ba50f70af164c3e5= 8b01aaf9cc656 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" =20 static int temp_fd; =20 @@ -108,14 +109,16 @@ static int load_vmstate_one(const VMStateDescription = *desc, void *obj, { QEMUFile *f; int ret; + Error *local_err =3D NULL; =20 f =3D open_test_file(true); qemu_put_buffer(f, wire, size); qemu_fclose(f); =20 f =3D open_test_file(false); - ret =3D vmstate_load_state(f, desc, obj, version); + ret =3D 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 =3D { =20 static void test_load_v1(void) { + Error *local_err =3D NULL; + int ret; uint8_t buf[] =3D { 0, 0, 0, 10, /* a */ 0, 0, 0, 30, /* c */ @@ -365,7 +370,10 @@ static void test_load_v1(void) =20 QEMUFile *loading =3D open_test_file(false); TestStruct obj =3D { .b =3D 200, .e =3D 500, .f =3D 600 }; - vmstate_load_state(loading, &vmstate_versioned, &obj, 1); + ret =3D vmstate_load_state(loading, &vmstate_versioned, &obj, 1, &loca= l_err); + if (ret < 0) { + warn_report_err(local_err); + } g_assert(!qemu_file_get_error(loading)); g_assert_cmpint(obj.a, =3D=3D, 10); g_assert_cmpint(obj.b, =3D=3D, 200); @@ -378,6 +386,8 @@ static void test_load_v1(void) =20 static void test_load_v2(void) { + Error *local_err =3D NULL; + int ret; uint8_t buf[] =3D { 0, 0, 0, 10, /* a */ 0, 0, 0, 20, /* b */ @@ -391,7 +401,10 @@ static void test_load_v2(void) =20 QEMUFile *loading =3D open_test_file(false); TestStruct obj; - vmstate_load_state(loading, &vmstate_versioned, &obj, 2); + ret =3D vmstate_load_state(loading, &vmstate_versioned, &obj, 2, &loca= l_err); + if (ret < 0) { + warn_report_err(local_err); + } g_assert_cmpint(obj.a, =3D=3D, 10); g_assert_cmpint(obj.b, =3D=3D, 20); g_assert_cmpint(obj.c, =3D=3D, 30); @@ -467,6 +480,8 @@ static void test_save_skip(void) =20 static void test_load_noskip(void) { + Error *local_err =3D NULL; + int ret; uint8_t buf[] =3D { 0, 0, 0, 10, /* a */ 0, 0, 0, 20, /* b */ @@ -480,7 +495,10 @@ static void test_load_noskip(void) =20 QEMUFile *loading =3D open_test_file(false); TestStruct obj =3D { .skip_c_e =3D false }; - vmstate_load_state(loading, &vmstate_skipping, &obj, 2); + ret =3D 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, =3D=3D, 10); g_assert_cmpint(obj.b, =3D=3D, 20); @@ -493,6 +511,8 @@ static void test_load_noskip(void) =20 static void test_load_skip(void) { + Error *local_err =3D NULL; + int ret; uint8_t buf[] =3D { 0, 0, 0, 10, /* a */ 0, 0, 0, 20, /* b */ @@ -504,7 +524,10 @@ static void test_load_skip(void) =20 QEMUFile *loading =3D open_test_file(false); TestStruct obj =3D { .skip_c_e =3D true, .c =3D 300, .e =3D 500 }; - vmstate_load_state(loading, &vmstate_skipping, &obj, 2); + ret =3D 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, =3D=3D, 10); g_assert_cmpint(obj.b, =3D=3D, 20); @@ -744,6 +767,8 @@ static void test_save_q(void) =20 static void test_load_q(void) { + int ret; + Error *local_err =3D NULL; TestQtailq obj_q =3D { .i16 =3D -512, .i32 =3D 70000, @@ -773,7 +798,10 @@ static void test_load_q(void) TestQtailq tgt; =20 QTAILQ_INIT(&tgt.q); - vmstate_load_state(fload, &vmstate_q, &tgt, 1); + ret =3D vmstate_load_state(fload, &vmstate_q, &tgt, 1, &local_err); + if (ret < 0) { + warn_report_err(local_err); + } char eof =3D qemu_get_byte(fload); g_assert(!qemu_file_get_error(fload)); g_assert_cmpint(tgt.i16, =3D=3D, obj_q.i16); @@ -1115,6 +1143,8 @@ static void diff_iommu(TestGTreeIOMMU *iommu1, TestGT= reeIOMMU *iommu2) =20 static void test_gtree_load_domain(void) { + Error *local_err =3D NULL; + int ret; TestGTreeDomain *dest_domain =3D g_new0(TestGTreeDomain, 1); TestGTreeDomain *orig_domain =3D create_first_domain(); QEMUFile *fload, *fsave; @@ -1127,7 +1157,11 @@ static void test_gtree_load_domain(void) =20 fload =3D open_test_file(false); =20 - vmstate_load_state(fload, &vmstate_domain, dest_domain, 1); + ret =3D vmstate_load_state(fload, &vmstate_domain, dest_domain, 1, + &local_err); + if (ret < 0) { + warn_report_err(local_err); + } eof =3D qemu_get_byte(fload); g_assert(!qemu_file_get_error(fload)); g_assert_cmpint(orig_domain->id, =3D=3D, dest_domain->id); @@ -1230,6 +1264,8 @@ static void test_gtree_save_iommu(void) =20 static void test_gtree_load_iommu(void) { + Error *local_err =3D NULL; + int ret; TestGTreeIOMMU *dest_iommu =3D g_new0(TestGTreeIOMMU, 1); TestGTreeIOMMU *orig_iommu =3D create_iommu(); QEMUFile *fsave, *fload; @@ -1241,7 +1277,10 @@ static void test_gtree_load_iommu(void) qemu_fclose(fsave); =20 fload =3D open_test_file(false); - vmstate_load_state(fload, &vmstate_iommu, dest_iommu, 1); + ret =3D vmstate_load_state(fload, &vmstate_iommu, dest_iommu, 1, &loca= l_err); + if (ret < 0) { + warn_report_err(local_err); + } eof =3D qemu_get_byte(fload); g_assert(!qemu_file_get_error(fload)); g_assert_cmpint(orig_iommu->id, =3D=3D, dest_iommu->id); @@ -1363,6 +1402,8 @@ static void test_save_qlist(void) =20 static void test_load_qlist(void) { + Error *local_err =3D NULL; + int ret; QEMUFile *fsave, *fload; TestQListContainer *orig_container =3D alloc_container(); TestQListContainer *dest_container =3D g_new0(TestQListContainer, 1); @@ -1376,7 +1417,11 @@ static void test_load_qlist(void) qemu_fclose(fsave); =20 fload =3D open_test_file(false); - vmstate_load_state(fload, &vmstate_container, dest_container, 1); + ret =3D vmstate_load_state(fload, &vmstate_container, dest_container, = 1, + &local_err); + if (ret < 0) { + warn_report_err(local_err); + } eof =3D qemu_get_byte(fload); g_assert(!qemu_file_get_error(fload)); g_assert_cmpint(eof, =3D=3D, QEMU_VM_EOF); diff --git a/ui/vdagent.c b/ui/vdagent.c index c0746fe5b168fdc7aeb4866de2ba0c3387566649..bec728668de4d2410c3b741bcb0= a21deb373dcd3 100644 --- a/ui/vdagent.c +++ b/ui/vdagent.c @@ -1001,6 +1001,7 @@ static int get_cbinfo(QEMUFile *f, void *pv, size_t s= ize, VDAgentChardev *vd =3D QEMU_VDAGENT_CHARDEV(pv); struct CBInfoArray cbinfo =3D {}; int i, ret; + Error *local_err =3D NULL; =20 if (!have_clipboard(vd)) { return 0; @@ -1008,8 +1009,10 @@ static int get_cbinfo(QEMUFile *f, void *pv, size_t = size, =20 vdagent_clipboard_peer_register(vd); =20 - ret =3D vmstate_load_state(f, &vmstate_cbinfo_array, &cbinfo, 0); + ret =3D vmstate_load_state(f, &vmstate_cbinfo_array, &cbinfo, 0, + &local_err); if (ret) { + warn_report_err(local_err); return ret; } =20 --=20 2.50.1