diff -NurpP --minimal linux-3.7.1-vs2.3.5.3/include/linux/vs_inet.h linux-3.7.1-vs2.3.5.4/include/linux/vs_inet.h --- linux-3.7.1-vs2.3.5.3/include/linux/vs_inet.h 2012-12-18 15:13:16.000000000 +0000 +++ linux-3.7.1-vs2.3.5.4/include/linux/vs_inet.h 2013-01-04 22:27:45.000000000 +0000 @@ -59,6 +59,7 @@ static inline int v4_addr_in_nx_info(struct nx_info *nxi, __be32 addr, uint16_t tmask) { struct nx_addr_v4 *nxa; + unsigned long irqflags; int ret = 1; if (!nxi) @@ -83,13 +84,13 @@ int v4_addr_in_nx_info(struct nx_info *n ret = 5; /* check for v4 addresses */ - spin_lock(&nxi->addr_lock); + spin_lock_irqsave(&nxi->addr_lock, irqflags); for (nxa = &nxi->v4; nxa; nxa = nxa->next) if (v4_addr_match(nxa, addr, tmask)) goto out_unlock; ret = 0; out_unlock: - spin_unlock(&nxi->addr_lock); + spin_unlock_irqrestore(&nxi->addr_lock, irqflags); out: vxdprintk(VXD_CBIT(net, 0), "v4_addr_in_nx_info(%p[#%u]," NIPQUAD_FMT ",%04x) = %d", @@ -108,15 +109,16 @@ static inline int v4_nx_addr_in_nx_info(struct nx_info *nxi, struct nx_addr_v4 *nxa, uint16_t mask) { struct nx_addr_v4 *ptr; + unsigned long irqflags; int ret = 1; - spin_lock(&nxi->addr_lock); + spin_lock_irqsave(&nxi->addr_lock, irqflags); for (ptr = &nxi->v4; ptr; ptr = ptr->next) if (v4_nx_addr_match(ptr, nxa, mask)) goto out_unlock; ret = 0; out_unlock: - spin_unlock(&nxi->addr_lock); + spin_unlock_irqrestore(&nxi->addr_lock, irqflags); return ret; } diff -NurpP --minimal linux-3.7.1-vs2.3.5.3/include/linux/vs_inet6.h linux-3.7.1-vs2.3.5.4/include/linux/vs_inet6.h --- linux-3.7.1-vs2.3.5.3/include/linux/vs_inet6.h 2012-12-18 15:13:16.000000000 +0000 +++ linux-3.7.1-vs2.3.5.4/include/linux/vs_inet6.h 2013-01-04 22:28:58.000000000 +0000 @@ -41,18 +41,19 @@ int v6_addr_in_nx_info(struct nx_info *n const struct in6_addr *addr, uint16_t mask) { struct nx_addr_v6 *nxa; + unsigned long irqflags; int ret = 1; if (!nxi) goto out; - spin_lock(&nxi->addr_lock); + spin_lock_irqsave(&nxi->addr_lock, irqflags); for (nxa = &nxi->v6; nxa; nxa = nxa->next) if (v6_addr_match(nxa, addr, mask)) goto out_unlock; ret = 0; out_unlock: - spin_unlock(&nxi->addr_lock); + spin_unlock_irqrestore(&nxi->addr_lock, irqflags); out: vxdprintk(VXD_CBIT(net, 0), "v6_addr_in_nx_info(%p[#%u],%pI6,%04x) = %d", @@ -71,15 +72,16 @@ static inline int v6_nx_addr_in_nx_info(struct nx_info *nxi, struct nx_addr_v6 *nxa, uint16_t mask) { struct nx_addr_v6 *ptr; + unsigned long irqflags; int ret = 1; - spin_lock(&nxi->addr_lock); + spin_lock_irqsave(&nxi->addr_lock, irqflags); for (ptr = &nxi->v6; ptr; ptr = ptr->next) if (v6_nx_addr_match(ptr, nxa, mask)) goto out_unlock; ret = 0; out_unlock: - spin_unlock(&nxi->addr_lock); + spin_unlock_irqrestore(&nxi->addr_lock, irqflags); return ret; } diff -NurpP --minimal linux-3.7.1-vs2.3.5.3/kernel/vserver/inet.c linux-3.7.1-vs2.3.5.4/kernel/vserver/inet.c --- linux-3.7.1-vs2.3.5.3/kernel/vserver/inet.c 2012-12-18 15:13:16.000000000 +0000 +++ linux-3.7.1-vs2.3.5.4/kernel/vserver/inet.c 2013-01-04 23:06:14.000000000 +0000 @@ -17,13 +17,18 @@ int nx_v4_addr_conflict(struct nx_info * ret = 1; else { struct nx_addr_v4 *ptr; + unsigned long irqflags; + spin_lock_irqsave(&nxi1->addr_lock, irqflags); + spin_lock(&nxi2->addr_lock); for (ptr = &nxi1->v4; ptr; ptr = ptr->next) { if (v4_nx_addr_in_nx_info(nxi2, ptr, -1)) { ret = 1; break; } } + spin_unlock(&nxi2->addr_lock); + spin_unlock_irqrestore(&nxi1->addr_lock, irqflags); } vxdprintk(VXD_CBIT(net, 2), @@ -44,13 +49,18 @@ int nx_v6_addr_conflict(struct nx_info * ret = 1; else { struct nx_addr_v6 *ptr; + unsigned long irqflags; + spin_lock_irqsave(&nxi1->addr_lock, irqflags); + spin_lock(&nxi2->addr_lock); for (ptr = &nxi1->v6; ptr; ptr = ptr->next) { if (v6_nx_addr_in_nx_info(nxi2, ptr, -1)) { ret = 1; break; } } + spin_unlock(&nxi2->addr_lock); + spin_unlock_irqrestore(&nxi1->addr_lock, irqflags); } vxdprintk(VXD_CBIT(net, 2), @@ -161,6 +171,7 @@ struct rtable *ip_v4_find_src(struct net if (fl4->saddr == INADDR_ANY) { struct nx_addr_v4 *ptr; + unsigned long irqflags; __be32 found = 0; rt = __ip_route_output_key(net, fl4); @@ -174,6 +185,7 @@ struct rtable *ip_v4_find_src(struct net goto found; } + spin_lock_irqsave(&nxi->addr_lock, irqflags); for (ptr = &nxi->v4; ptr; ptr = ptr->next) { __be32 primary = ptr->ip[0].s_addr; __be32 mask = ptr->mask.s_addr; @@ -195,12 +207,14 @@ struct rtable *ip_v4_find_src(struct net found = fl4->saddr; ip_rt_put(rt); if (found == primary) - goto found; + goto found_unlock; } } /* still no source ip? */ found = ipv4_is_loopback(fl4->daddr) ? IPI_LOOPBACK : nxi->v4.ip[0].s_addr; + found_unlock: + spin_unlock_irqrestore(&nxi->addr_lock, irqflags); found: /* assign src ip to flow */ fl4->saddr = found; diff -NurpP --minimal linux-3.7.1-vs2.3.5.3/kernel/vserver/network.c linux-3.7.1-vs2.3.5.4/kernel/vserver/network.c --- linux-3.7.1-vs2.3.5.3/kernel/vserver/network.c 2012-12-18 15:13:16.000000000 +0000 +++ linux-3.7.1-vs2.3.5.4/kernel/vserver/network.c 2013-01-04 22:38:16.000000000 +0000 @@ -620,12 +620,13 @@ int do_add_v4_addr(struct nx_info *nxi, { struct nx_addr_v4 *nxa = NULL; struct nx_addr_v4 *new = __alloc_nx_addr_v4(); + unsigned long irqflags; int ret = -EEXIST; if (IS_ERR(new)) return PTR_ERR(new); - spin_lock(&nxi->addr_lock); + spin_lock_irqsave(&nxi->addr_lock, irqflags); if (__find_v4_addr(nxi, ip, ip2, mask, type, flags, &nxa)) goto out_unlock; @@ -645,7 +646,7 @@ int do_add_v4_addr(struct nx_info *nxi, nxa->flags = flags; ret = 0; out_unlock: - spin_unlock(&nxi->addr_lock); + spin_unlock_irqrestore(&nxi->addr_lock, irqflags); if (new) __dealloc_nx_addr_v4(new); return ret; @@ -656,9 +657,10 @@ int do_remove_v4_addr(struct nx_info *nx { struct nx_addr_v4 *nxa = NULL; struct nx_addr_v4 *old = NULL; + unsigned long irqflags; int ret = 0; - spin_lock(&nxi->addr_lock); + spin_lock_irqsave(&nxi->addr_lock, irqflags); switch (type) { case NXA_TYPE_ADDR: old = __find_v4_addr(nxi, ip, ip2, mask, type, flags, &nxa); @@ -690,7 +692,7 @@ int do_remove_v4_addr(struct nx_info *nx default: ret = -EINVAL; } - spin_unlock(&nxi->addr_lock); + spin_unlock_irqrestore(&nxi->addr_lock, irqflags); __dealloc_nx_addr_v4_all(old); return ret; } @@ -863,12 +865,13 @@ int do_add_v6_addr(struct nx_info *nxi, { struct nx_addr_v6 *nxa = NULL; struct nx_addr_v6 *new = __alloc_nx_addr_v6(); + unsigned long irqflags; int ret = -EEXIST; if (IS_ERR(new)) return PTR_ERR(new); - spin_lock(&nxi->addr_lock); + spin_lock_irqsave(&nxi->addr_lock, irqflags); if (__find_v6_addr(nxi, ip, mask, prefix, type, flags, &nxa)) goto out_unlock; @@ -885,7 +888,7 @@ int do_add_v6_addr(struct nx_info *nxi, nxa->flags = flags; ret = 0; out_unlock: - spin_unlock(&nxi->addr_lock); + spin_unlock_irqrestore(&nxi->addr_lock, irqflags); if (new) __dealloc_nx_addr_v6(new); return ret; @@ -897,9 +900,10 @@ int do_remove_v6_addr(struct nx_info *nx { struct nx_addr_v6 *nxa = NULL; struct nx_addr_v6 *old = NULL; + unsigned long irqflags; int ret = 0; - spin_lock(&nxi->addr_lock); + spin_lock_irqsave(&nxi->addr_lock, irqflags); switch (type) { case NXA_TYPE_ADDR: old = __find_v6_addr(nxi, ip, mask, prefix, type, flags, &nxa); @@ -931,7 +935,7 @@ int do_remove_v6_addr(struct nx_info *nx default: ret = -EINVAL; } - spin_unlock(&nxi->addr_lock); + spin_unlock_irqrestore(&nxi->addr_lock, irqflags); __dealloc_nx_addr_v6_all(old); return ret; }