diff options
Diffstat (limited to 'net')
31 files changed, 396 insertions, 183 deletions
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index ca04163635da..e6b7fecb3af1 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c | |||
@@ -64,7 +64,7 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev) | |||
64 | br_flood_deliver(br, skb, false); | 64 | br_flood_deliver(br, skb, false); |
65 | goto out; | 65 | goto out; |
66 | } | 66 | } |
67 | if (br_multicast_rcv(br, NULL, skb)) { | 67 | if (br_multicast_rcv(br, NULL, skb, vid)) { |
68 | kfree_skb(skb); | 68 | kfree_skb(skb); |
69 | goto out; | 69 | goto out; |
70 | } | 70 | } |
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index a2fd37ec35f7..7e73c32e205d 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c | |||
@@ -80,7 +80,7 @@ int br_handle_frame_finish(struct sk_buff *skb) | |||
80 | br_fdb_update(br, p, eth_hdr(skb)->h_source, vid); | 80 | br_fdb_update(br, p, eth_hdr(skb)->h_source, vid); |
81 | 81 | ||
82 | if (!is_broadcast_ether_addr(dest) && is_multicast_ether_addr(dest) && | 82 | if (!is_broadcast_ether_addr(dest) && is_multicast_ether_addr(dest) && |
83 | br_multicast_rcv(br, p, skb)) | 83 | br_multicast_rcv(br, p, skb, vid)) |
84 | goto drop; | 84 | goto drop; |
85 | 85 | ||
86 | if (p->state == BR_STATE_LEARNING) | 86 | if (p->state == BR_STATE_LEARNING) |
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 8b0b610ca2c9..686284ff3d6a 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c | |||
@@ -947,7 +947,8 @@ void br_multicast_disable_port(struct net_bridge_port *port) | |||
947 | 947 | ||
948 | static int br_ip4_multicast_igmp3_report(struct net_bridge *br, | 948 | static int br_ip4_multicast_igmp3_report(struct net_bridge *br, |
949 | struct net_bridge_port *port, | 949 | struct net_bridge_port *port, |
950 | struct sk_buff *skb) | 950 | struct sk_buff *skb, |
951 | u16 vid) | ||
951 | { | 952 | { |
952 | struct igmpv3_report *ih; | 953 | struct igmpv3_report *ih; |
953 | struct igmpv3_grec *grec; | 954 | struct igmpv3_grec *grec; |
@@ -957,12 +958,10 @@ static int br_ip4_multicast_igmp3_report(struct net_bridge *br, | |||
957 | int type; | 958 | int type; |
958 | int err = 0; | 959 | int err = 0; |
959 | __be32 group; | 960 | __be32 group; |
960 | u16 vid = 0; | ||
961 | 961 | ||
962 | if (!pskb_may_pull(skb, sizeof(*ih))) | 962 | if (!pskb_may_pull(skb, sizeof(*ih))) |
963 | return -EINVAL; | 963 | return -EINVAL; |
964 | 964 | ||
965 | br_vlan_get_tag(skb, &vid); | ||
966 | ih = igmpv3_report_hdr(skb); | 965 | ih = igmpv3_report_hdr(skb); |
967 | num = ntohs(ih->ngrec); | 966 | num = ntohs(ih->ngrec); |
968 | len = sizeof(*ih); | 967 | len = sizeof(*ih); |
@@ -1005,7 +1004,8 @@ static int br_ip4_multicast_igmp3_report(struct net_bridge *br, | |||
1005 | #if IS_ENABLED(CONFIG_IPV6) | 1004 | #if IS_ENABLED(CONFIG_IPV6) |
1006 | static int br_ip6_multicast_mld2_report(struct net_bridge *br, | 1005 | static int br_ip6_multicast_mld2_report(struct net_bridge *br, |
1007 | struct net_bridge_port *port, | 1006 | struct net_bridge_port *port, |
1008 | struct sk_buff *skb) | 1007 | struct sk_buff *skb, |
1008 | u16 vid) | ||
1009 | { | 1009 | { |
1010 | struct icmp6hdr *icmp6h; | 1010 | struct icmp6hdr *icmp6h; |
1011 | struct mld2_grec *grec; | 1011 | struct mld2_grec *grec; |
@@ -1013,12 +1013,10 @@ static int br_ip6_multicast_mld2_report(struct net_bridge *br, | |||
1013 | int len; | 1013 | int len; |
1014 | int num; | 1014 | int num; |
1015 | int err = 0; | 1015 | int err = 0; |
1016 | u16 vid = 0; | ||
1017 | 1016 | ||
1018 | if (!pskb_may_pull(skb, sizeof(*icmp6h))) | 1017 | if (!pskb_may_pull(skb, sizeof(*icmp6h))) |
1019 | return -EINVAL; | 1018 | return -EINVAL; |
1020 | 1019 | ||
1021 | br_vlan_get_tag(skb, &vid); | ||
1022 | icmp6h = icmp6_hdr(skb); | 1020 | icmp6h = icmp6_hdr(skb); |
1023 | num = ntohs(icmp6h->icmp6_dataun.un_data16[1]); | 1021 | num = ntohs(icmp6h->icmp6_dataun.un_data16[1]); |
1024 | len = sizeof(*icmp6h); | 1022 | len = sizeof(*icmp6h); |
@@ -1141,7 +1139,8 @@ static void br_multicast_query_received(struct net_bridge *br, | |||
1141 | 1139 | ||
1142 | static int br_ip4_multicast_query(struct net_bridge *br, | 1140 | static int br_ip4_multicast_query(struct net_bridge *br, |
1143 | struct net_bridge_port *port, | 1141 | struct net_bridge_port *port, |
1144 | struct sk_buff *skb) | 1142 | struct sk_buff *skb, |
1143 | u16 vid) | ||
1145 | { | 1144 | { |
1146 | const struct iphdr *iph = ip_hdr(skb); | 1145 | const struct iphdr *iph = ip_hdr(skb); |
1147 | struct igmphdr *ih = igmp_hdr(skb); | 1146 | struct igmphdr *ih = igmp_hdr(skb); |
@@ -1153,7 +1152,6 @@ static int br_ip4_multicast_query(struct net_bridge *br, | |||
1153 | unsigned long now = jiffies; | 1152 | unsigned long now = jiffies; |
1154 | __be32 group; | 1153 | __be32 group; |
1155 | int err = 0; | 1154 | int err = 0; |
1156 | u16 vid = 0; | ||
1157 | 1155 | ||
1158 | spin_lock(&br->multicast_lock); | 1156 | spin_lock(&br->multicast_lock); |
1159 | if (!netif_running(br->dev) || | 1157 | if (!netif_running(br->dev) || |
@@ -1189,7 +1187,6 @@ static int br_ip4_multicast_query(struct net_bridge *br, | |||
1189 | if (!group) | 1187 | if (!group) |
1190 | goto out; | 1188 | goto out; |
1191 | 1189 | ||
1192 | br_vlan_get_tag(skb, &vid); | ||
1193 | mp = br_mdb_ip4_get(mlock_dereference(br->mdb, br), group, vid); | 1190 | mp = br_mdb_ip4_get(mlock_dereference(br->mdb, br), group, vid); |
1194 | if (!mp) | 1191 | if (!mp) |
1195 | goto out; | 1192 | goto out; |
@@ -1219,7 +1216,8 @@ out: | |||
1219 | #if IS_ENABLED(CONFIG_IPV6) | 1216 | #if IS_ENABLED(CONFIG_IPV6) |
1220 | static int br_ip6_multicast_query(struct net_bridge *br, | 1217 | static int br_ip6_multicast_query(struct net_bridge *br, |
1221 | struct net_bridge_port *port, | 1218 | struct net_bridge_port *port, |
1222 | struct sk_buff *skb) | 1219 | struct sk_buff *skb, |
1220 | u16 vid) | ||
1223 | { | 1221 | { |
1224 | const struct ipv6hdr *ip6h = ipv6_hdr(skb); | 1222 | const struct ipv6hdr *ip6h = ipv6_hdr(skb); |
1225 | struct mld_msg *mld; | 1223 | struct mld_msg *mld; |
@@ -1231,7 +1229,6 @@ static int br_ip6_multicast_query(struct net_bridge *br, | |||
1231 | unsigned long now = jiffies; | 1229 | unsigned long now = jiffies; |
1232 | const struct in6_addr *group = NULL; | 1230 | const struct in6_addr *group = NULL; |
1233 | int err = 0; | 1231 | int err = 0; |
1234 | u16 vid = 0; | ||
1235 | 1232 | ||
1236 | spin_lock(&br->multicast_lock); | 1233 | spin_lock(&br->multicast_lock); |
1237 | if (!netif_running(br->dev) || | 1234 | if (!netif_running(br->dev) || |
@@ -1265,7 +1262,6 @@ static int br_ip6_multicast_query(struct net_bridge *br, | |||
1265 | if (!group) | 1262 | if (!group) |
1266 | goto out; | 1263 | goto out; |
1267 | 1264 | ||
1268 | br_vlan_get_tag(skb, &vid); | ||
1269 | mp = br_mdb_ip6_get(mlock_dereference(br->mdb, br), group, vid); | 1265 | mp = br_mdb_ip6_get(mlock_dereference(br->mdb, br), group, vid); |
1270 | if (!mp) | 1266 | if (!mp) |
1271 | goto out; | 1267 | goto out; |
@@ -1439,7 +1435,8 @@ static void br_ip6_multicast_leave_group(struct net_bridge *br, | |||
1439 | 1435 | ||
1440 | static int br_multicast_ipv4_rcv(struct net_bridge *br, | 1436 | static int br_multicast_ipv4_rcv(struct net_bridge *br, |
1441 | struct net_bridge_port *port, | 1437 | struct net_bridge_port *port, |
1442 | struct sk_buff *skb) | 1438 | struct sk_buff *skb, |
1439 | u16 vid) | ||
1443 | { | 1440 | { |
1444 | struct sk_buff *skb2 = skb; | 1441 | struct sk_buff *skb2 = skb; |
1445 | const struct iphdr *iph; | 1442 | const struct iphdr *iph; |
@@ -1447,7 +1444,6 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br, | |||
1447 | unsigned int len; | 1444 | unsigned int len; |
1448 | unsigned int offset; | 1445 | unsigned int offset; |
1449 | int err; | 1446 | int err; |
1450 | u16 vid = 0; | ||
1451 | 1447 | ||
1452 | /* We treat OOM as packet loss for now. */ | 1448 | /* We treat OOM as packet loss for now. */ |
1453 | if (!pskb_may_pull(skb, sizeof(*iph))) | 1449 | if (!pskb_may_pull(skb, sizeof(*iph))) |
@@ -1508,7 +1504,6 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br, | |||
1508 | 1504 | ||
1509 | err = 0; | 1505 | err = 0; |
1510 | 1506 | ||
1511 | br_vlan_get_tag(skb2, &vid); | ||
1512 | BR_INPUT_SKB_CB(skb)->igmp = 1; | 1507 | BR_INPUT_SKB_CB(skb)->igmp = 1; |
1513 | ih = igmp_hdr(skb2); | 1508 | ih = igmp_hdr(skb2); |
1514 | 1509 | ||
@@ -1519,10 +1514,10 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br, | |||
1519 | err = br_ip4_multicast_add_group(br, port, ih->group, vid); | 1514 | err = br_ip4_multicast_add_group(br, port, ih->group, vid); |
1520 | break; | 1515 | break; |
1521 | case IGMPV3_HOST_MEMBERSHIP_REPORT: | 1516 | case IGMPV3_HOST_MEMBERSHIP_REPORT: |
1522 | err = br_ip4_multicast_igmp3_report(br, port, skb2); | 1517 | err = br_ip4_multicast_igmp3_report(br, port, skb2, vid); |
1523 | break; | 1518 | break; |
1524 | case IGMP_HOST_MEMBERSHIP_QUERY: | 1519 | case IGMP_HOST_MEMBERSHIP_QUERY: |
1525 | err = br_ip4_multicast_query(br, port, skb2); | 1520 | err = br_ip4_multicast_query(br, port, skb2, vid); |
1526 | break; | 1521 | break; |
1527 | case IGMP_HOST_LEAVE_MESSAGE: | 1522 | case IGMP_HOST_LEAVE_MESSAGE: |
1528 | br_ip4_multicast_leave_group(br, port, ih->group, vid); | 1523 | br_ip4_multicast_leave_group(br, port, ih->group, vid); |
@@ -1540,7 +1535,8 @@ err_out: | |||
1540 | #if IS_ENABLED(CONFIG_IPV6) | 1535 | #if IS_ENABLED(CONFIG_IPV6) |
1541 | static int br_multicast_ipv6_rcv(struct net_bridge *br, | 1536 | static int br_multicast_ipv6_rcv(struct net_bridge *br, |
1542 | struct net_bridge_port *port, | 1537 | struct net_bridge_port *port, |
1543 | struct sk_buff *skb) | 1538 | struct sk_buff *skb, |
1539 | u16 vid) | ||
1544 | { | 1540 | { |
1545 | struct sk_buff *skb2; | 1541 | struct sk_buff *skb2; |
1546 | const struct ipv6hdr *ip6h; | 1542 | const struct ipv6hdr *ip6h; |
@@ -1550,7 +1546,6 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br, | |||
1550 | unsigned int len; | 1546 | unsigned int len; |
1551 | int offset; | 1547 | int offset; |
1552 | int err; | 1548 | int err; |
1553 | u16 vid = 0; | ||
1554 | 1549 | ||
1555 | if (!pskb_may_pull(skb, sizeof(*ip6h))) | 1550 | if (!pskb_may_pull(skb, sizeof(*ip6h))) |
1556 | return -EINVAL; | 1551 | return -EINVAL; |
@@ -1640,7 +1635,6 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br, | |||
1640 | 1635 | ||
1641 | err = 0; | 1636 | err = 0; |
1642 | 1637 | ||
1643 | br_vlan_get_tag(skb, &vid); | ||
1644 | BR_INPUT_SKB_CB(skb)->igmp = 1; | 1638 | BR_INPUT_SKB_CB(skb)->igmp = 1; |
1645 | 1639 | ||
1646 | switch (icmp6_type) { | 1640 | switch (icmp6_type) { |
@@ -1657,10 +1651,10 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br, | |||
1657 | break; | 1651 | break; |
1658 | } | 1652 | } |
1659 | case ICMPV6_MLD2_REPORT: | 1653 | case ICMPV6_MLD2_REPORT: |
1660 | err = br_ip6_multicast_mld2_report(br, port, skb2); | 1654 | err = br_ip6_multicast_mld2_report(br, port, skb2, vid); |
1661 | break; | 1655 | break; |
1662 | case ICMPV6_MGM_QUERY: | 1656 | case ICMPV6_MGM_QUERY: |
1663 | err = br_ip6_multicast_query(br, port, skb2); | 1657 | err = br_ip6_multicast_query(br, port, skb2, vid); |
1664 | break; | 1658 | break; |
1665 | case ICMPV6_MGM_REDUCTION: | 1659 | case ICMPV6_MGM_REDUCTION: |
1666 | { | 1660 | { |
@@ -1681,7 +1675,7 @@ out: | |||
1681 | #endif | 1675 | #endif |
1682 | 1676 | ||
1683 | int br_multicast_rcv(struct net_bridge *br, struct net_bridge_port *port, | 1677 | int br_multicast_rcv(struct net_bridge *br, struct net_bridge_port *port, |
1684 | struct sk_buff *skb) | 1678 | struct sk_buff *skb, u16 vid) |
1685 | { | 1679 | { |
1686 | BR_INPUT_SKB_CB(skb)->igmp = 0; | 1680 | BR_INPUT_SKB_CB(skb)->igmp = 0; |
1687 | BR_INPUT_SKB_CB(skb)->mrouters_only = 0; | 1681 | BR_INPUT_SKB_CB(skb)->mrouters_only = 0; |
@@ -1691,10 +1685,10 @@ int br_multicast_rcv(struct net_bridge *br, struct net_bridge_port *port, | |||
1691 | 1685 | ||
1692 | switch (skb->protocol) { | 1686 | switch (skb->protocol) { |
1693 | case htons(ETH_P_IP): | 1687 | case htons(ETH_P_IP): |
1694 | return br_multicast_ipv4_rcv(br, port, skb); | 1688 | return br_multicast_ipv4_rcv(br, port, skb, vid); |
1695 | #if IS_ENABLED(CONFIG_IPV6) | 1689 | #if IS_ENABLED(CONFIG_IPV6) |
1696 | case htons(ETH_P_IPV6): | 1690 | case htons(ETH_P_IPV6): |
1697 | return br_multicast_ipv6_rcv(br, port, skb); | 1691 | return br_multicast_ipv6_rcv(br, port, skb, vid); |
1698 | #endif | 1692 | #endif |
1699 | } | 1693 | } |
1700 | 1694 | ||
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index e14c33b42f75..2e8244efb262 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h | |||
@@ -451,7 +451,8 @@ extern int br_ioctl_deviceless_stub(struct net *net, unsigned int cmd, void __us | |||
451 | extern unsigned int br_mdb_rehash_seq; | 451 | extern unsigned int br_mdb_rehash_seq; |
452 | extern int br_multicast_rcv(struct net_bridge *br, | 452 | extern int br_multicast_rcv(struct net_bridge *br, |
453 | struct net_bridge_port *port, | 453 | struct net_bridge_port *port, |
454 | struct sk_buff *skb); | 454 | struct sk_buff *skb, |
455 | u16 vid); | ||
455 | extern struct net_bridge_mdb_entry *br_mdb_get(struct net_bridge *br, | 456 | extern struct net_bridge_mdb_entry *br_mdb_get(struct net_bridge *br, |
456 | struct sk_buff *skb, u16 vid); | 457 | struct sk_buff *skb, u16 vid); |
457 | extern void br_multicast_add_port(struct net_bridge_port *port); | 458 | extern void br_multicast_add_port(struct net_bridge_port *port); |
@@ -522,7 +523,8 @@ static inline bool br_multicast_querier_exists(struct net_bridge *br, | |||
522 | #else | 523 | #else |
523 | static inline int br_multicast_rcv(struct net_bridge *br, | 524 | static inline int br_multicast_rcv(struct net_bridge *br, |
524 | struct net_bridge_port *port, | 525 | struct net_bridge_port *port, |
525 | struct sk_buff *skb) | 526 | struct sk_buff *skb, |
527 | u16 vid) | ||
526 | { | 528 | { |
527 | return 0; | 529 | return 0; |
528 | } | 530 | } |
diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c index 518093802d1d..7c470c371e14 100644 --- a/net/bridge/netfilter/ebt_ulog.c +++ b/net/bridge/netfilter/ebt_ulog.c | |||
@@ -181,6 +181,7 @@ static void ebt_ulog_packet(struct net *net, unsigned int hooknr, | |||
181 | ub->qlen++; | 181 | ub->qlen++; |
182 | 182 | ||
183 | pm = nlmsg_data(nlh); | 183 | pm = nlmsg_data(nlh); |
184 | memset(pm, 0, sizeof(*pm)); | ||
184 | 185 | ||
185 | /* Fill in the ulog data */ | 186 | /* Fill in the ulog data */ |
186 | pm->version = EBT_ULOG_VERSION; | 187 | pm->version = EBT_ULOG_VERSION; |
@@ -193,8 +194,6 @@ static void ebt_ulog_packet(struct net *net, unsigned int hooknr, | |||
193 | pm->hook = hooknr; | 194 | pm->hook = hooknr; |
194 | if (uloginfo->prefix != NULL) | 195 | if (uloginfo->prefix != NULL) |
195 | strcpy(pm->prefix, uloginfo->prefix); | 196 | strcpy(pm->prefix, uloginfo->prefix); |
196 | else | ||
197 | *(pm->prefix) = '\0'; | ||
198 | 197 | ||
199 | if (in) { | 198 | if (in) { |
200 | strcpy(pm->physindev, in->name); | 199 | strcpy(pm->physindev, in->name); |
@@ -204,16 +203,14 @@ static void ebt_ulog_packet(struct net *net, unsigned int hooknr, | |||
204 | strcpy(pm->indev, br_port_get_rcu(in)->br->dev->name); | 203 | strcpy(pm->indev, br_port_get_rcu(in)->br->dev->name); |
205 | else | 204 | else |
206 | strcpy(pm->indev, in->name); | 205 | strcpy(pm->indev, in->name); |
207 | } else | 206 | } |
208 | pm->indev[0] = pm->physindev[0] = '\0'; | ||
209 | 207 | ||
210 | if (out) { | 208 | if (out) { |
211 | /* If out exists, then out is a bridge port */ | 209 | /* If out exists, then out is a bridge port */ |
212 | strcpy(pm->physoutdev, out->name); | 210 | strcpy(pm->physoutdev, out->name); |
213 | /* rcu_read_lock()ed by nf_hook_slow */ | 211 | /* rcu_read_lock()ed by nf_hook_slow */ |
214 | strcpy(pm->outdev, br_port_get_rcu(out)->br->dev->name); | 212 | strcpy(pm->outdev, br_port_get_rcu(out)->br->dev->name); |
215 | } else | 213 | } |
216 | pm->outdev[0] = pm->physoutdev[0] = '\0'; | ||
217 | 214 | ||
218 | if (skb_copy_bits(skb, -ETH_HLEN, pm->data, copy_len) < 0) | 215 | if (skb_copy_bits(skb, -ETH_HLEN, pm->data, copy_len) < 0) |
219 | BUG(); | 216 | BUG(); |
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c index 8d7d0dd72db2..143b6fdb9647 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c | |||
@@ -40,7 +40,7 @@ again: | |||
40 | struct iphdr _iph; | 40 | struct iphdr _iph; |
41 | ip: | 41 | ip: |
42 | iph = skb_header_pointer(skb, nhoff, sizeof(_iph), &_iph); | 42 | iph = skb_header_pointer(skb, nhoff, sizeof(_iph), &_iph); |
43 | if (!iph) | 43 | if (!iph || iph->ihl < 5) |
44 | return false; | 44 | return false; |
45 | 45 | ||
46 | if (ip_is_fragment(iph)) | 46 | if (ip_is_fragment(iph)) |
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index d954b56b4e47..325dee863e46 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c | |||
@@ -1344,17 +1344,19 @@ int netdev_register_kobject(struct net_device *net) | |||
1344 | return error; | 1344 | return error; |
1345 | } | 1345 | } |
1346 | 1346 | ||
1347 | int netdev_class_create_file(struct class_attribute *class_attr) | 1347 | int netdev_class_create_file_ns(struct class_attribute *class_attr, |
1348 | const void *ns) | ||
1348 | { | 1349 | { |
1349 | return class_create_file(&net_class, class_attr); | 1350 | return class_create_file_ns(&net_class, class_attr, ns); |
1350 | } | 1351 | } |
1351 | EXPORT_SYMBOL(netdev_class_create_file); | 1352 | EXPORT_SYMBOL(netdev_class_create_file_ns); |
1352 | 1353 | ||
1353 | void netdev_class_remove_file(struct class_attribute *class_attr) | 1354 | void netdev_class_remove_file_ns(struct class_attribute *class_attr, |
1355 | const void *ns) | ||
1354 | { | 1356 | { |
1355 | class_remove_file(&net_class, class_attr); | 1357 | class_remove_file_ns(&net_class, class_attr, ns); |
1356 | } | 1358 | } |
1357 | EXPORT_SYMBOL(netdev_class_remove_file); | 1359 | EXPORT_SYMBOL(netdev_class_remove_file_ns); |
1358 | 1360 | ||
1359 | int netdev_kobject_init(void) | 1361 | int netdev_kobject_init(void) |
1360 | { | 1362 | { |
diff --git a/net/core/netpoll.c b/net/core/netpoll.c index fc75c9e461b8..8f971990677c 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c | |||
@@ -636,8 +636,9 @@ static void netpoll_neigh_reply(struct sk_buff *skb, struct netpoll_info *npinfo | |||
636 | 636 | ||
637 | netpoll_send_skb(np, send_skb); | 637 | netpoll_send_skb(np, send_skb); |
638 | 638 | ||
639 | /* If there are several rx_hooks for the same address, | 639 | /* If there are several rx_skb_hooks for the same |
640 | we're fine by sending a single reply */ | 640 | * address we're fine by sending a single reply |
641 | */ | ||
641 | break; | 642 | break; |
642 | } | 643 | } |
643 | spin_unlock_irqrestore(&npinfo->rx_lock, flags); | 644 | spin_unlock_irqrestore(&npinfo->rx_lock, flags); |
@@ -719,8 +720,9 @@ static void netpoll_neigh_reply(struct sk_buff *skb, struct netpoll_info *npinfo | |||
719 | 720 | ||
720 | netpoll_send_skb(np, send_skb); | 721 | netpoll_send_skb(np, send_skb); |
721 | 722 | ||
722 | /* If there are several rx_hooks for the same address, | 723 | /* If there are several rx_skb_hooks for the same |
723 | we're fine by sending a single reply */ | 724 | * address, we're fine by sending a single reply |
725 | */ | ||
724 | break; | 726 | break; |
725 | } | 727 | } |
726 | spin_unlock_irqrestore(&npinfo->rx_lock, flags); | 728 | spin_unlock_irqrestore(&npinfo->rx_lock, flags); |
@@ -756,11 +758,12 @@ static bool pkt_is_ns(struct sk_buff *skb) | |||
756 | 758 | ||
757 | int __netpoll_rx(struct sk_buff *skb, struct netpoll_info *npinfo) | 759 | int __netpoll_rx(struct sk_buff *skb, struct netpoll_info *npinfo) |
758 | { | 760 | { |
759 | int proto, len, ulen; | 761 | int proto, len, ulen, data_len; |
760 | int hits = 0; | 762 | int hits = 0, offset; |
761 | const struct iphdr *iph; | 763 | const struct iphdr *iph; |
762 | struct udphdr *uh; | 764 | struct udphdr *uh; |
763 | struct netpoll *np, *tmp; | 765 | struct netpoll *np, *tmp; |
766 | uint16_t source; | ||
764 | 767 | ||
765 | if (list_empty(&npinfo->rx_np)) | 768 | if (list_empty(&npinfo->rx_np)) |
766 | goto out; | 769 | goto out; |
@@ -820,7 +823,10 @@ int __netpoll_rx(struct sk_buff *skb, struct netpoll_info *npinfo) | |||
820 | 823 | ||
821 | len -= iph->ihl*4; | 824 | len -= iph->ihl*4; |
822 | uh = (struct udphdr *)(((char *)iph) + iph->ihl*4); | 825 | uh = (struct udphdr *)(((char *)iph) + iph->ihl*4); |
826 | offset = (unsigned char *)(uh + 1) - skb->data; | ||
823 | ulen = ntohs(uh->len); | 827 | ulen = ntohs(uh->len); |
828 | data_len = skb->len - offset; | ||
829 | source = ntohs(uh->source); | ||
824 | 830 | ||
825 | if (ulen != len) | 831 | if (ulen != len) |
826 | goto out; | 832 | goto out; |
@@ -834,9 +840,7 @@ int __netpoll_rx(struct sk_buff *skb, struct netpoll_info *npinfo) | |||
834 | if (np->local_port && np->local_port != ntohs(uh->dest)) | 840 | if (np->local_port && np->local_port != ntohs(uh->dest)) |
835 | continue; | 841 | continue; |
836 | 842 | ||
837 | np->rx_hook(np, ntohs(uh->source), | 843 | np->rx_skb_hook(np, source, skb, offset, data_len); |
838 | (char *)(uh+1), | ||
839 | ulen - sizeof(struct udphdr)); | ||
840 | hits++; | 844 | hits++; |
841 | } | 845 | } |
842 | } else { | 846 | } else { |
@@ -859,7 +863,10 @@ int __netpoll_rx(struct sk_buff *skb, struct netpoll_info *npinfo) | |||
859 | if (!pskb_may_pull(skb, sizeof(struct udphdr))) | 863 | if (!pskb_may_pull(skb, sizeof(struct udphdr))) |
860 | goto out; | 864 | goto out; |
861 | uh = udp_hdr(skb); | 865 | uh = udp_hdr(skb); |
866 | offset = (unsigned char *)(uh + 1) - skb->data; | ||
862 | ulen = ntohs(uh->len); | 867 | ulen = ntohs(uh->len); |
868 | data_len = skb->len - offset; | ||
869 | source = ntohs(uh->source); | ||
863 | if (ulen != skb->len) | 870 | if (ulen != skb->len) |
864 | goto out; | 871 | goto out; |
865 | if (udp6_csum_init(skb, uh, IPPROTO_UDP)) | 872 | if (udp6_csum_init(skb, uh, IPPROTO_UDP)) |
@@ -872,9 +879,7 @@ int __netpoll_rx(struct sk_buff *skb, struct netpoll_info *npinfo) | |||
872 | if (np->local_port && np->local_port != ntohs(uh->dest)) | 879 | if (np->local_port && np->local_port != ntohs(uh->dest)) |
873 | continue; | 880 | continue; |
874 | 881 | ||
875 | np->rx_hook(np, ntohs(uh->source), | 882 | np->rx_skb_hook(np, source, skb, offset, data_len); |
876 | (char *)(uh+1), | ||
877 | ulen - sizeof(struct udphdr)); | ||
878 | hits++; | 883 | hits++; |
879 | } | 884 | } |
880 | #endif | 885 | #endif |
@@ -1062,7 +1067,7 @@ int __netpoll_setup(struct netpoll *np, struct net_device *ndev, gfp_t gfp) | |||
1062 | 1067 | ||
1063 | npinfo->netpoll = np; | 1068 | npinfo->netpoll = np; |
1064 | 1069 | ||
1065 | if (np->rx_hook) { | 1070 | if (np->rx_skb_hook) { |
1066 | spin_lock_irqsave(&npinfo->rx_lock, flags); | 1071 | spin_lock_irqsave(&npinfo->rx_lock, flags); |
1067 | npinfo->rx_flags |= NETPOLL_RX_ENABLED; | 1072 | npinfo->rx_flags |= NETPOLL_RX_ENABLED; |
1068 | list_add_tail(&np->rx, &npinfo->rx_np); | 1073 | list_add_tail(&np->rx, &npinfo->rx_np); |
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index 85a4f21aac1a..59da7cde0724 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c | |||
@@ -271,6 +271,11 @@ unsigned int arpt_do_table(struct sk_buff *skb, | |||
271 | local_bh_disable(); | 271 | local_bh_disable(); |
272 | addend = xt_write_recseq_begin(); | 272 | addend = xt_write_recseq_begin(); |
273 | private = table->private; | 273 | private = table->private; |
274 | /* | ||
275 | * Ensure we load private-> members after we've fetched the base | ||
276 | * pointer. | ||
277 | */ | ||
278 | smp_read_barrier_depends(); | ||
274 | table_base = private->entries[smp_processor_id()]; | 279 | table_base = private->entries[smp_processor_id()]; |
275 | 280 | ||
276 | e = get_entry(table_base, private->hook_entry[hook]); | 281 | e = get_entry(table_base, private->hook_entry[hook]); |
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index d23118d95ff9..718dfbd30cbe 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c | |||
@@ -327,6 +327,11 @@ ipt_do_table(struct sk_buff *skb, | |||
327 | addend = xt_write_recseq_begin(); | 327 | addend = xt_write_recseq_begin(); |
328 | private = table->private; | 328 | private = table->private; |
329 | cpu = smp_processor_id(); | 329 | cpu = smp_processor_id(); |
330 | /* | ||
331 | * Ensure we load private-> members after we've fetched the base | ||
332 | * pointer. | ||
333 | */ | ||
334 | smp_read_barrier_depends(); | ||
330 | table_base = private->entries[cpu]; | 335 | table_base = private->entries[cpu]; |
331 | jumpstack = (struct ipt_entry **)private->jumpstack[cpu]; | 336 | jumpstack = (struct ipt_entry **)private->jumpstack[cpu]; |
332 | stackptr = per_cpu_ptr(private->stackptr, cpu); | 337 | stackptr = per_cpu_ptr(private->stackptr, cpu); |
diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c index cbc22158af49..9cb993cd224b 100644 --- a/net/ipv4/netfilter/ipt_ULOG.c +++ b/net/ipv4/netfilter/ipt_ULOG.c | |||
@@ -220,6 +220,7 @@ static void ipt_ulog_packet(struct net *net, | |||
220 | ub->qlen++; | 220 | ub->qlen++; |
221 | 221 | ||
222 | pm = nlmsg_data(nlh); | 222 | pm = nlmsg_data(nlh); |
223 | memset(pm, 0, sizeof(*pm)); | ||
223 | 224 | ||
224 | /* We might not have a timestamp, get one */ | 225 | /* We might not have a timestamp, get one */ |
225 | if (skb->tstamp.tv64 == 0) | 226 | if (skb->tstamp.tv64 == 0) |
@@ -238,8 +239,6 @@ static void ipt_ulog_packet(struct net *net, | |||
238 | } | 239 | } |
239 | else if (loginfo->prefix[0] != '\0') | 240 | else if (loginfo->prefix[0] != '\0') |
240 | strncpy(pm->prefix, loginfo->prefix, sizeof(pm->prefix)); | 241 | strncpy(pm->prefix, loginfo->prefix, sizeof(pm->prefix)); |
241 | else | ||
242 | *(pm->prefix) = '\0'; | ||
243 | 242 | ||
244 | if (in && in->hard_header_len > 0 && | 243 | if (in && in->hard_header_len > 0 && |
245 | skb->mac_header != skb->network_header && | 244 | skb->mac_header != skb->network_header && |
@@ -251,13 +250,9 @@ static void ipt_ulog_packet(struct net *net, | |||
251 | 250 | ||
252 | if (in) | 251 | if (in) |
253 | strncpy(pm->indev_name, in->name, sizeof(pm->indev_name)); | 252 | strncpy(pm->indev_name, in->name, sizeof(pm->indev_name)); |
254 | else | ||
255 | pm->indev_name[0] = '\0'; | ||
256 | 253 | ||
257 | if (out) | 254 | if (out) |
258 | strncpy(pm->outdev_name, out->name, sizeof(pm->outdev_name)); | 255 | strncpy(pm->outdev_name, out->name, sizeof(pm->outdev_name)); |
259 | else | ||
260 | pm->outdev_name[0] = '\0'; | ||
261 | 256 | ||
262 | /* copy_len <= skb->len, so can't fail. */ | 257 | /* copy_len <= skb->len, so can't fail. */ |
263 | if (skb_copy_bits(skb, 0, pm->payload, copy_len) < 0) | 258 | if (skb_copy_bits(skb, 0, pm->payload, copy_len) < 0) |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index a16b01b537ba..068c8fb0d158 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -2856,7 +2856,8 @@ static inline bool tcp_ack_update_rtt(struct sock *sk, const int flag, | |||
2856 | * left edge of the send window. | 2856 | * left edge of the send window. |
2857 | * See draft-ietf-tcplw-high-performance-00, section 3.3. | 2857 | * See draft-ietf-tcplw-high-performance-00, section 3.3. |
2858 | */ | 2858 | */ |
2859 | if (seq_rtt < 0 && tp->rx_opt.saw_tstamp && tp->rx_opt.rcv_tsecr) | 2859 | if (seq_rtt < 0 && tp->rx_opt.saw_tstamp && tp->rx_opt.rcv_tsecr && |
2860 | flag & FLAG_ACKED) | ||
2860 | seq_rtt = tcp_time_stamp - tp->rx_opt.rcv_tsecr; | 2861 | seq_rtt = tcp_time_stamp - tp->rx_opt.rcv_tsecr; |
2861 | 2862 | ||
2862 | if (seq_rtt < 0) | 2863 | if (seq_rtt < 0) |
@@ -2871,14 +2872,19 @@ static inline bool tcp_ack_update_rtt(struct sock *sk, const int flag, | |||
2871 | } | 2872 | } |
2872 | 2873 | ||
2873 | /* Compute time elapsed between (last) SYNACK and the ACK completing 3WHS. */ | 2874 | /* Compute time elapsed between (last) SYNACK and the ACK completing 3WHS. */ |
2874 | static void tcp_synack_rtt_meas(struct sock *sk, struct request_sock *req) | 2875 | static void tcp_synack_rtt_meas(struct sock *sk, const u32 synack_stamp) |
2875 | { | 2876 | { |
2876 | struct tcp_sock *tp = tcp_sk(sk); | 2877 | struct tcp_sock *tp = tcp_sk(sk); |
2877 | s32 seq_rtt = -1; | 2878 | s32 seq_rtt = -1; |
2878 | 2879 | ||
2879 | if (tp->lsndtime && !tp->total_retrans) | 2880 | if (synack_stamp && !tp->total_retrans) |
2880 | seq_rtt = tcp_time_stamp - tp->lsndtime; | 2881 | seq_rtt = tcp_time_stamp - synack_stamp; |
2881 | tcp_ack_update_rtt(sk, FLAG_SYN_ACKED, seq_rtt, -1); | 2882 | |
2883 | /* If the ACK acks both the SYNACK and the (Fast Open'd) data packets | ||
2884 | * sent in SYN_RECV, SYNACK RTT is the smooth RTT computed in tcp_ack() | ||
2885 | */ | ||
2886 | if (!tp->srtt) | ||
2887 | tcp_ack_update_rtt(sk, FLAG_SYN_ACKED, seq_rtt, -1); | ||
2882 | } | 2888 | } |
2883 | 2889 | ||
2884 | static void tcp_cong_avoid(struct sock *sk, u32 ack, u32 in_flight) | 2890 | static void tcp_cong_avoid(struct sock *sk, u32 ack, u32 in_flight) |
@@ -2981,6 +2987,7 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets, | |||
2981 | s32 seq_rtt = -1; | 2987 | s32 seq_rtt = -1; |
2982 | s32 ca_seq_rtt = -1; | 2988 | s32 ca_seq_rtt = -1; |
2983 | ktime_t last_ackt = net_invalid_timestamp(); | 2989 | ktime_t last_ackt = net_invalid_timestamp(); |
2990 | bool rtt_update; | ||
2984 | 2991 | ||
2985 | while ((skb = tcp_write_queue_head(sk)) && skb != tcp_send_head(sk)) { | 2992 | while ((skb = tcp_write_queue_head(sk)) && skb != tcp_send_head(sk)) { |
2986 | struct tcp_skb_cb *scb = TCP_SKB_CB(skb); | 2993 | struct tcp_skb_cb *scb = TCP_SKB_CB(skb); |
@@ -3057,14 +3064,13 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets, | |||
3057 | if (skb && (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED)) | 3064 | if (skb && (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED)) |
3058 | flag |= FLAG_SACK_RENEGING; | 3065 | flag |= FLAG_SACK_RENEGING; |
3059 | 3066 | ||
3060 | if (tcp_ack_update_rtt(sk, flag, seq_rtt, sack_rtt) || | 3067 | rtt_update = tcp_ack_update_rtt(sk, flag, seq_rtt, sack_rtt); |
3061 | (flag & FLAG_ACKED)) | ||
3062 | tcp_rearm_rto(sk); | ||
3063 | 3068 | ||
3064 | if (flag & FLAG_ACKED) { | 3069 | if (flag & FLAG_ACKED) { |
3065 | const struct tcp_congestion_ops *ca_ops | 3070 | const struct tcp_congestion_ops *ca_ops |
3066 | = inet_csk(sk)->icsk_ca_ops; | 3071 | = inet_csk(sk)->icsk_ca_ops; |
3067 | 3072 | ||
3073 | tcp_rearm_rto(sk); | ||
3068 | if (unlikely(icsk->icsk_mtup.probe_size && | 3074 | if (unlikely(icsk->icsk_mtup.probe_size && |
3069 | !after(tp->mtu_probe.probe_seq_end, tp->snd_una))) { | 3075 | !after(tp->mtu_probe.probe_seq_end, tp->snd_una))) { |
3070 | tcp_mtup_probe_success(sk); | 3076 | tcp_mtup_probe_success(sk); |
@@ -3103,6 +3109,13 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets, | |||
3103 | 3109 | ||
3104 | ca_ops->pkts_acked(sk, pkts_acked, rtt_us); | 3110 | ca_ops->pkts_acked(sk, pkts_acked, rtt_us); |
3105 | } | 3111 | } |
3112 | } else if (skb && rtt_update && sack_rtt >= 0 && | ||
3113 | sack_rtt > (s32)(now - TCP_SKB_CB(skb)->when)) { | ||
3114 | /* Do not re-arm RTO if the sack RTT is measured from data sent | ||
3115 | * after when the head was last (re)transmitted. Otherwise the | ||
3116 | * timeout may continue to extend in loss recovery. | ||
3117 | */ | ||
3118 | tcp_rearm_rto(sk); | ||
3106 | } | 3119 | } |
3107 | 3120 | ||
3108 | #if FASTRETRANS_DEBUG > 0 | 3121 | #if FASTRETRANS_DEBUG > 0 |
@@ -5587,6 +5600,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, | |||
5587 | struct request_sock *req; | 5600 | struct request_sock *req; |
5588 | int queued = 0; | 5601 | int queued = 0; |
5589 | bool acceptable; | 5602 | bool acceptable; |
5603 | u32 synack_stamp; | ||
5590 | 5604 | ||
5591 | tp->rx_opt.saw_tstamp = 0; | 5605 | tp->rx_opt.saw_tstamp = 0; |
5592 | 5606 | ||
@@ -5669,9 +5683,11 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, | |||
5669 | * so release it. | 5683 | * so release it. |
5670 | */ | 5684 | */ |
5671 | if (req) { | 5685 | if (req) { |
5686 | synack_stamp = tcp_rsk(req)->snt_synack; | ||
5672 | tp->total_retrans = req->num_retrans; | 5687 | tp->total_retrans = req->num_retrans; |
5673 | reqsk_fastopen_remove(sk, req, false); | 5688 | reqsk_fastopen_remove(sk, req, false); |
5674 | } else { | 5689 | } else { |
5690 | synack_stamp = tp->lsndtime; | ||
5675 | /* Make sure socket is routed, for correct metrics. */ | 5691 | /* Make sure socket is routed, for correct metrics. */ |
5676 | icsk->icsk_af_ops->rebuild_header(sk); | 5692 | icsk->icsk_af_ops->rebuild_header(sk); |
5677 | tcp_init_congestion_control(sk); | 5693 | tcp_init_congestion_control(sk); |
@@ -5694,7 +5710,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, | |||
5694 | tp->snd_una = TCP_SKB_CB(skb)->ack_seq; | 5710 | tp->snd_una = TCP_SKB_CB(skb)->ack_seq; |
5695 | tp->snd_wnd = ntohs(th->window) << tp->rx_opt.snd_wscale; | 5711 | tp->snd_wnd = ntohs(th->window) << tp->rx_opt.snd_wscale; |
5696 | tcp_init_wl(tp, TCP_SKB_CB(skb)->seq); | 5712 | tcp_init_wl(tp, TCP_SKB_CB(skb)->seq); |
5697 | tcp_synack_rtt_meas(sk, req); | 5713 | tcp_synack_rtt_meas(sk, synack_stamp); |
5698 | 5714 | ||
5699 | if (tp->rx_opt.tstamp_ok) | 5715 | if (tp->rx_opt.tstamp_ok) |
5700 | tp->advmss -= TCPOLEN_TSTAMP_ALIGNED; | 5716 | tp->advmss -= TCPOLEN_TSTAMP_ALIGNED; |
diff --git a/net/ipv4/tcp_offload.c b/net/ipv4/tcp_offload.c index 3a7525e6c086..533c58a5cfb7 100644 --- a/net/ipv4/tcp_offload.c +++ b/net/ipv4/tcp_offload.c | |||
@@ -18,6 +18,7 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, | |||
18 | netdev_features_t features) | 18 | netdev_features_t features) |
19 | { | 19 | { |
20 | struct sk_buff *segs = ERR_PTR(-EINVAL); | 20 | struct sk_buff *segs = ERR_PTR(-EINVAL); |
21 | unsigned int sum_truesize = 0; | ||
21 | struct tcphdr *th; | 22 | struct tcphdr *th; |
22 | unsigned int thlen; | 23 | unsigned int thlen; |
23 | unsigned int seq; | 24 | unsigned int seq; |
@@ -102,13 +103,7 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, | |||
102 | if (copy_destructor) { | 103 | if (copy_destructor) { |
103 | skb->destructor = gso_skb->destructor; | 104 | skb->destructor = gso_skb->destructor; |
104 | skb->sk = gso_skb->sk; | 105 | skb->sk = gso_skb->sk; |
105 | /* {tcp|sock}_wfree() use exact truesize accounting : | 106 | sum_truesize += skb->truesize; |
106 | * sum(skb->truesize) MUST be exactly be gso_skb->truesize | ||
107 | * So we account mss bytes of 'true size' for each segment. | ||
108 | * The last segment will contain the remaining. | ||
109 | */ | ||
110 | skb->truesize = mss; | ||
111 | gso_skb->truesize -= mss; | ||
112 | } | 107 | } |
113 | skb = skb->next; | 108 | skb = skb->next; |
114 | th = tcp_hdr(skb); | 109 | th = tcp_hdr(skb); |
@@ -125,7 +120,9 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, | |||
125 | if (copy_destructor) { | 120 | if (copy_destructor) { |
126 | swap(gso_skb->sk, skb->sk); | 121 | swap(gso_skb->sk, skb->sk); |
127 | swap(gso_skb->destructor, skb->destructor); | 122 | swap(gso_skb->destructor, skb->destructor); |
128 | swap(gso_skb->truesize, skb->truesize); | 123 | sum_truesize += skb->truesize; |
124 | atomic_add(sum_truesize - gso_skb->truesize, | ||
125 | &skb->sk->sk_wmem_alloc); | ||
129 | } | 126 | } |
130 | 127 | ||
131 | delta = htonl(oldlen + (skb_tail_pointer(skb) - | 128 | delta = htonl(oldlen + (skb_tail_pointer(skb) - |
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c index ccde54248c8c..e1a63930a967 100644 --- a/net/ipv4/xfrm4_policy.c +++ b/net/ipv4/xfrm4_policy.c | |||
@@ -104,10 +104,14 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse) | |||
104 | const struct iphdr *iph = ip_hdr(skb); | 104 | const struct iphdr *iph = ip_hdr(skb); |
105 | u8 *xprth = skb_network_header(skb) + iph->ihl * 4; | 105 | u8 *xprth = skb_network_header(skb) + iph->ihl * 4; |
106 | struct flowi4 *fl4 = &fl->u.ip4; | 106 | struct flowi4 *fl4 = &fl->u.ip4; |
107 | int oif = 0; | ||
108 | |||
109 | if (skb_dst(skb)) | ||
110 | oif = skb_dst(skb)->dev->ifindex; | ||
107 | 111 | ||
108 | memset(fl4, 0, sizeof(struct flowi4)); | 112 | memset(fl4, 0, sizeof(struct flowi4)); |
109 | fl4->flowi4_mark = skb->mark; | 113 | fl4->flowi4_mark = skb->mark; |
110 | fl4->flowi4_oif = skb_dst(skb)->dev->ifindex; | 114 | fl4->flowi4_oif = reverse ? skb->skb_iif : oif; |
111 | 115 | ||
112 | if (!ip_is_fragment(iph)) { | 116 | if (!ip_is_fragment(iph)) { |
113 | switch (iph->protocol) { | 117 | switch (iph->protocol) { |
@@ -236,7 +240,7 @@ static struct dst_ops xfrm4_dst_ops = { | |||
236 | .destroy = xfrm4_dst_destroy, | 240 | .destroy = xfrm4_dst_destroy, |
237 | .ifdown = xfrm4_dst_ifdown, | 241 | .ifdown = xfrm4_dst_ifdown, |
238 | .local_out = __ip_local_out, | 242 | .local_out = __ip_local_out, |
239 | .gc_thresh = 1024, | 243 | .gc_thresh = 32768, |
240 | }; | 244 | }; |
241 | 245 | ||
242 | static struct xfrm_policy_afinfo xfrm4_policy_afinfo = { | 246 | static struct xfrm_policy_afinfo xfrm4_policy_afinfo = { |
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 44400c216dc6..710238f58aa9 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c | |||
@@ -349,6 +349,11 @@ ip6t_do_table(struct sk_buff *skb, | |||
349 | local_bh_disable(); | 349 | local_bh_disable(); |
350 | addend = xt_write_recseq_begin(); | 350 | addend = xt_write_recseq_begin(); |
351 | private = table->private; | 351 | private = table->private; |
352 | /* | ||
353 | * Ensure we load private-> members after we've fetched the base | ||
354 | * pointer. | ||
355 | */ | ||
356 | smp_read_barrier_depends(); | ||
352 | cpu = smp_processor_id(); | 357 | cpu = smp_processor_id(); |
353 | table_base = private->entries[cpu]; | 358 | table_base = private->entries[cpu]; |
354 | jumpstack = (struct ip6t_entry **)private->jumpstack[cpu]; | 359 | jumpstack = (struct ip6t_entry **)private->jumpstack[cpu]; |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index f54e3a101098..04e17b3309fb 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -1087,10 +1087,13 @@ static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie) | |||
1087 | if (rt->rt6i_genid != rt_genid_ipv6(dev_net(rt->dst.dev))) | 1087 | if (rt->rt6i_genid != rt_genid_ipv6(dev_net(rt->dst.dev))) |
1088 | return NULL; | 1088 | return NULL; |
1089 | 1089 | ||
1090 | if (rt->rt6i_node && (rt->rt6i_node->fn_sernum == cookie)) | 1090 | if (!rt->rt6i_node || (rt->rt6i_node->fn_sernum != cookie)) |
1091 | return dst; | 1091 | return NULL; |
1092 | 1092 | ||
1093 | return NULL; | 1093 | if (rt6_check_expired(rt)) |
1094 | return NULL; | ||
1095 | |||
1096 | return dst; | ||
1094 | } | 1097 | } |
1095 | 1098 | ||
1096 | static struct dst_entry *ip6_negative_advice(struct dst_entry *dst) | 1099 | static struct dst_entry *ip6_negative_advice(struct dst_entry *dst) |
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index 08ed2772b7aa..5f8e128c512d 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c | |||
@@ -135,10 +135,14 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse) | |||
135 | struct ipv6_opt_hdr *exthdr; | 135 | struct ipv6_opt_hdr *exthdr; |
136 | const unsigned char *nh = skb_network_header(skb); | 136 | const unsigned char *nh = skb_network_header(skb); |
137 | u8 nexthdr = nh[IP6CB(skb)->nhoff]; | 137 | u8 nexthdr = nh[IP6CB(skb)->nhoff]; |
138 | int oif = 0; | ||
139 | |||
140 | if (skb_dst(skb)) | ||
141 | oif = skb_dst(skb)->dev->ifindex; | ||
138 | 142 | ||
139 | memset(fl6, 0, sizeof(struct flowi6)); | 143 | memset(fl6, 0, sizeof(struct flowi6)); |
140 | fl6->flowi6_mark = skb->mark; | 144 | fl6->flowi6_mark = skb->mark; |
141 | fl6->flowi6_oif = skb_dst(skb)->dev->ifindex; | 145 | fl6->flowi6_oif = reverse ? skb->skb_iif : oif; |
142 | 146 | ||
143 | fl6->daddr = reverse ? hdr->saddr : hdr->daddr; | 147 | fl6->daddr = reverse ? hdr->saddr : hdr->daddr; |
144 | fl6->saddr = reverse ? hdr->daddr : hdr->saddr; | 148 | fl6->saddr = reverse ? hdr->daddr : hdr->saddr; |
@@ -285,7 +289,7 @@ static struct dst_ops xfrm6_dst_ops = { | |||
285 | .destroy = xfrm6_dst_destroy, | 289 | .destroy = xfrm6_dst_destroy, |
286 | .ifdown = xfrm6_dst_ifdown, | 290 | .ifdown = xfrm6_dst_ifdown, |
287 | .local_out = __ip6_local_out, | 291 | .local_out = __ip6_local_out, |
288 | .gc_thresh = 1024, | 292 | .gc_thresh = 32768, |
289 | }; | 293 | }; |
290 | 294 | ||
291 | static struct xfrm_policy_afinfo xfrm6_policy_afinfo = { | 295 | static struct xfrm_policy_afinfo xfrm6_policy_afinfo = { |
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index 8b03028cca69..227aa11e8409 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c | |||
@@ -845,8 +845,13 @@ xt_replace_table(struct xt_table *table, | |||
845 | return NULL; | 845 | return NULL; |
846 | } | 846 | } |
847 | 847 | ||
848 | table->private = newinfo; | ||
849 | newinfo->initial_entries = private->initial_entries; | 848 | newinfo->initial_entries = private->initial_entries; |
849 | /* | ||
850 | * Ensure contents of newinfo are visible before assigning to | ||
851 | * private. | ||
852 | */ | ||
853 | smp_wmb(); | ||
854 | table->private = newinfo; | ||
850 | 855 | ||
851 | /* | 856 | /* |
852 | * Even though table entries have now been swapped, other CPU's | 857 | * Even though table entries have now been swapped, other CPU's |
diff --git a/net/netfilter/xt_NFQUEUE.c b/net/netfilter/xt_NFQUEUE.c index 1e2fae32f81b..ed00fef58996 100644 --- a/net/netfilter/xt_NFQUEUE.c +++ b/net/netfilter/xt_NFQUEUE.c | |||
@@ -147,6 +147,7 @@ nfqueue_tg_v3(struct sk_buff *skb, const struct xt_action_param *par) | |||
147 | { | 147 | { |
148 | const struct xt_NFQ_info_v3 *info = par->targinfo; | 148 | const struct xt_NFQ_info_v3 *info = par->targinfo; |
149 | u32 queue = info->queuenum; | 149 | u32 queue = info->queuenum; |
150 | int ret; | ||
150 | 151 | ||
151 | if (info->queues_total > 1) { | 152 | if (info->queues_total > 1) { |
152 | if (info->flags & NFQ_FLAG_CPU_FANOUT) { | 153 | if (info->flags & NFQ_FLAG_CPU_FANOUT) { |
@@ -157,7 +158,11 @@ nfqueue_tg_v3(struct sk_buff *skb, const struct xt_action_param *par) | |||
157 | queue = nfqueue_hash(skb, par); | 158 | queue = nfqueue_hash(skb, par); |
158 | } | 159 | } |
159 | 160 | ||
160 | return NF_QUEUE_NR(queue); | 161 | ret = NF_QUEUE_NR(queue); |
162 | if (info->flags & NFQ_FLAG_BYPASS) | ||
163 | ret |= NF_VERDICT_FLAG_QUEUE_BYPASS; | ||
164 | |||
165 | return ret; | ||
161 | } | 166 | } |
162 | 167 | ||
163 | static struct xt_target nfqueue_tg_reg[] __read_mostly = { | 168 | static struct xt_target nfqueue_tg_reg[] __read_mostly = { |
diff --git a/net/openvswitch/dp_notify.c b/net/openvswitch/dp_notify.c index c3235675f359..5c2dab276109 100644 --- a/net/openvswitch/dp_notify.c +++ b/net/openvswitch/dp_notify.c | |||
@@ -65,8 +65,7 @@ void ovs_dp_notify_wq(struct work_struct *work) | |||
65 | continue; | 65 | continue; |
66 | 66 | ||
67 | netdev_vport = netdev_vport_priv(vport); | 67 | netdev_vport = netdev_vport_priv(vport); |
68 | if (netdev_vport->dev->reg_state == NETREG_UNREGISTERED || | 68 | if (!(netdev_vport->dev->priv_flags & IFF_OVS_DATAPATH)) |
69 | netdev_vport->dev->reg_state == NETREG_UNREGISTERING) | ||
70 | dp_detach_port_notify(vport); | 69 | dp_detach_port_notify(vport); |
71 | } | 70 | } |
72 | } | 71 | } |
@@ -88,6 +87,10 @@ static int dp_device_event(struct notifier_block *unused, unsigned long event, | |||
88 | return NOTIFY_DONE; | 87 | return NOTIFY_DONE; |
89 | 88 | ||
90 | if (event == NETDEV_UNREGISTER) { | 89 | if (event == NETDEV_UNREGISTER) { |
90 | /* upper_dev_unlink and decrement promisc immediately */ | ||
91 | ovs_netdev_detach_dev(vport); | ||
92 | |||
93 | /* schedule vport destroy, dev_put and genl notification */ | ||
91 | ovs_net = net_generic(dev_net(dev), ovs_net_id); | 94 | ovs_net = net_generic(dev_net(dev), ovs_net_id); |
92 | queue_work(system_wq, &ovs_net->dp_notify_work); | 95 | queue_work(system_wq, &ovs_net->dp_notify_work); |
93 | } | 96 | } |
diff --git a/net/openvswitch/vport-netdev.c b/net/openvswitch/vport-netdev.c index 09d93c13cfd6..d21f77d875ba 100644 --- a/net/openvswitch/vport-netdev.c +++ b/net/openvswitch/vport-netdev.c | |||
@@ -150,15 +150,25 @@ static void free_port_rcu(struct rcu_head *rcu) | |||
150 | ovs_vport_free(vport_from_priv(netdev_vport)); | 150 | ovs_vport_free(vport_from_priv(netdev_vport)); |
151 | } | 151 | } |
152 | 152 | ||
153 | static void netdev_destroy(struct vport *vport) | 153 | void ovs_netdev_detach_dev(struct vport *vport) |
154 | { | 154 | { |
155 | struct netdev_vport *netdev_vport = netdev_vport_priv(vport); | 155 | struct netdev_vport *netdev_vport = netdev_vport_priv(vport); |
156 | 156 | ||
157 | rtnl_lock(); | 157 | ASSERT_RTNL(); |
158 | netdev_vport->dev->priv_flags &= ~IFF_OVS_DATAPATH; | 158 | netdev_vport->dev->priv_flags &= ~IFF_OVS_DATAPATH; |
159 | netdev_rx_handler_unregister(netdev_vport->dev); | 159 | netdev_rx_handler_unregister(netdev_vport->dev); |
160 | netdev_upper_dev_unlink(netdev_vport->dev, get_dpdev(vport->dp)); | 160 | netdev_upper_dev_unlink(netdev_vport->dev, |
161 | netdev_master_upper_dev_get(netdev_vport->dev)); | ||
161 | dev_set_promiscuity(netdev_vport->dev, -1); | 162 | dev_set_promiscuity(netdev_vport->dev, -1); |
163 | } | ||
164 | |||
165 | static void netdev_destroy(struct vport *vport) | ||
166 | { | ||
167 | struct netdev_vport *netdev_vport = netdev_vport_priv(vport); | ||
168 | |||
169 | rtnl_lock(); | ||
170 | if (netdev_vport->dev->priv_flags & IFF_OVS_DATAPATH) | ||
171 | ovs_netdev_detach_dev(vport); | ||
162 | rtnl_unlock(); | 172 | rtnl_unlock(); |
163 | 173 | ||
164 | call_rcu(&netdev_vport->rcu, free_port_rcu); | 174 | call_rcu(&netdev_vport->rcu, free_port_rcu); |
diff --git a/net/openvswitch/vport-netdev.h b/net/openvswitch/vport-netdev.h index dd298b5c5cdb..8df01c1127e5 100644 --- a/net/openvswitch/vport-netdev.h +++ b/net/openvswitch/vport-netdev.h | |||
@@ -39,5 +39,6 @@ netdev_vport_priv(const struct vport *vport) | |||
39 | } | 39 | } |
40 | 40 | ||
41 | const char *ovs_netdev_get_name(const struct vport *); | 41 | const char *ovs_netdev_get_name(const struct vport *); |
42 | void ovs_netdev_detach_dev(struct vport *); | ||
42 | 43 | ||
43 | #endif /* vport_netdev.h */ | 44 | #endif /* vport_netdev.h */ |
diff --git a/net/sched/sch_fq.c b/net/sched/sch_fq.c index a9dfdda9ed1d..fdc041c57853 100644 --- a/net/sched/sch_fq.c +++ b/net/sched/sch_fq.c | |||
@@ -255,6 +255,7 @@ static struct fq_flow *fq_classify(struct sk_buff *skb, struct fq_sched_data *q) | |||
255 | f->socket_hash != sk->sk_hash)) { | 255 | f->socket_hash != sk->sk_hash)) { |
256 | f->credit = q->initial_quantum; | 256 | f->credit = q->initial_quantum; |
257 | f->socket_hash = sk->sk_hash; | 257 | f->socket_hash = sk->sk_hash; |
258 | f->time_next_packet = 0ULL; | ||
258 | } | 259 | } |
259 | return f; | 260 | return f; |
260 | } | 261 | } |
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index e7b2d4fe2b6a..96a55910262c 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c | |||
@@ -279,7 +279,9 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr, | |||
279 | sctp_v6_to_addr(&dst_saddr, &fl6->saddr, htons(bp->port)); | 279 | sctp_v6_to_addr(&dst_saddr, &fl6->saddr, htons(bp->port)); |
280 | rcu_read_lock(); | 280 | rcu_read_lock(); |
281 | list_for_each_entry_rcu(laddr, &bp->address_list, list) { | 281 | list_for_each_entry_rcu(laddr, &bp->address_list, list) { |
282 | if (!laddr->valid || (laddr->state != SCTP_ADDR_SRC)) | 282 | if (!laddr->valid || laddr->state == SCTP_ADDR_DEL || |
283 | (laddr->state != SCTP_ADDR_SRC && | ||
284 | !asoc->src_out_of_asoc_ok)) | ||
283 | continue; | 285 | continue; |
284 | 286 | ||
285 | /* Do not compare against v4 addrs */ | 287 | /* Do not compare against v4 addrs */ |
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index 666c66842799..1a6eef39ab2f 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c | |||
@@ -860,7 +860,6 @@ static void sctp_cmd_delete_tcb(sctp_cmd_seq_t *cmds, | |||
860 | (!asoc->temp) && (sk->sk_shutdown != SHUTDOWN_MASK)) | 860 | (!asoc->temp) && (sk->sk_shutdown != SHUTDOWN_MASK)) |
861 | return; | 861 | return; |
862 | 862 | ||
863 | BUG_ON(asoc->peer.primary_path == NULL); | ||
864 | sctp_unhash_established(asoc); | 863 | sctp_unhash_established(asoc); |
865 | sctp_association_free(asoc); | 864 | sctp_association_free(asoc); |
866 | } | 865 | } |
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 084656671d6e..97912b40c254 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c | |||
@@ -420,41 +420,53 @@ static void gss_encode_v0_msg(struct gss_upcall_msg *gss_msg) | |||
420 | memcpy(gss_msg->databuf, &uid, sizeof(uid)); | 420 | memcpy(gss_msg->databuf, &uid, sizeof(uid)); |
421 | gss_msg->msg.data = gss_msg->databuf; | 421 | gss_msg->msg.data = gss_msg->databuf; |
422 | gss_msg->msg.len = sizeof(uid); | 422 | gss_msg->msg.len = sizeof(uid); |
423 | BUG_ON(sizeof(uid) > UPCALL_BUF_LEN); | 423 | |
424 | BUILD_BUG_ON(sizeof(uid) > sizeof(gss_msg->databuf)); | ||
424 | } | 425 | } |
425 | 426 | ||
426 | static void gss_encode_v1_msg(struct gss_upcall_msg *gss_msg, | 427 | static int gss_encode_v1_msg(struct gss_upcall_msg *gss_msg, |
427 | const char *service_name, | 428 | const char *service_name, |
428 | const char *target_name) | 429 | const char *target_name) |
429 | { | 430 | { |
430 | struct gss_api_mech *mech = gss_msg->auth->mech; | 431 | struct gss_api_mech *mech = gss_msg->auth->mech; |
431 | char *p = gss_msg->databuf; | 432 | char *p = gss_msg->databuf; |
432 | int len = 0; | 433 | size_t buflen = sizeof(gss_msg->databuf); |
433 | 434 | int len; | |
434 | gss_msg->msg.len = sprintf(gss_msg->databuf, "mech=%s uid=%d ", | 435 | |
435 | mech->gm_name, | 436 | len = scnprintf(p, buflen, "mech=%s uid=%d ", mech->gm_name, |
436 | from_kuid(&init_user_ns, gss_msg->uid)); | 437 | from_kuid(&init_user_ns, gss_msg->uid)); |
437 | p += gss_msg->msg.len; | 438 | buflen -= len; |
439 | p += len; | ||
440 | gss_msg->msg.len = len; | ||
438 | if (target_name) { | 441 | if (target_name) { |
439 | len = sprintf(p, "target=%s ", target_name); | 442 | len = scnprintf(p, buflen, "target=%s ", target_name); |
443 | buflen -= len; | ||
440 | p += len; | 444 | p += len; |
441 | gss_msg->msg.len += len; | 445 | gss_msg->msg.len += len; |
442 | } | 446 | } |
443 | if (service_name != NULL) { | 447 | if (service_name != NULL) { |
444 | len = sprintf(p, "service=%s ", service_name); | 448 | len = scnprintf(p, buflen, "service=%s ", service_name); |
449 | buflen -= len; | ||
445 | p += len; | 450 | p += len; |
446 | gss_msg->msg.len += len; | 451 | gss_msg->msg.len += len; |
447 | } | 452 | } |
448 | if (mech->gm_upcall_enctypes) { | 453 | if (mech->gm_upcall_enctypes) { |
449 | len = sprintf(p, "enctypes=%s ", mech->gm_upcall_enctypes); | 454 | len = scnprintf(p, buflen, "enctypes=%s ", |
455 | mech->gm_upcall_enctypes); | ||
456 | buflen -= len; | ||
450 | p += len; | 457 | p += len; |
451 | gss_msg->msg.len += len; | 458 | gss_msg->msg.len += len; |
452 | } | 459 | } |
453 | len = sprintf(p, "\n"); | 460 | len = scnprintf(p, buflen, "\n"); |
461 | if (len == 0) | ||
462 | goto out_overflow; | ||
454 | gss_msg->msg.len += len; | 463 | gss_msg->msg.len += len; |
455 | 464 | ||
456 | gss_msg->msg.data = gss_msg->databuf; | 465 | gss_msg->msg.data = gss_msg->databuf; |
457 | BUG_ON(gss_msg->msg.len > UPCALL_BUF_LEN); | 466 | return 0; |
467 | out_overflow: | ||
468 | WARN_ON_ONCE(1); | ||
469 | return -ENOMEM; | ||
458 | } | 470 | } |
459 | 471 | ||
460 | static struct gss_upcall_msg * | 472 | static struct gss_upcall_msg * |
@@ -463,15 +475,15 @@ gss_alloc_msg(struct gss_auth *gss_auth, | |||
463 | { | 475 | { |
464 | struct gss_upcall_msg *gss_msg; | 476 | struct gss_upcall_msg *gss_msg; |
465 | int vers; | 477 | int vers; |
478 | int err = -ENOMEM; | ||
466 | 479 | ||
467 | gss_msg = kzalloc(sizeof(*gss_msg), GFP_NOFS); | 480 | gss_msg = kzalloc(sizeof(*gss_msg), GFP_NOFS); |
468 | if (gss_msg == NULL) | 481 | if (gss_msg == NULL) |
469 | return ERR_PTR(-ENOMEM); | 482 | goto err; |
470 | vers = get_pipe_version(gss_auth->net); | 483 | vers = get_pipe_version(gss_auth->net); |
471 | if (vers < 0) { | 484 | err = vers; |
472 | kfree(gss_msg); | 485 | if (err < 0) |
473 | return ERR_PTR(vers); | 486 | goto err_free_msg; |
474 | } | ||
475 | gss_msg->pipe = gss_auth->gss_pipe[vers]->pipe; | 487 | gss_msg->pipe = gss_auth->gss_pipe[vers]->pipe; |
476 | INIT_LIST_HEAD(&gss_msg->list); | 488 | INIT_LIST_HEAD(&gss_msg->list); |
477 | rpc_init_wait_queue(&gss_msg->rpc_waitqueue, "RPCSEC_GSS upcall waitq"); | 489 | rpc_init_wait_queue(&gss_msg->rpc_waitqueue, "RPCSEC_GSS upcall waitq"); |
@@ -482,10 +494,17 @@ gss_alloc_msg(struct gss_auth *gss_auth, | |||
482 | switch (vers) { | 494 | switch (vers) { |
483 | case 0: | 495 | case 0: |
484 | gss_encode_v0_msg(gss_msg); | 496 | gss_encode_v0_msg(gss_msg); |
497 | break; | ||
485 | default: | 498 | default: |
486 | gss_encode_v1_msg(gss_msg, service_name, gss_auth->target_name); | 499 | err = gss_encode_v1_msg(gss_msg, service_name, gss_auth->target_name); |
500 | if (err) | ||
501 | goto err_free_msg; | ||
487 | }; | 502 | }; |
488 | return gss_msg; | 503 | return gss_msg; |
504 | err_free_msg: | ||
505 | kfree(gss_msg); | ||
506 | err: | ||
507 | return ERR_PTR(err); | ||
489 | } | 508 | } |
490 | 509 | ||
491 | static struct gss_upcall_msg * | 510 | static struct gss_upcall_msg * |
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 77479606a971..dab09dac8fc7 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
@@ -25,12 +25,12 @@ | |||
25 | #include <linux/namei.h> | 25 | #include <linux/namei.h> |
26 | #include <linux/mount.h> | 26 | #include <linux/mount.h> |
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | #include <linux/rcupdate.h> | ||
28 | #include <linux/utsname.h> | 29 | #include <linux/utsname.h> |
29 | #include <linux/workqueue.h> | 30 | #include <linux/workqueue.h> |
30 | #include <linux/in.h> | 31 | #include <linux/in.h> |
31 | #include <linux/in6.h> | 32 | #include <linux/in6.h> |
32 | #include <linux/un.h> | 33 | #include <linux/un.h> |
33 | #include <linux/rcupdate.h> | ||
34 | 34 | ||
35 | #include <linux/sunrpc/clnt.h> | 35 | #include <linux/sunrpc/clnt.h> |
36 | #include <linux/sunrpc/addr.h> | 36 | #include <linux/sunrpc/addr.h> |
@@ -264,6 +264,26 @@ void rpc_clients_notifier_unregister(void) | |||
264 | return rpc_pipefs_notifier_unregister(&rpc_clients_block); | 264 | return rpc_pipefs_notifier_unregister(&rpc_clients_block); |
265 | } | 265 | } |
266 | 266 | ||
267 | static struct rpc_xprt *rpc_clnt_set_transport(struct rpc_clnt *clnt, | ||
268 | struct rpc_xprt *xprt, | ||
269 | const struct rpc_timeout *timeout) | ||
270 | { | ||
271 | struct rpc_xprt *old; | ||
272 | |||
273 | spin_lock(&clnt->cl_lock); | ||
274 | old = rcu_dereference_protected(clnt->cl_xprt, | ||
275 | lockdep_is_held(&clnt->cl_lock)); | ||
276 | |||
277 | if (!xprt_bound(xprt)) | ||
278 | clnt->cl_autobind = 1; | ||
279 | |||
280 | clnt->cl_timeout = timeout; | ||
281 | rcu_assign_pointer(clnt->cl_xprt, xprt); | ||
282 | spin_unlock(&clnt->cl_lock); | ||
283 | |||
284 | return old; | ||
285 | } | ||
286 | |||
267 | static void rpc_clnt_set_nodename(struct rpc_clnt *clnt, const char *nodename) | 287 | static void rpc_clnt_set_nodename(struct rpc_clnt *clnt, const char *nodename) |
268 | { | 288 | { |
269 | clnt->cl_nodelen = strlen(nodename); | 289 | clnt->cl_nodelen = strlen(nodename); |
@@ -272,12 +292,13 @@ static void rpc_clnt_set_nodename(struct rpc_clnt *clnt, const char *nodename) | |||
272 | memcpy(clnt->cl_nodename, nodename, clnt->cl_nodelen); | 292 | memcpy(clnt->cl_nodename, nodename, clnt->cl_nodelen); |
273 | } | 293 | } |
274 | 294 | ||
275 | static int rpc_client_register(const struct rpc_create_args *args, | 295 | static int rpc_client_register(struct rpc_clnt *clnt, |
276 | struct rpc_clnt *clnt) | 296 | rpc_authflavor_t pseudoflavor, |
297 | const char *client_name) | ||
277 | { | 298 | { |
278 | struct rpc_auth_create_args auth_args = { | 299 | struct rpc_auth_create_args auth_args = { |
279 | .pseudoflavor = args->authflavor, | 300 | .pseudoflavor = pseudoflavor, |
280 | .target_name = args->client_name, | 301 | .target_name = client_name, |
281 | }; | 302 | }; |
282 | struct rpc_auth *auth; | 303 | struct rpc_auth *auth; |
283 | struct net *net = rpc_net_ns(clnt); | 304 | struct net *net = rpc_net_ns(clnt); |
@@ -298,7 +319,7 @@ static int rpc_client_register(const struct rpc_create_args *args, | |||
298 | auth = rpcauth_create(&auth_args, clnt); | 319 | auth = rpcauth_create(&auth_args, clnt); |
299 | if (IS_ERR(auth)) { | 320 | if (IS_ERR(auth)) { |
300 | dprintk("RPC: Couldn't create auth handle (flavor %u)\n", | 321 | dprintk("RPC: Couldn't create auth handle (flavor %u)\n", |
301 | args->authflavor); | 322 | pseudoflavor); |
302 | err = PTR_ERR(auth); | 323 | err = PTR_ERR(auth); |
303 | goto err_auth; | 324 | goto err_auth; |
304 | } | 325 | } |
@@ -337,7 +358,8 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, | |||
337 | { | 358 | { |
338 | const struct rpc_program *program = args->program; | 359 | const struct rpc_program *program = args->program; |
339 | const struct rpc_version *version; | 360 | const struct rpc_version *version; |
340 | struct rpc_clnt *clnt = NULL; | 361 | struct rpc_clnt *clnt = NULL; |
362 | const struct rpc_timeout *timeout; | ||
341 | int err; | 363 | int err; |
342 | 364 | ||
343 | /* sanity check the name before trying to print it */ | 365 | /* sanity check the name before trying to print it */ |
@@ -365,7 +387,6 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, | |||
365 | if (err) | 387 | if (err) |
366 | goto out_no_clid; | 388 | goto out_no_clid; |
367 | 389 | ||
368 | rcu_assign_pointer(clnt->cl_xprt, xprt); | ||
369 | clnt->cl_procinfo = version->procs; | 390 | clnt->cl_procinfo = version->procs; |
370 | clnt->cl_maxproc = version->nrprocs; | 391 | clnt->cl_maxproc = version->nrprocs; |
371 | clnt->cl_prog = args->prognumber ? : program->number; | 392 | clnt->cl_prog = args->prognumber ? : program->number; |
@@ -380,16 +401,15 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, | |||
380 | INIT_LIST_HEAD(&clnt->cl_tasks); | 401 | INIT_LIST_HEAD(&clnt->cl_tasks); |
381 | spin_lock_init(&clnt->cl_lock); | 402 | spin_lock_init(&clnt->cl_lock); |
382 | 403 | ||
383 | if (!xprt_bound(xprt)) | 404 | timeout = xprt->timeout; |
384 | clnt->cl_autobind = 1; | ||
385 | |||
386 | clnt->cl_timeout = xprt->timeout; | ||
387 | if (args->timeout != NULL) { | 405 | if (args->timeout != NULL) { |
388 | memcpy(&clnt->cl_timeout_default, args->timeout, | 406 | memcpy(&clnt->cl_timeout_default, args->timeout, |
389 | sizeof(clnt->cl_timeout_default)); | 407 | sizeof(clnt->cl_timeout_default)); |
390 | clnt->cl_timeout = &clnt->cl_timeout_default; | 408 | timeout = &clnt->cl_timeout_default; |
391 | } | 409 | } |
392 | 410 | ||
411 | rpc_clnt_set_transport(clnt, xprt, timeout); | ||
412 | |||
393 | clnt->cl_rtt = &clnt->cl_rtt_default; | 413 | clnt->cl_rtt = &clnt->cl_rtt_default; |
394 | rpc_init_rtt(&clnt->cl_rtt_default, clnt->cl_timeout->to_initval); | 414 | rpc_init_rtt(&clnt->cl_rtt_default, clnt->cl_timeout->to_initval); |
395 | 415 | ||
@@ -398,7 +418,7 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, | |||
398 | /* save the nodename */ | 418 | /* save the nodename */ |
399 | rpc_clnt_set_nodename(clnt, utsname()->nodename); | 419 | rpc_clnt_set_nodename(clnt, utsname()->nodename); |
400 | 420 | ||
401 | err = rpc_client_register(args, clnt); | 421 | err = rpc_client_register(clnt, args->authflavor, args->client_name); |
402 | if (err) | 422 | if (err) |
403 | goto out_no_path; | 423 | goto out_no_path; |
404 | if (parent) | 424 | if (parent) |
@@ -600,6 +620,80 @@ rpc_clone_client_set_auth(struct rpc_clnt *clnt, rpc_authflavor_t flavor) | |||
600 | } | 620 | } |
601 | EXPORT_SYMBOL_GPL(rpc_clone_client_set_auth); | 621 | EXPORT_SYMBOL_GPL(rpc_clone_client_set_auth); |
602 | 622 | ||
623 | /** | ||
624 | * rpc_switch_client_transport: switch the RPC transport on the fly | ||
625 | * @clnt: pointer to a struct rpc_clnt | ||
626 | * @args: pointer to the new transport arguments | ||
627 | * @timeout: pointer to the new timeout parameters | ||
628 | * | ||
629 | * This function allows the caller to switch the RPC transport for the | ||
630 | * rpc_clnt structure 'clnt' to allow it to connect to a mirrored NFS | ||
631 | * server, for instance. It assumes that the caller has ensured that | ||
632 | * there are no active RPC tasks by using some form of locking. | ||
633 | * | ||
634 | * Returns zero if "clnt" is now using the new xprt. Otherwise a | ||
635 | * negative errno is returned, and "clnt" continues to use the old | ||
636 | * xprt. | ||
637 | */ | ||
638 | int rpc_switch_client_transport(struct rpc_clnt *clnt, | ||
639 | struct xprt_create *args, | ||
640 | const struct rpc_timeout *timeout) | ||
641 | { | ||
642 | const struct rpc_timeout *old_timeo; | ||
643 | rpc_authflavor_t pseudoflavor; | ||
644 | struct rpc_xprt *xprt, *old; | ||
645 | struct rpc_clnt *parent; | ||
646 | int err; | ||
647 | |||
648 | xprt = xprt_create_transport(args); | ||
649 | if (IS_ERR(xprt)) { | ||
650 | dprintk("RPC: failed to create new xprt for clnt %p\n", | ||
651 | clnt); | ||
652 | return PTR_ERR(xprt); | ||
653 | } | ||
654 | |||
655 | pseudoflavor = clnt->cl_auth->au_flavor; | ||
656 | |||
657 | old_timeo = clnt->cl_timeout; | ||
658 | old = rpc_clnt_set_transport(clnt, xprt, timeout); | ||
659 | |||
660 | rpc_unregister_client(clnt); | ||
661 | __rpc_clnt_remove_pipedir(clnt); | ||
662 | |||
663 | /* | ||
664 | * A new transport was created. "clnt" therefore | ||
665 | * becomes the root of a new cl_parent tree. clnt's | ||
666 | * children, if it has any, still point to the old xprt. | ||
667 | */ | ||
668 | parent = clnt->cl_parent; | ||
669 | clnt->cl_parent = clnt; | ||
670 | |||
671 | /* | ||
672 | * The old rpc_auth cache cannot be re-used. GSS | ||
673 | * contexts in particular are between a single | ||
674 | * client and server. | ||
675 | */ | ||
676 | err = rpc_client_register(clnt, pseudoflavor, NULL); | ||
677 | if (err) | ||
678 | goto out_revert; | ||
679 | |||
680 | synchronize_rcu(); | ||
681 | if (parent != clnt) | ||
682 | rpc_release_client(parent); | ||
683 | xprt_put(old); | ||
684 | dprintk("RPC: replaced xprt for clnt %p\n", clnt); | ||
685 | return 0; | ||
686 | |||
687 | out_revert: | ||
688 | rpc_clnt_set_transport(clnt, old, old_timeo); | ||
689 | clnt->cl_parent = parent; | ||
690 | rpc_client_register(clnt, pseudoflavor, NULL); | ||
691 | xprt_put(xprt); | ||
692 | dprintk("RPC: failed to switch xprt for clnt %p\n", clnt); | ||
693 | return err; | ||
694 | } | ||
695 | EXPORT_SYMBOL_GPL(rpc_switch_client_transport); | ||
696 | |||
603 | /* | 697 | /* |
604 | * Kill all tasks for the given client. | 698 | * Kill all tasks for the given client. |
605 | * XXX: kill their descendants as well? | 699 | * XXX: kill their descendants as well? |
@@ -772,6 +866,8 @@ void rpc_task_set_client(struct rpc_task *task, struct rpc_clnt *clnt) | |||
772 | atomic_inc(&clnt->cl_count); | 866 | atomic_inc(&clnt->cl_count); |
773 | if (clnt->cl_softrtry) | 867 | if (clnt->cl_softrtry) |
774 | task->tk_flags |= RPC_TASK_SOFT; | 868 | task->tk_flags |= RPC_TASK_SOFT; |
869 | if (clnt->cl_noretranstimeo) | ||
870 | task->tk_flags |= RPC_TASK_NO_RETRANS_TIMEOUT; | ||
775 | if (sk_memalloc_socks()) { | 871 | if (sk_memalloc_socks()) { |
776 | struct rpc_xprt *xprt; | 872 | struct rpc_xprt *xprt; |
777 | 873 | ||
@@ -1690,6 +1786,7 @@ call_connect_status(struct rpc_task *task) | |||
1690 | dprint_status(task); | 1786 | dprint_status(task); |
1691 | 1787 | ||
1692 | trace_rpc_connect_status(task, status); | 1788 | trace_rpc_connect_status(task, status); |
1789 | task->tk_status = 0; | ||
1693 | switch (status) { | 1790 | switch (status) { |
1694 | /* if soft mounted, test if we've timed out */ | 1791 | /* if soft mounted, test if we've timed out */ |
1695 | case -ETIMEDOUT: | 1792 | case -ETIMEDOUT: |
@@ -1698,12 +1795,14 @@ call_connect_status(struct rpc_task *task) | |||
1698 | case -ECONNREFUSED: | 1795 | case -ECONNREFUSED: |
1699 | case -ECONNRESET: | 1796 | case -ECONNRESET: |
1700 | case -ENETUNREACH: | 1797 | case -ENETUNREACH: |
1798 | /* retry with existing socket, after a delay */ | ||
1799 | rpc_delay(task, 3*HZ); | ||
1701 | if (RPC_IS_SOFTCONN(task)) | 1800 | if (RPC_IS_SOFTCONN(task)) |
1702 | break; | 1801 | break; |
1703 | /* retry with existing socket, after a delay */ | ||
1704 | case 0: | ||
1705 | case -EAGAIN: | 1802 | case -EAGAIN: |
1706 | task->tk_status = 0; | 1803 | task->tk_action = call_bind; |
1804 | return; | ||
1805 | case 0: | ||
1707 | clnt->cl_stats->netreconn++; | 1806 | clnt->cl_stats->netreconn++; |
1708 | task->tk_action = call_transmit; | 1807 | task->tk_action = call_transmit; |
1709 | return; | 1808 | return; |
@@ -1717,13 +1816,14 @@ call_connect_status(struct rpc_task *task) | |||
1717 | static void | 1816 | static void |
1718 | call_transmit(struct rpc_task *task) | 1817 | call_transmit(struct rpc_task *task) |
1719 | { | 1818 | { |
1819 | int is_retrans = RPC_WAS_SENT(task); | ||
1820 | |||
1720 | dprint_status(task); | 1821 | dprint_status(task); |
1721 | 1822 | ||
1722 | task->tk_action = call_status; | 1823 | task->tk_action = call_status; |
1723 | if (task->tk_status < 0) | 1824 | if (task->tk_status < 0) |
1724 | return; | 1825 | return; |
1725 | task->tk_status = xprt_prepare_transmit(task); | 1826 | if (!xprt_prepare_transmit(task)) |
1726 | if (task->tk_status != 0) | ||
1727 | return; | 1827 | return; |
1728 | task->tk_action = call_transmit_status; | 1828 | task->tk_action = call_transmit_status; |
1729 | /* Encode here so that rpcsec_gss can use correct sequence number. */ | 1829 | /* Encode here so that rpcsec_gss can use correct sequence number. */ |
@@ -1742,6 +1842,8 @@ call_transmit(struct rpc_task *task) | |||
1742 | xprt_transmit(task); | 1842 | xprt_transmit(task); |
1743 | if (task->tk_status < 0) | 1843 | if (task->tk_status < 0) |
1744 | return; | 1844 | return; |
1845 | if (is_retrans) | ||
1846 | task->tk_client->cl_stats->rpcretrans++; | ||
1745 | /* | 1847 | /* |
1746 | * On success, ensure that we call xprt_end_transmit() before sleeping | 1848 | * On success, ensure that we call xprt_end_transmit() before sleeping |
1747 | * in order to allow access to the socket to other RPC requests. | 1849 | * in order to allow access to the socket to other RPC requests. |
@@ -1811,8 +1913,7 @@ call_bc_transmit(struct rpc_task *task) | |||
1811 | { | 1913 | { |
1812 | struct rpc_rqst *req = task->tk_rqstp; | 1914 | struct rpc_rqst *req = task->tk_rqstp; |
1813 | 1915 | ||
1814 | task->tk_status = xprt_prepare_transmit(task); | 1916 | if (!xprt_prepare_transmit(task)) { |
1815 | if (task->tk_status == -EAGAIN) { | ||
1816 | /* | 1917 | /* |
1817 | * Could not reserve the transport. Try again after the | 1918 | * Could not reserve the transport. Try again after the |
1818 | * transport is released. | 1919 | * transport is released. |
@@ -1900,7 +2001,8 @@ call_status(struct rpc_task *task) | |||
1900 | rpc_delay(task, 3*HZ); | 2001 | rpc_delay(task, 3*HZ); |
1901 | case -ETIMEDOUT: | 2002 | case -ETIMEDOUT: |
1902 | task->tk_action = call_timeout; | 2003 | task->tk_action = call_timeout; |
1903 | if (task->tk_client->cl_discrtry) | 2004 | if (!(task->tk_flags & RPC_TASK_NO_RETRANS_TIMEOUT) |
2005 | && task->tk_client->cl_discrtry) | ||
1904 | xprt_conditional_disconnect(req->rq_xprt, | 2006 | xprt_conditional_disconnect(req->rq_xprt, |
1905 | req->rq_connect_cookie); | 2007 | req->rq_connect_cookie); |
1906 | break; | 2008 | break; |
@@ -1982,7 +2084,6 @@ call_timeout(struct rpc_task *task) | |||
1982 | rpcauth_invalcred(task); | 2084 | rpcauth_invalcred(task); |
1983 | 2085 | ||
1984 | retry: | 2086 | retry: |
1985 | clnt->cl_stats->rpcretrans++; | ||
1986 | task->tk_action = call_bind; | 2087 | task->tk_action = call_bind; |
1987 | task->tk_status = 0; | 2088 | task->tk_status = 0; |
1988 | } | 2089 | } |
@@ -2025,7 +2126,6 @@ call_decode(struct rpc_task *task) | |||
2025 | if (req->rq_rcv_buf.len < 12) { | 2126 | if (req->rq_rcv_buf.len < 12) { |
2026 | if (!RPC_IS_SOFT(task)) { | 2127 | if (!RPC_IS_SOFT(task)) { |
2027 | task->tk_action = call_bind; | 2128 | task->tk_action = call_bind; |
2028 | clnt->cl_stats->rpcretrans++; | ||
2029 | goto out_retry; | 2129 | goto out_retry; |
2030 | } | 2130 | } |
2031 | dprintk("RPC: %s: too small RPC reply size (%d bytes)\n", | 2131 | dprintk("RPC: %s: too small RPC reply size (%d bytes)\n", |
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index 095363eee764..04199bc8416f 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c | |||
@@ -205,10 +205,8 @@ int xprt_reserve_xprt(struct rpc_xprt *xprt, struct rpc_task *task) | |||
205 | goto out_sleep; | 205 | goto out_sleep; |
206 | } | 206 | } |
207 | xprt->snd_task = task; | 207 | xprt->snd_task = task; |
208 | if (req != NULL) { | 208 | if (req != NULL) |
209 | req->rq_bytes_sent = 0; | ||
210 | req->rq_ntrans++; | 209 | req->rq_ntrans++; |
211 | } | ||
212 | 210 | ||
213 | return 1; | 211 | return 1; |
214 | 212 | ||
@@ -263,7 +261,6 @@ int xprt_reserve_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task) | |||
263 | } | 261 | } |
264 | if (__xprt_get_cong(xprt, task)) { | 262 | if (__xprt_get_cong(xprt, task)) { |
265 | xprt->snd_task = task; | 263 | xprt->snd_task = task; |
266 | req->rq_bytes_sent = 0; | ||
267 | req->rq_ntrans++; | 264 | req->rq_ntrans++; |
268 | return 1; | 265 | return 1; |
269 | } | 266 | } |
@@ -300,10 +297,8 @@ static bool __xprt_lock_write_func(struct rpc_task *task, void *data) | |||
300 | 297 | ||
301 | req = task->tk_rqstp; | 298 | req = task->tk_rqstp; |
302 | xprt->snd_task = task; | 299 | xprt->snd_task = task; |
303 | if (req) { | 300 | if (req) |
304 | req->rq_bytes_sent = 0; | ||
305 | req->rq_ntrans++; | 301 | req->rq_ntrans++; |
306 | } | ||
307 | return true; | 302 | return true; |
308 | } | 303 | } |
309 | 304 | ||
@@ -329,7 +324,6 @@ static bool __xprt_lock_write_cong_func(struct rpc_task *task, void *data) | |||
329 | } | 324 | } |
330 | if (__xprt_get_cong(xprt, task)) { | 325 | if (__xprt_get_cong(xprt, task)) { |
331 | xprt->snd_task = task; | 326 | xprt->snd_task = task; |
332 | req->rq_bytes_sent = 0; | ||
333 | req->rq_ntrans++; | 327 | req->rq_ntrans++; |
334 | return true; | 328 | return true; |
335 | } | 329 | } |
@@ -358,6 +352,11 @@ out_unlock: | |||
358 | void xprt_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task) | 352 | void xprt_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task) |
359 | { | 353 | { |
360 | if (xprt->snd_task == task) { | 354 | if (xprt->snd_task == task) { |
355 | if (task != NULL) { | ||
356 | struct rpc_rqst *req = task->tk_rqstp; | ||
357 | if (req != NULL) | ||
358 | req->rq_bytes_sent = 0; | ||
359 | } | ||
361 | xprt_clear_locked(xprt); | 360 | xprt_clear_locked(xprt); |
362 | __xprt_lock_write_next(xprt); | 361 | __xprt_lock_write_next(xprt); |
363 | } | 362 | } |
@@ -375,6 +374,11 @@ EXPORT_SYMBOL_GPL(xprt_release_xprt); | |||
375 | void xprt_release_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task) | 374 | void xprt_release_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task) |
376 | { | 375 | { |
377 | if (xprt->snd_task == task) { | 376 | if (xprt->snd_task == task) { |
377 | if (task != NULL) { | ||
378 | struct rpc_rqst *req = task->tk_rqstp; | ||
379 | if (req != NULL) | ||
380 | req->rq_bytes_sent = 0; | ||
381 | } | ||
378 | xprt_clear_locked(xprt); | 382 | xprt_clear_locked(xprt); |
379 | __xprt_lock_write_next_cong(xprt); | 383 | __xprt_lock_write_next_cong(xprt); |
380 | } | 384 | } |
@@ -854,24 +858,36 @@ static inline int xprt_has_timer(struct rpc_xprt *xprt) | |||
854 | * @task: RPC task about to send a request | 858 | * @task: RPC task about to send a request |
855 | * | 859 | * |
856 | */ | 860 | */ |
857 | int xprt_prepare_transmit(struct rpc_task *task) | 861 | bool xprt_prepare_transmit(struct rpc_task *task) |
858 | { | 862 | { |
859 | struct rpc_rqst *req = task->tk_rqstp; | 863 | struct rpc_rqst *req = task->tk_rqstp; |
860 | struct rpc_xprt *xprt = req->rq_xprt; | 864 | struct rpc_xprt *xprt = req->rq_xprt; |
861 | int err = 0; | 865 | bool ret = false; |
862 | 866 | ||
863 | dprintk("RPC: %5u xprt_prepare_transmit\n", task->tk_pid); | 867 | dprintk("RPC: %5u xprt_prepare_transmit\n", task->tk_pid); |
864 | 868 | ||
865 | spin_lock_bh(&xprt->transport_lock); | 869 | spin_lock_bh(&xprt->transport_lock); |
866 | if (req->rq_reply_bytes_recvd && !req->rq_bytes_sent) { | 870 | if (!req->rq_bytes_sent) { |
867 | err = req->rq_reply_bytes_recvd; | 871 | if (req->rq_reply_bytes_recvd) { |
872 | task->tk_status = req->rq_reply_bytes_recvd; | ||
873 | goto out_unlock; | ||
874 | } | ||
875 | if ((task->tk_flags & RPC_TASK_NO_RETRANS_TIMEOUT) | ||
876 | && xprt_connected(xprt) | ||
877 | && req->rq_connect_cookie == xprt->connect_cookie) { | ||
878 | xprt->ops->set_retrans_timeout(task); | ||
879 | rpc_sleep_on(&xprt->pending, task, xprt_timer); | ||
880 | goto out_unlock; | ||
881 | } | ||
882 | } | ||
883 | if (!xprt->ops->reserve_xprt(xprt, task)) { | ||
884 | task->tk_status = -EAGAIN; | ||
868 | goto out_unlock; | 885 | goto out_unlock; |
869 | } | 886 | } |
870 | if (!xprt->ops->reserve_xprt(xprt, task)) | 887 | ret = true; |
871 | err = -EAGAIN; | ||
872 | out_unlock: | 888 | out_unlock: |
873 | spin_unlock_bh(&xprt->transport_lock); | 889 | spin_unlock_bh(&xprt->transport_lock); |
874 | return err; | 890 | return ret; |
875 | } | 891 | } |
876 | 892 | ||
877 | void xprt_end_transmit(struct rpc_task *task) | 893 | void xprt_end_transmit(struct rpc_task *task) |
@@ -912,7 +928,6 @@ void xprt_transmit(struct rpc_task *task) | |||
912 | } else if (!req->rq_bytes_sent) | 928 | } else if (!req->rq_bytes_sent) |
913 | return; | 929 | return; |
914 | 930 | ||
915 | req->rq_connect_cookie = xprt->connect_cookie; | ||
916 | req->rq_xtime = ktime_get(); | 931 | req->rq_xtime = ktime_get(); |
917 | status = xprt->ops->send_request(task); | 932 | status = xprt->ops->send_request(task); |
918 | if (status != 0) { | 933 | if (status != 0) { |
@@ -938,12 +953,14 @@ void xprt_transmit(struct rpc_task *task) | |||
938 | /* Don't race with disconnect */ | 953 | /* Don't race with disconnect */ |
939 | if (!xprt_connected(xprt)) | 954 | if (!xprt_connected(xprt)) |
940 | task->tk_status = -ENOTCONN; | 955 | task->tk_status = -ENOTCONN; |
941 | else if (!req->rq_reply_bytes_recvd && rpc_reply_expected(task)) { | 956 | else { |
942 | /* | 957 | /* |
943 | * Sleep on the pending queue since | 958 | * Sleep on the pending queue since |
944 | * we're expecting a reply. | 959 | * we're expecting a reply. |
945 | */ | 960 | */ |
946 | rpc_sleep_on(&xprt->pending, task, xprt_timer); | 961 | if (!req->rq_reply_bytes_recvd && rpc_reply_expected(task)) |
962 | rpc_sleep_on(&xprt->pending, task, xprt_timer); | ||
963 | req->rq_connect_cookie = xprt->connect_cookie; | ||
947 | } | 964 | } |
948 | spin_unlock_bh(&xprt->transport_lock); | 965 | spin_unlock_bh(&xprt->transport_lock); |
949 | } | 966 | } |
@@ -1087,11 +1104,9 @@ struct rpc_xprt *xprt_alloc(struct net *net, size_t size, | |||
1087 | for (i = 0; i < num_prealloc; i++) { | 1104 | for (i = 0; i < num_prealloc; i++) { |
1088 | req = kzalloc(sizeof(struct rpc_rqst), GFP_KERNEL); | 1105 | req = kzalloc(sizeof(struct rpc_rqst), GFP_KERNEL); |
1089 | if (!req) | 1106 | if (!req) |
1090 | break; | 1107 | goto out_free; |
1091 | list_add(&req->rq_list, &xprt->free); | 1108 | list_add(&req->rq_list, &xprt->free); |
1092 | } | 1109 | } |
1093 | if (i < num_prealloc) | ||
1094 | goto out_free; | ||
1095 | if (max_alloc > num_prealloc) | 1110 | if (max_alloc > num_prealloc) |
1096 | xprt->max_reqs = max_alloc; | 1111 | xprt->max_reqs = max_alloc; |
1097 | else | 1112 | else |
@@ -1186,6 +1201,12 @@ static void xprt_request_init(struct rpc_task *task, struct rpc_xprt *xprt) | |||
1186 | req->rq_xprt = xprt; | 1201 | req->rq_xprt = xprt; |
1187 | req->rq_buffer = NULL; | 1202 | req->rq_buffer = NULL; |
1188 | req->rq_xid = xprt_alloc_xid(xprt); | 1203 | req->rq_xid = xprt_alloc_xid(xprt); |
1204 | req->rq_connect_cookie = xprt->connect_cookie - 1; | ||
1205 | req->rq_bytes_sent = 0; | ||
1206 | req->rq_snd_buf.len = 0; | ||
1207 | req->rq_snd_buf.buflen = 0; | ||
1208 | req->rq_rcv_buf.len = 0; | ||
1209 | req->rq_rcv_buf.buflen = 0; | ||
1189 | req->rq_release_snd_buf = NULL; | 1210 | req->rq_release_snd_buf = NULL; |
1190 | xprt_reset_majortimeo(req); | 1211 | xprt_reset_majortimeo(req); |
1191 | dprintk("RPC: %5u reserved req %p xid %08x\n", task->tk_pid, | 1212 | dprintk("RPC: %5u reserved req %p xid %08x\n", task->tk_pid, |
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index ee03d35677d9..17c88928b7db 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
@@ -835,6 +835,8 @@ static void xs_close(struct rpc_xprt *xprt) | |||
835 | 835 | ||
836 | dprintk("RPC: xs_close xprt %p\n", xprt); | 836 | dprintk("RPC: xs_close xprt %p\n", xprt); |
837 | 837 | ||
838 | cancel_delayed_work_sync(&transport->connect_worker); | ||
839 | |||
838 | xs_reset_transport(transport); | 840 | xs_reset_transport(transport); |
839 | xprt->reestablish_timeout = 0; | 841 | xprt->reestablish_timeout = 0; |
840 | 842 | ||
@@ -854,14 +856,6 @@ static void xs_tcp_close(struct rpc_xprt *xprt) | |||
854 | xs_tcp_shutdown(xprt); | 856 | xs_tcp_shutdown(xprt); |
855 | } | 857 | } |
856 | 858 | ||
857 | static void xs_local_destroy(struct rpc_xprt *xprt) | ||
858 | { | ||
859 | xs_close(xprt); | ||
860 | xs_free_peer_addresses(xprt); | ||
861 | xprt_free(xprt); | ||
862 | module_put(THIS_MODULE); | ||
863 | } | ||
864 | |||
865 | /** | 859 | /** |
866 | * xs_destroy - prepare to shutdown a transport | 860 | * xs_destroy - prepare to shutdown a transport |
867 | * @xprt: doomed transport | 861 | * @xprt: doomed transport |
@@ -869,13 +863,12 @@ static void xs_local_destroy(struct rpc_xprt *xprt) | |||
869 | */ | 863 | */ |
870 | static void xs_destroy(struct rpc_xprt *xprt) | 864 | static void xs_destroy(struct rpc_xprt *xprt) |
871 | { | 865 | { |
872 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); | ||
873 | |||
874 | dprintk("RPC: xs_destroy xprt %p\n", xprt); | 866 | dprintk("RPC: xs_destroy xprt %p\n", xprt); |
875 | 867 | ||
876 | cancel_delayed_work_sync(&transport->connect_worker); | 868 | xs_close(xprt); |
877 | 869 | xs_free_peer_addresses(xprt); | |
878 | xs_local_destroy(xprt); | 870 | xprt_free(xprt); |
871 | module_put(THIS_MODULE); | ||
879 | } | 872 | } |
880 | 873 | ||
881 | static inline struct rpc_xprt *xprt_from_sock(struct sock *sk) | 874 | static inline struct rpc_xprt *xprt_from_sock(struct sock *sk) |
@@ -1511,6 +1504,7 @@ static void xs_tcp_state_change(struct sock *sk) | |||
1511 | transport->tcp_copied = 0; | 1504 | transport->tcp_copied = 0; |
1512 | transport->tcp_flags = | 1505 | transport->tcp_flags = |
1513 | TCP_RCV_COPY_FRAGHDR | TCP_RCV_COPY_XID; | 1506 | TCP_RCV_COPY_FRAGHDR | TCP_RCV_COPY_XID; |
1507 | xprt->connect_cookie++; | ||
1514 | 1508 | ||
1515 | xprt_wake_pending_tasks(xprt, -EAGAIN); | 1509 | xprt_wake_pending_tasks(xprt, -EAGAIN); |
1516 | } | 1510 | } |
@@ -1816,6 +1810,10 @@ static inline void xs_reclassify_socket(int family, struct socket *sock) | |||
1816 | } | 1810 | } |
1817 | #endif | 1811 | #endif |
1818 | 1812 | ||
1813 | static void xs_dummy_setup_socket(struct work_struct *work) | ||
1814 | { | ||
1815 | } | ||
1816 | |||
1819 | static struct socket *xs_create_sock(struct rpc_xprt *xprt, | 1817 | static struct socket *xs_create_sock(struct rpc_xprt *xprt, |
1820 | struct sock_xprt *transport, int family, int type, int protocol) | 1818 | struct sock_xprt *transport, int family, int type, int protocol) |
1821 | { | 1819 | { |
@@ -2112,6 +2110,19 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) | |||
2112 | 2110 | ||
2113 | if (!transport->inet) { | 2111 | if (!transport->inet) { |
2114 | struct sock *sk = sock->sk; | 2112 | struct sock *sk = sock->sk; |
2113 | unsigned int keepidle = xprt->timeout->to_initval / HZ; | ||
2114 | unsigned int keepcnt = xprt->timeout->to_retries + 1; | ||
2115 | unsigned int opt_on = 1; | ||
2116 | |||
2117 | /* TCP Keepalive options */ | ||
2118 | kernel_setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, | ||
2119 | (char *)&opt_on, sizeof(opt_on)); | ||
2120 | kernel_setsockopt(sock, SOL_TCP, TCP_KEEPIDLE, | ||
2121 | (char *)&keepidle, sizeof(keepidle)); | ||
2122 | kernel_setsockopt(sock, SOL_TCP, TCP_KEEPINTVL, | ||
2123 | (char *)&keepidle, sizeof(keepidle)); | ||
2124 | kernel_setsockopt(sock, SOL_TCP, TCP_KEEPCNT, | ||
2125 | (char *)&keepcnt, sizeof(keepcnt)); | ||
2115 | 2126 | ||
2116 | write_lock_bh(&sk->sk_callback_lock); | 2127 | write_lock_bh(&sk->sk_callback_lock); |
2117 | 2128 | ||
@@ -2151,7 +2162,6 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) | |||
2151 | case 0: | 2162 | case 0: |
2152 | case -EINPROGRESS: | 2163 | case -EINPROGRESS: |
2153 | /* SYN_SENT! */ | 2164 | /* SYN_SENT! */ |
2154 | xprt->connect_cookie++; | ||
2155 | if (xprt->reestablish_timeout < XS_TCP_INIT_REEST_TO) | 2165 | if (xprt->reestablish_timeout < XS_TCP_INIT_REEST_TO) |
2156 | xprt->reestablish_timeout = XS_TCP_INIT_REEST_TO; | 2166 | xprt->reestablish_timeout = XS_TCP_INIT_REEST_TO; |
2157 | } | 2167 | } |
@@ -2498,7 +2508,7 @@ static struct rpc_xprt_ops xs_local_ops = { | |||
2498 | .send_request = xs_local_send_request, | 2508 | .send_request = xs_local_send_request, |
2499 | .set_retrans_timeout = xprt_set_retrans_timeout_def, | 2509 | .set_retrans_timeout = xprt_set_retrans_timeout_def, |
2500 | .close = xs_close, | 2510 | .close = xs_close, |
2501 | .destroy = xs_local_destroy, | 2511 | .destroy = xs_destroy, |
2502 | .print_stats = xs_local_print_stats, | 2512 | .print_stats = xs_local_print_stats, |
2503 | }; | 2513 | }; |
2504 | 2514 | ||
@@ -2655,6 +2665,9 @@ static struct rpc_xprt *xs_setup_local(struct xprt_create *args) | |||
2655 | xprt->ops = &xs_local_ops; | 2665 | xprt->ops = &xs_local_ops; |
2656 | xprt->timeout = &xs_local_default_timeout; | 2666 | xprt->timeout = &xs_local_default_timeout; |
2657 | 2667 | ||
2668 | INIT_DELAYED_WORK(&transport->connect_worker, | ||
2669 | xs_dummy_setup_socket); | ||
2670 | |||
2658 | switch (sun->sun_family) { | 2671 | switch (sun->sun_family) { |
2659 | case AF_LOCAL: | 2672 | case AF_LOCAL: |
2660 | if (sun->sun_path[0] != '/') { | 2673 | if (sun->sun_path[0] != '/') { |
@@ -2859,8 +2872,8 @@ static struct rpc_xprt *xs_setup_bc_tcp(struct xprt_create *args) | |||
2859 | if (args->bc_xprt->xpt_bc_xprt) { | 2872 | if (args->bc_xprt->xpt_bc_xprt) { |
2860 | /* | 2873 | /* |
2861 | * This server connection already has a backchannel | 2874 | * This server connection already has a backchannel |
2862 | * export; we can't create a new one, as we wouldn't be | 2875 | * transport; we can't create a new one, as we wouldn't |
2863 | * able to match replies based on xid any more. So, | 2876 | * be able to match replies based on xid any more. So, |
2864 | * reuse the already-existing one: | 2877 | * reuse the already-existing one: |
2865 | */ | 2878 | */ |
2866 | return args->bc_xprt->xpt_bc_xprt; | 2879 | return args->bc_xprt->xpt_bc_xprt; |
diff --git a/net/x25/Kconfig b/net/x25/Kconfig index c959312c45e3..e2fa133f9fba 100644 --- a/net/x25/Kconfig +++ b/net/x25/Kconfig | |||
@@ -16,8 +16,8 @@ config X25 | |||
16 | if you want that) and the lower level data link layer protocol LAPB | 16 | if you want that) and the lower level data link layer protocol LAPB |
17 | (say Y to "LAPB Data Link Driver" below if you want that). | 17 | (say Y to "LAPB Data Link Driver" below if you want that). |
18 | 18 | ||
19 | You can read more about X.25 at <http://www.sangoma.com/x25.htm> and | 19 | You can read more about X.25 at <http://www.sangoma.com/tutorials/x25/> and |
20 | <http://www.cisco.com/univercd/cc/td/doc/product/software/ios11/cbook/cx25.htm>. | 20 | <http://docwiki.cisco.com/wiki/X.25>. |
21 | Information about X.25 for Linux is contained in the files | 21 | Information about X.25 for Linux is contained in the files |
22 | <file:Documentation/networking/x25.txt> and | 22 | <file:Documentation/networking/x25.txt> and |
23 | <file:Documentation/networking/x25-iface.txt>. | 23 | <file:Documentation/networking/x25-iface.txt>. |
diff --git a/net/xfrm/xfrm_ipcomp.c b/net/xfrm/xfrm_ipcomp.c index 2906d520eea7..3be02b680268 100644 --- a/net/xfrm/xfrm_ipcomp.c +++ b/net/xfrm/xfrm_ipcomp.c | |||
@@ -141,14 +141,14 @@ static int ipcomp_compress(struct xfrm_state *x, struct sk_buff *skb) | |||
141 | const int plen = skb->len; | 141 | const int plen = skb->len; |
142 | int dlen = IPCOMP_SCRATCH_SIZE; | 142 | int dlen = IPCOMP_SCRATCH_SIZE; |
143 | u8 *start = skb->data; | 143 | u8 *start = skb->data; |
144 | const int cpu = get_cpu(); | 144 | struct crypto_comp *tfm; |
145 | u8 *scratch = *per_cpu_ptr(ipcomp_scratches, cpu); | 145 | u8 *scratch; |
146 | struct crypto_comp *tfm = *per_cpu_ptr(ipcd->tfms, cpu); | ||
147 | int err; | 146 | int err; |
148 | 147 | ||
149 | local_bh_disable(); | 148 | local_bh_disable(); |
149 | scratch = *this_cpu_ptr(ipcomp_scratches); | ||
150 | tfm = *this_cpu_ptr(ipcd->tfms); | ||
150 | err = crypto_comp_compress(tfm, start, plen, scratch, &dlen); | 151 | err = crypto_comp_compress(tfm, start, plen, scratch, &dlen); |
151 | local_bh_enable(); | ||
152 | if (err) | 152 | if (err) |
153 | goto out; | 153 | goto out; |
154 | 154 | ||
@@ -158,13 +158,13 @@ static int ipcomp_compress(struct xfrm_state *x, struct sk_buff *skb) | |||
158 | } | 158 | } |
159 | 159 | ||
160 | memcpy(start + sizeof(struct ip_comp_hdr), scratch, dlen); | 160 | memcpy(start + sizeof(struct ip_comp_hdr), scratch, dlen); |
161 | put_cpu(); | 161 | local_bh_enable(); |
162 | 162 | ||
163 | pskb_trim(skb, dlen + sizeof(struct ip_comp_hdr)); | 163 | pskb_trim(skb, dlen + sizeof(struct ip_comp_hdr)); |
164 | return 0; | 164 | return 0; |
165 | 165 | ||
166 | out: | 166 | out: |
167 | put_cpu(); | 167 | local_bh_enable(); |
168 | return err; | 168 | return err; |
169 | } | 169 | } |
170 | 170 | ||