[PATCH 07/27] hw/usb/dev-smartcard-reader: block migration with pending queues
Marc-André Lureau <[email protected]> Wed, 05 Aug 2026 15:50:57 +0400
| Newsgroups | gmane.comp.emulators.qemu |
|---|---|
| Message-ID | <[email protected]> |
Several queue state fields are not included in the vmstate:
bulk_in_pending_num, pending_answers_start, and pending_answers_end.
Also if current_bulk_in != NULL (ongoing transfer). Migrating while any
of these are non-zero produces inconsistent state on the destination.
Rather than extending the vmstate (which would require a version bump
and migration compat machinery), block migration when the queues are
non-empty. In practice this window is very short since the CMD_SLOT_BUSY
enforcement limits pending_answers to at most one entry.
Convert pre_save to the pre_save_errp form so it can report the error
cleanly. Follow up patches will add migration blocker and new migration
version.
Fixes: 367071447ec5 ("usb-ccid: add CCID bus")
Signed-off-by: Marc-André Lureau <[email protected]>
---
hw/usb/dev-smartcard-reader.c | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c
index a147cd19f388..1b8f0e10e172 100644
--- a/hw/usb/dev-smartcard-reader.c
+++ b/hw/usb/dev-smartcard-reader.c
@@ -1377,13 +1377,20 @@ static int ccid_post_load(void *opaque, int version_id)
return 0;
}
-static int ccid_pre_save(void *opaque)
+static bool ccid_pre_save(void *opaque, Error **errp)
{
USBCCIDState *s = opaque;
+ if (s->pending_answers_num || s->bulk_in_pending_num ||
+ s->current_bulk_in) {
+ error_setg(errp, "usb-ccid has pending queue state which cannot be "
+ "migrated safely");
+ return false;
+ }
+
s->state_vmstate = s->dev.state;
- return 0;
+ return true;
}
static const VMStateDescription bulk_in_vmstate = {
@@ -1426,7 +1433,7 @@ static const VMStateDescription ccid_vmstate = {
.version_id = 1,
.minimum_version_id = 1,
.post_load = ccid_post_load,
- .pre_save = ccid_pre_save,
+ .pre_save_errp = ccid_pre_save,
.fields = (const VMStateField[]) {
VMSTATE_STRUCT(dev, USBCCIDState, 1, usb_device_vmstate, USBDevice),
VMSTATE_UINT8(debug, USBCCIDState),
--
2.55.0