diff options
author | David S. Miller <davem@davemloft.net> | 2017-11-02 14:59:52 +0900 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-11-02 15:23:39 +0900 |
commit | ed29668d1aa2c6f01e61dd616df13b5241cee7e0 (patch) | |
tree | a086cf6311ed8623b292d3ea8d73c03f53207be0 /net | |
parent | 65c959a39b7e9ad6b443b74904486b4a75b0232f (diff) | |
parent | 3a99df9a3d14cd866b5516f8cba515a3bfd554ab (diff) | |
download | linux-ed29668d1aa2c6f01e61dd616df13b5241cee7e0.tar.bz2 |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Smooth Cong Wang's bug fix into 'net-next'. Basically put
the bulk of the tcf_block_put() logic from 'net' into
tcf_block_put_ext(), but after the offload unbind.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/ife/ife.c | 2 | ||||
-rw-r--r-- | net/ipv4/tcp_output.c | 3 | ||||
-rw-r--r-- | net/ipv6/addrconf.c | 1 | ||||
-rw-r--r-- | net/l2tp/l2tp_ppp.c | 7 | ||||
-rw-r--r-- | net/psample/psample.c | 2 | ||||
-rw-r--r-- | net/sched/act_sample.c | 2 | ||||
-rw-r--r-- | net/sched/cls_api.c | 38 | ||||
-rw-r--r-- | net/xfrm/xfrm_output.c | 4 | ||||
-rw-r--r-- | net/xfrm/xfrm_policy.c | 1 | ||||
-rw-r--r-- | net/xfrm/xfrm_state.c | 1 |
10 files changed, 25 insertions, 36 deletions
diff --git a/net/ife/ife.c b/net/ife/ife.c index f360341c72eb..7d1ec76e7f43 100644 --- a/net/ife/ife.c +++ b/net/ife/ife.c @@ -137,6 +137,6 @@ int ife_tlv_meta_encode(void *skbdata, u16 attrtype, u16 dlen, const void *dval) EXPORT_SYMBOL_GPL(ife_tlv_meta_encode); MODULE_AUTHOR("Jamal Hadi Salim <jhs@mojatatu.com>"); -MODULE_AUTHOR("Yotam Gigi <yotamg@mellanox.com>"); +MODULE_AUTHOR("Yotam Gigi <yotam.gi@gmail.com>"); MODULE_DESCRIPTION("Inter-FE LFB action"); MODULE_LICENSE("GPL"); diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index a69a34f57330..a85e8a282d17 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -2132,6 +2132,7 @@ static int tcp_mtu_probe(struct sock *sk) nskb->ip_summed = skb->ip_summed; tcp_insert_write_queue_before(nskb, skb, sk); + tcp_highest_sack_replace(sk, skb, nskb); len = 0; tcp_for_write_queue_from_safe(skb, next, sk) { @@ -2735,7 +2736,7 @@ static bool tcp_collapse_retrans(struct sock *sk, struct sk_buff *skb) else if (!skb_shift(skb, next_skb, next_skb_size)) return false; } - tcp_highest_sack_combine(sk, next_skb, skb); + tcp_highest_sack_replace(sk, next_skb, skb); if (next_skb->ip_summed == CHECKSUM_PARTIAL) skb->ip_summed = CHECKSUM_PARTIAL; diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index cfa374c8b54c..69b8cdb43aa2 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -3349,6 +3349,7 @@ static void addrconf_permanent_addr(struct net_device *dev) if ((ifp->flags & IFA_F_PERMANENT) && fixup_permanent_addr(idev, ifp) < 0) { write_unlock_bh(&idev->lock); + in6_ifa_hold(ifp); ipv6_del_addr(ifp); write_lock_bh(&idev->lock); diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c index 535db8319769..5f5c78b632d0 100644 --- a/net/l2tp/l2tp_ppp.c +++ b/net/l2tp/l2tp_ppp.c @@ -641,6 +641,7 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr, u32 tunnel_id, peer_tunnel_id; u32 session_id, peer_session_id; bool drop_refcnt = false; + bool drop_tunnel = false; int ver = 2; int fd; @@ -709,7 +710,9 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr, if (tunnel_id == 0) goto end; - tunnel = l2tp_tunnel_find(sock_net(sk), tunnel_id); + tunnel = l2tp_tunnel_get(sock_net(sk), tunnel_id); + if (tunnel) + drop_tunnel = true; /* Special case: create tunnel context if session_id and * peer_session_id is 0. Otherwise look up tunnel using supplied @@ -837,6 +840,8 @@ out_no_ppp: end: if (drop_refcnt) l2tp_session_dec_refcount(session); + if (drop_tunnel) + l2tp_tunnel_dec_refcount(tunnel); release_sock(sk); return error; diff --git a/net/psample/psample.c b/net/psample/psample.c index 3a6ad0f438dc..64f95624f219 100644 --- a/net/psample/psample.c +++ b/net/psample/psample.c @@ -296,6 +296,6 @@ static void __exit psample_module_exit(void) module_init(psample_module_init); module_exit(psample_module_exit); -MODULE_AUTHOR("Yotam Gigi <yotamg@mellanox.com>"); +MODULE_AUTHOR("Yotam Gigi <yotam.gi@gmail.com>"); MODULE_DESCRIPTION("netlink channel for packet sampling"); MODULE_LICENSE("GPL v2"); diff --git a/net/sched/act_sample.c b/net/sched/act_sample.c index a9f9a2ccc664..8b5abcd2f32f 100644 --- a/net/sched/act_sample.c +++ b/net/sched/act_sample.c @@ -271,6 +271,6 @@ static void __exit sample_cleanup_module(void) module_init(sample_init_module); module_exit(sample_cleanup_module); -MODULE_AUTHOR("Yotam Gigi <yotamg@mellanox.com>"); +MODULE_AUTHOR("Yotam Gigi <yotam.gi@gmail.com>"); MODULE_DESCRIPTION("Packet sampling action"); MODULE_LICENSE("GPL v2"); diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index d9d54b367d23..2c03fcbc7188 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -322,8 +322,8 @@ static void tcf_block_put_final(struct work_struct *work) struct tcf_block *block = container_of(work, struct tcf_block, work); struct tcf_chain *chain, *tmp; - /* At this point, all the chains should have refcnt == 1. */ rtnl_lock(); + /* Only chain 0 should be still here. */ list_for_each_entry_safe(chain, tmp, &block->chain_list, list) tcf_chain_put(chain); rtnl_unlock(); @@ -331,44 +331,24 @@ static void tcf_block_put_final(struct work_struct *work) } /* XXX: Standalone actions are not allowed to jump to any chain, and bound - * actions should be all removed after flushing. However, filters are destroyed - * in RCU callbacks, we have to hold the chains first, otherwise we would - * always race with RCU callbacks on this list without proper locking. + * actions should be all removed after flushing. However, filters are now + * destroyed in tc filter workqueue with RTNL lock, they can not race here. */ -static void tcf_block_put_deferred(struct work_struct *work) -{ - struct tcf_block *block = container_of(work, struct tcf_block, work); - struct tcf_chain *chain; - - rtnl_lock(); - /* Hold a refcnt for all chains, except 0, in case they are gone. */ - list_for_each_entry(chain, &block->chain_list, list) - if (chain->index) - tcf_chain_hold(chain); - - /* No race on the list, because no chain could be destroyed. */ - list_for_each_entry(chain, &block->chain_list, list) - tcf_chain_flush(chain); - - INIT_WORK(&block->work, tcf_block_put_final); - /* Wait for RCU callbacks to release the reference count and make - * sure their works have been queued before this. - */ - rcu_barrier(); - tcf_queue_work(&block->work); - rtnl_unlock(); -} - void tcf_block_put_ext(struct tcf_block *block, struct tcf_proto __rcu **p_filter_chain, struct Qdisc *q, struct tcf_block_ext_info *ei) { + struct tcf_chain *chain, *tmp; + if (!block) return; tcf_block_offload_unbind(block, q, ei); - INIT_WORK(&block->work, tcf_block_put_deferred); + list_for_each_entry_safe(chain, tmp, &block->chain_list, list) + tcf_chain_flush(chain); + + INIT_WORK(&block->work, tcf_block_put_final); /* Wait for existing RCU callbacks to cool down, make sure their works * have been queued before this. We can not flush pending works here * because we are holding the RTNL lock. diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c index 31a2e6d34dba..73ad8c8ef344 100644 --- a/net/xfrm/xfrm_output.c +++ b/net/xfrm/xfrm_output.c @@ -105,6 +105,9 @@ static int xfrm_output_one(struct sk_buff *skb, int err) if (xfrm_offload(skb)) { x->type_offload->encap(x, skb); } else { + /* Inner headers are invalid now. */ + skb->encapsulation = 0; + err = x->type->output(x, skb); if (err == -EINPROGRESS) goto out; @@ -208,7 +211,6 @@ int xfrm_output(struct sock *sk, struct sk_buff *skb) int err; secpath_reset(skb); - skb->encapsulation = 0; if (xfrm_dev_offload_ok(skb, x)) { struct sec_path *sp; diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index b669c624a1ec..f02b1743b239 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -2075,7 +2075,6 @@ make_dummy_bundle: xdst->num_xfrms = num_xfrms; memcpy(xdst->pols, pols, sizeof(struct xfrm_policy *) * num_pols); - dst_hold(&xdst->u.dst); return xdst; inc_error: diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 12213477cd3a..1f5cee2269af 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -2069,6 +2069,7 @@ int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen if (err >= 0) { xfrm_sk_policy_insert(sk, err, pol); xfrm_pol_put(pol); + __sk_dst_reset(sk); err = 0; } |