RDMA/rxe: Use rdma_read_gid_attr_ndev_rcu to access netdev
authorParav Pandit <parav@mellanox.com>
Thu, 2 May 2019 07:48:05 +0000 (10:48 +0300)
committerJason Gunthorpe <jgg@mellanox.com>
Fri, 3 May 2019 14:10:03 +0000 (11:10 -0300)
Use rdma_read_gid_attr_ndev_rcu() to access netdevice attached to GID
entry under rcu lock.

This ensures that while working on the netdevice of the GID, it doesn't
get freed.

Signed-off-by: Parav Pandit <parav@mellanox.com>
Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
drivers/infiniband/sw/rxe/rxe_net.c

index c441397..5a3474f 100644 (file)
@@ -458,7 +458,7 @@ struct sk_buff *rxe_init_packet(struct rxe_dev *rxe, struct rxe_av *av,
                                int paylen, struct rxe_pkt_info *pkt)
 {
        unsigned int hdr_len;
-       struct sk_buff *skb;
+       struct sk_buff *skb = NULL;
        struct net_device *ndev;
        const struct ib_gid_attr *attr;
        const int port_num = 1;
@@ -466,7 +466,6 @@ struct sk_buff *rxe_init_packet(struct rxe_dev *rxe, struct rxe_av *av,
        attr = rdma_get_gid_attr(&rxe->ib_dev, port_num, av->grh.sgid_index);
        if (IS_ERR(attr))
                return NULL;
-       ndev = attr->ndev;
 
        if (av->network_type == RDMA_NETWORK_IPV4)
                hdr_len = ETH_HLEN + sizeof(struct udphdr) +
@@ -475,16 +474,26 @@ struct sk_buff *rxe_init_packet(struct rxe_dev *rxe, struct rxe_av *av,
                hdr_len = ETH_HLEN + sizeof(struct udphdr) +
                        sizeof(struct ipv6hdr);
 
+       rcu_read_lock();
+       ndev = rdma_read_gid_attr_ndev_rcu(attr);
+       if (IS_ERR(ndev)) {
+               rcu_read_unlock();
+               goto out;
+       }
        skb = alloc_skb(paylen + hdr_len + LL_RESERVED_SPACE(ndev),
                        GFP_ATOMIC);
 
-       if (unlikely(!skb))
+       if (unlikely(!skb)) {
+               rcu_read_unlock();
                goto out;
+       }
 
        skb_reserve(skb, hdr_len + LL_RESERVED_SPACE(ndev));
 
        /* FIXME: hold reference to this netdev until life of this skb. */
        skb->dev        = ndev;
+       rcu_read_unlock();
+
        if (av->network_type == RDMA_NETWORK_IPV4)
                skb->protocol = htons(ETH_P_IP);
        else