diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index a17d5739fc..ed9a9012e9 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -858,27 +858,24 @@ static DeviceState *failover_find_primary_device(VirtIONet *n) static void failover_add_primary(VirtIONet *n, Error **errp) { Error *err = NULL; - QemuOpts *opts; - char *id; DeviceState *dev = failover_find_primary_device(n); if (dev) { return; } - id = failover_find_primary_device_id(n); - if (!id) { + if (!n->primary_opts) { error_setg(errp, "Primary device not found"); error_append_hint(errp, "Virtio-net failover will not work. Make " "sure primary device has parameter" " failover_pair_id=%s\n", n->netclient_name); return; } - opts = qemu_opts_find(qemu_find_opts("device"), id); - g_assert(opts); /* cannot be NULL because id was found using opts list */ - dev = qdev_device_add(opts, &err); + + dev = qdev_device_add(n->primary_opts, &err); if (err) { - qemu_opts_del(opts); + qemu_opts_del(n->primary_opts); + n->primary_opts = NULL; } else { object_unref(OBJECT(dev)); } @@ -3317,6 +3314,19 @@ static bool failover_hide_primary_device(DeviceListener *listener, return false; } + if (n->primary_opts) { + error_setg(errp, "Cannot attach more than one primary device to '%s'", + n->netclient_name); + return false; + } + + /* + * Having a weak reference here should be okay because a device can't be + * deleted while it's hidden. This will be replaced soon with a QDict that + * has a clearer ownership model. + */ + n->primary_opts = device_opts; + /* failover_primary_hidden is set during feature negotiation */ return qatomic_read(&n->failover_primary_hidden); } diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h index 824a69c23f..d118c95f69 100644 --- a/include/hw/virtio/virtio-net.h +++ b/include/hw/virtio/virtio-net.h @@ -209,6 +209,7 @@ struct VirtIONet { bool failover_primary_hidden; bool failover; DeviceListener primary_listener; + QemuOpts *primary_opts; Notifier migration_state; VirtioNetRssData rss_data; struct NetRxPkt *rx_pkt;