With -netdev, virtio devices present offload features to guest, depending on the backend used. Thus, removing host ntedev peer while guest is active leads to guest-visible inconsistency and/or crashes. See e.g. https://bugzilla.redhat.com/show_bug.cgi?id=623735
As a solution, while guest (NIC) peer device exists, we must prevent the host peer from being deleted. This patch does this by adding peer_deleted flag in nic state: if host device is going away while guest device is around, set this flag and keep host device around for as long as guest device exists. Signed-off-by: Michael S. Tsirkin <m...@redhat.com> --- net.c | 21 ++++++++++++++++++++- net.h | 1 + 2 files changed, 21 insertions(+), 1 deletions(-) diff --git a/net.c b/net.c index 3d0fde7..10855d1 100644 --- a/net.c +++ b/net.c @@ -286,12 +286,31 @@ void qemu_del_vlan_client(VLANClientState *vc) if (vc->vlan) { QTAILQ_REMOVE(&vc->vlan->clients, vc, next); } else { + /* Even if client will not be deleted yet, remove it from list so it + * does not appear in monitor. */ + QTAILQ_REMOVE(&non_vlan_clients, vc, next); + /* Detect that guest-visible (NIC) peer is active, and delay deletion. + * */ + if (vc->peer && vc->peer->info->type == NET_CLIENT_TYPE_NIC) { + NICState *nic = DO_UPCAST(NICState, nc, vc->peer); + assert(!nic->peer_deleted); + nic->peer_deleted = true; + return; + } if (vc->send_queue) { qemu_del_net_queue(vc->send_queue); } - QTAILQ_REMOVE(&non_vlan_clients, vc, next); if (vc->peer) { vc->peer->peer = NULL; + /* If this is a guest-visible (NIC) device, + * and peer has already been removed from monitor, + * delete it here. */ + if (vc->info->type == NET_CLIENT_TYPE_NIC) { + NICState *nic = DO_UPCAST(NICState, nc, vc); + if (nic->peer_deleted) { + qemu_del_vlan_client(vc->peer); + } + } } } diff --git a/net.h b/net.h index 518cf9c..44c31a9 100644 --- a/net.h +++ b/net.h @@ -72,6 +72,7 @@ typedef struct NICState { VLANClientState nc; NICConf *conf; void *opaque; + bool peer_deleted; } NICState; struct VLANState { -- 1.7.2.2