Commit 8fb8e9e4 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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

Pull rdma fix from Doug Ledford:
 "Much calmer week this week.  Just one patch queued up:

  The way the siw driver was locking around the traversal of the list of
  ipv6 addresses on a device was causing a scheduling while atomic
  issue. Bernard straightened it out by using the rtnl_lock"

* tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma:
  RDMA/siw: Fix IPv6 addr_list locking
parents fbcb0b4f 531a64e4
...@@ -1962,6 +1962,10 @@ int siw_create_listen(struct iw_cm_id *id, int backlog) ...@@ -1962,6 +1962,10 @@ int siw_create_listen(struct iw_cm_id *id, int backlog)
struct sockaddr_in s_laddr, *s_raddr; struct sockaddr_in s_laddr, *s_raddr;
const struct in_ifaddr *ifa; const struct in_ifaddr *ifa;
if (!in_dev) {
rv = -ENODEV;
goto out;
}
memcpy(&s_laddr, &id->local_addr, sizeof(s_laddr)); memcpy(&s_laddr, &id->local_addr, sizeof(s_laddr));
s_raddr = (struct sockaddr_in *)&id->remote_addr; s_raddr = (struct sockaddr_in *)&id->remote_addr;
...@@ -1991,22 +1995,27 @@ int siw_create_listen(struct iw_cm_id *id, int backlog) ...@@ -1991,22 +1995,27 @@ int siw_create_listen(struct iw_cm_id *id, int backlog)
struct sockaddr_in6 *s_laddr = &to_sockaddr_in6(id->local_addr), struct sockaddr_in6 *s_laddr = &to_sockaddr_in6(id->local_addr),
*s_raddr = &to_sockaddr_in6(id->remote_addr); *s_raddr = &to_sockaddr_in6(id->remote_addr);
if (!in6_dev) {
rv = -ENODEV;
goto out;
}
siw_dbg(id->device, siw_dbg(id->device,
"laddr %pI6:%d, raddr %pI6:%d\n", "laddr %pI6:%d, raddr %pI6:%d\n",
&s_laddr->sin6_addr, ntohs(s_laddr->sin6_port), &s_laddr->sin6_addr, ntohs(s_laddr->sin6_port),
&s_raddr->sin6_addr, ntohs(s_raddr->sin6_port)); &s_raddr->sin6_addr, ntohs(s_raddr->sin6_port));
read_lock_bh(&in6_dev->lock); rtnl_lock();
list_for_each_entry(ifp, &in6_dev->addr_list, if_list) { list_for_each_entry(ifp, &in6_dev->addr_list, if_list) {
struct sockaddr_in6 bind_addr; if (ifp->flags & (IFA_F_TENTATIVE | IFA_F_DEPRECATED))
continue;
if (ipv6_addr_any(&s_laddr->sin6_addr) || if (ipv6_addr_any(&s_laddr->sin6_addr) ||
ipv6_addr_equal(&s_laddr->sin6_addr, &ifp->addr)) { ipv6_addr_equal(&s_laddr->sin6_addr, &ifp->addr)) {
bind_addr.sin6_family = AF_INET6; struct sockaddr_in6 bind_addr = {
bind_addr.sin6_port = s_laddr->sin6_port; .sin6_family = AF_INET6,
bind_addr.sin6_flowinfo = 0; .sin6_port = s_laddr->sin6_port,
bind_addr.sin6_addr = ifp->addr; .sin6_flowinfo = 0,
bind_addr.sin6_scope_id = dev->ifindex; .sin6_addr = ifp->addr,
.sin6_scope_id = dev->ifindex };
rv = siw_listen_address(id, backlog, rv = siw_listen_address(id, backlog,
(struct sockaddr *)&bind_addr, (struct sockaddr *)&bind_addr,
...@@ -2015,12 +2024,12 @@ int siw_create_listen(struct iw_cm_id *id, int backlog) ...@@ -2015,12 +2024,12 @@ int siw_create_listen(struct iw_cm_id *id, int backlog)
listeners++; listeners++;
} }
} }
read_unlock_bh(&in6_dev->lock); rtnl_unlock();
in6_dev_put(in6_dev); in6_dev_put(in6_dev);
} else { } else {
return -EAFNOSUPPORT; rv = -EAFNOSUPPORT;
} }
out:
if (listeners) if (listeners)
rv = 0; rv = 0;
else if (!rv) else if (!rv)
......
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