Paul Durrant
2013-Sep-20 12:56 UTC
[PATCH net-next 1/2] xen-netback: add a vif-is-connected flag
Having applied my patch to separate vif disconnect and free, I ran into a BUG when testing resume from S3 with a Windows frontend because the vif task pointer was not cleared by xenvif_disconnect() and so a double call to this function tries to stop the thread twice. Rather than applying a point fix for that issue it seems better to introduce a boolean to indicate whether the vif is connected or not such that repeated calls to either xenvif_connect() or xenvif_disconnect() behave appropriately. Signed-off-by: Paul Durrant <paul.durrant@citrix.com> Cc: David Vrabel <david.vrabel@citrix.com> Cc: Wei Liu <wei.liu2@citrix.com> Cc: Ian Campbell <ian.campbell@citrix.com> --- drivers/net/xen-netback/common.h | 1 + drivers/net/xen-netback/interface.c | 24 +++++++++++++----------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h index 5715318..860d92c 100644 --- a/drivers/net/xen-netback/common.h +++ b/drivers/net/xen-netback/common.h @@ -169,6 +169,7 @@ struct xenvif { /* Miscellaneous private stuff. */ struct net_device *dev; + bool connected; }; static inline struct xenbus_device *xenvif_to_xenbus_device(struct xenvif *vif) diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index 01bb854..94b47f5 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c @@ -366,7 +366,7 @@ int xenvif_connect(struct xenvif *vif, unsigned long tx_ring_ref, int err = -ENOMEM; /* Already connected through? */ - if (vif->tx_irq) + if (vif->connected) return 0; err = xenvif_map_frontend_rings(vif, tx_ring_ref, rx_ring_ref); @@ -425,6 +425,7 @@ int xenvif_connect(struct xenvif *vif, unsigned long tx_ring_ref, wake_up_process(vif->task); + vif->connected = 1; return 0; err_rx_unbind: @@ -453,23 +454,24 @@ void xenvif_carrier_off(struct xenvif *vif) void xenvif_disconnect(struct xenvif *vif) { + if (!vif->connected) + return; + if (netif_carrier_ok(vif->dev)) xenvif_carrier_off(vif); - if (vif->tx_irq) { - if (vif->tx_irq == vif->rx_irq) - unbind_from_irqhandler(vif->tx_irq, vif); - else { - unbind_from_irqhandler(vif->tx_irq, vif); - unbind_from_irqhandler(vif->rx_irq, vif); - } - vif->tx_irq = 0; + if (vif->tx_irq == vif->rx_irq) + unbind_from_irqhandler(vif->tx_irq, vif); + else { + unbind_from_irqhandler(vif->tx_irq, vif); + unbind_from_irqhandler(vif->rx_irq, vif); } - if (vif->task) - kthread_stop(vif->task); + kthread_stop(vif->task); xenvif_unmap_frontend_rings(vif); + + vif->connected = 0; } void xenvif_free(struct xenvif *vif) -- 1.7.10.4
Wei Liu
2013-Sep-20 13:31 UTC
Re: [PATCH net-next 1/2] xen-netback: add a vif-is-connected flag
On Fri, Sep 20, 2013 at 01:56:30PM +0100, Paul Durrant wrote:> Having applied my patch to separate vif disconnect and free, I ran into a > BUG when testing resume from S3 with a Windows frontend because the vif task > pointer was not cleared by xenvif_disconnect() and so a double call to this > function tries to stop the thread twice. > Rather than applying a point fix for that issue it seems better to introduce > a boolean to indicate whether the vif is connected or not such that repeated > calls to either xenvif_connect() or xenvif_disconnect() behave appropriately. > > Signed-off-by: Paul Durrant <paul.durrant@citrix.com> > Cc: David Vrabel <david.vrabel@citrix.com> > Cc: Wei Liu <wei.liu2@citrix.com> > Cc: Ian Campbell <ian.campbell@citrix.com>Reasonable change. Acked-by: Wei Liu <wei.liu2@citrix.com> Thanks Wei.> --- > drivers/net/xen-netback/common.h | 1 + > drivers/net/xen-netback/interface.c | 24 +++++++++++++----------- > 2 files changed, 14 insertions(+), 11 deletions(-) > > diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h > index 5715318..860d92c 100644 > --- a/drivers/net/xen-netback/common.h > +++ b/drivers/net/xen-netback/common.h > @@ -169,6 +169,7 @@ struct xenvif { > > /* Miscellaneous private stuff. */ > struct net_device *dev; > + bool connected; > }; > > static inline struct xenbus_device *xenvif_to_xenbus_device(struct xenvif *vif) > diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c > index 01bb854..94b47f5 100644 > --- a/drivers/net/xen-netback/interface.c > +++ b/drivers/net/xen-netback/interface.c > @@ -366,7 +366,7 @@ int xenvif_connect(struct xenvif *vif, unsigned long tx_ring_ref, > int err = -ENOMEM; > > /* Already connected through? */ > - if (vif->tx_irq) > + if (vif->connected) > return 0; > > err = xenvif_map_frontend_rings(vif, tx_ring_ref, rx_ring_ref); > @@ -425,6 +425,7 @@ int xenvif_connect(struct xenvif *vif, unsigned long tx_ring_ref, > > wake_up_process(vif->task); > > + vif->connected = 1; > return 0; > > err_rx_unbind: > @@ -453,23 +454,24 @@ void xenvif_carrier_off(struct xenvif *vif) > > void xenvif_disconnect(struct xenvif *vif) > { > + if (!vif->connected) > + return; > + > if (netif_carrier_ok(vif->dev)) > xenvif_carrier_off(vif); > > - if (vif->tx_irq) { > - if (vif->tx_irq == vif->rx_irq) > - unbind_from_irqhandler(vif->tx_irq, vif); > - else { > - unbind_from_irqhandler(vif->tx_irq, vif); > - unbind_from_irqhandler(vif->rx_irq, vif); > - } > - vif->tx_irq = 0; > + if (vif->tx_irq == vif->rx_irq) > + unbind_from_irqhandler(vif->tx_irq, vif); > + else { > + unbind_from_irqhandler(vif->tx_irq, vif); > + unbind_from_irqhandler(vif->rx_irq, vif); > } > > - if (vif->task) > - kthread_stop(vif->task); > + kthread_stop(vif->task); > > xenvif_unmap_frontend_rings(vif); > + > + vif->connected = 0; > } > > void xenvif_free(struct xenvif *vif) > -- > 1.7.10.4
David Vrabel
2013-Sep-20 14:28 UTC
Re: [PATCH net-next 1/2] xen-netback: add a vif-is-connected flag
On 20/09/13 14:31, Wei Liu wrote:> On Fri, Sep 20, 2013 at 01:56:30PM +0100, Paul Durrant wrote: >> Having applied my patch to separate vif disconnect and free, I ran into a >> BUG when testing resume from S3 with a Windows frontend because the vif task >> pointer was not cleared by xenvif_disconnect() and so a double call to this >> function tries to stop the thread twice. >> Rather than applying a point fix for that issue it seems better to introduce >> a boolean to indicate whether the vif is connected or not such that repeated >> calls to either xenvif_connect() or xenvif_disconnect() behave appropriately.We already have a backend state of CONNECTED/CLOSED/etc. why do we need an additional bit of state outside of this? Does something like this in frontend_changed() fix it? case XenbusStateClosing: switch (dev->state) { case XenbusStateClosed; break; case XenbusStateConnected: disconnect_backend(dev); /* fall through */ default: xenbus_switch_state(dev, XenbusStateClosing); break; } break; case XenbusStateClosed: switch (dev->state) { case XenbusStateConnected; disconnect_backend(dev); /* fall through */ default: xenbus_switch_state(dev, XenbusStateClosed); break; } if (xenbus_dev_is_online(dev)) break; /* fall through if not online */ Can you also remove destroy_backend()? It''s not needed any more. I''d also recommend waiting a bit for other review feedback before posting an updated series. David
Paul Durrant
2013-Sep-20 15:02 UTC
Re: [PATCH net-next 1/2] xen-netback: add a vif-is-connected flag
> -----Original Message----- > From: David Vrabel > Sent: 20 September 2013 15:29 > To: Wei Liu > Cc: Paul Durrant; netdev@vger.kernel.org; xen-devel@lists.xen.org; Ian > Campbell > Subject: Re: [PATCH net-next 1/2] xen-netback: add a vif-is-connected flag > > On 20/09/13 14:31, Wei Liu wrote: > > On Fri, Sep 20, 2013 at 01:56:30PM +0100, Paul Durrant wrote: > >> Having applied my patch to separate vif disconnect and free, I ran into a > >> BUG when testing resume from S3 with a Windows frontend because the > vif task > >> pointer was not cleared by xenvif_disconnect() and so a double call to this > >> function tries to stop the thread twice. > >> Rather than applying a point fix for that issue it seems better to introduce > >> a boolean to indicate whether the vif is connected or not such that > repeated > >> calls to either xenvif_connect() or xenvif_disconnect() behave > appropriately. > > We already have a backend state of CONNECTED/CLOSED/etc. why do we > need > an additional bit of state outside of this? >It''s not really additional state; we were essentially inferring connected-ness from the value of tx_irq. This patch really just removes that inference and created something with the intended meaning.> Does something like this in frontend_changed() fix it? >It may well do, but it''s a far more invasive change and would require more testing. It certainly sounds like a good thing to do in the longer term. Paul> case XenbusStateClosing: > switch (dev->state) { > case XenbusStateClosed; > break; > case XenbusStateConnected: > disconnect_backend(dev); > /* fall through */ > default: > xenbus_switch_state(dev, XenbusStateClosing); > break; > } > break; > > case XenbusStateClosed: > switch (dev->state) { > case XenbusStateConnected; > disconnect_backend(dev); > /* fall through */ > default: > xenbus_switch_state(dev, XenbusStateClosed); > break; > } > if (xenbus_dev_is_online(dev)) > break; > /* fall through if not online */ > > Can you also remove destroy_backend()? It''s not needed any more. > > I''d also recommend waiting a bit for other review feedback before > posting an updated series. > > David