]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commitdiff
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 9 Jan 2018 00:17:31 +0000 (16:17 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 9 Jan 2018 00:17:31 +0000 (16:17 -0800)
Pull rdma fixes from Doug Ledford:

 - One line fix to mlx4 error flow (same as mlx5 fix in last pull
   request, just in the mlx4 driver)

 - Fix a race condition in the IPoIB driver. This patch is larger than
   just a one line fix, but resolves a race condition in a fairly
   straight forward manner

 - Fix a locking issue in the RDMA netlink code. This patch is also
   larger than I would like for a late -rc. It has, however, had a week
   to bake in the rdma tree prior to this pull request

 - One line fix to fix granting remote machine access to memory that
   they don't need and shouldn't have

 - One line fix to correct the fact that our sgid/dgid pair is swapped
   from what you would expect when receiving an incoming connection
   request

* tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma:
  IB/srpt: Fix ACL lookup during login
  IB/srpt: Disable RDMA access by the initiator
  RDMA/netlink: Fix locking around __ib_get_device_by_index
  IB/ipoib: Fix race condition in neigh creation
  IB/mlx4: Fix mlx4_ib_alloc_mr error flow

drivers/infiniband/core/core_priv.h
drivers/infiniband/core/device.c
drivers/infiniband/core/nldev.c
drivers/infiniband/hw/mlx4/mr.c
drivers/infiniband/ulp/ipoib/ipoib_main.c
drivers/infiniband/ulp/ipoib/ipoib_multicast.c
drivers/infiniband/ulp/srpt/ib_srpt.c

index a1d687a664f85edc4eeb1bf50360cb02c65faa45..66f0268f37a6ca143f558a6c02080c1b702afcc3 100644 (file)
@@ -314,7 +314,7 @@ static inline int ib_mad_enforce_security(struct ib_mad_agent_private *map,
 }
 #endif
 
-struct ib_device *__ib_device_get_by_index(u32 ifindex);
+struct ib_device *ib_device_get_by_index(u32 ifindex);
 /* RDMA device netlink */
 void nldev_init(void);
 void nldev_exit(void);
index 30914f3baa5f1ee5b43695c96f56c54b8ce2a2df..465520627e4b6b93c85aae4c276be44607eb7400 100644 (file)
@@ -134,7 +134,7 @@ static int ib_device_check_mandatory(struct ib_device *device)
        return 0;
 }
 
-struct ib_device *__ib_device_get_by_index(u32 index)
+static struct ib_device *__ib_device_get_by_index(u32 index)
 {
        struct ib_device *device;
 
@@ -145,6 +145,22 @@ struct ib_device *__ib_device_get_by_index(u32 index)
        return NULL;
 }
 
+/*
+ * Caller is responsible to return refrerence count by calling put_device()
+ */
+struct ib_device *ib_device_get_by_index(u32 index)
+{
+       struct ib_device *device;
+
+       down_read(&lists_rwsem);
+       device = __ib_device_get_by_index(index);
+       if (device)
+               get_device(&device->dev);
+
+       up_read(&lists_rwsem);
+       return device;
+}
+
 static struct ib_device *__ib_device_get_by_name(const char *name)
 {
        struct ib_device *device;
index 9a05245a1acf4a7fd010fb7f038e84d7bbf5003e..0dcd1aa6f683e8bc73901ecb4fee08c8a167801e 100644 (file)
@@ -142,27 +142,34 @@ static int nldev_get_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
 
        index = nla_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
 
-       device = __ib_device_get_by_index(index);
+       device = ib_device_get_by_index(index);
        if (!device)
                return -EINVAL;
 
        msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
-       if (!msg)
-               return -ENOMEM;
+       if (!msg) {
+               err = -ENOMEM;
+               goto err;
+       }
 
        nlh = nlmsg_put(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq,
                        RDMA_NL_GET_TYPE(RDMA_NL_NLDEV, RDMA_NLDEV_CMD_GET),
                        0, 0);
 
        err = fill_dev_info(msg, device);
-       if (err) {
-               nlmsg_free(msg);
-               return err;
-       }
+       if (err)
+               goto err_free;
 
        nlmsg_end(msg, nlh);
 
+       put_device(&device->dev);
        return rdma_nl_unicast(msg, NETLINK_CB(skb).portid);
+
+err_free:
+       nlmsg_free(msg);
+err:
+       put_device(&device->dev);
+       return err;
 }
 
 static int _nldev_get_dumpit(struct ib_device *device,
@@ -220,31 +227,40 @@ static int nldev_port_get_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
                return -EINVAL;
 
        index = nla_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
-       device = __ib_device_get_by_index(index);
+       device = ib_device_get_by_index(index);
        if (!device)
                return -EINVAL;
 
        port = nla_get_u32(tb[RDMA_NLDEV_ATTR_PORT_INDEX]);
-       if (!rdma_is_port_valid(device, port))
-               return -EINVAL;
+       if (!rdma_is_port_valid(device, port)) {
+               err = -EINVAL;
+               goto err;
+       }
 
        msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
-       if (!msg)
-               return -ENOMEM;
+       if (!msg) {
+               err = -ENOMEM;
+               goto err;
+       }
 
        nlh = nlmsg_put(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq,
                        RDMA_NL_GET_TYPE(RDMA_NL_NLDEV, RDMA_NLDEV_CMD_GET),
                        0, 0);
 
        err = fill_port_info(msg, device, port);
-       if (err) {
-               nlmsg_free(msg);
-               return err;
-       }
+       if (err)
+               goto err_free;
 
        nlmsg_end(msg, nlh);
+       put_device(&device->dev);
 
        return rdma_nl_unicast(msg, NETLINK_CB(skb).portid);
+
+err_free:
+       nlmsg_free(msg);
+err:
+       put_device(&device->dev);
+       return err;
 }
 
 static int nldev_port_get_dumpit(struct sk_buff *skb,
@@ -265,7 +281,7 @@ static int nldev_port_get_dumpit(struct sk_buff *skb,
                return -EINVAL;
 
        ifindex = nla_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
-       device = __ib_device_get_by_index(ifindex);
+       device = ib_device_get_by_index(ifindex);
        if (!device)
                return -EINVAL;
 
@@ -299,7 +315,9 @@ static int nldev_port_get_dumpit(struct sk_buff *skb,
                nlmsg_end(skb, nlh);
        }
 
-out:   cb->args[0] = idx;
+out:
+       put_device(&device->dev);
+       cb->args[0] = idx;
        return skb->len;
 }
 
index 313bfb9ccb71a3b42ebacbaa9b98b91daca51a19..4975f3e6596e49aaa8586ad9a13da719ef4dd6ab 100644 (file)
@@ -642,7 +642,6 @@ struct ib_mr *mlx4_ib_alloc_mr(struct ib_pd *pd,
                goto err_free_mr;
 
        mr->max_pages = max_num_sg;
-
        err = mlx4_mr_enable(dev->dev, &mr->mmr);
        if (err)
                goto err_free_pl;
@@ -653,6 +652,7 @@ struct ib_mr *mlx4_ib_alloc_mr(struct ib_pd *pd,
        return &mr->ibmr;
 
 err_free_pl:
+       mr->ibmr.device = pd->device;
        mlx4_free_priv_pages(mr);
 err_free_mr:
        (void) mlx4_mr_free(dev->dev, &mr->mmr);
index 12b7f911f0e5b9b9fce4f034bde66db4fcc26e81..8880351df179382fa6d64b4b6e698c2fdb563e94 100644 (file)
@@ -902,8 +902,8 @@ static int path_rec_start(struct net_device *dev,
        return 0;
 }
 
-static void neigh_add_path(struct sk_buff *skb, u8 *daddr,
-                          struct net_device *dev)
+static struct ipoib_neigh *neigh_add_path(struct sk_buff *skb, u8 *daddr,
+                                         struct net_device *dev)
 {
        struct ipoib_dev_priv *priv = ipoib_priv(dev);
        struct rdma_netdev *rn = netdev_priv(dev);
@@ -917,7 +917,15 @@ static void neigh_add_path(struct sk_buff *skb, u8 *daddr,
                spin_unlock_irqrestore(&priv->lock, flags);
                ++dev->stats.tx_dropped;
                dev_kfree_skb_any(skb);
-               return;
+               return NULL;
+       }
+
+       /* To avoid race condition, make sure that the
+        * neigh will be added only once.
+        */
+       if (unlikely(!list_empty(&neigh->list))) {
+               spin_unlock_irqrestore(&priv->lock, flags);
+               return neigh;
        }
 
        path = __path_find(dev, daddr + 4);
@@ -956,7 +964,7 @@ static void neigh_add_path(struct sk_buff *skb, u8 *daddr,
                        path->ah->last_send = rn->send(dev, skb, path->ah->ah,
                                                       IPOIB_QPN(daddr));
                        ipoib_neigh_put(neigh);
-                       return;
+                       return NULL;
                }
        } else {
                neigh->ah  = NULL;
@@ -973,7 +981,7 @@ static void neigh_add_path(struct sk_buff *skb, u8 *daddr,
 
        spin_unlock_irqrestore(&priv->lock, flags);
        ipoib_neigh_put(neigh);
-       return;
+       return NULL;
 
 err_path:
        ipoib_neigh_free(neigh);
@@ -983,6 +991,8 @@ err_drop:
 
        spin_unlock_irqrestore(&priv->lock, flags);
        ipoib_neigh_put(neigh);
+
+       return NULL;
 }
 
 static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev,
@@ -1091,8 +1101,9 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
        case htons(ETH_P_TIPC):
                neigh = ipoib_neigh_get(dev, phdr->hwaddr);
                if (unlikely(!neigh)) {
-                       neigh_add_path(skb, phdr->hwaddr, dev);
-                       return NETDEV_TX_OK;
+                       neigh = neigh_add_path(skb, phdr->hwaddr, dev);
+                       if (likely(!neigh))
+                               return NETDEV_TX_OK;
                }
                break;
        case htons(ETH_P_ARP):
index 93e149efc1f5fc0382b61dcfc9f84d786d8b52ca..9b3f47ae201603e8bc4e1527a0b3546a0de69878 100644 (file)
@@ -816,7 +816,10 @@ void ipoib_mcast_send(struct net_device *dev, u8 *daddr, struct sk_buff *skb)
                spin_lock_irqsave(&priv->lock, flags);
                if (!neigh) {
                        neigh = ipoib_neigh_alloc(daddr, dev);
-                       if (neigh) {
+                       /* Make sure that the neigh will be added only
+                        * once to mcast list.
+                        */
+                       if (neigh && list_empty(&neigh->list)) {
                                kref_get(&mcast->ah->ref);
                                neigh->ah       = mcast->ah;
                                list_add_tail(&neigh->list, &mcast->neigh_list);
index 8a1bd354b1cc1cb195d77be4d545a11c1bc93ac4..bfa576aa9f03c75727b9b61db67d47bfc8846797 100644 (file)
@@ -1013,8 +1013,7 @@ static int srpt_init_ch_qp(struct srpt_rdma_ch *ch, struct ib_qp *qp)
                return -ENOMEM;
 
        attr->qp_state = IB_QPS_INIT;
-       attr->qp_access_flags = IB_ACCESS_LOCAL_WRITE | IB_ACCESS_REMOTE_READ |
-           IB_ACCESS_REMOTE_WRITE;
+       attr->qp_access_flags = IB_ACCESS_LOCAL_WRITE;
        attr->port_num = ch->sport->port;
        attr->pkey_index = 0;
 
@@ -2078,7 +2077,7 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id,
                goto destroy_ib;
        }
 
-       guid = (__be16 *)&param->primary_path->sgid.global.interface_id;
+       guid = (__be16 *)&param->primary_path->dgid.global.interface_id;
        snprintf(ch->ini_guid, sizeof(ch->ini_guid), "%04x:%04x:%04x:%04x",
                 be16_to_cpu(guid[0]), be16_to_cpu(guid[1]),
                 be16_to_cpu(guid[2]), be16_to_cpu(guid[3]));