Commit 9eb7f8e4 authored by Andrew Boyer's avatar Andrew Boyer Committed by Doug Ledford

IB/rxe: Move refcounting earlier in rxe_send()

The network stack will call nskb's destructor, rxe_skb_tx_dtor(), if the
packet gets dropped by ip_local_out()/ip6_local_out(). Thus we need to add
the QP ref before output to avoid extra dereferences during network
congestion. This could lead to unwanted destruction of the QP.

Fix up the skb_out accounting, too.

Fixes: fda85ce9 ("IB/rxe: Fix kernel panic from skb destructor")
Signed-off-by: default avatarAndrew Boyer <andrew.boyer@dell.com>
Acked-by: default avatarMoni Shoua <monis@mellanox.com>
Signed-off-by: default avatarDoug Ledford <dledford@redhat.com>
parent 0208da90
...@@ -460,12 +460,17 @@ int rxe_send(struct rxe_dev *rxe, struct rxe_pkt_info *pkt, struct sk_buff *skb) ...@@ -460,12 +460,17 @@ int rxe_send(struct rxe_dev *rxe, struct rxe_pkt_info *pkt, struct sk_buff *skb)
nskb->destructor = rxe_skb_tx_dtor; nskb->destructor = rxe_skb_tx_dtor;
nskb->sk = pkt->qp->sk->sk; nskb->sk = pkt->qp->sk->sk;
rxe_add_ref(pkt->qp);
atomic_inc(&pkt->qp->skb_out);
if (av->network_type == RDMA_NETWORK_IPV4) { if (av->network_type == RDMA_NETWORK_IPV4) {
err = ip_local_out(dev_net(skb_dst(skb)->dev), nskb->sk, nskb); err = ip_local_out(dev_net(skb_dst(skb)->dev), nskb->sk, nskb);
} else if (av->network_type == RDMA_NETWORK_IPV6) { } else if (av->network_type == RDMA_NETWORK_IPV6) {
err = ip6_local_out(dev_net(skb_dst(skb)->dev), nskb->sk, nskb); err = ip6_local_out(dev_net(skb_dst(skb)->dev), nskb->sk, nskb);
} else { } else {
pr_err("Unknown layer 3 protocol: %d\n", av->network_type); pr_err("Unknown layer 3 protocol: %d\n", av->network_type);
atomic_dec(&pkt->qp->skb_out);
rxe_drop_ref(pkt->qp);
kfree_skb(nskb); kfree_skb(nskb);
return -EINVAL; return -EINVAL;
} }
...@@ -475,10 +480,7 @@ int rxe_send(struct rxe_dev *rxe, struct rxe_pkt_info *pkt, struct sk_buff *skb) ...@@ -475,10 +480,7 @@ int rxe_send(struct rxe_dev *rxe, struct rxe_pkt_info *pkt, struct sk_buff *skb)
return -EAGAIN; return -EAGAIN;
} }
rxe_add_ref(pkt->qp);
atomic_inc(&pkt->qp->skb_out);
kfree_skb(skb); kfree_skb(skb);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment