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