Commit 44596f86 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma

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
parents d32da584 a1ffa467
...@@ -314,7 +314,7 @@ static inline int ib_mad_enforce_security(struct ib_mad_agent_private *map, ...@@ -314,7 +314,7 @@ static inline int ib_mad_enforce_security(struct ib_mad_agent_private *map,
} }
#endif #endif
struct ib_device *__ib_device_get_by_index(u32 ifindex); struct ib_device *ib_device_get_by_index(u32 ifindex);
/* RDMA device netlink */ /* RDMA device netlink */
void nldev_init(void); void nldev_init(void);
void nldev_exit(void); void nldev_exit(void);
......
...@@ -134,7 +134,7 @@ static int ib_device_check_mandatory(struct ib_device *device) ...@@ -134,7 +134,7 @@ static int ib_device_check_mandatory(struct ib_device *device)
return 0; 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; struct ib_device *device;
...@@ -145,6 +145,22 @@ struct ib_device *__ib_device_get_by_index(u32 index) ...@@ -145,6 +145,22 @@ struct ib_device *__ib_device_get_by_index(u32 index)
return NULL; 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) static struct ib_device *__ib_device_get_by_name(const char *name)
{ {
struct ib_device *device; struct ib_device *device;
......
...@@ -142,27 +142,34 @@ static int nldev_get_doit(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -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]); 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) if (!device)
return -EINVAL; return -EINVAL;
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
if (!msg) if (!msg) {
return -ENOMEM; err = -ENOMEM;
goto err;
}
nlh = nlmsg_put(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq, nlh = nlmsg_put(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq,
RDMA_NL_GET_TYPE(RDMA_NL_NLDEV, RDMA_NLDEV_CMD_GET), RDMA_NL_GET_TYPE(RDMA_NL_NLDEV, RDMA_NLDEV_CMD_GET),
0, 0); 0, 0);
err = fill_dev_info(msg, device); err = fill_dev_info(msg, device);
if (err) { if (err)
nlmsg_free(msg); goto err_free;
return err;
}
nlmsg_end(msg, nlh); nlmsg_end(msg, nlh);
put_device(&device->dev);
return rdma_nl_unicast(msg, NETLINK_CB(skb).portid); 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, 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, ...@@ -220,31 +227,40 @@ static int nldev_port_get_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
return -EINVAL; return -EINVAL;
index = nla_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]); 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) if (!device)
return -EINVAL; return -EINVAL;
port = nla_get_u32(tb[RDMA_NLDEV_ATTR_PORT_INDEX]); port = nla_get_u32(tb[RDMA_NLDEV_ATTR_PORT_INDEX]);
if (!rdma_is_port_valid(device, port)) if (!rdma_is_port_valid(device, port)) {
return -EINVAL; err = -EINVAL;
goto err;
}
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
if (!msg) if (!msg) {
return -ENOMEM; err = -ENOMEM;
goto err;
}
nlh = nlmsg_put(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq, nlh = nlmsg_put(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq,
RDMA_NL_GET_TYPE(RDMA_NL_NLDEV, RDMA_NLDEV_CMD_GET), RDMA_NL_GET_TYPE(RDMA_NL_NLDEV, RDMA_NLDEV_CMD_GET),
0, 0); 0, 0);
err = fill_port_info(msg, device, port); err = fill_port_info(msg, device, port);
if (err) { if (err)
nlmsg_free(msg); goto err_free;
return err;
}
nlmsg_end(msg, nlh); nlmsg_end(msg, nlh);
put_device(&device->dev);
return rdma_nl_unicast(msg, NETLINK_CB(skb).portid); 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, static int nldev_port_get_dumpit(struct sk_buff *skb,
...@@ -265,7 +281,7 @@ 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; return -EINVAL;
ifindex = nla_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]); 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) if (!device)
return -EINVAL; return -EINVAL;
...@@ -299,7 +315,9 @@ static int nldev_port_get_dumpit(struct sk_buff *skb, ...@@ -299,7 +315,9 @@ static int nldev_port_get_dumpit(struct sk_buff *skb,
nlmsg_end(skb, nlh); nlmsg_end(skb, nlh);
} }
out: cb->args[0] = idx; out:
put_device(&device->dev);
cb->args[0] = idx;
return skb->len; return skb->len;
} }
......
...@@ -642,7 +642,6 @@ struct ib_mr *mlx4_ib_alloc_mr(struct ib_pd *pd, ...@@ -642,7 +642,6 @@ struct ib_mr *mlx4_ib_alloc_mr(struct ib_pd *pd,
goto err_free_mr; goto err_free_mr;
mr->max_pages = max_num_sg; mr->max_pages = max_num_sg;
err = mlx4_mr_enable(dev->dev, &mr->mmr); err = mlx4_mr_enable(dev->dev, &mr->mmr);
if (err) if (err)
goto err_free_pl; goto err_free_pl;
...@@ -653,6 +652,7 @@ struct ib_mr *mlx4_ib_alloc_mr(struct ib_pd *pd, ...@@ -653,6 +652,7 @@ struct ib_mr *mlx4_ib_alloc_mr(struct ib_pd *pd,
return &mr->ibmr; return &mr->ibmr;
err_free_pl: err_free_pl:
mr->ibmr.device = pd->device;
mlx4_free_priv_pages(mr); mlx4_free_priv_pages(mr);
err_free_mr: err_free_mr:
(void) mlx4_mr_free(dev->dev, &mr->mmr); (void) mlx4_mr_free(dev->dev, &mr->mmr);
......
...@@ -902,7 +902,7 @@ static int path_rec_start(struct net_device *dev, ...@@ -902,7 +902,7 @@ static int path_rec_start(struct net_device *dev,
return 0; return 0;
} }
static void neigh_add_path(struct sk_buff *skb, u8 *daddr, static struct ipoib_neigh *neigh_add_path(struct sk_buff *skb, u8 *daddr,
struct net_device *dev) struct net_device *dev)
{ {
struct ipoib_dev_priv *priv = ipoib_priv(dev); struct ipoib_dev_priv *priv = ipoib_priv(dev);
...@@ -917,7 +917,15 @@ static void neigh_add_path(struct sk_buff *skb, u8 *daddr, ...@@ -917,7 +917,15 @@ static void neigh_add_path(struct sk_buff *skb, u8 *daddr,
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irqrestore(&priv->lock, flags);
++dev->stats.tx_dropped; ++dev->stats.tx_dropped;
dev_kfree_skb_any(skb); 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); path = __path_find(dev, daddr + 4);
...@@ -956,7 +964,7 @@ static void neigh_add_path(struct sk_buff *skb, u8 *daddr, ...@@ -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, path->ah->last_send = rn->send(dev, skb, path->ah->ah,
IPOIB_QPN(daddr)); IPOIB_QPN(daddr));
ipoib_neigh_put(neigh); ipoib_neigh_put(neigh);
return; return NULL;
} }
} else { } else {
neigh->ah = NULL; neigh->ah = NULL;
...@@ -973,7 +981,7 @@ static void neigh_add_path(struct sk_buff *skb, u8 *daddr, ...@@ -973,7 +981,7 @@ static void neigh_add_path(struct sk_buff *skb, u8 *daddr,
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irqrestore(&priv->lock, flags);
ipoib_neigh_put(neigh); ipoib_neigh_put(neigh);
return; return NULL;
err_path: err_path:
ipoib_neigh_free(neigh); ipoib_neigh_free(neigh);
...@@ -983,6 +991,8 @@ static void neigh_add_path(struct sk_buff *skb, u8 *daddr, ...@@ -983,6 +991,8 @@ static void neigh_add_path(struct sk_buff *skb, u8 *daddr,
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irqrestore(&priv->lock, flags);
ipoib_neigh_put(neigh); ipoib_neigh_put(neigh);
return NULL;
} }
static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev, static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev,
...@@ -1091,7 +1101,8 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -1091,7 +1101,8 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
case htons(ETH_P_TIPC): case htons(ETH_P_TIPC):
neigh = ipoib_neigh_get(dev, phdr->hwaddr); neigh = ipoib_neigh_get(dev, phdr->hwaddr);
if (unlikely(!neigh)) { if (unlikely(!neigh)) {
neigh_add_path(skb, phdr->hwaddr, dev); neigh = neigh_add_path(skb, phdr->hwaddr, dev);
if (likely(!neigh))
return NETDEV_TX_OK; return NETDEV_TX_OK;
} }
break; break;
......
...@@ -816,7 +816,10 @@ void ipoib_mcast_send(struct net_device *dev, u8 *daddr, struct sk_buff *skb) ...@@ -816,7 +816,10 @@ void ipoib_mcast_send(struct net_device *dev, u8 *daddr, struct sk_buff *skb)
spin_lock_irqsave(&priv->lock, flags); spin_lock_irqsave(&priv->lock, flags);
if (!neigh) { if (!neigh) {
neigh = ipoib_neigh_alloc(daddr, dev); 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); kref_get(&mcast->ah->ref);
neigh->ah = mcast->ah; neigh->ah = mcast->ah;
list_add_tail(&neigh->list, &mcast->neigh_list); list_add_tail(&neigh->list, &mcast->neigh_list);
......
...@@ -1013,8 +1013,7 @@ static int srpt_init_ch_qp(struct srpt_rdma_ch *ch, struct ib_qp *qp) ...@@ -1013,8 +1013,7 @@ static int srpt_init_ch_qp(struct srpt_rdma_ch *ch, struct ib_qp *qp)
return -ENOMEM; return -ENOMEM;
attr->qp_state = IB_QPS_INIT; attr->qp_state = IB_QPS_INIT;
attr->qp_access_flags = IB_ACCESS_LOCAL_WRITE | IB_ACCESS_REMOTE_READ | attr->qp_access_flags = IB_ACCESS_LOCAL_WRITE;
IB_ACCESS_REMOTE_WRITE;
attr->port_num = ch->sport->port; attr->port_num = ch->sport->port;
attr->pkey_index = 0; attr->pkey_index = 0;
...@@ -2078,7 +2077,7 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id, ...@@ -2078,7 +2077,7 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id,
goto destroy_ib; 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", 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[0]), be16_to_cpu(guid[1]),
be16_to_cpu(guid[2]), be16_to_cpu(guid[3])); be16_to_cpu(guid[2]), be16_to_cpu(guid[3]));
......
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