| From foo@baz Mon Nov 29 07:12:46 PM CET 2021 |
| From: Juergen Gross <jgross@suse.com> |
| Date: Mon, 29 Nov 2021 15:57:03 +0100 |
| Subject: xen/netfront: read response from backend only once |
| |
| From: Juergen Gross <jgross@suse.com> |
| |
| commit 8446066bf8c1f9f7b7412c43fbea0fb87464d75b upstream. |
| |
| In order to avoid problems in case the backend is modifying a response |
| on the ring page while the frontend has already seen it, just read the |
| response into a local buffer in one go and then operate on that buffer |
| only. |
| |
| Signed-off-by: Juergen Gross <jgross@suse.com> |
| Reviewed-by: Jan Beulich <jbeulich@suse.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/net/xen-netfront.c | 38 +++++++++++++++++++------------------- |
| 1 file changed, 19 insertions(+), 19 deletions(-) |
| |
| --- a/drivers/net/xen-netfront.c |
| +++ b/drivers/net/xen-netfront.c |
| @@ -387,13 +387,13 @@ static void xennet_tx_buf_gc(struct netf |
| rmb(); /* Ensure we see responses up to 'rp'. */ |
| |
| for (cons = queue->tx.rsp_cons; cons != prod; cons++) { |
| - struct xen_netif_tx_response *txrsp; |
| + struct xen_netif_tx_response txrsp; |
| |
| - txrsp = RING_GET_RESPONSE(&queue->tx, cons); |
| - if (txrsp->status == XEN_NETIF_RSP_NULL) |
| + RING_COPY_RESPONSE(&queue->tx, cons, &txrsp); |
| + if (txrsp.status == XEN_NETIF_RSP_NULL) |
| continue; |
| |
| - id = txrsp->id; |
| + id = txrsp.id; |
| skb = queue->tx_skbs[id].skb; |
| if (unlikely(gnttab_query_foreign_access( |
| queue->grant_tx_ref[id]) != 0)) { |
| @@ -736,7 +736,7 @@ static int xennet_get_extras(struct netf |
| RING_IDX rp) |
| |
| { |
| - struct xen_netif_extra_info *extra; |
| + struct xen_netif_extra_info extra; |
| struct device *dev = &queue->info->netdev->dev; |
| RING_IDX cons = queue->rx.rsp_cons; |
| int err = 0; |
| @@ -752,24 +752,22 @@ static int xennet_get_extras(struct netf |
| break; |
| } |
| |
| - extra = (struct xen_netif_extra_info *) |
| - RING_GET_RESPONSE(&queue->rx, ++cons); |
| + RING_COPY_RESPONSE(&queue->rx, ++cons, &extra); |
| |
| - if (unlikely(!extra->type || |
| - extra->type >= XEN_NETIF_EXTRA_TYPE_MAX)) { |
| + if (unlikely(!extra.type || |
| + extra.type >= XEN_NETIF_EXTRA_TYPE_MAX)) { |
| if (net_ratelimit()) |
| dev_warn(dev, "Invalid extra type: %d\n", |
| - extra->type); |
| + extra.type); |
| err = -EINVAL; |
| } else { |
| - memcpy(&extras[extra->type - 1], extra, |
| - sizeof(*extra)); |
| + extras[extra.type - 1] = extra; |
| } |
| |
| skb = xennet_get_rx_skb(queue, cons); |
| ref = xennet_get_rx_ref(queue, cons); |
| xennet_move_rx_slot(queue, skb, ref); |
| - } while (extra->flags & XEN_NETIF_EXTRA_FLAG_MORE); |
| + } while (extra.flags & XEN_NETIF_EXTRA_FLAG_MORE); |
| |
| queue->rx.rsp_cons = cons; |
| return err; |
| @@ -779,7 +777,7 @@ static int xennet_get_responses(struct n |
| struct netfront_rx_info *rinfo, RING_IDX rp, |
| struct sk_buff_head *list) |
| { |
| - struct xen_netif_rx_response *rx = &rinfo->rx; |
| + struct xen_netif_rx_response *rx = &rinfo->rx, rx_local; |
| struct xen_netif_extra_info *extras = rinfo->extras; |
| struct device *dev = &queue->info->netdev->dev; |
| RING_IDX cons = queue->rx.rsp_cons; |
| @@ -837,7 +835,8 @@ next: |
| break; |
| } |
| |
| - rx = RING_GET_RESPONSE(&queue->rx, cons + slots); |
| + RING_COPY_RESPONSE(&queue->rx, cons + slots, &rx_local); |
| + rx = &rx_local; |
| skb = xennet_get_rx_skb(queue, cons + slots); |
| ref = xennet_get_rx_ref(queue, cons + slots); |
| slots++; |
| @@ -892,10 +891,11 @@ static int xennet_fill_frags(struct netf |
| struct sk_buff *nskb; |
| |
| while ((nskb = __skb_dequeue(list))) { |
| - struct xen_netif_rx_response *rx = |
| - RING_GET_RESPONSE(&queue->rx, ++cons); |
| + struct xen_netif_rx_response rx; |
| skb_frag_t *nfrag = &skb_shinfo(nskb)->frags[0]; |
| |
| + RING_COPY_RESPONSE(&queue->rx, ++cons, &rx); |
| + |
| if (skb_shinfo(skb)->nr_frags == MAX_SKB_FRAGS) { |
| unsigned int pull_to = NETFRONT_SKB_CB(skb)->pull_to; |
| |
| @@ -910,7 +910,7 @@ static int xennet_fill_frags(struct netf |
| |
| skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, |
| skb_frag_page(nfrag), |
| - rx->offset, rx->status, PAGE_SIZE); |
| + rx.offset, rx.status, PAGE_SIZE); |
| |
| skb_shinfo(nskb)->nr_frags = 0; |
| kfree_skb(nskb); |
| @@ -1008,7 +1008,7 @@ static int xennet_poll(struct napi_struc |
| i = queue->rx.rsp_cons; |
| work_done = 0; |
| while ((i != rp) && (work_done < budget)) { |
| - memcpy(rx, RING_GET_RESPONSE(&queue->rx, i), sizeof(*rx)); |
| + RING_COPY_RESPONSE(&queue->rx, i, rx); |
| memset(extras, 0, sizeof(rinfo.extras)); |
| |
| err = xennet_get_responses(queue, &rinfo, rp, &tmpq); |