qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] Re: [PATCHv3] net: delay freeing peer host device


From: Alex Williamson
Subject: [Qemu-devel] Re: [PATCHv3] net: delay freeing peer host device
Date: Wed, 06 Oct 2010 09:48:06 -0600

On Mon, 2010-10-04 at 18:13 +0200, Michael S. Tsirkin wrote:
> With -netdev, virtio devices present offload
> features to guest, depending on the backend used.
> Thus, removing host netdev peer while guest is
> active leads to guest-visible inconsistency and/or crashes.
> 
> As a solution, while guest (NIC) peer device exists,
> we prevent the host peer pointer 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 a shell of
> the host device around for as long as guest device exists.
> 
> The link is put down so all packets will get discarded.
> 
> Note: this does not fix the fact that hotplug is asynchronous and
> depends on the guest.  At the moment, management can detect that pci
> device deletion is delayed by doing e.g. info net. As a next step, we
> shall add commands that control hotplug/unplug without removing the
> device, an event to report that guest has responded to the hotplug
> event, and a command to cause instant device removal.
> 
> Signed-off-by: Michael S. Tsirkin <address@hidden>
> ---
> 
> So the below has survived some stress-testing, I'll put
> this on my tree unless there are any objections.
> 
> Changes from v2:
>   fix crash on repeated netdev_del
> 
>  net.c |   50 ++++++++++++++++++++++++++++++++++++++++----------
>  net.h |    1 +
>  2 files changed, 41 insertions(+), 10 deletions(-)
> 
> diff --git a/net.c b/net.c
> index 3d0fde7..032f09e 100644
> --- a/net.c
> +++ b/net.c
> @@ -281,29 +281,59 @@ NICState *qemu_new_nic(NetClientInfo *info,
>      return nic;
>  }
>  
> -void qemu_del_vlan_client(VLANClientState *vc)
> +static void qemu_free_vlan_client(VLANClientState *vc)
>  {
> -    if (vc->vlan) {
> -        QTAILQ_REMOVE(&vc->vlan->clients, vc, next);
> -    } else {
> +    if (!vc->vlan) {
>          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 (vc->info->cleanup) {
> -        vc->info->cleanup(vc);
> -    }
> -
>      qemu_free(vc->name);
>      qemu_free(vc->model);
>      qemu_free(vc);
>  }
>  
> +void qemu_del_vlan_client(VLANClientState *vc)
> +{
> +    /* If there is a peer NIC, delete and cleanup client, but do not free. */
> +    if (!vc->vlan && vc->peer && vc->peer->info->type == 
> NET_CLIENT_TYPE_NIC) {
> +        NICState *nic = DO_UPCAST(NICState, nc, vc->peer);
> +        if (nic->peer_deleted) {
> +            return;
> +        }
> +        nic->peer_deleted = true;
> +        /* Let NIC know peer is gone. */
> +        vc->peer->link_down = true;
> +        if (vc->peer->info->link_status_changed) {
> +            vc->peer->info->link_status_changed(vc->peer);
> +        }
> +        if (vc->info->cleanup) {
> +            vc->info->cleanup(vc);
> +        }

This is now the only case that calls cleanup, is that intentional?
Seems like we won't end up calling nic cleanup routines.

Alex

> +        QTAILQ_REMOVE(&non_vlan_clients, vc, next);
> +        return;
> +    }
> +
> +    /* If this is a peer NIC and peer has already been deleted, free it now. 
> */
> +    if (!vc->vlan && vc->peer && vc->info->type == NET_CLIENT_TYPE_NIC) {
> +        NICState *nic = DO_UPCAST(NICState, nc, vc);
> +        if (nic->peer_deleted) {
> +            qemu_free_vlan_client(vc->peer);
> +        }
> +    }
> +
> +    if (vc->vlan) {
> +        QTAILQ_REMOVE(&vc->vlan->clients, vc, next);
> +    } else {
> +        QTAILQ_REMOVE(&non_vlan_clients, vc, next);
> +    }
> +
> +    qemu_free_vlan_client(vc);
> +}
> +
>  VLANClientState *
>  qemu_find_vlan_client_by_name(Monitor *mon, int vlan_id,
>                                const char *client_str)
> 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 {






reply via email to

[Prev in Thread] Current Thread [Next in Thread]