Skip to content

Commit 4c0d6df

Browse files
Feng Liusmb49
authored andcommitted
virtio_net: Fix error unwinding of XDP initialization
BugLink: https://bugs.launchpad.net/bugs/2028408 [ Upstream commit 5306623 ] When initializing XDP in virtnet_open(), some rq xdp initialization may hit an error causing net device open failed. However, previous rqs have already initialized XDP and enabled NAPI, which is not the expected behavior. Need to roll back the previous rq initialization to avoid leaks in error unwinding of init code. Also extract helper functions of disable and enable queue pairs. Use newly introduced disable helper function in error unwinding and virtnet_close. Use enable helper function in virtnet_open. Fixes: 754b8a2 ("virtio_net: setup xdp_rxq_info") Signed-off-by: Feng Liu <feliu@nvidia.com> Reviewed-by: Jiri Pirko <jiri@nvidia.com> Reviewed-by: William Tu <witu@nvidia.com> Acked-by: Michael S. Tsirkin <mst@redhat.com> Acked-by: Jason Wang <jasowang@redhat.com> Reviewed-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com> Acked-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Sasha Levin <sashal@kernel.org> Signed-off-by: Kamal Mostafa <kamal@canonical.com> Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
1 parent 0fe2477 commit 4c0d6df

File tree

1 file changed

+44
-17
lines changed

1 file changed

+44
-17
lines changed

drivers/net/virtio_net.c

Lines changed: 44 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1604,6 +1604,38 @@ static int virtnet_poll(struct napi_struct *napi, int budget)
16041604
return received;
16051605
}
16061606

1607+
static void virtnet_disable_queue_pair(struct virtnet_info *vi, int qp_index)
1608+
{
1609+
virtnet_napi_tx_disable(&vi->sq[qp_index].napi);
1610+
napi_disable(&vi->rq[qp_index].napi);
1611+
xdp_rxq_info_unreg(&vi->rq[qp_index].xdp_rxq);
1612+
}
1613+
1614+
static int virtnet_enable_queue_pair(struct virtnet_info *vi, int qp_index)
1615+
{
1616+
struct net_device *dev = vi->dev;
1617+
int err;
1618+
1619+
err = xdp_rxq_info_reg(&vi->rq[qp_index].xdp_rxq, dev, qp_index,
1620+
vi->rq[qp_index].napi.napi_id);
1621+
if (err < 0)
1622+
return err;
1623+
1624+
err = xdp_rxq_info_reg_mem_model(&vi->rq[qp_index].xdp_rxq,
1625+
MEM_TYPE_PAGE_SHARED, NULL);
1626+
if (err < 0)
1627+
goto err_xdp_reg_mem_model;
1628+
1629+
virtnet_napi_enable(vi->rq[qp_index].vq, &vi->rq[qp_index].napi);
1630+
virtnet_napi_tx_enable(vi, vi->sq[qp_index].vq, &vi->sq[qp_index].napi);
1631+
1632+
return 0;
1633+
1634+
err_xdp_reg_mem_model:
1635+
xdp_rxq_info_unreg(&vi->rq[qp_index].xdp_rxq);
1636+
return err;
1637+
}
1638+
16071639
static int virtnet_open(struct net_device *dev)
16081640
{
16091641
struct virtnet_info *vi = netdev_priv(dev);
@@ -1617,22 +1649,20 @@ static int virtnet_open(struct net_device *dev)
16171649
if (!try_fill_recv(vi, &vi->rq[i], GFP_KERNEL))
16181650
schedule_delayed_work(&vi->refill, 0);
16191651

1620-
err = xdp_rxq_info_reg(&vi->rq[i].xdp_rxq, dev, i, vi->rq[i].napi.napi_id);
1652+
err = virtnet_enable_queue_pair(vi, i);
16211653
if (err < 0)
1622-
return err;
1623-
1624-
err = xdp_rxq_info_reg_mem_model(&vi->rq[i].xdp_rxq,
1625-
MEM_TYPE_PAGE_SHARED, NULL);
1626-
if (err < 0) {
1627-
xdp_rxq_info_unreg(&vi->rq[i].xdp_rxq);
1628-
return err;
1629-
}
1630-
1631-
virtnet_napi_enable(vi->rq[i].vq, &vi->rq[i].napi);
1632-
virtnet_napi_tx_enable(vi, vi->sq[i].vq, &vi->sq[i].napi);
1654+
goto err_enable_qp;
16331655
}
16341656

16351657
return 0;
1658+
1659+
err_enable_qp:
1660+
disable_delayed_refill(vi);
1661+
cancel_delayed_work_sync(&vi->refill);
1662+
1663+
for (i--; i >= 0; i--)
1664+
virtnet_disable_queue_pair(vi, i);
1665+
return err;
16361666
}
16371667

16381668
static int virtnet_poll_tx(struct napi_struct *napi, int budget)
@@ -1998,11 +2028,8 @@ static int virtnet_close(struct net_device *dev)
19982028
/* Make sure refill_work doesn't re-enable napi! */
19992029
cancel_delayed_work_sync(&vi->refill);
20002030

2001-
for (i = 0; i < vi->max_queue_pairs; i++) {
2002-
virtnet_napi_tx_disable(&vi->sq[i].napi);
2003-
napi_disable(&vi->rq[i].napi);
2004-
xdp_rxq_info_unreg(&vi->rq[i].xdp_rxq);
2005-
}
2031+
for (i = 0; i < vi->max_queue_pairs; i++)
2032+
virtnet_disable_queue_pair(vi, i);
20062033

20072034
return 0;
20082035
}

0 commit comments

Comments
 (0)