From: Dongli Zhang Date: Mon, 21 Jan 2019 01:56:55 +0000 (+0800) Subject: xen-netback: wake up xenvif_dealloc_kthread when it should stop X-Git-Tag: v4.1.12-124.31.3~307 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=4de57e4161aa6cb0ed289856ed2b47c8f57a5c1e;p=users%2Fjedix%2Flinux-maple.git xen-netback: wake up xenvif_dealloc_kthread when it should stop The feature 'staging grant' changed the behaviour of xenvif_zerocopy_callback() that queue->dealloc_prod may not increase during the do-while loop because of 'staging grant'. As a result, xenvif_skb_zerocopy_complete() would not wake up xenvif_dealloc_kthread because (prod == queue->dealloc_prod). This makes trouble when the xenvif_dealloc_kthread is requested to stop by xenvif_disconnect(). When xenvif_dealloc_kthread is stopped while inflight_packets is not 0, xenvif_dealloc_kthread would not exit until inflight_packets becomes 0. However, because of 'staging grant', xenvif_skb_zerocopy_complete() would not wake up xenvif_dealloc_kthread() although inflight_packets is decremented and already becomes 0. As a result, xenvif_dealloc_kthread will never wakes up. xenvif_skb_zerocopy_complete() should wake up xenvif_dealloc_kthread when the latter is in the progress to stop. Orabug: 29217927 Fixes: fdbb2e3659b3 ("xen-netback: use gref mappings for Tx requests") Reported-by: Ajaykumar Hotchandani Signed-off-by: Dongli Zhang Reviewed-by: Joao Martins Reviewed-by: Joe Jin Signed-off-by: Brian Maly --- diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index 461b764f0567..432a965242da 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c @@ -66,9 +66,12 @@ void xenvif_skb_zerocopy_complete(struct xenvif_queue *queue, /* Wake the dealloc thread _after_ decrementing inflight_packets so * that if kthread_stop() has already been called, the dealloc thread * does not wait forever with nothing to wake it. But only wake up when - * there are grants to unmap. + * there are grants to unmap, or when we disconnect/teardown the + * interface. */ - if (prod != queue->dealloc_prod) + if (prod != queue->dealloc_prod || + (unlikely(!test_bit(VIF_STATUS_CONNECTED, &queue->vif->status) && + !atomic_read(&queue->inflight_packets)))) wake_up(&queue->dealloc_wq); }