diff options
author | John W. Linville <linville@tuxdriver.com> | 2006-08-14 15:33:54 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2006-08-14 15:33:54 -0400 |
commit | e9ffb3d7ec94083a44a8721681391beca2ffd68c (patch) | |
tree | 6768ab487b3f44c2a4995ee61307e47760ca9b88 /net | |
parent | 8b9411014e6f18a883c18b38f41338dbd53fddea (diff) | |
parent | e9fa4f7bd291c29a785666e2fa5a9cf3241ee6c3 (diff) |
Merge branch 'from-linus' into upstream
Diffstat (limited to 'net')
31 files changed, 249 insertions, 119 deletions
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index 06abb6634f5b..53086fb75089 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c | |||
@@ -85,7 +85,7 @@ void br_ifinfo_notify(int event, struct net_bridge_port *port) | |||
85 | goto err_out; | 85 | goto err_out; |
86 | 86 | ||
87 | err = br_fill_ifinfo(skb, port, current->pid, 0, event, 0); | 87 | err = br_fill_ifinfo(skb, port, current->pid, 0, event, 0); |
88 | if (err) | 88 | if (err < 0) |
89 | goto err_kfree; | 89 | goto err_kfree; |
90 | 90 | ||
91 | NETLINK_CB(skb).dst_group = RTNLGRP_LINK; | 91 | NETLINK_CB(skb).dst_group = RTNLGRP_LINK; |
diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c index 02693a230dc1..9f950db3b76f 100644 --- a/net/bridge/netfilter/ebt_ulog.c +++ b/net/bridge/netfilter/ebt_ulog.c | |||
@@ -74,6 +74,9 @@ static void ulog_send(unsigned int nlgroup) | |||
74 | if (timer_pending(&ub->timer)) | 74 | if (timer_pending(&ub->timer)) |
75 | del_timer(&ub->timer); | 75 | del_timer(&ub->timer); |
76 | 76 | ||
77 | if (!ub->skb) | ||
78 | return; | ||
79 | |||
77 | /* last nlmsg needs NLMSG_DONE */ | 80 | /* last nlmsg needs NLMSG_DONE */ |
78 | if (ub->qlen > 1) | 81 | if (ub->qlen > 1) |
79 | ub->lastnlh->nlmsg_type = NLMSG_DONE; | 82 | ub->lastnlh->nlmsg_type = NLMSG_DONE; |
diff --git a/net/core/dst.c b/net/core/dst.c index 470c05bc4cb2..1a5e49da0e77 100644 --- a/net/core/dst.c +++ b/net/core/dst.c | |||
@@ -95,12 +95,11 @@ static void dst_run_gc(unsigned long dummy) | |||
95 | dst_gc_timer_inc = DST_GC_INC; | 95 | dst_gc_timer_inc = DST_GC_INC; |
96 | dst_gc_timer_expires = DST_GC_MIN; | 96 | dst_gc_timer_expires = DST_GC_MIN; |
97 | } | 97 | } |
98 | dst_gc_timer.expires = jiffies + dst_gc_timer_expires; | ||
99 | #if RT_CACHE_DEBUG >= 2 | 98 | #if RT_CACHE_DEBUG >= 2 |
100 | printk("dst_total: %d/%d %ld\n", | 99 | printk("dst_total: %d/%d %ld\n", |
101 | atomic_read(&dst_total), delayed, dst_gc_timer_expires); | 100 | atomic_read(&dst_total), delayed, dst_gc_timer_expires); |
102 | #endif | 101 | #endif |
103 | add_timer(&dst_gc_timer); | 102 | mod_timer(&dst_gc_timer, jiffies + dst_gc_timer_expires); |
104 | 103 | ||
105 | out: | 104 | out: |
106 | spin_unlock(&dst_lock); | 105 | spin_unlock(&dst_lock); |
diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 67ed14ddabd2..6a7320b39ed0 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c | |||
@@ -2149,6 +2149,8 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev, | |||
2149 | skb->mac.raw = ((u8 *) iph) - 14 - pkt_dev->nr_labels*sizeof(u32); | 2149 | skb->mac.raw = ((u8 *) iph) - 14 - pkt_dev->nr_labels*sizeof(u32); |
2150 | skb->dev = odev; | 2150 | skb->dev = odev; |
2151 | skb->pkt_type = PACKET_HOST; | 2151 | skb->pkt_type = PACKET_HOST; |
2152 | skb->nh.iph = iph; | ||
2153 | skb->h.uh = udph; | ||
2152 | 2154 | ||
2153 | if (pkt_dev->nfrags <= 0) | 2155 | if (pkt_dev->nfrags <= 0) |
2154 | pgh = (struct pktgen_hdr *)skb_put(skb, datalen); | 2156 | pgh = (struct pktgen_hdr *)skb_put(skb, datalen); |
@@ -2460,6 +2462,8 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev, | |||
2460 | skb->protocol = protocol; | 2462 | skb->protocol = protocol; |
2461 | skb->dev = odev; | 2463 | skb->dev = odev; |
2462 | skb->pkt_type = PACKET_HOST; | 2464 | skb->pkt_type = PACKET_HOST; |
2465 | skb->nh.ipv6h = iph; | ||
2466 | skb->h.uh = udph; | ||
2463 | 2467 | ||
2464 | if (pkt_dev->nfrags <= 0) | 2468 | if (pkt_dev->nfrags <= 0) |
2465 | pgh = (struct pktgen_hdr *)skb_put(skb, datalen); | 2469 | pgh = (struct pktgen_hdr *)skb_put(skb, datalen); |
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 20e5bb73f147..30cc1ba6ed5c 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -394,6 +394,9 @@ static int do_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
394 | } | 394 | } |
395 | 395 | ||
396 | if (ida[IFLA_ADDRESS - 1]) { | 396 | if (ida[IFLA_ADDRESS - 1]) { |
397 | struct sockaddr *sa; | ||
398 | int len; | ||
399 | |||
397 | if (!dev->set_mac_address) { | 400 | if (!dev->set_mac_address) { |
398 | err = -EOPNOTSUPP; | 401 | err = -EOPNOTSUPP; |
399 | goto out; | 402 | goto out; |
@@ -405,7 +408,17 @@ static int do_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
405 | if (ida[IFLA_ADDRESS - 1]->rta_len != RTA_LENGTH(dev->addr_len)) | 408 | if (ida[IFLA_ADDRESS - 1]->rta_len != RTA_LENGTH(dev->addr_len)) |
406 | goto out; | 409 | goto out; |
407 | 410 | ||
408 | err = dev->set_mac_address(dev, RTA_DATA(ida[IFLA_ADDRESS - 1])); | 411 | len = sizeof(sa_family_t) + dev->addr_len; |
412 | sa = kmalloc(len, GFP_KERNEL); | ||
413 | if (!sa) { | ||
414 | err = -ENOMEM; | ||
415 | goto out; | ||
416 | } | ||
417 | sa->sa_family = dev->type; | ||
418 | memcpy(sa->sa_data, RTA_DATA(ida[IFLA_ADDRESS - 1]), | ||
419 | dev->addr_len); | ||
420 | err = dev->set_mac_address(dev, sa); | ||
421 | kfree(sa); | ||
409 | if (err) | 422 | if (err) |
410 | goto out; | 423 | goto out; |
411 | send_addr_notify = 1; | 424 | send_addr_notify = 1; |
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 022d8894c11d..c54f3664bce5 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -268,8 +268,10 @@ struct sk_buff *__netdev_alloc_skb(struct net_device *dev, | |||
268 | struct sk_buff *skb; | 268 | struct sk_buff *skb; |
269 | 269 | ||
270 | skb = alloc_skb(length + NET_SKB_PAD, gfp_mask); | 270 | skb = alloc_skb(length + NET_SKB_PAD, gfp_mask); |
271 | if (likely(skb)) | 271 | if (likely(skb)) { |
272 | skb_reserve(skb, NET_SKB_PAD); | 272 | skb_reserve(skb, NET_SKB_PAD); |
273 | skb->dev = dev; | ||
274 | } | ||
273 | return skb; | 275 | return skb; |
274 | } | 276 | } |
275 | 277 | ||
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 9bf307a29783..4c20f5546893 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c | |||
@@ -947,7 +947,7 @@ alloc_new_skb: | |||
947 | skb_prev->csum = csum_sub(skb_prev->csum, | 947 | skb_prev->csum = csum_sub(skb_prev->csum, |
948 | skb->csum); | 948 | skb->csum); |
949 | data += fraggap; | 949 | data += fraggap; |
950 | skb_trim(skb_prev, maxfraglen); | 950 | pskb_trim_unique(skb_prev, maxfraglen); |
951 | } | 951 | } |
952 | 952 | ||
953 | copy = datalen - transhdrlen - fraggap; | 953 | copy = datalen - transhdrlen - fraggap; |
@@ -1142,7 +1142,7 @@ ssize_t ip_append_page(struct sock *sk, struct page *page, | |||
1142 | data, fraggap, 0); | 1142 | data, fraggap, 0); |
1143 | skb_prev->csum = csum_sub(skb_prev->csum, | 1143 | skb_prev->csum = csum_sub(skb_prev->csum, |
1144 | skb->csum); | 1144 | skb->csum); |
1145 | skb_trim(skb_prev, maxfraglen); | 1145 | pskb_trim_unique(skb_prev, maxfraglen); |
1146 | } | 1146 | } |
1147 | 1147 | ||
1148 | /* | 1148 | /* |
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index 80c73ca90116..df4854cf598b 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c | |||
@@ -1170,21 +1170,34 @@ static int __init arp_tables_init(void) | |||
1170 | { | 1170 | { |
1171 | int ret; | 1171 | int ret; |
1172 | 1172 | ||
1173 | xt_proto_init(NF_ARP); | 1173 | ret = xt_proto_init(NF_ARP); |
1174 | if (ret < 0) | ||
1175 | goto err1; | ||
1174 | 1176 | ||
1175 | /* Noone else will be downing sem now, so we won't sleep */ | 1177 | /* Noone else will be downing sem now, so we won't sleep */ |
1176 | xt_register_target(&arpt_standard_target); | 1178 | ret = xt_register_target(&arpt_standard_target); |
1177 | xt_register_target(&arpt_error_target); | 1179 | if (ret < 0) |
1180 | goto err2; | ||
1181 | ret = xt_register_target(&arpt_error_target); | ||
1182 | if (ret < 0) | ||
1183 | goto err3; | ||
1178 | 1184 | ||
1179 | /* Register setsockopt */ | 1185 | /* Register setsockopt */ |
1180 | ret = nf_register_sockopt(&arpt_sockopts); | 1186 | ret = nf_register_sockopt(&arpt_sockopts); |
1181 | if (ret < 0) { | 1187 | if (ret < 0) |
1182 | duprintf("Unable to register sockopts.\n"); | 1188 | goto err4; |
1183 | return ret; | ||
1184 | } | ||
1185 | 1189 | ||
1186 | printk("arp_tables: (C) 2002 David S. Miller\n"); | 1190 | printk("arp_tables: (C) 2002 David S. Miller\n"); |
1187 | return 0; | 1191 | return 0; |
1192 | |||
1193 | err4: | ||
1194 | xt_unregister_target(&arpt_error_target); | ||
1195 | err3: | ||
1196 | xt_unregister_target(&arpt_standard_target); | ||
1197 | err2: | ||
1198 | xt_proto_fini(NF_ARP); | ||
1199 | err1: | ||
1200 | return ret; | ||
1188 | } | 1201 | } |
1189 | 1202 | ||
1190 | static void __exit arp_tables_fini(void) | 1203 | static void __exit arp_tables_fini(void) |
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index fc5bdd5eb7d3..f316ff5fd8a6 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c | |||
@@ -2239,22 +2239,39 @@ static int __init ip_tables_init(void) | |||
2239 | { | 2239 | { |
2240 | int ret; | 2240 | int ret; |
2241 | 2241 | ||
2242 | xt_proto_init(AF_INET); | 2242 | ret = xt_proto_init(AF_INET); |
2243 | if (ret < 0) | ||
2244 | goto err1; | ||
2243 | 2245 | ||
2244 | /* Noone else will be downing sem now, so we won't sleep */ | 2246 | /* Noone else will be downing sem now, so we won't sleep */ |
2245 | xt_register_target(&ipt_standard_target); | 2247 | ret = xt_register_target(&ipt_standard_target); |
2246 | xt_register_target(&ipt_error_target); | 2248 | if (ret < 0) |
2247 | xt_register_match(&icmp_matchstruct); | 2249 | goto err2; |
2250 | ret = xt_register_target(&ipt_error_target); | ||
2251 | if (ret < 0) | ||
2252 | goto err3; | ||
2253 | ret = xt_register_match(&icmp_matchstruct); | ||
2254 | if (ret < 0) | ||
2255 | goto err4; | ||
2248 | 2256 | ||
2249 | /* Register setsockopt */ | 2257 | /* Register setsockopt */ |
2250 | ret = nf_register_sockopt(&ipt_sockopts); | 2258 | ret = nf_register_sockopt(&ipt_sockopts); |
2251 | if (ret < 0) { | 2259 | if (ret < 0) |
2252 | duprintf("Unable to register sockopts.\n"); | 2260 | goto err5; |
2253 | return ret; | ||
2254 | } | ||
2255 | 2261 | ||
2256 | printk("ip_tables: (C) 2000-2006 Netfilter Core Team\n"); | 2262 | printk("ip_tables: (C) 2000-2006 Netfilter Core Team\n"); |
2257 | return 0; | 2263 | return 0; |
2264 | |||
2265 | err5: | ||
2266 | xt_unregister_match(&icmp_matchstruct); | ||
2267 | err4: | ||
2268 | xt_unregister_target(&ipt_error_target); | ||
2269 | err3: | ||
2270 | xt_unregister_target(&ipt_standard_target); | ||
2271 | err2: | ||
2272 | xt_proto_fini(AF_INET); | ||
2273 | err1: | ||
2274 | return ret; | ||
2258 | } | 2275 | } |
2259 | 2276 | ||
2260 | static void __exit ip_tables_fini(void) | 2277 | static void __exit ip_tables_fini(void) |
diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c index d7dd7fe7051c..d46fd677fa11 100644 --- a/net/ipv4/netfilter/ipt_ULOG.c +++ b/net/ipv4/netfilter/ipt_ULOG.c | |||
@@ -115,6 +115,11 @@ static void ulog_send(unsigned int nlgroupnum) | |||
115 | del_timer(&ub->timer); | 115 | del_timer(&ub->timer); |
116 | } | 116 | } |
117 | 117 | ||
118 | if (!ub->skb) { | ||
119 | DEBUGP("ipt_ULOG: ulog_send: nothing to send\n"); | ||
120 | return; | ||
121 | } | ||
122 | |||
118 | /* last nlmsg needs NLMSG_DONE */ | 123 | /* last nlmsg needs NLMSG_DONE */ |
119 | if (ub->qlen > 1) | 124 | if (ub->qlen > 1) |
120 | ub->lastnlh->nlmsg_type = NLMSG_DONE; | 125 | ub->lastnlh->nlmsg_type = NLMSG_DONE; |
diff --git a/net/ipv4/netfilter/ipt_hashlimit.c b/net/ipv4/netfilter/ipt_hashlimit.c index 6b662449e825..3bd2368e1fc9 100644 --- a/net/ipv4/netfilter/ipt_hashlimit.c +++ b/net/ipv4/netfilter/ipt_hashlimit.c | |||
@@ -454,15 +454,12 @@ hashlimit_match(const struct sk_buff *skb, | |||
454 | dh->rateinfo.credit_cap = user2credits(hinfo->cfg.avg * | 454 | dh->rateinfo.credit_cap = user2credits(hinfo->cfg.avg * |
455 | hinfo->cfg.burst); | 455 | hinfo->cfg.burst); |
456 | dh->rateinfo.cost = user2credits(hinfo->cfg.avg); | 456 | dh->rateinfo.cost = user2credits(hinfo->cfg.avg); |
457 | 457 | } else { | |
458 | spin_unlock_bh(&hinfo->lock); | 458 | /* update expiration timeout */ |
459 | return 1; | 459 | dh->expires = now + msecs_to_jiffies(hinfo->cfg.expire); |
460 | rateinfo_recalc(dh, now); | ||
460 | } | 461 | } |
461 | 462 | ||
462 | /* update expiration timeout */ | ||
463 | dh->expires = now + msecs_to_jiffies(hinfo->cfg.expire); | ||
464 | |||
465 | rateinfo_recalc(dh, now); | ||
466 | if (dh->rateinfo.credit >= dh->rateinfo.cost) { | 463 | if (dh->rateinfo.credit >= dh->rateinfo.cost) { |
467 | /* We're underlimit. */ | 464 | /* We're underlimit. */ |
468 | dh->rateinfo.credit -= dh->rateinfo.cost; | 465 | dh->rateinfo.credit -= dh->rateinfo.cost; |
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 19bd49d69d9f..b873cbcdd0b8 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -3157,7 +3157,7 @@ int __init ip_rt_init(void) | |||
3157 | rhash_entries, | 3157 | rhash_entries, |
3158 | (num_physpages >= 128 * 1024) ? | 3158 | (num_physpages >= 128 * 1024) ? |
3159 | 15 : 17, | 3159 | 15 : 17, |
3160 | HASH_HIGHMEM, | 3160 | 0, |
3161 | &rt_hash_log, | 3161 | &rt_hash_log, |
3162 | &rt_hash_mask, | 3162 | &rt_hash_mask, |
3163 | 0); | 3163 | 0); |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 738dad9f7d49..104af5d5bcbc 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -3541,7 +3541,8 @@ void tcp_cwnd_application_limited(struct sock *sk) | |||
3541 | if (inet_csk(sk)->icsk_ca_state == TCP_CA_Open && | 3541 | if (inet_csk(sk)->icsk_ca_state == TCP_CA_Open && |
3542 | sk->sk_socket && !test_bit(SOCK_NOSPACE, &sk->sk_socket->flags)) { | 3542 | sk->sk_socket && !test_bit(SOCK_NOSPACE, &sk->sk_socket->flags)) { |
3543 | /* Limited by application or receiver window. */ | 3543 | /* Limited by application or receiver window. */ |
3544 | u32 win_used = max(tp->snd_cwnd_used, 2U); | 3544 | u32 init_win = tcp_init_cwnd(tp, __sk_dst_get(sk)); |
3545 | u32 win_used = max(tp->snd_cwnd_used, init_win); | ||
3545 | if (win_used < tp->snd_cwnd) { | 3546 | if (win_used < tp->snd_cwnd) { |
3546 | tp->snd_ssthresh = tcp_current_ssthresh(sk); | 3547 | tp->snd_ssthresh = tcp_current_ssthresh(sk); |
3547 | tp->snd_cwnd = (tp->snd_cwnd + win_used) >> 1; | 3548 | tp->snd_cwnd = (tp->snd_cwnd + win_used) >> 1; |
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 5c08ea20a18d..507adefbc17c 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
@@ -466,7 +466,8 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, | |||
466 | if (skb->len != tcp_header_size) | 466 | if (skb->len != tcp_header_size) |
467 | tcp_event_data_sent(tp, skb, sk); | 467 | tcp_event_data_sent(tp, skb, sk); |
468 | 468 | ||
469 | TCP_INC_STATS(TCP_MIB_OUTSEGS); | 469 | if (after(tcb->end_seq, tp->snd_nxt) || tcb->seq == tcb->end_seq) |
470 | TCP_INC_STATS(TCP_MIB_OUTSEGS); | ||
470 | 471 | ||
471 | err = icsk->icsk_af_ops->queue_xmit(skb, 0); | 472 | err = icsk->icsk_af_ops->queue_xmit(skb, 0); |
472 | if (likely(err <= 0)) | 473 | if (likely(err <= 0)) |
@@ -2157,10 +2158,9 @@ int tcp_connect(struct sock *sk) | |||
2157 | skb_shinfo(buff)->gso_size = 0; | 2158 | skb_shinfo(buff)->gso_size = 0; |
2158 | skb_shinfo(buff)->gso_type = 0; | 2159 | skb_shinfo(buff)->gso_type = 0; |
2159 | buff->csum = 0; | 2160 | buff->csum = 0; |
2161 | tp->snd_nxt = tp->write_seq; | ||
2160 | TCP_SKB_CB(buff)->seq = tp->write_seq++; | 2162 | TCP_SKB_CB(buff)->seq = tp->write_seq++; |
2161 | TCP_SKB_CB(buff)->end_seq = tp->write_seq; | 2163 | TCP_SKB_CB(buff)->end_seq = tp->write_seq; |
2162 | tp->snd_nxt = tp->write_seq; | ||
2163 | tp->pushed_seq = tp->write_seq; | ||
2164 | 2164 | ||
2165 | /* Send it off. */ | 2165 | /* Send it off. */ |
2166 | TCP_SKB_CB(buff)->when = tcp_time_stamp; | 2166 | TCP_SKB_CB(buff)->when = tcp_time_stamp; |
@@ -2170,6 +2170,12 @@ int tcp_connect(struct sock *sk) | |||
2170 | sk_charge_skb(sk, buff); | 2170 | sk_charge_skb(sk, buff); |
2171 | tp->packets_out += tcp_skb_pcount(buff); | 2171 | tp->packets_out += tcp_skb_pcount(buff); |
2172 | tcp_transmit_skb(sk, buff, 1, GFP_KERNEL); | 2172 | tcp_transmit_skb(sk, buff, 1, GFP_KERNEL); |
2173 | |||
2174 | /* We change tp->snd_nxt after the tcp_transmit_skb() call | ||
2175 | * in order to make this packet get counted in tcpOutSegs. | ||
2176 | */ | ||
2177 | tp->snd_nxt = tp->write_seq; | ||
2178 | tp->pushed_seq = tp->write_seq; | ||
2173 | TCP_INC_STATS(TCP_MIB_ACTIVEOPENS); | 2179 | TCP_INC_STATS(TCP_MIB_ACTIVEOPENS); |
2174 | 2180 | ||
2175 | /* Timer for repeating the SYN until an answer. */ | 2181 | /* Timer for repeating the SYN until an answer. */ |
diff --git a/net/ipv4/tcp_probe.c b/net/ipv4/tcp_probe.c index b3435324b573..dab37d2f65fc 100644 --- a/net/ipv4/tcp_probe.c +++ b/net/ipv4/tcp_probe.c | |||
@@ -130,11 +130,12 @@ static ssize_t tcpprobe_read(struct file *file, char __user *buf, | |||
130 | error = wait_event_interruptible(tcpw.wait, | 130 | error = wait_event_interruptible(tcpw.wait, |
131 | __kfifo_len(tcpw.fifo) != 0); | 131 | __kfifo_len(tcpw.fifo) != 0); |
132 | if (error) | 132 | if (error) |
133 | return error; | 133 | goto out_free; |
134 | 134 | ||
135 | cnt = kfifo_get(tcpw.fifo, tbuf, len); | 135 | cnt = kfifo_get(tcpw.fifo, tbuf, len); |
136 | error = copy_to_user(buf, tbuf, cnt); | 136 | error = copy_to_user(buf, tbuf, cnt); |
137 | 137 | ||
138 | out_free: | ||
138 | vfree(tbuf); | 139 | vfree(tbuf); |
139 | 140 | ||
140 | return error ? error : cnt; | 141 | return error ? error : cnt; |
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 8ea1e36bf8eb..0c5042e7380d 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -1909,11 +1909,11 @@ static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen, | |||
1909 | ifp = ipv6_add_addr(idev, pfx, plen, scope, ifa_flags); | 1909 | ifp = ipv6_add_addr(idev, pfx, plen, scope, ifa_flags); |
1910 | 1910 | ||
1911 | if (!IS_ERR(ifp)) { | 1911 | if (!IS_ERR(ifp)) { |
1912 | spin_lock(&ifp->lock); | 1912 | spin_lock_bh(&ifp->lock); |
1913 | ifp->valid_lft = valid_lft; | 1913 | ifp->valid_lft = valid_lft; |
1914 | ifp->prefered_lft = prefered_lft; | 1914 | ifp->prefered_lft = prefered_lft; |
1915 | ifp->tstamp = jiffies; | 1915 | ifp->tstamp = jiffies; |
1916 | spin_unlock(&ifp->lock); | 1916 | spin_unlock_bh(&ifp->lock); |
1917 | 1917 | ||
1918 | addrconf_dad_start(ifp, 0); | 1918 | addrconf_dad_start(ifp, 0); |
1919 | in6_ifa_put(ifp); | 1919 | in6_ifa_put(ifp); |
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 69451af6abe7..4fb47a252913 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -1095,7 +1095,7 @@ alloc_new_skb: | |||
1095 | skb_prev->csum = csum_sub(skb_prev->csum, | 1095 | skb_prev->csum = csum_sub(skb_prev->csum, |
1096 | skb->csum); | 1096 | skb->csum); |
1097 | data += fraggap; | 1097 | data += fraggap; |
1098 | skb_trim(skb_prev, maxfraglen); | 1098 | pskb_trim_unique(skb_prev, maxfraglen); |
1099 | } | 1099 | } |
1100 | copy = datalen - transhdrlen - fraggap; | 1100 | copy = datalen - transhdrlen - fraggap; |
1101 | if (copy < 0) { | 1101 | if (copy < 0) { |
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index f26898b00347..c9d6b23cd3f7 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c | |||
@@ -1398,23 +1398,39 @@ static int __init ip6_tables_init(void) | |||
1398 | { | 1398 | { |
1399 | int ret; | 1399 | int ret; |
1400 | 1400 | ||
1401 | xt_proto_init(AF_INET6); | 1401 | ret = xt_proto_init(AF_INET6); |
1402 | if (ret < 0) | ||
1403 | goto err1; | ||
1402 | 1404 | ||
1403 | /* Noone else will be downing sem now, so we won't sleep */ | 1405 | /* Noone else will be downing sem now, so we won't sleep */ |
1404 | xt_register_target(&ip6t_standard_target); | 1406 | ret = xt_register_target(&ip6t_standard_target); |
1405 | xt_register_target(&ip6t_error_target); | 1407 | if (ret < 0) |
1406 | xt_register_match(&icmp6_matchstruct); | 1408 | goto err2; |
1409 | ret = xt_register_target(&ip6t_error_target); | ||
1410 | if (ret < 0) | ||
1411 | goto err3; | ||
1412 | ret = xt_register_match(&icmp6_matchstruct); | ||
1413 | if (ret < 0) | ||
1414 | goto err4; | ||
1407 | 1415 | ||
1408 | /* Register setsockopt */ | 1416 | /* Register setsockopt */ |
1409 | ret = nf_register_sockopt(&ip6t_sockopts); | 1417 | ret = nf_register_sockopt(&ip6t_sockopts); |
1410 | if (ret < 0) { | 1418 | if (ret < 0) |
1411 | duprintf("Unable to register sockopts.\n"); | 1419 | goto err5; |
1412 | xt_proto_fini(AF_INET6); | ||
1413 | return ret; | ||
1414 | } | ||
1415 | 1420 | ||
1416 | printk("ip6_tables: (C) 2000-2006 Netfilter Core Team\n"); | 1421 | printk("ip6_tables: (C) 2000-2006 Netfilter Core Team\n"); |
1417 | return 0; | 1422 | return 0; |
1423 | |||
1424 | err5: | ||
1425 | xt_unregister_match(&icmp6_matchstruct); | ||
1426 | err4: | ||
1427 | xt_unregister_target(&ip6t_error_target); | ||
1428 | err3: | ||
1429 | xt_unregister_target(&ip6t_standard_target); | ||
1430 | err2: | ||
1431 | xt_proto_fini(AF_INET6); | ||
1432 | err1: | ||
1433 | return ret; | ||
1418 | } | 1434 | } |
1419 | 1435 | ||
1420 | static void __exit ip6_tables_fini(void) | 1436 | static void __exit ip6_tables_fini(void) |
diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c index aa34ff4b707c..bef3f61569f7 100644 --- a/net/ipx/af_ipx.c +++ b/net/ipx/af_ipx.c | |||
@@ -1642,13 +1642,17 @@ static int ipx_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_ty | |||
1642 | if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) | 1642 | if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) |
1643 | goto out; | 1643 | goto out; |
1644 | 1644 | ||
1645 | ipx = ipx_hdr(skb); | 1645 | if (!pskb_may_pull(skb, sizeof(struct ipxhdr))) |
1646 | ipx_pktsize = ntohs(ipx->ipx_pktsize); | 1646 | goto drop; |
1647 | |||
1648 | ipx_pktsize = ntohs(ipx_hdr(skb)->ipx_pktsize); | ||
1647 | 1649 | ||
1648 | /* Too small or invalid header? */ | 1650 | /* Too small or invalid header? */ |
1649 | if (ipx_pktsize < sizeof(struct ipxhdr) || ipx_pktsize > skb->len) | 1651 | if (ipx_pktsize < sizeof(struct ipxhdr) || |
1652 | !pskb_may_pull(skb, ipx_pktsize)) | ||
1650 | goto drop; | 1653 | goto drop; |
1651 | 1654 | ||
1655 | ipx = ipx_hdr(skb); | ||
1652 | if (ipx->ipx_checksum != IPX_NO_CHECKSUM && | 1656 | if (ipx->ipx_checksum != IPX_NO_CHECKSUM && |
1653 | ipx->ipx_checksum != ipx_cksum(ipx, ipx_pktsize)) | 1657 | ipx->ipx_checksum != ipx_cksum(ipx, ipx_pktsize)) |
1654 | goto drop; | 1658 | goto drop; |
diff --git a/net/lapb/lapb_iface.c b/net/lapb/lapb_iface.c index d504eed416f6..7e6bc41eeb21 100644 --- a/net/lapb/lapb_iface.c +++ b/net/lapb/lapb_iface.c | |||
@@ -238,11 +238,13 @@ int lapb_setparms(struct net_device *dev, struct lapb_parms_struct *parms) | |||
238 | goto out_put; | 238 | goto out_put; |
239 | 239 | ||
240 | if (lapb->state == LAPB_STATE_0) { | 240 | if (lapb->state == LAPB_STATE_0) { |
241 | if (((parms->mode & LAPB_EXTENDED) && | 241 | if (parms->mode & LAPB_EXTENDED) { |
242 | (parms->window < 1 || parms->window > 127)) || | 242 | if (parms->window < 1 || parms->window > 127) |
243 | (parms->window < 1 || parms->window > 7)) | 243 | goto out_put; |
244 | goto out_put; | 244 | } else { |
245 | 245 | if (parms->window < 1 || parms->window > 7) | |
246 | goto out_put; | ||
247 | } | ||
246 | lapb->mode = parms->mode; | 248 | lapb->mode = parms->mode; |
247 | lapb->window = parms->window; | 249 | lapb->window = parms->window; |
248 | } | 250 | } |
diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index d6cfe84d521b..2652ead96c64 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c | |||
@@ -784,24 +784,20 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
784 | copied += used; | 784 | copied += used; |
785 | len -= used; | 785 | len -= used; |
786 | 786 | ||
787 | if (used + offset < skb->len) | ||
788 | continue; | ||
789 | |||
790 | if (!(flags & MSG_PEEK)) { | 787 | if (!(flags & MSG_PEEK)) { |
791 | sk_eat_skb(sk, skb, 0); | 788 | sk_eat_skb(sk, skb, 0); |
792 | *seq = 0; | 789 | *seq = 0; |
793 | } | 790 | } |
791 | |||
792 | /* For non stream protcols we get one packet per recvmsg call */ | ||
793 | if (sk->sk_type != SOCK_STREAM) | ||
794 | goto copy_uaddr; | ||
795 | |||
796 | /* Partial read */ | ||
797 | if (used + offset < skb->len) | ||
798 | continue; | ||
794 | } while (len > 0); | 799 | } while (len > 0); |
795 | 800 | ||
796 | /* | ||
797 | * According to UNIX98, msg_name/msg_namelen are ignored | ||
798 | * on connected socket. -ANK | ||
799 | * But... af_llc still doesn't have separate sets of methods for | ||
800 | * SOCK_DGRAM and SOCK_STREAM :-( So we have to do this test, will | ||
801 | * eventually fix this tho :-) -acme | ||
802 | */ | ||
803 | if (sk->sk_type == SOCK_DGRAM) | ||
804 | goto copy_uaddr; | ||
805 | out: | 801 | out: |
806 | release_sock(sk); | 802 | release_sock(sk); |
807 | return copied; | 803 | return copied; |
diff --git a/net/llc/llc_sap.c b/net/llc/llc_sap.c index 20c4eb5c1ac6..61cb8cf7d153 100644 --- a/net/llc/llc_sap.c +++ b/net/llc/llc_sap.c | |||
@@ -51,10 +51,10 @@ void llc_save_primitive(struct sock *sk, struct sk_buff* skb, u8 prim) | |||
51 | { | 51 | { |
52 | struct sockaddr_llc *addr; | 52 | struct sockaddr_llc *addr; |
53 | 53 | ||
54 | if (skb->sk->sk_type == SOCK_STREAM) /* See UNIX98 */ | ||
55 | return; | ||
56 | /* save primitive for use by the user. */ | 54 | /* save primitive for use by the user. */ |
57 | addr = llc_ui_skb_cb(skb); | 55 | addr = llc_ui_skb_cb(skb); |
56 | |||
57 | memset(addr, 0, sizeof(*addr)); | ||
58 | addr->sllc_family = sk->sk_family; | 58 | addr->sllc_family = sk->sk_family; |
59 | addr->sllc_arphrd = skb->dev->type; | 59 | addr->sllc_arphrd = skb->dev->type; |
60 | addr->sllc_test = prim == LLC_TEST_PRIM; | 60 | addr->sllc_test = prim == LLC_TEST_PRIM; |
@@ -330,6 +330,9 @@ static void llc_sap_mcast(struct llc_sap *sap, | |||
330 | if (llc->laddr.lsap != laddr->lsap) | 330 | if (llc->laddr.lsap != laddr->lsap) |
331 | continue; | 331 | continue; |
332 | 332 | ||
333 | if (llc->dev != skb->dev) | ||
334 | continue; | ||
335 | |||
333 | skb1 = skb_clone(skb, GFP_ATOMIC); | 336 | skb1 = skb_clone(skb, GFP_ATOMIC); |
334 | if (!skb1) | 337 | if (!skb1) |
335 | break; | 338 | break; |
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index 61cdda4e5d3b..b59d3b2bde21 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c | |||
@@ -366,6 +366,9 @@ __nfulnl_send(struct nfulnl_instance *inst) | |||
366 | if (timer_pending(&inst->timer)) | 366 | if (timer_pending(&inst->timer)) |
367 | del_timer(&inst->timer); | 367 | del_timer(&inst->timer); |
368 | 368 | ||
369 | if (!inst->skb) | ||
370 | return 0; | ||
371 | |||
369 | if (inst->qlen > 1) | 372 | if (inst->qlen > 1) |
370 | inst->lastnlh->nlmsg_type = NLMSG_DONE; | 373 | inst->lastnlh->nlmsg_type = NLMSG_DONE; |
371 | 374 | ||
diff --git a/net/netfilter/xt_string.c b/net/netfilter/xt_string.c index d8e3891b5f8b..275330fcdaaa 100644 --- a/net/netfilter/xt_string.c +++ b/net/netfilter/xt_string.c | |||
@@ -37,7 +37,7 @@ static int match(const struct sk_buff *skb, | |||
37 | 37 | ||
38 | return (skb_find_text((struct sk_buff *)skb, conf->from_offset, | 38 | return (skb_find_text((struct sk_buff *)skb, conf->from_offset, |
39 | conf->to_offset, conf->config, &state) | 39 | conf->to_offset, conf->config, &state) |
40 | != UINT_MAX) && !conf->invert; | 40 | != UINT_MAX) ^ conf->invert; |
41 | } | 41 | } |
42 | 42 | ||
43 | #define STRING_TEXT_PRIV(m) ((struct xt_string_info *) m) | 43 | #define STRING_TEXT_PRIV(m) ((struct xt_string_info *) m) |
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index c7844bacbbcb..a19eff12cf78 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c | |||
@@ -430,7 +430,7 @@ qdisc_create(struct net_device *dev, u32 handle, struct rtattr **tca, int *errp) | |||
430 | } | 430 | } |
431 | #endif | 431 | #endif |
432 | 432 | ||
433 | err = -EINVAL; | 433 | err = -ENOENT; |
434 | if (ops == NULL) | 434 | if (ops == NULL) |
435 | goto err_out; | 435 | goto err_out; |
436 | 436 | ||
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index 7026b0866b7b..00cb388ece03 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c | |||
@@ -71,7 +71,12 @@ struct cache_head *sunrpc_cache_lookup(struct cache_detail *detail, | |||
71 | new = detail->alloc(); | 71 | new = detail->alloc(); |
72 | if (!new) | 72 | if (!new) |
73 | return NULL; | 73 | return NULL; |
74 | /* must fully initialise 'new', else | ||
75 | * we might get lose if we need to | ||
76 | * cache_put it soon. | ||
77 | */ | ||
74 | cache_init(new); | 78 | cache_init(new); |
79 | detail->init(new, key); | ||
75 | 80 | ||
76 | write_lock(&detail->hash_lock); | 81 | write_lock(&detail->hash_lock); |
77 | 82 | ||
@@ -85,7 +90,6 @@ struct cache_head *sunrpc_cache_lookup(struct cache_detail *detail, | |||
85 | return tmp; | 90 | return tmp; |
86 | } | 91 | } |
87 | } | 92 | } |
88 | detail->init(new, key); | ||
89 | new->next = *head; | 93 | new->next = *head; |
90 | *head = new; | 94 | *head = new; |
91 | detail->entries++; | 95 | detail->entries++; |
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 4ba271f892c8..d6409e757219 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
@@ -921,26 +921,43 @@ call_transmit(struct rpc_task *task) | |||
921 | task->tk_status = xprt_prepare_transmit(task); | 921 | task->tk_status = xprt_prepare_transmit(task); |
922 | if (task->tk_status != 0) | 922 | if (task->tk_status != 0) |
923 | return; | 923 | return; |
924 | task->tk_action = call_transmit_status; | ||
924 | /* Encode here so that rpcsec_gss can use correct sequence number. */ | 925 | /* Encode here so that rpcsec_gss can use correct sequence number. */ |
925 | if (rpc_task_need_encode(task)) { | 926 | if (rpc_task_need_encode(task)) { |
926 | task->tk_rqstp->rq_bytes_sent = 0; | 927 | BUG_ON(task->tk_rqstp->rq_bytes_sent != 0); |
927 | call_encode(task); | 928 | call_encode(task); |
928 | /* Did the encode result in an error condition? */ | 929 | /* Did the encode result in an error condition? */ |
929 | if (task->tk_status != 0) | 930 | if (task->tk_status != 0) |
930 | goto out_nosend; | 931 | return; |
931 | } | 932 | } |
932 | task->tk_action = call_transmit_status; | ||
933 | xprt_transmit(task); | 933 | xprt_transmit(task); |
934 | if (task->tk_status < 0) | 934 | if (task->tk_status < 0) |
935 | return; | 935 | return; |
936 | if (!task->tk_msg.rpc_proc->p_decode) { | 936 | /* |
937 | task->tk_action = rpc_exit_task; | 937 | * On success, ensure that we call xprt_end_transmit() before sleeping |
938 | rpc_wake_up_task(task); | 938 | * in order to allow access to the socket to other RPC requests. |
939 | } | 939 | */ |
940 | return; | 940 | call_transmit_status(task); |
941 | out_nosend: | 941 | if (task->tk_msg.rpc_proc->p_decode != NULL) |
942 | /* release socket write lock before attempting to handle error */ | 942 | return; |
943 | xprt_abort_transmit(task); | 943 | task->tk_action = rpc_exit_task; |
944 | rpc_wake_up_task(task); | ||
945 | } | ||
946 | |||
947 | /* | ||
948 | * 5a. Handle cleanup after a transmission | ||
949 | */ | ||
950 | static void | ||
951 | call_transmit_status(struct rpc_task *task) | ||
952 | { | ||
953 | task->tk_action = call_status; | ||
954 | /* | ||
955 | * Special case: if we've been waiting on the socket's write_space() | ||
956 | * callback, then don't call xprt_end_transmit(). | ||
957 | */ | ||
958 | if (task->tk_status == -EAGAIN) | ||
959 | return; | ||
960 | xprt_end_transmit(task); | ||
944 | rpc_task_force_reencode(task); | 961 | rpc_task_force_reencode(task); |
945 | } | 962 | } |
946 | 963 | ||
@@ -992,18 +1009,7 @@ call_status(struct rpc_task *task) | |||
992 | } | 1009 | } |
993 | 1010 | ||
994 | /* | 1011 | /* |
995 | * 6a. Handle transmission errors. | 1012 | * 6a. Handle RPC timeout |
996 | */ | ||
997 | static void | ||
998 | call_transmit_status(struct rpc_task *task) | ||
999 | { | ||
1000 | if (task->tk_status != -EAGAIN) | ||
1001 | rpc_task_force_reencode(task); | ||
1002 | call_status(task); | ||
1003 | } | ||
1004 | |||
1005 | /* | ||
1006 | * 6b. Handle RPC timeout | ||
1007 | * We do not release the request slot, so we keep using the | 1013 | * We do not release the request slot, so we keep using the |
1008 | * same XID for all retransmits. | 1014 | * same XID for all retransmits. |
1009 | */ | 1015 | */ |
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index dc6cb93c8830..a3bd2db2e024 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c | |||
@@ -667,10 +667,11 @@ rpc_mkdir(char *path, struct rpc_clnt *rpc_client) | |||
667 | RPCAUTH_info, RPCAUTH_EOF); | 667 | RPCAUTH_info, RPCAUTH_EOF); |
668 | if (error) | 668 | if (error) |
669 | goto err_depopulate; | 669 | goto err_depopulate; |
670 | dget(dentry); | ||
670 | out: | 671 | out: |
671 | mutex_unlock(&dir->i_mutex); | 672 | mutex_unlock(&dir->i_mutex); |
672 | rpc_release_path(&nd); | 673 | rpc_release_path(&nd); |
673 | return dget(dentry); | 674 | return dentry; |
674 | err_depopulate: | 675 | err_depopulate: |
675 | rpc_depopulate(dentry); | 676 | rpc_depopulate(dentry); |
676 | __rpc_rmdir(dir, dentry); | 677 | __rpc_rmdir(dir, dentry); |
@@ -731,10 +732,11 @@ rpc_mkpipe(char *path, void *private, struct rpc_pipe_ops *ops, int flags) | |||
731 | rpci->flags = flags; | 732 | rpci->flags = flags; |
732 | rpci->ops = ops; | 733 | rpci->ops = ops; |
733 | inode_dir_notify(dir, DN_CREATE); | 734 | inode_dir_notify(dir, DN_CREATE); |
735 | dget(dentry); | ||
734 | out: | 736 | out: |
735 | mutex_unlock(&dir->i_mutex); | 737 | mutex_unlock(&dir->i_mutex); |
736 | rpc_release_path(&nd); | 738 | rpc_release_path(&nd); |
737 | return dget(dentry); | 739 | return dentry; |
738 | err_dput: | 740 | err_dput: |
739 | dput(dentry); | 741 | dput(dentry); |
740 | dentry = ERR_PTR(-ENOMEM); | 742 | dentry = ERR_PTR(-ENOMEM); |
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index 313b68d892c6..e8c2bc4977f3 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c | |||
@@ -707,12 +707,9 @@ out_unlock: | |||
707 | return err; | 707 | return err; |
708 | } | 708 | } |
709 | 709 | ||
710 | void | 710 | void xprt_end_transmit(struct rpc_task *task) |
711 | xprt_abort_transmit(struct rpc_task *task) | ||
712 | { | 711 | { |
713 | struct rpc_xprt *xprt = task->tk_xprt; | 712 | xprt_release_write(task->tk_xprt, task); |
714 | |||
715 | xprt_release_write(xprt, task); | ||
716 | } | 713 | } |
717 | 714 | ||
718 | /** | 715 | /** |
@@ -761,8 +758,6 @@ void xprt_transmit(struct rpc_task *task) | |||
761 | task->tk_status = -ENOTCONN; | 758 | task->tk_status = -ENOTCONN; |
762 | else if (!req->rq_received) | 759 | else if (!req->rq_received) |
763 | rpc_sleep_on(&xprt->pending, task, NULL, xprt_timer); | 760 | rpc_sleep_on(&xprt->pending, task, NULL, xprt_timer); |
764 | |||
765 | xprt->ops->release_xprt(xprt, task); | ||
766 | spin_unlock_bh(&xprt->transport_lock); | 761 | spin_unlock_bh(&xprt->transport_lock); |
767 | return; | 762 | return; |
768 | } | 763 | } |
@@ -772,18 +767,8 @@ void xprt_transmit(struct rpc_task *task) | |||
772 | * schedq, and being picked up by a parallel run of rpciod(). | 767 | * schedq, and being picked up by a parallel run of rpciod(). |
773 | */ | 768 | */ |
774 | task->tk_status = status; | 769 | task->tk_status = status; |
775 | 770 | if (status == -ECONNREFUSED) | |
776 | switch (status) { | ||
777 | case -ECONNREFUSED: | ||
778 | rpc_sleep_on(&xprt->sending, task, NULL, NULL); | 771 | rpc_sleep_on(&xprt->sending, task, NULL, NULL); |
779 | case -EAGAIN: | ||
780 | case -ENOTCONN: | ||
781 | return; | ||
782 | default: | ||
783 | break; | ||
784 | } | ||
785 | xprt_release_write(xprt, task); | ||
786 | return; | ||
787 | } | 772 | } |
788 | 773 | ||
789 | static inline void do_xprt_reserve(struct rpc_task *task) | 774 | static inline void do_xprt_reserve(struct rpc_task *task) |
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index ee678ed13b6f..441bd53f5eca 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
@@ -414,6 +414,33 @@ static int xs_tcp_send_request(struct rpc_task *task) | |||
414 | } | 414 | } |
415 | 415 | ||
416 | /** | 416 | /** |
417 | * xs_tcp_release_xprt - clean up after a tcp transmission | ||
418 | * @xprt: transport | ||
419 | * @task: rpc task | ||
420 | * | ||
421 | * This cleans up if an error causes us to abort the transmission of a request. | ||
422 | * In this case, the socket may need to be reset in order to avoid confusing | ||
423 | * the server. | ||
424 | */ | ||
425 | static void xs_tcp_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task) | ||
426 | { | ||
427 | struct rpc_rqst *req; | ||
428 | |||
429 | if (task != xprt->snd_task) | ||
430 | return; | ||
431 | if (task == NULL) | ||
432 | goto out_release; | ||
433 | req = task->tk_rqstp; | ||
434 | if (req->rq_bytes_sent == 0) | ||
435 | goto out_release; | ||
436 | if (req->rq_bytes_sent == req->rq_snd_buf.len) | ||
437 | goto out_release; | ||
438 | set_bit(XPRT_CLOSE_WAIT, &task->tk_xprt->state); | ||
439 | out_release: | ||
440 | xprt_release_xprt(xprt, task); | ||
441 | } | ||
442 | |||
443 | /** | ||
417 | * xs_close - close a socket | 444 | * xs_close - close a socket |
418 | * @xprt: transport | 445 | * @xprt: transport |
419 | * | 446 | * |
@@ -1250,7 +1277,7 @@ static struct rpc_xprt_ops xs_udp_ops = { | |||
1250 | 1277 | ||
1251 | static struct rpc_xprt_ops xs_tcp_ops = { | 1278 | static struct rpc_xprt_ops xs_tcp_ops = { |
1252 | .reserve_xprt = xprt_reserve_xprt, | 1279 | .reserve_xprt = xprt_reserve_xprt, |
1253 | .release_xprt = xprt_release_xprt, | 1280 | .release_xprt = xs_tcp_release_xprt, |
1254 | .set_port = xs_set_port, | 1281 | .set_port = xs_set_port, |
1255 | .connect = xs_connect, | 1282 | .connect = xs_connect, |
1256 | .buf_alloc = rpc_malloc, | 1283 | .buf_alloc = rpc_malloc, |
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index f35bc676128c..3da67ca2c3ce 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c | |||
@@ -1134,12 +1134,33 @@ int __xfrm_route_forward(struct sk_buff *skb, unsigned short family) | |||
1134 | } | 1134 | } |
1135 | EXPORT_SYMBOL(__xfrm_route_forward); | 1135 | EXPORT_SYMBOL(__xfrm_route_forward); |
1136 | 1136 | ||
1137 | /* Optimize later using cookies and generation ids. */ | ||
1138 | |||
1137 | static struct dst_entry *xfrm_dst_check(struct dst_entry *dst, u32 cookie) | 1139 | static struct dst_entry *xfrm_dst_check(struct dst_entry *dst, u32 cookie) |
1138 | { | 1140 | { |
1139 | /* If it is marked obsolete, which is how we even get here, | 1141 | /* Code (such as __xfrm4_bundle_create()) sets dst->obsolete |
1140 | * then we have purged it from the policy bundle list and we | 1142 | * to "-1" to force all XFRM destinations to get validated by |
1141 | * did that for a good reason. | 1143 | * dst_ops->check on every use. We do this because when a |
1144 | * normal route referenced by an XFRM dst is obsoleted we do | ||
1145 | * not go looking around for all parent referencing XFRM dsts | ||
1146 | * so that we can invalidate them. It is just too much work. | ||
1147 | * Instead we make the checks here on every use. For example: | ||
1148 | * | ||
1149 | * XFRM dst A --> IPv4 dst X | ||
1150 | * | ||
1151 | * X is the "xdst->route" of A (X is also the "dst->path" of A | ||
1152 | * in this example). If X is marked obsolete, "A" will not | ||
1153 | * notice. That's what we are validating here via the | ||
1154 | * stale_bundle() check. | ||
1155 | * | ||
1156 | * When a policy's bundle is pruned, we dst_free() the XFRM | ||
1157 | * dst which causes it's ->obsolete field to be set to a | ||
1158 | * positive non-zero integer. If an XFRM dst has been pruned | ||
1159 | * like this, we want to force a new route lookup. | ||
1142 | */ | 1160 | */ |
1161 | if (dst->obsolete < 0 && !stale_bundle(dst)) | ||
1162 | return dst; | ||
1163 | |||
1143 | return NULL; | 1164 | return NULL; |
1144 | } | 1165 | } |
1145 | 1166 | ||