Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net

Pull networking fixes from David Miller:

 1) Fix VSOCK layer handling of context ID changes, from Reilly Grant.

 2) Now that we have a synchronize_net() in netdev_rx_handler_unregister(),
    we can't let any call sites hold locks.  Unfortunately bonding does,
    so we have to drop the rwlock there a little bit earlier, fix from
    Veaceslav Falico.

 3) MAC address setting loop exits one iteration too early in mlx4
    driver, from Yan Burman.

 4) Restore ipv6 routes properly upon ifdown/ifup of loopback, from
    Balakumaran Kannan.

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net:
  VSOCK: Handle changes to the VMCI context ID.
  net IPv6 : Fix broken IPv6 routing table after loopback down-up
  cbq: incorrect processing of high limits
  net/mlx4_en: Fix setting initial MAC address
  bonding: get netdev_rx_handler_unregister out of locks
This commit is contained in:
Linus Torvalds 2013-04-02 18:58:01 -07:00
commit da241efcd9
8 changed files with 57 additions and 31 deletions

View File

@ -1976,12 +1976,11 @@ static int __bond_release_one(struct net_device *bond_dev,
return -EINVAL; return -EINVAL;
} }
write_unlock_bh(&bond->lock);
/* unregister rx_handler early so bond_handle_frame wouldn't be called /* unregister rx_handler early so bond_handle_frame wouldn't be called
* for this slave anymore. * for this slave anymore.
*/ */
netdev_rx_handler_unregister(slave_dev); netdev_rx_handler_unregister(slave_dev);
write_unlock_bh(&bond->lock);
synchronize_net();
write_lock_bh(&bond->lock); write_lock_bh(&bond->lock);
if (!all && !bond->params.fail_over_mac) { if (!all && !bond->params.fail_over_mac) {

View File

@ -411,8 +411,8 @@ static int mlx4_en_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
static void mlx4_en_u64_to_mac(unsigned char dst_mac[ETH_ALEN + 2], u64 src_mac) static void mlx4_en_u64_to_mac(unsigned char dst_mac[ETH_ALEN + 2], u64 src_mac)
{ {
unsigned int i; int i;
for (i = ETH_ALEN - 1; i; --i) { for (i = ETH_ALEN - 1; i >= 0; --i) {
dst_mac[i] = src_mac & 0xff; dst_mac[i] = src_mac & 0xff;
src_mac >>= 8; src_mac >>= 8;
} }

View File

@ -2529,6 +2529,9 @@ static void sit_add_v4_addrs(struct inet6_dev *idev)
static void init_loopback(struct net_device *dev) static void init_loopback(struct net_device *dev)
{ {
struct inet6_dev *idev; struct inet6_dev *idev;
struct net_device *sp_dev;
struct inet6_ifaddr *sp_ifa;
struct rt6_info *sp_rt;
/* ::1 */ /* ::1 */
@ -2540,6 +2543,30 @@ static void init_loopback(struct net_device *dev)
} }
add_addr(idev, &in6addr_loopback, 128, IFA_HOST); add_addr(idev, &in6addr_loopback, 128, IFA_HOST);
/* Add routes to other interface's IPv6 addresses */
for_each_netdev(dev_net(dev), sp_dev) {
if (!strcmp(sp_dev->name, dev->name))
continue;
idev = __in6_dev_get(sp_dev);
if (!idev)
continue;
read_lock_bh(&idev->lock);
list_for_each_entry(sp_ifa, &idev->addr_list, if_list) {
if (sp_ifa->flags & (IFA_F_DADFAILED | IFA_F_TENTATIVE))
continue;
sp_rt = addrconf_dst_alloc(idev, &sp_ifa->addr, 0);
/* Failure cases are ignored */
if (!IS_ERR(sp_rt))
ip6_ins_rt(sp_rt);
}
read_unlock_bh(&idev->lock);
}
} }
static void addrconf_add_linklocal(struct inet6_dev *idev, const struct in6_addr *addr) static void addrconf_add_linklocal(struct inet6_dev *idev, const struct in6_addr *addr)

View File

@ -962,8 +962,11 @@ cbq_dequeue(struct Qdisc *sch)
cbq_update(q); cbq_update(q);
if ((incr -= incr2) < 0) if ((incr -= incr2) < 0)
incr = 0; incr = 0;
q->now += incr;
} else {
if (now > q->now)
q->now = now;
} }
q->now += incr;
q->now_rt = now; q->now_rt = now;
for (;;) { for (;;) {

View File

@ -207,7 +207,7 @@ static struct sock *__vsock_find_bound_socket(struct sockaddr_vm *addr)
struct vsock_sock *vsk; struct vsock_sock *vsk;
list_for_each_entry(vsk, vsock_bound_sockets(addr), bound_table) list_for_each_entry(vsk, vsock_bound_sockets(addr), bound_table)
if (vsock_addr_equals_addr_any(addr, &vsk->local_addr)) if (addr->svm_port == vsk->local_addr.svm_port)
return sk_vsock(vsk); return sk_vsock(vsk);
return NULL; return NULL;
@ -220,8 +220,8 @@ static struct sock *__vsock_find_connected_socket(struct sockaddr_vm *src,
list_for_each_entry(vsk, vsock_connected_sockets(src, dst), list_for_each_entry(vsk, vsock_connected_sockets(src, dst),
connected_table) { connected_table) {
if (vsock_addr_equals_addr(src, &vsk->remote_addr) if (vsock_addr_equals_addr(src, &vsk->remote_addr) &&
&& vsock_addr_equals_addr(dst, &vsk->local_addr)) { dst->svm_port == vsk->local_addr.svm_port) {
return sk_vsock(vsk); return sk_vsock(vsk);
} }
} }

View File

@ -464,19 +464,16 @@ static struct sock *vmci_transport_get_pending(
struct vsock_sock *vlistener; struct vsock_sock *vlistener;
struct vsock_sock *vpending; struct vsock_sock *vpending;
struct sock *pending; struct sock *pending;
struct sockaddr_vm src;
vsock_addr_init(&src, pkt->dg.src.context, pkt->src_port);
vlistener = vsock_sk(listener); vlistener = vsock_sk(listener);
list_for_each_entry(vpending, &vlistener->pending_links, list_for_each_entry(vpending, &vlistener->pending_links,
pending_links) { pending_links) {
struct sockaddr_vm src;
struct sockaddr_vm dst;
vsock_addr_init(&src, pkt->dg.src.context, pkt->src_port);
vsock_addr_init(&dst, pkt->dg.dst.context, pkt->dst_port);
if (vsock_addr_equals_addr(&src, &vpending->remote_addr) && if (vsock_addr_equals_addr(&src, &vpending->remote_addr) &&
vsock_addr_equals_addr(&dst, &vpending->local_addr)) { pkt->dst_port == vpending->local_addr.svm_port) {
pending = sk_vsock(vpending); pending = sk_vsock(vpending);
sock_hold(pending); sock_hold(pending);
goto found; goto found;
@ -739,10 +736,15 @@ static int vmci_transport_recv_stream_cb(void *data, struct vmci_datagram *dg)
*/ */
bh_lock_sock(sk); bh_lock_sock(sk);
if (!sock_owned_by_user(sk) && sk->sk_state == SS_CONNECTED) if (!sock_owned_by_user(sk)) {
vmci_trans(vsk)->notify_ops->handle_notify_pkt( /* The local context ID may be out of date, update it. */
sk, pkt, true, &dst, &src, vsk->local_addr.svm_cid = dst.svm_cid;
&bh_process_pkt);
if (sk->sk_state == SS_CONNECTED)
vmci_trans(vsk)->notify_ops->handle_notify_pkt(
sk, pkt, true, &dst, &src,
&bh_process_pkt);
}
bh_unlock_sock(sk); bh_unlock_sock(sk);
@ -902,6 +904,9 @@ static void vmci_transport_recv_pkt_work(struct work_struct *work)
lock_sock(sk); lock_sock(sk);
/* The local context ID may be out of date. */
vsock_sk(sk)->local_addr.svm_cid = pkt->dg.dst.context;
switch (sk->sk_state) { switch (sk->sk_state) {
case SS_LISTEN: case SS_LISTEN:
vmci_transport_recv_listen(sk, pkt); vmci_transport_recv_listen(sk, pkt);
@ -958,6 +963,10 @@ static int vmci_transport_recv_listen(struct sock *sk,
pending = vmci_transport_get_pending(sk, pkt); pending = vmci_transport_get_pending(sk, pkt);
if (pending) { if (pending) {
lock_sock(pending); lock_sock(pending);
/* The local context ID may be out of date. */
vsock_sk(pending)->local_addr.svm_cid = pkt->dg.dst.context;
switch (pending->sk_state) { switch (pending->sk_state) {
case SS_CONNECTING: case SS_CONNECTING:
err = vmci_transport_recv_connecting_server(sk, err = vmci_transport_recv_connecting_server(sk,

View File

@ -64,16 +64,6 @@ bool vsock_addr_equals_addr(const struct sockaddr_vm *addr,
} }
EXPORT_SYMBOL_GPL(vsock_addr_equals_addr); EXPORT_SYMBOL_GPL(vsock_addr_equals_addr);
bool vsock_addr_equals_addr_any(const struct sockaddr_vm *addr,
const struct sockaddr_vm *other)
{
return (addr->svm_cid == VMADDR_CID_ANY ||
other->svm_cid == VMADDR_CID_ANY ||
addr->svm_cid == other->svm_cid) &&
addr->svm_port == other->svm_port;
}
EXPORT_SYMBOL_GPL(vsock_addr_equals_addr_any);
int vsock_addr_cast(const struct sockaddr *addr, int vsock_addr_cast(const struct sockaddr *addr,
size_t len, struct sockaddr_vm **out_addr) size_t len, struct sockaddr_vm **out_addr)
{ {

View File

@ -24,8 +24,6 @@ bool vsock_addr_bound(const struct sockaddr_vm *addr);
void vsock_addr_unbind(struct sockaddr_vm *addr); void vsock_addr_unbind(struct sockaddr_vm *addr);
bool vsock_addr_equals_addr(const struct sockaddr_vm *addr, bool vsock_addr_equals_addr(const struct sockaddr_vm *addr,
const struct sockaddr_vm *other); const struct sockaddr_vm *other);
bool vsock_addr_equals_addr_any(const struct sockaddr_vm *addr,
const struct sockaddr_vm *other);
int vsock_addr_cast(const struct sockaddr *addr, size_t len, int vsock_addr_cast(const struct sockaddr *addr, size_t len,
struct sockaddr_vm **out_addr); struct sockaddr_vm **out_addr);