diff options
author | Dave Airlie <airlied@redhat.com> | 2015-08-24 02:36:42 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2015-08-24 02:36:42 -0400 |
commit | 3732ce72b45a2a145803558758821bf198751276 (patch) | |
tree | 75047ed1f43cfd56231535c401924dbb27c4d0f0 /net | |
parent | e829d7ef9f17d7b84d4c3d110ecd4b7b2bcba865 (diff) | |
parent | c13dcf9f2d6f5f06ef1bf79ec456df614c5e058b (diff) |
Merge tag 'v4.2-rc8' into drm-next
Linux 4.2-rc8
Backmerge required for Intel so they can fix their -next tree up properly.
Diffstat (limited to 'net')
-rw-r--r-- | net/9p/client.c | 2 | ||||
-rw-r--r-- | net/batman-adv/translation-table.c | 5 | ||||
-rw-r--r-- | net/bridge/br_multicast.c | 4 | ||||
-rw-r--r-- | net/core/skbuff.c | 39 | ||||
-rw-r--r-- | net/ipv4/fib_trie.c | 2 | ||||
-rw-r--r-- | net/ipv4/igmp.c | 33 | ||||
-rw-r--r-- | net/ipv4/inet_connection_sock.c | 2 | ||||
-rw-r--r-- | net/ipv4/sysctl_net_ipv4.c | 10 | ||||
-rw-r--r-- | net/ipv6/ip6_fib.c | 2 | ||||
-rw-r--r-- | net/ipv6/mcast_snoop.c | 33 | ||||
-rw-r--r-- | net/ipv6/route.c | 79 | ||||
-rw-r--r-- | net/mac80211/rc80211_minstrel.c | 11 |
12 files changed, 132 insertions, 90 deletions
diff --git a/net/9p/client.c b/net/9p/client.c index 498454b3c06c..ea79ee9a7348 100644 --- a/net/9p/client.c +++ b/net/9p/client.c | |||
@@ -1541,6 +1541,7 @@ p9_client_read(struct p9_fid *fid, u64 offset, struct iov_iter *to, int *err) | |||
1541 | struct p9_client *clnt = fid->clnt; | 1541 | struct p9_client *clnt = fid->clnt; |
1542 | struct p9_req_t *req; | 1542 | struct p9_req_t *req; |
1543 | int total = 0; | 1543 | int total = 0; |
1544 | *err = 0; | ||
1544 | 1545 | ||
1545 | p9_debug(P9_DEBUG_9P, ">>> TREAD fid %d offset %llu %d\n", | 1546 | p9_debug(P9_DEBUG_9P, ">>> TREAD fid %d offset %llu %d\n", |
1546 | fid->fid, (unsigned long long) offset, (int)iov_iter_count(to)); | 1547 | fid->fid, (unsigned long long) offset, (int)iov_iter_count(to)); |
@@ -1620,6 +1621,7 @@ p9_client_write(struct p9_fid *fid, u64 offset, struct iov_iter *from, int *err) | |||
1620 | struct p9_client *clnt = fid->clnt; | 1621 | struct p9_client *clnt = fid->clnt; |
1621 | struct p9_req_t *req; | 1622 | struct p9_req_t *req; |
1622 | int total = 0; | 1623 | int total = 0; |
1624 | *err = 0; | ||
1623 | 1625 | ||
1624 | p9_debug(P9_DEBUG_9P, ">>> TWRITE fid %d offset %llu count %zd\n", | 1626 | p9_debug(P9_DEBUG_9P, ">>> TWRITE fid %d offset %llu count %zd\n", |
1625 | fid->fid, (unsigned long long) offset, | 1627 | fid->fid, (unsigned long long) offset, |
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index 5e953297d3b2..5809b39c1922 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c | |||
@@ -595,8 +595,11 @@ bool batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr, | |||
595 | /* increase the refcounter of the related vlan */ | 595 | /* increase the refcounter of the related vlan */ |
596 | vlan = batadv_softif_vlan_get(bat_priv, vid); | 596 | vlan = batadv_softif_vlan_get(bat_priv, vid); |
597 | if (WARN(!vlan, "adding TT local entry %pM to non-existent VLAN %d", | 597 | if (WARN(!vlan, "adding TT local entry %pM to non-existent VLAN %d", |
598 | addr, BATADV_PRINT_VID(vid))) | 598 | addr, BATADV_PRINT_VID(vid))) { |
599 | kfree(tt_local); | ||
600 | tt_local = NULL; | ||
599 | goto out; | 601 | goto out; |
602 | } | ||
600 | 603 | ||
601 | batadv_dbg(BATADV_DBG_TT, bat_priv, | 604 | batadv_dbg(BATADV_DBG_TT, bat_priv, |
602 | "Creating new local tt entry: %pM (vid: %d, ttvn: %d)\n", | 605 | "Creating new local tt entry: %pM (vid: %d, ttvn: %d)\n", |
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 0b39dcc65b94..1285eaf5dc22 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c | |||
@@ -1591,7 +1591,7 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br, | |||
1591 | break; | 1591 | break; |
1592 | } | 1592 | } |
1593 | 1593 | ||
1594 | if (skb_trimmed) | 1594 | if (skb_trimmed && skb_trimmed != skb) |
1595 | kfree_skb(skb_trimmed); | 1595 | kfree_skb(skb_trimmed); |
1596 | 1596 | ||
1597 | return err; | 1597 | return err; |
@@ -1636,7 +1636,7 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br, | |||
1636 | break; | 1636 | break; |
1637 | } | 1637 | } |
1638 | 1638 | ||
1639 | if (skb_trimmed) | 1639 | if (skb_trimmed && skb_trimmed != skb) |
1640 | kfree_skb(skb_trimmed); | 1640 | kfree_skb(skb_trimmed); |
1641 | 1641 | ||
1642 | return err; | 1642 | return err; |
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index b6a19ca0f99e..7b84330e5d30 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -340,7 +340,7 @@ struct sk_buff *build_skb(void *data, unsigned int frag_size) | |||
340 | 340 | ||
341 | if (skb && frag_size) { | 341 | if (skb && frag_size) { |
342 | skb->head_frag = 1; | 342 | skb->head_frag = 1; |
343 | if (virt_to_head_page(data)->pfmemalloc) | 343 | if (page_is_pfmemalloc(virt_to_head_page(data))) |
344 | skb->pfmemalloc = 1; | 344 | skb->pfmemalloc = 1; |
345 | } | 345 | } |
346 | return skb; | 346 | return skb; |
@@ -4022,8 +4022,8 @@ EXPORT_SYMBOL(skb_checksum_setup); | |||
4022 | * Otherwise returns the provided skb. Returns NULL in error cases | 4022 | * Otherwise returns the provided skb. Returns NULL in error cases |
4023 | * (e.g. transport_len exceeds skb length or out-of-memory). | 4023 | * (e.g. transport_len exceeds skb length or out-of-memory). |
4024 | * | 4024 | * |
4025 | * Caller needs to set the skb transport header and release the returned skb. | 4025 | * Caller needs to set the skb transport header and free any returned skb if it |
4026 | * Provided skb is consumed. | 4026 | * differs from the provided skb. |
4027 | */ | 4027 | */ |
4028 | static struct sk_buff *skb_checksum_maybe_trim(struct sk_buff *skb, | 4028 | static struct sk_buff *skb_checksum_maybe_trim(struct sk_buff *skb, |
4029 | unsigned int transport_len) | 4029 | unsigned int transport_len) |
@@ -4032,16 +4032,12 @@ static struct sk_buff *skb_checksum_maybe_trim(struct sk_buff *skb, | |||
4032 | unsigned int len = skb_transport_offset(skb) + transport_len; | 4032 | unsigned int len = skb_transport_offset(skb) + transport_len; |
4033 | int ret; | 4033 | int ret; |
4034 | 4034 | ||
4035 | if (skb->len < len) { | 4035 | if (skb->len < len) |
4036 | kfree_skb(skb); | ||
4037 | return NULL; | 4036 | return NULL; |
4038 | } else if (skb->len == len) { | 4037 | else if (skb->len == len) |
4039 | return skb; | 4038 | return skb; |
4040 | } | ||
4041 | 4039 | ||
4042 | skb_chk = skb_clone(skb, GFP_ATOMIC); | 4040 | skb_chk = skb_clone(skb, GFP_ATOMIC); |
4043 | kfree_skb(skb); | ||
4044 | |||
4045 | if (!skb_chk) | 4041 | if (!skb_chk) |
4046 | return NULL; | 4042 | return NULL; |
4047 | 4043 | ||
@@ -4066,8 +4062,8 @@ static struct sk_buff *skb_checksum_maybe_trim(struct sk_buff *skb, | |||
4066 | * If the skb has data beyond the given transport length, then a | 4062 | * If the skb has data beyond the given transport length, then a |
4067 | * trimmed & cloned skb is checked and returned. | 4063 | * trimmed & cloned skb is checked and returned. |
4068 | * | 4064 | * |
4069 | * Caller needs to set the skb transport header and release the returned skb. | 4065 | * Caller needs to set the skb transport header and free any returned skb if it |
4070 | * Provided skb is consumed. | 4066 | * differs from the provided skb. |
4071 | */ | 4067 | */ |
4072 | struct sk_buff *skb_checksum_trimmed(struct sk_buff *skb, | 4068 | struct sk_buff *skb_checksum_trimmed(struct sk_buff *skb, |
4073 | unsigned int transport_len, | 4069 | unsigned int transport_len, |
@@ -4079,23 +4075,26 @@ struct sk_buff *skb_checksum_trimmed(struct sk_buff *skb, | |||
4079 | 4075 | ||
4080 | skb_chk = skb_checksum_maybe_trim(skb, transport_len); | 4076 | skb_chk = skb_checksum_maybe_trim(skb, transport_len); |
4081 | if (!skb_chk) | 4077 | if (!skb_chk) |
4082 | return NULL; | 4078 | goto err; |
4083 | 4079 | ||
4084 | if (!pskb_may_pull(skb_chk, offset)) { | 4080 | if (!pskb_may_pull(skb_chk, offset)) |
4085 | kfree_skb(skb_chk); | 4081 | goto err; |
4086 | return NULL; | ||
4087 | } | ||
4088 | 4082 | ||
4089 | __skb_pull(skb_chk, offset); | 4083 | __skb_pull(skb_chk, offset); |
4090 | ret = skb_chkf(skb_chk); | 4084 | ret = skb_chkf(skb_chk); |
4091 | __skb_push(skb_chk, offset); | 4085 | __skb_push(skb_chk, offset); |
4092 | 4086 | ||
4093 | if (ret) { | 4087 | if (ret) |
4094 | kfree_skb(skb_chk); | 4088 | goto err; |
4095 | return NULL; | ||
4096 | } | ||
4097 | 4089 | ||
4098 | return skb_chk; | 4090 | return skb_chk; |
4091 | |||
4092 | err: | ||
4093 | if (skb_chk && skb_chk != skb) | ||
4094 | kfree_skb(skb_chk); | ||
4095 | |||
4096 | return NULL; | ||
4097 | |||
4099 | } | 4098 | } |
4100 | EXPORT_SYMBOL(skb_checksum_trimmed); | 4099 | EXPORT_SYMBOL(skb_checksum_trimmed); |
4101 | 4100 | ||
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index 37c4bb89a708..b0c6258ffb79 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c | |||
@@ -2465,7 +2465,7 @@ static struct key_vector *fib_route_get_idx(struct fib_route_iter *iter, | |||
2465 | key = l->key + 1; | 2465 | key = l->key + 1; |
2466 | iter->pos++; | 2466 | iter->pos++; |
2467 | 2467 | ||
2468 | if (pos-- <= 0) | 2468 | if (--pos <= 0) |
2469 | break; | 2469 | break; |
2470 | 2470 | ||
2471 | l = NULL; | 2471 | l = NULL; |
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 651cdf648ec4..9fdfd9deac11 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c | |||
@@ -1435,33 +1435,35 @@ static int __ip_mc_check_igmp(struct sk_buff *skb, struct sk_buff **skb_trimmed) | |||
1435 | struct sk_buff *skb_chk; | 1435 | struct sk_buff *skb_chk; |
1436 | unsigned int transport_len; | 1436 | unsigned int transport_len; |
1437 | unsigned int len = skb_transport_offset(skb) + sizeof(struct igmphdr); | 1437 | unsigned int len = skb_transport_offset(skb) + sizeof(struct igmphdr); |
1438 | int ret; | 1438 | int ret = -EINVAL; |
1439 | 1439 | ||
1440 | transport_len = ntohs(ip_hdr(skb)->tot_len) - ip_hdrlen(skb); | 1440 | transport_len = ntohs(ip_hdr(skb)->tot_len) - ip_hdrlen(skb); |
1441 | 1441 | ||
1442 | skb_get(skb); | ||
1443 | skb_chk = skb_checksum_trimmed(skb, transport_len, | 1442 | skb_chk = skb_checksum_trimmed(skb, transport_len, |
1444 | ip_mc_validate_checksum); | 1443 | ip_mc_validate_checksum); |
1445 | if (!skb_chk) | 1444 | if (!skb_chk) |
1446 | return -EINVAL; | 1445 | goto err; |
1447 | 1446 | ||
1448 | if (!pskb_may_pull(skb_chk, len)) { | 1447 | if (!pskb_may_pull(skb_chk, len)) |
1449 | kfree_skb(skb_chk); | 1448 | goto err; |
1450 | return -EINVAL; | ||
1451 | } | ||
1452 | 1449 | ||
1453 | ret = ip_mc_check_igmp_msg(skb_chk); | 1450 | ret = ip_mc_check_igmp_msg(skb_chk); |
1454 | if (ret) { | 1451 | if (ret) |
1455 | kfree_skb(skb_chk); | 1452 | goto err; |
1456 | return ret; | ||
1457 | } | ||
1458 | 1453 | ||
1459 | if (skb_trimmed) | 1454 | if (skb_trimmed) |
1460 | *skb_trimmed = skb_chk; | 1455 | *skb_trimmed = skb_chk; |
1461 | else | 1456 | /* free now unneeded clone */ |
1457 | else if (skb_chk != skb) | ||
1462 | kfree_skb(skb_chk); | 1458 | kfree_skb(skb_chk); |
1463 | 1459 | ||
1464 | return 0; | 1460 | ret = 0; |
1461 | |||
1462 | err: | ||
1463 | if (ret && skb_chk && skb_chk != skb) | ||
1464 | kfree_skb(skb_chk); | ||
1465 | |||
1466 | return ret; | ||
1465 | } | 1467 | } |
1466 | 1468 | ||
1467 | /** | 1469 | /** |
@@ -1470,7 +1472,7 @@ static int __ip_mc_check_igmp(struct sk_buff *skb, struct sk_buff **skb_trimmed) | |||
1470 | * @skb_trimmed: to store an skb pointer trimmed to IPv4 packet tail (optional) | 1472 | * @skb_trimmed: to store an skb pointer trimmed to IPv4 packet tail (optional) |
1471 | * | 1473 | * |
1472 | * Checks whether an IPv4 packet is a valid IGMP packet. If so sets | 1474 | * Checks whether an IPv4 packet is a valid IGMP packet. If so sets |
1473 | * skb network and transport headers accordingly and returns zero. | 1475 | * skb transport header accordingly and returns zero. |
1474 | * | 1476 | * |
1475 | * -EINVAL: A broken packet was detected, i.e. it violates some internet | 1477 | * -EINVAL: A broken packet was detected, i.e. it violates some internet |
1476 | * standard | 1478 | * standard |
@@ -1485,7 +1487,8 @@ static int __ip_mc_check_igmp(struct sk_buff *skb, struct sk_buff **skb_trimmed) | |||
1485 | * to leave the original skb and its full frame unchanged (which might be | 1487 | * to leave the original skb and its full frame unchanged (which might be |
1486 | * desirable for layer 2 frame jugglers). | 1488 | * desirable for layer 2 frame jugglers). |
1487 | * | 1489 | * |
1488 | * The caller needs to release a reference count from any returned skb_trimmed. | 1490 | * Caller needs to set the skb network header and free any returned skb if it |
1491 | * differs from the provided skb. | ||
1489 | */ | 1492 | */ |
1490 | int ip_mc_check_igmp(struct sk_buff *skb, struct sk_buff **skb_trimmed) | 1493 | int ip_mc_check_igmp(struct sk_buff *skb, struct sk_buff **skb_trimmed) |
1491 | { | 1494 | { |
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 05e3145f7dc3..134957159c27 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c | |||
@@ -593,7 +593,7 @@ static bool reqsk_queue_unlink(struct request_sock_queue *queue, | |||
593 | } | 593 | } |
594 | 594 | ||
595 | spin_unlock(&queue->syn_wait_lock); | 595 | spin_unlock(&queue->syn_wait_lock); |
596 | if (del_timer_sync(&req->rsk_timer)) | 596 | if (timer_pending(&req->rsk_timer) && del_timer_sync(&req->rsk_timer)) |
597 | reqsk_put(req); | 597 | reqsk_put(req); |
598 | return found; | 598 | return found; |
599 | } | 599 | } |
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index 433231ccfb17..0330ab2e2b63 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c | |||
@@ -41,8 +41,6 @@ static int tcp_syn_retries_min = 1; | |||
41 | static int tcp_syn_retries_max = MAX_TCP_SYNCNT; | 41 | static int tcp_syn_retries_max = MAX_TCP_SYNCNT; |
42 | static int ip_ping_group_range_min[] = { 0, 0 }; | 42 | static int ip_ping_group_range_min[] = { 0, 0 }; |
43 | static int ip_ping_group_range_max[] = { GID_T_MAX, GID_T_MAX }; | 43 | static int ip_ping_group_range_max[] = { GID_T_MAX, GID_T_MAX }; |
44 | static int min_sndbuf = SOCK_MIN_SNDBUF; | ||
45 | static int min_rcvbuf = SOCK_MIN_RCVBUF; | ||
46 | 44 | ||
47 | /* Update system visible IP port range */ | 45 | /* Update system visible IP port range */ |
48 | static void set_local_port_range(struct net *net, int range[2]) | 46 | static void set_local_port_range(struct net *net, int range[2]) |
@@ -530,7 +528,7 @@ static struct ctl_table ipv4_table[] = { | |||
530 | .maxlen = sizeof(sysctl_tcp_wmem), | 528 | .maxlen = sizeof(sysctl_tcp_wmem), |
531 | .mode = 0644, | 529 | .mode = 0644, |
532 | .proc_handler = proc_dointvec_minmax, | 530 | .proc_handler = proc_dointvec_minmax, |
533 | .extra1 = &min_sndbuf, | 531 | .extra1 = &one, |
534 | }, | 532 | }, |
535 | { | 533 | { |
536 | .procname = "tcp_notsent_lowat", | 534 | .procname = "tcp_notsent_lowat", |
@@ -545,7 +543,7 @@ static struct ctl_table ipv4_table[] = { | |||
545 | .maxlen = sizeof(sysctl_tcp_rmem), | 543 | .maxlen = sizeof(sysctl_tcp_rmem), |
546 | .mode = 0644, | 544 | .mode = 0644, |
547 | .proc_handler = proc_dointvec_minmax, | 545 | .proc_handler = proc_dointvec_minmax, |
548 | .extra1 = &min_rcvbuf, | 546 | .extra1 = &one, |
549 | }, | 547 | }, |
550 | { | 548 | { |
551 | .procname = "tcp_app_win", | 549 | .procname = "tcp_app_win", |
@@ -758,7 +756,7 @@ static struct ctl_table ipv4_table[] = { | |||
758 | .maxlen = sizeof(sysctl_udp_rmem_min), | 756 | .maxlen = sizeof(sysctl_udp_rmem_min), |
759 | .mode = 0644, | 757 | .mode = 0644, |
760 | .proc_handler = proc_dointvec_minmax, | 758 | .proc_handler = proc_dointvec_minmax, |
761 | .extra1 = &min_rcvbuf, | 759 | .extra1 = &one |
762 | }, | 760 | }, |
763 | { | 761 | { |
764 | .procname = "udp_wmem_min", | 762 | .procname = "udp_wmem_min", |
@@ -766,7 +764,7 @@ static struct ctl_table ipv4_table[] = { | |||
766 | .maxlen = sizeof(sysctl_udp_wmem_min), | 764 | .maxlen = sizeof(sysctl_udp_wmem_min), |
767 | .mode = 0644, | 765 | .mode = 0644, |
768 | .proc_handler = proc_dointvec_minmax, | 766 | .proc_handler = proc_dointvec_minmax, |
769 | .extra1 = &min_sndbuf, | 767 | .extra1 = &one |
770 | }, | 768 | }, |
771 | { } | 769 | { } |
772 | }; | 770 | }; |
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 55d19861ab20..548c6237b1e7 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c | |||
@@ -172,6 +172,8 @@ static void rt6_free_pcpu(struct rt6_info *non_pcpu_rt) | |||
172 | *ppcpu_rt = NULL; | 172 | *ppcpu_rt = NULL; |
173 | } | 173 | } |
174 | } | 174 | } |
175 | |||
176 | non_pcpu_rt->rt6i_pcpu = NULL; | ||
175 | } | 177 | } |
176 | 178 | ||
177 | static void rt6_release(struct rt6_info *rt) | 179 | static void rt6_release(struct rt6_info *rt) |
diff --git a/net/ipv6/mcast_snoop.c b/net/ipv6/mcast_snoop.c index df8afe5ab31e..9405b04eecc6 100644 --- a/net/ipv6/mcast_snoop.c +++ b/net/ipv6/mcast_snoop.c | |||
@@ -143,34 +143,36 @@ static int __ipv6_mc_check_mld(struct sk_buff *skb, | |||
143 | struct sk_buff *skb_chk = NULL; | 143 | struct sk_buff *skb_chk = NULL; |
144 | unsigned int transport_len; | 144 | unsigned int transport_len; |
145 | unsigned int len = skb_transport_offset(skb) + sizeof(struct mld_msg); | 145 | unsigned int len = skb_transport_offset(skb) + sizeof(struct mld_msg); |
146 | int ret; | 146 | int ret = -EINVAL; |
147 | 147 | ||
148 | transport_len = ntohs(ipv6_hdr(skb)->payload_len); | 148 | transport_len = ntohs(ipv6_hdr(skb)->payload_len); |
149 | transport_len -= skb_transport_offset(skb) - sizeof(struct ipv6hdr); | 149 | transport_len -= skb_transport_offset(skb) - sizeof(struct ipv6hdr); |
150 | 150 | ||
151 | skb_get(skb); | ||
152 | skb_chk = skb_checksum_trimmed(skb, transport_len, | 151 | skb_chk = skb_checksum_trimmed(skb, transport_len, |
153 | ipv6_mc_validate_checksum); | 152 | ipv6_mc_validate_checksum); |
154 | if (!skb_chk) | 153 | if (!skb_chk) |
155 | return -EINVAL; | 154 | goto err; |
156 | 155 | ||
157 | if (!pskb_may_pull(skb_chk, len)) { | 156 | if (!pskb_may_pull(skb_chk, len)) |
158 | kfree_skb(skb_chk); | 157 | goto err; |
159 | return -EINVAL; | ||
160 | } | ||
161 | 158 | ||
162 | ret = ipv6_mc_check_mld_msg(skb_chk); | 159 | ret = ipv6_mc_check_mld_msg(skb_chk); |
163 | if (ret) { | 160 | if (ret) |
164 | kfree_skb(skb_chk); | 161 | goto err; |
165 | return ret; | ||
166 | } | ||
167 | 162 | ||
168 | if (skb_trimmed) | 163 | if (skb_trimmed) |
169 | *skb_trimmed = skb_chk; | 164 | *skb_trimmed = skb_chk; |
170 | else | 165 | /* free now unneeded clone */ |
166 | else if (skb_chk != skb) | ||
171 | kfree_skb(skb_chk); | 167 | kfree_skb(skb_chk); |
172 | 168 | ||
173 | return 0; | 169 | ret = 0; |
170 | |||
171 | err: | ||
172 | if (ret && skb_chk && skb_chk != skb) | ||
173 | kfree_skb(skb_chk); | ||
174 | |||
175 | return ret; | ||
174 | } | 176 | } |
175 | 177 | ||
176 | /** | 178 | /** |
@@ -179,7 +181,7 @@ static int __ipv6_mc_check_mld(struct sk_buff *skb, | |||
179 | * @skb_trimmed: to store an skb pointer trimmed to IPv6 packet tail (optional) | 181 | * @skb_trimmed: to store an skb pointer trimmed to IPv6 packet tail (optional) |
180 | * | 182 | * |
181 | * Checks whether an IPv6 packet is a valid MLD packet. If so sets | 183 | * Checks whether an IPv6 packet is a valid MLD packet. If so sets |
182 | * skb network and transport headers accordingly and returns zero. | 184 | * skb transport header accordingly and returns zero. |
183 | * | 185 | * |
184 | * -EINVAL: A broken packet was detected, i.e. it violates some internet | 186 | * -EINVAL: A broken packet was detected, i.e. it violates some internet |
185 | * standard | 187 | * standard |
@@ -194,7 +196,8 @@ static int __ipv6_mc_check_mld(struct sk_buff *skb, | |||
194 | * to leave the original skb and its full frame unchanged (which might be | 196 | * to leave the original skb and its full frame unchanged (which might be |
195 | * desirable for layer 2 frame jugglers). | 197 | * desirable for layer 2 frame jugglers). |
196 | * | 198 | * |
197 | * The caller needs to release a reference count from any returned skb_trimmed. | 199 | * Caller needs to set the skb network header and free any returned skb if it |
200 | * differs from the provided skb. | ||
198 | */ | 201 | */ |
199 | int ipv6_mc_check_mld(struct sk_buff *skb, struct sk_buff **skb_trimmed) | 202 | int ipv6_mc_check_mld(struct sk_buff *skb, struct sk_buff **skb_trimmed) |
200 | { | 203 | { |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 9de4d2bcd916..d15586490cec 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -318,8 +318,7 @@ static const struct rt6_info ip6_blk_hole_entry_template = { | |||
318 | /* allocate dst with ip6_dst_ops */ | 318 | /* allocate dst with ip6_dst_ops */ |
319 | static struct rt6_info *__ip6_dst_alloc(struct net *net, | 319 | static struct rt6_info *__ip6_dst_alloc(struct net *net, |
320 | struct net_device *dev, | 320 | struct net_device *dev, |
321 | int flags, | 321 | int flags) |
322 | struct fib6_table *table) | ||
323 | { | 322 | { |
324 | struct rt6_info *rt = dst_alloc(&net->ipv6.ip6_dst_ops, dev, | 323 | struct rt6_info *rt = dst_alloc(&net->ipv6.ip6_dst_ops, dev, |
325 | 0, DST_OBSOLETE_FORCE_CHK, flags); | 324 | 0, DST_OBSOLETE_FORCE_CHK, flags); |
@@ -336,10 +335,9 @@ static struct rt6_info *__ip6_dst_alloc(struct net *net, | |||
336 | 335 | ||
337 | static struct rt6_info *ip6_dst_alloc(struct net *net, | 336 | static struct rt6_info *ip6_dst_alloc(struct net *net, |
338 | struct net_device *dev, | 337 | struct net_device *dev, |
339 | int flags, | 338 | int flags) |
340 | struct fib6_table *table) | ||
341 | { | 339 | { |
342 | struct rt6_info *rt = __ip6_dst_alloc(net, dev, flags, table); | 340 | struct rt6_info *rt = __ip6_dst_alloc(net, dev, flags); |
343 | 341 | ||
344 | if (rt) { | 342 | if (rt) { |
345 | rt->rt6i_pcpu = alloc_percpu_gfp(struct rt6_info *, GFP_ATOMIC); | 343 | rt->rt6i_pcpu = alloc_percpu_gfp(struct rt6_info *, GFP_ATOMIC); |
@@ -950,8 +948,7 @@ static struct rt6_info *ip6_rt_cache_alloc(struct rt6_info *ort, | |||
950 | if (ort->rt6i_flags & (RTF_CACHE | RTF_PCPU)) | 948 | if (ort->rt6i_flags & (RTF_CACHE | RTF_PCPU)) |
951 | ort = (struct rt6_info *)ort->dst.from; | 949 | ort = (struct rt6_info *)ort->dst.from; |
952 | 950 | ||
953 | rt = __ip6_dst_alloc(dev_net(ort->dst.dev), ort->dst.dev, | 951 | rt = __ip6_dst_alloc(dev_net(ort->dst.dev), ort->dst.dev, 0); |
954 | 0, ort->rt6i_table); | ||
955 | 952 | ||
956 | if (!rt) | 953 | if (!rt) |
957 | return NULL; | 954 | return NULL; |
@@ -983,8 +980,7 @@ static struct rt6_info *ip6_rt_pcpu_alloc(struct rt6_info *rt) | |||
983 | struct rt6_info *pcpu_rt; | 980 | struct rt6_info *pcpu_rt; |
984 | 981 | ||
985 | pcpu_rt = __ip6_dst_alloc(dev_net(rt->dst.dev), | 982 | pcpu_rt = __ip6_dst_alloc(dev_net(rt->dst.dev), |
986 | rt->dst.dev, rt->dst.flags, | 983 | rt->dst.dev, rt->dst.flags); |
987 | rt->rt6i_table); | ||
988 | 984 | ||
989 | if (!pcpu_rt) | 985 | if (!pcpu_rt) |
990 | return NULL; | 986 | return NULL; |
@@ -997,32 +993,53 @@ static struct rt6_info *ip6_rt_pcpu_alloc(struct rt6_info *rt) | |||
997 | /* It should be called with read_lock_bh(&tb6_lock) acquired */ | 993 | /* It should be called with read_lock_bh(&tb6_lock) acquired */ |
998 | static struct rt6_info *rt6_get_pcpu_route(struct rt6_info *rt) | 994 | static struct rt6_info *rt6_get_pcpu_route(struct rt6_info *rt) |
999 | { | 995 | { |
1000 | struct rt6_info *pcpu_rt, *prev, **p; | 996 | struct rt6_info *pcpu_rt, **p; |
1001 | 997 | ||
1002 | p = this_cpu_ptr(rt->rt6i_pcpu); | 998 | p = this_cpu_ptr(rt->rt6i_pcpu); |
1003 | pcpu_rt = *p; | 999 | pcpu_rt = *p; |
1004 | 1000 | ||
1005 | if (pcpu_rt) | 1001 | if (pcpu_rt) { |
1006 | goto done; | 1002 | dst_hold(&pcpu_rt->dst); |
1003 | rt6_dst_from_metrics_check(pcpu_rt); | ||
1004 | } | ||
1005 | return pcpu_rt; | ||
1006 | } | ||
1007 | |||
1008 | static struct rt6_info *rt6_make_pcpu_route(struct rt6_info *rt) | ||
1009 | { | ||
1010 | struct fib6_table *table = rt->rt6i_table; | ||
1011 | struct rt6_info *pcpu_rt, *prev, **p; | ||
1007 | 1012 | ||
1008 | pcpu_rt = ip6_rt_pcpu_alloc(rt); | 1013 | pcpu_rt = ip6_rt_pcpu_alloc(rt); |
1009 | if (!pcpu_rt) { | 1014 | if (!pcpu_rt) { |
1010 | struct net *net = dev_net(rt->dst.dev); | 1015 | struct net *net = dev_net(rt->dst.dev); |
1011 | 1016 | ||
1012 | pcpu_rt = net->ipv6.ip6_null_entry; | 1017 | dst_hold(&net->ipv6.ip6_null_entry->dst); |
1013 | goto done; | 1018 | return net->ipv6.ip6_null_entry; |
1014 | } | 1019 | } |
1015 | 1020 | ||
1016 | prev = cmpxchg(p, NULL, pcpu_rt); | 1021 | read_lock_bh(&table->tb6_lock); |
1017 | if (prev) { | 1022 | if (rt->rt6i_pcpu) { |
1018 | /* If someone did it before us, return prev instead */ | 1023 | p = this_cpu_ptr(rt->rt6i_pcpu); |
1024 | prev = cmpxchg(p, NULL, pcpu_rt); | ||
1025 | if (prev) { | ||
1026 | /* If someone did it before us, return prev instead */ | ||
1027 | dst_destroy(&pcpu_rt->dst); | ||
1028 | pcpu_rt = prev; | ||
1029 | } | ||
1030 | } else { | ||
1031 | /* rt has been removed from the fib6 tree | ||
1032 | * before we have a chance to acquire the read_lock. | ||
1033 | * In this case, don't brother to create a pcpu rt | ||
1034 | * since rt is going away anyway. The next | ||
1035 | * dst_check() will trigger a re-lookup. | ||
1036 | */ | ||
1019 | dst_destroy(&pcpu_rt->dst); | 1037 | dst_destroy(&pcpu_rt->dst); |
1020 | pcpu_rt = prev; | 1038 | pcpu_rt = rt; |
1021 | } | 1039 | } |
1022 | |||
1023 | done: | ||
1024 | dst_hold(&pcpu_rt->dst); | 1040 | dst_hold(&pcpu_rt->dst); |
1025 | rt6_dst_from_metrics_check(pcpu_rt); | 1041 | rt6_dst_from_metrics_check(pcpu_rt); |
1042 | read_unlock_bh(&table->tb6_lock); | ||
1026 | return pcpu_rt; | 1043 | return pcpu_rt; |
1027 | } | 1044 | } |
1028 | 1045 | ||
@@ -1097,9 +1114,22 @@ redo_rt6_select: | |||
1097 | rt->dst.lastuse = jiffies; | 1114 | rt->dst.lastuse = jiffies; |
1098 | rt->dst.__use++; | 1115 | rt->dst.__use++; |
1099 | pcpu_rt = rt6_get_pcpu_route(rt); | 1116 | pcpu_rt = rt6_get_pcpu_route(rt); |
1100 | read_unlock_bh(&table->tb6_lock); | 1117 | |
1118 | if (pcpu_rt) { | ||
1119 | read_unlock_bh(&table->tb6_lock); | ||
1120 | } else { | ||
1121 | /* We have to do the read_unlock first | ||
1122 | * because rt6_make_pcpu_route() may trigger | ||
1123 | * ip6_dst_gc() which will take the write_lock. | ||
1124 | */ | ||
1125 | dst_hold(&rt->dst); | ||
1126 | read_unlock_bh(&table->tb6_lock); | ||
1127 | pcpu_rt = rt6_make_pcpu_route(rt); | ||
1128 | dst_release(&rt->dst); | ||
1129 | } | ||
1101 | 1130 | ||
1102 | return pcpu_rt; | 1131 | return pcpu_rt; |
1132 | |||
1103 | } | 1133 | } |
1104 | } | 1134 | } |
1105 | 1135 | ||
@@ -1555,7 +1585,7 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev, | |||
1555 | if (unlikely(!idev)) | 1585 | if (unlikely(!idev)) |
1556 | return ERR_PTR(-ENODEV); | 1586 | return ERR_PTR(-ENODEV); |
1557 | 1587 | ||
1558 | rt = ip6_dst_alloc(net, dev, 0, NULL); | 1588 | rt = ip6_dst_alloc(net, dev, 0); |
1559 | if (unlikely(!rt)) { | 1589 | if (unlikely(!rt)) { |
1560 | in6_dev_put(idev); | 1590 | in6_dev_put(idev); |
1561 | dst = ERR_PTR(-ENOMEM); | 1591 | dst = ERR_PTR(-ENOMEM); |
@@ -1742,7 +1772,8 @@ int ip6_route_add(struct fib6_config *cfg) | |||
1742 | if (!table) | 1772 | if (!table) |
1743 | goto out; | 1773 | goto out; |
1744 | 1774 | ||
1745 | rt = ip6_dst_alloc(net, NULL, (cfg->fc_flags & RTF_ADDRCONF) ? 0 : DST_NOCOUNT, table); | 1775 | rt = ip6_dst_alloc(net, NULL, |
1776 | (cfg->fc_flags & RTF_ADDRCONF) ? 0 : DST_NOCOUNT); | ||
1746 | 1777 | ||
1747 | if (!rt) { | 1778 | if (!rt) { |
1748 | err = -ENOMEM; | 1779 | err = -ENOMEM; |
@@ -2399,7 +2430,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, | |||
2399 | { | 2430 | { |
2400 | struct net *net = dev_net(idev->dev); | 2431 | struct net *net = dev_net(idev->dev); |
2401 | struct rt6_info *rt = ip6_dst_alloc(net, net->loopback_dev, | 2432 | struct rt6_info *rt = ip6_dst_alloc(net, net->loopback_dev, |
2402 | DST_NOCOUNT, NULL); | 2433 | DST_NOCOUNT); |
2403 | if (!rt) | 2434 | if (!rt) |
2404 | return ERR_PTR(-ENOMEM); | 2435 | return ERR_PTR(-ENOMEM); |
2405 | 2436 | ||
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c index 247552a7f6c2..3ece7d1034c8 100644 --- a/net/mac80211/rc80211_minstrel.c +++ b/net/mac80211/rc80211_minstrel.c | |||
@@ -92,14 +92,15 @@ int minstrel_get_tp_avg(struct minstrel_rate *mr, int prob_ewma) | |||
92 | static inline void | 92 | static inline void |
93 | minstrel_sort_best_tp_rates(struct minstrel_sta_info *mi, int i, u8 *tp_list) | 93 | minstrel_sort_best_tp_rates(struct minstrel_sta_info *mi, int i, u8 *tp_list) |
94 | { | 94 | { |
95 | int j = MAX_THR_RATES; | 95 | int j; |
96 | struct minstrel_rate_stats *tmp_mrs = &mi->r[j - 1].stats; | 96 | struct minstrel_rate_stats *tmp_mrs; |
97 | struct minstrel_rate_stats *cur_mrs = &mi->r[i].stats; | 97 | struct minstrel_rate_stats *cur_mrs = &mi->r[i].stats; |
98 | 98 | ||
99 | while (j > 0 && (minstrel_get_tp_avg(&mi->r[i], cur_mrs->prob_ewma) > | 99 | for (j = MAX_THR_RATES; j > 0; --j) { |
100 | minstrel_get_tp_avg(&mi->r[tp_list[j - 1]], tmp_mrs->prob_ewma))) { | ||
101 | j--; | ||
102 | tmp_mrs = &mi->r[tp_list[j - 1]].stats; | 100 | tmp_mrs = &mi->r[tp_list[j - 1]].stats; |
101 | if (minstrel_get_tp_avg(&mi->r[i], cur_mrs->prob_ewma) <= | ||
102 | minstrel_get_tp_avg(&mi->r[tp_list[j - 1]], tmp_mrs->prob_ewma)) | ||
103 | break; | ||
103 | } | 104 | } |
104 | 105 | ||
105 | if (j < MAX_THR_RATES - 1) | 106 | if (j < MAX_THR_RATES - 1) |