diff options
author | Dave Airlie <airlied@redhat.com> | 2015-08-17 00:13:53 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2015-08-17 00:13:53 -0400 |
commit | 4eebf60b7452fbd551fd7dece855ba7825a49cbc (patch) | |
tree | 490b4d194ba09c90e10201ab7fc084a0bda0ed27 /net | |
parent | 8f9cb50789e76f3e224e8861adf650e55c747af4 (diff) | |
parent | 2c6625cd545bdd66acff14f3394865d43920a5c7 (diff) |
Merge tag 'v4.2-rc7' into drm-next
Linux 4.2-rc7
Backmerge master for i915 fixes
Diffstat (limited to 'net')
92 files changed, 849 insertions, 422 deletions
diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c index 9dd49ca67dbc..6e70ddb158b4 100644 --- a/net/9p/trans_virtio.c +++ b/net/9p/trans_virtio.c | |||
@@ -704,6 +704,7 @@ static void p9_virtio_remove(struct virtio_device *vdev) | |||
704 | 704 | ||
705 | mutex_unlock(&virtio_9p_lock); | 705 | mutex_unlock(&virtio_9p_lock); |
706 | 706 | ||
707 | vdev->config->reset(vdev); | ||
707 | vdev->config->del_vqs(vdev); | 708 | vdev->config->del_vqs(vdev); |
708 | 709 | ||
709 | sysfs_remove_file(&(vdev->dev.kobj), &dev_attr_mount_tag.attr); | 710 | sysfs_remove_file(&(vdev->dev.kobj), &dev_attr_mount_tag.attr); |
diff --git a/net/ax25/ax25_subr.c b/net/ax25/ax25_subr.c index 1997538a5d23..3b78e8473a01 100644 --- a/net/ax25/ax25_subr.c +++ b/net/ax25/ax25_subr.c | |||
@@ -264,6 +264,7 @@ void ax25_disconnect(ax25_cb *ax25, int reason) | |||
264 | { | 264 | { |
265 | ax25_clear_queues(ax25); | 265 | ax25_clear_queues(ax25); |
266 | 266 | ||
267 | ax25_stop_heartbeat(ax25); | ||
267 | ax25_stop_t1timer(ax25); | 268 | ax25_stop_t1timer(ax25); |
268 | ax25_stop_t2timer(ax25); | 269 | ax25_stop_t2timer(ax25); |
269 | ax25_stop_t3timer(ax25); | 270 | ax25_stop_t3timer(ax25); |
diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c index fb54e6aed096..6d0b471eede8 100644 --- a/net/batman-adv/distributed-arp-table.c +++ b/net/batman-adv/distributed-arp-table.c | |||
@@ -1138,6 +1138,9 @@ void batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv, | |||
1138 | * @bat_priv: the bat priv with all the soft interface information | 1138 | * @bat_priv: the bat priv with all the soft interface information |
1139 | * @skb: packet to check | 1139 | * @skb: packet to check |
1140 | * @hdr_size: size of the encapsulation header | 1140 | * @hdr_size: size of the encapsulation header |
1141 | * | ||
1142 | * Returns true if the packet was snooped and consumed by DAT. False if the | ||
1143 | * packet has to be delivered to the interface | ||
1141 | */ | 1144 | */ |
1142 | bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv, | 1145 | bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv, |
1143 | struct sk_buff *skb, int hdr_size) | 1146 | struct sk_buff *skb, int hdr_size) |
@@ -1145,7 +1148,7 @@ bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv, | |||
1145 | uint16_t type; | 1148 | uint16_t type; |
1146 | __be32 ip_src, ip_dst; | 1149 | __be32 ip_src, ip_dst; |
1147 | uint8_t *hw_src, *hw_dst; | 1150 | uint8_t *hw_src, *hw_dst; |
1148 | bool ret = false; | 1151 | bool dropped = false; |
1149 | unsigned short vid; | 1152 | unsigned short vid; |
1150 | 1153 | ||
1151 | if (!atomic_read(&bat_priv->distributed_arp_table)) | 1154 | if (!atomic_read(&bat_priv->distributed_arp_table)) |
@@ -1174,12 +1177,17 @@ bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv, | |||
1174 | /* if this REPLY is directed to a client of mine, let's deliver the | 1177 | /* if this REPLY is directed to a client of mine, let's deliver the |
1175 | * packet to the interface | 1178 | * packet to the interface |
1176 | */ | 1179 | */ |
1177 | ret = !batadv_is_my_client(bat_priv, hw_dst, vid); | 1180 | dropped = !batadv_is_my_client(bat_priv, hw_dst, vid); |
1181 | |||
1182 | /* if this REPLY is sent on behalf of a client of mine, let's drop the | ||
1183 | * packet because the client will reply by itself | ||
1184 | */ | ||
1185 | dropped |= batadv_is_my_client(bat_priv, hw_src, vid); | ||
1178 | out: | 1186 | out: |
1179 | if (ret) | 1187 | if (dropped) |
1180 | kfree_skb(skb); | 1188 | kfree_skb(skb); |
1181 | /* if ret == false -> packet has to be delivered to the interface */ | 1189 | /* if dropped == false -> deliver to the interface */ |
1182 | return ret; | 1190 | return dropped; |
1183 | } | 1191 | } |
1184 | 1192 | ||
1185 | /** | 1193 | /** |
diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c index bb0158620628..cffa92dd9877 100644 --- a/net/batman-adv/gateway_client.c +++ b/net/batman-adv/gateway_client.c | |||
@@ -439,6 +439,8 @@ static void batadv_gw_node_add(struct batadv_priv *bat_priv, | |||
439 | 439 | ||
440 | INIT_HLIST_NODE(&gw_node->list); | 440 | INIT_HLIST_NODE(&gw_node->list); |
441 | gw_node->orig_node = orig_node; | 441 | gw_node->orig_node = orig_node; |
442 | gw_node->bandwidth_down = ntohl(gateway->bandwidth_down); | ||
443 | gw_node->bandwidth_up = ntohl(gateway->bandwidth_up); | ||
442 | atomic_set(&gw_node->refcount, 1); | 444 | atomic_set(&gw_node->refcount, 1); |
443 | 445 | ||
444 | spin_lock_bh(&bat_priv->gw.list_lock); | 446 | spin_lock_bh(&bat_priv->gw.list_lock); |
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index c002961da75d..a2fc843c2243 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c | |||
@@ -479,6 +479,9 @@ out: | |||
479 | */ | 479 | */ |
480 | void batadv_softif_vlan_free_ref(struct batadv_softif_vlan *vlan) | 480 | void batadv_softif_vlan_free_ref(struct batadv_softif_vlan *vlan) |
481 | { | 481 | { |
482 | if (!vlan) | ||
483 | return; | ||
484 | |||
482 | if (atomic_dec_and_test(&vlan->refcount)) { | 485 | if (atomic_dec_and_test(&vlan->refcount)) { |
483 | spin_lock_bh(&vlan->bat_priv->softif_vlan_list_lock); | 486 | spin_lock_bh(&vlan->bat_priv->softif_vlan_list_lock); |
484 | hlist_del_rcu(&vlan->list); | 487 | hlist_del_rcu(&vlan->list); |
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index b4824951010b..5e953297d3b2 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c | |||
@@ -594,6 +594,9 @@ bool batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr, | |||
594 | 594 | ||
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", | ||
598 | addr, BATADV_PRINT_VID(vid))) | ||
599 | goto out; | ||
597 | 600 | ||
598 | batadv_dbg(BATADV_DBG_TT, bat_priv, | 601 | batadv_dbg(BATADV_DBG_TT, bat_priv, |
599 | "Creating new local tt entry: %pM (vid: %d, ttvn: %d)\n", | 602 | "Creating new local tt entry: %pM (vid: %d, ttvn: %d)\n", |
@@ -1034,6 +1037,7 @@ uint16_t batadv_tt_local_remove(struct batadv_priv *bat_priv, | |||
1034 | struct batadv_tt_local_entry *tt_local_entry; | 1037 | struct batadv_tt_local_entry *tt_local_entry; |
1035 | uint16_t flags, curr_flags = BATADV_NO_FLAGS; | 1038 | uint16_t flags, curr_flags = BATADV_NO_FLAGS; |
1036 | struct batadv_softif_vlan *vlan; | 1039 | struct batadv_softif_vlan *vlan; |
1040 | void *tt_entry_exists; | ||
1037 | 1041 | ||
1038 | tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr, vid); | 1042 | tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr, vid); |
1039 | if (!tt_local_entry) | 1043 | if (!tt_local_entry) |
@@ -1061,11 +1065,22 @@ uint16_t batadv_tt_local_remove(struct batadv_priv *bat_priv, | |||
1061 | * immediately purge it | 1065 | * immediately purge it |
1062 | */ | 1066 | */ |
1063 | batadv_tt_local_event(bat_priv, tt_local_entry, BATADV_TT_CLIENT_DEL); | 1067 | batadv_tt_local_event(bat_priv, tt_local_entry, BATADV_TT_CLIENT_DEL); |
1064 | hlist_del_rcu(&tt_local_entry->common.hash_entry); | 1068 | |
1069 | tt_entry_exists = batadv_hash_remove(bat_priv->tt.local_hash, | ||
1070 | batadv_compare_tt, | ||
1071 | batadv_choose_tt, | ||
1072 | &tt_local_entry->common); | ||
1073 | if (!tt_entry_exists) | ||
1074 | goto out; | ||
1075 | |||
1076 | /* extra call to free the local tt entry */ | ||
1065 | batadv_tt_local_entry_free_ref(tt_local_entry); | 1077 | batadv_tt_local_entry_free_ref(tt_local_entry); |
1066 | 1078 | ||
1067 | /* decrease the reference held for this vlan */ | 1079 | /* decrease the reference held for this vlan */ |
1068 | vlan = batadv_softif_vlan_get(bat_priv, vid); | 1080 | vlan = batadv_softif_vlan_get(bat_priv, vid); |
1081 | if (!vlan) | ||
1082 | goto out; | ||
1083 | |||
1069 | batadv_softif_vlan_free_ref(vlan); | 1084 | batadv_softif_vlan_free_ref(vlan); |
1070 | batadv_softif_vlan_free_ref(vlan); | 1085 | batadv_softif_vlan_free_ref(vlan); |
1071 | 1086 | ||
@@ -1166,8 +1181,10 @@ static void batadv_tt_local_table_free(struct batadv_priv *bat_priv) | |||
1166 | /* decrease the reference held for this vlan */ | 1181 | /* decrease the reference held for this vlan */ |
1167 | vlan = batadv_softif_vlan_get(bat_priv, | 1182 | vlan = batadv_softif_vlan_get(bat_priv, |
1168 | tt_common_entry->vid); | 1183 | tt_common_entry->vid); |
1169 | batadv_softif_vlan_free_ref(vlan); | 1184 | if (vlan) { |
1170 | batadv_softif_vlan_free_ref(vlan); | 1185 | batadv_softif_vlan_free_ref(vlan); |
1186 | batadv_softif_vlan_free_ref(vlan); | ||
1187 | } | ||
1171 | 1188 | ||
1172 | batadv_tt_local_entry_free_ref(tt_local); | 1189 | batadv_tt_local_entry_free_ref(tt_local); |
1173 | } | 1190 | } |
@@ -3207,8 +3224,10 @@ static void batadv_tt_local_purge_pending_clients(struct batadv_priv *bat_priv) | |||
3207 | 3224 | ||
3208 | /* decrease the reference held for this vlan */ | 3225 | /* decrease the reference held for this vlan */ |
3209 | vlan = batadv_softif_vlan_get(bat_priv, tt_common->vid); | 3226 | vlan = batadv_softif_vlan_get(bat_priv, tt_common->vid); |
3210 | batadv_softif_vlan_free_ref(vlan); | 3227 | if (vlan) { |
3211 | batadv_softif_vlan_free_ref(vlan); | 3228 | batadv_softif_vlan_free_ref(vlan); |
3229 | batadv_softif_vlan_free_ref(vlan); | ||
3230 | } | ||
3212 | 3231 | ||
3213 | batadv_tt_local_entry_free_ref(tt_local); | 3232 | batadv_tt_local_entry_free_ref(tt_local); |
3214 | } | 3233 | } |
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 7998fb279165..92720f3fe573 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -7820,7 +7820,7 @@ void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent) | |||
7820 | /* Make sure we copy only the significant bytes based on the | 7820 | /* Make sure we copy only the significant bytes based on the |
7821 | * encryption key size, and set the rest of the value to zeroes. | 7821 | * encryption key size, and set the rest of the value to zeroes. |
7822 | */ | 7822 | */ |
7823 | memcpy(ev.key.val, key->val, sizeof(key->enc_size)); | 7823 | memcpy(ev.key.val, key->val, key->enc_size); |
7824 | memset(ev.key.val + key->enc_size, 0, | 7824 | memset(ev.key.val + key->enc_size, 0, |
7825 | sizeof(ev.key.val) - key->enc_size); | 7825 | sizeof(ev.key.val) - key->enc_size); |
7826 | 7826 | ||
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 3d0f7d2a0616..ad82324f710f 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c | |||
@@ -2312,6 +2312,10 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level) | |||
2312 | return 1; | 2312 | return 1; |
2313 | 2313 | ||
2314 | chan = conn->smp; | 2314 | chan = conn->smp; |
2315 | if (!chan) { | ||
2316 | BT_ERR("SMP security requested but not available"); | ||
2317 | return 1; | ||
2318 | } | ||
2315 | 2319 | ||
2316 | if (!hci_dev_test_flag(hcon->hdev, HCI_LE_ENABLED)) | 2320 | if (!hci_dev_test_flag(hcon->hdev, HCI_LE_ENABLED)) |
2317 | return 1; | 2321 | return 1; |
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c index 0ff6e1bbca91..fa7bfced888e 100644 --- a/net/bridge/br_forward.c +++ b/net/bridge/br_forward.c | |||
@@ -37,15 +37,30 @@ static inline int should_deliver(const struct net_bridge_port *p, | |||
37 | 37 | ||
38 | int br_dev_queue_push_xmit(struct sock *sk, struct sk_buff *skb) | 38 | int br_dev_queue_push_xmit(struct sock *sk, struct sk_buff *skb) |
39 | { | 39 | { |
40 | if (!is_skb_forwardable(skb->dev, skb)) { | 40 | if (!is_skb_forwardable(skb->dev, skb)) |
41 | kfree_skb(skb); | 41 | goto drop; |
42 | } else { | 42 | |
43 | skb_push(skb, ETH_HLEN); | 43 | skb_push(skb, ETH_HLEN); |
44 | br_drop_fake_rtable(skb); | 44 | br_drop_fake_rtable(skb); |
45 | skb_sender_cpu_clear(skb); | 45 | skb_sender_cpu_clear(skb); |
46 | dev_queue_xmit(skb); | 46 | |
47 | if (skb->ip_summed == CHECKSUM_PARTIAL && | ||
48 | (skb->protocol == htons(ETH_P_8021Q) || | ||
49 | skb->protocol == htons(ETH_P_8021AD))) { | ||
50 | int depth; | ||
51 | |||
52 | if (!__vlan_get_protocol(skb, skb->protocol, &depth)) | ||
53 | goto drop; | ||
54 | |||
55 | skb_set_network_header(skb, depth); | ||
47 | } | 56 | } |
48 | 57 | ||
58 | dev_queue_xmit(skb); | ||
59 | |||
60 | return 0; | ||
61 | |||
62 | drop: | ||
63 | kfree_skb(skb); | ||
49 | return 0; | 64 | return 0; |
50 | } | 65 | } |
51 | EXPORT_SYMBOL_GPL(br_dev_queue_push_xmit); | 66 | EXPORT_SYMBOL_GPL(br_dev_queue_push_xmit); |
diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c index c11cf2611db0..c94321955db7 100644 --- a/net/bridge/br_mdb.c +++ b/net/bridge/br_mdb.c | |||
@@ -351,7 +351,6 @@ static int br_mdb_add_group(struct net_bridge *br, struct net_bridge_port *port, | |||
351 | if (state == MDB_TEMPORARY) | 351 | if (state == MDB_TEMPORARY) |
352 | mod_timer(&p->timer, now + br->multicast_membership_interval); | 352 | mod_timer(&p->timer, now + br->multicast_membership_interval); |
353 | 353 | ||
354 | br_mdb_notify(br->dev, port, group, RTM_NEWMDB); | ||
355 | return 0; | 354 | return 0; |
356 | } | 355 | } |
357 | 356 | ||
@@ -446,6 +445,7 @@ static int __br_mdb_del(struct net_bridge *br, struct br_mdb_entry *entry) | |||
446 | if (p->port->state == BR_STATE_DISABLED) | 445 | if (p->port->state == BR_STATE_DISABLED) |
447 | goto unlock; | 446 | goto unlock; |
448 | 447 | ||
448 | entry->state = p->state; | ||
449 | rcu_assign_pointer(*pp, p->next); | 449 | rcu_assign_pointer(*pp, p->next); |
450 | hlist_del_init(&p->mglist); | 450 | hlist_del_init(&p->mglist); |
451 | del_timer(&p->timer); | 451 | del_timer(&p->timer); |
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 742a6c27d7a2..0b39dcc65b94 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c | |||
@@ -39,6 +39,16 @@ static void br_multicast_start_querier(struct net_bridge *br, | |||
39 | struct bridge_mcast_own_query *query); | 39 | struct bridge_mcast_own_query *query); |
40 | static void br_multicast_add_router(struct net_bridge *br, | 40 | static void br_multicast_add_router(struct net_bridge *br, |
41 | struct net_bridge_port *port); | 41 | struct net_bridge_port *port); |
42 | static void br_ip4_multicast_leave_group(struct net_bridge *br, | ||
43 | struct net_bridge_port *port, | ||
44 | __be32 group, | ||
45 | __u16 vid); | ||
46 | #if IS_ENABLED(CONFIG_IPV6) | ||
47 | static void br_ip6_multicast_leave_group(struct net_bridge *br, | ||
48 | struct net_bridge_port *port, | ||
49 | const struct in6_addr *group, | ||
50 | __u16 vid); | ||
51 | #endif | ||
42 | unsigned int br_mdb_rehash_seq; | 52 | unsigned int br_mdb_rehash_seq; |
43 | 53 | ||
44 | static inline int br_ip_equal(const struct br_ip *a, const struct br_ip *b) | 54 | static inline int br_ip_equal(const struct br_ip *a, const struct br_ip *b) |
@@ -1010,9 +1020,15 @@ static int br_ip4_multicast_igmp3_report(struct net_bridge *br, | |||
1010 | continue; | 1020 | continue; |
1011 | } | 1021 | } |
1012 | 1022 | ||
1013 | err = br_ip4_multicast_add_group(br, port, group, vid); | 1023 | if ((type == IGMPV3_CHANGE_TO_INCLUDE || |
1014 | if (err) | 1024 | type == IGMPV3_MODE_IS_INCLUDE) && |
1015 | break; | 1025 | ntohs(grec->grec_nsrcs) == 0) { |
1026 | br_ip4_multicast_leave_group(br, port, group, vid); | ||
1027 | } else { | ||
1028 | err = br_ip4_multicast_add_group(br, port, group, vid); | ||
1029 | if (err) | ||
1030 | break; | ||
1031 | } | ||
1016 | } | 1032 | } |
1017 | 1033 | ||
1018 | return err; | 1034 | return err; |
@@ -1071,10 +1087,17 @@ static int br_ip6_multicast_mld2_report(struct net_bridge *br, | |||
1071 | continue; | 1087 | continue; |
1072 | } | 1088 | } |
1073 | 1089 | ||
1074 | err = br_ip6_multicast_add_group(br, port, &grec->grec_mca, | 1090 | if ((grec->grec_type == MLD2_CHANGE_TO_INCLUDE || |
1075 | vid); | 1091 | grec->grec_type == MLD2_MODE_IS_INCLUDE) && |
1076 | if (err) | 1092 | ntohs(*nsrcs) == 0) { |
1077 | break; | 1093 | br_ip6_multicast_leave_group(br, port, &grec->grec_mca, |
1094 | vid); | ||
1095 | } else { | ||
1096 | err = br_ip6_multicast_add_group(br, port, | ||
1097 | &grec->grec_mca, vid); | ||
1098 | if (!err) | ||
1099 | break; | ||
1100 | } | ||
1078 | } | 1101 | } |
1079 | 1102 | ||
1080 | return err; | 1103 | return err; |
@@ -1393,8 +1416,7 @@ br_multicast_leave_group(struct net_bridge *br, | |||
1393 | 1416 | ||
1394 | spin_lock(&br->multicast_lock); | 1417 | spin_lock(&br->multicast_lock); |
1395 | if (!netif_running(br->dev) || | 1418 | if (!netif_running(br->dev) || |
1396 | (port && port->state == BR_STATE_DISABLED) || | 1419 | (port && port->state == BR_STATE_DISABLED)) |
1397 | timer_pending(&other_query->timer)) | ||
1398 | goto out; | 1420 | goto out; |
1399 | 1421 | ||
1400 | mdb = mlock_dereference(br->mdb, br); | 1422 | mdb = mlock_dereference(br->mdb, br); |
@@ -1402,6 +1424,31 @@ br_multicast_leave_group(struct net_bridge *br, | |||
1402 | if (!mp) | 1424 | if (!mp) |
1403 | goto out; | 1425 | goto out; |
1404 | 1426 | ||
1427 | if (port && (port->flags & BR_MULTICAST_FAST_LEAVE)) { | ||
1428 | struct net_bridge_port_group __rcu **pp; | ||
1429 | |||
1430 | for (pp = &mp->ports; | ||
1431 | (p = mlock_dereference(*pp, br)) != NULL; | ||
1432 | pp = &p->next) { | ||
1433 | if (p->port != port) | ||
1434 | continue; | ||
1435 | |||
1436 | rcu_assign_pointer(*pp, p->next); | ||
1437 | hlist_del_init(&p->mglist); | ||
1438 | del_timer(&p->timer); | ||
1439 | call_rcu_bh(&p->rcu, br_multicast_free_pg); | ||
1440 | br_mdb_notify(br->dev, port, group, RTM_DELMDB); | ||
1441 | |||
1442 | if (!mp->ports && !mp->mglist && | ||
1443 | netif_running(br->dev)) | ||
1444 | mod_timer(&mp->timer, jiffies); | ||
1445 | } | ||
1446 | goto out; | ||
1447 | } | ||
1448 | |||
1449 | if (timer_pending(&other_query->timer)) | ||
1450 | goto out; | ||
1451 | |||
1405 | if (br->multicast_querier) { | 1452 | if (br->multicast_querier) { |
1406 | __br_multicast_send_query(br, port, &mp->addr); | 1453 | __br_multicast_send_query(br, port, &mp->addr); |
1407 | 1454 | ||
@@ -1427,28 +1474,6 @@ br_multicast_leave_group(struct net_bridge *br, | |||
1427 | } | 1474 | } |
1428 | } | 1475 | } |
1429 | 1476 | ||
1430 | if (port && (port->flags & BR_MULTICAST_FAST_LEAVE)) { | ||
1431 | struct net_bridge_port_group __rcu **pp; | ||
1432 | |||
1433 | for (pp = &mp->ports; | ||
1434 | (p = mlock_dereference(*pp, br)) != NULL; | ||
1435 | pp = &p->next) { | ||
1436 | if (p->port != port) | ||
1437 | continue; | ||
1438 | |||
1439 | rcu_assign_pointer(*pp, p->next); | ||
1440 | hlist_del_init(&p->mglist); | ||
1441 | del_timer(&p->timer); | ||
1442 | call_rcu_bh(&p->rcu, br_multicast_free_pg); | ||
1443 | br_mdb_notify(br->dev, port, group, RTM_DELMDB); | ||
1444 | |||
1445 | if (!mp->ports && !mp->mglist && | ||
1446 | netif_running(br->dev)) | ||
1447 | mod_timer(&mp->timer, jiffies); | ||
1448 | } | ||
1449 | goto out; | ||
1450 | } | ||
1451 | |||
1452 | now = jiffies; | 1477 | now = jiffies; |
1453 | time = now + br->multicast_last_member_count * | 1478 | time = now + br->multicast_last_member_count * |
1454 | br->multicast_last_member_interval; | 1479 | br->multicast_last_member_interval; |
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index 364bdc98bd9b..4d74a0639c4c 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c | |||
@@ -112,6 +112,8 @@ static inline size_t br_port_info_size(void) | |||
112 | + nla_total_size(1) /* IFLA_BRPORT_FAST_LEAVE */ | 112 | + nla_total_size(1) /* IFLA_BRPORT_FAST_LEAVE */ |
113 | + nla_total_size(1) /* IFLA_BRPORT_LEARNING */ | 113 | + nla_total_size(1) /* IFLA_BRPORT_LEARNING */ |
114 | + nla_total_size(1) /* IFLA_BRPORT_UNICAST_FLOOD */ | 114 | + nla_total_size(1) /* IFLA_BRPORT_UNICAST_FLOOD */ |
115 | + nla_total_size(1) /* IFLA_BRPORT_PROXYARP */ | ||
116 | + nla_total_size(1) /* IFLA_BRPORT_PROXYARP_WIFI */ | ||
115 | + 0; | 117 | + 0; |
116 | } | 118 | } |
117 | 119 | ||
@@ -506,6 +508,8 @@ static const struct nla_policy br_port_policy[IFLA_BRPORT_MAX + 1] = { | |||
506 | [IFLA_BRPORT_FAST_LEAVE]= { .type = NLA_U8 }, | 508 | [IFLA_BRPORT_FAST_LEAVE]= { .type = NLA_U8 }, |
507 | [IFLA_BRPORT_LEARNING] = { .type = NLA_U8 }, | 509 | [IFLA_BRPORT_LEARNING] = { .type = NLA_U8 }, |
508 | [IFLA_BRPORT_UNICAST_FLOOD] = { .type = NLA_U8 }, | 510 | [IFLA_BRPORT_UNICAST_FLOOD] = { .type = NLA_U8 }, |
511 | [IFLA_BRPORT_PROXYARP] = { .type = NLA_U8 }, | ||
512 | [IFLA_BRPORT_PROXYARP_WIFI] = { .type = NLA_U8 }, | ||
509 | }; | 513 | }; |
510 | 514 | ||
511 | /* Change the state of the port and notify spanning tree */ | 515 | /* Change the state of the port and notify spanning tree */ |
@@ -693,9 +697,17 @@ static int br_port_slave_changelink(struct net_device *brdev, | |||
693 | struct nlattr *tb[], | 697 | struct nlattr *tb[], |
694 | struct nlattr *data[]) | 698 | struct nlattr *data[]) |
695 | { | 699 | { |
700 | struct net_bridge *br = netdev_priv(brdev); | ||
701 | int ret; | ||
702 | |||
696 | if (!data) | 703 | if (!data) |
697 | return 0; | 704 | return 0; |
698 | return br_setport(br_port_get_rtnl(dev), data); | 705 | |
706 | spin_lock_bh(&br->lock); | ||
707 | ret = br_setport(br_port_get_rtnl(dev), data); | ||
708 | spin_unlock_bh(&br->lock); | ||
709 | |||
710 | return ret; | ||
699 | } | 711 | } |
700 | 712 | ||
701 | static int br_port_fill_slave_info(struct sk_buff *skb, | 713 | static int br_port_fill_slave_info(struct sk_buff *skb, |
diff --git a/net/bridge/br_stp.c b/net/bridge/br_stp.c index b4b6dab9c285..ed74ffaa851f 100644 --- a/net/bridge/br_stp.c +++ b/net/bridge/br_stp.c | |||
@@ -209,8 +209,9 @@ void br_transmit_config(struct net_bridge_port *p) | |||
209 | br_send_config_bpdu(p, &bpdu); | 209 | br_send_config_bpdu(p, &bpdu); |
210 | p->topology_change_ack = 0; | 210 | p->topology_change_ack = 0; |
211 | p->config_pending = 0; | 211 | p->config_pending = 0; |
212 | mod_timer(&p->hold_timer, | 212 | if (p->br->stp_enabled == BR_KERNEL_STP) |
213 | round_jiffies(jiffies + BR_HOLD_TIME)); | 213 | mod_timer(&p->hold_timer, |
214 | round_jiffies(jiffies + BR_HOLD_TIME)); | ||
214 | } | 215 | } |
215 | } | 216 | } |
216 | 217 | ||
diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c index a2730e7196cd..4ca449a16132 100644 --- a/net/bridge/br_stp_if.c +++ b/net/bridge/br_stp_if.c | |||
@@ -48,7 +48,8 @@ void br_stp_enable_bridge(struct net_bridge *br) | |||
48 | struct net_bridge_port *p; | 48 | struct net_bridge_port *p; |
49 | 49 | ||
50 | spin_lock_bh(&br->lock); | 50 | spin_lock_bh(&br->lock); |
51 | mod_timer(&br->hello_timer, jiffies + br->hello_time); | 51 | if (br->stp_enabled == BR_KERNEL_STP) |
52 | mod_timer(&br->hello_timer, jiffies + br->hello_time); | ||
52 | mod_timer(&br->gc_timer, jiffies + HZ/10); | 53 | mod_timer(&br->gc_timer, jiffies + HZ/10); |
53 | 54 | ||
54 | br_config_bpdu_generation(br); | 55 | br_config_bpdu_generation(br); |
@@ -127,6 +128,7 @@ static void br_stp_start(struct net_bridge *br) | |||
127 | int r; | 128 | int r; |
128 | char *argv[] = { BR_STP_PROG, br->dev->name, "start", NULL }; | 129 | char *argv[] = { BR_STP_PROG, br->dev->name, "start", NULL }; |
129 | char *envp[] = { NULL }; | 130 | char *envp[] = { NULL }; |
131 | struct net_bridge_port *p; | ||
130 | 132 | ||
131 | r = call_usermodehelper(BR_STP_PROG, argv, envp, UMH_WAIT_PROC); | 133 | r = call_usermodehelper(BR_STP_PROG, argv, envp, UMH_WAIT_PROC); |
132 | 134 | ||
@@ -140,6 +142,10 @@ static void br_stp_start(struct net_bridge *br) | |||
140 | if (r == 0) { | 142 | if (r == 0) { |
141 | br->stp_enabled = BR_USER_STP; | 143 | br->stp_enabled = BR_USER_STP; |
142 | br_debug(br, "userspace STP started\n"); | 144 | br_debug(br, "userspace STP started\n"); |
145 | /* Stop hello and hold timers */ | ||
146 | del_timer(&br->hello_timer); | ||
147 | list_for_each_entry(p, &br->port_list, list) | ||
148 | del_timer(&p->hold_timer); | ||
143 | } else { | 149 | } else { |
144 | br->stp_enabled = BR_KERNEL_STP; | 150 | br->stp_enabled = BR_KERNEL_STP; |
145 | br_debug(br, "using kernel STP\n"); | 151 | br_debug(br, "using kernel STP\n"); |
@@ -156,12 +162,17 @@ static void br_stp_stop(struct net_bridge *br) | |||
156 | int r; | 162 | int r; |
157 | char *argv[] = { BR_STP_PROG, br->dev->name, "stop", NULL }; | 163 | char *argv[] = { BR_STP_PROG, br->dev->name, "stop", NULL }; |
158 | char *envp[] = { NULL }; | 164 | char *envp[] = { NULL }; |
165 | struct net_bridge_port *p; | ||
159 | 166 | ||
160 | if (br->stp_enabled == BR_USER_STP) { | 167 | if (br->stp_enabled == BR_USER_STP) { |
161 | r = call_usermodehelper(BR_STP_PROG, argv, envp, UMH_WAIT_PROC); | 168 | r = call_usermodehelper(BR_STP_PROG, argv, envp, UMH_WAIT_PROC); |
162 | br_info(br, "userspace STP stopped, return code %d\n", r); | 169 | br_info(br, "userspace STP stopped, return code %d\n", r); |
163 | 170 | ||
164 | /* To start timers on any ports left in blocking */ | 171 | /* To start timers on any ports left in blocking */ |
172 | mod_timer(&br->hello_timer, jiffies + br->hello_time); | ||
173 | list_for_each_entry(p, &br->port_list, list) | ||
174 | mod_timer(&p->hold_timer, | ||
175 | round_jiffies(jiffies + BR_HOLD_TIME)); | ||
165 | spin_lock_bh(&br->lock); | 176 | spin_lock_bh(&br->lock); |
166 | br_port_state_selection(br); | 177 | br_port_state_selection(br); |
167 | spin_unlock_bh(&br->lock); | 178 | spin_unlock_bh(&br->lock); |
diff --git a/net/bridge/br_stp_timer.c b/net/bridge/br_stp_timer.c index 7caf7fae2d5b..5f0f5af0ec35 100644 --- a/net/bridge/br_stp_timer.c +++ b/net/bridge/br_stp_timer.c | |||
@@ -40,7 +40,9 @@ static void br_hello_timer_expired(unsigned long arg) | |||
40 | if (br->dev->flags & IFF_UP) { | 40 | if (br->dev->flags & IFF_UP) { |
41 | br_config_bpdu_generation(br); | 41 | br_config_bpdu_generation(br); |
42 | 42 | ||
43 | mod_timer(&br->hello_timer, round_jiffies(jiffies + br->hello_time)); | 43 | if (br->stp_enabled != BR_USER_STP) |
44 | mod_timer(&br->hello_timer, | ||
45 | round_jiffies(jiffies + br->hello_time)); | ||
44 | } | 46 | } |
45 | spin_unlock(&br->lock); | 47 | spin_unlock(&br->lock); |
46 | } | 48 | } |
diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c index 3cc71b9f5517..cc858919108e 100644 --- a/net/caif/caif_socket.c +++ b/net/caif/caif_socket.c | |||
@@ -121,12 +121,13 @@ static void caif_flow_ctrl(struct sock *sk, int mode) | |||
121 | * Copied from sock.c:sock_queue_rcv_skb(), but changed so packets are | 121 | * Copied from sock.c:sock_queue_rcv_skb(), but changed so packets are |
122 | * not dropped, but CAIF is sending flow off instead. | 122 | * not dropped, but CAIF is sending flow off instead. |
123 | */ | 123 | */ |
124 | static int caif_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) | 124 | static void caif_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) |
125 | { | 125 | { |
126 | int err; | 126 | int err; |
127 | unsigned long flags; | 127 | unsigned long flags; |
128 | struct sk_buff_head *list = &sk->sk_receive_queue; | 128 | struct sk_buff_head *list = &sk->sk_receive_queue; |
129 | struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); | 129 | struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); |
130 | bool queued = false; | ||
130 | 131 | ||
131 | if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >= | 132 | if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >= |
132 | (unsigned int)sk->sk_rcvbuf && rx_flow_is_on(cf_sk)) { | 133 | (unsigned int)sk->sk_rcvbuf && rx_flow_is_on(cf_sk)) { |
@@ -139,7 +140,8 @@ static int caif_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
139 | 140 | ||
140 | err = sk_filter(sk, skb); | 141 | err = sk_filter(sk, skb); |
141 | if (err) | 142 | if (err) |
142 | return err; | 143 | goto out; |
144 | |||
143 | if (!sk_rmem_schedule(sk, skb, skb->truesize) && rx_flow_is_on(cf_sk)) { | 145 | if (!sk_rmem_schedule(sk, skb, skb->truesize) && rx_flow_is_on(cf_sk)) { |
144 | set_rx_flow_off(cf_sk); | 146 | set_rx_flow_off(cf_sk); |
145 | net_dbg_ratelimited("sending flow OFF due to rmem_schedule\n"); | 147 | net_dbg_ratelimited("sending flow OFF due to rmem_schedule\n"); |
@@ -147,21 +149,16 @@ static int caif_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
147 | } | 149 | } |
148 | skb->dev = NULL; | 150 | skb->dev = NULL; |
149 | skb_set_owner_r(skb, sk); | 151 | skb_set_owner_r(skb, sk); |
150 | /* Cache the SKB length before we tack it onto the receive | ||
151 | * queue. Once it is added it no longer belongs to us and | ||
152 | * may be freed by other threads of control pulling packets | ||
153 | * from the queue. | ||
154 | */ | ||
155 | spin_lock_irqsave(&list->lock, flags); | 152 | spin_lock_irqsave(&list->lock, flags); |
156 | if (!sock_flag(sk, SOCK_DEAD)) | 153 | queued = !sock_flag(sk, SOCK_DEAD); |
154 | if (queued) | ||
157 | __skb_queue_tail(list, skb); | 155 | __skb_queue_tail(list, skb); |
158 | spin_unlock_irqrestore(&list->lock, flags); | 156 | spin_unlock_irqrestore(&list->lock, flags); |
159 | 157 | out: | |
160 | if (!sock_flag(sk, SOCK_DEAD)) | 158 | if (queued) |
161 | sk->sk_data_ready(sk); | 159 | sk->sk_data_ready(sk); |
162 | else | 160 | else |
163 | kfree_skb(skb); | 161 | kfree_skb(skb); |
164 | return 0; | ||
165 | } | 162 | } |
166 | 163 | ||
167 | /* Packet Receive Callback function called from CAIF Stack */ | 164 | /* Packet Receive Callback function called from CAIF Stack */ |
diff --git a/net/core/datagram.c b/net/core/datagram.c index b80fb91bb3f7..617088aee21d 100644 --- a/net/core/datagram.c +++ b/net/core/datagram.c | |||
@@ -131,6 +131,35 @@ out_noerr: | |||
131 | goto out; | 131 | goto out; |
132 | } | 132 | } |
133 | 133 | ||
134 | static struct sk_buff *skb_set_peeked(struct sk_buff *skb) | ||
135 | { | ||
136 | struct sk_buff *nskb; | ||
137 | |||
138 | if (skb->peeked) | ||
139 | return skb; | ||
140 | |||
141 | /* We have to unshare an skb before modifying it. */ | ||
142 | if (!skb_shared(skb)) | ||
143 | goto done; | ||
144 | |||
145 | nskb = skb_clone(skb, GFP_ATOMIC); | ||
146 | if (!nskb) | ||
147 | return ERR_PTR(-ENOMEM); | ||
148 | |||
149 | skb->prev->next = nskb; | ||
150 | skb->next->prev = nskb; | ||
151 | nskb->prev = skb->prev; | ||
152 | nskb->next = skb->next; | ||
153 | |||
154 | consume_skb(skb); | ||
155 | skb = nskb; | ||
156 | |||
157 | done: | ||
158 | skb->peeked = 1; | ||
159 | |||
160 | return skb; | ||
161 | } | ||
162 | |||
134 | /** | 163 | /** |
135 | * __skb_recv_datagram - Receive a datagram skbuff | 164 | * __skb_recv_datagram - Receive a datagram skbuff |
136 | * @sk: socket | 165 | * @sk: socket |
@@ -165,7 +194,9 @@ out_noerr: | |||
165 | struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned int flags, | 194 | struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned int flags, |
166 | int *peeked, int *off, int *err) | 195 | int *peeked, int *off, int *err) |
167 | { | 196 | { |
197 | struct sk_buff_head *queue = &sk->sk_receive_queue; | ||
168 | struct sk_buff *skb, *last; | 198 | struct sk_buff *skb, *last; |
199 | unsigned long cpu_flags; | ||
169 | long timeo; | 200 | long timeo; |
170 | /* | 201 | /* |
171 | * Caller is allowed not to check sk->sk_err before skb_recv_datagram() | 202 | * Caller is allowed not to check sk->sk_err before skb_recv_datagram() |
@@ -184,8 +215,6 @@ struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned int flags, | |||
184 | * Look at current nfs client by the way... | 215 | * Look at current nfs client by the way... |
185 | * However, this function was correct in any case. 8) | 216 | * However, this function was correct in any case. 8) |
186 | */ | 217 | */ |
187 | unsigned long cpu_flags; | ||
188 | struct sk_buff_head *queue = &sk->sk_receive_queue; | ||
189 | int _off = *off; | 218 | int _off = *off; |
190 | 219 | ||
191 | last = (struct sk_buff *)queue; | 220 | last = (struct sk_buff *)queue; |
@@ -199,7 +228,12 @@ struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned int flags, | |||
199 | _off -= skb->len; | 228 | _off -= skb->len; |
200 | continue; | 229 | continue; |
201 | } | 230 | } |
202 | skb->peeked = 1; | 231 | |
232 | skb = skb_set_peeked(skb); | ||
233 | error = PTR_ERR(skb); | ||
234 | if (IS_ERR(skb)) | ||
235 | goto unlock_err; | ||
236 | |||
203 | atomic_inc(&skb->users); | 237 | atomic_inc(&skb->users); |
204 | } else | 238 | } else |
205 | __skb_unlink(skb, queue); | 239 | __skb_unlink(skb, queue); |
@@ -223,6 +257,8 @@ struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned int flags, | |||
223 | 257 | ||
224 | return NULL; | 258 | return NULL; |
225 | 259 | ||
260 | unlock_err: | ||
261 | spin_unlock_irqrestore(&queue->lock, cpu_flags); | ||
226 | no_packet: | 262 | no_packet: |
227 | *err = error; | 263 | *err = error; |
228 | return NULL; | 264 | return NULL; |
@@ -622,7 +658,8 @@ __sum16 __skb_checksum_complete_head(struct sk_buff *skb, int len) | |||
622 | !skb->csum_complete_sw) | 658 | !skb->csum_complete_sw) |
623 | netdev_rx_csum_fault(skb->dev); | 659 | netdev_rx_csum_fault(skb->dev); |
624 | } | 660 | } |
625 | skb->csum_valid = !sum; | 661 | if (!skb_shared(skb)) |
662 | skb->csum_valid = !sum; | ||
626 | return sum; | 663 | return sum; |
627 | } | 664 | } |
628 | EXPORT_SYMBOL(__skb_checksum_complete_head); | 665 | EXPORT_SYMBOL(__skb_checksum_complete_head); |
@@ -642,11 +679,13 @@ __sum16 __skb_checksum_complete(struct sk_buff *skb) | |||
642 | netdev_rx_csum_fault(skb->dev); | 679 | netdev_rx_csum_fault(skb->dev); |
643 | } | 680 | } |
644 | 681 | ||
645 | /* Save full packet checksum */ | 682 | if (!skb_shared(skb)) { |
646 | skb->csum = csum; | 683 | /* Save full packet checksum */ |
647 | skb->ip_summed = CHECKSUM_COMPLETE; | 684 | skb->csum = csum; |
648 | skb->csum_complete_sw = 1; | 685 | skb->ip_summed = CHECKSUM_COMPLETE; |
649 | skb->csum_valid = !sum; | 686 | skb->csum_complete_sw = 1; |
687 | skb->csum_valid = !sum; | ||
688 | } | ||
650 | 689 | ||
651 | return sum; | 690 | return sum; |
652 | } | 691 | } |
diff --git a/net/core/dst.c b/net/core/dst.c index e956ce6d1378..002144bea935 100644 --- a/net/core/dst.c +++ b/net/core/dst.c | |||
@@ -284,7 +284,9 @@ void dst_release(struct dst_entry *dst) | |||
284 | int newrefcnt; | 284 | int newrefcnt; |
285 | 285 | ||
286 | newrefcnt = atomic_dec_return(&dst->__refcnt); | 286 | newrefcnt = atomic_dec_return(&dst->__refcnt); |
287 | WARN_ON(newrefcnt < 0); | 287 | if (unlikely(newrefcnt < 0)) |
288 | net_warn_ratelimited("%s: dst:%p refcnt:%d\n", | ||
289 | __func__, dst, newrefcnt); | ||
288 | if (unlikely(dst->flags & DST_NOCACHE) && !newrefcnt) | 290 | if (unlikely(dst->flags & DST_NOCACHE) && !newrefcnt) |
289 | call_rcu(&dst->rcu_head, dst_destroy_rcu); | 291 | call_rcu(&dst->rcu_head, dst_destroy_rcu); |
290 | } | 292 | } |
diff --git a/net/core/netclassid_cgroup.c b/net/core/netclassid_cgroup.c index 1f2a126f4ffa..6441f47b1a8f 100644 --- a/net/core/netclassid_cgroup.c +++ b/net/core/netclassid_cgroup.c | |||
@@ -23,7 +23,8 @@ static inline struct cgroup_cls_state *css_cls_state(struct cgroup_subsys_state | |||
23 | 23 | ||
24 | struct cgroup_cls_state *task_cls_state(struct task_struct *p) | 24 | struct cgroup_cls_state *task_cls_state(struct task_struct *p) |
25 | { | 25 | { |
26 | return css_cls_state(task_css(p, net_cls_cgrp_id)); | 26 | return css_cls_state(task_css_check(p, net_cls_cgrp_id, |
27 | rcu_read_lock_bh_held())); | ||
27 | } | 28 | } |
28 | EXPORT_SYMBOL_GPL(task_cls_state); | 29 | EXPORT_SYMBOL_GPL(task_cls_state); |
29 | 30 | ||
diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 1ebdf1c0d118..1cbd209192ea 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c | |||
@@ -3514,8 +3514,6 @@ static int pktgen_thread_worker(void *arg) | |||
3514 | 3514 | ||
3515 | set_freezable(); | 3515 | set_freezable(); |
3516 | 3516 | ||
3517 | __set_current_state(TASK_RUNNING); | ||
3518 | |||
3519 | while (!kthread_should_stop()) { | 3517 | while (!kthread_should_stop()) { |
3520 | pkt_dev = next_to_run(t); | 3518 | pkt_dev = next_to_run(t); |
3521 | 3519 | ||
@@ -3560,7 +3558,6 @@ static int pktgen_thread_worker(void *arg) | |||
3560 | 3558 | ||
3561 | try_to_freeze(); | 3559 | try_to_freeze(); |
3562 | } | 3560 | } |
3563 | set_current_state(TASK_INTERRUPTIBLE); | ||
3564 | 3561 | ||
3565 | pr_debug("%s stopping all device\n", t->tsk->comm); | 3562 | pr_debug("%s stopping all device\n", t->tsk->comm); |
3566 | pktgen_stop(t); | 3563 | pktgen_stop(t); |
diff --git a/net/core/request_sock.c b/net/core/request_sock.c index 87b22c0bc08c..b42f0e26f89e 100644 --- a/net/core/request_sock.c +++ b/net/core/request_sock.c | |||
@@ -103,10 +103,16 @@ void reqsk_queue_destroy(struct request_sock_queue *queue) | |||
103 | spin_lock_bh(&queue->syn_wait_lock); | 103 | spin_lock_bh(&queue->syn_wait_lock); |
104 | while ((req = lopt->syn_table[i]) != NULL) { | 104 | while ((req = lopt->syn_table[i]) != NULL) { |
105 | lopt->syn_table[i] = req->dl_next; | 105 | lopt->syn_table[i] = req->dl_next; |
106 | /* Because of following del_timer_sync(), | ||
107 | * we must release the spinlock here | ||
108 | * or risk a dead lock. | ||
109 | */ | ||
110 | spin_unlock_bh(&queue->syn_wait_lock); | ||
106 | atomic_inc(&lopt->qlen_dec); | 111 | atomic_inc(&lopt->qlen_dec); |
107 | if (del_timer(&req->rsk_timer)) | 112 | if (del_timer_sync(&req->rsk_timer)) |
108 | reqsk_put(req); | 113 | reqsk_put(req); |
109 | reqsk_put(req); | 114 | reqsk_put(req); |
115 | spin_lock_bh(&queue->syn_wait_lock); | ||
110 | } | 116 | } |
111 | spin_unlock_bh(&queue->syn_wait_lock); | 117 | spin_unlock_bh(&queue->syn_wait_lock); |
112 | } | 118 | } |
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 9e433d58d265..dc004b1e1f85 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -1804,10 +1804,13 @@ static int do_setlink(const struct sk_buff *skb, | |||
1804 | goto errout; | 1804 | goto errout; |
1805 | 1805 | ||
1806 | nla_for_each_nested(attr, tb[IFLA_VF_PORTS], rem) { | 1806 | nla_for_each_nested(attr, tb[IFLA_VF_PORTS], rem) { |
1807 | if (nla_type(attr) != IFLA_VF_PORT) | 1807 | if (nla_type(attr) != IFLA_VF_PORT || |
1808 | continue; | 1808 | nla_len(attr) < NLA_HDRLEN) { |
1809 | err = nla_parse_nested(port, IFLA_PORT_MAX, | 1809 | err = -EINVAL; |
1810 | attr, ifla_port_policy); | 1810 | goto errout; |
1811 | } | ||
1812 | err = nla_parse_nested(port, IFLA_PORT_MAX, attr, | ||
1813 | ifla_port_policy); | ||
1811 | if (err < 0) | 1814 | if (err < 0) |
1812 | goto errout; | 1815 | goto errout; |
1813 | if (!port[IFLA_PORT_VF]) { | 1816 | if (!port[IFLA_PORT_VF]) { |
diff --git a/net/core/sock.c b/net/core/sock.c index 08f16db46070..193901d09757 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -1497,7 +1497,8 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority) | |||
1497 | sock_copy(newsk, sk); | 1497 | sock_copy(newsk, sk); |
1498 | 1498 | ||
1499 | /* SANITY */ | 1499 | /* SANITY */ |
1500 | get_net(sock_net(newsk)); | 1500 | if (likely(newsk->sk_net_refcnt)) |
1501 | get_net(sock_net(newsk)); | ||
1501 | sk_node_init(&newsk->sk_node); | 1502 | sk_node_init(&newsk->sk_node); |
1502 | sock_lock_init(newsk); | 1503 | sock_lock_init(newsk); |
1503 | bh_lock_sock(newsk); | 1504 | bh_lock_sock(newsk); |
@@ -1967,20 +1968,21 @@ static void __release_sock(struct sock *sk) | |||
1967 | * sk_wait_data - wait for data to arrive at sk_receive_queue | 1968 | * sk_wait_data - wait for data to arrive at sk_receive_queue |
1968 | * @sk: sock to wait on | 1969 | * @sk: sock to wait on |
1969 | * @timeo: for how long | 1970 | * @timeo: for how long |
1971 | * @skb: last skb seen on sk_receive_queue | ||
1970 | * | 1972 | * |
1971 | * Now socket state including sk->sk_err is changed only under lock, | 1973 | * Now socket state including sk->sk_err is changed only under lock, |
1972 | * hence we may omit checks after joining wait queue. | 1974 | * hence we may omit checks after joining wait queue. |
1973 | * We check receive queue before schedule() only as optimization; | 1975 | * We check receive queue before schedule() only as optimization; |
1974 | * it is very likely that release_sock() added new data. | 1976 | * it is very likely that release_sock() added new data. |
1975 | */ | 1977 | */ |
1976 | int sk_wait_data(struct sock *sk, long *timeo) | 1978 | int sk_wait_data(struct sock *sk, long *timeo, const struct sk_buff *skb) |
1977 | { | 1979 | { |
1978 | int rc; | 1980 | int rc; |
1979 | DEFINE_WAIT(wait); | 1981 | DEFINE_WAIT(wait); |
1980 | 1982 | ||
1981 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); | 1983 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
1982 | set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); | 1984 | set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); |
1983 | rc = sk_wait_event(sk, timeo, !skb_queue_empty(&sk->sk_receive_queue)); | 1985 | rc = sk_wait_event(sk, timeo, skb_peek_tail(&sk->sk_receive_queue) != skb); |
1984 | clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); | 1986 | clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); |
1985 | finish_wait(sk_sleep(sk), &wait); | 1987 | finish_wait(sk_sleep(sk), &wait); |
1986 | return rc; | 1988 | return rc; |
diff --git a/net/dccp/proto.c b/net/dccp/proto.c index 52a94016526d..b5cf13a28009 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c | |||
@@ -886,7 +886,7 @@ verify_sock_status: | |||
886 | break; | 886 | break; |
887 | } | 887 | } |
888 | 888 | ||
889 | sk_wait_data(sk, &timeo); | 889 | sk_wait_data(sk, &timeo, NULL); |
890 | continue; | 890 | continue; |
891 | found_ok_skb: | 891 | found_ok_skb: |
892 | if (len > skb->len) | 892 | if (len > skb->len) |
diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 0917123790ea..35c47ddd04f0 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c | |||
@@ -756,7 +756,8 @@ static int dsa_slave_phy_connect(struct dsa_slave_priv *p, | |||
756 | return -ENODEV; | 756 | return -ENODEV; |
757 | 757 | ||
758 | /* Use already configured phy mode */ | 758 | /* Use already configured phy mode */ |
759 | p->phy_interface = p->phy->interface; | 759 | if (p->phy_interface == PHY_INTERFACE_MODE_NA) |
760 | p->phy_interface = p->phy->interface; | ||
760 | phy_connect_direct(slave_dev, p->phy, dsa_slave_adjust_link, | 761 | phy_connect_direct(slave_dev, p->phy, dsa_slave_adjust_link, |
761 | p->phy_interface); | 762 | p->phy_interface); |
762 | 763 | ||
diff --git a/net/ieee802154/6lowpan/reassembly.c b/net/ieee802154/6lowpan/reassembly.c index f46e4d1306f2..214d44aef35b 100644 --- a/net/ieee802154/6lowpan/reassembly.c +++ b/net/ieee802154/6lowpan/reassembly.c | |||
@@ -207,7 +207,7 @@ found: | |||
207 | } else { | 207 | } else { |
208 | fq->q.meat += skb->len; | 208 | fq->q.meat += skb->len; |
209 | } | 209 | } |
210 | add_frag_mem_limit(&fq->q, skb->truesize); | 210 | add_frag_mem_limit(fq->q.net, skb->truesize); |
211 | 211 | ||
212 | if (fq->q.flags == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) && | 212 | if (fq->q.flags == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) && |
213 | fq->q.meat == fq->q.len) { | 213 | fq->q.meat == fq->q.len) { |
@@ -287,7 +287,7 @@ static int lowpan_frag_reasm(struct lowpan_frag_queue *fq, struct sk_buff *prev, | |||
287 | clone->data_len = clone->len; | 287 | clone->data_len = clone->len; |
288 | head->data_len -= clone->len; | 288 | head->data_len -= clone->len; |
289 | head->len -= clone->len; | 289 | head->len -= clone->len; |
290 | add_frag_mem_limit(&fq->q, clone->truesize); | 290 | add_frag_mem_limit(fq->q.net, clone->truesize); |
291 | } | 291 | } |
292 | 292 | ||
293 | WARN_ON(head == NULL); | 293 | WARN_ON(head == NULL); |
@@ -310,7 +310,7 @@ static int lowpan_frag_reasm(struct lowpan_frag_queue *fq, struct sk_buff *prev, | |||
310 | } | 310 | } |
311 | fp = next; | 311 | fp = next; |
312 | } | 312 | } |
313 | sub_frag_mem_limit(&fq->q, sum_truesize); | 313 | sub_frag_mem_limit(fq->q.net, sum_truesize); |
314 | 314 | ||
315 | head->next = NULL; | 315 | head->next = NULL; |
316 | head->dev = dev; | 316 | head->dev = dev; |
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index 933a92820d26..6c8b1fbafce8 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c | |||
@@ -1017,14 +1017,16 @@ static int arp_req_get(struct arpreq *r, struct net_device *dev) | |||
1017 | 1017 | ||
1018 | neigh = neigh_lookup(&arp_tbl, &ip, dev); | 1018 | neigh = neigh_lookup(&arp_tbl, &ip, dev); |
1019 | if (neigh) { | 1019 | if (neigh) { |
1020 | read_lock_bh(&neigh->lock); | 1020 | if (!(neigh->nud_state & NUD_NOARP)) { |
1021 | memcpy(r->arp_ha.sa_data, neigh->ha, dev->addr_len); | 1021 | read_lock_bh(&neigh->lock); |
1022 | r->arp_flags = arp_state_to_flags(neigh); | 1022 | memcpy(r->arp_ha.sa_data, neigh->ha, dev->addr_len); |
1023 | read_unlock_bh(&neigh->lock); | 1023 | r->arp_flags = arp_state_to_flags(neigh); |
1024 | r->arp_ha.sa_family = dev->type; | 1024 | read_unlock_bh(&neigh->lock); |
1025 | strlcpy(r->arp_dev, dev->name, sizeof(r->arp_dev)); | 1025 | r->arp_ha.sa_family = dev->type; |
1026 | strlcpy(r->arp_dev, dev->name, sizeof(r->arp_dev)); | ||
1027 | err = 0; | ||
1028 | } | ||
1026 | neigh_release(neigh); | 1029 | neigh_release(neigh); |
1027 | err = 0; | ||
1028 | } | 1030 | } |
1029 | return err; | 1031 | return err; |
1030 | } | 1032 | } |
diff --git a/net/ipv4/datagram.c b/net/ipv4/datagram.c index 90c0e8386116..574fad9cca05 100644 --- a/net/ipv4/datagram.c +++ b/net/ipv4/datagram.c | |||
@@ -20,7 +20,7 @@ | |||
20 | #include <net/route.h> | 20 | #include <net/route.h> |
21 | #include <net/tcp_states.h> | 21 | #include <net/tcp_states.h> |
22 | 22 | ||
23 | int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | 23 | int __ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) |
24 | { | 24 | { |
25 | struct inet_sock *inet = inet_sk(sk); | 25 | struct inet_sock *inet = inet_sk(sk); |
26 | struct sockaddr_in *usin = (struct sockaddr_in *) uaddr; | 26 | struct sockaddr_in *usin = (struct sockaddr_in *) uaddr; |
@@ -39,8 +39,6 @@ int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
39 | 39 | ||
40 | sk_dst_reset(sk); | 40 | sk_dst_reset(sk); |
41 | 41 | ||
42 | lock_sock(sk); | ||
43 | |||
44 | oif = sk->sk_bound_dev_if; | 42 | oif = sk->sk_bound_dev_if; |
45 | saddr = inet->inet_saddr; | 43 | saddr = inet->inet_saddr; |
46 | if (ipv4_is_multicast(usin->sin_addr.s_addr)) { | 44 | if (ipv4_is_multicast(usin->sin_addr.s_addr)) { |
@@ -82,9 +80,19 @@ int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
82 | sk_dst_set(sk, &rt->dst); | 80 | sk_dst_set(sk, &rt->dst); |
83 | err = 0; | 81 | err = 0; |
84 | out: | 82 | out: |
85 | release_sock(sk); | ||
86 | return err; | 83 | return err; |
87 | } | 84 | } |
85 | EXPORT_SYMBOL(__ip4_datagram_connect); | ||
86 | |||
87 | int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | ||
88 | { | ||
89 | int res; | ||
90 | |||
91 | lock_sock(sk); | ||
92 | res = __ip4_datagram_connect(sk, uaddr, addr_len); | ||
93 | release_sock(sk); | ||
94 | return res; | ||
95 | } | ||
88 | EXPORT_SYMBOL(ip4_datagram_connect); | 96 | EXPORT_SYMBOL(ip4_datagram_connect); |
89 | 97 | ||
90 | /* Because UDP xmit path can manipulate sk_dst_cache without holding | 98 | /* Because UDP xmit path can manipulate sk_dst_cache without holding |
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index e813196c91c7..2d9cb1748f81 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c | |||
@@ -882,7 +882,6 @@ static int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
882 | queue_delayed_work(system_power_efficient_wq, | 882 | queue_delayed_work(system_power_efficient_wq, |
883 | &check_lifetime_work, 0); | 883 | &check_lifetime_work, 0); |
884 | rtmsg_ifa(RTM_NEWADDR, ifa, nlh, NETLINK_CB(skb).portid); | 884 | rtmsg_ifa(RTM_NEWADDR, ifa, nlh, NETLINK_CB(skb).portid); |
885 | blocking_notifier_call_chain(&inetaddr_chain, NETDEV_UP, ifa); | ||
886 | } | 885 | } |
887 | return 0; | 886 | return 0; |
888 | } | 887 | } |
diff --git a/net/ipv4/fib_lookup.h b/net/ipv4/fib_lookup.h index c6211ed60b03..9c02920725db 100644 --- a/net/ipv4/fib_lookup.h +++ b/net/ipv4/fib_lookup.h | |||
@@ -13,6 +13,7 @@ struct fib_alias { | |||
13 | u8 fa_state; | 13 | u8 fa_state; |
14 | u8 fa_slen; | 14 | u8 fa_slen; |
15 | u32 tb_id; | 15 | u32 tb_id; |
16 | s16 fa_default; | ||
16 | struct rcu_head rcu; | 17 | struct rcu_head rcu; |
17 | }; | 18 | }; |
18 | 19 | ||
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index c7358ea4ae93..3a06586b170c 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c | |||
@@ -1202,23 +1202,40 @@ int fib_sync_down_dev(struct net_device *dev, unsigned long event) | |||
1202 | } | 1202 | } |
1203 | 1203 | ||
1204 | /* Must be invoked inside of an RCU protected region. */ | 1204 | /* Must be invoked inside of an RCU protected region. */ |
1205 | void fib_select_default(struct fib_result *res) | 1205 | void fib_select_default(const struct flowi4 *flp, struct fib_result *res) |
1206 | { | 1206 | { |
1207 | struct fib_info *fi = NULL, *last_resort = NULL; | 1207 | struct fib_info *fi = NULL, *last_resort = NULL; |
1208 | struct hlist_head *fa_head = res->fa_head; | 1208 | struct hlist_head *fa_head = res->fa_head; |
1209 | struct fib_table *tb = res->table; | 1209 | struct fib_table *tb = res->table; |
1210 | u8 slen = 32 - res->prefixlen; | ||
1210 | int order = -1, last_idx = -1; | 1211 | int order = -1, last_idx = -1; |
1211 | struct fib_alias *fa; | 1212 | struct fib_alias *fa, *fa1 = NULL; |
1213 | u32 last_prio = res->fi->fib_priority; | ||
1214 | u8 last_tos = 0; | ||
1212 | 1215 | ||
1213 | hlist_for_each_entry_rcu(fa, fa_head, fa_list) { | 1216 | hlist_for_each_entry_rcu(fa, fa_head, fa_list) { |
1214 | struct fib_info *next_fi = fa->fa_info; | 1217 | struct fib_info *next_fi = fa->fa_info; |
1215 | 1218 | ||
1219 | if (fa->fa_slen != slen) | ||
1220 | continue; | ||
1221 | if (fa->fa_tos && fa->fa_tos != flp->flowi4_tos) | ||
1222 | continue; | ||
1223 | if (fa->tb_id != tb->tb_id) | ||
1224 | continue; | ||
1225 | if (next_fi->fib_priority > last_prio && | ||
1226 | fa->fa_tos == last_tos) { | ||
1227 | if (last_tos) | ||
1228 | continue; | ||
1229 | break; | ||
1230 | } | ||
1231 | if (next_fi->fib_flags & RTNH_F_DEAD) | ||
1232 | continue; | ||
1233 | last_tos = fa->fa_tos; | ||
1234 | last_prio = next_fi->fib_priority; | ||
1235 | |||
1216 | if (next_fi->fib_scope != res->scope || | 1236 | if (next_fi->fib_scope != res->scope || |
1217 | fa->fa_type != RTN_UNICAST) | 1237 | fa->fa_type != RTN_UNICAST) |
1218 | continue; | 1238 | continue; |
1219 | |||
1220 | if (next_fi->fib_priority > res->fi->fib_priority) | ||
1221 | break; | ||
1222 | if (!next_fi->fib_nh[0].nh_gw || | 1239 | if (!next_fi->fib_nh[0].nh_gw || |
1223 | next_fi->fib_nh[0].nh_scope != RT_SCOPE_LINK) | 1240 | next_fi->fib_nh[0].nh_scope != RT_SCOPE_LINK) |
1224 | continue; | 1241 | continue; |
@@ -1228,10 +1245,11 @@ void fib_select_default(struct fib_result *res) | |||
1228 | if (!fi) { | 1245 | if (!fi) { |
1229 | if (next_fi != res->fi) | 1246 | if (next_fi != res->fi) |
1230 | break; | 1247 | break; |
1248 | fa1 = fa; | ||
1231 | } else if (!fib_detect_death(fi, order, &last_resort, | 1249 | } else if (!fib_detect_death(fi, order, &last_resort, |
1232 | &last_idx, tb->tb_default)) { | 1250 | &last_idx, fa1->fa_default)) { |
1233 | fib_result_assign(res, fi); | 1251 | fib_result_assign(res, fi); |
1234 | tb->tb_default = order; | 1252 | fa1->fa_default = order; |
1235 | goto out; | 1253 | goto out; |
1236 | } | 1254 | } |
1237 | fi = next_fi; | 1255 | fi = next_fi; |
@@ -1239,20 +1257,21 @@ void fib_select_default(struct fib_result *res) | |||
1239 | } | 1257 | } |
1240 | 1258 | ||
1241 | if (order <= 0 || !fi) { | 1259 | if (order <= 0 || !fi) { |
1242 | tb->tb_default = -1; | 1260 | if (fa1) |
1261 | fa1->fa_default = -1; | ||
1243 | goto out; | 1262 | goto out; |
1244 | } | 1263 | } |
1245 | 1264 | ||
1246 | if (!fib_detect_death(fi, order, &last_resort, &last_idx, | 1265 | if (!fib_detect_death(fi, order, &last_resort, &last_idx, |
1247 | tb->tb_default)) { | 1266 | fa1->fa_default)) { |
1248 | fib_result_assign(res, fi); | 1267 | fib_result_assign(res, fi); |
1249 | tb->tb_default = order; | 1268 | fa1->fa_default = order; |
1250 | goto out; | 1269 | goto out; |
1251 | } | 1270 | } |
1252 | 1271 | ||
1253 | if (last_idx >= 0) | 1272 | if (last_idx >= 0) |
1254 | fib_result_assign(res, last_resort); | 1273 | fib_result_assign(res, last_resort); |
1255 | tb->tb_default = last_idx; | 1274 | fa1->fa_default = last_idx; |
1256 | out: | 1275 | out: |
1257 | return; | 1276 | return; |
1258 | } | 1277 | } |
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index 15d32612e3c6..37c4bb89a708 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c | |||
@@ -1171,6 +1171,7 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg) | |||
1171 | new_fa->fa_state = state & ~FA_S_ACCESSED; | 1171 | new_fa->fa_state = state & ~FA_S_ACCESSED; |
1172 | new_fa->fa_slen = fa->fa_slen; | 1172 | new_fa->fa_slen = fa->fa_slen; |
1173 | new_fa->tb_id = tb->tb_id; | 1173 | new_fa->tb_id = tb->tb_id; |
1174 | new_fa->fa_default = -1; | ||
1174 | 1175 | ||
1175 | err = switchdev_fib_ipv4_add(key, plen, fi, | 1176 | err = switchdev_fib_ipv4_add(key, plen, fi, |
1176 | new_fa->fa_tos, | 1177 | new_fa->fa_tos, |
@@ -1222,6 +1223,7 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg) | |||
1222 | new_fa->fa_state = 0; | 1223 | new_fa->fa_state = 0; |
1223 | new_fa->fa_slen = slen; | 1224 | new_fa->fa_slen = slen; |
1224 | new_fa->tb_id = tb->tb_id; | 1225 | new_fa->tb_id = tb->tb_id; |
1226 | new_fa->fa_default = -1; | ||
1225 | 1227 | ||
1226 | /* (Optionally) offload fib entry to switch hardware. */ | 1228 | /* (Optionally) offload fib entry to switch hardware. */ |
1227 | err = switchdev_fib_ipv4_add(key, plen, fi, tos, cfg->fc_type, | 1229 | err = switchdev_fib_ipv4_add(key, plen, fi, tos, cfg->fc_type, |
@@ -1791,8 +1793,6 @@ void fib_table_flush_external(struct fib_table *tb) | |||
1791 | if (hlist_empty(&n->leaf)) { | 1793 | if (hlist_empty(&n->leaf)) { |
1792 | put_child_root(pn, n->key, NULL); | 1794 | put_child_root(pn, n->key, NULL); |
1793 | node_free(n); | 1795 | node_free(n); |
1794 | } else { | ||
1795 | leaf_pull_suffix(pn, n); | ||
1796 | } | 1796 | } |
1797 | } | 1797 | } |
1798 | } | 1798 | } |
@@ -1862,8 +1862,6 @@ int fib_table_flush(struct fib_table *tb) | |||
1862 | if (hlist_empty(&n->leaf)) { | 1862 | if (hlist_empty(&n->leaf)) { |
1863 | put_child_root(pn, n->key, NULL); | 1863 | put_child_root(pn, n->key, NULL); |
1864 | node_free(n); | 1864 | node_free(n); |
1865 | } else { | ||
1866 | leaf_pull_suffix(pn, n); | ||
1867 | } | 1865 | } |
1868 | } | 1866 | } |
1869 | 1867 | ||
@@ -1990,7 +1988,6 @@ struct fib_table *fib_trie_table(u32 id, struct fib_table *alias) | |||
1990 | return NULL; | 1988 | return NULL; |
1991 | 1989 | ||
1992 | tb->tb_id = id; | 1990 | tb->tb_id = id; |
1993 | tb->tb_default = -1; | ||
1994 | tb->tb_num_default = 0; | 1991 | tb->tb_num_default = 0; |
1995 | tb->tb_data = (alias ? alias->__data : tb->__data); | 1992 | tb->tb_data = (alias ? alias->__data : tb->__data); |
1996 | 1993 | ||
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 60021d0d9326..05e3145f7dc3 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(&req->rsk_timer)) | 596 | if (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/inet_fragment.c b/net/ipv4/inet_fragment.c index 5e346a082e5f..d0a7c0319e3d 100644 --- a/net/ipv4/inet_fragment.c +++ b/net/ipv4/inet_fragment.c | |||
@@ -131,34 +131,22 @@ inet_evict_bucket(struct inet_frags *f, struct inet_frag_bucket *hb) | |||
131 | unsigned int evicted = 0; | 131 | unsigned int evicted = 0; |
132 | HLIST_HEAD(expired); | 132 | HLIST_HEAD(expired); |
133 | 133 | ||
134 | evict_again: | ||
135 | spin_lock(&hb->chain_lock); | 134 | spin_lock(&hb->chain_lock); |
136 | 135 | ||
137 | hlist_for_each_entry_safe(fq, n, &hb->chain, list) { | 136 | hlist_for_each_entry_safe(fq, n, &hb->chain, list) { |
138 | if (!inet_fragq_should_evict(fq)) | 137 | if (!inet_fragq_should_evict(fq)) |
139 | continue; | 138 | continue; |
140 | 139 | ||
141 | if (!del_timer(&fq->timer)) { | 140 | if (!del_timer(&fq->timer)) |
142 | /* q expiring right now thus increment its refcount so | 141 | continue; |
143 | * it won't be freed under us and wait until the timer | ||
144 | * has finished executing then destroy it | ||
145 | */ | ||
146 | atomic_inc(&fq->refcnt); | ||
147 | spin_unlock(&hb->chain_lock); | ||
148 | del_timer_sync(&fq->timer); | ||
149 | inet_frag_put(fq, f); | ||
150 | goto evict_again; | ||
151 | } | ||
152 | 142 | ||
153 | fq->flags |= INET_FRAG_EVICTED; | 143 | hlist_add_head(&fq->list_evictor, &expired); |
154 | hlist_del(&fq->list); | ||
155 | hlist_add_head(&fq->list, &expired); | ||
156 | ++evicted; | 144 | ++evicted; |
157 | } | 145 | } |
158 | 146 | ||
159 | spin_unlock(&hb->chain_lock); | 147 | spin_unlock(&hb->chain_lock); |
160 | 148 | ||
161 | hlist_for_each_entry_safe(fq, n, &expired, list) | 149 | hlist_for_each_entry_safe(fq, n, &expired, list_evictor) |
162 | f->frag_expire((unsigned long) fq); | 150 | f->frag_expire((unsigned long) fq); |
163 | 151 | ||
164 | return evicted; | 152 | return evicted; |
@@ -240,18 +228,20 @@ void inet_frags_exit_net(struct netns_frags *nf, struct inet_frags *f) | |||
240 | int i; | 228 | int i; |
241 | 229 | ||
242 | nf->low_thresh = 0; | 230 | nf->low_thresh = 0; |
243 | local_bh_disable(); | ||
244 | 231 | ||
245 | evict_again: | 232 | evict_again: |
233 | local_bh_disable(); | ||
246 | seq = read_seqbegin(&f->rnd_seqlock); | 234 | seq = read_seqbegin(&f->rnd_seqlock); |
247 | 235 | ||
248 | for (i = 0; i < INETFRAGS_HASHSZ ; i++) | 236 | for (i = 0; i < INETFRAGS_HASHSZ ; i++) |
249 | inet_evict_bucket(f, &f->hash[i]); | 237 | inet_evict_bucket(f, &f->hash[i]); |
250 | 238 | ||
251 | if (read_seqretry(&f->rnd_seqlock, seq)) | ||
252 | goto evict_again; | ||
253 | |||
254 | local_bh_enable(); | 239 | local_bh_enable(); |
240 | cond_resched(); | ||
241 | |||
242 | if (read_seqretry(&f->rnd_seqlock, seq) || | ||
243 | percpu_counter_sum(&nf->mem)) | ||
244 | goto evict_again; | ||
255 | 245 | ||
256 | percpu_counter_destroy(&nf->mem); | 246 | percpu_counter_destroy(&nf->mem); |
257 | } | 247 | } |
@@ -284,8 +274,8 @@ static inline void fq_unlink(struct inet_frag_queue *fq, struct inet_frags *f) | |||
284 | struct inet_frag_bucket *hb; | 274 | struct inet_frag_bucket *hb; |
285 | 275 | ||
286 | hb = get_frag_bucket_locked(fq, f); | 276 | hb = get_frag_bucket_locked(fq, f); |
287 | if (!(fq->flags & INET_FRAG_EVICTED)) | 277 | hlist_del(&fq->list); |
288 | hlist_del(&fq->list); | 278 | fq->flags |= INET_FRAG_COMPLETE; |
289 | spin_unlock(&hb->chain_lock); | 279 | spin_unlock(&hb->chain_lock); |
290 | } | 280 | } |
291 | 281 | ||
@@ -297,7 +287,6 @@ void inet_frag_kill(struct inet_frag_queue *fq, struct inet_frags *f) | |||
297 | if (!(fq->flags & INET_FRAG_COMPLETE)) { | 287 | if (!(fq->flags & INET_FRAG_COMPLETE)) { |
298 | fq_unlink(fq, f); | 288 | fq_unlink(fq, f); |
299 | atomic_dec(&fq->refcnt); | 289 | atomic_dec(&fq->refcnt); |
300 | fq->flags |= INET_FRAG_COMPLETE; | ||
301 | } | 290 | } |
302 | } | 291 | } |
303 | EXPORT_SYMBOL(inet_frag_kill); | 292 | EXPORT_SYMBOL(inet_frag_kill); |
@@ -330,11 +319,12 @@ void inet_frag_destroy(struct inet_frag_queue *q, struct inet_frags *f) | |||
330 | fp = xp; | 319 | fp = xp; |
331 | } | 320 | } |
332 | sum = sum_truesize + f->qsize; | 321 | sum = sum_truesize + f->qsize; |
333 | sub_frag_mem_limit(q, sum); | ||
334 | 322 | ||
335 | if (f->destructor) | 323 | if (f->destructor) |
336 | f->destructor(q); | 324 | f->destructor(q); |
337 | kmem_cache_free(f->frags_cachep, q); | 325 | kmem_cache_free(f->frags_cachep, q); |
326 | |||
327 | sub_frag_mem_limit(nf, sum); | ||
338 | } | 328 | } |
339 | EXPORT_SYMBOL(inet_frag_destroy); | 329 | EXPORT_SYMBOL(inet_frag_destroy); |
340 | 330 | ||
@@ -390,7 +380,7 @@ static struct inet_frag_queue *inet_frag_alloc(struct netns_frags *nf, | |||
390 | 380 | ||
391 | q->net = nf; | 381 | q->net = nf; |
392 | f->constructor(q, arg); | 382 | f->constructor(q, arg); |
393 | add_frag_mem_limit(q, f->qsize); | 383 | add_frag_mem_limit(nf, f->qsize); |
394 | 384 | ||
395 | setup_timer(&q->timer, f->frag_expire, (unsigned long)q); | 385 | setup_timer(&q->timer, f->frag_expire, (unsigned long)q); |
396 | spin_lock_init(&q->lock); | 386 | spin_lock_init(&q->lock); |
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c index 5f9b063bbe8a..0cb9165421d4 100644 --- a/net/ipv4/inet_hashtables.c +++ b/net/ipv4/inet_hashtables.c | |||
@@ -624,22 +624,21 @@ EXPORT_SYMBOL_GPL(inet_hashinfo_init); | |||
624 | 624 | ||
625 | int inet_ehash_locks_alloc(struct inet_hashinfo *hashinfo) | 625 | int inet_ehash_locks_alloc(struct inet_hashinfo *hashinfo) |
626 | { | 626 | { |
627 | unsigned int locksz = sizeof(spinlock_t); | ||
627 | unsigned int i, nblocks = 1; | 628 | unsigned int i, nblocks = 1; |
628 | 629 | ||
629 | if (sizeof(spinlock_t) != 0) { | 630 | if (locksz != 0) { |
630 | /* allocate 2 cache lines or at least one spinlock per cpu */ | 631 | /* allocate 2 cache lines or at least one spinlock per cpu */ |
631 | nblocks = max_t(unsigned int, | 632 | nblocks = max(2U * L1_CACHE_BYTES / locksz, 1U); |
632 | 2 * L1_CACHE_BYTES / sizeof(spinlock_t), | ||
633 | 1); | ||
634 | nblocks = roundup_pow_of_two(nblocks * num_possible_cpus()); | 633 | nblocks = roundup_pow_of_two(nblocks * num_possible_cpus()); |
635 | 634 | ||
636 | /* no more locks than number of hash buckets */ | 635 | /* no more locks than number of hash buckets */ |
637 | nblocks = min(nblocks, hashinfo->ehash_mask + 1); | 636 | nblocks = min(nblocks, hashinfo->ehash_mask + 1); |
638 | 637 | ||
639 | hashinfo->ehash_locks = kmalloc_array(nblocks, sizeof(spinlock_t), | 638 | hashinfo->ehash_locks = kmalloc_array(nblocks, locksz, |
640 | GFP_KERNEL | __GFP_NOWARN); | 639 | GFP_KERNEL | __GFP_NOWARN); |
641 | if (!hashinfo->ehash_locks) | 640 | if (!hashinfo->ehash_locks) |
642 | hashinfo->ehash_locks = vmalloc(nblocks * sizeof(spinlock_t)); | 641 | hashinfo->ehash_locks = vmalloc(nblocks * locksz); |
643 | 642 | ||
644 | if (!hashinfo->ehash_locks) | 643 | if (!hashinfo->ehash_locks) |
645 | return -ENOMEM; | 644 | return -ENOMEM; |
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index a50dc6d408d1..921138f6c97c 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c | |||
@@ -202,7 +202,7 @@ static void ip_expire(unsigned long arg) | |||
202 | ipq_kill(qp); | 202 | ipq_kill(qp); |
203 | IP_INC_STATS_BH(net, IPSTATS_MIB_REASMFAILS); | 203 | IP_INC_STATS_BH(net, IPSTATS_MIB_REASMFAILS); |
204 | 204 | ||
205 | if (!(qp->q.flags & INET_FRAG_EVICTED)) { | 205 | if (!inet_frag_evicting(&qp->q)) { |
206 | struct sk_buff *head = qp->q.fragments; | 206 | struct sk_buff *head = qp->q.fragments; |
207 | const struct iphdr *iph; | 207 | const struct iphdr *iph; |
208 | int err; | 208 | int err; |
@@ -309,7 +309,7 @@ static int ip_frag_reinit(struct ipq *qp) | |||
309 | kfree_skb(fp); | 309 | kfree_skb(fp); |
310 | fp = xp; | 310 | fp = xp; |
311 | } while (fp); | 311 | } while (fp); |
312 | sub_frag_mem_limit(&qp->q, sum_truesize); | 312 | sub_frag_mem_limit(qp->q.net, sum_truesize); |
313 | 313 | ||
314 | qp->q.flags = 0; | 314 | qp->q.flags = 0; |
315 | qp->q.len = 0; | 315 | qp->q.len = 0; |
@@ -351,7 +351,7 @@ static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb) | |||
351 | ihl = ip_hdrlen(skb); | 351 | ihl = ip_hdrlen(skb); |
352 | 352 | ||
353 | /* Determine the position of this fragment. */ | 353 | /* Determine the position of this fragment. */ |
354 | end = offset + skb->len - ihl; | 354 | end = offset + skb->len - skb_network_offset(skb) - ihl; |
355 | err = -EINVAL; | 355 | err = -EINVAL; |
356 | 356 | ||
357 | /* Is this the final fragment? */ | 357 | /* Is this the final fragment? */ |
@@ -381,7 +381,7 @@ static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb) | |||
381 | goto err; | 381 | goto err; |
382 | 382 | ||
383 | err = -ENOMEM; | 383 | err = -ENOMEM; |
384 | if (!pskb_pull(skb, ihl)) | 384 | if (!pskb_pull(skb, skb_network_offset(skb) + ihl)) |
385 | goto err; | 385 | goto err; |
386 | 386 | ||
387 | err = pskb_trim_rcsum(skb, end - offset); | 387 | err = pskb_trim_rcsum(skb, end - offset); |
@@ -455,7 +455,7 @@ found: | |||
455 | qp->q.fragments = next; | 455 | qp->q.fragments = next; |
456 | 456 | ||
457 | qp->q.meat -= free_it->len; | 457 | qp->q.meat -= free_it->len; |
458 | sub_frag_mem_limit(&qp->q, free_it->truesize); | 458 | sub_frag_mem_limit(qp->q.net, free_it->truesize); |
459 | kfree_skb(free_it); | 459 | kfree_skb(free_it); |
460 | } | 460 | } |
461 | } | 461 | } |
@@ -479,7 +479,7 @@ found: | |||
479 | qp->q.stamp = skb->tstamp; | 479 | qp->q.stamp = skb->tstamp; |
480 | qp->q.meat += skb->len; | 480 | qp->q.meat += skb->len; |
481 | qp->ecn |= ecn; | 481 | qp->ecn |= ecn; |
482 | add_frag_mem_limit(&qp->q, skb->truesize); | 482 | add_frag_mem_limit(qp->q.net, skb->truesize); |
483 | if (offset == 0) | 483 | if (offset == 0) |
484 | qp->q.flags |= INET_FRAG_FIRST_IN; | 484 | qp->q.flags |= INET_FRAG_FIRST_IN; |
485 | 485 | ||
@@ -587,7 +587,7 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev, | |||
587 | head->len -= clone->len; | 587 | head->len -= clone->len; |
588 | clone->csum = 0; | 588 | clone->csum = 0; |
589 | clone->ip_summed = head->ip_summed; | 589 | clone->ip_summed = head->ip_summed; |
590 | add_frag_mem_limit(&qp->q, clone->truesize); | 590 | add_frag_mem_limit(qp->q.net, clone->truesize); |
591 | } | 591 | } |
592 | 592 | ||
593 | skb_push(head, head->data - skb_network_header(head)); | 593 | skb_push(head, head->data - skb_network_header(head)); |
@@ -615,7 +615,7 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev, | |||
615 | } | 615 | } |
616 | fp = next; | 616 | fp = next; |
617 | } | 617 | } |
618 | sub_frag_mem_limit(&qp->q, sum_truesize); | 618 | sub_frag_mem_limit(qp->q.net, sum_truesize); |
619 | 619 | ||
620 | head->next = NULL; | 620 | head->next = NULL; |
621 | head->dev = dev; | 621 | head->dev = dev; |
@@ -641,6 +641,8 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev, | |||
641 | iph->frag_off = 0; | 641 | iph->frag_off = 0; |
642 | } | 642 | } |
643 | 643 | ||
644 | ip_send_check(iph); | ||
645 | |||
644 | IP_INC_STATS_BH(net, IPSTATS_MIB_REASMOKS); | 646 | IP_INC_STATS_BH(net, IPSTATS_MIB_REASMOKS); |
645 | qp->q.fragments = NULL; | 647 | qp->q.fragments = NULL; |
646 | qp->q.fragments_tail = NULL; | 648 | qp->q.fragments_tail = NULL; |
diff --git a/net/ipv4/netfilter/ipt_SYNPROXY.c b/net/ipv4/netfilter/ipt_SYNPROXY.c index fe8cc183411e..95ea633e8356 100644 --- a/net/ipv4/netfilter/ipt_SYNPROXY.c +++ b/net/ipv4/netfilter/ipt_SYNPROXY.c | |||
@@ -226,7 +226,8 @@ synproxy_send_client_ack(const struct synproxy_net *snet, | |||
226 | 226 | ||
227 | synproxy_build_options(nth, opts); | 227 | synproxy_build_options(nth, opts); |
228 | 228 | ||
229 | synproxy_send_tcp(skb, nskb, NULL, 0, niph, nth, tcp_hdr_size); | 229 | synproxy_send_tcp(skb, nskb, skb->nfct, IP_CT_ESTABLISHED_REPLY, |
230 | niph, nth, tcp_hdr_size); | ||
230 | } | 231 | } |
231 | 232 | ||
232 | static bool | 233 | static bool |
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index d0362a2de3d3..e681b852ced1 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -2176,7 +2176,7 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *fl4) | |||
2176 | if (!res.prefixlen && | 2176 | if (!res.prefixlen && |
2177 | res.table->tb_num_default > 1 && | 2177 | res.table->tb_num_default > 1 && |
2178 | res.type == RTN_UNICAST && !fl4->flowi4_oif) | 2178 | res.type == RTN_UNICAST && !fl4->flowi4_oif) |
2179 | fib_select_default(&res); | 2179 | fib_select_default(fl4, &res); |
2180 | 2180 | ||
2181 | if (!fl4->saddr) | 2181 | if (!fl4->saddr) |
2182 | fl4->saddr = FIB_RES_PREFSRC(net, res); | 2182 | fl4->saddr = FIB_RES_PREFSRC(net, res); |
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 7f4056785acc..45534a5ab430 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -780,7 +780,7 @@ ssize_t tcp_splice_read(struct socket *sock, loff_t *ppos, | |||
780 | ret = -EAGAIN; | 780 | ret = -EAGAIN; |
781 | break; | 781 | break; |
782 | } | 782 | } |
783 | sk_wait_data(sk, &timeo); | 783 | sk_wait_data(sk, &timeo, NULL); |
784 | if (signal_pending(current)) { | 784 | if (signal_pending(current)) { |
785 | ret = sock_intr_errno(timeo); | 785 | ret = sock_intr_errno(timeo); |
786 | break; | 786 | break; |
@@ -1575,7 +1575,7 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int nonblock, | |||
1575 | int target; /* Read at least this many bytes */ | 1575 | int target; /* Read at least this many bytes */ |
1576 | long timeo; | 1576 | long timeo; |
1577 | struct task_struct *user_recv = NULL; | 1577 | struct task_struct *user_recv = NULL; |
1578 | struct sk_buff *skb; | 1578 | struct sk_buff *skb, *last; |
1579 | u32 urg_hole = 0; | 1579 | u32 urg_hole = 0; |
1580 | 1580 | ||
1581 | if (unlikely(flags & MSG_ERRQUEUE)) | 1581 | if (unlikely(flags & MSG_ERRQUEUE)) |
@@ -1635,7 +1635,9 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int nonblock, | |||
1635 | 1635 | ||
1636 | /* Next get a buffer. */ | 1636 | /* Next get a buffer. */ |
1637 | 1637 | ||
1638 | last = skb_peek_tail(&sk->sk_receive_queue); | ||
1638 | skb_queue_walk(&sk->sk_receive_queue, skb) { | 1639 | skb_queue_walk(&sk->sk_receive_queue, skb) { |
1640 | last = skb; | ||
1639 | /* Now that we have two receive queues this | 1641 | /* Now that we have two receive queues this |
1640 | * shouldn't happen. | 1642 | * shouldn't happen. |
1641 | */ | 1643 | */ |
@@ -1754,8 +1756,9 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int nonblock, | |||
1754 | /* Do not sleep, just process backlog. */ | 1756 | /* Do not sleep, just process backlog. */ |
1755 | release_sock(sk); | 1757 | release_sock(sk); |
1756 | lock_sock(sk); | 1758 | lock_sock(sk); |
1757 | } else | 1759 | } else { |
1758 | sk_wait_data(sk, &timeo); | 1760 | sk_wait_data(sk, &timeo, last); |
1761 | } | ||
1759 | 1762 | ||
1760 | if (user_recv) { | 1763 | if (user_recv) { |
1761 | int chunk; | 1764 | int chunk; |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 684f095d196e..728f5b3d3c64 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -1917,14 +1917,13 @@ void tcp_enter_loss(struct sock *sk) | |||
1917 | const struct inet_connection_sock *icsk = inet_csk(sk); | 1917 | const struct inet_connection_sock *icsk = inet_csk(sk); |
1918 | struct tcp_sock *tp = tcp_sk(sk); | 1918 | struct tcp_sock *tp = tcp_sk(sk); |
1919 | struct sk_buff *skb; | 1919 | struct sk_buff *skb; |
1920 | bool new_recovery = false; | 1920 | bool new_recovery = icsk->icsk_ca_state < TCP_CA_Recovery; |
1921 | bool is_reneg; /* is receiver reneging on SACKs? */ | 1921 | bool is_reneg; /* is receiver reneging on SACKs? */ |
1922 | 1922 | ||
1923 | /* Reduce ssthresh if it has not yet been made inside this window. */ | 1923 | /* Reduce ssthresh if it has not yet been made inside this window. */ |
1924 | if (icsk->icsk_ca_state <= TCP_CA_Disorder || | 1924 | if (icsk->icsk_ca_state <= TCP_CA_Disorder || |
1925 | !after(tp->high_seq, tp->snd_una) || | 1925 | !after(tp->high_seq, tp->snd_una) || |
1926 | (icsk->icsk_ca_state == TCP_CA_Loss && !icsk->icsk_retransmits)) { | 1926 | (icsk->icsk_ca_state == TCP_CA_Loss && !icsk->icsk_retransmits)) { |
1927 | new_recovery = true; | ||
1928 | tp->prior_ssthresh = tcp_current_ssthresh(sk); | 1927 | tp->prior_ssthresh = tcp_current_ssthresh(sk); |
1929 | tp->snd_ssthresh = icsk->icsk_ca_ops->ssthresh(sk); | 1928 | tp->snd_ssthresh = icsk->icsk_ca_ops->ssthresh(sk); |
1930 | tcp_ca_event(sk, CA_EVENT_LOSS); | 1929 | tcp_ca_event(sk, CA_EVENT_LOSS); |
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index d7d4c2b79cf2..0ea2e1c5d395 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -1348,7 +1348,7 @@ static struct sock *tcp_v4_hnd_req(struct sock *sk, struct sk_buff *skb) | |||
1348 | req = inet_csk_search_req(sk, th->source, iph->saddr, iph->daddr); | 1348 | req = inet_csk_search_req(sk, th->source, iph->saddr, iph->daddr); |
1349 | if (req) { | 1349 | if (req) { |
1350 | nsk = tcp_check_req(sk, skb, req, false); | 1350 | nsk = tcp_check_req(sk, skb, req, false); |
1351 | if (!nsk) | 1351 | if (!nsk || nsk == sk) |
1352 | reqsk_put(req); | 1352 | reqsk_put(req); |
1353 | return nsk; | 1353 | return nsk; |
1354 | } | 1354 | } |
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 83aa604f9273..1b8c5ba7d5f7 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -1995,12 +1995,19 @@ void udp_v4_early_demux(struct sk_buff *skb) | |||
1995 | 1995 | ||
1996 | skb->sk = sk; | 1996 | skb->sk = sk; |
1997 | skb->destructor = sock_efree; | 1997 | skb->destructor = sock_efree; |
1998 | dst = sk->sk_rx_dst; | 1998 | dst = READ_ONCE(sk->sk_rx_dst); |
1999 | 1999 | ||
2000 | if (dst) | 2000 | if (dst) |
2001 | dst = dst_check(dst, 0); | 2001 | dst = dst_check(dst, 0); |
2002 | if (dst) | 2002 | if (dst) { |
2003 | skb_dst_set_noref(skb, dst); | 2003 | /* DST_NOCACHE can not be used without taking a reference */ |
2004 | if (dst->flags & DST_NOCACHE) { | ||
2005 | if (likely(atomic_inc_not_zero(&dst->__refcnt))) | ||
2006 | skb_dst_set(skb, dst); | ||
2007 | } else { | ||
2008 | skb_dst_set_noref(skb, dst); | ||
2009 | } | ||
2010 | } | ||
2004 | } | 2011 | } |
2005 | 2012 | ||
2006 | int udp_rcv(struct sk_buff *skb) | 2013 | int udp_rcv(struct sk_buff *skb) |
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index 62d908e64eeb..b10a88986a98 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c | |||
@@ -40,7 +40,7 @@ static bool ipv6_mapped_addr_any(const struct in6_addr *a) | |||
40 | return ipv6_addr_v4mapped(a) && (a->s6_addr32[3] == 0); | 40 | return ipv6_addr_v4mapped(a) && (a->s6_addr32[3] == 0); |
41 | } | 41 | } |
42 | 42 | ||
43 | int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | 43 | static int __ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) |
44 | { | 44 | { |
45 | struct sockaddr_in6 *usin = (struct sockaddr_in6 *) uaddr; | 45 | struct sockaddr_in6 *usin = (struct sockaddr_in6 *) uaddr; |
46 | struct inet_sock *inet = inet_sk(sk); | 46 | struct inet_sock *inet = inet_sk(sk); |
@@ -56,7 +56,7 @@ int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
56 | if (usin->sin6_family == AF_INET) { | 56 | if (usin->sin6_family == AF_INET) { |
57 | if (__ipv6_only_sock(sk)) | 57 | if (__ipv6_only_sock(sk)) |
58 | return -EAFNOSUPPORT; | 58 | return -EAFNOSUPPORT; |
59 | err = ip4_datagram_connect(sk, uaddr, addr_len); | 59 | err = __ip4_datagram_connect(sk, uaddr, addr_len); |
60 | goto ipv4_connected; | 60 | goto ipv4_connected; |
61 | } | 61 | } |
62 | 62 | ||
@@ -98,9 +98,9 @@ int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
98 | sin.sin_addr.s_addr = daddr->s6_addr32[3]; | 98 | sin.sin_addr.s_addr = daddr->s6_addr32[3]; |
99 | sin.sin_port = usin->sin6_port; | 99 | sin.sin_port = usin->sin6_port; |
100 | 100 | ||
101 | err = ip4_datagram_connect(sk, | 101 | err = __ip4_datagram_connect(sk, |
102 | (struct sockaddr *) &sin, | 102 | (struct sockaddr *) &sin, |
103 | sizeof(sin)); | 103 | sizeof(sin)); |
104 | 104 | ||
105 | ipv4_connected: | 105 | ipv4_connected: |
106 | if (err) | 106 | if (err) |
@@ -204,6 +204,16 @@ out: | |||
204 | fl6_sock_release(flowlabel); | 204 | fl6_sock_release(flowlabel); |
205 | return err; | 205 | return err; |
206 | } | 206 | } |
207 | |||
208 | int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | ||
209 | { | ||
210 | int res; | ||
211 | |||
212 | lock_sock(sk); | ||
213 | res = __ip6_datagram_connect(sk, uaddr, addr_len); | ||
214 | release_sock(sk); | ||
215 | return res; | ||
216 | } | ||
207 | EXPORT_SYMBOL_GPL(ip6_datagram_connect); | 217 | EXPORT_SYMBOL_GPL(ip6_datagram_connect); |
208 | 218 | ||
209 | int ip6_datagram_connect_v6_only(struct sock *sk, struct sockaddr *uaddr, | 219 | int ip6_datagram_connect_v6_only(struct sock *sk, struct sockaddr *uaddr, |
diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c index e893cd18612f..08b62047c67f 100644 --- a/net/ipv6/ip6_offload.c +++ b/net/ipv6/ip6_offload.c | |||
@@ -292,8 +292,6 @@ static struct packet_offload ipv6_packet_offload __read_mostly = { | |||
292 | static const struct net_offload sit_offload = { | 292 | static const struct net_offload sit_offload = { |
293 | .callbacks = { | 293 | .callbacks = { |
294 | .gso_segment = ipv6_gso_segment, | 294 | .gso_segment = ipv6_gso_segment, |
295 | .gro_receive = ipv6_gro_receive, | ||
296 | .gro_complete = ipv6_gro_complete, | ||
297 | }, | 295 | }, |
298 | }; | 296 | }; |
299 | 297 | ||
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 0a05b35a90fc..c53331cfed95 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
@@ -1650,6 +1650,7 @@ int ndisc_rcv(struct sk_buff *skb) | |||
1650 | static int ndisc_netdev_event(struct notifier_block *this, unsigned long event, void *ptr) | 1650 | static int ndisc_netdev_event(struct notifier_block *this, unsigned long event, void *ptr) |
1651 | { | 1651 | { |
1652 | struct net_device *dev = netdev_notifier_info_to_dev(ptr); | 1652 | struct net_device *dev = netdev_notifier_info_to_dev(ptr); |
1653 | struct netdev_notifier_change_info *change_info; | ||
1653 | struct net *net = dev_net(dev); | 1654 | struct net *net = dev_net(dev); |
1654 | struct inet6_dev *idev; | 1655 | struct inet6_dev *idev; |
1655 | 1656 | ||
@@ -1664,6 +1665,11 @@ static int ndisc_netdev_event(struct notifier_block *this, unsigned long event, | |||
1664 | ndisc_send_unsol_na(dev); | 1665 | ndisc_send_unsol_na(dev); |
1665 | in6_dev_put(idev); | 1666 | in6_dev_put(idev); |
1666 | break; | 1667 | break; |
1668 | case NETDEV_CHANGE: | ||
1669 | change_info = ptr; | ||
1670 | if (change_info->flags_changed & IFF_NOARP) | ||
1671 | neigh_changeaddr(&nd_tbl, dev); | ||
1672 | break; | ||
1667 | case NETDEV_DOWN: | 1673 | case NETDEV_DOWN: |
1668 | neigh_ifdown(&nd_tbl, dev); | 1674 | neigh_ifdown(&nd_tbl, dev); |
1669 | fib6_run_gc(0, net, false); | 1675 | fib6_run_gc(0, net, false); |
diff --git a/net/ipv6/netfilter/ip6t_SYNPROXY.c b/net/ipv6/netfilter/ip6t_SYNPROXY.c index 6edb7b106de7..ebbb754c2111 100644 --- a/net/ipv6/netfilter/ip6t_SYNPROXY.c +++ b/net/ipv6/netfilter/ip6t_SYNPROXY.c | |||
@@ -37,12 +37,13 @@ synproxy_build_ip(struct sk_buff *skb, const struct in6_addr *saddr, | |||
37 | } | 37 | } |
38 | 38 | ||
39 | static void | 39 | static void |
40 | synproxy_send_tcp(const struct sk_buff *skb, struct sk_buff *nskb, | 40 | synproxy_send_tcp(const struct synproxy_net *snet, |
41 | const struct sk_buff *skb, struct sk_buff *nskb, | ||
41 | struct nf_conntrack *nfct, enum ip_conntrack_info ctinfo, | 42 | struct nf_conntrack *nfct, enum ip_conntrack_info ctinfo, |
42 | struct ipv6hdr *niph, struct tcphdr *nth, | 43 | struct ipv6hdr *niph, struct tcphdr *nth, |
43 | unsigned int tcp_hdr_size) | 44 | unsigned int tcp_hdr_size) |
44 | { | 45 | { |
45 | struct net *net = nf_ct_net((struct nf_conn *)nfct); | 46 | struct net *net = nf_ct_net(snet->tmpl); |
46 | struct dst_entry *dst; | 47 | struct dst_entry *dst; |
47 | struct flowi6 fl6; | 48 | struct flowi6 fl6; |
48 | 49 | ||
@@ -83,7 +84,8 @@ free_nskb: | |||
83 | } | 84 | } |
84 | 85 | ||
85 | static void | 86 | static void |
86 | synproxy_send_client_synack(const struct sk_buff *skb, const struct tcphdr *th, | 87 | synproxy_send_client_synack(const struct synproxy_net *snet, |
88 | const struct sk_buff *skb, const struct tcphdr *th, | ||
87 | const struct synproxy_options *opts) | 89 | const struct synproxy_options *opts) |
88 | { | 90 | { |
89 | struct sk_buff *nskb; | 91 | struct sk_buff *nskb; |
@@ -119,7 +121,7 @@ synproxy_send_client_synack(const struct sk_buff *skb, const struct tcphdr *th, | |||
119 | 121 | ||
120 | synproxy_build_options(nth, opts); | 122 | synproxy_build_options(nth, opts); |
121 | 123 | ||
122 | synproxy_send_tcp(skb, nskb, skb->nfct, IP_CT_ESTABLISHED_REPLY, | 124 | synproxy_send_tcp(snet, skb, nskb, skb->nfct, IP_CT_ESTABLISHED_REPLY, |
123 | niph, nth, tcp_hdr_size); | 125 | niph, nth, tcp_hdr_size); |
124 | } | 126 | } |
125 | 127 | ||
@@ -163,7 +165,7 @@ synproxy_send_server_syn(const struct synproxy_net *snet, | |||
163 | 165 | ||
164 | synproxy_build_options(nth, opts); | 166 | synproxy_build_options(nth, opts); |
165 | 167 | ||
166 | synproxy_send_tcp(skb, nskb, &snet->tmpl->ct_general, IP_CT_NEW, | 168 | synproxy_send_tcp(snet, skb, nskb, &snet->tmpl->ct_general, IP_CT_NEW, |
167 | niph, nth, tcp_hdr_size); | 169 | niph, nth, tcp_hdr_size); |
168 | } | 170 | } |
169 | 171 | ||
@@ -203,7 +205,7 @@ synproxy_send_server_ack(const struct synproxy_net *snet, | |||
203 | 205 | ||
204 | synproxy_build_options(nth, opts); | 206 | synproxy_build_options(nth, opts); |
205 | 207 | ||
206 | synproxy_send_tcp(skb, nskb, NULL, 0, niph, nth, tcp_hdr_size); | 208 | synproxy_send_tcp(snet, skb, nskb, NULL, 0, niph, nth, tcp_hdr_size); |
207 | } | 209 | } |
208 | 210 | ||
209 | static void | 211 | static void |
@@ -241,7 +243,8 @@ synproxy_send_client_ack(const struct synproxy_net *snet, | |||
241 | 243 | ||
242 | synproxy_build_options(nth, opts); | 244 | synproxy_build_options(nth, opts); |
243 | 245 | ||
244 | synproxy_send_tcp(skb, nskb, NULL, 0, niph, nth, tcp_hdr_size); | 246 | synproxy_send_tcp(snet, skb, nskb, skb->nfct, IP_CT_ESTABLISHED_REPLY, |
247 | niph, nth, tcp_hdr_size); | ||
245 | } | 248 | } |
246 | 249 | ||
247 | static bool | 250 | static bool |
@@ -301,7 +304,7 @@ synproxy_tg6(struct sk_buff *skb, const struct xt_action_param *par) | |||
301 | XT_SYNPROXY_OPT_SACK_PERM | | 304 | XT_SYNPROXY_OPT_SACK_PERM | |
302 | XT_SYNPROXY_OPT_ECN); | 305 | XT_SYNPROXY_OPT_ECN); |
303 | 306 | ||
304 | synproxy_send_client_synack(skb, th, &opts); | 307 | synproxy_send_client_synack(snet, skb, th, &opts); |
305 | return NF_DROP; | 308 | return NF_DROP; |
306 | 309 | ||
307 | } else if (th->ack && !(th->fin || th->rst || th->syn)) { | 310 | } else if (th->ack && !(th->fin || th->rst || th->syn)) { |
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index 6f187c8d8a1b..6d02498172c1 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c | |||
@@ -348,7 +348,7 @@ found: | |||
348 | fq->ecn |= ecn; | 348 | fq->ecn |= ecn; |
349 | if (payload_len > fq->q.max_size) | 349 | if (payload_len > fq->q.max_size) |
350 | fq->q.max_size = payload_len; | 350 | fq->q.max_size = payload_len; |
351 | add_frag_mem_limit(&fq->q, skb->truesize); | 351 | add_frag_mem_limit(fq->q.net, skb->truesize); |
352 | 352 | ||
353 | /* The first fragment. | 353 | /* The first fragment. |
354 | * nhoffset is obtained from the first fragment, of course. | 354 | * nhoffset is obtained from the first fragment, of course. |
@@ -430,7 +430,7 @@ nf_ct_frag6_reasm(struct frag_queue *fq, struct net_device *dev) | |||
430 | clone->ip_summed = head->ip_summed; | 430 | clone->ip_summed = head->ip_summed; |
431 | 431 | ||
432 | NFCT_FRAG6_CB(clone)->orig = NULL; | 432 | NFCT_FRAG6_CB(clone)->orig = NULL; |
433 | add_frag_mem_limit(&fq->q, clone->truesize); | 433 | add_frag_mem_limit(fq->q.net, clone->truesize); |
434 | } | 434 | } |
435 | 435 | ||
436 | /* We have to remove fragment header from datagram and to relocate | 436 | /* We have to remove fragment header from datagram and to relocate |
@@ -454,7 +454,7 @@ nf_ct_frag6_reasm(struct frag_queue *fq, struct net_device *dev) | |||
454 | head->csum = csum_add(head->csum, fp->csum); | 454 | head->csum = csum_add(head->csum, fp->csum); |
455 | head->truesize += fp->truesize; | 455 | head->truesize += fp->truesize; |
456 | } | 456 | } |
457 | sub_frag_mem_limit(&fq->q, head->truesize); | 457 | sub_frag_mem_limit(fq->q.net, head->truesize); |
458 | 458 | ||
459 | head->ignore_df = 1; | 459 | head->ignore_df = 1; |
460 | head->next = NULL; | 460 | head->next = NULL; |
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index 8ffa2c8cce77..f1159bb76e0a 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c | |||
@@ -144,7 +144,7 @@ void ip6_expire_frag_queue(struct net *net, struct frag_queue *fq, | |||
144 | 144 | ||
145 | IP6_INC_STATS_BH(net, __in6_dev_get(dev), IPSTATS_MIB_REASMFAILS); | 145 | IP6_INC_STATS_BH(net, __in6_dev_get(dev), IPSTATS_MIB_REASMFAILS); |
146 | 146 | ||
147 | if (fq->q.flags & INET_FRAG_EVICTED) | 147 | if (inet_frag_evicting(&fq->q)) |
148 | goto out_rcu_unlock; | 148 | goto out_rcu_unlock; |
149 | 149 | ||
150 | IP6_INC_STATS_BH(net, __in6_dev_get(dev), IPSTATS_MIB_REASMTIMEOUT); | 150 | IP6_INC_STATS_BH(net, __in6_dev_get(dev), IPSTATS_MIB_REASMTIMEOUT); |
@@ -330,7 +330,7 @@ found: | |||
330 | fq->q.stamp = skb->tstamp; | 330 | fq->q.stamp = skb->tstamp; |
331 | fq->q.meat += skb->len; | 331 | fq->q.meat += skb->len; |
332 | fq->ecn |= ecn; | 332 | fq->ecn |= ecn; |
333 | add_frag_mem_limit(&fq->q, skb->truesize); | 333 | add_frag_mem_limit(fq->q.net, skb->truesize); |
334 | 334 | ||
335 | /* The first fragment. | 335 | /* The first fragment. |
336 | * nhoffset is obtained from the first fragment, of course. | 336 | * nhoffset is obtained from the first fragment, of course. |
@@ -443,7 +443,7 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev, | |||
443 | head->len -= clone->len; | 443 | head->len -= clone->len; |
444 | clone->csum = 0; | 444 | clone->csum = 0; |
445 | clone->ip_summed = head->ip_summed; | 445 | clone->ip_summed = head->ip_summed; |
446 | add_frag_mem_limit(&fq->q, clone->truesize); | 446 | add_frag_mem_limit(fq->q.net, clone->truesize); |
447 | } | 447 | } |
448 | 448 | ||
449 | /* We have to remove fragment header from datagram and to relocate | 449 | /* We have to remove fragment header from datagram and to relocate |
@@ -481,7 +481,7 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev, | |||
481 | } | 481 | } |
482 | fp = next; | 482 | fp = next; |
483 | } | 483 | } |
484 | sub_frag_mem_limit(&fq->q, sum_truesize); | 484 | sub_frag_mem_limit(fq->q.net, sum_truesize); |
485 | 485 | ||
486 | head->next = NULL; | 486 | head->next = NULL; |
487 | head->dev = dev; | 487 | head->dev = dev; |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 6090969937f8..9de4d2bcd916 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -1831,6 +1831,7 @@ int ip6_route_add(struct fib6_config *cfg) | |||
1831 | int gwa_type; | 1831 | int gwa_type; |
1832 | 1832 | ||
1833 | gw_addr = &cfg->fc_gateway; | 1833 | gw_addr = &cfg->fc_gateway; |
1834 | gwa_type = ipv6_addr_type(gw_addr); | ||
1834 | 1835 | ||
1835 | /* if gw_addr is local we will fail to detect this in case | 1836 | /* if gw_addr is local we will fail to detect this in case |
1836 | * address is still TENTATIVE (DAD in progress). rt6_lookup() | 1837 | * address is still TENTATIVE (DAD in progress). rt6_lookup() |
@@ -1838,11 +1839,12 @@ int ip6_route_add(struct fib6_config *cfg) | |||
1838 | * prefix route was assigned to, which might be non-loopback. | 1839 | * prefix route was assigned to, which might be non-loopback. |
1839 | */ | 1840 | */ |
1840 | err = -EINVAL; | 1841 | err = -EINVAL; |
1841 | if (ipv6_chk_addr_and_flags(net, gw_addr, NULL, 0, 0)) | 1842 | if (ipv6_chk_addr_and_flags(net, gw_addr, |
1843 | gwa_type & IPV6_ADDR_LINKLOCAL ? | ||
1844 | dev : NULL, 0, 0)) | ||
1842 | goto out; | 1845 | goto out; |
1843 | 1846 | ||
1844 | rt->rt6i_gateway = *gw_addr; | 1847 | rt->rt6i_gateway = *gw_addr; |
1845 | gwa_type = ipv6_addr_type(gw_addr); | ||
1846 | 1848 | ||
1847 | if (gwa_type != (IPV6_ADDR_LINKLOCAL|IPV6_ADDR_UNICAST)) { | 1849 | if (gwa_type != (IPV6_ADDR_LINKLOCAL|IPV6_ADDR_UNICAST)) { |
1848 | struct rt6_info *grt; | 1850 | struct rt6_info *grt; |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 6748c4277aff..7a6cea5e4274 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -943,7 +943,7 @@ static struct sock *tcp_v6_hnd_req(struct sock *sk, struct sk_buff *skb) | |||
943 | &ipv6_hdr(skb)->daddr, tcp_v6_iif(skb)); | 943 | &ipv6_hdr(skb)->daddr, tcp_v6_iif(skb)); |
944 | if (req) { | 944 | if (req) { |
945 | nsk = tcp_check_req(sk, skb, req, false); | 945 | nsk = tcp_check_req(sk, skb, req, false); |
946 | if (!nsk) | 946 | if (!nsk || nsk == sk) |
947 | reqsk_put(req); | 947 | reqsk_put(req); |
948 | return nsk; | 948 | return nsk; |
949 | } | 949 | } |
diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index 8fd9febaa5ba..8dab4e569571 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c | |||
@@ -613,7 +613,7 @@ static int llc_wait_data(struct sock *sk, long timeo) | |||
613 | if (signal_pending(current)) | 613 | if (signal_pending(current)) |
614 | break; | 614 | break; |
615 | rc = 0; | 615 | rc = 0; |
616 | if (sk_wait_data(sk, &timeo)) | 616 | if (sk_wait_data(sk, &timeo, NULL)) |
617 | break; | 617 | break; |
618 | } | 618 | } |
619 | return rc; | 619 | return rc; |
@@ -802,7 +802,7 @@ static int llc_ui_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, | |||
802 | release_sock(sk); | 802 | release_sock(sk); |
803 | lock_sock(sk); | 803 | lock_sock(sk); |
804 | } else | 804 | } else |
805 | sk_wait_data(sk, &timeo); | 805 | sk_wait_data(sk, &timeo, NULL); |
806 | 806 | ||
807 | if ((flags & MSG_PEEK) && peek_seq != llc->copied_seq) { | 807 | if ((flags & MSG_PEEK) && peek_seq != llc->copied_seq) { |
808 | net_dbg_ratelimited("LLC(%s:%d): Application bug, race in MSG_PEEK\n", | 808 | net_dbg_ratelimited("LLC(%s:%d): Application bug, race in MSG_PEEK\n", |
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 29236e832e44..c09c0131bfa2 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c | |||
@@ -723,6 +723,7 @@ void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata) | |||
723 | 723 | ||
724 | debugfs_remove_recursive(sdata->vif.debugfs_dir); | 724 | debugfs_remove_recursive(sdata->vif.debugfs_dir); |
725 | sdata->vif.debugfs_dir = NULL; | 725 | sdata->vif.debugfs_dir = NULL; |
726 | sdata->debugfs.subdir_stations = NULL; | ||
726 | } | 727 | } |
727 | 728 | ||
728 | void ieee80211_debugfs_rename_netdev(struct ieee80211_sub_if_data *sdata) | 729 | void ieee80211_debugfs_rename_netdev(struct ieee80211_sub_if_data *sdata) |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index ed1edac14372..553ac6dd4867 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -1863,10 +1863,6 @@ void ieee80211_sdata_stop(struct ieee80211_sub_if_data *sdata) | |||
1863 | ieee80211_teardown_sdata(sdata); | 1863 | ieee80211_teardown_sdata(sdata); |
1864 | } | 1864 | } |
1865 | 1865 | ||
1866 | /* | ||
1867 | * Remove all interfaces, may only be called at hardware unregistration | ||
1868 | * time because it doesn't do RCU-safe list removals. | ||
1869 | */ | ||
1870 | void ieee80211_remove_interfaces(struct ieee80211_local *local) | 1866 | void ieee80211_remove_interfaces(struct ieee80211_local *local) |
1871 | { | 1867 | { |
1872 | struct ieee80211_sub_if_data *sdata, *tmp; | 1868 | struct ieee80211_sub_if_data *sdata, *tmp; |
@@ -1875,14 +1871,21 @@ void ieee80211_remove_interfaces(struct ieee80211_local *local) | |||
1875 | 1871 | ||
1876 | ASSERT_RTNL(); | 1872 | ASSERT_RTNL(); |
1877 | 1873 | ||
1878 | /* | 1874 | /* Before destroying the interfaces, make sure they're all stopped so |
1879 | * Close all AP_VLAN interfaces first, as otherwise they | 1875 | * that the hardware is stopped. Otherwise, the driver might still be |
1880 | * might be closed while the AP interface they belong to | 1876 | * iterating the interfaces during the shutdown, e.g. from a worker |
1881 | * is closed, causing unregister_netdevice_many() to crash. | 1877 | * or from RX processing or similar, and if it does so (using atomic |
1878 | * iteration) while we're manipulating the list, the iteration will | ||
1879 | * crash. | ||
1880 | * | ||
1881 | * After this, the hardware should be stopped and the driver should | ||
1882 | * have stopped all of its activities, so that we can do RCU-unaware | ||
1883 | * manipulations of the interface list below. | ||
1882 | */ | 1884 | */ |
1883 | list_for_each_entry(sdata, &local->interfaces, list) | 1885 | cfg80211_shutdown_all_interfaces(local->hw.wiphy); |
1884 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 1886 | |
1885 | dev_close(sdata->dev); | 1887 | WARN(local->open_count, "%s: open count remains %d\n", |
1888 | wiphy_name(local->hw.wiphy), local->open_count); | ||
1886 | 1889 | ||
1887 | mutex_lock(&local->iflist_mtx); | 1890 | mutex_lock(&local->iflist_mtx); |
1888 | list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) { | 1891 | list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) { |
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 5438d13e2f00..3b59099413fb 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
@@ -306,7 +306,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | |||
306 | if (action == WLAN_SP_MESH_PEERING_CONFIRM) { | 306 | if (action == WLAN_SP_MESH_PEERING_CONFIRM) { |
307 | /* AID */ | 307 | /* AID */ |
308 | pos = skb_put(skb, 2); | 308 | pos = skb_put(skb, 2); |
309 | put_unaligned_le16(plid, pos + 2); | 309 | put_unaligned_le16(plid, pos); |
310 | } | 310 | } |
311 | if (ieee80211_add_srates_ie(sdata, skb, true, band) || | 311 | if (ieee80211_add_srates_ie(sdata, skb, true, band) || |
312 | ieee80211_add_ext_srates_ie(sdata, skb, true, band) || | 312 | ieee80211_add_ext_srates_ie(sdata, skb, true, band) || |
@@ -1122,6 +1122,9 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, | |||
1122 | WLAN_SP_MESH_PEERING_CONFIRM) { | 1122 | WLAN_SP_MESH_PEERING_CONFIRM) { |
1123 | baseaddr += 4; | 1123 | baseaddr += 4; |
1124 | baselen += 4; | 1124 | baselen += 4; |
1125 | |||
1126 | if (baselen > len) | ||
1127 | return; | ||
1125 | } | 1128 | } |
1126 | ieee802_11_parse_elems(baseaddr, len - baselen, true, &elems); | 1129 | ieee802_11_parse_elems(baseaddr, len - baselen, true, &elems); |
1127 | mesh_process_plink_frame(sdata, mgmt, &elems); | 1130 | mesh_process_plink_frame(sdata, mgmt, &elems); |
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index 06b60980c62c..b676b9fa707b 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c | |||
@@ -76,6 +76,22 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | |||
76 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | 76 | if (sdata->vif.type != NL80211_IFTYPE_STATION) |
77 | continue; | 77 | continue; |
78 | ieee80211_mgd_quiesce(sdata); | 78 | ieee80211_mgd_quiesce(sdata); |
79 | /* If suspended during TX in progress, and wowlan | ||
80 | * is enabled (connection will be active) there | ||
81 | * can be a race where the driver is put out | ||
82 | * of power-save due to TX and during suspend | ||
83 | * dynamic_ps_timer is cancelled and TX packet | ||
84 | * is flushed, leaving the driver in ACTIVE even | ||
85 | * after resuming until dynamic_ps_timer puts | ||
86 | * driver back in DOZE. | ||
87 | */ | ||
88 | if (sdata->u.mgd.associated && | ||
89 | sdata->u.mgd.powersave && | ||
90 | !(local->hw.conf.flags & IEEE80211_CONF_PS)) { | ||
91 | local->hw.conf.flags |= IEEE80211_CONF_PS; | ||
92 | ieee80211_hw_config(local, | ||
93 | IEEE80211_CONF_CHANGE_PS); | ||
94 | } | ||
79 | } | 95 | } |
80 | 96 | ||
81 | err = drv_suspend(local, wowlan); | 97 | err = drv_suspend(local, wowlan); |
diff --git a/net/mac80211/tdls.c b/net/mac80211/tdls.c index ad31b2dab4f5..8db6e2994bbc 100644 --- a/net/mac80211/tdls.c +++ b/net/mac80211/tdls.c | |||
@@ -60,6 +60,7 @@ ieee80211_tdls_add_subband(struct ieee80211_sub_if_data *sdata, | |||
60 | struct ieee80211_channel *ch; | 60 | struct ieee80211_channel *ch; |
61 | struct cfg80211_chan_def chandef; | 61 | struct cfg80211_chan_def chandef; |
62 | int i, subband_start; | 62 | int i, subband_start; |
63 | struct wiphy *wiphy = sdata->local->hw.wiphy; | ||
63 | 64 | ||
64 | for (i = start; i <= end; i += spacing) { | 65 | for (i = start; i <= end; i += spacing) { |
65 | if (!ch_cnt) | 66 | if (!ch_cnt) |
@@ -70,9 +71,8 @@ ieee80211_tdls_add_subband(struct ieee80211_sub_if_data *sdata, | |||
70 | /* we will be active on the channel */ | 71 | /* we will be active on the channel */ |
71 | cfg80211_chandef_create(&chandef, ch, | 72 | cfg80211_chandef_create(&chandef, ch, |
72 | NL80211_CHAN_NO_HT); | 73 | NL80211_CHAN_NO_HT); |
73 | if (cfg80211_reg_can_beacon(sdata->local->hw.wiphy, | 74 | if (cfg80211_reg_can_beacon_relax(wiphy, &chandef, |
74 | &chandef, | 75 | sdata->wdev.iftype)) { |
75 | sdata->wdev.iftype)) { | ||
76 | ch_cnt++; | 76 | ch_cnt++; |
77 | /* | 77 | /* |
78 | * check if the next channel is also part of | 78 | * check if the next channel is also part of |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 8410bb3bf5e8..b8233505bf9f 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -1117,7 +1117,9 @@ static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx, | |||
1117 | queued = true; | 1117 | queued = true; |
1118 | info->control.vif = &tx->sdata->vif; | 1118 | info->control.vif = &tx->sdata->vif; |
1119 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; | 1119 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; |
1120 | info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS; | 1120 | info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS | |
1121 | IEEE80211_TX_CTL_NO_PS_BUFFER | | ||
1122 | IEEE80211_TX_STATUS_EOSP; | ||
1121 | __skb_queue_tail(&tid_tx->pending, skb); | 1123 | __skb_queue_tail(&tid_tx->pending, skb); |
1122 | if (skb_queue_len(&tid_tx->pending) > STA_MAX_TX_BUFFER) | 1124 | if (skb_queue_len(&tid_tx->pending) > STA_MAX_TX_BUFFER) |
1123 | purge_skb = __skb_dequeue(&tid_tx->pending); | 1125 | purge_skb = __skb_dequeue(&tid_tx->pending); |
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c index 5d2b806a862e..38fbc194b9cb 100644 --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c | |||
@@ -319,7 +319,13 @@ ip_vs_sched_persist(struct ip_vs_service *svc, | |||
319 | * return *ignored=0 i.e. ICMP and NF_DROP | 319 | * return *ignored=0 i.e. ICMP and NF_DROP |
320 | */ | 320 | */ |
321 | sched = rcu_dereference(svc->scheduler); | 321 | sched = rcu_dereference(svc->scheduler); |
322 | dest = sched->schedule(svc, skb, iph); | 322 | if (sched) { |
323 | /* read svc->sched_data after svc->scheduler */ | ||
324 | smp_rmb(); | ||
325 | dest = sched->schedule(svc, skb, iph); | ||
326 | } else { | ||
327 | dest = NULL; | ||
328 | } | ||
323 | if (!dest) { | 329 | if (!dest) { |
324 | IP_VS_DBG(1, "p-schedule: no dest found.\n"); | 330 | IP_VS_DBG(1, "p-schedule: no dest found.\n"); |
325 | kfree(param.pe_data); | 331 | kfree(param.pe_data); |
@@ -467,7 +473,13 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb, | |||
467 | } | 473 | } |
468 | 474 | ||
469 | sched = rcu_dereference(svc->scheduler); | 475 | sched = rcu_dereference(svc->scheduler); |
470 | dest = sched->schedule(svc, skb, iph); | 476 | if (sched) { |
477 | /* read svc->sched_data after svc->scheduler */ | ||
478 | smp_rmb(); | ||
479 | dest = sched->schedule(svc, skb, iph); | ||
480 | } else { | ||
481 | dest = NULL; | ||
482 | } | ||
471 | if (dest == NULL) { | 483 | if (dest == NULL) { |
472 | IP_VS_DBG(1, "Schedule: no dest found.\n"); | 484 | IP_VS_DBG(1, "Schedule: no dest found.\n"); |
473 | return NULL; | 485 | return NULL; |
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index 285eae3a1454..24c554201a76 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c | |||
@@ -842,15 +842,16 @@ __ip_vs_update_dest(struct ip_vs_service *svc, struct ip_vs_dest *dest, | |||
842 | __ip_vs_dst_cache_reset(dest); | 842 | __ip_vs_dst_cache_reset(dest); |
843 | spin_unlock_bh(&dest->dst_lock); | 843 | spin_unlock_bh(&dest->dst_lock); |
844 | 844 | ||
845 | sched = rcu_dereference_protected(svc->scheduler, 1); | ||
846 | if (add) { | 845 | if (add) { |
847 | ip_vs_start_estimator(svc->net, &dest->stats); | 846 | ip_vs_start_estimator(svc->net, &dest->stats); |
848 | list_add_rcu(&dest->n_list, &svc->destinations); | 847 | list_add_rcu(&dest->n_list, &svc->destinations); |
849 | svc->num_dests++; | 848 | svc->num_dests++; |
850 | if (sched->add_dest) | 849 | sched = rcu_dereference_protected(svc->scheduler, 1); |
850 | if (sched && sched->add_dest) | ||
851 | sched->add_dest(svc, dest); | 851 | sched->add_dest(svc, dest); |
852 | } else { | 852 | } else { |
853 | if (sched->upd_dest) | 853 | sched = rcu_dereference_protected(svc->scheduler, 1); |
854 | if (sched && sched->upd_dest) | ||
854 | sched->upd_dest(svc, dest); | 855 | sched->upd_dest(svc, dest); |
855 | } | 856 | } |
856 | } | 857 | } |
@@ -1084,7 +1085,7 @@ static void __ip_vs_unlink_dest(struct ip_vs_service *svc, | |||
1084 | struct ip_vs_scheduler *sched; | 1085 | struct ip_vs_scheduler *sched; |
1085 | 1086 | ||
1086 | sched = rcu_dereference_protected(svc->scheduler, 1); | 1087 | sched = rcu_dereference_protected(svc->scheduler, 1); |
1087 | if (sched->del_dest) | 1088 | if (sched && sched->del_dest) |
1088 | sched->del_dest(svc, dest); | 1089 | sched->del_dest(svc, dest); |
1089 | } | 1090 | } |
1090 | } | 1091 | } |
@@ -1175,11 +1176,14 @@ ip_vs_add_service(struct net *net, struct ip_vs_service_user_kern *u, | |||
1175 | ip_vs_use_count_inc(); | 1176 | ip_vs_use_count_inc(); |
1176 | 1177 | ||
1177 | /* Lookup the scheduler by 'u->sched_name' */ | 1178 | /* Lookup the scheduler by 'u->sched_name' */ |
1178 | sched = ip_vs_scheduler_get(u->sched_name); | 1179 | if (strcmp(u->sched_name, "none")) { |
1179 | if (sched == NULL) { | 1180 | sched = ip_vs_scheduler_get(u->sched_name); |
1180 | pr_info("Scheduler module ip_vs_%s not found\n", u->sched_name); | 1181 | if (!sched) { |
1181 | ret = -ENOENT; | 1182 | pr_info("Scheduler module ip_vs_%s not found\n", |
1182 | goto out_err; | 1183 | u->sched_name); |
1184 | ret = -ENOENT; | ||
1185 | goto out_err; | ||
1186 | } | ||
1183 | } | 1187 | } |
1184 | 1188 | ||
1185 | if (u->pe_name && *u->pe_name) { | 1189 | if (u->pe_name && *u->pe_name) { |
@@ -1240,10 +1244,12 @@ ip_vs_add_service(struct net *net, struct ip_vs_service_user_kern *u, | |||
1240 | spin_lock_init(&svc->stats.lock); | 1244 | spin_lock_init(&svc->stats.lock); |
1241 | 1245 | ||
1242 | /* Bind the scheduler */ | 1246 | /* Bind the scheduler */ |
1243 | ret = ip_vs_bind_scheduler(svc, sched); | 1247 | if (sched) { |
1244 | if (ret) | 1248 | ret = ip_vs_bind_scheduler(svc, sched); |
1245 | goto out_err; | 1249 | if (ret) |
1246 | sched = NULL; | 1250 | goto out_err; |
1251 | sched = NULL; | ||
1252 | } | ||
1247 | 1253 | ||
1248 | /* Bind the ct retriever */ | 1254 | /* Bind the ct retriever */ |
1249 | RCU_INIT_POINTER(svc->pe, pe); | 1255 | RCU_INIT_POINTER(svc->pe, pe); |
@@ -1291,17 +1297,20 @@ ip_vs_add_service(struct net *net, struct ip_vs_service_user_kern *u, | |||
1291 | static int | 1297 | static int |
1292 | ip_vs_edit_service(struct ip_vs_service *svc, struct ip_vs_service_user_kern *u) | 1298 | ip_vs_edit_service(struct ip_vs_service *svc, struct ip_vs_service_user_kern *u) |
1293 | { | 1299 | { |
1294 | struct ip_vs_scheduler *sched, *old_sched; | 1300 | struct ip_vs_scheduler *sched = NULL, *old_sched; |
1295 | struct ip_vs_pe *pe = NULL, *old_pe = NULL; | 1301 | struct ip_vs_pe *pe = NULL, *old_pe = NULL; |
1296 | int ret = 0; | 1302 | int ret = 0; |
1297 | 1303 | ||
1298 | /* | 1304 | /* |
1299 | * Lookup the scheduler, by 'u->sched_name' | 1305 | * Lookup the scheduler, by 'u->sched_name' |
1300 | */ | 1306 | */ |
1301 | sched = ip_vs_scheduler_get(u->sched_name); | 1307 | if (strcmp(u->sched_name, "none")) { |
1302 | if (sched == NULL) { | 1308 | sched = ip_vs_scheduler_get(u->sched_name); |
1303 | pr_info("Scheduler module ip_vs_%s not found\n", u->sched_name); | 1309 | if (!sched) { |
1304 | return -ENOENT; | 1310 | pr_info("Scheduler module ip_vs_%s not found\n", |
1311 | u->sched_name); | ||
1312 | return -ENOENT; | ||
1313 | } | ||
1305 | } | 1314 | } |
1306 | old_sched = sched; | 1315 | old_sched = sched; |
1307 | 1316 | ||
@@ -1329,14 +1338,20 @@ ip_vs_edit_service(struct ip_vs_service *svc, struct ip_vs_service_user_kern *u) | |||
1329 | 1338 | ||
1330 | old_sched = rcu_dereference_protected(svc->scheduler, 1); | 1339 | old_sched = rcu_dereference_protected(svc->scheduler, 1); |
1331 | if (sched != old_sched) { | 1340 | if (sched != old_sched) { |
1341 | if (old_sched) { | ||
1342 | ip_vs_unbind_scheduler(svc, old_sched); | ||
1343 | RCU_INIT_POINTER(svc->scheduler, NULL); | ||
1344 | /* Wait all svc->sched_data users */ | ||
1345 | synchronize_rcu(); | ||
1346 | } | ||
1332 | /* Bind the new scheduler */ | 1347 | /* Bind the new scheduler */ |
1333 | ret = ip_vs_bind_scheduler(svc, sched); | 1348 | if (sched) { |
1334 | if (ret) { | 1349 | ret = ip_vs_bind_scheduler(svc, sched); |
1335 | old_sched = sched; | 1350 | if (ret) { |
1336 | goto out; | 1351 | ip_vs_scheduler_put(sched); |
1352 | goto out; | ||
1353 | } | ||
1337 | } | 1354 | } |
1338 | /* Unbind the old scheduler on success */ | ||
1339 | ip_vs_unbind_scheduler(svc, old_sched); | ||
1340 | } | 1355 | } |
1341 | 1356 | ||
1342 | /* | 1357 | /* |
@@ -1982,6 +1997,7 @@ static int ip_vs_info_seq_show(struct seq_file *seq, void *v) | |||
1982 | const struct ip_vs_iter *iter = seq->private; | 1997 | const struct ip_vs_iter *iter = seq->private; |
1983 | const struct ip_vs_dest *dest; | 1998 | const struct ip_vs_dest *dest; |
1984 | struct ip_vs_scheduler *sched = rcu_dereference(svc->scheduler); | 1999 | struct ip_vs_scheduler *sched = rcu_dereference(svc->scheduler); |
2000 | char *sched_name = sched ? sched->name : "none"; | ||
1985 | 2001 | ||
1986 | if (iter->table == ip_vs_svc_table) { | 2002 | if (iter->table == ip_vs_svc_table) { |
1987 | #ifdef CONFIG_IP_VS_IPV6 | 2003 | #ifdef CONFIG_IP_VS_IPV6 |
@@ -1990,18 +2006,18 @@ static int ip_vs_info_seq_show(struct seq_file *seq, void *v) | |||
1990 | ip_vs_proto_name(svc->protocol), | 2006 | ip_vs_proto_name(svc->protocol), |
1991 | &svc->addr.in6, | 2007 | &svc->addr.in6, |
1992 | ntohs(svc->port), | 2008 | ntohs(svc->port), |
1993 | sched->name); | 2009 | sched_name); |
1994 | else | 2010 | else |
1995 | #endif | 2011 | #endif |
1996 | seq_printf(seq, "%s %08X:%04X %s %s ", | 2012 | seq_printf(seq, "%s %08X:%04X %s %s ", |
1997 | ip_vs_proto_name(svc->protocol), | 2013 | ip_vs_proto_name(svc->protocol), |
1998 | ntohl(svc->addr.ip), | 2014 | ntohl(svc->addr.ip), |
1999 | ntohs(svc->port), | 2015 | ntohs(svc->port), |
2000 | sched->name, | 2016 | sched_name, |
2001 | (svc->flags & IP_VS_SVC_F_ONEPACKET)?"ops ":""); | 2017 | (svc->flags & IP_VS_SVC_F_ONEPACKET)?"ops ":""); |
2002 | } else { | 2018 | } else { |
2003 | seq_printf(seq, "FWM %08X %s %s", | 2019 | seq_printf(seq, "FWM %08X %s %s", |
2004 | svc->fwmark, sched->name, | 2020 | svc->fwmark, sched_name, |
2005 | (svc->flags & IP_VS_SVC_F_ONEPACKET)?"ops ":""); | 2021 | (svc->flags & IP_VS_SVC_F_ONEPACKET)?"ops ":""); |
2006 | } | 2022 | } |
2007 | 2023 | ||
@@ -2427,13 +2443,15 @@ ip_vs_copy_service(struct ip_vs_service_entry *dst, struct ip_vs_service *src) | |||
2427 | { | 2443 | { |
2428 | struct ip_vs_scheduler *sched; | 2444 | struct ip_vs_scheduler *sched; |
2429 | struct ip_vs_kstats kstats; | 2445 | struct ip_vs_kstats kstats; |
2446 | char *sched_name; | ||
2430 | 2447 | ||
2431 | sched = rcu_dereference_protected(src->scheduler, 1); | 2448 | sched = rcu_dereference_protected(src->scheduler, 1); |
2449 | sched_name = sched ? sched->name : "none"; | ||
2432 | dst->protocol = src->protocol; | 2450 | dst->protocol = src->protocol; |
2433 | dst->addr = src->addr.ip; | 2451 | dst->addr = src->addr.ip; |
2434 | dst->port = src->port; | 2452 | dst->port = src->port; |
2435 | dst->fwmark = src->fwmark; | 2453 | dst->fwmark = src->fwmark; |
2436 | strlcpy(dst->sched_name, sched->name, sizeof(dst->sched_name)); | 2454 | strlcpy(dst->sched_name, sched_name, sizeof(dst->sched_name)); |
2437 | dst->flags = src->flags; | 2455 | dst->flags = src->flags; |
2438 | dst->timeout = src->timeout / HZ; | 2456 | dst->timeout = src->timeout / HZ; |
2439 | dst->netmask = src->netmask; | 2457 | dst->netmask = src->netmask; |
@@ -2892,6 +2910,7 @@ static int ip_vs_genl_fill_service(struct sk_buff *skb, | |||
2892 | struct ip_vs_flags flags = { .flags = svc->flags, | 2910 | struct ip_vs_flags flags = { .flags = svc->flags, |
2893 | .mask = ~0 }; | 2911 | .mask = ~0 }; |
2894 | struct ip_vs_kstats kstats; | 2912 | struct ip_vs_kstats kstats; |
2913 | char *sched_name; | ||
2895 | 2914 | ||
2896 | nl_service = nla_nest_start(skb, IPVS_CMD_ATTR_SERVICE); | 2915 | nl_service = nla_nest_start(skb, IPVS_CMD_ATTR_SERVICE); |
2897 | if (!nl_service) | 2916 | if (!nl_service) |
@@ -2910,8 +2929,9 @@ static int ip_vs_genl_fill_service(struct sk_buff *skb, | |||
2910 | } | 2929 | } |
2911 | 2930 | ||
2912 | sched = rcu_dereference_protected(svc->scheduler, 1); | 2931 | sched = rcu_dereference_protected(svc->scheduler, 1); |
2932 | sched_name = sched ? sched->name : "none"; | ||
2913 | pe = rcu_dereference_protected(svc->pe, 1); | 2933 | pe = rcu_dereference_protected(svc->pe, 1); |
2914 | if (nla_put_string(skb, IPVS_SVC_ATTR_SCHED_NAME, sched->name) || | 2934 | if (nla_put_string(skb, IPVS_SVC_ATTR_SCHED_NAME, sched_name) || |
2915 | (pe && nla_put_string(skb, IPVS_SVC_ATTR_PE_NAME, pe->name)) || | 2935 | (pe && nla_put_string(skb, IPVS_SVC_ATTR_PE_NAME, pe->name)) || |
2916 | nla_put(skb, IPVS_SVC_ATTR_FLAGS, sizeof(flags), &flags) || | 2936 | nla_put(skb, IPVS_SVC_ATTR_FLAGS, sizeof(flags), &flags) || |
2917 | nla_put_u32(skb, IPVS_SVC_ATTR_TIMEOUT, svc->timeout / HZ) || | 2937 | nla_put_u32(skb, IPVS_SVC_ATTR_TIMEOUT, svc->timeout / HZ) || |
diff --git a/net/netfilter/ipvs/ip_vs_sched.c b/net/netfilter/ipvs/ip_vs_sched.c index 199760c71f39..7e8141647943 100644 --- a/net/netfilter/ipvs/ip_vs_sched.c +++ b/net/netfilter/ipvs/ip_vs_sched.c | |||
@@ -74,7 +74,7 @@ void ip_vs_unbind_scheduler(struct ip_vs_service *svc, | |||
74 | 74 | ||
75 | if (sched->done_service) | 75 | if (sched->done_service) |
76 | sched->done_service(svc); | 76 | sched->done_service(svc); |
77 | /* svc->scheduler can not be set to NULL */ | 77 | /* svc->scheduler can be set to NULL only by caller */ |
78 | } | 78 | } |
79 | 79 | ||
80 | 80 | ||
@@ -147,21 +147,21 @@ void ip_vs_scheduler_put(struct ip_vs_scheduler *scheduler) | |||
147 | 147 | ||
148 | void ip_vs_scheduler_err(struct ip_vs_service *svc, const char *msg) | 148 | void ip_vs_scheduler_err(struct ip_vs_service *svc, const char *msg) |
149 | { | 149 | { |
150 | struct ip_vs_scheduler *sched; | 150 | struct ip_vs_scheduler *sched = rcu_dereference(svc->scheduler); |
151 | char *sched_name = sched ? sched->name : "none"; | ||
151 | 152 | ||
152 | sched = rcu_dereference(svc->scheduler); | ||
153 | if (svc->fwmark) { | 153 | if (svc->fwmark) { |
154 | IP_VS_ERR_RL("%s: FWM %u 0x%08X - %s\n", | 154 | IP_VS_ERR_RL("%s: FWM %u 0x%08X - %s\n", |
155 | sched->name, svc->fwmark, svc->fwmark, msg); | 155 | sched_name, svc->fwmark, svc->fwmark, msg); |
156 | #ifdef CONFIG_IP_VS_IPV6 | 156 | #ifdef CONFIG_IP_VS_IPV6 |
157 | } else if (svc->af == AF_INET6) { | 157 | } else if (svc->af == AF_INET6) { |
158 | IP_VS_ERR_RL("%s: %s [%pI6c]:%d - %s\n", | 158 | IP_VS_ERR_RL("%s: %s [%pI6c]:%d - %s\n", |
159 | sched->name, ip_vs_proto_name(svc->protocol), | 159 | sched_name, ip_vs_proto_name(svc->protocol), |
160 | &svc->addr.in6, ntohs(svc->port), msg); | 160 | &svc->addr.in6, ntohs(svc->port), msg); |
161 | #endif | 161 | #endif |
162 | } else { | 162 | } else { |
163 | IP_VS_ERR_RL("%s: %s %pI4:%d - %s\n", | 163 | IP_VS_ERR_RL("%s: %s %pI4:%d - %s\n", |
164 | sched->name, ip_vs_proto_name(svc->protocol), | 164 | sched_name, ip_vs_proto_name(svc->protocol), |
165 | &svc->addr.ip, ntohs(svc->port), msg); | 165 | &svc->addr.ip, ntohs(svc->port), msg); |
166 | } | 166 | } |
167 | } | 167 | } |
diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c index b08ba9538d12..d99ad93eb855 100644 --- a/net/netfilter/ipvs/ip_vs_sync.c +++ b/net/netfilter/ipvs/ip_vs_sync.c | |||
@@ -612,7 +612,7 @@ static void ip_vs_sync_conn_v0(struct net *net, struct ip_vs_conn *cp, | |||
612 | pkts = atomic_add_return(1, &cp->in_pkts); | 612 | pkts = atomic_add_return(1, &cp->in_pkts); |
613 | else | 613 | else |
614 | pkts = sysctl_sync_threshold(ipvs); | 614 | pkts = sysctl_sync_threshold(ipvs); |
615 | ip_vs_sync_conn(net, cp->control, pkts); | 615 | ip_vs_sync_conn(net, cp, pkts); |
616 | } | 616 | } |
617 | } | 617 | } |
618 | 618 | ||
diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c index bf66a8657a5f..258a0b0e82a2 100644 --- a/net/netfilter/ipvs/ip_vs_xmit.c +++ b/net/netfilter/ipvs/ip_vs_xmit.c | |||
@@ -130,7 +130,6 @@ static struct rtable *do_output_route4(struct net *net, __be32 daddr, | |||
130 | 130 | ||
131 | memset(&fl4, 0, sizeof(fl4)); | 131 | memset(&fl4, 0, sizeof(fl4)); |
132 | fl4.daddr = daddr; | 132 | fl4.daddr = daddr; |
133 | fl4.saddr = (rt_mode & IP_VS_RT_MODE_CONNECT) ? *saddr : 0; | ||
134 | fl4.flowi4_flags = (rt_mode & IP_VS_RT_MODE_KNOWN_NH) ? | 133 | fl4.flowi4_flags = (rt_mode & IP_VS_RT_MODE_KNOWN_NH) ? |
135 | FLOWI_FLAG_KNOWN_NH : 0; | 134 | FLOWI_FLAG_KNOWN_NH : 0; |
136 | 135 | ||
@@ -505,6 +504,13 @@ err_put: | |||
505 | return -1; | 504 | return -1; |
506 | 505 | ||
507 | err_unreach: | 506 | err_unreach: |
507 | /* The ip6_link_failure function requires the dev field to be set | ||
508 | * in order to get the net (further for the sake of fwmark | ||
509 | * reflection). | ||
510 | */ | ||
511 | if (!skb->dev) | ||
512 | skb->dev = skb_dst(skb)->dev; | ||
513 | |||
508 | dst_link_failure(skb); | 514 | dst_link_failure(skb); |
509 | return -1; | 515 | return -1; |
510 | } | 516 | } |
@@ -523,10 +529,27 @@ static inline int ip_vs_tunnel_xmit_prepare(struct sk_buff *skb, | |||
523 | if (ret == NF_ACCEPT) { | 529 | if (ret == NF_ACCEPT) { |
524 | nf_reset(skb); | 530 | nf_reset(skb); |
525 | skb_forward_csum(skb); | 531 | skb_forward_csum(skb); |
532 | if (!skb->sk) | ||
533 | skb_sender_cpu_clear(skb); | ||
526 | } | 534 | } |
527 | return ret; | 535 | return ret; |
528 | } | 536 | } |
529 | 537 | ||
538 | /* In the event of a remote destination, it's possible that we would have | ||
539 | * matches against an old socket (particularly a TIME-WAIT socket). This | ||
540 | * causes havoc down the line (ip_local_out et. al. expect regular sockets | ||
541 | * and invalid memory accesses will happen) so simply drop the association | ||
542 | * in this case. | ||
543 | */ | ||
544 | static inline void ip_vs_drop_early_demux_sk(struct sk_buff *skb) | ||
545 | { | ||
546 | /* If dev is set, the packet came from the LOCAL_IN callback and | ||
547 | * not from a local TCP socket. | ||
548 | */ | ||
549 | if (skb->dev) | ||
550 | skb_orphan(skb); | ||
551 | } | ||
552 | |||
530 | /* return NF_STOLEN (sent) or NF_ACCEPT if local=1 (not sent) */ | 553 | /* return NF_STOLEN (sent) or NF_ACCEPT if local=1 (not sent) */ |
531 | static inline int ip_vs_nat_send_or_cont(int pf, struct sk_buff *skb, | 554 | static inline int ip_vs_nat_send_or_cont(int pf, struct sk_buff *skb, |
532 | struct ip_vs_conn *cp, int local) | 555 | struct ip_vs_conn *cp, int local) |
@@ -538,12 +561,23 @@ static inline int ip_vs_nat_send_or_cont(int pf, struct sk_buff *skb, | |||
538 | ip_vs_notrack(skb); | 561 | ip_vs_notrack(skb); |
539 | else | 562 | else |
540 | ip_vs_update_conntrack(skb, cp, 1); | 563 | ip_vs_update_conntrack(skb, cp, 1); |
564 | |||
565 | /* Remove the early_demux association unless it's bound for the | ||
566 | * exact same port and address on this host after translation. | ||
567 | */ | ||
568 | if (!local || cp->vport != cp->dport || | ||
569 | !ip_vs_addr_equal(cp->af, &cp->vaddr, &cp->daddr)) | ||
570 | ip_vs_drop_early_demux_sk(skb); | ||
571 | |||
541 | if (!local) { | 572 | if (!local) { |
542 | skb_forward_csum(skb); | 573 | skb_forward_csum(skb); |
574 | if (!skb->sk) | ||
575 | skb_sender_cpu_clear(skb); | ||
543 | NF_HOOK(pf, NF_INET_LOCAL_OUT, NULL, skb, | 576 | NF_HOOK(pf, NF_INET_LOCAL_OUT, NULL, skb, |
544 | NULL, skb_dst(skb)->dev, dst_output_sk); | 577 | NULL, skb_dst(skb)->dev, dst_output_sk); |
545 | } else | 578 | } else |
546 | ret = NF_ACCEPT; | 579 | ret = NF_ACCEPT; |
580 | |||
547 | return ret; | 581 | return ret; |
548 | } | 582 | } |
549 | 583 | ||
@@ -557,7 +591,10 @@ static inline int ip_vs_send_or_cont(int pf, struct sk_buff *skb, | |||
557 | if (likely(!(cp->flags & IP_VS_CONN_F_NFCT))) | 591 | if (likely(!(cp->flags & IP_VS_CONN_F_NFCT))) |
558 | ip_vs_notrack(skb); | 592 | ip_vs_notrack(skb); |
559 | if (!local) { | 593 | if (!local) { |
594 | ip_vs_drop_early_demux_sk(skb); | ||
560 | skb_forward_csum(skb); | 595 | skb_forward_csum(skb); |
596 | if (!skb->sk) | ||
597 | skb_sender_cpu_clear(skb); | ||
561 | NF_HOOK(pf, NF_INET_LOCAL_OUT, NULL, skb, | 598 | NF_HOOK(pf, NF_INET_LOCAL_OUT, NULL, skb, |
562 | NULL, skb_dst(skb)->dev, dst_output_sk); | 599 | NULL, skb_dst(skb)->dev, dst_output_sk); |
563 | } else | 600 | } else |
@@ -845,6 +882,8 @@ ip_vs_prepare_tunneled_skb(struct sk_buff *skb, int skb_af, | |||
845 | struct ipv6hdr *old_ipv6h = NULL; | 882 | struct ipv6hdr *old_ipv6h = NULL; |
846 | #endif | 883 | #endif |
847 | 884 | ||
885 | ip_vs_drop_early_demux_sk(skb); | ||
886 | |||
848 | if (skb_headroom(skb) < max_headroom || skb_cloned(skb)) { | 887 | if (skb_headroom(skb) < max_headroom || skb_cloned(skb)) { |
849 | new_skb = skb_realloc_headroom(skb, max_headroom); | 888 | new_skb = skb_realloc_headroom(skb, max_headroom); |
850 | if (!new_skb) | 889 | if (!new_skb) |
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 13fad8668f83..3c20d02aee73 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c | |||
@@ -287,6 +287,46 @@ static void nf_ct_del_from_dying_or_unconfirmed_list(struct nf_conn *ct) | |||
287 | spin_unlock(&pcpu->lock); | 287 | spin_unlock(&pcpu->lock); |
288 | } | 288 | } |
289 | 289 | ||
290 | /* Released via destroy_conntrack() */ | ||
291 | struct nf_conn *nf_ct_tmpl_alloc(struct net *net, u16 zone, gfp_t flags) | ||
292 | { | ||
293 | struct nf_conn *tmpl; | ||
294 | |||
295 | tmpl = kzalloc(sizeof(*tmpl), flags); | ||
296 | if (tmpl == NULL) | ||
297 | return NULL; | ||
298 | |||
299 | tmpl->status = IPS_TEMPLATE; | ||
300 | write_pnet(&tmpl->ct_net, net); | ||
301 | |||
302 | #ifdef CONFIG_NF_CONNTRACK_ZONES | ||
303 | if (zone) { | ||
304 | struct nf_conntrack_zone *nf_ct_zone; | ||
305 | |||
306 | nf_ct_zone = nf_ct_ext_add(tmpl, NF_CT_EXT_ZONE, flags); | ||
307 | if (!nf_ct_zone) | ||
308 | goto out_free; | ||
309 | nf_ct_zone->id = zone; | ||
310 | } | ||
311 | #endif | ||
312 | atomic_set(&tmpl->ct_general.use, 0); | ||
313 | |||
314 | return tmpl; | ||
315 | #ifdef CONFIG_NF_CONNTRACK_ZONES | ||
316 | out_free: | ||
317 | kfree(tmpl); | ||
318 | return NULL; | ||
319 | #endif | ||
320 | } | ||
321 | EXPORT_SYMBOL_GPL(nf_ct_tmpl_alloc); | ||
322 | |||
323 | static void nf_ct_tmpl_free(struct nf_conn *tmpl) | ||
324 | { | ||
325 | nf_ct_ext_destroy(tmpl); | ||
326 | nf_ct_ext_free(tmpl); | ||
327 | kfree(tmpl); | ||
328 | } | ||
329 | |||
290 | static void | 330 | static void |
291 | destroy_conntrack(struct nf_conntrack *nfct) | 331 | destroy_conntrack(struct nf_conntrack *nfct) |
292 | { | 332 | { |
@@ -298,6 +338,10 @@ destroy_conntrack(struct nf_conntrack *nfct) | |||
298 | NF_CT_ASSERT(atomic_read(&nfct->use) == 0); | 338 | NF_CT_ASSERT(atomic_read(&nfct->use) == 0); |
299 | NF_CT_ASSERT(!timer_pending(&ct->timeout)); | 339 | NF_CT_ASSERT(!timer_pending(&ct->timeout)); |
300 | 340 | ||
341 | if (unlikely(nf_ct_is_template(ct))) { | ||
342 | nf_ct_tmpl_free(ct); | ||
343 | return; | ||
344 | } | ||
301 | rcu_read_lock(); | 345 | rcu_read_lock(); |
302 | l4proto = __nf_ct_l4proto_find(nf_ct_l3num(ct), nf_ct_protonum(ct)); | 346 | l4proto = __nf_ct_l4proto_find(nf_ct_l3num(ct), nf_ct_protonum(ct)); |
303 | if (l4proto && l4proto->destroy) | 347 | if (l4proto && l4proto->destroy) |
@@ -540,28 +584,6 @@ out: | |||
540 | } | 584 | } |
541 | EXPORT_SYMBOL_GPL(nf_conntrack_hash_check_insert); | 585 | EXPORT_SYMBOL_GPL(nf_conntrack_hash_check_insert); |
542 | 586 | ||
543 | /* deletion from this larval template list happens via nf_ct_put() */ | ||
544 | void nf_conntrack_tmpl_insert(struct net *net, struct nf_conn *tmpl) | ||
545 | { | ||
546 | struct ct_pcpu *pcpu; | ||
547 | |||
548 | __set_bit(IPS_TEMPLATE_BIT, &tmpl->status); | ||
549 | __set_bit(IPS_CONFIRMED_BIT, &tmpl->status); | ||
550 | nf_conntrack_get(&tmpl->ct_general); | ||
551 | |||
552 | /* add this conntrack to the (per cpu) tmpl list */ | ||
553 | local_bh_disable(); | ||
554 | tmpl->cpu = smp_processor_id(); | ||
555 | pcpu = per_cpu_ptr(nf_ct_net(tmpl)->ct.pcpu_lists, tmpl->cpu); | ||
556 | |||
557 | spin_lock(&pcpu->lock); | ||
558 | /* Overload tuple linked list to put us in template list. */ | ||
559 | hlist_nulls_add_head_rcu(&tmpl->tuplehash[IP_CT_DIR_ORIGINAL].hnnode, | ||
560 | &pcpu->tmpl); | ||
561 | spin_unlock_bh(&pcpu->lock); | ||
562 | } | ||
563 | EXPORT_SYMBOL_GPL(nf_conntrack_tmpl_insert); | ||
564 | |||
565 | /* Confirm a connection given skb; places it in hash table */ | 587 | /* Confirm a connection given skb; places it in hash table */ |
566 | int | 588 | int |
567 | __nf_conntrack_confirm(struct sk_buff *skb) | 589 | __nf_conntrack_confirm(struct sk_buff *skb) |
@@ -1522,10 +1544,8 @@ void *nf_ct_alloc_hashtable(unsigned int *sizep, int nulls) | |||
1522 | sz = nr_slots * sizeof(struct hlist_nulls_head); | 1544 | sz = nr_slots * sizeof(struct hlist_nulls_head); |
1523 | hash = (void *)__get_free_pages(GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO, | 1545 | hash = (void *)__get_free_pages(GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO, |
1524 | get_order(sz)); | 1546 | get_order(sz)); |
1525 | if (!hash) { | 1547 | if (!hash) |
1526 | printk(KERN_WARNING "nf_conntrack: falling back to vmalloc.\n"); | ||
1527 | hash = vzalloc(sz); | 1548 | hash = vzalloc(sz); |
1528 | } | ||
1529 | 1549 | ||
1530 | if (hash && nulls) | 1550 | if (hash && nulls) |
1531 | for (i = 0; i < nr_slots; i++) | 1551 | for (i = 0; i < nr_slots; i++) |
@@ -1751,7 +1771,6 @@ int nf_conntrack_init_net(struct net *net) | |||
1751 | spin_lock_init(&pcpu->lock); | 1771 | spin_lock_init(&pcpu->lock); |
1752 | INIT_HLIST_NULLS_HEAD(&pcpu->unconfirmed, UNCONFIRMED_NULLS_VAL); | 1772 | INIT_HLIST_NULLS_HEAD(&pcpu->unconfirmed, UNCONFIRMED_NULLS_VAL); |
1753 | INIT_HLIST_NULLS_HEAD(&pcpu->dying, DYING_NULLS_VAL); | 1773 | INIT_HLIST_NULLS_HEAD(&pcpu->dying, DYING_NULLS_VAL); |
1754 | INIT_HLIST_NULLS_HEAD(&pcpu->tmpl, TEMPLATE_NULLS_VAL); | ||
1755 | } | 1774 | } |
1756 | 1775 | ||
1757 | net->ct.stat = alloc_percpu(struct ip_conntrack_stat); | 1776 | net->ct.stat = alloc_percpu(struct ip_conntrack_stat); |
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c index 7a17070c5dab..b45a4223cb05 100644 --- a/net/netfilter/nf_conntrack_expect.c +++ b/net/netfilter/nf_conntrack_expect.c | |||
@@ -219,7 +219,8 @@ static inline int expect_clash(const struct nf_conntrack_expect *a, | |||
219 | a->mask.src.u3.all[count] & b->mask.src.u3.all[count]; | 219 | a->mask.src.u3.all[count] & b->mask.src.u3.all[count]; |
220 | } | 220 | } |
221 | 221 | ||
222 | return nf_ct_tuple_mask_cmp(&a->tuple, &b->tuple, &intersect_mask); | 222 | return nf_ct_tuple_mask_cmp(&a->tuple, &b->tuple, &intersect_mask) && |
223 | nf_ct_zone(a->master) == nf_ct_zone(b->master); | ||
223 | } | 224 | } |
224 | 225 | ||
225 | static inline int expect_matches(const struct nf_conntrack_expect *a, | 226 | static inline int expect_matches(const struct nf_conntrack_expect *a, |
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index d1c23940a86a..6b8b0abbfab4 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c | |||
@@ -2995,11 +2995,6 @@ ctnetlink_create_expect(struct net *net, u16 zone, | |||
2995 | } | 2995 | } |
2996 | 2996 | ||
2997 | err = nf_ct_expect_related_report(exp, portid, report); | 2997 | err = nf_ct_expect_related_report(exp, portid, report); |
2998 | if (err < 0) | ||
2999 | goto err_exp; | ||
3000 | |||
3001 | return 0; | ||
3002 | err_exp: | ||
3003 | nf_ct_expect_put(exp); | 2998 | nf_ct_expect_put(exp); |
3004 | err_ct: | 2999 | err_ct: |
3005 | nf_ct_put(ct); | 3000 | nf_ct_put(ct); |
diff --git a/net/netfilter/nf_synproxy_core.c b/net/netfilter/nf_synproxy_core.c index 789feeae6c44..d7f168527903 100644 --- a/net/netfilter/nf_synproxy_core.c +++ b/net/netfilter/nf_synproxy_core.c | |||
@@ -349,23 +349,20 @@ static void __net_exit synproxy_proc_exit(struct net *net) | |||
349 | static int __net_init synproxy_net_init(struct net *net) | 349 | static int __net_init synproxy_net_init(struct net *net) |
350 | { | 350 | { |
351 | struct synproxy_net *snet = synproxy_pernet(net); | 351 | struct synproxy_net *snet = synproxy_pernet(net); |
352 | struct nf_conntrack_tuple t; | ||
353 | struct nf_conn *ct; | 352 | struct nf_conn *ct; |
354 | int err = -ENOMEM; | 353 | int err = -ENOMEM; |
355 | 354 | ||
356 | memset(&t, 0, sizeof(t)); | 355 | ct = nf_ct_tmpl_alloc(net, 0, GFP_KERNEL); |
357 | ct = nf_conntrack_alloc(net, 0, &t, &t, GFP_KERNEL); | 356 | if (!ct) |
358 | if (IS_ERR(ct)) { | ||
359 | err = PTR_ERR(ct); | ||
360 | goto err1; | 357 | goto err1; |
361 | } | ||
362 | 358 | ||
363 | if (!nfct_seqadj_ext_add(ct)) | 359 | if (!nfct_seqadj_ext_add(ct)) |
364 | goto err2; | 360 | goto err2; |
365 | if (!nfct_synproxy_ext_add(ct)) | 361 | if (!nfct_synproxy_ext_add(ct)) |
366 | goto err2; | 362 | goto err2; |
367 | 363 | ||
368 | nf_conntrack_tmpl_insert(net, ct); | 364 | __set_bit(IPS_CONFIRMED_BIT, &ct->status); |
365 | nf_conntrack_get(&ct->ct_general); | ||
369 | snet->tmpl = ct; | 366 | snet->tmpl = ct; |
370 | 367 | ||
371 | snet->stats = alloc_percpu(struct synproxy_stats); | 368 | snet->stats = alloc_percpu(struct synproxy_stats); |
diff --git a/net/netfilter/xt_CT.c b/net/netfilter/xt_CT.c index 75747aecdebe..43ddeee404e9 100644 --- a/net/netfilter/xt_CT.c +++ b/net/netfilter/xt_CT.c | |||
@@ -184,7 +184,6 @@ out: | |||
184 | static int xt_ct_tg_check(const struct xt_tgchk_param *par, | 184 | static int xt_ct_tg_check(const struct xt_tgchk_param *par, |
185 | struct xt_ct_target_info_v1 *info) | 185 | struct xt_ct_target_info_v1 *info) |
186 | { | 186 | { |
187 | struct nf_conntrack_tuple t; | ||
188 | struct nf_conn *ct; | 187 | struct nf_conn *ct; |
189 | int ret = -EOPNOTSUPP; | 188 | int ret = -EOPNOTSUPP; |
190 | 189 | ||
@@ -202,11 +201,11 @@ static int xt_ct_tg_check(const struct xt_tgchk_param *par, | |||
202 | if (ret < 0) | 201 | if (ret < 0) |
203 | goto err1; | 202 | goto err1; |
204 | 203 | ||
205 | memset(&t, 0, sizeof(t)); | 204 | ct = nf_ct_tmpl_alloc(par->net, info->zone, GFP_KERNEL); |
206 | ct = nf_conntrack_alloc(par->net, info->zone, &t, &t, GFP_KERNEL); | 205 | if (!ct) { |
207 | ret = PTR_ERR(ct); | 206 | ret = -ENOMEM; |
208 | if (IS_ERR(ct)) | ||
209 | goto err2; | 207 | goto err2; |
208 | } | ||
210 | 209 | ||
211 | ret = 0; | 210 | ret = 0; |
212 | if ((info->ct_events || info->exp_events) && | 211 | if ((info->ct_events || info->exp_events) && |
@@ -227,8 +226,8 @@ static int xt_ct_tg_check(const struct xt_tgchk_param *par, | |||
227 | if (ret < 0) | 226 | if (ret < 0) |
228 | goto err3; | 227 | goto err3; |
229 | } | 228 | } |
230 | 229 | __set_bit(IPS_CONFIRMED_BIT, &ct->status); | |
231 | nf_conntrack_tmpl_insert(par->net, ct); | 230 | nf_conntrack_get(&ct->ct_general); |
232 | out: | 231 | out: |
233 | info->ct = ct; | 232 | info->ct = ct; |
234 | return 0; | 233 | return 0; |
diff --git a/net/netfilter/xt_IDLETIMER.c b/net/netfilter/xt_IDLETIMER.c index f407ebc13481..29d2c31f406c 100644 --- a/net/netfilter/xt_IDLETIMER.c +++ b/net/netfilter/xt_IDLETIMER.c | |||
@@ -126,6 +126,7 @@ static int idletimer_tg_create(struct idletimer_tg_info *info) | |||
126 | goto out; | 126 | goto out; |
127 | } | 127 | } |
128 | 128 | ||
129 | sysfs_attr_init(&info->timer->attr.attr); | ||
129 | info->timer->attr.attr.name = kstrdup(info->label, GFP_KERNEL); | 130 | info->timer->attr.attr.name = kstrdup(info->label, GFP_KERNEL); |
130 | if (!info->timer->attr.attr.name) { | 131 | if (!info->timer->attr.attr.name) { |
131 | ret = -ENOMEM; | 132 | ret = -ENOMEM; |
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 9a0ae7172f92..67d210477863 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
@@ -357,25 +357,52 @@ err1: | |||
357 | return NULL; | 357 | return NULL; |
358 | } | 358 | } |
359 | 359 | ||
360 | |||
361 | static void | ||
362 | __netlink_set_ring(struct sock *sk, struct nl_mmap_req *req, bool tx_ring, void **pg_vec, | ||
363 | unsigned int order) | ||
364 | { | ||
365 | struct netlink_sock *nlk = nlk_sk(sk); | ||
366 | struct sk_buff_head *queue; | ||
367 | struct netlink_ring *ring; | ||
368 | |||
369 | queue = tx_ring ? &sk->sk_write_queue : &sk->sk_receive_queue; | ||
370 | ring = tx_ring ? &nlk->tx_ring : &nlk->rx_ring; | ||
371 | |||
372 | spin_lock_bh(&queue->lock); | ||
373 | |||
374 | ring->frame_max = req->nm_frame_nr - 1; | ||
375 | ring->head = 0; | ||
376 | ring->frame_size = req->nm_frame_size; | ||
377 | ring->pg_vec_pages = req->nm_block_size / PAGE_SIZE; | ||
378 | |||
379 | swap(ring->pg_vec_len, req->nm_block_nr); | ||
380 | swap(ring->pg_vec_order, order); | ||
381 | swap(ring->pg_vec, pg_vec); | ||
382 | |||
383 | __skb_queue_purge(queue); | ||
384 | spin_unlock_bh(&queue->lock); | ||
385 | |||
386 | WARN_ON(atomic_read(&nlk->mapped)); | ||
387 | |||
388 | if (pg_vec) | ||
389 | free_pg_vec(pg_vec, order, req->nm_block_nr); | ||
390 | } | ||
391 | |||
360 | static int netlink_set_ring(struct sock *sk, struct nl_mmap_req *req, | 392 | static int netlink_set_ring(struct sock *sk, struct nl_mmap_req *req, |
361 | bool closing, bool tx_ring) | 393 | bool tx_ring) |
362 | { | 394 | { |
363 | struct netlink_sock *nlk = nlk_sk(sk); | 395 | struct netlink_sock *nlk = nlk_sk(sk); |
364 | struct netlink_ring *ring; | 396 | struct netlink_ring *ring; |
365 | struct sk_buff_head *queue; | ||
366 | void **pg_vec = NULL; | 397 | void **pg_vec = NULL; |
367 | unsigned int order = 0; | 398 | unsigned int order = 0; |
368 | int err; | ||
369 | 399 | ||
370 | ring = tx_ring ? &nlk->tx_ring : &nlk->rx_ring; | 400 | ring = tx_ring ? &nlk->tx_ring : &nlk->rx_ring; |
371 | queue = tx_ring ? &sk->sk_write_queue : &sk->sk_receive_queue; | ||
372 | 401 | ||
373 | if (!closing) { | 402 | if (atomic_read(&nlk->mapped)) |
374 | if (atomic_read(&nlk->mapped)) | 403 | return -EBUSY; |
375 | return -EBUSY; | 404 | if (atomic_read(&ring->pending)) |
376 | if (atomic_read(&ring->pending)) | 405 | return -EBUSY; |
377 | return -EBUSY; | ||
378 | } | ||
379 | 406 | ||
380 | if (req->nm_block_nr) { | 407 | if (req->nm_block_nr) { |
381 | if (ring->pg_vec != NULL) | 408 | if (ring->pg_vec != NULL) |
@@ -407,31 +434,19 @@ static int netlink_set_ring(struct sock *sk, struct nl_mmap_req *req, | |||
407 | return -EINVAL; | 434 | return -EINVAL; |
408 | } | 435 | } |
409 | 436 | ||
410 | err = -EBUSY; | ||
411 | mutex_lock(&nlk->pg_vec_lock); | 437 | mutex_lock(&nlk->pg_vec_lock); |
412 | if (closing || atomic_read(&nlk->mapped) == 0) { | 438 | if (atomic_read(&nlk->mapped) == 0) { |
413 | err = 0; | 439 | __netlink_set_ring(sk, req, tx_ring, pg_vec, order); |
414 | spin_lock_bh(&queue->lock); | 440 | mutex_unlock(&nlk->pg_vec_lock); |
415 | 441 | return 0; | |
416 | ring->frame_max = req->nm_frame_nr - 1; | ||
417 | ring->head = 0; | ||
418 | ring->frame_size = req->nm_frame_size; | ||
419 | ring->pg_vec_pages = req->nm_block_size / PAGE_SIZE; | ||
420 | |||
421 | swap(ring->pg_vec_len, req->nm_block_nr); | ||
422 | swap(ring->pg_vec_order, order); | ||
423 | swap(ring->pg_vec, pg_vec); | ||
424 | |||
425 | __skb_queue_purge(queue); | ||
426 | spin_unlock_bh(&queue->lock); | ||
427 | |||
428 | WARN_ON(atomic_read(&nlk->mapped)); | ||
429 | } | 442 | } |
443 | |||
430 | mutex_unlock(&nlk->pg_vec_lock); | 444 | mutex_unlock(&nlk->pg_vec_lock); |
431 | 445 | ||
432 | if (pg_vec) | 446 | if (pg_vec) |
433 | free_pg_vec(pg_vec, order, req->nm_block_nr); | 447 | free_pg_vec(pg_vec, order, req->nm_block_nr); |
434 | return err; | 448 | |
449 | return -EBUSY; | ||
435 | } | 450 | } |
436 | 451 | ||
437 | static void netlink_mm_open(struct vm_area_struct *vma) | 452 | static void netlink_mm_open(struct vm_area_struct *vma) |
@@ -900,10 +915,10 @@ static void netlink_sock_destruct(struct sock *sk) | |||
900 | 915 | ||
901 | memset(&req, 0, sizeof(req)); | 916 | memset(&req, 0, sizeof(req)); |
902 | if (nlk->rx_ring.pg_vec) | 917 | if (nlk->rx_ring.pg_vec) |
903 | netlink_set_ring(sk, &req, true, false); | 918 | __netlink_set_ring(sk, &req, false, NULL, 0); |
904 | memset(&req, 0, sizeof(req)); | 919 | memset(&req, 0, sizeof(req)); |
905 | if (nlk->tx_ring.pg_vec) | 920 | if (nlk->tx_ring.pg_vec) |
906 | netlink_set_ring(sk, &req, true, true); | 921 | __netlink_set_ring(sk, &req, true, NULL, 0); |
907 | } | 922 | } |
908 | #endif /* CONFIG_NETLINK_MMAP */ | 923 | #endif /* CONFIG_NETLINK_MMAP */ |
909 | 924 | ||
@@ -1081,6 +1096,11 @@ static int netlink_insert(struct sock *sk, u32 portid) | |||
1081 | 1096 | ||
1082 | err = __netlink_insert(table, sk); | 1097 | err = __netlink_insert(table, sk); |
1083 | if (err) { | 1098 | if (err) { |
1099 | /* In case the hashtable backend returns with -EBUSY | ||
1100 | * from here, it must not escape to the caller. | ||
1101 | */ | ||
1102 | if (unlikely(err == -EBUSY)) | ||
1103 | err = -EOVERFLOW; | ||
1084 | if (err == -EEXIST) | 1104 | if (err == -EEXIST) |
1085 | err = -EADDRINUSE; | 1105 | err = -EADDRINUSE; |
1086 | nlk_sk(sk)->portid = 0; | 1106 | nlk_sk(sk)->portid = 0; |
@@ -2223,7 +2243,7 @@ static int netlink_setsockopt(struct socket *sock, int level, int optname, | |||
2223 | return -EINVAL; | 2243 | return -EINVAL; |
2224 | if (copy_from_user(&req, optval, sizeof(req))) | 2244 | if (copy_from_user(&req, optval, sizeof(req))) |
2225 | return -EFAULT; | 2245 | return -EFAULT; |
2226 | err = netlink_set_ring(sk, &req, false, | 2246 | err = netlink_set_ring(sk, &req, |
2227 | optname == NETLINK_TX_RING); | 2247 | optname == NETLINK_TX_RING); |
2228 | break; | 2248 | break; |
2229 | } | 2249 | } |
diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c index 8a8c0b8b4f63..ee34f474ad14 100644 --- a/net/openvswitch/actions.c +++ b/net/openvswitch/actions.c | |||
@@ -273,28 +273,36 @@ static int set_eth_addr(struct sk_buff *skb, struct sw_flow_key *flow_key, | |||
273 | return 0; | 273 | return 0; |
274 | } | 274 | } |
275 | 275 | ||
276 | static void set_ip_addr(struct sk_buff *skb, struct iphdr *nh, | 276 | static void update_ip_l4_checksum(struct sk_buff *skb, struct iphdr *nh, |
277 | __be32 *addr, __be32 new_addr) | 277 | __be32 addr, __be32 new_addr) |
278 | { | 278 | { |
279 | int transport_len = skb->len - skb_transport_offset(skb); | 279 | int transport_len = skb->len - skb_transport_offset(skb); |
280 | 280 | ||
281 | if (nh->frag_off & htons(IP_OFFSET)) | ||
282 | return; | ||
283 | |||
281 | if (nh->protocol == IPPROTO_TCP) { | 284 | if (nh->protocol == IPPROTO_TCP) { |
282 | if (likely(transport_len >= sizeof(struct tcphdr))) | 285 | if (likely(transport_len >= sizeof(struct tcphdr))) |
283 | inet_proto_csum_replace4(&tcp_hdr(skb)->check, skb, | 286 | inet_proto_csum_replace4(&tcp_hdr(skb)->check, skb, |
284 | *addr, new_addr, 1); | 287 | addr, new_addr, 1); |
285 | } else if (nh->protocol == IPPROTO_UDP) { | 288 | } else if (nh->protocol == IPPROTO_UDP) { |
286 | if (likely(transport_len >= sizeof(struct udphdr))) { | 289 | if (likely(transport_len >= sizeof(struct udphdr))) { |
287 | struct udphdr *uh = udp_hdr(skb); | 290 | struct udphdr *uh = udp_hdr(skb); |
288 | 291 | ||
289 | if (uh->check || skb->ip_summed == CHECKSUM_PARTIAL) { | 292 | if (uh->check || skb->ip_summed == CHECKSUM_PARTIAL) { |
290 | inet_proto_csum_replace4(&uh->check, skb, | 293 | inet_proto_csum_replace4(&uh->check, skb, |
291 | *addr, new_addr, 1); | 294 | addr, new_addr, 1); |
292 | if (!uh->check) | 295 | if (!uh->check) |
293 | uh->check = CSUM_MANGLED_0; | 296 | uh->check = CSUM_MANGLED_0; |
294 | } | 297 | } |
295 | } | 298 | } |
296 | } | 299 | } |
300 | } | ||
297 | 301 | ||
302 | static void set_ip_addr(struct sk_buff *skb, struct iphdr *nh, | ||
303 | __be32 *addr, __be32 new_addr) | ||
304 | { | ||
305 | update_ip_l4_checksum(skb, nh, *addr, new_addr); | ||
298 | csum_replace4(&nh->check, *addr, new_addr); | 306 | csum_replace4(&nh->check, *addr, new_addr); |
299 | skb_clear_hash(skb); | 307 | skb_clear_hash(skb); |
300 | *addr = new_addr; | 308 | *addr = new_addr; |
diff --git a/net/openvswitch/flow_table.c b/net/openvswitch/flow_table.c index 4613df8c8290..65523948fb95 100644 --- a/net/openvswitch/flow_table.c +++ b/net/openvswitch/flow_table.c | |||
@@ -752,7 +752,7 @@ int ovs_flow_init(void) | |||
752 | BUILD_BUG_ON(sizeof(struct sw_flow_key) % sizeof(long)); | 752 | BUILD_BUG_ON(sizeof(struct sw_flow_key) % sizeof(long)); |
753 | 753 | ||
754 | flow_cache = kmem_cache_create("sw_flow", sizeof(struct sw_flow) | 754 | flow_cache = kmem_cache_create("sw_flow", sizeof(struct sw_flow) |
755 | + (num_possible_nodes() | 755 | + (nr_node_ids |
756 | * sizeof(struct flow_stats *)), | 756 | * sizeof(struct flow_stats *)), |
757 | 0, 0, NULL); | 757 | 0, 0, NULL); |
758 | if (flow_cache == NULL) | 758 | if (flow_cache == NULL) |
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index c9e8741226c6..ed458b315ef4 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
@@ -2403,7 +2403,8 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) | |||
2403 | } | 2403 | } |
2404 | tp_len = tpacket_fill_skb(po, skb, ph, dev, size_max, proto, | 2404 | tp_len = tpacket_fill_skb(po, skb, ph, dev, size_max, proto, |
2405 | addr, hlen); | 2405 | addr, hlen); |
2406 | if (tp_len > dev->mtu + dev->hard_header_len) { | 2406 | if (likely(tp_len >= 0) && |
2407 | tp_len > dev->mtu + dev->hard_header_len) { | ||
2407 | struct ethhdr *ehdr; | 2408 | struct ethhdr *ehdr; |
2408 | /* Earlier code assumed this would be a VLAN pkt, | 2409 | /* Earlier code assumed this would be a VLAN pkt, |
2409 | * double-check this now that we have the actual | 2410 | * double-check this now that we have the actual |
@@ -2784,7 +2785,7 @@ static int packet_release(struct socket *sock) | |||
2784 | static int packet_do_bind(struct sock *sk, struct net_device *dev, __be16 proto) | 2785 | static int packet_do_bind(struct sock *sk, struct net_device *dev, __be16 proto) |
2785 | { | 2786 | { |
2786 | struct packet_sock *po = pkt_sk(sk); | 2787 | struct packet_sock *po = pkt_sk(sk); |
2787 | const struct net_device *dev_curr; | 2788 | struct net_device *dev_curr; |
2788 | __be16 proto_curr; | 2789 | __be16 proto_curr; |
2789 | bool need_rehook; | 2790 | bool need_rehook; |
2790 | 2791 | ||
@@ -2808,15 +2809,13 @@ static int packet_do_bind(struct sock *sk, struct net_device *dev, __be16 proto) | |||
2808 | 2809 | ||
2809 | po->num = proto; | 2810 | po->num = proto; |
2810 | po->prot_hook.type = proto; | 2811 | po->prot_hook.type = proto; |
2811 | |||
2812 | if (po->prot_hook.dev) | ||
2813 | dev_put(po->prot_hook.dev); | ||
2814 | |||
2815 | po->prot_hook.dev = dev; | 2812 | po->prot_hook.dev = dev; |
2816 | 2813 | ||
2817 | po->ifindex = dev ? dev->ifindex : 0; | 2814 | po->ifindex = dev ? dev->ifindex : 0; |
2818 | packet_cached_dev_assign(po, dev); | 2815 | packet_cached_dev_assign(po, dev); |
2819 | } | 2816 | } |
2817 | if (dev_curr) | ||
2818 | dev_put(dev_curr); | ||
2820 | 2819 | ||
2821 | if (proto == 0 || !need_rehook) | 2820 | if (proto == 0 || !need_rehook) |
2822 | goto out_unlock; | 2821 | goto out_unlock; |
diff --git a/net/rds/info.c b/net/rds/info.c index 9a6b4f66187c..140a44a5f7b7 100644 --- a/net/rds/info.c +++ b/net/rds/info.c | |||
@@ -176,7 +176,7 @@ int rds_info_getsockopt(struct socket *sock, int optname, char __user *optval, | |||
176 | 176 | ||
177 | /* check for all kinds of wrapping and the like */ | 177 | /* check for all kinds of wrapping and the like */ |
178 | start = (unsigned long)optval; | 178 | start = (unsigned long)optval; |
179 | if (len < 0 || len + PAGE_SIZE - 1 < len || start + len < start) { | 179 | if (len < 0 || len > INT_MAX - PAGE_SIZE + 1 || start + len < start) { |
180 | ret = -EINVAL; | 180 | ret = -EINVAL; |
181 | goto out; | 181 | goto out; |
182 | } | 182 | } |
diff --git a/net/sched/act_api.c b/net/sched/act_api.c index af427a3dbcba..43ec92680ae8 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c | |||
@@ -45,7 +45,7 @@ void tcf_hash_destroy(struct tc_action *a) | |||
45 | } | 45 | } |
46 | EXPORT_SYMBOL(tcf_hash_destroy); | 46 | EXPORT_SYMBOL(tcf_hash_destroy); |
47 | 47 | ||
48 | int tcf_hash_release(struct tc_action *a, int bind) | 48 | int __tcf_hash_release(struct tc_action *a, bool bind, bool strict) |
49 | { | 49 | { |
50 | struct tcf_common *p = a->priv; | 50 | struct tcf_common *p = a->priv; |
51 | int ret = 0; | 51 | int ret = 0; |
@@ -53,7 +53,7 @@ int tcf_hash_release(struct tc_action *a, int bind) | |||
53 | if (p) { | 53 | if (p) { |
54 | if (bind) | 54 | if (bind) |
55 | p->tcfc_bindcnt--; | 55 | p->tcfc_bindcnt--; |
56 | else if (p->tcfc_bindcnt > 0) | 56 | else if (strict && p->tcfc_bindcnt > 0) |
57 | return -EPERM; | 57 | return -EPERM; |
58 | 58 | ||
59 | p->tcfc_refcnt--; | 59 | p->tcfc_refcnt--; |
@@ -64,9 +64,10 @@ int tcf_hash_release(struct tc_action *a, int bind) | |||
64 | ret = 1; | 64 | ret = 1; |
65 | } | 65 | } |
66 | } | 66 | } |
67 | |||
67 | return ret; | 68 | return ret; |
68 | } | 69 | } |
69 | EXPORT_SYMBOL(tcf_hash_release); | 70 | EXPORT_SYMBOL(__tcf_hash_release); |
70 | 71 | ||
71 | static int tcf_dump_walker(struct sk_buff *skb, struct netlink_callback *cb, | 72 | static int tcf_dump_walker(struct sk_buff *skb, struct netlink_callback *cb, |
72 | struct tc_action *a) | 73 | struct tc_action *a) |
@@ -136,7 +137,7 @@ static int tcf_del_walker(struct sk_buff *skb, struct tc_action *a) | |||
136 | head = &hinfo->htab[tcf_hash(i, hinfo->hmask)]; | 137 | head = &hinfo->htab[tcf_hash(i, hinfo->hmask)]; |
137 | hlist_for_each_entry_safe(p, n, head, tcfc_head) { | 138 | hlist_for_each_entry_safe(p, n, head, tcfc_head) { |
138 | a->priv = p; | 139 | a->priv = p; |
139 | ret = tcf_hash_release(a, 0); | 140 | ret = __tcf_hash_release(a, false, true); |
140 | if (ret == ACT_P_DELETED) { | 141 | if (ret == ACT_P_DELETED) { |
141 | module_put(a->ops->owner); | 142 | module_put(a->ops->owner); |
142 | n_i++; | 143 | n_i++; |
@@ -408,7 +409,7 @@ int tcf_action_destroy(struct list_head *actions, int bind) | |||
408 | int ret = 0; | 409 | int ret = 0; |
409 | 410 | ||
410 | list_for_each_entry_safe(a, tmp, actions, list) { | 411 | list_for_each_entry_safe(a, tmp, actions, list) { |
411 | ret = tcf_hash_release(a, bind); | 412 | ret = __tcf_hash_release(a, bind, true); |
412 | if (ret == ACT_P_DELETED) | 413 | if (ret == ACT_P_DELETED) |
413 | module_put(a->ops->owner); | 414 | module_put(a->ops->owner); |
414 | else if (ret < 0) | 415 | else if (ret < 0) |
diff --git a/net/sched/act_bpf.c b/net/sched/act_bpf.c index 1d56903fd4c7..d0edeb7a1950 100644 --- a/net/sched/act_bpf.c +++ b/net/sched/act_bpf.c | |||
@@ -27,9 +27,10 @@ | |||
27 | struct tcf_bpf_cfg { | 27 | struct tcf_bpf_cfg { |
28 | struct bpf_prog *filter; | 28 | struct bpf_prog *filter; |
29 | struct sock_filter *bpf_ops; | 29 | struct sock_filter *bpf_ops; |
30 | char *bpf_name; | 30 | const char *bpf_name; |
31 | u32 bpf_fd; | 31 | u32 bpf_fd; |
32 | u16 bpf_num_ops; | 32 | u16 bpf_num_ops; |
33 | bool is_ebpf; | ||
33 | }; | 34 | }; |
34 | 35 | ||
35 | static int tcf_bpf(struct sk_buff *skb, const struct tc_action *act, | 36 | static int tcf_bpf(struct sk_buff *skb, const struct tc_action *act, |
@@ -207,6 +208,7 @@ static int tcf_bpf_init_from_ops(struct nlattr **tb, struct tcf_bpf_cfg *cfg) | |||
207 | cfg->bpf_ops = bpf_ops; | 208 | cfg->bpf_ops = bpf_ops; |
208 | cfg->bpf_num_ops = bpf_num_ops; | 209 | cfg->bpf_num_ops = bpf_num_ops; |
209 | cfg->filter = fp; | 210 | cfg->filter = fp; |
211 | cfg->is_ebpf = false; | ||
210 | 212 | ||
211 | return 0; | 213 | return 0; |
212 | } | 214 | } |
@@ -241,18 +243,40 @@ static int tcf_bpf_init_from_efd(struct nlattr **tb, struct tcf_bpf_cfg *cfg) | |||
241 | cfg->bpf_fd = bpf_fd; | 243 | cfg->bpf_fd = bpf_fd; |
242 | cfg->bpf_name = name; | 244 | cfg->bpf_name = name; |
243 | cfg->filter = fp; | 245 | cfg->filter = fp; |
246 | cfg->is_ebpf = true; | ||
244 | 247 | ||
245 | return 0; | 248 | return 0; |
246 | } | 249 | } |
247 | 250 | ||
251 | static void tcf_bpf_cfg_cleanup(const struct tcf_bpf_cfg *cfg) | ||
252 | { | ||
253 | if (cfg->is_ebpf) | ||
254 | bpf_prog_put(cfg->filter); | ||
255 | else | ||
256 | bpf_prog_destroy(cfg->filter); | ||
257 | |||
258 | kfree(cfg->bpf_ops); | ||
259 | kfree(cfg->bpf_name); | ||
260 | } | ||
261 | |||
262 | static void tcf_bpf_prog_fill_cfg(const struct tcf_bpf *prog, | ||
263 | struct tcf_bpf_cfg *cfg) | ||
264 | { | ||
265 | cfg->is_ebpf = tcf_bpf_is_ebpf(prog); | ||
266 | cfg->filter = prog->filter; | ||
267 | |||
268 | cfg->bpf_ops = prog->bpf_ops; | ||
269 | cfg->bpf_name = prog->bpf_name; | ||
270 | } | ||
271 | |||
248 | static int tcf_bpf_init(struct net *net, struct nlattr *nla, | 272 | static int tcf_bpf_init(struct net *net, struct nlattr *nla, |
249 | struct nlattr *est, struct tc_action *act, | 273 | struct nlattr *est, struct tc_action *act, |
250 | int replace, int bind) | 274 | int replace, int bind) |
251 | { | 275 | { |
252 | struct nlattr *tb[TCA_ACT_BPF_MAX + 1]; | 276 | struct nlattr *tb[TCA_ACT_BPF_MAX + 1]; |
277 | struct tcf_bpf_cfg cfg, old; | ||
253 | struct tc_act_bpf *parm; | 278 | struct tc_act_bpf *parm; |
254 | struct tcf_bpf *prog; | 279 | struct tcf_bpf *prog; |
255 | struct tcf_bpf_cfg cfg; | ||
256 | bool is_bpf, is_ebpf; | 280 | bool is_bpf, is_ebpf; |
257 | int ret; | 281 | int ret; |
258 | 282 | ||
@@ -301,6 +325,9 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla, | |||
301 | prog = to_bpf(act); | 325 | prog = to_bpf(act); |
302 | spin_lock_bh(&prog->tcf_lock); | 326 | spin_lock_bh(&prog->tcf_lock); |
303 | 327 | ||
328 | if (ret != ACT_P_CREATED) | ||
329 | tcf_bpf_prog_fill_cfg(prog, &old); | ||
330 | |||
304 | prog->bpf_ops = cfg.bpf_ops; | 331 | prog->bpf_ops = cfg.bpf_ops; |
305 | prog->bpf_name = cfg.bpf_name; | 332 | prog->bpf_name = cfg.bpf_name; |
306 | 333 | ||
@@ -316,29 +343,22 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla, | |||
316 | 343 | ||
317 | if (ret == ACT_P_CREATED) | 344 | if (ret == ACT_P_CREATED) |
318 | tcf_hash_insert(act); | 345 | tcf_hash_insert(act); |
346 | else | ||
347 | tcf_bpf_cfg_cleanup(&old); | ||
319 | 348 | ||
320 | return ret; | 349 | return ret; |
321 | 350 | ||
322 | destroy_fp: | 351 | destroy_fp: |
323 | if (is_ebpf) | 352 | tcf_bpf_cfg_cleanup(&cfg); |
324 | bpf_prog_put(cfg.filter); | ||
325 | else | ||
326 | bpf_prog_destroy(cfg.filter); | ||
327 | |||
328 | kfree(cfg.bpf_ops); | ||
329 | kfree(cfg.bpf_name); | ||
330 | |||
331 | return ret; | 353 | return ret; |
332 | } | 354 | } |
333 | 355 | ||
334 | static void tcf_bpf_cleanup(struct tc_action *act, int bind) | 356 | static void tcf_bpf_cleanup(struct tc_action *act, int bind) |
335 | { | 357 | { |
336 | const struct tcf_bpf *prog = act->priv; | 358 | struct tcf_bpf_cfg tmp; |
337 | 359 | ||
338 | if (tcf_bpf_is_ebpf(prog)) | 360 | tcf_bpf_prog_fill_cfg(act->priv, &tmp); |
339 | bpf_prog_put(prog->filter); | 361 | tcf_bpf_cfg_cleanup(&tmp); |
340 | else | ||
341 | bpf_prog_destroy(prog->filter); | ||
342 | } | 362 | } |
343 | 363 | ||
344 | static struct tc_action_ops act_bpf_ops __read_mostly = { | 364 | static struct tc_action_ops act_bpf_ops __read_mostly = { |
diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c index a42a3b257226..268545050ddb 100644 --- a/net/sched/act_mirred.c +++ b/net/sched/act_mirred.c | |||
@@ -98,6 +98,8 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla, | |||
98 | return ret; | 98 | return ret; |
99 | ret = ACT_P_CREATED; | 99 | ret = ACT_P_CREATED; |
100 | } else { | 100 | } else { |
101 | if (bind) | ||
102 | return 0; | ||
101 | if (!ovr) { | 103 | if (!ovr) { |
102 | tcf_hash_release(a, bind); | 104 | tcf_hash_release(a, bind); |
103 | return -EEXIST; | 105 | return -EEXIST; |
diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c index 17e6d6669c7f..ff8b466a73f6 100644 --- a/net/sched/act_pedit.c +++ b/net/sched/act_pedit.c | |||
@@ -68,13 +68,12 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla, | |||
68 | } | 68 | } |
69 | ret = ACT_P_CREATED; | 69 | ret = ACT_P_CREATED; |
70 | } else { | 70 | } else { |
71 | p = to_pedit(a); | ||
72 | tcf_hash_release(a, bind); | ||
73 | if (bind) | 71 | if (bind) |
74 | return 0; | 72 | return 0; |
73 | tcf_hash_release(a, bind); | ||
75 | if (!ovr) | 74 | if (!ovr) |
76 | return -EEXIST; | 75 | return -EEXIST; |
77 | 76 | p = to_pedit(a); | |
78 | if (p->tcfp_nkeys && p->tcfp_nkeys != parm->nkeys) { | 77 | if (p->tcfp_nkeys && p->tcfp_nkeys != parm->nkeys) { |
79 | keys = kmalloc(ksize, GFP_KERNEL); | 78 | keys = kmalloc(ksize, GFP_KERNEL); |
80 | if (keys == NULL) | 79 | if (keys == NULL) |
diff --git a/net/sched/cls_bpf.c b/net/sched/cls_bpf.c index c79ecfd36e0f..e5168f8b9640 100644 --- a/net/sched/cls_bpf.c +++ b/net/sched/cls_bpf.c | |||
@@ -378,7 +378,7 @@ static int cls_bpf_change(struct net *net, struct sk_buff *in_skb, | |||
378 | goto errout; | 378 | goto errout; |
379 | 379 | ||
380 | if (oldprog) { | 380 | if (oldprog) { |
381 | list_replace_rcu(&prog->link, &oldprog->link); | 381 | list_replace_rcu(&oldprog->link, &prog->link); |
382 | tcf_unbind_filter(tp, &oldprog->res); | 382 | tcf_unbind_filter(tp, &oldprog->res); |
383 | call_rcu(&oldprog->rcu, __cls_bpf_delete_prog); | 383 | call_rcu(&oldprog->rcu, __cls_bpf_delete_prog); |
384 | } else { | 384 | } else { |
diff --git a/net/sched/cls_flow.c b/net/sched/cls_flow.c index 76bc3a20ffdb..bb2a0f529c1f 100644 --- a/net/sched/cls_flow.c +++ b/net/sched/cls_flow.c | |||
@@ -425,6 +425,8 @@ static int flow_change(struct net *net, struct sk_buff *in_skb, | |||
425 | if (!fnew) | 425 | if (!fnew) |
426 | goto err2; | 426 | goto err2; |
427 | 427 | ||
428 | tcf_exts_init(&fnew->exts, TCA_FLOW_ACT, TCA_FLOW_POLICE); | ||
429 | |||
428 | fold = (struct flow_filter *)*arg; | 430 | fold = (struct flow_filter *)*arg; |
429 | if (fold) { | 431 | if (fold) { |
430 | err = -EINVAL; | 432 | err = -EINVAL; |
@@ -486,7 +488,6 @@ static int flow_change(struct net *net, struct sk_buff *in_skb, | |||
486 | fnew->mask = ~0U; | 488 | fnew->mask = ~0U; |
487 | fnew->tp = tp; | 489 | fnew->tp = tp; |
488 | get_random_bytes(&fnew->hashrnd, 4); | 490 | get_random_bytes(&fnew->hashrnd, 4); |
489 | tcf_exts_init(&fnew->exts, TCA_FLOW_ACT, TCA_FLOW_POLICE); | ||
490 | } | 491 | } |
491 | 492 | ||
492 | fnew->perturb_timer.function = flow_perturbation; | 493 | fnew->perturb_timer.function = flow_perturbation; |
@@ -526,7 +527,7 @@ static int flow_change(struct net *net, struct sk_buff *in_skb, | |||
526 | if (*arg == 0) | 527 | if (*arg == 0) |
527 | list_add_tail_rcu(&fnew->list, &head->filters); | 528 | list_add_tail_rcu(&fnew->list, &head->filters); |
528 | else | 529 | else |
529 | list_replace_rcu(&fnew->list, &fold->list); | 530 | list_replace_rcu(&fold->list, &fnew->list); |
530 | 531 | ||
531 | *arg = (unsigned long)fnew; | 532 | *arg = (unsigned long)fnew; |
532 | 533 | ||
diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c index 9d37ccd95062..2f3d03f99487 100644 --- a/net/sched/cls_flower.c +++ b/net/sched/cls_flower.c | |||
@@ -499,7 +499,7 @@ static int fl_change(struct net *net, struct sk_buff *in_skb, | |||
499 | *arg = (unsigned long) fnew; | 499 | *arg = (unsigned long) fnew; |
500 | 500 | ||
501 | if (fold) { | 501 | if (fold) { |
502 | list_replace_rcu(&fnew->list, &fold->list); | 502 | list_replace_rcu(&fold->list, &fnew->list); |
503 | tcf_unbind_filter(tp, &fold->res); | 503 | tcf_unbind_filter(tp, &fold->res); |
504 | call_rcu(&fold->rcu, fl_destroy_filter); | 504 | call_rcu(&fold->rcu, fl_destroy_filter); |
505 | } else { | 505 | } else { |
diff --git a/net/sched/sch_choke.c b/net/sched/sch_choke.c index 93d5742dc7e0..6a783afe4960 100644 --- a/net/sched/sch_choke.c +++ b/net/sched/sch_choke.c | |||
@@ -385,6 +385,19 @@ static void choke_reset(struct Qdisc *sch) | |||
385 | { | 385 | { |
386 | struct choke_sched_data *q = qdisc_priv(sch); | 386 | struct choke_sched_data *q = qdisc_priv(sch); |
387 | 387 | ||
388 | while (q->head != q->tail) { | ||
389 | struct sk_buff *skb = q->tab[q->head]; | ||
390 | |||
391 | q->head = (q->head + 1) & q->tab_mask; | ||
392 | if (!skb) | ||
393 | continue; | ||
394 | qdisc_qstats_backlog_dec(sch, skb); | ||
395 | --sch->q.qlen; | ||
396 | qdisc_drop(skb, sch); | ||
397 | } | ||
398 | |||
399 | memset(q->tab, 0, (q->tab_mask + 1) * sizeof(struct sk_buff *)); | ||
400 | q->head = q->tail = 0; | ||
388 | red_restart(&q->vars); | 401 | red_restart(&q->vars); |
389 | } | 402 | } |
390 | 403 | ||
diff --git a/net/sched/sch_fq_codel.c b/net/sched/sch_fq_codel.c index d75993f89fac..a9ba030435a2 100644 --- a/net/sched/sch_fq_codel.c +++ b/net/sched/sch_fq_codel.c | |||
@@ -155,14 +155,23 @@ static unsigned int fq_codel_drop(struct Qdisc *sch) | |||
155 | skb = dequeue_head(flow); | 155 | skb = dequeue_head(flow); |
156 | len = qdisc_pkt_len(skb); | 156 | len = qdisc_pkt_len(skb); |
157 | q->backlogs[idx] -= len; | 157 | q->backlogs[idx] -= len; |
158 | kfree_skb(skb); | ||
159 | sch->q.qlen--; | 158 | sch->q.qlen--; |
160 | qdisc_qstats_drop(sch); | 159 | qdisc_qstats_drop(sch); |
161 | qdisc_qstats_backlog_dec(sch, skb); | 160 | qdisc_qstats_backlog_dec(sch, skb); |
161 | kfree_skb(skb); | ||
162 | flow->dropped++; | 162 | flow->dropped++; |
163 | return idx; | 163 | return idx; |
164 | } | 164 | } |
165 | 165 | ||
166 | static unsigned int fq_codel_qdisc_drop(struct Qdisc *sch) | ||
167 | { | ||
168 | unsigned int prev_backlog; | ||
169 | |||
170 | prev_backlog = sch->qstats.backlog; | ||
171 | fq_codel_drop(sch); | ||
172 | return prev_backlog - sch->qstats.backlog; | ||
173 | } | ||
174 | |||
166 | static int fq_codel_enqueue(struct sk_buff *skb, struct Qdisc *sch) | 175 | static int fq_codel_enqueue(struct sk_buff *skb, struct Qdisc *sch) |
167 | { | 176 | { |
168 | struct fq_codel_sched_data *q = qdisc_priv(sch); | 177 | struct fq_codel_sched_data *q = qdisc_priv(sch); |
@@ -279,10 +288,26 @@ begin: | |||
279 | 288 | ||
280 | static void fq_codel_reset(struct Qdisc *sch) | 289 | static void fq_codel_reset(struct Qdisc *sch) |
281 | { | 290 | { |
282 | struct sk_buff *skb; | 291 | struct fq_codel_sched_data *q = qdisc_priv(sch); |
292 | int i; | ||
283 | 293 | ||
284 | while ((skb = fq_codel_dequeue(sch)) != NULL) | 294 | INIT_LIST_HEAD(&q->new_flows); |
285 | kfree_skb(skb); | 295 | INIT_LIST_HEAD(&q->old_flows); |
296 | for (i = 0; i < q->flows_cnt; i++) { | ||
297 | struct fq_codel_flow *flow = q->flows + i; | ||
298 | |||
299 | while (flow->head) { | ||
300 | struct sk_buff *skb = dequeue_head(flow); | ||
301 | |||
302 | qdisc_qstats_backlog_dec(sch, skb); | ||
303 | kfree_skb(skb); | ||
304 | } | ||
305 | |||
306 | INIT_LIST_HEAD(&flow->flowchain); | ||
307 | codel_vars_init(&flow->cvars); | ||
308 | } | ||
309 | memset(q->backlogs, 0, q->flows_cnt * sizeof(u32)); | ||
310 | sch->q.qlen = 0; | ||
286 | } | 311 | } |
287 | 312 | ||
288 | static const struct nla_policy fq_codel_policy[TCA_FQ_CODEL_MAX + 1] = { | 313 | static const struct nla_policy fq_codel_policy[TCA_FQ_CODEL_MAX + 1] = { |
@@ -604,7 +629,7 @@ static struct Qdisc_ops fq_codel_qdisc_ops __read_mostly = { | |||
604 | .enqueue = fq_codel_enqueue, | 629 | .enqueue = fq_codel_enqueue, |
605 | .dequeue = fq_codel_dequeue, | 630 | .dequeue = fq_codel_dequeue, |
606 | .peek = qdisc_peek_dequeued, | 631 | .peek = qdisc_peek_dequeued, |
607 | .drop = fq_codel_drop, | 632 | .drop = fq_codel_qdisc_drop, |
608 | .init = fq_codel_init, | 633 | .init = fq_codel_init, |
609 | .reset = fq_codel_reset, | 634 | .reset = fq_codel_reset, |
610 | .destroy = fq_codel_destroy, | 635 | .destroy = fq_codel_destroy, |
diff --git a/net/sched/sch_plug.c b/net/sched/sch_plug.c index 89f8fcf73f18..ade9445a55ab 100644 --- a/net/sched/sch_plug.c +++ b/net/sched/sch_plug.c | |||
@@ -216,6 +216,7 @@ static struct Qdisc_ops plug_qdisc_ops __read_mostly = { | |||
216 | .peek = qdisc_peek_head, | 216 | .peek = qdisc_peek_head, |
217 | .init = plug_init, | 217 | .init = plug_init, |
218 | .change = plug_change, | 218 | .change = plug_change, |
219 | .reset = qdisc_reset_queue, | ||
219 | .owner = THIS_MODULE, | 220 | .owner = THIS_MODULE, |
220 | }; | 221 | }; |
221 | 222 | ||
diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c index 7d1492663360..52f75a5473e1 100644 --- a/net/sched/sch_sfq.c +++ b/net/sched/sch_sfq.c | |||
@@ -306,10 +306,10 @@ drop: | |||
306 | len = qdisc_pkt_len(skb); | 306 | len = qdisc_pkt_len(skb); |
307 | slot->backlog -= len; | 307 | slot->backlog -= len; |
308 | sfq_dec(q, x); | 308 | sfq_dec(q, x); |
309 | kfree_skb(skb); | ||
310 | sch->q.qlen--; | 309 | sch->q.qlen--; |
311 | qdisc_qstats_drop(sch); | 310 | qdisc_qstats_drop(sch); |
312 | qdisc_qstats_backlog_dec(sch, skb); | 311 | qdisc_qstats_backlog_dec(sch, skb); |
312 | kfree_skb(skb); | ||
313 | return len; | 313 | return len; |
314 | } | 314 | } |
315 | 315 | ||
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 1425ec2bbd5a..17bef01b9aa3 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -2200,12 +2200,6 @@ static int sctp_setsockopt_events(struct sock *sk, char __user *optval, | |||
2200 | if (copy_from_user(&sctp_sk(sk)->subscribe, optval, optlen)) | 2200 | if (copy_from_user(&sctp_sk(sk)->subscribe, optval, optlen)) |
2201 | return -EFAULT; | 2201 | return -EFAULT; |
2202 | 2202 | ||
2203 | if (sctp_sk(sk)->subscribe.sctp_data_io_event) | ||
2204 | pr_warn_ratelimited(DEPRECATED "%s (pid %d) " | ||
2205 | "Requested SCTP_SNDRCVINFO event.\n" | ||
2206 | "Use SCTP_RCVINFO through SCTP_RECVRCVINFO option instead.\n", | ||
2207 | current->comm, task_pid_nr(current)); | ||
2208 | |||
2209 | /* At the time when a user app subscribes to SCTP_SENDER_DRY_EVENT, | 2203 | /* At the time when a user app subscribes to SCTP_SENDER_DRY_EVENT, |
2210 | * if there is no data to be sent or retransmit, the stack will | 2204 | * if there is no data to be sent or retransmit, the stack will |
2211 | * immediately send up this notification. | 2205 | * immediately send up this notification. |
diff --git a/net/sunrpc/backchannel_rqst.c b/net/sunrpc/backchannel_rqst.c index 9825ff0f91d6..6255d141133b 100644 --- a/net/sunrpc/backchannel_rqst.c +++ b/net/sunrpc/backchannel_rqst.c | |||
@@ -240,8 +240,8 @@ static struct rpc_rqst *xprt_alloc_bc_request(struct rpc_xprt *xprt, __be32 xid) | |||
240 | req = xprt_alloc_bc_req(xprt, GFP_ATOMIC); | 240 | req = xprt_alloc_bc_req(xprt, GFP_ATOMIC); |
241 | if (!req) | 241 | if (!req) |
242 | goto not_found; | 242 | goto not_found; |
243 | /* Note: this 'free' request adds it to xprt->bc_pa_list */ | 243 | list_add_tail(&req->rq_bc_pa_list, &xprt->bc_pa_list); |
244 | xprt_free_bc_request(req); | 244 | xprt->bc_alloc_count++; |
245 | } | 245 | } |
246 | req = list_first_entry(&xprt->bc_pa_list, struct rpc_rqst, | 246 | req = list_first_entry(&xprt->bc_pa_list, struct rpc_rqst, |
247 | rq_bc_pa_list); | 247 | rq_bc_pa_list); |
@@ -336,7 +336,7 @@ void xprt_complete_bc_request(struct rpc_rqst *req, uint32_t copied) | |||
336 | 336 | ||
337 | spin_lock(&xprt->bc_pa_lock); | 337 | spin_lock(&xprt->bc_pa_lock); |
338 | list_del(&req->rq_bc_pa_list); | 338 | list_del(&req->rq_bc_pa_list); |
339 | xprt->bc_alloc_count--; | 339 | xprt_dec_alloc_count(xprt, 1); |
340 | spin_unlock(&xprt->bc_pa_lock); | 340 | spin_unlock(&xprt->bc_pa_lock); |
341 | 341 | ||
342 | req->rq_private_buf.len = copied; | 342 | req->rq_private_buf.len = copied; |
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index cbc6af923dd1..23608eb0ded2 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
@@ -1902,6 +1902,7 @@ call_transmit_status(struct rpc_task *task) | |||
1902 | 1902 | ||
1903 | switch (task->tk_status) { | 1903 | switch (task->tk_status) { |
1904 | case -EAGAIN: | 1904 | case -EAGAIN: |
1905 | case -ENOBUFS: | ||
1905 | break; | 1906 | break; |
1906 | default: | 1907 | default: |
1907 | dprint_status(task); | 1908 | dprint_status(task); |
@@ -1928,7 +1929,6 @@ call_transmit_status(struct rpc_task *task) | |||
1928 | case -ECONNABORTED: | 1929 | case -ECONNABORTED: |
1929 | case -EADDRINUSE: | 1930 | case -EADDRINUSE: |
1930 | case -ENOTCONN: | 1931 | case -ENOTCONN: |
1931 | case -ENOBUFS: | ||
1932 | case -EPIPE: | 1932 | case -EPIPE: |
1933 | rpc_task_force_reencode(task); | 1933 | rpc_task_force_reencode(task); |
1934 | } | 1934 | } |
@@ -2057,12 +2057,13 @@ call_status(struct rpc_task *task) | |||
2057 | case -ECONNABORTED: | 2057 | case -ECONNABORTED: |
2058 | rpc_force_rebind(clnt); | 2058 | rpc_force_rebind(clnt); |
2059 | case -EADDRINUSE: | 2059 | case -EADDRINUSE: |
2060 | case -ENOBUFS: | ||
2061 | rpc_delay(task, 3*HZ); | 2060 | rpc_delay(task, 3*HZ); |
2062 | case -EPIPE: | 2061 | case -EPIPE: |
2063 | case -ENOTCONN: | 2062 | case -ENOTCONN: |
2064 | task->tk_action = call_bind; | 2063 | task->tk_action = call_bind; |
2065 | break; | 2064 | break; |
2065 | case -ENOBUFS: | ||
2066 | rpc_delay(task, HZ>>2); | ||
2066 | case -EAGAIN: | 2067 | case -EAGAIN: |
2067 | task->tk_action = call_transmit; | 2068 | task->tk_action = call_transmit; |
2068 | break; | 2069 | break; |
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index e193c2b5476b..0030376327b7 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
@@ -527,6 +527,10 @@ static int xs_local_send_request(struct rpc_task *task) | |||
527 | true, &sent); | 527 | true, &sent); |
528 | dprintk("RPC: %s(%u) = %d\n", | 528 | dprintk("RPC: %s(%u) = %d\n", |
529 | __func__, xdr->len - req->rq_bytes_sent, status); | 529 | __func__, xdr->len - req->rq_bytes_sent, status); |
530 | |||
531 | if (status == -EAGAIN && sock_writeable(transport->inet)) | ||
532 | status = -ENOBUFS; | ||
533 | |||
530 | if (likely(sent > 0) || status == 0) { | 534 | if (likely(sent > 0) || status == 0) { |
531 | req->rq_bytes_sent += sent; | 535 | req->rq_bytes_sent += sent; |
532 | req->rq_xmit_bytes_sent += sent; | 536 | req->rq_xmit_bytes_sent += sent; |
@@ -539,6 +543,7 @@ static int xs_local_send_request(struct rpc_task *task) | |||
539 | 543 | ||
540 | switch (status) { | 544 | switch (status) { |
541 | case -ENOBUFS: | 545 | case -ENOBUFS: |
546 | break; | ||
542 | case -EAGAIN: | 547 | case -EAGAIN: |
543 | status = xs_nospace(task); | 548 | status = xs_nospace(task); |
544 | break; | 549 | break; |
@@ -589,6 +594,9 @@ static int xs_udp_send_request(struct rpc_task *task) | |||
589 | if (status == -EPERM) | 594 | if (status == -EPERM) |
590 | goto process_status; | 595 | goto process_status; |
591 | 596 | ||
597 | if (status == -EAGAIN && sock_writeable(transport->inet)) | ||
598 | status = -ENOBUFS; | ||
599 | |||
592 | if (sent > 0 || status == 0) { | 600 | if (sent > 0 || status == 0) { |
593 | req->rq_xmit_bytes_sent += sent; | 601 | req->rq_xmit_bytes_sent += sent; |
594 | if (sent >= req->rq_slen) | 602 | if (sent >= req->rq_slen) |
@@ -669,9 +677,6 @@ static int xs_tcp_send_request(struct rpc_task *task) | |||
669 | dprintk("RPC: xs_tcp_send_request(%u) = %d\n", | 677 | dprintk("RPC: xs_tcp_send_request(%u) = %d\n", |
670 | xdr->len - req->rq_bytes_sent, status); | 678 | xdr->len - req->rq_bytes_sent, status); |
671 | 679 | ||
672 | if (unlikely(sent == 0 && status < 0)) | ||
673 | break; | ||
674 | |||
675 | /* If we've sent the entire packet, immediately | 680 | /* If we've sent the entire packet, immediately |
676 | * reset the count of bytes sent. */ | 681 | * reset the count of bytes sent. */ |
677 | req->rq_bytes_sent += sent; | 682 | req->rq_bytes_sent += sent; |
@@ -681,18 +686,21 @@ static int xs_tcp_send_request(struct rpc_task *task) | |||
681 | return 0; | 686 | return 0; |
682 | } | 687 | } |
683 | 688 | ||
684 | if (sent != 0) | 689 | if (status < 0) |
685 | continue; | 690 | break; |
686 | status = -EAGAIN; | 691 | if (sent == 0) { |
687 | break; | 692 | status = -EAGAIN; |
693 | break; | ||
694 | } | ||
688 | } | 695 | } |
696 | if (status == -EAGAIN && sk_stream_is_writeable(transport->inet)) | ||
697 | status = -ENOBUFS; | ||
689 | 698 | ||
690 | switch (status) { | 699 | switch (status) { |
691 | case -ENOTSOCK: | 700 | case -ENOTSOCK: |
692 | status = -ENOTCONN; | 701 | status = -ENOTCONN; |
693 | /* Should we call xs_close() here? */ | 702 | /* Should we call xs_close() here? */ |
694 | break; | 703 | break; |
695 | case -ENOBUFS: | ||
696 | case -EAGAIN: | 704 | case -EAGAIN: |
697 | status = xs_nospace(task); | 705 | status = xs_nospace(task); |
698 | break; | 706 | break; |
@@ -703,6 +711,7 @@ static int xs_tcp_send_request(struct rpc_task *task) | |||
703 | case -ECONNREFUSED: | 711 | case -ECONNREFUSED: |
704 | case -ENOTCONN: | 712 | case -ENOTCONN: |
705 | case -EADDRINUSE: | 713 | case -EADDRINUSE: |
714 | case -ENOBUFS: | ||
706 | case -EPIPE: | 715 | case -EPIPE: |
707 | clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags); | 716 | clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags); |
708 | } | 717 | } |
diff --git a/net/wireless/chan.c b/net/wireless/chan.c index 915b328b9ac5..59cabc9bce69 100644 --- a/net/wireless/chan.c +++ b/net/wireless/chan.c | |||
@@ -797,23 +797,18 @@ static bool cfg80211_ir_permissive_chan(struct wiphy *wiphy, | |||
797 | return false; | 797 | return false; |
798 | } | 798 | } |
799 | 799 | ||
800 | bool cfg80211_reg_can_beacon(struct wiphy *wiphy, | 800 | static bool _cfg80211_reg_can_beacon(struct wiphy *wiphy, |
801 | struct cfg80211_chan_def *chandef, | 801 | struct cfg80211_chan_def *chandef, |
802 | enum nl80211_iftype iftype) | 802 | enum nl80211_iftype iftype, |
803 | bool check_no_ir) | ||
803 | { | 804 | { |
804 | bool res; | 805 | bool res; |
805 | u32 prohibited_flags = IEEE80211_CHAN_DISABLED | | 806 | u32 prohibited_flags = IEEE80211_CHAN_DISABLED | |
806 | IEEE80211_CHAN_RADAR; | 807 | IEEE80211_CHAN_RADAR; |
807 | 808 | ||
808 | trace_cfg80211_reg_can_beacon(wiphy, chandef, iftype); | 809 | trace_cfg80211_reg_can_beacon(wiphy, chandef, iftype, check_no_ir); |
809 | 810 | ||
810 | /* | 811 | if (check_no_ir) |
811 | * Under certain conditions suggested by some regulatory bodies a | ||
812 | * GO/STA can IR on channels marked with IEEE80211_NO_IR. Set this flag | ||
813 | * only if such relaxations are not enabled and the conditions are not | ||
814 | * met. | ||
815 | */ | ||
816 | if (!cfg80211_ir_permissive_chan(wiphy, iftype, chandef->chan)) | ||
817 | prohibited_flags |= IEEE80211_CHAN_NO_IR; | 812 | prohibited_flags |= IEEE80211_CHAN_NO_IR; |
818 | 813 | ||
819 | if (cfg80211_chandef_dfs_required(wiphy, chandef, iftype) > 0 && | 814 | if (cfg80211_chandef_dfs_required(wiphy, chandef, iftype) > 0 && |
@@ -827,8 +822,36 @@ bool cfg80211_reg_can_beacon(struct wiphy *wiphy, | |||
827 | trace_cfg80211_return_bool(res); | 822 | trace_cfg80211_return_bool(res); |
828 | return res; | 823 | return res; |
829 | } | 824 | } |
825 | |||
826 | bool cfg80211_reg_can_beacon(struct wiphy *wiphy, | ||
827 | struct cfg80211_chan_def *chandef, | ||
828 | enum nl80211_iftype iftype) | ||
829 | { | ||
830 | return _cfg80211_reg_can_beacon(wiphy, chandef, iftype, true); | ||
831 | } | ||
830 | EXPORT_SYMBOL(cfg80211_reg_can_beacon); | 832 | EXPORT_SYMBOL(cfg80211_reg_can_beacon); |
831 | 833 | ||
834 | bool cfg80211_reg_can_beacon_relax(struct wiphy *wiphy, | ||
835 | struct cfg80211_chan_def *chandef, | ||
836 | enum nl80211_iftype iftype) | ||
837 | { | ||
838 | bool check_no_ir; | ||
839 | |||
840 | ASSERT_RTNL(); | ||
841 | |||
842 | /* | ||
843 | * Under certain conditions suggested by some regulatory bodies a | ||
844 | * GO/STA can IR on channels marked with IEEE80211_NO_IR. Set this flag | ||
845 | * only if such relaxations are not enabled and the conditions are not | ||
846 | * met. | ||
847 | */ | ||
848 | check_no_ir = !cfg80211_ir_permissive_chan(wiphy, iftype, | ||
849 | chandef->chan); | ||
850 | |||
851 | return _cfg80211_reg_can_beacon(wiphy, chandef, iftype, check_no_ir); | ||
852 | } | ||
853 | EXPORT_SYMBOL(cfg80211_reg_can_beacon_relax); | ||
854 | |||
832 | int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev, | 855 | int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev, |
833 | struct cfg80211_chan_def *chandef) | 856 | struct cfg80211_chan_def *chandef) |
834 | { | 857 | { |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index c264effd00a6..76b41578a838 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -2003,7 +2003,8 @@ static int __nl80211_set_channel(struct cfg80211_registered_device *rdev, | |||
2003 | switch (iftype) { | 2003 | switch (iftype) { |
2004 | case NL80211_IFTYPE_AP: | 2004 | case NL80211_IFTYPE_AP: |
2005 | case NL80211_IFTYPE_P2P_GO: | 2005 | case NL80211_IFTYPE_P2P_GO: |
2006 | if (!cfg80211_reg_can_beacon(&rdev->wiphy, &chandef, iftype)) { | 2006 | if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &chandef, |
2007 | iftype)) { | ||
2007 | result = -EINVAL; | 2008 | result = -EINVAL; |
2008 | break; | 2009 | break; |
2009 | } | 2010 | } |
@@ -3403,8 +3404,8 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) | |||
3403 | } else if (!nl80211_get_ap_channel(rdev, ¶ms)) | 3404 | } else if (!nl80211_get_ap_channel(rdev, ¶ms)) |
3404 | return -EINVAL; | 3405 | return -EINVAL; |
3405 | 3406 | ||
3406 | if (!cfg80211_reg_can_beacon(&rdev->wiphy, ¶ms.chandef, | 3407 | if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, ¶ms.chandef, |
3407 | wdev->iftype)) | 3408 | wdev->iftype)) |
3408 | return -EINVAL; | 3409 | return -EINVAL; |
3409 | 3410 | ||
3410 | if (info->attrs[NL80211_ATTR_ACL_POLICY]) { | 3411 | if (info->attrs[NL80211_ATTR_ACL_POLICY]) { |
@@ -6492,8 +6493,8 @@ skip_beacons: | |||
6492 | if (err) | 6493 | if (err) |
6493 | return err; | 6494 | return err; |
6494 | 6495 | ||
6495 | if (!cfg80211_reg_can_beacon(&rdev->wiphy, ¶ms.chandef, | 6496 | if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, ¶ms.chandef, |
6496 | wdev->iftype)) | 6497 | wdev->iftype)) |
6497 | return -EINVAL; | 6498 | return -EINVAL; |
6498 | 6499 | ||
6499 | err = cfg80211_chandef_dfs_required(wdev->wiphy, | 6500 | err = cfg80211_chandef_dfs_required(wdev->wiphy, |
@@ -10170,7 +10171,8 @@ static int nl80211_tdls_channel_switch(struct sk_buff *skb, | |||
10170 | return -EINVAL; | 10171 | return -EINVAL; |
10171 | 10172 | ||
10172 | /* we will be active on the TDLS link */ | 10173 | /* we will be active on the TDLS link */ |
10173 | if (!cfg80211_reg_can_beacon(&rdev->wiphy, &chandef, wdev->iftype)) | 10174 | if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &chandef, |
10175 | wdev->iftype)) | ||
10174 | return -EINVAL; | 10176 | return -EINVAL; |
10175 | 10177 | ||
10176 | /* don't allow switching to DFS channels */ | 10178 | /* don't allow switching to DFS channels */ |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index d359e0610198..aa2d75482017 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -544,15 +544,15 @@ static int call_crda(const char *alpha2) | |||
544 | reg_regdb_query(alpha2); | 544 | reg_regdb_query(alpha2); |
545 | 545 | ||
546 | if (reg_crda_timeouts > REG_MAX_CRDA_TIMEOUTS) { | 546 | if (reg_crda_timeouts > REG_MAX_CRDA_TIMEOUTS) { |
547 | pr_info("Exceeded CRDA call max attempts. Not calling CRDA\n"); | 547 | pr_debug("Exceeded CRDA call max attempts. Not calling CRDA\n"); |
548 | return -EINVAL; | 548 | return -EINVAL; |
549 | } | 549 | } |
550 | 550 | ||
551 | if (!is_world_regdom((char *) alpha2)) | 551 | if (!is_world_regdom((char *) alpha2)) |
552 | pr_info("Calling CRDA for country: %c%c\n", | 552 | pr_debug("Calling CRDA for country: %c%c\n", |
553 | alpha2[0], alpha2[1]); | 553 | alpha2[0], alpha2[1]); |
554 | else | 554 | else |
555 | pr_info("Calling CRDA to update world regulatory domain\n"); | 555 | pr_debug("Calling CRDA to update world regulatory domain\n"); |
556 | 556 | ||
557 | return kobject_uevent_env(®_pdev->dev.kobj, KOBJ_CHANGE, env); | 557 | return kobject_uevent_env(®_pdev->dev.kobj, KOBJ_CHANGE, env); |
558 | } | 558 | } |
@@ -1589,7 +1589,7 @@ static bool reg_wdev_chan_valid(struct wiphy *wiphy, struct wireless_dev *wdev) | |||
1589 | case NL80211_IFTYPE_AP: | 1589 | case NL80211_IFTYPE_AP: |
1590 | case NL80211_IFTYPE_P2P_GO: | 1590 | case NL80211_IFTYPE_P2P_GO: |
1591 | case NL80211_IFTYPE_ADHOC: | 1591 | case NL80211_IFTYPE_ADHOC: |
1592 | return cfg80211_reg_can_beacon(wiphy, &chandef, iftype); | 1592 | return cfg80211_reg_can_beacon_relax(wiphy, &chandef, iftype); |
1593 | case NL80211_IFTYPE_STATION: | 1593 | case NL80211_IFTYPE_STATION: |
1594 | case NL80211_IFTYPE_P2P_CLIENT: | 1594 | case NL80211_IFTYPE_P2P_CLIENT: |
1595 | return cfg80211_chandef_usable(wiphy, &chandef, | 1595 | return cfg80211_chandef_usable(wiphy, &chandef, |
diff --git a/net/wireless/trace.h b/net/wireless/trace.h index af3617c9879e..a808279a432a 100644 --- a/net/wireless/trace.h +++ b/net/wireless/trace.h | |||
@@ -2358,20 +2358,23 @@ TRACE_EVENT(cfg80211_cqm_rssi_notify, | |||
2358 | 2358 | ||
2359 | TRACE_EVENT(cfg80211_reg_can_beacon, | 2359 | TRACE_EVENT(cfg80211_reg_can_beacon, |
2360 | TP_PROTO(struct wiphy *wiphy, struct cfg80211_chan_def *chandef, | 2360 | TP_PROTO(struct wiphy *wiphy, struct cfg80211_chan_def *chandef, |
2361 | enum nl80211_iftype iftype), | 2361 | enum nl80211_iftype iftype, bool check_no_ir), |
2362 | TP_ARGS(wiphy, chandef, iftype), | 2362 | TP_ARGS(wiphy, chandef, iftype, check_no_ir), |
2363 | TP_STRUCT__entry( | 2363 | TP_STRUCT__entry( |
2364 | WIPHY_ENTRY | 2364 | WIPHY_ENTRY |
2365 | CHAN_DEF_ENTRY | 2365 | CHAN_DEF_ENTRY |
2366 | __field(enum nl80211_iftype, iftype) | 2366 | __field(enum nl80211_iftype, iftype) |
2367 | __field(bool, check_no_ir) | ||
2367 | ), | 2368 | ), |
2368 | TP_fast_assign( | 2369 | TP_fast_assign( |
2369 | WIPHY_ASSIGN; | 2370 | WIPHY_ASSIGN; |
2370 | CHAN_DEF_ASSIGN(chandef); | 2371 | CHAN_DEF_ASSIGN(chandef); |
2371 | __entry->iftype = iftype; | 2372 | __entry->iftype = iftype; |
2373 | __entry->check_no_ir = check_no_ir; | ||
2372 | ), | 2374 | ), |
2373 | TP_printk(WIPHY_PR_FMT ", " CHAN_DEF_PR_FMT ", iftype=%d", | 2375 | TP_printk(WIPHY_PR_FMT ", " CHAN_DEF_PR_FMT ", iftype=%d check_no_ir=%s", |
2374 | WIPHY_PR_ARG, CHAN_DEF_PR_ARG, __entry->iftype) | 2376 | WIPHY_PR_ARG, CHAN_DEF_PR_ARG, __entry->iftype, |
2377 | BOOL_TO_STR(__entry->check_no_ir)) | ||
2375 | ); | 2378 | ); |
2376 | 2379 | ||
2377 | TRACE_EVENT(cfg80211_chandef_dfs_required, | 2380 | TRACE_EVENT(cfg80211_chandef_dfs_required, |