diff options
Diffstat (limited to 'net')
63 files changed, 823 insertions, 316 deletions
diff --git a/net/batman-adv/bat_v_elp.c b/net/batman-adv/bat_v_elp.c index e8090f099eb8..ef0dec20c7d8 100644 --- a/net/batman-adv/bat_v_elp.c +++ b/net/batman-adv/bat_v_elp.c | |||
| @@ -104,6 +104,9 @@ static u32 batadv_v_elp_get_throughput(struct batadv_hardif_neigh_node *neigh) | |||
| 104 | 104 | ||
| 105 | ret = cfg80211_get_station(real_netdev, neigh->addr, &sinfo); | 105 | ret = cfg80211_get_station(real_netdev, neigh->addr, &sinfo); |
| 106 | 106 | ||
| 107 | /* free the TID stats immediately */ | ||
| 108 | cfg80211_sinfo_release_content(&sinfo); | ||
| 109 | |||
| 107 | dev_put(real_netdev); | 110 | dev_put(real_netdev); |
| 108 | if (ret == -ENOENT) { | 111 | if (ret == -ENOENT) { |
| 109 | /* Node is not associated anymore! It would be | 112 | /* Node is not associated anymore! It would be |
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c index 508f4416dfc9..415d494cbe22 100644 --- a/net/batman-adv/hard-interface.c +++ b/net/batman-adv/hard-interface.c | |||
| @@ -20,7 +20,6 @@ | |||
| 20 | #include "main.h" | 20 | #include "main.h" |
| 21 | 21 | ||
| 22 | #include <linux/atomic.h> | 22 | #include <linux/atomic.h> |
| 23 | #include <linux/bug.h> | ||
| 24 | #include <linux/byteorder/generic.h> | 23 | #include <linux/byteorder/generic.h> |
| 25 | #include <linux/errno.h> | 24 | #include <linux/errno.h> |
| 26 | #include <linux/gfp.h> | 25 | #include <linux/gfp.h> |
| @@ -179,8 +178,10 @@ static bool batadv_is_on_batman_iface(const struct net_device *net_dev) | |||
| 179 | parent_dev = __dev_get_by_index((struct net *)parent_net, | 178 | parent_dev = __dev_get_by_index((struct net *)parent_net, |
| 180 | dev_get_iflink(net_dev)); | 179 | dev_get_iflink(net_dev)); |
| 181 | /* if we got a NULL parent_dev there is something broken.. */ | 180 | /* if we got a NULL parent_dev there is something broken.. */ |
| 182 | if (WARN(!parent_dev, "Cannot find parent device")) | 181 | if (!parent_dev) { |
| 182 | pr_err("Cannot find parent device\n"); | ||
| 183 | return false; | 183 | return false; |
| 184 | } | ||
| 184 | 185 | ||
| 185 | if (batadv_mutual_parents(net_dev, net, parent_dev, parent_net)) | 186 | if (batadv_mutual_parents(net_dev, net, parent_dev, parent_net)) |
| 186 | return false; | 187 | return false; |
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index 5db5a0a4c959..b85ca809e509 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c | |||
| @@ -221,6 +221,8 @@ static netdev_tx_t batadv_interface_tx(struct sk_buff *skb, | |||
| 221 | 221 | ||
| 222 | netif_trans_update(soft_iface); | 222 | netif_trans_update(soft_iface); |
| 223 | vid = batadv_get_vid(skb, 0); | 223 | vid = batadv_get_vid(skb, 0); |
| 224 | |||
| 225 | skb_reset_mac_header(skb); | ||
| 224 | ethhdr = eth_hdr(skb); | 226 | ethhdr = eth_hdr(skb); |
| 225 | 227 | ||
| 226 | switch (ntohs(ethhdr->h_proto)) { | 228 | switch (ntohs(ethhdr->h_proto)) { |
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index 5e55cef0cec3..6693e209efe8 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c | |||
| @@ -2293,9 +2293,12 @@ static int compat_do_replace(struct net *net, void __user *user, | |||
| 2293 | 2293 | ||
| 2294 | xt_compat_lock(NFPROTO_BRIDGE); | 2294 | xt_compat_lock(NFPROTO_BRIDGE); |
| 2295 | 2295 | ||
| 2296 | ret = xt_compat_init_offsets(NFPROTO_BRIDGE, tmp.nentries); | 2296 | if (tmp.nentries) { |
| 2297 | if (ret < 0) | 2297 | ret = xt_compat_init_offsets(NFPROTO_BRIDGE, tmp.nentries); |
| 2298 | goto out_unlock; | 2298 | if (ret < 0) |
| 2299 | goto out_unlock; | ||
| 2300 | } | ||
| 2301 | |||
| 2299 | ret = compat_copy_entries(entries_tmp, tmp.entries_size, &state); | 2302 | ret = compat_copy_entries(entries_tmp, tmp.entries_size, &state); |
| 2300 | if (ret < 0) | 2303 | if (ret < 0) |
| 2301 | goto out_unlock; | 2304 | goto out_unlock; |
diff --git a/net/core/dev.c b/net/core/dev.c index 82f20022259d..8e276e0192a1 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
| @@ -8712,6 +8712,9 @@ int init_dummy_netdev(struct net_device *dev) | |||
| 8712 | set_bit(__LINK_STATE_PRESENT, &dev->state); | 8712 | set_bit(__LINK_STATE_PRESENT, &dev->state); |
| 8713 | set_bit(__LINK_STATE_START, &dev->state); | 8713 | set_bit(__LINK_STATE_START, &dev->state); |
| 8714 | 8714 | ||
| 8715 | /* napi_busy_loop stats accounting wants this */ | ||
| 8716 | dev_net_set(dev, &init_net); | ||
| 8717 | |||
| 8715 | /* Note : We dont allocate pcpu_refcnt for dummy devices, | 8718 | /* Note : We dont allocate pcpu_refcnt for dummy devices, |
| 8716 | * because users of this 'device' dont need to change | 8719 | * because users of this 'device' dont need to change |
| 8717 | * its refcount. | 8720 | * its refcount. |
diff --git a/net/core/filter.c b/net/core/filter.c index 7559d6835ecb..7a54dc11ac2d 100644 --- a/net/core/filter.c +++ b/net/core/filter.c | |||
| @@ -4112,10 +4112,12 @@ BPF_CALL_5(bpf_setsockopt, struct bpf_sock_ops_kern *, bpf_sock, | |||
| 4112 | /* Only some socketops are supported */ | 4112 | /* Only some socketops are supported */ |
| 4113 | switch (optname) { | 4113 | switch (optname) { |
| 4114 | case SO_RCVBUF: | 4114 | case SO_RCVBUF: |
| 4115 | val = min_t(u32, val, sysctl_rmem_max); | ||
| 4115 | sk->sk_userlocks |= SOCK_RCVBUF_LOCK; | 4116 | sk->sk_userlocks |= SOCK_RCVBUF_LOCK; |
| 4116 | sk->sk_rcvbuf = max_t(int, val * 2, SOCK_MIN_RCVBUF); | 4117 | sk->sk_rcvbuf = max_t(int, val * 2, SOCK_MIN_RCVBUF); |
| 4117 | break; | 4118 | break; |
| 4118 | case SO_SNDBUF: | 4119 | case SO_SNDBUF: |
| 4120 | val = min_t(u32, val, sysctl_wmem_max); | ||
| 4119 | sk->sk_userlocks |= SOCK_SNDBUF_LOCK; | 4121 | sk->sk_userlocks |= SOCK_SNDBUF_LOCK; |
| 4120 | sk->sk_sndbuf = max_t(int, val * 2, SOCK_MIN_SNDBUF); | 4122 | sk->sk_sndbuf = max_t(int, val * 2, SOCK_MIN_SNDBUF); |
| 4121 | break; | 4123 | break; |
diff --git a/net/core/skmsg.c b/net/core/skmsg.c index d6d5c20d7044..8c826603bf36 100644 --- a/net/core/skmsg.c +++ b/net/core/skmsg.c | |||
| @@ -545,8 +545,7 @@ static void sk_psock_destroy_deferred(struct work_struct *gc) | |||
| 545 | struct sk_psock *psock = container_of(gc, struct sk_psock, gc); | 545 | struct sk_psock *psock = container_of(gc, struct sk_psock, gc); |
| 546 | 546 | ||
| 547 | /* No sk_callback_lock since already detached. */ | 547 | /* No sk_callback_lock since already detached. */ |
| 548 | if (psock->parser.enabled) | 548 | strp_done(&psock->parser.strp); |
| 549 | strp_done(&psock->parser.strp); | ||
| 550 | 549 | ||
| 551 | cancel_work_sync(&psock->work); | 550 | cancel_work_sync(&psock->work); |
| 552 | 551 | ||
diff --git a/net/dccp/ccid.h b/net/dccp/ccid.h index 6eb837a47b5c..baaaeb2b2c42 100644 --- a/net/dccp/ccid.h +++ b/net/dccp/ccid.h | |||
| @@ -202,7 +202,7 @@ static inline void ccid_hc_tx_packet_recv(struct ccid *ccid, struct sock *sk, | |||
| 202 | static inline int ccid_hc_tx_parse_options(struct ccid *ccid, struct sock *sk, | 202 | static inline int ccid_hc_tx_parse_options(struct ccid *ccid, struct sock *sk, |
| 203 | u8 pkt, u8 opt, u8 *val, u8 len) | 203 | u8 pkt, u8 opt, u8 *val, u8 len) |
| 204 | { | 204 | { |
| 205 | if (ccid->ccid_ops->ccid_hc_tx_parse_options == NULL) | 205 | if (!ccid || !ccid->ccid_ops->ccid_hc_tx_parse_options) |
| 206 | return 0; | 206 | return 0; |
| 207 | return ccid->ccid_ops->ccid_hc_tx_parse_options(sk, pkt, opt, val, len); | 207 | return ccid->ccid_ops->ccid_hc_tx_parse_options(sk, pkt, opt, val, len); |
| 208 | } | 208 | } |
| @@ -214,7 +214,7 @@ static inline int ccid_hc_tx_parse_options(struct ccid *ccid, struct sock *sk, | |||
| 214 | static inline int ccid_hc_rx_parse_options(struct ccid *ccid, struct sock *sk, | 214 | static inline int ccid_hc_rx_parse_options(struct ccid *ccid, struct sock *sk, |
| 215 | u8 pkt, u8 opt, u8 *val, u8 len) | 215 | u8 pkt, u8 opt, u8 *val, u8 len) |
| 216 | { | 216 | { |
| 217 | if (ccid->ccid_ops->ccid_hc_rx_parse_options == NULL) | 217 | if (!ccid || !ccid->ccid_ops->ccid_hc_rx_parse_options) |
| 218 | return 0; | 218 | return 0; |
| 219 | return ccid->ccid_ops->ccid_hc_rx_parse_options(sk, pkt, opt, val, len); | 219 | return ccid->ccid_ops->ccid_hc_rx_parse_options(sk, pkt, opt, val, len); |
| 220 | } | 220 | } |
diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c index d0b3e69c6b39..0962f9201baa 100644 --- a/net/decnet/dn_dev.c +++ b/net/decnet/dn_dev.c | |||
| @@ -56,7 +56,7 @@ | |||
| 56 | #include <net/dn_neigh.h> | 56 | #include <net/dn_neigh.h> |
| 57 | #include <net/dn_fib.h> | 57 | #include <net/dn_fib.h> |
| 58 | 58 | ||
| 59 | #define DN_IFREQ_SIZE (sizeof(struct ifreq) - sizeof(struct sockaddr) + sizeof(struct sockaddr_dn)) | 59 | #define DN_IFREQ_SIZE (offsetof(struct ifreq, ifr_ifru) + sizeof(struct sockaddr_dn)) |
| 60 | 60 | ||
| 61 | static char dn_rt_all_end_mcast[ETH_ALEN] = {0xAB,0x00,0x00,0x04,0x00,0x00}; | 61 | static char dn_rt_all_end_mcast[ETH_ALEN] = {0xAB,0x00,0x00,0x04,0x00,0x00}; |
| 62 | static char dn_rt_all_rt_mcast[ETH_ALEN] = {0xAB,0x00,0x00,0x03,0x00,0x00}; | 62 | static char dn_rt_all_rt_mcast[ETH_ALEN] = {0xAB,0x00,0x00,0x03,0x00,0x00}; |
diff --git a/net/dsa/master.c b/net/dsa/master.c index 71bb15f491c8..54f5551fb799 100644 --- a/net/dsa/master.c +++ b/net/dsa/master.c | |||
| @@ -205,6 +205,8 @@ static void dsa_master_reset_mtu(struct net_device *dev) | |||
| 205 | rtnl_unlock(); | 205 | rtnl_unlock(); |
| 206 | } | 206 | } |
| 207 | 207 | ||
| 208 | static struct lock_class_key dsa_master_addr_list_lock_key; | ||
| 209 | |||
| 208 | int dsa_master_setup(struct net_device *dev, struct dsa_port *cpu_dp) | 210 | int dsa_master_setup(struct net_device *dev, struct dsa_port *cpu_dp) |
| 209 | { | 211 | { |
| 210 | int ret; | 212 | int ret; |
| @@ -218,6 +220,8 @@ int dsa_master_setup(struct net_device *dev, struct dsa_port *cpu_dp) | |||
| 218 | wmb(); | 220 | wmb(); |
| 219 | 221 | ||
| 220 | dev->dsa_ptr = cpu_dp; | 222 | dev->dsa_ptr = cpu_dp; |
| 223 | lockdep_set_class(&dev->addr_list_lock, | ||
| 224 | &dsa_master_addr_list_lock_key); | ||
| 221 | 225 | ||
| 222 | ret = dsa_master_ethtool_setup(dev); | 226 | ret = dsa_master_ethtool_setup(dev); |
| 223 | if (ret) | 227 | if (ret) |
diff --git a/net/dsa/slave.c b/net/dsa/slave.c index a3fcc1d01615..a1c9fe155057 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c | |||
| @@ -140,11 +140,14 @@ static int dsa_slave_close(struct net_device *dev) | |||
| 140 | static void dsa_slave_change_rx_flags(struct net_device *dev, int change) | 140 | static void dsa_slave_change_rx_flags(struct net_device *dev, int change) |
| 141 | { | 141 | { |
| 142 | struct net_device *master = dsa_slave_to_master(dev); | 142 | struct net_device *master = dsa_slave_to_master(dev); |
| 143 | 143 | if (dev->flags & IFF_UP) { | |
| 144 | if (change & IFF_ALLMULTI) | 144 | if (change & IFF_ALLMULTI) |
| 145 | dev_set_allmulti(master, dev->flags & IFF_ALLMULTI ? 1 : -1); | 145 | dev_set_allmulti(master, |
| 146 | if (change & IFF_PROMISC) | 146 | dev->flags & IFF_ALLMULTI ? 1 : -1); |
| 147 | dev_set_promiscuity(master, dev->flags & IFF_PROMISC ? 1 : -1); | 147 | if (change & IFF_PROMISC) |
| 148 | dev_set_promiscuity(master, | ||
| 149 | dev->flags & IFF_PROMISC ? 1 : -1); | ||
| 150 | } | ||
| 148 | } | 151 | } |
| 149 | 152 | ||
| 150 | static void dsa_slave_set_rx_mode(struct net_device *dev) | 153 | static void dsa_slave_set_rx_mode(struct net_device *dev) |
| @@ -639,7 +642,7 @@ static int dsa_slave_set_eee(struct net_device *dev, struct ethtool_eee *e) | |||
| 639 | int ret; | 642 | int ret; |
| 640 | 643 | ||
| 641 | /* Port's PHY and MAC both need to be EEE capable */ | 644 | /* Port's PHY and MAC both need to be EEE capable */ |
| 642 | if (!dev->phydev && !dp->pl) | 645 | if (!dev->phydev || !dp->pl) |
| 643 | return -ENODEV; | 646 | return -ENODEV; |
| 644 | 647 | ||
| 645 | if (!ds->ops->set_mac_eee) | 648 | if (!ds->ops->set_mac_eee) |
| @@ -659,7 +662,7 @@ static int dsa_slave_get_eee(struct net_device *dev, struct ethtool_eee *e) | |||
| 659 | int ret; | 662 | int ret; |
| 660 | 663 | ||
| 661 | /* Port's PHY and MAC both need to be EEE capable */ | 664 | /* Port's PHY and MAC both need to be EEE capable */ |
| 662 | if (!dev->phydev && !dp->pl) | 665 | if (!dev->phydev || !dp->pl) |
| 663 | return -ENODEV; | 666 | return -ENODEV; |
| 664 | 667 | ||
| 665 | if (!ds->ops->get_mac_eee) | 668 | if (!ds->ops->get_mac_eee) |
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 20a64fe6254b..3978f807fa8b 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c | |||
| @@ -1455,12 +1455,17 @@ static int ipgre_fill_info(struct sk_buff *skb, const struct net_device *dev) | |||
| 1455 | { | 1455 | { |
| 1456 | struct ip_tunnel *t = netdev_priv(dev); | 1456 | struct ip_tunnel *t = netdev_priv(dev); |
| 1457 | struct ip_tunnel_parm *p = &t->parms; | 1457 | struct ip_tunnel_parm *p = &t->parms; |
| 1458 | __be16 o_flags = p->o_flags; | ||
| 1459 | |||
| 1460 | if ((t->erspan_ver == 1 || t->erspan_ver == 2) && | ||
| 1461 | !t->collect_md) | ||
| 1462 | o_flags |= TUNNEL_KEY; | ||
| 1458 | 1463 | ||
| 1459 | if (nla_put_u32(skb, IFLA_GRE_LINK, p->link) || | 1464 | if (nla_put_u32(skb, IFLA_GRE_LINK, p->link) || |
| 1460 | nla_put_be16(skb, IFLA_GRE_IFLAGS, | 1465 | nla_put_be16(skb, IFLA_GRE_IFLAGS, |
| 1461 | gre_tnl_flags_to_gre_flags(p->i_flags)) || | 1466 | gre_tnl_flags_to_gre_flags(p->i_flags)) || |
| 1462 | nla_put_be16(skb, IFLA_GRE_OFLAGS, | 1467 | nla_put_be16(skb, IFLA_GRE_OFLAGS, |
| 1463 | gre_tnl_flags_to_gre_flags(p->o_flags)) || | 1468 | gre_tnl_flags_to_gre_flags(o_flags)) || |
| 1464 | nla_put_be32(skb, IFLA_GRE_IKEY, p->i_key) || | 1469 | nla_put_be32(skb, IFLA_GRE_IKEY, p->i_key) || |
| 1465 | nla_put_be32(skb, IFLA_GRE_OKEY, p->o_key) || | 1470 | nla_put_be32(skb, IFLA_GRE_OKEY, p->o_key) || |
| 1466 | nla_put_in_addr(skb, IFLA_GRE_LOCAL, p->iph.saddr) || | 1471 | nla_put_in_addr(skb, IFLA_GRE_LOCAL, p->iph.saddr) || |
diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c index d7b43e700023..68a21bf75dd0 100644 --- a/net/ipv4/ip_vti.c +++ b/net/ipv4/ip_vti.c | |||
| @@ -74,6 +74,33 @@ drop: | |||
| 74 | return 0; | 74 | return 0; |
| 75 | } | 75 | } |
| 76 | 76 | ||
| 77 | static int vti_input_ipip(struct sk_buff *skb, int nexthdr, __be32 spi, | ||
| 78 | int encap_type) | ||
| 79 | { | ||
| 80 | struct ip_tunnel *tunnel; | ||
| 81 | const struct iphdr *iph = ip_hdr(skb); | ||
| 82 | struct net *net = dev_net(skb->dev); | ||
| 83 | struct ip_tunnel_net *itn = net_generic(net, vti_net_id); | ||
| 84 | |||
| 85 | tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, TUNNEL_NO_KEY, | ||
| 86 | iph->saddr, iph->daddr, 0); | ||
| 87 | if (tunnel) { | ||
| 88 | if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) | ||
| 89 | goto drop; | ||
| 90 | |||
| 91 | XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4 = tunnel; | ||
| 92 | |||
| 93 | skb->dev = tunnel->dev; | ||
| 94 | |||
| 95 | return xfrm_input(skb, nexthdr, spi, encap_type); | ||
| 96 | } | ||
| 97 | |||
| 98 | return -EINVAL; | ||
| 99 | drop: | ||
| 100 | kfree_skb(skb); | ||
| 101 | return 0; | ||
| 102 | } | ||
| 103 | |||
| 77 | static int vti_rcv(struct sk_buff *skb) | 104 | static int vti_rcv(struct sk_buff *skb) |
| 78 | { | 105 | { |
| 79 | XFRM_SPI_SKB_CB(skb)->family = AF_INET; | 106 | XFRM_SPI_SKB_CB(skb)->family = AF_INET; |
| @@ -82,6 +109,14 @@ static int vti_rcv(struct sk_buff *skb) | |||
| 82 | return vti_input(skb, ip_hdr(skb)->protocol, 0, 0); | 109 | return vti_input(skb, ip_hdr(skb)->protocol, 0, 0); |
| 83 | } | 110 | } |
| 84 | 111 | ||
| 112 | static int vti_rcv_ipip(struct sk_buff *skb) | ||
| 113 | { | ||
| 114 | XFRM_SPI_SKB_CB(skb)->family = AF_INET; | ||
| 115 | XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct iphdr, daddr); | ||
| 116 | |||
| 117 | return vti_input_ipip(skb, ip_hdr(skb)->protocol, ip_hdr(skb)->saddr, 0); | ||
| 118 | } | ||
| 119 | |||
| 85 | static int vti_rcv_cb(struct sk_buff *skb, int err) | 120 | static int vti_rcv_cb(struct sk_buff *skb, int err) |
| 86 | { | 121 | { |
| 87 | unsigned short family; | 122 | unsigned short family; |
| @@ -435,6 +470,12 @@ static struct xfrm4_protocol vti_ipcomp4_protocol __read_mostly = { | |||
| 435 | .priority = 100, | 470 | .priority = 100, |
| 436 | }; | 471 | }; |
| 437 | 472 | ||
| 473 | static struct xfrm_tunnel ipip_handler __read_mostly = { | ||
| 474 | .handler = vti_rcv_ipip, | ||
| 475 | .err_handler = vti4_err, | ||
| 476 | .priority = 0, | ||
| 477 | }; | ||
| 478 | |||
| 438 | static int __net_init vti_init_net(struct net *net) | 479 | static int __net_init vti_init_net(struct net *net) |
| 439 | { | 480 | { |
| 440 | int err; | 481 | int err; |
| @@ -603,6 +644,13 @@ static int __init vti_init(void) | |||
| 603 | if (err < 0) | 644 | if (err < 0) |
| 604 | goto xfrm_proto_comp_failed; | 645 | goto xfrm_proto_comp_failed; |
| 605 | 646 | ||
| 647 | msg = "ipip tunnel"; | ||
| 648 | err = xfrm4_tunnel_register(&ipip_handler, AF_INET); | ||
| 649 | if (err < 0) { | ||
| 650 | pr_info("%s: cant't register tunnel\n",__func__); | ||
| 651 | goto xfrm_tunnel_failed; | ||
| 652 | } | ||
| 653 | |||
| 606 | msg = "netlink interface"; | 654 | msg = "netlink interface"; |
| 607 | err = rtnl_link_register(&vti_link_ops); | 655 | err = rtnl_link_register(&vti_link_ops); |
| 608 | if (err < 0) | 656 | if (err < 0) |
| @@ -612,6 +660,8 @@ static int __init vti_init(void) | |||
| 612 | 660 | ||
| 613 | rtnl_link_failed: | 661 | rtnl_link_failed: |
| 614 | xfrm4_protocol_deregister(&vti_ipcomp4_protocol, IPPROTO_COMP); | 662 | xfrm4_protocol_deregister(&vti_ipcomp4_protocol, IPPROTO_COMP); |
| 663 | xfrm_tunnel_failed: | ||
| 664 | xfrm4_tunnel_deregister(&ipip_handler, AF_INET); | ||
| 615 | xfrm_proto_comp_failed: | 665 | xfrm_proto_comp_failed: |
| 616 | xfrm4_protocol_deregister(&vti_ah4_protocol, IPPROTO_AH); | 666 | xfrm4_protocol_deregister(&vti_ah4_protocol, IPPROTO_AH); |
| 617 | xfrm_proto_ah_failed: | 667 | xfrm_proto_ah_failed: |
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c index b61977db9b7f..2a909e5f9ba0 100644 --- a/net/ipv4/netfilter/ipt_CLUSTERIP.c +++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c | |||
| @@ -846,9 +846,9 @@ static int clusterip_net_init(struct net *net) | |||
| 846 | 846 | ||
| 847 | static void clusterip_net_exit(struct net *net) | 847 | static void clusterip_net_exit(struct net *net) |
| 848 | { | 848 | { |
| 849 | #ifdef CONFIG_PROC_FS | ||
| 849 | struct clusterip_net *cn = clusterip_pernet(net); | 850 | struct clusterip_net *cn = clusterip_pernet(net); |
| 850 | 851 | ||
| 851 | #ifdef CONFIG_PROC_FS | ||
| 852 | mutex_lock(&cn->mutex); | 852 | mutex_lock(&cn->mutex); |
| 853 | proc_remove(cn->procdir); | 853 | proc_remove(cn->procdir); |
| 854 | cn->procdir = NULL; | 854 | cn->procdir = NULL; |
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c index 4416368dbd49..801a9a0c217e 100644 --- a/net/ipv6/ip6_gre.c +++ b/net/ipv6/ip6_gre.c | |||
| @@ -2098,12 +2098,17 @@ static int ip6gre_fill_info(struct sk_buff *skb, const struct net_device *dev) | |||
| 2098 | { | 2098 | { |
| 2099 | struct ip6_tnl *t = netdev_priv(dev); | 2099 | struct ip6_tnl *t = netdev_priv(dev); |
| 2100 | struct __ip6_tnl_parm *p = &t->parms; | 2100 | struct __ip6_tnl_parm *p = &t->parms; |
| 2101 | __be16 o_flags = p->o_flags; | ||
| 2102 | |||
| 2103 | if ((p->erspan_ver == 1 || p->erspan_ver == 2) && | ||
| 2104 | !p->collect_md) | ||
| 2105 | o_flags |= TUNNEL_KEY; | ||
| 2101 | 2106 | ||
| 2102 | if (nla_put_u32(skb, IFLA_GRE_LINK, p->link) || | 2107 | if (nla_put_u32(skb, IFLA_GRE_LINK, p->link) || |
| 2103 | nla_put_be16(skb, IFLA_GRE_IFLAGS, | 2108 | nla_put_be16(skb, IFLA_GRE_IFLAGS, |
| 2104 | gre_tnl_flags_to_gre_flags(p->i_flags)) || | 2109 | gre_tnl_flags_to_gre_flags(p->i_flags)) || |
| 2105 | nla_put_be16(skb, IFLA_GRE_OFLAGS, | 2110 | nla_put_be16(skb, IFLA_GRE_OFLAGS, |
| 2106 | gre_tnl_flags_to_gre_flags(p->o_flags)) || | 2111 | gre_tnl_flags_to_gre_flags(o_flags)) || |
| 2107 | nla_put_be32(skb, IFLA_GRE_IKEY, p->i_key) || | 2112 | nla_put_be32(skb, IFLA_GRE_IKEY, p->i_key) || |
| 2108 | nla_put_be32(skb, IFLA_GRE_OKEY, p->o_key) || | 2113 | nla_put_be32(skb, IFLA_GRE_OKEY, p->o_key) || |
| 2109 | nla_put_in6_addr(skb, IFLA_GRE_LOCAL, &p->laddr) || | 2114 | nla_put_in6_addr(skb, IFLA_GRE_LOCAL, &p->laddr) || |
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index 30337b38274b..cc01aa3f2b5e 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c | |||
| @@ -1516,6 +1516,9 @@ static void mroute_clean_tables(struct mr_table *mrt, bool all) | |||
| 1516 | continue; | 1516 | continue; |
| 1517 | rhltable_remove(&mrt->mfc_hash, &c->mnode, ip6mr_rht_params); | 1517 | rhltable_remove(&mrt->mfc_hash, &c->mnode, ip6mr_rht_params); |
| 1518 | list_del_rcu(&c->list); | 1518 | list_del_rcu(&c->list); |
| 1519 | call_ip6mr_mfc_entry_notifiers(read_pnet(&mrt->net), | ||
| 1520 | FIB_EVENT_ENTRY_DEL, | ||
| 1521 | (struct mfc6_cache *)c, mrt->id); | ||
| 1519 | mr6_netlink_event(mrt, (struct mfc6_cache *)c, RTM_DELROUTE); | 1522 | mr6_netlink_event(mrt, (struct mfc6_cache *)c, RTM_DELROUTE); |
| 1520 | mr_cache_put(c); | 1523 | mr_cache_put(c); |
| 1521 | } | 1524 | } |
| @@ -1524,10 +1527,6 @@ static void mroute_clean_tables(struct mr_table *mrt, bool all) | |||
| 1524 | spin_lock_bh(&mfc_unres_lock); | 1527 | spin_lock_bh(&mfc_unres_lock); |
| 1525 | list_for_each_entry_safe(c, tmp, &mrt->mfc_unres_queue, list) { | 1528 | list_for_each_entry_safe(c, tmp, &mrt->mfc_unres_queue, list) { |
| 1526 | list_del(&c->list); | 1529 | list_del(&c->list); |
| 1527 | call_ip6mr_mfc_entry_notifiers(read_pnet(&mrt->net), | ||
| 1528 | FIB_EVENT_ENTRY_DEL, | ||
| 1529 | (struct mfc6_cache *)c, | ||
| 1530 | mrt->id); | ||
| 1531 | mr6_netlink_event(mrt, (struct mfc6_cache *)c, | 1530 | mr6_netlink_event(mrt, (struct mfc6_cache *)c, |
| 1532 | RTM_DELROUTE); | 1531 | RTM_DELROUTE); |
| 1533 | ip6mr_destroy_unres(mrt, (struct mfc6_cache *)c); | 1532 | ip6mr_destroy_unres(mrt, (struct mfc6_cache *)c); |
diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c index 8b075f0bc351..6d0b1f3e927b 100644 --- a/net/ipv6/netfilter.c +++ b/net/ipv6/netfilter.c | |||
| @@ -23,9 +23,11 @@ int ip6_route_me_harder(struct net *net, struct sk_buff *skb) | |||
| 23 | struct sock *sk = sk_to_full_sk(skb->sk); | 23 | struct sock *sk = sk_to_full_sk(skb->sk); |
| 24 | unsigned int hh_len; | 24 | unsigned int hh_len; |
| 25 | struct dst_entry *dst; | 25 | struct dst_entry *dst; |
| 26 | int strict = (ipv6_addr_type(&iph->daddr) & | ||
| 27 | (IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL)); | ||
| 26 | struct flowi6 fl6 = { | 28 | struct flowi6 fl6 = { |
| 27 | .flowi6_oif = sk && sk->sk_bound_dev_if ? sk->sk_bound_dev_if : | 29 | .flowi6_oif = sk && sk->sk_bound_dev_if ? sk->sk_bound_dev_if : |
| 28 | rt6_need_strict(&iph->daddr) ? skb_dst(skb)->dev->ifindex : 0, | 30 | strict ? skb_dst(skb)->dev->ifindex : 0, |
| 29 | .flowi6_mark = skb->mark, | 31 | .flowi6_mark = skb->mark, |
| 30 | .flowi6_uid = sock_net_uid(net, sk), | 32 | .flowi6_uid = sock_net_uid(net, sk), |
| 31 | .daddr = iph->daddr, | 33 | .daddr = iph->daddr, |
diff --git a/net/ipv6/seg6_iptunnel.c b/net/ipv6/seg6_iptunnel.c index 8181ee7e1e27..ee5403cbe655 100644 --- a/net/ipv6/seg6_iptunnel.c +++ b/net/ipv6/seg6_iptunnel.c | |||
| @@ -146,6 +146,8 @@ int seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh, int proto) | |||
| 146 | } else { | 146 | } else { |
| 147 | ip6_flow_hdr(hdr, 0, flowlabel); | 147 | ip6_flow_hdr(hdr, 0, flowlabel); |
| 148 | hdr->hop_limit = ip6_dst_hoplimit(skb_dst(skb)); | 148 | hdr->hop_limit = ip6_dst_hoplimit(skb_dst(skb)); |
| 149 | |||
| 150 | memset(IP6CB(skb), 0, sizeof(*IP6CB(skb))); | ||
| 149 | } | 151 | } |
| 150 | 152 | ||
| 151 | hdr->nexthdr = NEXTHDR_ROUTING; | 153 | hdr->nexthdr = NEXTHDR_ROUTING; |
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 1e03305c0549..e8a1dabef803 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
| @@ -546,7 +546,8 @@ static int ipip6_err(struct sk_buff *skb, u32 info) | |||
| 546 | } | 546 | } |
| 547 | 547 | ||
| 548 | err = 0; | 548 | err = 0; |
| 549 | if (!ip6_err_gen_icmpv6_unreach(skb, iph->ihl * 4, type, data_len)) | 549 | if (__in6_dev_get(skb->dev) && |
| 550 | !ip6_err_gen_icmpv6_unreach(skb, iph->ihl * 4, type, data_len)) | ||
| 550 | goto out; | 551 | goto out; |
| 551 | 552 | ||
| 552 | if (t->parms.iph.daddr == 0) | 553 | if (t->parms.iph.daddr == 0) |
diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c index 26f1d435696a..fed6becc5daf 100644 --- a/net/l2tp/l2tp_core.c +++ b/net/l2tp/l2tp_core.c | |||
| @@ -83,8 +83,7 @@ | |||
| 83 | #define L2TP_SLFLAG_S 0x40000000 | 83 | #define L2TP_SLFLAG_S 0x40000000 |
| 84 | #define L2TP_SL_SEQ_MASK 0x00ffffff | 84 | #define L2TP_SL_SEQ_MASK 0x00ffffff |
| 85 | 85 | ||
| 86 | #define L2TP_HDR_SIZE_SEQ 10 | 86 | #define L2TP_HDR_SIZE_MAX 14 |
| 87 | #define L2TP_HDR_SIZE_NOSEQ 6 | ||
| 88 | 87 | ||
| 89 | /* Default trace flags */ | 88 | /* Default trace flags */ |
| 90 | #define L2TP_DEFAULT_DEBUG_FLAGS 0 | 89 | #define L2TP_DEFAULT_DEBUG_FLAGS 0 |
| @@ -808,7 +807,7 @@ static int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb) | |||
| 808 | __skb_pull(skb, sizeof(struct udphdr)); | 807 | __skb_pull(skb, sizeof(struct udphdr)); |
| 809 | 808 | ||
| 810 | /* Short packet? */ | 809 | /* Short packet? */ |
| 811 | if (!pskb_may_pull(skb, L2TP_HDR_SIZE_SEQ)) { | 810 | if (!pskb_may_pull(skb, L2TP_HDR_SIZE_MAX)) { |
| 812 | l2tp_info(tunnel, L2TP_MSG_DATA, | 811 | l2tp_info(tunnel, L2TP_MSG_DATA, |
| 813 | "%s: recv short packet (len=%d)\n", | 812 | "%s: recv short packet (len=%d)\n", |
| 814 | tunnel->name, skb->len); | 813 | tunnel->name, skb->len); |
| @@ -884,6 +883,10 @@ static int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb) | |||
| 884 | goto error; | 883 | goto error; |
| 885 | } | 884 | } |
| 886 | 885 | ||
| 886 | if (tunnel->version == L2TP_HDR_VER_3 && | ||
| 887 | l2tp_v3_ensure_opt_in_linear(session, skb, &ptr, &optr)) | ||
| 888 | goto error; | ||
| 889 | |||
| 887 | l2tp_recv_common(session, skb, ptr, optr, hdrflags, length); | 890 | l2tp_recv_common(session, skb, ptr, optr, hdrflags, length); |
| 888 | l2tp_session_dec_refcount(session); | 891 | l2tp_session_dec_refcount(session); |
| 889 | 892 | ||
diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h index 9c9afe94d389..b2ce90260c35 100644 --- a/net/l2tp/l2tp_core.h +++ b/net/l2tp/l2tp_core.h | |||
| @@ -301,6 +301,26 @@ static inline bool l2tp_tunnel_uses_xfrm(const struct l2tp_tunnel *tunnel) | |||
| 301 | } | 301 | } |
| 302 | #endif | 302 | #endif |
| 303 | 303 | ||
| 304 | static inline int l2tp_v3_ensure_opt_in_linear(struct l2tp_session *session, struct sk_buff *skb, | ||
| 305 | unsigned char **ptr, unsigned char **optr) | ||
| 306 | { | ||
| 307 | int opt_len = session->peer_cookie_len + l2tp_get_l2specific_len(session); | ||
| 308 | |||
| 309 | if (opt_len > 0) { | ||
| 310 | int off = *ptr - *optr; | ||
| 311 | |||
| 312 | if (!pskb_may_pull(skb, off + opt_len)) | ||
| 313 | return -1; | ||
| 314 | |||
| 315 | if (skb->data != *optr) { | ||
| 316 | *optr = skb->data; | ||
| 317 | *ptr = skb->data + off; | ||
| 318 | } | ||
| 319 | } | ||
| 320 | |||
| 321 | return 0; | ||
| 322 | } | ||
| 323 | |||
| 304 | #define l2tp_printk(ptr, type, func, fmt, ...) \ | 324 | #define l2tp_printk(ptr, type, func, fmt, ...) \ |
| 305 | do { \ | 325 | do { \ |
| 306 | if (((ptr)->debug) & (type)) \ | 326 | if (((ptr)->debug) & (type)) \ |
diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c index 35f6f86d4dcc..d4c60523c549 100644 --- a/net/l2tp/l2tp_ip.c +++ b/net/l2tp/l2tp_ip.c | |||
| @@ -165,6 +165,9 @@ static int l2tp_ip_recv(struct sk_buff *skb) | |||
| 165 | print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, ptr, length); | 165 | print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, ptr, length); |
| 166 | } | 166 | } |
| 167 | 167 | ||
| 168 | if (l2tp_v3_ensure_opt_in_linear(session, skb, &ptr, &optr)) | ||
| 169 | goto discard_sess; | ||
| 170 | |||
| 168 | l2tp_recv_common(session, skb, ptr, optr, 0, skb->len); | 171 | l2tp_recv_common(session, skb, ptr, optr, 0, skb->len); |
| 169 | l2tp_session_dec_refcount(session); | 172 | l2tp_session_dec_refcount(session); |
| 170 | 173 | ||
diff --git a/net/l2tp/l2tp_ip6.c b/net/l2tp/l2tp_ip6.c index 237f1a4a0b0c..0ae6899edac0 100644 --- a/net/l2tp/l2tp_ip6.c +++ b/net/l2tp/l2tp_ip6.c | |||
| @@ -178,6 +178,9 @@ static int l2tp_ip6_recv(struct sk_buff *skb) | |||
| 178 | print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, ptr, length); | 178 | print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, ptr, length); |
| 179 | } | 179 | } |
| 180 | 180 | ||
| 181 | if (l2tp_v3_ensure_opt_in_linear(session, skb, &ptr, &optr)) | ||
| 182 | goto discard_sess; | ||
| 183 | |||
| 181 | l2tp_recv_common(session, skb, ptr, optr, 0, skb->len); | 184 | l2tp_recv_common(session, skb, ptr, optr, 0, skb->len); |
| 182 | l2tp_session_dec_refcount(session); | 185 | l2tp_session_dec_refcount(session); |
| 183 | 186 | ||
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index f170d6c6629a..928f13a208b0 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
| @@ -1938,9 +1938,16 @@ static int ieee80211_skb_resize(struct ieee80211_sub_if_data *sdata, | |||
| 1938 | int head_need, bool may_encrypt) | 1938 | int head_need, bool may_encrypt) |
| 1939 | { | 1939 | { |
| 1940 | struct ieee80211_local *local = sdata->local; | 1940 | struct ieee80211_local *local = sdata->local; |
| 1941 | struct ieee80211_hdr *hdr; | ||
| 1942 | bool enc_tailroom; | ||
| 1941 | int tail_need = 0; | 1943 | int tail_need = 0; |
| 1942 | 1944 | ||
| 1943 | if (may_encrypt && sdata->crypto_tx_tailroom_needed_cnt) { | 1945 | hdr = (struct ieee80211_hdr *) skb->data; |
| 1946 | enc_tailroom = may_encrypt && | ||
| 1947 | (sdata->crypto_tx_tailroom_needed_cnt || | ||
| 1948 | ieee80211_is_mgmt(hdr->frame_control)); | ||
| 1949 | |||
| 1950 | if (enc_tailroom) { | ||
| 1944 | tail_need = IEEE80211_ENCRYPT_TAILROOM; | 1951 | tail_need = IEEE80211_ENCRYPT_TAILROOM; |
| 1945 | tail_need -= skb_tailroom(skb); | 1952 | tail_need -= skb_tailroom(skb); |
| 1946 | tail_need = max_t(int, tail_need, 0); | 1953 | tail_need = max_t(int, tail_need, 0); |
| @@ -1948,8 +1955,7 @@ static int ieee80211_skb_resize(struct ieee80211_sub_if_data *sdata, | |||
| 1948 | 1955 | ||
| 1949 | if (skb_cloned(skb) && | 1956 | if (skb_cloned(skb) && |
| 1950 | (!ieee80211_hw_check(&local->hw, SUPPORTS_CLONED_SKBS) || | 1957 | (!ieee80211_hw_check(&local->hw, SUPPORTS_CLONED_SKBS) || |
| 1951 | !skb_clone_writable(skb, ETH_HLEN) || | 1958 | !skb_clone_writable(skb, ETH_HLEN) || enc_tailroom)) |
| 1952 | (may_encrypt && sdata->crypto_tx_tailroom_needed_cnt))) | ||
| 1953 | I802_DEBUG_INC(local->tx_expand_skb_head_cloned); | 1959 | I802_DEBUG_INC(local->tx_expand_skb_head_cloned); |
| 1954 | else if (head_need || tail_need) | 1960 | else if (head_need || tail_need) |
| 1955 | I802_DEBUG_INC(local->tx_expand_skb_head); | 1961 | I802_DEBUG_INC(local->tx_expand_skb_head); |
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index 432141f04af3..7d6318664eb2 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c | |||
| @@ -2221,6 +2221,18 @@ static int ip_vs_set_timeout(struct netns_ipvs *ipvs, struct ip_vs_timeout_user | |||
| 2221 | u->udp_timeout); | 2221 | u->udp_timeout); |
| 2222 | 2222 | ||
| 2223 | #ifdef CONFIG_IP_VS_PROTO_TCP | 2223 | #ifdef CONFIG_IP_VS_PROTO_TCP |
| 2224 | if (u->tcp_timeout < 0 || u->tcp_timeout > (INT_MAX / HZ) || | ||
| 2225 | u->tcp_fin_timeout < 0 || u->tcp_fin_timeout > (INT_MAX / HZ)) { | ||
| 2226 | return -EINVAL; | ||
| 2227 | } | ||
| 2228 | #endif | ||
| 2229 | |||
| 2230 | #ifdef CONFIG_IP_VS_PROTO_UDP | ||
| 2231 | if (u->udp_timeout < 0 || u->udp_timeout > (INT_MAX / HZ)) | ||
| 2232 | return -EINVAL; | ||
| 2233 | #endif | ||
| 2234 | |||
| 2235 | #ifdef CONFIG_IP_VS_PROTO_TCP | ||
| 2224 | if (u->tcp_timeout) { | 2236 | if (u->tcp_timeout) { |
| 2225 | pd = ip_vs_proto_data_get(ipvs, IPPROTO_TCP); | 2237 | pd = ip_vs_proto_data_get(ipvs, IPPROTO_TCP); |
| 2226 | pd->timeout_table[IP_VS_TCP_S_ESTABLISHED] | 2238 | pd->timeout_table[IP_VS_TCP_S_ESTABLISHED] |
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 741b533148ba..db4d46332e86 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c | |||
| @@ -1007,6 +1007,22 @@ nf_conntrack_tuple_taken(const struct nf_conntrack_tuple *tuple, | |||
| 1007 | } | 1007 | } |
| 1008 | 1008 | ||
| 1009 | if (nf_ct_key_equal(h, tuple, zone, net)) { | 1009 | if (nf_ct_key_equal(h, tuple, zone, net)) { |
| 1010 | /* Tuple is taken already, so caller will need to find | ||
| 1011 | * a new source port to use. | ||
| 1012 | * | ||
| 1013 | * Only exception: | ||
| 1014 | * If the *original tuples* are identical, then both | ||
| 1015 | * conntracks refer to the same flow. | ||
| 1016 | * This is a rare situation, it can occur e.g. when | ||
| 1017 | * more than one UDP packet is sent from same socket | ||
| 1018 | * in different threads. | ||
| 1019 | * | ||
| 1020 | * Let nf_ct_resolve_clash() deal with this later. | ||
| 1021 | */ | ||
| 1022 | if (nf_ct_tuple_equal(&ignored_conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple, | ||
| 1023 | &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple)) | ||
| 1024 | continue; | ||
| 1025 | |||
| 1010 | NF_CT_STAT_INC_ATOMIC(net, found); | 1026 | NF_CT_STAT_INC_ATOMIC(net, found); |
| 1011 | rcu_read_unlock(); | 1027 | rcu_read_unlock(); |
| 1012 | return 1; | 1028 | return 1; |
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index fb07f6cfc719..5a92f23f179f 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c | |||
| @@ -116,6 +116,23 @@ static void nft_trans_destroy(struct nft_trans *trans) | |||
| 116 | kfree(trans); | 116 | kfree(trans); |
| 117 | } | 117 | } |
| 118 | 118 | ||
| 119 | static void nft_set_trans_bind(const struct nft_ctx *ctx, struct nft_set *set) | ||
| 120 | { | ||
| 121 | struct net *net = ctx->net; | ||
| 122 | struct nft_trans *trans; | ||
| 123 | |||
| 124 | if (!nft_set_is_anonymous(set)) | ||
| 125 | return; | ||
| 126 | |||
| 127 | list_for_each_entry_reverse(trans, &net->nft.commit_list, list) { | ||
| 128 | if (trans->msg_type == NFT_MSG_NEWSET && | ||
| 129 | nft_trans_set(trans) == set) { | ||
| 130 | nft_trans_set_bound(trans) = true; | ||
| 131 | break; | ||
| 132 | } | ||
| 133 | } | ||
| 134 | } | ||
| 135 | |||
| 119 | static int nf_tables_register_hook(struct net *net, | 136 | static int nf_tables_register_hook(struct net *net, |
| 120 | const struct nft_table *table, | 137 | const struct nft_table *table, |
| 121 | struct nft_chain *chain) | 138 | struct nft_chain *chain) |
| @@ -211,18 +228,6 @@ static int nft_delchain(struct nft_ctx *ctx) | |||
| 211 | return err; | 228 | return err; |
| 212 | } | 229 | } |
| 213 | 230 | ||
| 214 | /* either expr ops provide both activate/deactivate, or neither */ | ||
| 215 | static bool nft_expr_check_ops(const struct nft_expr_ops *ops) | ||
| 216 | { | ||
| 217 | if (!ops) | ||
| 218 | return true; | ||
| 219 | |||
| 220 | if (WARN_ON_ONCE((!ops->activate ^ !ops->deactivate))) | ||
| 221 | return false; | ||
| 222 | |||
| 223 | return true; | ||
| 224 | } | ||
| 225 | |||
| 226 | static void nft_rule_expr_activate(const struct nft_ctx *ctx, | 231 | static void nft_rule_expr_activate(const struct nft_ctx *ctx, |
| 227 | struct nft_rule *rule) | 232 | struct nft_rule *rule) |
| 228 | { | 233 | { |
| @@ -238,14 +243,15 @@ static void nft_rule_expr_activate(const struct nft_ctx *ctx, | |||
| 238 | } | 243 | } |
| 239 | 244 | ||
| 240 | static void nft_rule_expr_deactivate(const struct nft_ctx *ctx, | 245 | static void nft_rule_expr_deactivate(const struct nft_ctx *ctx, |
| 241 | struct nft_rule *rule) | 246 | struct nft_rule *rule, |
| 247 | enum nft_trans_phase phase) | ||
| 242 | { | 248 | { |
| 243 | struct nft_expr *expr; | 249 | struct nft_expr *expr; |
| 244 | 250 | ||
| 245 | expr = nft_expr_first(rule); | 251 | expr = nft_expr_first(rule); |
| 246 | while (expr != nft_expr_last(rule) && expr->ops) { | 252 | while (expr != nft_expr_last(rule) && expr->ops) { |
| 247 | if (expr->ops->deactivate) | 253 | if (expr->ops->deactivate) |
| 248 | expr->ops->deactivate(ctx, expr); | 254 | expr->ops->deactivate(ctx, expr, phase); |
| 249 | 255 | ||
| 250 | expr = nft_expr_next(expr); | 256 | expr = nft_expr_next(expr); |
| 251 | } | 257 | } |
| @@ -296,7 +302,7 @@ static int nft_delrule(struct nft_ctx *ctx, struct nft_rule *rule) | |||
| 296 | nft_trans_destroy(trans); | 302 | nft_trans_destroy(trans); |
| 297 | return err; | 303 | return err; |
| 298 | } | 304 | } |
| 299 | nft_rule_expr_deactivate(ctx, rule); | 305 | nft_rule_expr_deactivate(ctx, rule, NFT_TRANS_PREPARE); |
| 300 | 306 | ||
| 301 | return 0; | 307 | return 0; |
| 302 | } | 308 | } |
| @@ -1929,9 +1935,6 @@ static int nf_tables_delchain(struct net *net, struct sock *nlsk, | |||
| 1929 | */ | 1935 | */ |
| 1930 | int nft_register_expr(struct nft_expr_type *type) | 1936 | int nft_register_expr(struct nft_expr_type *type) |
| 1931 | { | 1937 | { |
| 1932 | if (!nft_expr_check_ops(type->ops)) | ||
| 1933 | return -EINVAL; | ||
| 1934 | |||
| 1935 | nfnl_lock(NFNL_SUBSYS_NFTABLES); | 1938 | nfnl_lock(NFNL_SUBSYS_NFTABLES); |
| 1936 | if (type->family == NFPROTO_UNSPEC) | 1939 | if (type->family == NFPROTO_UNSPEC) |
| 1937 | list_add_tail_rcu(&type->list, &nf_tables_expressions); | 1940 | list_add_tail_rcu(&type->list, &nf_tables_expressions); |
| @@ -2079,10 +2082,6 @@ static int nf_tables_expr_parse(const struct nft_ctx *ctx, | |||
| 2079 | err = PTR_ERR(ops); | 2082 | err = PTR_ERR(ops); |
| 2080 | goto err1; | 2083 | goto err1; |
| 2081 | } | 2084 | } |
| 2082 | if (!nft_expr_check_ops(ops)) { | ||
| 2083 | err = -EINVAL; | ||
| 2084 | goto err1; | ||
| 2085 | } | ||
| 2086 | } else | 2085 | } else |
| 2087 | ops = type->ops; | 2086 | ops = type->ops; |
| 2088 | 2087 | ||
| @@ -2511,7 +2510,7 @@ static void nf_tables_rule_destroy(const struct nft_ctx *ctx, | |||
| 2511 | static void nf_tables_rule_release(const struct nft_ctx *ctx, | 2510 | static void nf_tables_rule_release(const struct nft_ctx *ctx, |
| 2512 | struct nft_rule *rule) | 2511 | struct nft_rule *rule) |
| 2513 | { | 2512 | { |
| 2514 | nft_rule_expr_deactivate(ctx, rule); | 2513 | nft_rule_expr_deactivate(ctx, rule, NFT_TRANS_RELEASE); |
| 2515 | nf_tables_rule_destroy(ctx, rule); | 2514 | nf_tables_rule_destroy(ctx, rule); |
| 2516 | } | 2515 | } |
| 2517 | 2516 | ||
| @@ -3708,39 +3707,30 @@ int nf_tables_bind_set(const struct nft_ctx *ctx, struct nft_set *set, | |||
| 3708 | bind: | 3707 | bind: |
| 3709 | binding->chain = ctx->chain; | 3708 | binding->chain = ctx->chain; |
| 3710 | list_add_tail_rcu(&binding->list, &set->bindings); | 3709 | list_add_tail_rcu(&binding->list, &set->bindings); |
| 3710 | nft_set_trans_bind(ctx, set); | ||
| 3711 | |||
| 3711 | return 0; | 3712 | return 0; |
| 3712 | } | 3713 | } |
| 3713 | EXPORT_SYMBOL_GPL(nf_tables_bind_set); | 3714 | EXPORT_SYMBOL_GPL(nf_tables_bind_set); |
| 3714 | 3715 | ||
| 3715 | void nf_tables_rebind_set(const struct nft_ctx *ctx, struct nft_set *set, | ||
| 3716 | struct nft_set_binding *binding) | ||
| 3717 | { | ||
| 3718 | if (list_empty(&set->bindings) && nft_set_is_anonymous(set) && | ||
| 3719 | nft_is_active(ctx->net, set)) | ||
| 3720 | list_add_tail_rcu(&set->list, &ctx->table->sets); | ||
| 3721 | |||
| 3722 | list_add_tail_rcu(&binding->list, &set->bindings); | ||
| 3723 | } | ||
| 3724 | EXPORT_SYMBOL_GPL(nf_tables_rebind_set); | ||
| 3725 | |||
| 3726 | void nf_tables_unbind_set(const struct nft_ctx *ctx, struct nft_set *set, | 3716 | void nf_tables_unbind_set(const struct nft_ctx *ctx, struct nft_set *set, |
| 3727 | struct nft_set_binding *binding) | 3717 | struct nft_set_binding *binding, bool event) |
| 3728 | { | 3718 | { |
| 3729 | list_del_rcu(&binding->list); | 3719 | list_del_rcu(&binding->list); |
| 3730 | 3720 | ||
| 3731 | if (list_empty(&set->bindings) && nft_set_is_anonymous(set) && | 3721 | if (list_empty(&set->bindings) && nft_set_is_anonymous(set)) { |
| 3732 | nft_is_active(ctx->net, set)) | ||
| 3733 | list_del_rcu(&set->list); | 3722 | list_del_rcu(&set->list); |
| 3723 | if (event) | ||
| 3724 | nf_tables_set_notify(ctx, set, NFT_MSG_DELSET, | ||
| 3725 | GFP_KERNEL); | ||
| 3726 | } | ||
| 3734 | } | 3727 | } |
| 3735 | EXPORT_SYMBOL_GPL(nf_tables_unbind_set); | 3728 | EXPORT_SYMBOL_GPL(nf_tables_unbind_set); |
| 3736 | 3729 | ||
| 3737 | void nf_tables_destroy_set(const struct nft_ctx *ctx, struct nft_set *set) | 3730 | void nf_tables_destroy_set(const struct nft_ctx *ctx, struct nft_set *set) |
| 3738 | { | 3731 | { |
| 3739 | if (list_empty(&set->bindings) && nft_set_is_anonymous(set) && | 3732 | if (list_empty(&set->bindings) && nft_set_is_anonymous(set)) |
| 3740 | nft_is_active(ctx->net, set)) { | ||
| 3741 | nf_tables_set_notify(ctx, set, NFT_MSG_DELSET, GFP_ATOMIC); | ||
| 3742 | nft_set_destroy(set); | 3733 | nft_set_destroy(set); |
| 3743 | } | ||
| 3744 | } | 3734 | } |
| 3745 | EXPORT_SYMBOL_GPL(nf_tables_destroy_set); | 3735 | EXPORT_SYMBOL_GPL(nf_tables_destroy_set); |
| 3746 | 3736 | ||
| @@ -6535,6 +6525,9 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb) | |||
| 6535 | nf_tables_rule_notify(&trans->ctx, | 6525 | nf_tables_rule_notify(&trans->ctx, |
| 6536 | nft_trans_rule(trans), | 6526 | nft_trans_rule(trans), |
| 6537 | NFT_MSG_DELRULE); | 6527 | NFT_MSG_DELRULE); |
| 6528 | nft_rule_expr_deactivate(&trans->ctx, | ||
| 6529 | nft_trans_rule(trans), | ||
| 6530 | NFT_TRANS_COMMIT); | ||
| 6538 | break; | 6531 | break; |
| 6539 | case NFT_MSG_NEWSET: | 6532 | case NFT_MSG_NEWSET: |
| 6540 | nft_clear(net, nft_trans_set(trans)); | 6533 | nft_clear(net, nft_trans_set(trans)); |
| @@ -6621,7 +6614,8 @@ static void nf_tables_abort_release(struct nft_trans *trans) | |||
| 6621 | nf_tables_rule_destroy(&trans->ctx, nft_trans_rule(trans)); | 6614 | nf_tables_rule_destroy(&trans->ctx, nft_trans_rule(trans)); |
| 6622 | break; | 6615 | break; |
| 6623 | case NFT_MSG_NEWSET: | 6616 | case NFT_MSG_NEWSET: |
| 6624 | nft_set_destroy(nft_trans_set(trans)); | 6617 | if (!nft_trans_set_bound(trans)) |
| 6618 | nft_set_destroy(nft_trans_set(trans)); | ||
| 6625 | break; | 6619 | break; |
| 6626 | case NFT_MSG_NEWSETELEM: | 6620 | case NFT_MSG_NEWSETELEM: |
| 6627 | nft_set_elem_destroy(nft_trans_elem_set(trans), | 6621 | nft_set_elem_destroy(nft_trans_elem_set(trans), |
| @@ -6682,7 +6676,9 @@ static int __nf_tables_abort(struct net *net) | |||
| 6682 | case NFT_MSG_NEWRULE: | 6676 | case NFT_MSG_NEWRULE: |
| 6683 | trans->ctx.chain->use--; | 6677 | trans->ctx.chain->use--; |
| 6684 | list_del_rcu(&nft_trans_rule(trans)->list); | 6678 | list_del_rcu(&nft_trans_rule(trans)->list); |
| 6685 | nft_rule_expr_deactivate(&trans->ctx, nft_trans_rule(trans)); | 6679 | nft_rule_expr_deactivate(&trans->ctx, |
| 6680 | nft_trans_rule(trans), | ||
| 6681 | NFT_TRANS_ABORT); | ||
| 6686 | break; | 6682 | break; |
| 6687 | case NFT_MSG_DELRULE: | 6683 | case NFT_MSG_DELRULE: |
| 6688 | trans->ctx.chain->use++; | 6684 | trans->ctx.chain->use++; |
| @@ -6692,7 +6688,8 @@ static int __nf_tables_abort(struct net *net) | |||
| 6692 | break; | 6688 | break; |
| 6693 | case NFT_MSG_NEWSET: | 6689 | case NFT_MSG_NEWSET: |
| 6694 | trans->ctx.table->use--; | 6690 | trans->ctx.table->use--; |
| 6695 | list_del_rcu(&nft_trans_set(trans)->list); | 6691 | if (!nft_trans_set_bound(trans)) |
| 6692 | list_del_rcu(&nft_trans_set(trans)->list); | ||
| 6696 | break; | 6693 | break; |
| 6697 | case NFT_MSG_DELSET: | 6694 | case NFT_MSG_DELSET: |
| 6698 | trans->ctx.table->use++; | 6695 | trans->ctx.table->use++; |
diff --git a/net/netfilter/nfnetlink_osf.c b/net/netfilter/nfnetlink_osf.c index 6f41dd74729d..1f1d90c1716b 100644 --- a/net/netfilter/nfnetlink_osf.c +++ b/net/netfilter/nfnetlink_osf.c | |||
| @@ -66,6 +66,7 @@ static bool nf_osf_match_one(const struct sk_buff *skb, | |||
| 66 | int ttl_check, | 66 | int ttl_check, |
| 67 | struct nf_osf_hdr_ctx *ctx) | 67 | struct nf_osf_hdr_ctx *ctx) |
| 68 | { | 68 | { |
| 69 | const __u8 *optpinit = ctx->optp; | ||
| 69 | unsigned int check_WSS = 0; | 70 | unsigned int check_WSS = 0; |
| 70 | int fmatch = FMATCH_WRONG; | 71 | int fmatch = FMATCH_WRONG; |
| 71 | int foptsize, optnum; | 72 | int foptsize, optnum; |
| @@ -155,6 +156,9 @@ static bool nf_osf_match_one(const struct sk_buff *skb, | |||
| 155 | } | 156 | } |
| 156 | } | 157 | } |
| 157 | 158 | ||
| 159 | if (fmatch != FMATCH_OK) | ||
| 160 | ctx->optp = optpinit; | ||
| 161 | |||
| 158 | return fmatch == FMATCH_OK; | 162 | return fmatch == FMATCH_OK; |
| 159 | } | 163 | } |
| 160 | 164 | ||
diff --git a/net/netfilter/nft_compat.c b/net/netfilter/nft_compat.c index 7334e0b80a5e..fe64df848365 100644 --- a/net/netfilter/nft_compat.c +++ b/net/netfilter/nft_compat.c | |||
| @@ -22,11 +22,15 @@ | |||
| 22 | #include <linux/netfilter_bridge/ebtables.h> | 22 | #include <linux/netfilter_bridge/ebtables.h> |
| 23 | #include <linux/netfilter_arp/arp_tables.h> | 23 | #include <linux/netfilter_arp/arp_tables.h> |
| 24 | #include <net/netfilter/nf_tables.h> | 24 | #include <net/netfilter/nf_tables.h> |
| 25 | #include <net/netns/generic.h> | ||
| 25 | 26 | ||
| 26 | struct nft_xt { | 27 | struct nft_xt { |
| 27 | struct list_head head; | 28 | struct list_head head; |
| 28 | struct nft_expr_ops ops; | 29 | struct nft_expr_ops ops; |
| 29 | unsigned int refcnt; | 30 | refcount_t refcnt; |
| 31 | |||
| 32 | /* used only when transaction mutex is locked */ | ||
| 33 | unsigned int listcnt; | ||
| 30 | 34 | ||
| 31 | /* Unlike other expressions, ops doesn't have static storage duration. | 35 | /* Unlike other expressions, ops doesn't have static storage duration. |
| 32 | * nft core assumes they do. We use kfree_rcu so that nft core can | 36 | * nft core assumes they do. We use kfree_rcu so that nft core can |
| @@ -43,10 +47,39 @@ struct nft_xt_match_priv { | |||
| 43 | void *info; | 47 | void *info; |
| 44 | }; | 48 | }; |
| 45 | 49 | ||
| 50 | struct nft_compat_net { | ||
| 51 | struct list_head nft_target_list; | ||
| 52 | struct list_head nft_match_list; | ||
| 53 | }; | ||
| 54 | |||
| 55 | static unsigned int nft_compat_net_id __read_mostly; | ||
| 56 | static struct nft_expr_type nft_match_type; | ||
| 57 | static struct nft_expr_type nft_target_type; | ||
| 58 | |||
| 59 | static struct nft_compat_net *nft_compat_pernet(struct net *net) | ||
| 60 | { | ||
| 61 | return net_generic(net, nft_compat_net_id); | ||
| 62 | } | ||
| 63 | |||
| 64 | static void nft_xt_get(struct nft_xt *xt) | ||
| 65 | { | ||
| 66 | /* refcount_inc() warns on 0 -> 1 transition, but we can't | ||
| 67 | * init the reference count to 1 in .select_ops -- we can't | ||
| 68 | * undo such an increase when another expression inside the same | ||
| 69 | * rule fails afterwards. | ||
| 70 | */ | ||
| 71 | if (xt->listcnt == 0) | ||
| 72 | refcount_set(&xt->refcnt, 1); | ||
| 73 | else | ||
| 74 | refcount_inc(&xt->refcnt); | ||
| 75 | |||
| 76 | xt->listcnt++; | ||
| 77 | } | ||
| 78 | |||
| 46 | static bool nft_xt_put(struct nft_xt *xt) | 79 | static bool nft_xt_put(struct nft_xt *xt) |
| 47 | { | 80 | { |
| 48 | if (--xt->refcnt == 0) { | 81 | if (refcount_dec_and_test(&xt->refcnt)) { |
| 49 | list_del(&xt->head); | 82 | WARN_ON_ONCE(!list_empty(&xt->head)); |
| 50 | kfree_rcu(xt, rcu_head); | 83 | kfree_rcu(xt, rcu_head); |
| 51 | return true; | 84 | return true; |
| 52 | } | 85 | } |
| @@ -273,7 +306,7 @@ nft_target_init(const struct nft_ctx *ctx, const struct nft_expr *expr, | |||
| 273 | return -EINVAL; | 306 | return -EINVAL; |
| 274 | 307 | ||
| 275 | nft_xt = container_of(expr->ops, struct nft_xt, ops); | 308 | nft_xt = container_of(expr->ops, struct nft_xt, ops); |
| 276 | nft_xt->refcnt++; | 309 | nft_xt_get(nft_xt); |
| 277 | return 0; | 310 | return 0; |
| 278 | } | 311 | } |
| 279 | 312 | ||
| @@ -486,7 +519,7 @@ __nft_match_init(const struct nft_ctx *ctx, const struct nft_expr *expr, | |||
| 486 | return ret; | 519 | return ret; |
| 487 | 520 | ||
| 488 | nft_xt = container_of(expr->ops, struct nft_xt, ops); | 521 | nft_xt = container_of(expr->ops, struct nft_xt, ops); |
| 489 | nft_xt->refcnt++; | 522 | nft_xt_get(nft_xt); |
| 490 | return 0; | 523 | return 0; |
| 491 | } | 524 | } |
| 492 | 525 | ||
| @@ -540,6 +573,18 @@ nft_match_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr) | |||
| 540 | __nft_match_destroy(ctx, expr, nft_expr_priv(expr)); | 573 | __nft_match_destroy(ctx, expr, nft_expr_priv(expr)); |
| 541 | } | 574 | } |
| 542 | 575 | ||
| 576 | static void nft_compat_deactivate(const struct nft_ctx *ctx, | ||
| 577 | const struct nft_expr *expr, | ||
| 578 | enum nft_trans_phase phase) | ||
| 579 | { | ||
| 580 | struct nft_xt *xt = container_of(expr->ops, struct nft_xt, ops); | ||
| 581 | |||
| 582 | if (phase == NFT_TRANS_ABORT || phase == NFT_TRANS_COMMIT) { | ||
| 583 | if (--xt->listcnt == 0) | ||
| 584 | list_del_init(&xt->head); | ||
| 585 | } | ||
| 586 | } | ||
| 587 | |||
| 543 | static void | 588 | static void |
| 544 | nft_match_large_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr) | 589 | nft_match_large_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr) |
| 545 | { | 590 | { |
| @@ -734,10 +779,6 @@ static const struct nfnetlink_subsystem nfnl_compat_subsys = { | |||
| 734 | .cb = nfnl_nft_compat_cb, | 779 | .cb = nfnl_nft_compat_cb, |
| 735 | }; | 780 | }; |
| 736 | 781 | ||
| 737 | static LIST_HEAD(nft_match_list); | ||
| 738 | |||
| 739 | static struct nft_expr_type nft_match_type; | ||
| 740 | |||
| 741 | static bool nft_match_cmp(const struct xt_match *match, | 782 | static bool nft_match_cmp(const struct xt_match *match, |
| 742 | const char *name, u32 rev, u32 family) | 783 | const char *name, u32 rev, u32 family) |
| 743 | { | 784 | { |
| @@ -749,6 +790,7 @@ static const struct nft_expr_ops * | |||
| 749 | nft_match_select_ops(const struct nft_ctx *ctx, | 790 | nft_match_select_ops(const struct nft_ctx *ctx, |
| 750 | const struct nlattr * const tb[]) | 791 | const struct nlattr * const tb[]) |
| 751 | { | 792 | { |
| 793 | struct nft_compat_net *cn; | ||
| 752 | struct nft_xt *nft_match; | 794 | struct nft_xt *nft_match; |
| 753 | struct xt_match *match; | 795 | struct xt_match *match; |
| 754 | unsigned int matchsize; | 796 | unsigned int matchsize; |
| @@ -765,8 +807,10 @@ nft_match_select_ops(const struct nft_ctx *ctx, | |||
| 765 | rev = ntohl(nla_get_be32(tb[NFTA_MATCH_REV])); | 807 | rev = ntohl(nla_get_be32(tb[NFTA_MATCH_REV])); |
| 766 | family = ctx->family; | 808 | family = ctx->family; |
| 767 | 809 | ||
| 810 | cn = nft_compat_pernet(ctx->net); | ||
| 811 | |||
| 768 | /* Re-use the existing match if it's already loaded. */ | 812 | /* Re-use the existing match if it's already loaded. */ |
| 769 | list_for_each_entry(nft_match, &nft_match_list, head) { | 813 | list_for_each_entry(nft_match, &cn->nft_match_list, head) { |
| 770 | struct xt_match *match = nft_match->ops.data; | 814 | struct xt_match *match = nft_match->ops.data; |
| 771 | 815 | ||
| 772 | if (nft_match_cmp(match, mt_name, rev, family)) | 816 | if (nft_match_cmp(match, mt_name, rev, family)) |
| @@ -789,11 +833,12 @@ nft_match_select_ops(const struct nft_ctx *ctx, | |||
| 789 | goto err; | 833 | goto err; |
| 790 | } | 834 | } |
| 791 | 835 | ||
| 792 | nft_match->refcnt = 0; | 836 | refcount_set(&nft_match->refcnt, 0); |
| 793 | nft_match->ops.type = &nft_match_type; | 837 | nft_match->ops.type = &nft_match_type; |
| 794 | nft_match->ops.eval = nft_match_eval; | 838 | nft_match->ops.eval = nft_match_eval; |
| 795 | nft_match->ops.init = nft_match_init; | 839 | nft_match->ops.init = nft_match_init; |
| 796 | nft_match->ops.destroy = nft_match_destroy; | 840 | nft_match->ops.destroy = nft_match_destroy; |
| 841 | nft_match->ops.deactivate = nft_compat_deactivate; | ||
| 797 | nft_match->ops.dump = nft_match_dump; | 842 | nft_match->ops.dump = nft_match_dump; |
| 798 | nft_match->ops.validate = nft_match_validate; | 843 | nft_match->ops.validate = nft_match_validate; |
| 799 | nft_match->ops.data = match; | 844 | nft_match->ops.data = match; |
| @@ -810,7 +855,8 @@ nft_match_select_ops(const struct nft_ctx *ctx, | |||
| 810 | 855 | ||
| 811 | nft_match->ops.size = matchsize; | 856 | nft_match->ops.size = matchsize; |
| 812 | 857 | ||
| 813 | list_add(&nft_match->head, &nft_match_list); | 858 | nft_match->listcnt = 0; |
| 859 | list_add(&nft_match->head, &cn->nft_match_list); | ||
| 814 | 860 | ||
| 815 | return &nft_match->ops; | 861 | return &nft_match->ops; |
| 816 | err: | 862 | err: |
| @@ -826,10 +872,6 @@ static struct nft_expr_type nft_match_type __read_mostly = { | |||
| 826 | .owner = THIS_MODULE, | 872 | .owner = THIS_MODULE, |
| 827 | }; | 873 | }; |
| 828 | 874 | ||
| 829 | static LIST_HEAD(nft_target_list); | ||
| 830 | |||
| 831 | static struct nft_expr_type nft_target_type; | ||
| 832 | |||
| 833 | static bool nft_target_cmp(const struct xt_target *tg, | 875 | static bool nft_target_cmp(const struct xt_target *tg, |
| 834 | const char *name, u32 rev, u32 family) | 876 | const char *name, u32 rev, u32 family) |
| 835 | { | 877 | { |
| @@ -841,6 +883,7 @@ static const struct nft_expr_ops * | |||
| 841 | nft_target_select_ops(const struct nft_ctx *ctx, | 883 | nft_target_select_ops(const struct nft_ctx *ctx, |
| 842 | const struct nlattr * const tb[]) | 884 | const struct nlattr * const tb[]) |
| 843 | { | 885 | { |
| 886 | struct nft_compat_net *cn; | ||
| 844 | struct nft_xt *nft_target; | 887 | struct nft_xt *nft_target; |
| 845 | struct xt_target *target; | 888 | struct xt_target *target; |
| 846 | char *tg_name; | 889 | char *tg_name; |
| @@ -861,8 +904,9 @@ nft_target_select_ops(const struct nft_ctx *ctx, | |||
| 861 | strcmp(tg_name, "standard") == 0) | 904 | strcmp(tg_name, "standard") == 0) |
| 862 | return ERR_PTR(-EINVAL); | 905 | return ERR_PTR(-EINVAL); |
| 863 | 906 | ||
| 907 | cn = nft_compat_pernet(ctx->net); | ||
| 864 | /* Re-use the existing target if it's already loaded. */ | 908 | /* Re-use the existing target if it's already loaded. */ |
| 865 | list_for_each_entry(nft_target, &nft_target_list, head) { | 909 | list_for_each_entry(nft_target, &cn->nft_target_list, head) { |
| 866 | struct xt_target *target = nft_target->ops.data; | 910 | struct xt_target *target = nft_target->ops.data; |
| 867 | 911 | ||
| 868 | if (!target->target) | 912 | if (!target->target) |
| @@ -893,11 +937,12 @@ nft_target_select_ops(const struct nft_ctx *ctx, | |||
| 893 | goto err; | 937 | goto err; |
| 894 | } | 938 | } |
| 895 | 939 | ||
| 896 | nft_target->refcnt = 0; | 940 | refcount_set(&nft_target->refcnt, 0); |
| 897 | nft_target->ops.type = &nft_target_type; | 941 | nft_target->ops.type = &nft_target_type; |
| 898 | nft_target->ops.size = NFT_EXPR_SIZE(XT_ALIGN(target->targetsize)); | 942 | nft_target->ops.size = NFT_EXPR_SIZE(XT_ALIGN(target->targetsize)); |
| 899 | nft_target->ops.init = nft_target_init; | 943 | nft_target->ops.init = nft_target_init; |
| 900 | nft_target->ops.destroy = nft_target_destroy; | 944 | nft_target->ops.destroy = nft_target_destroy; |
| 945 | nft_target->ops.deactivate = nft_compat_deactivate; | ||
| 901 | nft_target->ops.dump = nft_target_dump; | 946 | nft_target->ops.dump = nft_target_dump; |
| 902 | nft_target->ops.validate = nft_target_validate; | 947 | nft_target->ops.validate = nft_target_validate; |
| 903 | nft_target->ops.data = target; | 948 | nft_target->ops.data = target; |
| @@ -907,7 +952,8 @@ nft_target_select_ops(const struct nft_ctx *ctx, | |||
| 907 | else | 952 | else |
| 908 | nft_target->ops.eval = nft_target_eval_xt; | 953 | nft_target->ops.eval = nft_target_eval_xt; |
| 909 | 954 | ||
| 910 | list_add(&nft_target->head, &nft_target_list); | 955 | nft_target->listcnt = 0; |
| 956 | list_add(&nft_target->head, &cn->nft_target_list); | ||
| 911 | 957 | ||
| 912 | return &nft_target->ops; | 958 | return &nft_target->ops; |
| 913 | err: | 959 | err: |
| @@ -923,13 +969,74 @@ static struct nft_expr_type nft_target_type __read_mostly = { | |||
| 923 | .owner = THIS_MODULE, | 969 | .owner = THIS_MODULE, |
| 924 | }; | 970 | }; |
| 925 | 971 | ||
| 972 | static int __net_init nft_compat_init_net(struct net *net) | ||
| 973 | { | ||
| 974 | struct nft_compat_net *cn = nft_compat_pernet(net); | ||
| 975 | |||
| 976 | INIT_LIST_HEAD(&cn->nft_target_list); | ||
| 977 | INIT_LIST_HEAD(&cn->nft_match_list); | ||
| 978 | |||
| 979 | return 0; | ||
| 980 | } | ||
| 981 | |||
| 982 | static void __net_exit nft_compat_exit_net(struct net *net) | ||
| 983 | { | ||
| 984 | struct nft_compat_net *cn = nft_compat_pernet(net); | ||
| 985 | struct nft_xt *xt, *next; | ||
| 986 | |||
| 987 | if (list_empty(&cn->nft_match_list) && | ||
| 988 | list_empty(&cn->nft_target_list)) | ||
| 989 | return; | ||
| 990 | |||
| 991 | /* If there was an error that caused nft_xt expr to not be initialized | ||
| 992 | * fully and noone else requested the same expression later, the lists | ||
| 993 | * contain 0-refcount entries that still hold module reference. | ||
| 994 | * | ||
| 995 | * Clean them here. | ||
| 996 | */ | ||
| 997 | mutex_lock(&net->nft.commit_mutex); | ||
| 998 | list_for_each_entry_safe(xt, next, &cn->nft_target_list, head) { | ||
| 999 | struct xt_target *target = xt->ops.data; | ||
| 1000 | |||
| 1001 | list_del_init(&xt->head); | ||
| 1002 | |||
| 1003 | if (refcount_read(&xt->refcnt)) | ||
| 1004 | continue; | ||
| 1005 | module_put(target->me); | ||
| 1006 | kfree(xt); | ||
| 1007 | } | ||
| 1008 | |||
| 1009 | list_for_each_entry_safe(xt, next, &cn->nft_match_list, head) { | ||
| 1010 | struct xt_match *match = xt->ops.data; | ||
| 1011 | |||
| 1012 | list_del_init(&xt->head); | ||
| 1013 | |||
| 1014 | if (refcount_read(&xt->refcnt)) | ||
| 1015 | continue; | ||
| 1016 | module_put(match->me); | ||
| 1017 | kfree(xt); | ||
| 1018 | } | ||
| 1019 | mutex_unlock(&net->nft.commit_mutex); | ||
| 1020 | } | ||
| 1021 | |||
| 1022 | static struct pernet_operations nft_compat_net_ops = { | ||
| 1023 | .init = nft_compat_init_net, | ||
| 1024 | .exit = nft_compat_exit_net, | ||
| 1025 | .id = &nft_compat_net_id, | ||
| 1026 | .size = sizeof(struct nft_compat_net), | ||
| 1027 | }; | ||
| 1028 | |||
| 926 | static int __init nft_compat_module_init(void) | 1029 | static int __init nft_compat_module_init(void) |
| 927 | { | 1030 | { |
| 928 | int ret; | 1031 | int ret; |
| 929 | 1032 | ||
| 1033 | ret = register_pernet_subsys(&nft_compat_net_ops); | ||
| 1034 | if (ret < 0) | ||
| 1035 | goto err_target; | ||
| 1036 | |||
| 930 | ret = nft_register_expr(&nft_match_type); | 1037 | ret = nft_register_expr(&nft_match_type); |
| 931 | if (ret < 0) | 1038 | if (ret < 0) |
| 932 | return ret; | 1039 | goto err_pernet; |
| 933 | 1040 | ||
| 934 | ret = nft_register_expr(&nft_target_type); | 1041 | ret = nft_register_expr(&nft_target_type); |
| 935 | if (ret < 0) | 1042 | if (ret < 0) |
| @@ -942,45 +1049,21 @@ static int __init nft_compat_module_init(void) | |||
| 942 | } | 1049 | } |
| 943 | 1050 | ||
| 944 | return ret; | 1051 | return ret; |
| 945 | |||
| 946 | err_target: | 1052 | err_target: |
| 947 | nft_unregister_expr(&nft_target_type); | 1053 | nft_unregister_expr(&nft_target_type); |
| 948 | err_match: | 1054 | err_match: |
| 949 | nft_unregister_expr(&nft_match_type); | 1055 | nft_unregister_expr(&nft_match_type); |
| 1056 | err_pernet: | ||
| 1057 | unregister_pernet_subsys(&nft_compat_net_ops); | ||
| 950 | return ret; | 1058 | return ret; |
| 951 | } | 1059 | } |
| 952 | 1060 | ||
| 953 | static void __exit nft_compat_module_exit(void) | 1061 | static void __exit nft_compat_module_exit(void) |
| 954 | { | 1062 | { |
| 955 | struct nft_xt *xt, *next; | ||
| 956 | |||
| 957 | /* list should be empty here, it can be non-empty only in case there | ||
| 958 | * was an error that caused nft_xt expr to not be initialized fully | ||
| 959 | * and noone else requested the same expression later. | ||
| 960 | * | ||
| 961 | * In this case, the lists contain 0-refcount entries that still | ||
| 962 | * hold module reference. | ||
| 963 | */ | ||
| 964 | list_for_each_entry_safe(xt, next, &nft_target_list, head) { | ||
| 965 | struct xt_target *target = xt->ops.data; | ||
| 966 | |||
| 967 | if (WARN_ON_ONCE(xt->refcnt)) | ||
| 968 | continue; | ||
| 969 | module_put(target->me); | ||
| 970 | kfree(xt); | ||
| 971 | } | ||
| 972 | |||
| 973 | list_for_each_entry_safe(xt, next, &nft_match_list, head) { | ||
| 974 | struct xt_match *match = xt->ops.data; | ||
| 975 | |||
| 976 | if (WARN_ON_ONCE(xt->refcnt)) | ||
| 977 | continue; | ||
| 978 | module_put(match->me); | ||
| 979 | kfree(xt); | ||
| 980 | } | ||
| 981 | nfnetlink_subsys_unregister(&nfnl_compat_subsys); | 1063 | nfnetlink_subsys_unregister(&nfnl_compat_subsys); |
| 982 | nft_unregister_expr(&nft_target_type); | 1064 | nft_unregister_expr(&nft_target_type); |
| 983 | nft_unregister_expr(&nft_match_type); | 1065 | nft_unregister_expr(&nft_match_type); |
| 1066 | unregister_pernet_subsys(&nft_compat_net_ops); | ||
| 984 | } | 1067 | } |
| 985 | 1068 | ||
| 986 | MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_NFT_COMPAT); | 1069 | MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_NFT_COMPAT); |
diff --git a/net/netfilter/nft_dynset.c b/net/netfilter/nft_dynset.c index 07d4efd3d851..f1172f99752b 100644 --- a/net/netfilter/nft_dynset.c +++ b/net/netfilter/nft_dynset.c | |||
| @@ -235,20 +235,17 @@ err1: | |||
| 235 | return err; | 235 | return err; |
| 236 | } | 236 | } |
| 237 | 237 | ||
| 238 | static void nft_dynset_activate(const struct nft_ctx *ctx, | ||
| 239 | const struct nft_expr *expr) | ||
| 240 | { | ||
| 241 | struct nft_dynset *priv = nft_expr_priv(expr); | ||
| 242 | |||
| 243 | nf_tables_rebind_set(ctx, priv->set, &priv->binding); | ||
| 244 | } | ||
| 245 | |||
| 246 | static void nft_dynset_deactivate(const struct nft_ctx *ctx, | 238 | static void nft_dynset_deactivate(const struct nft_ctx *ctx, |
| 247 | const struct nft_expr *expr) | 239 | const struct nft_expr *expr, |
| 240 | enum nft_trans_phase phase) | ||
| 248 | { | 241 | { |
| 249 | struct nft_dynset *priv = nft_expr_priv(expr); | 242 | struct nft_dynset *priv = nft_expr_priv(expr); |
| 250 | 243 | ||
| 251 | nf_tables_unbind_set(ctx, priv->set, &priv->binding); | 244 | if (phase == NFT_TRANS_PREPARE) |
| 245 | return; | ||
| 246 | |||
| 247 | nf_tables_unbind_set(ctx, priv->set, &priv->binding, | ||
| 248 | phase == NFT_TRANS_COMMIT); | ||
| 252 | } | 249 | } |
| 253 | 250 | ||
| 254 | static void nft_dynset_destroy(const struct nft_ctx *ctx, | 251 | static void nft_dynset_destroy(const struct nft_ctx *ctx, |
| @@ -296,7 +293,6 @@ static const struct nft_expr_ops nft_dynset_ops = { | |||
| 296 | .eval = nft_dynset_eval, | 293 | .eval = nft_dynset_eval, |
| 297 | .init = nft_dynset_init, | 294 | .init = nft_dynset_init, |
| 298 | .destroy = nft_dynset_destroy, | 295 | .destroy = nft_dynset_destroy, |
| 299 | .activate = nft_dynset_activate, | ||
| 300 | .deactivate = nft_dynset_deactivate, | 296 | .deactivate = nft_dynset_deactivate, |
| 301 | .dump = nft_dynset_dump, | 297 | .dump = nft_dynset_dump, |
| 302 | }; | 298 | }; |
diff --git a/net/netfilter/nft_immediate.c b/net/netfilter/nft_immediate.c index 0777a93211e2..3f6d1d2a6281 100644 --- a/net/netfilter/nft_immediate.c +++ b/net/netfilter/nft_immediate.c | |||
| @@ -72,10 +72,14 @@ static void nft_immediate_activate(const struct nft_ctx *ctx, | |||
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | static void nft_immediate_deactivate(const struct nft_ctx *ctx, | 74 | static void nft_immediate_deactivate(const struct nft_ctx *ctx, |
| 75 | const struct nft_expr *expr) | 75 | const struct nft_expr *expr, |
| 76 | enum nft_trans_phase phase) | ||
| 76 | { | 77 | { |
| 77 | const struct nft_immediate_expr *priv = nft_expr_priv(expr); | 78 | const struct nft_immediate_expr *priv = nft_expr_priv(expr); |
| 78 | 79 | ||
| 80 | if (phase == NFT_TRANS_COMMIT) | ||
| 81 | return; | ||
| 82 | |||
| 79 | return nft_data_release(&priv->data, nft_dreg_to_type(priv->dreg)); | 83 | return nft_data_release(&priv->data, nft_dreg_to_type(priv->dreg)); |
| 80 | } | 84 | } |
| 81 | 85 | ||
diff --git a/net/netfilter/nft_lookup.c b/net/netfilter/nft_lookup.c index 227b2b15a19c..14496da5141d 100644 --- a/net/netfilter/nft_lookup.c +++ b/net/netfilter/nft_lookup.c | |||
| @@ -121,20 +121,17 @@ static int nft_lookup_init(const struct nft_ctx *ctx, | |||
| 121 | return 0; | 121 | return 0; |
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | static void nft_lookup_activate(const struct nft_ctx *ctx, | ||
| 125 | const struct nft_expr *expr) | ||
| 126 | { | ||
| 127 | struct nft_lookup *priv = nft_expr_priv(expr); | ||
| 128 | |||
| 129 | nf_tables_rebind_set(ctx, priv->set, &priv->binding); | ||
| 130 | } | ||
| 131 | |||
| 132 | static void nft_lookup_deactivate(const struct nft_ctx *ctx, | 124 | static void nft_lookup_deactivate(const struct nft_ctx *ctx, |
| 133 | const struct nft_expr *expr) | 125 | const struct nft_expr *expr, |
| 126 | enum nft_trans_phase phase) | ||
| 134 | { | 127 | { |
| 135 | struct nft_lookup *priv = nft_expr_priv(expr); | 128 | struct nft_lookup *priv = nft_expr_priv(expr); |
| 136 | 129 | ||
| 137 | nf_tables_unbind_set(ctx, priv->set, &priv->binding); | 130 | if (phase == NFT_TRANS_PREPARE) |
| 131 | return; | ||
| 132 | |||
| 133 | nf_tables_unbind_set(ctx, priv->set, &priv->binding, | ||
| 134 | phase == NFT_TRANS_COMMIT); | ||
| 138 | } | 135 | } |
| 139 | 136 | ||
| 140 | static void nft_lookup_destroy(const struct nft_ctx *ctx, | 137 | static void nft_lookup_destroy(const struct nft_ctx *ctx, |
| @@ -225,7 +222,6 @@ static const struct nft_expr_ops nft_lookup_ops = { | |||
| 225 | .size = NFT_EXPR_SIZE(sizeof(struct nft_lookup)), | 222 | .size = NFT_EXPR_SIZE(sizeof(struct nft_lookup)), |
| 226 | .eval = nft_lookup_eval, | 223 | .eval = nft_lookup_eval, |
| 227 | .init = nft_lookup_init, | 224 | .init = nft_lookup_init, |
| 228 | .activate = nft_lookup_activate, | ||
| 229 | .deactivate = nft_lookup_deactivate, | 225 | .deactivate = nft_lookup_deactivate, |
| 230 | .destroy = nft_lookup_destroy, | 226 | .destroy = nft_lookup_destroy, |
| 231 | .dump = nft_lookup_dump, | 227 | .dump = nft_lookup_dump, |
diff --git a/net/netfilter/nft_objref.c b/net/netfilter/nft_objref.c index a3185ca2a3a9..ae178e914486 100644 --- a/net/netfilter/nft_objref.c +++ b/net/netfilter/nft_objref.c | |||
| @@ -155,20 +155,17 @@ nla_put_failure: | |||
| 155 | return -1; | 155 | return -1; |
| 156 | } | 156 | } |
| 157 | 157 | ||
| 158 | static void nft_objref_map_activate(const struct nft_ctx *ctx, | ||
| 159 | const struct nft_expr *expr) | ||
| 160 | { | ||
| 161 | struct nft_objref_map *priv = nft_expr_priv(expr); | ||
| 162 | |||
| 163 | nf_tables_rebind_set(ctx, priv->set, &priv->binding); | ||
| 164 | } | ||
| 165 | |||
| 166 | static void nft_objref_map_deactivate(const struct nft_ctx *ctx, | 158 | static void nft_objref_map_deactivate(const struct nft_ctx *ctx, |
| 167 | const struct nft_expr *expr) | 159 | const struct nft_expr *expr, |
| 160 | enum nft_trans_phase phase) | ||
| 168 | { | 161 | { |
| 169 | struct nft_objref_map *priv = nft_expr_priv(expr); | 162 | struct nft_objref_map *priv = nft_expr_priv(expr); |
| 170 | 163 | ||
| 171 | nf_tables_unbind_set(ctx, priv->set, &priv->binding); | 164 | if (phase == NFT_TRANS_PREPARE) |
| 165 | return; | ||
| 166 | |||
| 167 | nf_tables_unbind_set(ctx, priv->set, &priv->binding, | ||
| 168 | phase == NFT_TRANS_COMMIT); | ||
| 172 | } | 169 | } |
| 173 | 170 | ||
| 174 | static void nft_objref_map_destroy(const struct nft_ctx *ctx, | 171 | static void nft_objref_map_destroy(const struct nft_ctx *ctx, |
| @@ -185,7 +182,6 @@ static const struct nft_expr_ops nft_objref_map_ops = { | |||
| 185 | .size = NFT_EXPR_SIZE(sizeof(struct nft_objref_map)), | 182 | .size = NFT_EXPR_SIZE(sizeof(struct nft_objref_map)), |
| 186 | .eval = nft_objref_map_eval, | 183 | .eval = nft_objref_map_eval, |
| 187 | .init = nft_objref_map_init, | 184 | .init = nft_objref_map_init, |
| 188 | .activate = nft_objref_map_activate, | ||
| 189 | .deactivate = nft_objref_map_deactivate, | 185 | .deactivate = nft_objref_map_deactivate, |
| 190 | .destroy = nft_objref_map_destroy, | 186 | .destroy = nft_objref_map_destroy, |
| 191 | .dump = nft_objref_map_dump, | 187 | .dump = nft_objref_map_dump, |
diff --git a/net/netrom/nr_timer.c b/net/netrom/nr_timer.c index cbd51ed5a2d7..908e53ab47a4 100644 --- a/net/netrom/nr_timer.c +++ b/net/netrom/nr_timer.c | |||
| @@ -52,21 +52,21 @@ void nr_start_t1timer(struct sock *sk) | |||
| 52 | { | 52 | { |
| 53 | struct nr_sock *nr = nr_sk(sk); | 53 | struct nr_sock *nr = nr_sk(sk); |
| 54 | 54 | ||
| 55 | mod_timer(&nr->t1timer, jiffies + nr->t1); | 55 | sk_reset_timer(sk, &nr->t1timer, jiffies + nr->t1); |
| 56 | } | 56 | } |
| 57 | 57 | ||
| 58 | void nr_start_t2timer(struct sock *sk) | 58 | void nr_start_t2timer(struct sock *sk) |
| 59 | { | 59 | { |
| 60 | struct nr_sock *nr = nr_sk(sk); | 60 | struct nr_sock *nr = nr_sk(sk); |
| 61 | 61 | ||
| 62 | mod_timer(&nr->t2timer, jiffies + nr->t2); | 62 | sk_reset_timer(sk, &nr->t2timer, jiffies + nr->t2); |
| 63 | } | 63 | } |
| 64 | 64 | ||
| 65 | void nr_start_t4timer(struct sock *sk) | 65 | void nr_start_t4timer(struct sock *sk) |
| 66 | { | 66 | { |
| 67 | struct nr_sock *nr = nr_sk(sk); | 67 | struct nr_sock *nr = nr_sk(sk); |
| 68 | 68 | ||
| 69 | mod_timer(&nr->t4timer, jiffies + nr->t4); | 69 | sk_reset_timer(sk, &nr->t4timer, jiffies + nr->t4); |
| 70 | } | 70 | } |
| 71 | 71 | ||
| 72 | void nr_start_idletimer(struct sock *sk) | 72 | void nr_start_idletimer(struct sock *sk) |
| @@ -74,37 +74,37 @@ void nr_start_idletimer(struct sock *sk) | |||
| 74 | struct nr_sock *nr = nr_sk(sk); | 74 | struct nr_sock *nr = nr_sk(sk); |
| 75 | 75 | ||
| 76 | if (nr->idle > 0) | 76 | if (nr->idle > 0) |
| 77 | mod_timer(&nr->idletimer, jiffies + nr->idle); | 77 | sk_reset_timer(sk, &nr->idletimer, jiffies + nr->idle); |
| 78 | } | 78 | } |
| 79 | 79 | ||
| 80 | void nr_start_heartbeat(struct sock *sk) | 80 | void nr_start_heartbeat(struct sock *sk) |
| 81 | { | 81 | { |
| 82 | mod_timer(&sk->sk_timer, jiffies + 5 * HZ); | 82 | sk_reset_timer(sk, &sk->sk_timer, jiffies + 5 * HZ); |
| 83 | } | 83 | } |
| 84 | 84 | ||
| 85 | void nr_stop_t1timer(struct sock *sk) | 85 | void nr_stop_t1timer(struct sock *sk) |
| 86 | { | 86 | { |
| 87 | del_timer(&nr_sk(sk)->t1timer); | 87 | sk_stop_timer(sk, &nr_sk(sk)->t1timer); |
| 88 | } | 88 | } |
| 89 | 89 | ||
| 90 | void nr_stop_t2timer(struct sock *sk) | 90 | void nr_stop_t2timer(struct sock *sk) |
| 91 | { | 91 | { |
| 92 | del_timer(&nr_sk(sk)->t2timer); | 92 | sk_stop_timer(sk, &nr_sk(sk)->t2timer); |
| 93 | } | 93 | } |
| 94 | 94 | ||
| 95 | void nr_stop_t4timer(struct sock *sk) | 95 | void nr_stop_t4timer(struct sock *sk) |
| 96 | { | 96 | { |
| 97 | del_timer(&nr_sk(sk)->t4timer); | 97 | sk_stop_timer(sk, &nr_sk(sk)->t4timer); |
| 98 | } | 98 | } |
| 99 | 99 | ||
| 100 | void nr_stop_idletimer(struct sock *sk) | 100 | void nr_stop_idletimer(struct sock *sk) |
| 101 | { | 101 | { |
| 102 | del_timer(&nr_sk(sk)->idletimer); | 102 | sk_stop_timer(sk, &nr_sk(sk)->idletimer); |
| 103 | } | 103 | } |
| 104 | 104 | ||
| 105 | void nr_stop_heartbeat(struct sock *sk) | 105 | void nr_stop_heartbeat(struct sock *sk) |
| 106 | { | 106 | { |
| 107 | del_timer(&sk->sk_timer); | 107 | sk_stop_timer(sk, &sk->sk_timer); |
| 108 | } | 108 | } |
| 109 | 109 | ||
| 110 | int nr_t1timer_running(struct sock *sk) | 110 | int nr_t1timer_running(struct sock *sk) |
diff --git a/net/rds/bind.c b/net/rds/bind.c index 762d2c6788a3..17c9d9f0c848 100644 --- a/net/rds/bind.c +++ b/net/rds/bind.c | |||
| @@ -78,10 +78,10 @@ struct rds_sock *rds_find_bound(const struct in6_addr *addr, __be16 port, | |||
| 78 | __rds_create_bind_key(key, addr, port, scope_id); | 78 | __rds_create_bind_key(key, addr, port, scope_id); |
| 79 | rcu_read_lock(); | 79 | rcu_read_lock(); |
| 80 | rs = rhashtable_lookup(&bind_hash_table, key, ht_parms); | 80 | rs = rhashtable_lookup(&bind_hash_table, key, ht_parms); |
| 81 | if (rs && !sock_flag(rds_rs_to_sk(rs), SOCK_DEAD)) | 81 | if (rs && (sock_flag(rds_rs_to_sk(rs), SOCK_DEAD) || |
| 82 | rds_sock_addref(rs); | 82 | !refcount_inc_not_zero(&rds_rs_to_sk(rs)->sk_refcnt))) |
| 83 | else | ||
| 84 | rs = NULL; | 83 | rs = NULL; |
| 84 | |||
| 85 | rcu_read_unlock(); | 85 | rcu_read_unlock(); |
| 86 | 86 | ||
| 87 | rdsdebug("returning rs %p for %pI6c:%u\n", rs, addr, | 87 | rdsdebug("returning rs %p for %pI6c:%u\n", rs, addr, |
diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c index 77e9f85a2c92..f2ff21d7df08 100644 --- a/net/rose/rose_route.c +++ b/net/rose/rose_route.c | |||
| @@ -850,6 +850,7 @@ void rose_link_device_down(struct net_device *dev) | |||
| 850 | 850 | ||
| 851 | /* | 851 | /* |
| 852 | * Route a frame to an appropriate AX.25 connection. | 852 | * Route a frame to an appropriate AX.25 connection. |
| 853 | * A NULL ax25_cb indicates an internally generated frame. | ||
| 853 | */ | 854 | */ |
| 854 | int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25) | 855 | int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25) |
| 855 | { | 856 | { |
| @@ -867,6 +868,10 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25) | |||
| 867 | 868 | ||
| 868 | if (skb->len < ROSE_MIN_LEN) | 869 | if (skb->len < ROSE_MIN_LEN) |
| 869 | return res; | 870 | return res; |
| 871 | |||
| 872 | if (!ax25) | ||
| 873 | return rose_loopback_queue(skb, NULL); | ||
| 874 | |||
| 870 | frametype = skb->data[2]; | 875 | frametype = skb->data[2]; |
| 871 | lci = ((skb->data[0] << 8) & 0xF00) + ((skb->data[1] << 0) & 0x0FF); | 876 | lci = ((skb->data[0] << 8) & 0xF00) + ((skb->data[1] << 0) & 0x0FF); |
| 872 | if (frametype == ROSE_CALL_REQUEST && | 877 | if (frametype == ROSE_CALL_REQUEST && |
diff --git a/net/rxrpc/recvmsg.c b/net/rxrpc/recvmsg.c index eaf19ebaa964..3f7bb11f3290 100644 --- a/net/rxrpc/recvmsg.c +++ b/net/rxrpc/recvmsg.c | |||
| @@ -596,6 +596,7 @@ error_requeue_call: | |||
| 596 | } | 596 | } |
| 597 | error_no_call: | 597 | error_no_call: |
| 598 | release_sock(&rx->sk); | 598 | release_sock(&rx->sk); |
| 599 | error_trace: | ||
| 599 | trace_rxrpc_recvmsg(call, rxrpc_recvmsg_return, 0, 0, 0, ret); | 600 | trace_rxrpc_recvmsg(call, rxrpc_recvmsg_return, 0, 0, 0, ret); |
| 600 | return ret; | 601 | return ret; |
| 601 | 602 | ||
| @@ -604,7 +605,7 @@ wait_interrupted: | |||
| 604 | wait_error: | 605 | wait_error: |
| 605 | finish_wait(sk_sleep(&rx->sk), &wait); | 606 | finish_wait(sk_sleep(&rx->sk), &wait); |
| 606 | call = NULL; | 607 | call = NULL; |
| 607 | goto error_no_call; | 608 | goto error_trace; |
| 608 | } | 609 | } |
| 609 | 610 | ||
| 610 | /** | 611 | /** |
diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c index f6aa57fbbbaf..12ca9d13db83 100644 --- a/net/sched/cls_flower.c +++ b/net/sched/cls_flower.c | |||
| @@ -1371,7 +1371,7 @@ static int fl_change(struct net *net, struct sk_buff *in_skb, | |||
| 1371 | if (!tc_skip_hw(fnew->flags)) { | 1371 | if (!tc_skip_hw(fnew->flags)) { |
| 1372 | err = fl_hw_replace_filter(tp, fnew, extack); | 1372 | err = fl_hw_replace_filter(tp, fnew, extack); |
| 1373 | if (err) | 1373 | if (err) |
| 1374 | goto errout_mask; | 1374 | goto errout_mask_ht; |
| 1375 | } | 1375 | } |
| 1376 | 1376 | ||
| 1377 | if (!tc_in_hw(fnew->flags)) | 1377 | if (!tc_in_hw(fnew->flags)) |
| @@ -1401,6 +1401,10 @@ static int fl_change(struct net *net, struct sk_buff *in_skb, | |||
| 1401 | kfree(mask); | 1401 | kfree(mask); |
| 1402 | return 0; | 1402 | return 0; |
| 1403 | 1403 | ||
| 1404 | errout_mask_ht: | ||
| 1405 | rhashtable_remove_fast(&fnew->mask->ht, &fnew->ht_node, | ||
| 1406 | fnew->mask->filter_ht_params); | ||
| 1407 | |||
| 1404 | errout_mask: | 1408 | errout_mask: |
| 1405 | fl_mask_put(head, fnew->mask, false); | 1409 | fl_mask_put(head, fnew->mask, false); |
| 1406 | 1410 | ||
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index f93c3cf9e567..65d6d04546ae 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
| @@ -2027,7 +2027,7 @@ static int sctp_sendmsg(struct sock *sk, struct msghdr *msg, size_t msg_len) | |||
| 2027 | struct sctp_endpoint *ep = sctp_sk(sk)->ep; | 2027 | struct sctp_endpoint *ep = sctp_sk(sk)->ep; |
| 2028 | struct sctp_transport *transport = NULL; | 2028 | struct sctp_transport *transport = NULL; |
| 2029 | struct sctp_sndrcvinfo _sinfo, *sinfo; | 2029 | struct sctp_sndrcvinfo _sinfo, *sinfo; |
| 2030 | struct sctp_association *asoc; | 2030 | struct sctp_association *asoc, *tmp; |
| 2031 | struct sctp_cmsgs cmsgs; | 2031 | struct sctp_cmsgs cmsgs; |
| 2032 | union sctp_addr *daddr; | 2032 | union sctp_addr *daddr; |
| 2033 | bool new = false; | 2033 | bool new = false; |
| @@ -2053,7 +2053,7 @@ static int sctp_sendmsg(struct sock *sk, struct msghdr *msg, size_t msg_len) | |||
| 2053 | 2053 | ||
| 2054 | /* SCTP_SENDALL process */ | 2054 | /* SCTP_SENDALL process */ |
| 2055 | if ((sflags & SCTP_SENDALL) && sctp_style(sk, UDP)) { | 2055 | if ((sflags & SCTP_SENDALL) && sctp_style(sk, UDP)) { |
| 2056 | list_for_each_entry(asoc, &ep->asocs, asocs) { | 2056 | list_for_each_entry_safe(asoc, tmp, &ep->asocs, asocs) { |
| 2057 | err = sctp_sendmsg_check_sflags(asoc, sflags, msg, | 2057 | err = sctp_sendmsg_check_sflags(asoc, sflags, msg, |
| 2058 | msg_len); | 2058 | msg_len); |
| 2059 | if (err == 0) | 2059 | if (err == 0) |
diff --git a/net/sctp/stream.c b/net/sctp/stream.c index 80e0ae5534ec..f24633114dfd 100644 --- a/net/sctp/stream.c +++ b/net/sctp/stream.c | |||
| @@ -84,6 +84,19 @@ static void fa_zero(struct flex_array *fa, size_t index, size_t count) | |||
| 84 | } | 84 | } |
| 85 | } | 85 | } |
| 86 | 86 | ||
| 87 | static size_t fa_index(struct flex_array *fa, void *elem, size_t count) | ||
| 88 | { | ||
| 89 | size_t index = 0; | ||
| 90 | |||
| 91 | while (count--) { | ||
| 92 | if (elem == flex_array_get(fa, index)) | ||
| 93 | break; | ||
| 94 | index++; | ||
| 95 | } | ||
| 96 | |||
| 97 | return index; | ||
| 98 | } | ||
| 99 | |||
| 87 | /* Migrates chunks from stream queues to new stream queues if needed, | 100 | /* Migrates chunks from stream queues to new stream queues if needed, |
| 88 | * but not across associations. Also, removes those chunks to streams | 101 | * but not across associations. Also, removes those chunks to streams |
| 89 | * higher than the new max. | 102 | * higher than the new max. |
| @@ -147,6 +160,13 @@ static int sctp_stream_alloc_out(struct sctp_stream *stream, __u16 outcnt, | |||
| 147 | 160 | ||
| 148 | if (stream->out) { | 161 | if (stream->out) { |
| 149 | fa_copy(out, stream->out, 0, min(outcnt, stream->outcnt)); | 162 | fa_copy(out, stream->out, 0, min(outcnt, stream->outcnt)); |
| 163 | if (stream->out_curr) { | ||
| 164 | size_t index = fa_index(stream->out, stream->out_curr, | ||
| 165 | stream->outcnt); | ||
| 166 | |||
| 167 | BUG_ON(index == stream->outcnt); | ||
| 168 | stream->out_curr = flex_array_get(out, index); | ||
| 169 | } | ||
| 150 | fa_free(stream->out); | 170 | fa_free(stream->out); |
| 151 | } | 171 | } |
| 152 | 172 | ||
diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c index c4e56602e0c6..b04a813fc865 100644 --- a/net/smc/af_smc.c +++ b/net/smc/af_smc.c | |||
| @@ -1505,6 +1505,11 @@ static int smc_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, | |||
| 1505 | 1505 | ||
| 1506 | smc = smc_sk(sk); | 1506 | smc = smc_sk(sk); |
| 1507 | lock_sock(sk); | 1507 | lock_sock(sk); |
| 1508 | if (sk->sk_state == SMC_CLOSED && (sk->sk_shutdown & RCV_SHUTDOWN)) { | ||
| 1509 | /* socket was connected before, no more data to read */ | ||
| 1510 | rc = 0; | ||
| 1511 | goto out; | ||
| 1512 | } | ||
| 1508 | if ((sk->sk_state == SMC_INIT) || | 1513 | if ((sk->sk_state == SMC_INIT) || |
| 1509 | (sk->sk_state == SMC_LISTEN) || | 1514 | (sk->sk_state == SMC_LISTEN) || |
| 1510 | (sk->sk_state == SMC_CLOSED)) | 1515 | (sk->sk_state == SMC_CLOSED)) |
| @@ -1840,7 +1845,11 @@ static ssize_t smc_splice_read(struct socket *sock, loff_t *ppos, | |||
| 1840 | 1845 | ||
| 1841 | smc = smc_sk(sk); | 1846 | smc = smc_sk(sk); |
| 1842 | lock_sock(sk); | 1847 | lock_sock(sk); |
| 1843 | 1848 | if (sk->sk_state == SMC_CLOSED && (sk->sk_shutdown & RCV_SHUTDOWN)) { | |
| 1849 | /* socket was connected before, no more data to read */ | ||
| 1850 | rc = 0; | ||
| 1851 | goto out; | ||
| 1852 | } | ||
| 1844 | if (sk->sk_state == SMC_INIT || | 1853 | if (sk->sk_state == SMC_INIT || |
| 1845 | sk->sk_state == SMC_LISTEN || | 1854 | sk->sk_state == SMC_LISTEN || |
| 1846 | sk->sk_state == SMC_CLOSED) | 1855 | sk->sk_state == SMC_CLOSED) |
diff --git a/net/smc/smc_cdc.c b/net/smc/smc_cdc.c index db83332ac1c8..a712c9f8699b 100644 --- a/net/smc/smc_cdc.c +++ b/net/smc/smc_cdc.c | |||
| @@ -21,13 +21,6 @@ | |||
| 21 | 21 | ||
| 22 | /********************************** send *************************************/ | 22 | /********************************** send *************************************/ |
| 23 | 23 | ||
| 24 | struct smc_cdc_tx_pend { | ||
| 25 | struct smc_connection *conn; /* socket connection */ | ||
| 26 | union smc_host_cursor cursor; /* tx sndbuf cursor sent */ | ||
| 27 | union smc_host_cursor p_cursor; /* rx RMBE cursor produced */ | ||
| 28 | u16 ctrl_seq; /* conn. tx sequence # */ | ||
| 29 | }; | ||
| 30 | |||
| 31 | /* handler for send/transmission completion of a CDC msg */ | 24 | /* handler for send/transmission completion of a CDC msg */ |
| 32 | static void smc_cdc_tx_handler(struct smc_wr_tx_pend_priv *pnd_snd, | 25 | static void smc_cdc_tx_handler(struct smc_wr_tx_pend_priv *pnd_snd, |
| 33 | struct smc_link *link, | 26 | struct smc_link *link, |
| @@ -61,12 +54,14 @@ static void smc_cdc_tx_handler(struct smc_wr_tx_pend_priv *pnd_snd, | |||
| 61 | 54 | ||
| 62 | int smc_cdc_get_free_slot(struct smc_connection *conn, | 55 | int smc_cdc_get_free_slot(struct smc_connection *conn, |
| 63 | struct smc_wr_buf **wr_buf, | 56 | struct smc_wr_buf **wr_buf, |
| 57 | struct smc_rdma_wr **wr_rdma_buf, | ||
| 64 | struct smc_cdc_tx_pend **pend) | 58 | struct smc_cdc_tx_pend **pend) |
| 65 | { | 59 | { |
| 66 | struct smc_link *link = &conn->lgr->lnk[SMC_SINGLE_LINK]; | 60 | struct smc_link *link = &conn->lgr->lnk[SMC_SINGLE_LINK]; |
| 67 | int rc; | 61 | int rc; |
| 68 | 62 | ||
| 69 | rc = smc_wr_tx_get_free_slot(link, smc_cdc_tx_handler, wr_buf, | 63 | rc = smc_wr_tx_get_free_slot(link, smc_cdc_tx_handler, wr_buf, |
| 64 | wr_rdma_buf, | ||
| 70 | (struct smc_wr_tx_pend_priv **)pend); | 65 | (struct smc_wr_tx_pend_priv **)pend); |
| 71 | if (!conn->alert_token_local) | 66 | if (!conn->alert_token_local) |
| 72 | /* abnormal termination */ | 67 | /* abnormal termination */ |
| @@ -96,6 +91,7 @@ int smc_cdc_msg_send(struct smc_connection *conn, | |||
| 96 | struct smc_wr_buf *wr_buf, | 91 | struct smc_wr_buf *wr_buf, |
| 97 | struct smc_cdc_tx_pend *pend) | 92 | struct smc_cdc_tx_pend *pend) |
| 98 | { | 93 | { |
| 94 | union smc_host_cursor cfed; | ||
| 99 | struct smc_link *link; | 95 | struct smc_link *link; |
| 100 | int rc; | 96 | int rc; |
| 101 | 97 | ||
| @@ -107,10 +103,10 @@ int smc_cdc_msg_send(struct smc_connection *conn, | |||
| 107 | conn->local_tx_ctrl.seqno = conn->tx_cdc_seq; | 103 | conn->local_tx_ctrl.seqno = conn->tx_cdc_seq; |
| 108 | smc_host_msg_to_cdc((struct smc_cdc_msg *)wr_buf, | 104 | smc_host_msg_to_cdc((struct smc_cdc_msg *)wr_buf, |
| 109 | &conn->local_tx_ctrl, conn); | 105 | &conn->local_tx_ctrl, conn); |
| 106 | smc_curs_copy(&cfed, &((struct smc_host_cdc_msg *)wr_buf)->cons, conn); | ||
| 110 | rc = smc_wr_tx_send(link, (struct smc_wr_tx_pend_priv *)pend); | 107 | rc = smc_wr_tx_send(link, (struct smc_wr_tx_pend_priv *)pend); |
| 111 | if (!rc) | 108 | if (!rc) |
| 112 | smc_curs_copy(&conn->rx_curs_confirmed, | 109 | smc_curs_copy(&conn->rx_curs_confirmed, &cfed, conn); |
| 113 | &conn->local_tx_ctrl.cons, conn); | ||
| 114 | 110 | ||
| 115 | return rc; | 111 | return rc; |
| 116 | } | 112 | } |
| @@ -121,11 +117,14 @@ static int smcr_cdc_get_slot_and_msg_send(struct smc_connection *conn) | |||
| 121 | struct smc_wr_buf *wr_buf; | 117 | struct smc_wr_buf *wr_buf; |
| 122 | int rc; | 118 | int rc; |
| 123 | 119 | ||
| 124 | rc = smc_cdc_get_free_slot(conn, &wr_buf, &pend); | 120 | rc = smc_cdc_get_free_slot(conn, &wr_buf, NULL, &pend); |
| 125 | if (rc) | 121 | if (rc) |
| 126 | return rc; | 122 | return rc; |
| 127 | 123 | ||
| 128 | return smc_cdc_msg_send(conn, wr_buf, pend); | 124 | spin_lock_bh(&conn->send_lock); |
| 125 | rc = smc_cdc_msg_send(conn, wr_buf, pend); | ||
| 126 | spin_unlock_bh(&conn->send_lock); | ||
| 127 | return rc; | ||
| 129 | } | 128 | } |
| 130 | 129 | ||
| 131 | int smc_cdc_get_slot_and_msg_send(struct smc_connection *conn) | 130 | int smc_cdc_get_slot_and_msg_send(struct smc_connection *conn) |
diff --git a/net/smc/smc_cdc.h b/net/smc/smc_cdc.h index b5bfe38c7f9b..271e2524dc8f 100644 --- a/net/smc/smc_cdc.h +++ b/net/smc/smc_cdc.h | |||
| @@ -160,7 +160,9 @@ static inline void smcd_curs_copy(union smcd_cdc_cursor *tgt, | |||
| 160 | #endif | 160 | #endif |
| 161 | } | 161 | } |
| 162 | 162 | ||
| 163 | /* calculate cursor difference between old and new, where old <= new */ | 163 | /* calculate cursor difference between old and new, where old <= new and |
| 164 | * difference cannot exceed size | ||
| 165 | */ | ||
| 164 | static inline int smc_curs_diff(unsigned int size, | 166 | static inline int smc_curs_diff(unsigned int size, |
| 165 | union smc_host_cursor *old, | 167 | union smc_host_cursor *old, |
| 166 | union smc_host_cursor *new) | 168 | union smc_host_cursor *new) |
| @@ -185,6 +187,28 @@ static inline int smc_curs_comp(unsigned int size, | |||
| 185 | return smc_curs_diff(size, old, new); | 187 | return smc_curs_diff(size, old, new); |
| 186 | } | 188 | } |
| 187 | 189 | ||
| 190 | /* calculate cursor difference between old and new, where old <= new and | ||
| 191 | * difference may exceed size | ||
| 192 | */ | ||
| 193 | static inline int smc_curs_diff_large(unsigned int size, | ||
| 194 | union smc_host_cursor *old, | ||
| 195 | union smc_host_cursor *new) | ||
| 196 | { | ||
| 197 | if (old->wrap < new->wrap) | ||
| 198 | return min_t(int, | ||
| 199 | (size - old->count) + new->count + | ||
| 200 | (new->wrap - old->wrap - 1) * size, | ||
| 201 | size); | ||
| 202 | |||
| 203 | if (old->wrap > new->wrap) /* wrap has switched from 0xffff to 0x0000 */ | ||
| 204 | return min_t(int, | ||
| 205 | (size - old->count) + new->count + | ||
| 206 | (new->wrap + 0xffff - old->wrap) * size, | ||
| 207 | size); | ||
| 208 | |||
| 209 | return max_t(int, 0, (new->count - old->count)); | ||
| 210 | } | ||
| 211 | |||
| 188 | static inline void smc_host_cursor_to_cdc(union smc_cdc_cursor *peer, | 212 | static inline void smc_host_cursor_to_cdc(union smc_cdc_cursor *peer, |
| 189 | union smc_host_cursor *local, | 213 | union smc_host_cursor *local, |
| 190 | struct smc_connection *conn) | 214 | struct smc_connection *conn) |
| @@ -270,10 +294,16 @@ static inline void smc_cdc_msg_to_host(struct smc_host_cdc_msg *local, | |||
| 270 | smcr_cdc_msg_to_host(local, peer, conn); | 294 | smcr_cdc_msg_to_host(local, peer, conn); |
| 271 | } | 295 | } |
| 272 | 296 | ||
| 273 | struct smc_cdc_tx_pend; | 297 | struct smc_cdc_tx_pend { |
| 298 | struct smc_connection *conn; /* socket connection */ | ||
| 299 | union smc_host_cursor cursor; /* tx sndbuf cursor sent */ | ||
| 300 | union smc_host_cursor p_cursor; /* rx RMBE cursor produced */ | ||
| 301 | u16 ctrl_seq; /* conn. tx sequence # */ | ||
| 302 | }; | ||
| 274 | 303 | ||
| 275 | int smc_cdc_get_free_slot(struct smc_connection *conn, | 304 | int smc_cdc_get_free_slot(struct smc_connection *conn, |
| 276 | struct smc_wr_buf **wr_buf, | 305 | struct smc_wr_buf **wr_buf, |
| 306 | struct smc_rdma_wr **wr_rdma_buf, | ||
| 277 | struct smc_cdc_tx_pend **pend); | 307 | struct smc_cdc_tx_pend **pend); |
| 278 | void smc_cdc_tx_dismiss_slots(struct smc_connection *conn); | 308 | void smc_cdc_tx_dismiss_slots(struct smc_connection *conn); |
| 279 | int smc_cdc_msg_send(struct smc_connection *conn, struct smc_wr_buf *wr_buf, | 309 | int smc_cdc_msg_send(struct smc_connection *conn, struct smc_wr_buf *wr_buf, |
diff --git a/net/smc/smc_clc.c b/net/smc/smc_clc.c index 776e9dfc915d..d53fd588d1f5 100644 --- a/net/smc/smc_clc.c +++ b/net/smc/smc_clc.c | |||
| @@ -378,7 +378,7 @@ int smc_clc_send_decline(struct smc_sock *smc, u32 peer_diag_info) | |||
| 378 | vec.iov_len = sizeof(struct smc_clc_msg_decline); | 378 | vec.iov_len = sizeof(struct smc_clc_msg_decline); |
| 379 | len = kernel_sendmsg(smc->clcsock, &msg, &vec, 1, | 379 | len = kernel_sendmsg(smc->clcsock, &msg, &vec, 1, |
| 380 | sizeof(struct smc_clc_msg_decline)); | 380 | sizeof(struct smc_clc_msg_decline)); |
| 381 | if (len < sizeof(struct smc_clc_msg_decline)) | 381 | if (len < 0 || len < sizeof(struct smc_clc_msg_decline)) |
| 382 | len = -EPROTO; | 382 | len = -EPROTO; |
| 383 | return len > 0 ? 0 : len; | 383 | return len > 0 ? 0 : len; |
| 384 | } | 384 | } |
diff --git a/net/smc/smc_close.c b/net/smc/smc_close.c index ea2b87f29469..e39cadda1bf5 100644 --- a/net/smc/smc_close.c +++ b/net/smc/smc_close.c | |||
| @@ -345,14 +345,7 @@ static void smc_close_passive_work(struct work_struct *work) | |||
| 345 | 345 | ||
| 346 | switch (sk->sk_state) { | 346 | switch (sk->sk_state) { |
| 347 | case SMC_INIT: | 347 | case SMC_INIT: |
| 348 | if (atomic_read(&conn->bytes_to_rcv) || | 348 | sk->sk_state = SMC_APPCLOSEWAIT1; |
| 349 | (rxflags->peer_done_writing && | ||
| 350 | !smc_cdc_rxed_any_close(conn))) { | ||
| 351 | sk->sk_state = SMC_APPCLOSEWAIT1; | ||
| 352 | } else { | ||
| 353 | sk->sk_state = SMC_CLOSED; | ||
| 354 | sock_put(sk); /* passive closing */ | ||
| 355 | } | ||
| 356 | break; | 349 | break; |
| 357 | case SMC_ACTIVE: | 350 | case SMC_ACTIVE: |
| 358 | sk->sk_state = SMC_APPCLOSEWAIT1; | 351 | sk->sk_state = SMC_APPCLOSEWAIT1; |
diff --git a/net/smc/smc_core.c b/net/smc/smc_core.c index 35c1cdc93e1c..aa1c551cee81 100644 --- a/net/smc/smc_core.c +++ b/net/smc/smc_core.c | |||
| @@ -128,6 +128,8 @@ static void smc_lgr_unregister_conn(struct smc_connection *conn) | |||
| 128 | { | 128 | { |
| 129 | struct smc_link_group *lgr = conn->lgr; | 129 | struct smc_link_group *lgr = conn->lgr; |
| 130 | 130 | ||
| 131 | if (!lgr) | ||
| 132 | return; | ||
| 131 | write_lock_bh(&lgr->conns_lock); | 133 | write_lock_bh(&lgr->conns_lock); |
| 132 | if (conn->alert_token_local) { | 134 | if (conn->alert_token_local) { |
| 133 | __smc_lgr_unregister_conn(conn); | 135 | __smc_lgr_unregister_conn(conn); |
| @@ -300,13 +302,13 @@ static void smc_buf_unuse(struct smc_connection *conn, | |||
| 300 | conn->sndbuf_desc->used = 0; | 302 | conn->sndbuf_desc->used = 0; |
| 301 | if (conn->rmb_desc) { | 303 | if (conn->rmb_desc) { |
| 302 | if (!conn->rmb_desc->regerr) { | 304 | if (!conn->rmb_desc->regerr) { |
| 303 | conn->rmb_desc->used = 0; | ||
| 304 | if (!lgr->is_smcd) { | 305 | if (!lgr->is_smcd) { |
| 305 | /* unregister rmb with peer */ | 306 | /* unregister rmb with peer */ |
| 306 | smc_llc_do_delete_rkey( | 307 | smc_llc_do_delete_rkey( |
| 307 | &lgr->lnk[SMC_SINGLE_LINK], | 308 | &lgr->lnk[SMC_SINGLE_LINK], |
| 308 | conn->rmb_desc); | 309 | conn->rmb_desc); |
| 309 | } | 310 | } |
| 311 | conn->rmb_desc->used = 0; | ||
| 310 | } else { | 312 | } else { |
| 311 | /* buf registration failed, reuse not possible */ | 313 | /* buf registration failed, reuse not possible */ |
| 312 | write_lock_bh(&lgr->rmbs_lock); | 314 | write_lock_bh(&lgr->rmbs_lock); |
| @@ -628,6 +630,8 @@ int smc_conn_create(struct smc_sock *smc, bool is_smcd, int srv_first_contact, | |||
| 628 | local_contact = SMC_REUSE_CONTACT; | 630 | local_contact = SMC_REUSE_CONTACT; |
| 629 | conn->lgr = lgr; | 631 | conn->lgr = lgr; |
| 630 | smc_lgr_register_conn(conn); /* add smc conn to lgr */ | 632 | smc_lgr_register_conn(conn); /* add smc conn to lgr */ |
| 633 | if (delayed_work_pending(&lgr->free_work)) | ||
| 634 | cancel_delayed_work(&lgr->free_work); | ||
| 631 | write_unlock_bh(&lgr->conns_lock); | 635 | write_unlock_bh(&lgr->conns_lock); |
| 632 | break; | 636 | break; |
| 633 | } | 637 | } |
diff --git a/net/smc/smc_core.h b/net/smc/smc_core.h index b00287989a3d..8806d2afa6ed 100644 --- a/net/smc/smc_core.h +++ b/net/smc/smc_core.h | |||
| @@ -52,6 +52,24 @@ enum smc_wr_reg_state { | |||
| 52 | FAILED /* ib_wr_reg_mr response: failure */ | 52 | FAILED /* ib_wr_reg_mr response: failure */ |
| 53 | }; | 53 | }; |
| 54 | 54 | ||
| 55 | struct smc_rdma_sge { /* sges for RDMA writes */ | ||
| 56 | struct ib_sge wr_tx_rdma_sge[SMC_IB_MAX_SEND_SGE]; | ||
| 57 | }; | ||
| 58 | |||
| 59 | #define SMC_MAX_RDMA_WRITES 2 /* max. # of RDMA writes per | ||
| 60 | * message send | ||
| 61 | */ | ||
| 62 | |||
| 63 | struct smc_rdma_sges { /* sges per message send */ | ||
| 64 | struct smc_rdma_sge tx_rdma_sge[SMC_MAX_RDMA_WRITES]; | ||
| 65 | }; | ||
| 66 | |||
| 67 | struct smc_rdma_wr { /* work requests per message | ||
| 68 | * send | ||
| 69 | */ | ||
| 70 | struct ib_rdma_wr wr_tx_rdma[SMC_MAX_RDMA_WRITES]; | ||
| 71 | }; | ||
| 72 | |||
| 55 | struct smc_link { | 73 | struct smc_link { |
| 56 | struct smc_ib_device *smcibdev; /* ib-device */ | 74 | struct smc_ib_device *smcibdev; /* ib-device */ |
| 57 | u8 ibport; /* port - values 1 | 2 */ | 75 | u8 ibport; /* port - values 1 | 2 */ |
| @@ -64,6 +82,8 @@ struct smc_link { | |||
| 64 | struct smc_wr_buf *wr_tx_bufs; /* WR send payload buffers */ | 82 | struct smc_wr_buf *wr_tx_bufs; /* WR send payload buffers */ |
| 65 | struct ib_send_wr *wr_tx_ibs; /* WR send meta data */ | 83 | struct ib_send_wr *wr_tx_ibs; /* WR send meta data */ |
| 66 | struct ib_sge *wr_tx_sges; /* WR send gather meta data */ | 84 | struct ib_sge *wr_tx_sges; /* WR send gather meta data */ |
| 85 | struct smc_rdma_sges *wr_tx_rdma_sges;/*RDMA WRITE gather meta data*/ | ||
| 86 | struct smc_rdma_wr *wr_tx_rdmas; /* WR RDMA WRITE */ | ||
| 67 | struct smc_wr_tx_pend *wr_tx_pends; /* WR send waiting for CQE */ | 87 | struct smc_wr_tx_pend *wr_tx_pends; /* WR send waiting for CQE */ |
| 68 | /* above four vectors have wr_tx_cnt elements and use the same index */ | 88 | /* above four vectors have wr_tx_cnt elements and use the same index */ |
| 69 | dma_addr_t wr_tx_dma_addr; /* DMA address of wr_tx_bufs */ | 89 | dma_addr_t wr_tx_dma_addr; /* DMA address of wr_tx_bufs */ |
diff --git a/net/smc/smc_ib.c b/net/smc/smc_ib.c index e519ef29c0ff..76487a16934e 100644 --- a/net/smc/smc_ib.c +++ b/net/smc/smc_ib.c | |||
| @@ -289,8 +289,8 @@ int smc_ib_create_protection_domain(struct smc_link *lnk) | |||
| 289 | 289 | ||
| 290 | static void smc_ib_qp_event_handler(struct ib_event *ibevent, void *priv) | 290 | static void smc_ib_qp_event_handler(struct ib_event *ibevent, void *priv) |
| 291 | { | 291 | { |
| 292 | struct smc_ib_device *smcibdev = | 292 | struct smc_link *lnk = (struct smc_link *)priv; |
| 293 | (struct smc_ib_device *)ibevent->device; | 293 | struct smc_ib_device *smcibdev = lnk->smcibdev; |
| 294 | u8 port_idx; | 294 | u8 port_idx; |
| 295 | 295 | ||
| 296 | switch (ibevent->event) { | 296 | switch (ibevent->event) { |
| @@ -298,7 +298,7 @@ static void smc_ib_qp_event_handler(struct ib_event *ibevent, void *priv) | |||
| 298 | case IB_EVENT_GID_CHANGE: | 298 | case IB_EVENT_GID_CHANGE: |
| 299 | case IB_EVENT_PORT_ERR: | 299 | case IB_EVENT_PORT_ERR: |
| 300 | case IB_EVENT_QP_ACCESS_ERR: | 300 | case IB_EVENT_QP_ACCESS_ERR: |
| 301 | port_idx = ibevent->element.port_num - 1; | 301 | port_idx = ibevent->element.qp->port - 1; |
| 302 | set_bit(port_idx, &smcibdev->port_event_mask); | 302 | set_bit(port_idx, &smcibdev->port_event_mask); |
| 303 | schedule_work(&smcibdev->port_event_work); | 303 | schedule_work(&smcibdev->port_event_work); |
| 304 | break; | 304 | break; |
diff --git a/net/smc/smc_llc.c b/net/smc/smc_llc.c index a6d3623d06f4..4fd60c522802 100644 --- a/net/smc/smc_llc.c +++ b/net/smc/smc_llc.c | |||
| @@ -166,7 +166,8 @@ static int smc_llc_add_pending_send(struct smc_link *link, | |||
| 166 | { | 166 | { |
| 167 | int rc; | 167 | int rc; |
| 168 | 168 | ||
| 169 | rc = smc_wr_tx_get_free_slot(link, smc_llc_tx_handler, wr_buf, pend); | 169 | rc = smc_wr_tx_get_free_slot(link, smc_llc_tx_handler, wr_buf, NULL, |
| 170 | pend); | ||
| 170 | if (rc < 0) | 171 | if (rc < 0) |
| 171 | return rc; | 172 | return rc; |
| 172 | BUILD_BUG_ON_MSG( | 173 | BUILD_BUG_ON_MSG( |
diff --git a/net/smc/smc_pnet.c b/net/smc/smc_pnet.c index 7cb3e4f07c10..632c3109dee5 100644 --- a/net/smc/smc_pnet.c +++ b/net/smc/smc_pnet.c | |||
| @@ -27,7 +27,7 @@ | |||
| 27 | static struct nla_policy smc_pnet_policy[SMC_PNETID_MAX + 1] = { | 27 | static struct nla_policy smc_pnet_policy[SMC_PNETID_MAX + 1] = { |
| 28 | [SMC_PNETID_NAME] = { | 28 | [SMC_PNETID_NAME] = { |
| 29 | .type = NLA_NUL_STRING, | 29 | .type = NLA_NUL_STRING, |
| 30 | .len = SMC_MAX_PNETID_LEN - 1 | 30 | .len = SMC_MAX_PNETID_LEN |
| 31 | }, | 31 | }, |
| 32 | [SMC_PNETID_ETHNAME] = { | 32 | [SMC_PNETID_ETHNAME] = { |
| 33 | .type = NLA_NUL_STRING, | 33 | .type = NLA_NUL_STRING, |
diff --git a/net/smc/smc_tx.c b/net/smc/smc_tx.c index d8366ed51757..f93f3580c100 100644 --- a/net/smc/smc_tx.c +++ b/net/smc/smc_tx.c | |||
| @@ -165,12 +165,11 @@ int smc_tx_sendmsg(struct smc_sock *smc, struct msghdr *msg, size_t len) | |||
| 165 | conn->local_tx_ctrl.prod_flags.urg_data_pending = 1; | 165 | conn->local_tx_ctrl.prod_flags.urg_data_pending = 1; |
| 166 | 166 | ||
| 167 | if (!atomic_read(&conn->sndbuf_space) || conn->urg_tx_pend) { | 167 | if (!atomic_read(&conn->sndbuf_space) || conn->urg_tx_pend) { |
| 168 | if (send_done) | ||
| 169 | return send_done; | ||
| 168 | rc = smc_tx_wait(smc, msg->msg_flags); | 170 | rc = smc_tx_wait(smc, msg->msg_flags); |
| 169 | if (rc) { | 171 | if (rc) |
| 170 | if (send_done) | ||
| 171 | return send_done; | ||
| 172 | goto out_err; | 172 | goto out_err; |
| 173 | } | ||
| 174 | continue; | 173 | continue; |
| 175 | } | 174 | } |
| 176 | 175 | ||
| @@ -267,27 +266,23 @@ int smcd_tx_ism_write(struct smc_connection *conn, void *data, size_t len, | |||
| 267 | 266 | ||
| 268 | /* sndbuf consumer: actual data transfer of one target chunk with RDMA write */ | 267 | /* sndbuf consumer: actual data transfer of one target chunk with RDMA write */ |
| 269 | static int smc_tx_rdma_write(struct smc_connection *conn, int peer_rmbe_offset, | 268 | static int smc_tx_rdma_write(struct smc_connection *conn, int peer_rmbe_offset, |
| 270 | int num_sges, struct ib_sge sges[]) | 269 | int num_sges, struct ib_rdma_wr *rdma_wr) |
| 271 | { | 270 | { |
| 272 | struct smc_link_group *lgr = conn->lgr; | 271 | struct smc_link_group *lgr = conn->lgr; |
| 273 | struct ib_rdma_wr rdma_wr; | ||
| 274 | struct smc_link *link; | 272 | struct smc_link *link; |
| 275 | int rc; | 273 | int rc; |
| 276 | 274 | ||
| 277 | memset(&rdma_wr, 0, sizeof(rdma_wr)); | ||
| 278 | link = &lgr->lnk[SMC_SINGLE_LINK]; | 275 | link = &lgr->lnk[SMC_SINGLE_LINK]; |
| 279 | rdma_wr.wr.wr_id = smc_wr_tx_get_next_wr_id(link); | 276 | rdma_wr->wr.wr_id = smc_wr_tx_get_next_wr_id(link); |
| 280 | rdma_wr.wr.sg_list = sges; | 277 | rdma_wr->wr.num_sge = num_sges; |
| 281 | rdma_wr.wr.num_sge = num_sges; | 278 | rdma_wr->remote_addr = |
| 282 | rdma_wr.wr.opcode = IB_WR_RDMA_WRITE; | ||
| 283 | rdma_wr.remote_addr = | ||
| 284 | lgr->rtokens[conn->rtoken_idx][SMC_SINGLE_LINK].dma_addr + | 279 | lgr->rtokens[conn->rtoken_idx][SMC_SINGLE_LINK].dma_addr + |
| 285 | /* RMBE within RMB */ | 280 | /* RMBE within RMB */ |
| 286 | conn->tx_off + | 281 | conn->tx_off + |
| 287 | /* offset within RMBE */ | 282 | /* offset within RMBE */ |
| 288 | peer_rmbe_offset; | 283 | peer_rmbe_offset; |
| 289 | rdma_wr.rkey = lgr->rtokens[conn->rtoken_idx][SMC_SINGLE_LINK].rkey; | 284 | rdma_wr->rkey = lgr->rtokens[conn->rtoken_idx][SMC_SINGLE_LINK].rkey; |
| 290 | rc = ib_post_send(link->roce_qp, &rdma_wr.wr, NULL); | 285 | rc = ib_post_send(link->roce_qp, &rdma_wr->wr, NULL); |
| 291 | if (rc) { | 286 | if (rc) { |
| 292 | conn->local_tx_ctrl.conn_state_flags.peer_conn_abort = 1; | 287 | conn->local_tx_ctrl.conn_state_flags.peer_conn_abort = 1; |
| 293 | smc_lgr_terminate(lgr); | 288 | smc_lgr_terminate(lgr); |
| @@ -314,24 +309,25 @@ static inline void smc_tx_advance_cursors(struct smc_connection *conn, | |||
| 314 | /* SMC-R helper for smc_tx_rdma_writes() */ | 309 | /* SMC-R helper for smc_tx_rdma_writes() */ |
| 315 | static int smcr_tx_rdma_writes(struct smc_connection *conn, size_t len, | 310 | static int smcr_tx_rdma_writes(struct smc_connection *conn, size_t len, |
| 316 | size_t src_off, size_t src_len, | 311 | size_t src_off, size_t src_len, |
| 317 | size_t dst_off, size_t dst_len) | 312 | size_t dst_off, size_t dst_len, |
| 313 | struct smc_rdma_wr *wr_rdma_buf) | ||
| 318 | { | 314 | { |
| 319 | dma_addr_t dma_addr = | 315 | dma_addr_t dma_addr = |
| 320 | sg_dma_address(conn->sndbuf_desc->sgt[SMC_SINGLE_LINK].sgl); | 316 | sg_dma_address(conn->sndbuf_desc->sgt[SMC_SINGLE_LINK].sgl); |
| 321 | struct smc_link *link = &conn->lgr->lnk[SMC_SINGLE_LINK]; | ||
| 322 | int src_len_sum = src_len, dst_len_sum = dst_len; | 317 | int src_len_sum = src_len, dst_len_sum = dst_len; |
| 323 | struct ib_sge sges[SMC_IB_MAX_SEND_SGE]; | ||
| 324 | int sent_count = src_off; | 318 | int sent_count = src_off; |
| 325 | int srcchunk, dstchunk; | 319 | int srcchunk, dstchunk; |
| 326 | int num_sges; | 320 | int num_sges; |
| 327 | int rc; | 321 | int rc; |
| 328 | 322 | ||
| 329 | for (dstchunk = 0; dstchunk < 2; dstchunk++) { | 323 | for (dstchunk = 0; dstchunk < 2; dstchunk++) { |
| 324 | struct ib_sge *sge = | ||
| 325 | wr_rdma_buf->wr_tx_rdma[dstchunk].wr.sg_list; | ||
| 326 | |||
| 330 | num_sges = 0; | 327 | num_sges = 0; |
| 331 | for (srcchunk = 0; srcchunk < 2; srcchunk++) { | 328 | for (srcchunk = 0; srcchunk < 2; srcchunk++) { |
| 332 | sges[srcchunk].addr = dma_addr + src_off; | 329 | sge[srcchunk].addr = dma_addr + src_off; |
| 333 | sges[srcchunk].length = src_len; | 330 | sge[srcchunk].length = src_len; |
| 334 | sges[srcchunk].lkey = link->roce_pd->local_dma_lkey; | ||
| 335 | num_sges++; | 331 | num_sges++; |
| 336 | 332 | ||
| 337 | src_off += src_len; | 333 | src_off += src_len; |
| @@ -344,7 +340,8 @@ static int smcr_tx_rdma_writes(struct smc_connection *conn, size_t len, | |||
| 344 | src_len = dst_len - src_len; /* remainder */ | 340 | src_len = dst_len - src_len; /* remainder */ |
| 345 | src_len_sum += src_len; | 341 | src_len_sum += src_len; |
| 346 | } | 342 | } |
| 347 | rc = smc_tx_rdma_write(conn, dst_off, num_sges, sges); | 343 | rc = smc_tx_rdma_write(conn, dst_off, num_sges, |
| 344 | &wr_rdma_buf->wr_tx_rdma[dstchunk]); | ||
| 348 | if (rc) | 345 | if (rc) |
| 349 | return rc; | 346 | return rc; |
| 350 | if (dst_len_sum == len) | 347 | if (dst_len_sum == len) |
| @@ -403,7 +400,8 @@ static int smcd_tx_rdma_writes(struct smc_connection *conn, size_t len, | |||
| 403 | /* sndbuf consumer: prepare all necessary (src&dst) chunks of data transmit; | 400 | /* sndbuf consumer: prepare all necessary (src&dst) chunks of data transmit; |
| 404 | * usable snd_wnd as max transmit | 401 | * usable snd_wnd as max transmit |
| 405 | */ | 402 | */ |
| 406 | static int smc_tx_rdma_writes(struct smc_connection *conn) | 403 | static int smc_tx_rdma_writes(struct smc_connection *conn, |
| 404 | struct smc_rdma_wr *wr_rdma_buf) | ||
| 407 | { | 405 | { |
| 408 | size_t len, src_len, dst_off, dst_len; /* current chunk values */ | 406 | size_t len, src_len, dst_off, dst_len; /* current chunk values */ |
| 409 | union smc_host_cursor sent, prep, prod, cons; | 407 | union smc_host_cursor sent, prep, prod, cons; |
| @@ -464,7 +462,7 @@ static int smc_tx_rdma_writes(struct smc_connection *conn) | |||
| 464 | dst_off, dst_len); | 462 | dst_off, dst_len); |
| 465 | else | 463 | else |
| 466 | rc = smcr_tx_rdma_writes(conn, len, sent.count, src_len, | 464 | rc = smcr_tx_rdma_writes(conn, len, sent.count, src_len, |
| 467 | dst_off, dst_len); | 465 | dst_off, dst_len, wr_rdma_buf); |
| 468 | if (rc) | 466 | if (rc) |
| 469 | return rc; | 467 | return rc; |
| 470 | 468 | ||
| @@ -485,31 +483,30 @@ static int smc_tx_rdma_writes(struct smc_connection *conn) | |||
| 485 | static int smcr_tx_sndbuf_nonempty(struct smc_connection *conn) | 483 | static int smcr_tx_sndbuf_nonempty(struct smc_connection *conn) |
| 486 | { | 484 | { |
| 487 | struct smc_cdc_producer_flags *pflags; | 485 | struct smc_cdc_producer_flags *pflags; |
| 486 | struct smc_rdma_wr *wr_rdma_buf; | ||
| 488 | struct smc_cdc_tx_pend *pend; | 487 | struct smc_cdc_tx_pend *pend; |
| 489 | struct smc_wr_buf *wr_buf; | 488 | struct smc_wr_buf *wr_buf; |
| 490 | int rc; | 489 | int rc; |
| 491 | 490 | ||
| 492 | spin_lock_bh(&conn->send_lock); | 491 | rc = smc_cdc_get_free_slot(conn, &wr_buf, &wr_rdma_buf, &pend); |
| 493 | rc = smc_cdc_get_free_slot(conn, &wr_buf, &pend); | ||
| 494 | if (rc < 0) { | 492 | if (rc < 0) { |
| 495 | if (rc == -EBUSY) { | 493 | if (rc == -EBUSY) { |
| 496 | struct smc_sock *smc = | 494 | struct smc_sock *smc = |
| 497 | container_of(conn, struct smc_sock, conn); | 495 | container_of(conn, struct smc_sock, conn); |
| 498 | 496 | ||
| 499 | if (smc->sk.sk_err == ECONNABORTED) { | 497 | if (smc->sk.sk_err == ECONNABORTED) |
| 500 | rc = sock_error(&smc->sk); | 498 | return sock_error(&smc->sk); |
| 501 | goto out_unlock; | ||
| 502 | } | ||
| 503 | rc = 0; | 499 | rc = 0; |
| 504 | if (conn->alert_token_local) /* connection healthy */ | 500 | if (conn->alert_token_local) /* connection healthy */ |
| 505 | mod_delayed_work(system_wq, &conn->tx_work, | 501 | mod_delayed_work(system_wq, &conn->tx_work, |
| 506 | SMC_TX_WORK_DELAY); | 502 | SMC_TX_WORK_DELAY); |
| 507 | } | 503 | } |
| 508 | goto out_unlock; | 504 | return rc; |
| 509 | } | 505 | } |
| 510 | 506 | ||
| 507 | spin_lock_bh(&conn->send_lock); | ||
| 511 | if (!conn->local_tx_ctrl.prod_flags.urg_data_present) { | 508 | if (!conn->local_tx_ctrl.prod_flags.urg_data_present) { |
| 512 | rc = smc_tx_rdma_writes(conn); | 509 | rc = smc_tx_rdma_writes(conn, wr_rdma_buf); |
| 513 | if (rc) { | 510 | if (rc) { |
| 514 | smc_wr_tx_put_slot(&conn->lgr->lnk[SMC_SINGLE_LINK], | 511 | smc_wr_tx_put_slot(&conn->lgr->lnk[SMC_SINGLE_LINK], |
| 515 | (struct smc_wr_tx_pend_priv *)pend); | 512 | (struct smc_wr_tx_pend_priv *)pend); |
| @@ -536,7 +533,7 @@ static int smcd_tx_sndbuf_nonempty(struct smc_connection *conn) | |||
| 536 | 533 | ||
| 537 | spin_lock_bh(&conn->send_lock); | 534 | spin_lock_bh(&conn->send_lock); |
| 538 | if (!pflags->urg_data_present) | 535 | if (!pflags->urg_data_present) |
| 539 | rc = smc_tx_rdma_writes(conn); | 536 | rc = smc_tx_rdma_writes(conn, NULL); |
| 540 | if (!rc) | 537 | if (!rc) |
| 541 | rc = smcd_cdc_msg_send(conn); | 538 | rc = smcd_cdc_msg_send(conn); |
| 542 | 539 | ||
| @@ -598,7 +595,8 @@ void smc_tx_consumer_update(struct smc_connection *conn, bool force) | |||
| 598 | if (to_confirm > conn->rmbe_update_limit) { | 595 | if (to_confirm > conn->rmbe_update_limit) { |
| 599 | smc_curs_copy(&prod, &conn->local_rx_ctrl.prod, conn); | 596 | smc_curs_copy(&prod, &conn->local_rx_ctrl.prod, conn); |
| 600 | sender_free = conn->rmb_desc->len - | 597 | sender_free = conn->rmb_desc->len - |
| 601 | smc_curs_diff(conn->rmb_desc->len, &prod, &cfed); | 598 | smc_curs_diff_large(conn->rmb_desc->len, |
| 599 | &cfed, &prod); | ||
| 602 | } | 600 | } |
| 603 | 601 | ||
| 604 | if (conn->local_rx_ctrl.prod_flags.cons_curs_upd_req || | 602 | if (conn->local_rx_ctrl.prod_flags.cons_curs_upd_req || |
diff --git a/net/smc/smc_wr.c b/net/smc/smc_wr.c index c2694750a6a8..253aa75dc2b6 100644 --- a/net/smc/smc_wr.c +++ b/net/smc/smc_wr.c | |||
| @@ -160,6 +160,7 @@ static inline int smc_wr_tx_get_free_slot_index(struct smc_link *link, u32 *idx) | |||
| 160 | * @link: Pointer to smc_link used to later send the message. | 160 | * @link: Pointer to smc_link used to later send the message. |
| 161 | * @handler: Send completion handler function pointer. | 161 | * @handler: Send completion handler function pointer. |
| 162 | * @wr_buf: Out value returns pointer to message buffer. | 162 | * @wr_buf: Out value returns pointer to message buffer. |
| 163 | * @wr_rdma_buf: Out value returns pointer to rdma work request. | ||
| 163 | * @wr_pend_priv: Out value returns pointer serving as handler context. | 164 | * @wr_pend_priv: Out value returns pointer serving as handler context. |
| 164 | * | 165 | * |
| 165 | * Return: 0 on success, or -errno on error. | 166 | * Return: 0 on success, or -errno on error. |
| @@ -167,6 +168,7 @@ static inline int smc_wr_tx_get_free_slot_index(struct smc_link *link, u32 *idx) | |||
| 167 | int smc_wr_tx_get_free_slot(struct smc_link *link, | 168 | int smc_wr_tx_get_free_slot(struct smc_link *link, |
| 168 | smc_wr_tx_handler handler, | 169 | smc_wr_tx_handler handler, |
| 169 | struct smc_wr_buf **wr_buf, | 170 | struct smc_wr_buf **wr_buf, |
| 171 | struct smc_rdma_wr **wr_rdma_buf, | ||
| 170 | struct smc_wr_tx_pend_priv **wr_pend_priv) | 172 | struct smc_wr_tx_pend_priv **wr_pend_priv) |
| 171 | { | 173 | { |
| 172 | struct smc_wr_tx_pend *wr_pend; | 174 | struct smc_wr_tx_pend *wr_pend; |
| @@ -204,6 +206,8 @@ int smc_wr_tx_get_free_slot(struct smc_link *link, | |||
| 204 | wr_ib = &link->wr_tx_ibs[idx]; | 206 | wr_ib = &link->wr_tx_ibs[idx]; |
| 205 | wr_ib->wr_id = wr_id; | 207 | wr_ib->wr_id = wr_id; |
| 206 | *wr_buf = &link->wr_tx_bufs[idx]; | 208 | *wr_buf = &link->wr_tx_bufs[idx]; |
| 209 | if (wr_rdma_buf) | ||
| 210 | *wr_rdma_buf = &link->wr_tx_rdmas[idx]; | ||
| 207 | *wr_pend_priv = &wr_pend->priv; | 211 | *wr_pend_priv = &wr_pend->priv; |
| 208 | return 0; | 212 | return 0; |
| 209 | } | 213 | } |
| @@ -218,10 +222,10 @@ int smc_wr_tx_put_slot(struct smc_link *link, | |||
| 218 | u32 idx = pend->idx; | 222 | u32 idx = pend->idx; |
| 219 | 223 | ||
| 220 | /* clear the full struct smc_wr_tx_pend including .priv */ | 224 | /* clear the full struct smc_wr_tx_pend including .priv */ |
| 221 | memset(&link->wr_tx_pends[pend->idx], 0, | 225 | memset(&link->wr_tx_pends[idx], 0, |
| 222 | sizeof(link->wr_tx_pends[pend->idx])); | 226 | sizeof(link->wr_tx_pends[idx])); |
| 223 | memset(&link->wr_tx_bufs[pend->idx], 0, | 227 | memset(&link->wr_tx_bufs[idx], 0, |
| 224 | sizeof(link->wr_tx_bufs[pend->idx])); | 228 | sizeof(link->wr_tx_bufs[idx])); |
| 225 | test_and_clear_bit(idx, link->wr_tx_mask); | 229 | test_and_clear_bit(idx, link->wr_tx_mask); |
| 226 | return 1; | 230 | return 1; |
| 227 | } | 231 | } |
| @@ -465,12 +469,26 @@ static void smc_wr_init_sge(struct smc_link *lnk) | |||
| 465 | lnk->wr_tx_dma_addr + i * SMC_WR_BUF_SIZE; | 469 | lnk->wr_tx_dma_addr + i * SMC_WR_BUF_SIZE; |
| 466 | lnk->wr_tx_sges[i].length = SMC_WR_TX_SIZE; | 470 | lnk->wr_tx_sges[i].length = SMC_WR_TX_SIZE; |
| 467 | lnk->wr_tx_sges[i].lkey = lnk->roce_pd->local_dma_lkey; | 471 | lnk->wr_tx_sges[i].lkey = lnk->roce_pd->local_dma_lkey; |
| 472 | lnk->wr_tx_rdma_sges[i].tx_rdma_sge[0].wr_tx_rdma_sge[0].lkey = | ||
| 473 | lnk->roce_pd->local_dma_lkey; | ||
| 474 | lnk->wr_tx_rdma_sges[i].tx_rdma_sge[0].wr_tx_rdma_sge[1].lkey = | ||
| 475 | lnk->roce_pd->local_dma_lkey; | ||
| 476 | lnk->wr_tx_rdma_sges[i].tx_rdma_sge[1].wr_tx_rdma_sge[0].lkey = | ||
| 477 | lnk->roce_pd->local_dma_lkey; | ||
| 478 | lnk->wr_tx_rdma_sges[i].tx_rdma_sge[1].wr_tx_rdma_sge[1].lkey = | ||
| 479 | lnk->roce_pd->local_dma_lkey; | ||
| 468 | lnk->wr_tx_ibs[i].next = NULL; | 480 | lnk->wr_tx_ibs[i].next = NULL; |
| 469 | lnk->wr_tx_ibs[i].sg_list = &lnk->wr_tx_sges[i]; | 481 | lnk->wr_tx_ibs[i].sg_list = &lnk->wr_tx_sges[i]; |
| 470 | lnk->wr_tx_ibs[i].num_sge = 1; | 482 | lnk->wr_tx_ibs[i].num_sge = 1; |
| 471 | lnk->wr_tx_ibs[i].opcode = IB_WR_SEND; | 483 | lnk->wr_tx_ibs[i].opcode = IB_WR_SEND; |
| 472 | lnk->wr_tx_ibs[i].send_flags = | 484 | lnk->wr_tx_ibs[i].send_flags = |
| 473 | IB_SEND_SIGNALED | IB_SEND_SOLICITED; | 485 | IB_SEND_SIGNALED | IB_SEND_SOLICITED; |
| 486 | lnk->wr_tx_rdmas[i].wr_tx_rdma[0].wr.opcode = IB_WR_RDMA_WRITE; | ||
| 487 | lnk->wr_tx_rdmas[i].wr_tx_rdma[1].wr.opcode = IB_WR_RDMA_WRITE; | ||
| 488 | lnk->wr_tx_rdmas[i].wr_tx_rdma[0].wr.sg_list = | ||
| 489 | lnk->wr_tx_rdma_sges[i].tx_rdma_sge[0].wr_tx_rdma_sge; | ||
| 490 | lnk->wr_tx_rdmas[i].wr_tx_rdma[1].wr.sg_list = | ||
| 491 | lnk->wr_tx_rdma_sges[i].tx_rdma_sge[1].wr_tx_rdma_sge; | ||
| 474 | } | 492 | } |
| 475 | for (i = 0; i < lnk->wr_rx_cnt; i++) { | 493 | for (i = 0; i < lnk->wr_rx_cnt; i++) { |
| 476 | lnk->wr_rx_sges[i].addr = | 494 | lnk->wr_rx_sges[i].addr = |
| @@ -521,8 +539,12 @@ void smc_wr_free_link_mem(struct smc_link *lnk) | |||
| 521 | lnk->wr_tx_mask = NULL; | 539 | lnk->wr_tx_mask = NULL; |
| 522 | kfree(lnk->wr_tx_sges); | 540 | kfree(lnk->wr_tx_sges); |
| 523 | lnk->wr_tx_sges = NULL; | 541 | lnk->wr_tx_sges = NULL; |
| 542 | kfree(lnk->wr_tx_rdma_sges); | ||
| 543 | lnk->wr_tx_rdma_sges = NULL; | ||
| 524 | kfree(lnk->wr_rx_sges); | 544 | kfree(lnk->wr_rx_sges); |
| 525 | lnk->wr_rx_sges = NULL; | 545 | lnk->wr_rx_sges = NULL; |
| 546 | kfree(lnk->wr_tx_rdmas); | ||
| 547 | lnk->wr_tx_rdmas = NULL; | ||
| 526 | kfree(lnk->wr_rx_ibs); | 548 | kfree(lnk->wr_rx_ibs); |
| 527 | lnk->wr_rx_ibs = NULL; | 549 | lnk->wr_rx_ibs = NULL; |
| 528 | kfree(lnk->wr_tx_ibs); | 550 | kfree(lnk->wr_tx_ibs); |
| @@ -552,10 +574,20 @@ int smc_wr_alloc_link_mem(struct smc_link *link) | |||
| 552 | GFP_KERNEL); | 574 | GFP_KERNEL); |
| 553 | if (!link->wr_rx_ibs) | 575 | if (!link->wr_rx_ibs) |
| 554 | goto no_mem_wr_tx_ibs; | 576 | goto no_mem_wr_tx_ibs; |
| 577 | link->wr_tx_rdmas = kcalloc(SMC_WR_BUF_CNT, | ||
| 578 | sizeof(link->wr_tx_rdmas[0]), | ||
| 579 | GFP_KERNEL); | ||
| 580 | if (!link->wr_tx_rdmas) | ||
| 581 | goto no_mem_wr_rx_ibs; | ||
| 582 | link->wr_tx_rdma_sges = kcalloc(SMC_WR_BUF_CNT, | ||
| 583 | sizeof(link->wr_tx_rdma_sges[0]), | ||
| 584 | GFP_KERNEL); | ||
| 585 | if (!link->wr_tx_rdma_sges) | ||
| 586 | goto no_mem_wr_tx_rdmas; | ||
| 555 | link->wr_tx_sges = kcalloc(SMC_WR_BUF_CNT, sizeof(link->wr_tx_sges[0]), | 587 | link->wr_tx_sges = kcalloc(SMC_WR_BUF_CNT, sizeof(link->wr_tx_sges[0]), |
| 556 | GFP_KERNEL); | 588 | GFP_KERNEL); |
| 557 | if (!link->wr_tx_sges) | 589 | if (!link->wr_tx_sges) |
| 558 | goto no_mem_wr_rx_ibs; | 590 | goto no_mem_wr_tx_rdma_sges; |
| 559 | link->wr_rx_sges = kcalloc(SMC_WR_BUF_CNT * 3, | 591 | link->wr_rx_sges = kcalloc(SMC_WR_BUF_CNT * 3, |
| 560 | sizeof(link->wr_rx_sges[0]), | 592 | sizeof(link->wr_rx_sges[0]), |
| 561 | GFP_KERNEL); | 593 | GFP_KERNEL); |
| @@ -579,6 +611,10 @@ no_mem_wr_rx_sges: | |||
| 579 | kfree(link->wr_rx_sges); | 611 | kfree(link->wr_rx_sges); |
| 580 | no_mem_wr_tx_sges: | 612 | no_mem_wr_tx_sges: |
| 581 | kfree(link->wr_tx_sges); | 613 | kfree(link->wr_tx_sges); |
| 614 | no_mem_wr_tx_rdma_sges: | ||
| 615 | kfree(link->wr_tx_rdma_sges); | ||
| 616 | no_mem_wr_tx_rdmas: | ||
| 617 | kfree(link->wr_tx_rdmas); | ||
| 582 | no_mem_wr_rx_ibs: | 618 | no_mem_wr_rx_ibs: |
| 583 | kfree(link->wr_rx_ibs); | 619 | kfree(link->wr_rx_ibs); |
| 584 | no_mem_wr_tx_ibs: | 620 | no_mem_wr_tx_ibs: |
diff --git a/net/smc/smc_wr.h b/net/smc/smc_wr.h index 1d85bb14fd6f..09bf32fd3959 100644 --- a/net/smc/smc_wr.h +++ b/net/smc/smc_wr.h | |||
| @@ -85,6 +85,7 @@ void smc_wr_add_dev(struct smc_ib_device *smcibdev); | |||
| 85 | 85 | ||
| 86 | int smc_wr_tx_get_free_slot(struct smc_link *link, smc_wr_tx_handler handler, | 86 | int smc_wr_tx_get_free_slot(struct smc_link *link, smc_wr_tx_handler handler, |
| 87 | struct smc_wr_buf **wr_buf, | 87 | struct smc_wr_buf **wr_buf, |
| 88 | struct smc_rdma_wr **wrs, | ||
| 88 | struct smc_wr_tx_pend_priv **wr_pend_priv); | 89 | struct smc_wr_tx_pend_priv **wr_pend_priv); |
| 89 | int smc_wr_tx_put_slot(struct smc_link *link, | 90 | int smc_wr_tx_put_slot(struct smc_link *link, |
| 90 | struct smc_wr_tx_pend_priv *wr_pend_priv); | 91 | struct smc_wr_tx_pend_priv *wr_pend_priv); |
diff --git a/net/socket.c b/net/socket.c index e89884e2197b..d80d87a395ea 100644 --- a/net/socket.c +++ b/net/socket.c | |||
| @@ -941,8 +941,7 @@ void dlci_ioctl_set(int (*hook) (unsigned int, void __user *)) | |||
| 941 | EXPORT_SYMBOL(dlci_ioctl_set); | 941 | EXPORT_SYMBOL(dlci_ioctl_set); |
| 942 | 942 | ||
| 943 | static long sock_do_ioctl(struct net *net, struct socket *sock, | 943 | static long sock_do_ioctl(struct net *net, struct socket *sock, |
| 944 | unsigned int cmd, unsigned long arg, | 944 | unsigned int cmd, unsigned long arg) |
| 945 | unsigned int ifreq_size) | ||
| 946 | { | 945 | { |
| 947 | int err; | 946 | int err; |
| 948 | void __user *argp = (void __user *)arg; | 947 | void __user *argp = (void __user *)arg; |
| @@ -968,11 +967,11 @@ static long sock_do_ioctl(struct net *net, struct socket *sock, | |||
| 968 | } else { | 967 | } else { |
| 969 | struct ifreq ifr; | 968 | struct ifreq ifr; |
| 970 | bool need_copyout; | 969 | bool need_copyout; |
| 971 | if (copy_from_user(&ifr, argp, ifreq_size)) | 970 | if (copy_from_user(&ifr, argp, sizeof(struct ifreq))) |
| 972 | return -EFAULT; | 971 | return -EFAULT; |
| 973 | err = dev_ioctl(net, cmd, &ifr, &need_copyout); | 972 | err = dev_ioctl(net, cmd, &ifr, &need_copyout); |
| 974 | if (!err && need_copyout) | 973 | if (!err && need_copyout) |
| 975 | if (copy_to_user(argp, &ifr, ifreq_size)) | 974 | if (copy_to_user(argp, &ifr, sizeof(struct ifreq))) |
| 976 | return -EFAULT; | 975 | return -EFAULT; |
| 977 | } | 976 | } |
| 978 | return err; | 977 | return err; |
| @@ -1071,8 +1070,7 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg) | |||
| 1071 | err = open_related_ns(&net->ns, get_net_ns); | 1070 | err = open_related_ns(&net->ns, get_net_ns); |
| 1072 | break; | 1071 | break; |
| 1073 | default: | 1072 | default: |
| 1074 | err = sock_do_ioctl(net, sock, cmd, arg, | 1073 | err = sock_do_ioctl(net, sock, cmd, arg); |
| 1075 | sizeof(struct ifreq)); | ||
| 1076 | break; | 1074 | break; |
| 1077 | } | 1075 | } |
| 1078 | return err; | 1076 | return err; |
| @@ -2780,8 +2778,7 @@ static int do_siocgstamp(struct net *net, struct socket *sock, | |||
| 2780 | int err; | 2778 | int err; |
| 2781 | 2779 | ||
| 2782 | set_fs(KERNEL_DS); | 2780 | set_fs(KERNEL_DS); |
| 2783 | err = sock_do_ioctl(net, sock, cmd, (unsigned long)&ktv, | 2781 | err = sock_do_ioctl(net, sock, cmd, (unsigned long)&ktv); |
| 2784 | sizeof(struct compat_ifreq)); | ||
| 2785 | set_fs(old_fs); | 2782 | set_fs(old_fs); |
| 2786 | if (!err) | 2783 | if (!err) |
| 2787 | err = compat_put_timeval(&ktv, up); | 2784 | err = compat_put_timeval(&ktv, up); |
| @@ -2797,8 +2794,7 @@ static int do_siocgstampns(struct net *net, struct socket *sock, | |||
| 2797 | int err; | 2794 | int err; |
| 2798 | 2795 | ||
| 2799 | set_fs(KERNEL_DS); | 2796 | set_fs(KERNEL_DS); |
| 2800 | err = sock_do_ioctl(net, sock, cmd, (unsigned long)&kts, | 2797 | err = sock_do_ioctl(net, sock, cmd, (unsigned long)&kts); |
| 2801 | sizeof(struct compat_ifreq)); | ||
| 2802 | set_fs(old_fs); | 2798 | set_fs(old_fs); |
| 2803 | if (!err) | 2799 | if (!err) |
| 2804 | err = compat_put_timespec(&kts, up); | 2800 | err = compat_put_timespec(&kts, up); |
| @@ -2994,6 +2990,54 @@ static int compat_ifr_data_ioctl(struct net *net, unsigned int cmd, | |||
| 2994 | return dev_ioctl(net, cmd, &ifreq, NULL); | 2990 | return dev_ioctl(net, cmd, &ifreq, NULL); |
| 2995 | } | 2991 | } |
| 2996 | 2992 | ||
| 2993 | static int compat_ifreq_ioctl(struct net *net, struct socket *sock, | ||
| 2994 | unsigned int cmd, | ||
| 2995 | struct compat_ifreq __user *uifr32) | ||
| 2996 | { | ||
| 2997 | struct ifreq __user *uifr; | ||
| 2998 | int err; | ||
| 2999 | |||
| 3000 | /* Handle the fact that while struct ifreq has the same *layout* on | ||
| 3001 | * 32/64 for everything but ifreq::ifru_ifmap and ifreq::ifru_data, | ||
| 3002 | * which are handled elsewhere, it still has different *size* due to | ||
| 3003 | * ifreq::ifru_ifmap (which is 16 bytes on 32 bit, 24 bytes on 64-bit, | ||
| 3004 | * resulting in struct ifreq being 32 and 40 bytes respectively). | ||
| 3005 | * As a result, if the struct happens to be at the end of a page and | ||
| 3006 | * the next page isn't readable/writable, we get a fault. To prevent | ||
| 3007 | * that, copy back and forth to the full size. | ||
| 3008 | */ | ||
| 3009 | |||
| 3010 | uifr = compat_alloc_user_space(sizeof(*uifr)); | ||
| 3011 | if (copy_in_user(uifr, uifr32, sizeof(*uifr32))) | ||
| 3012 | return -EFAULT; | ||
| 3013 | |||
| 3014 | err = sock_do_ioctl(net, sock, cmd, (unsigned long)uifr); | ||
| 3015 | |||
| 3016 | if (!err) { | ||
| 3017 | switch (cmd) { | ||
| 3018 | case SIOCGIFFLAGS: | ||
| 3019 | case SIOCGIFMETRIC: | ||
| 3020 | case SIOCGIFMTU: | ||
| 3021 | case SIOCGIFMEM: | ||
| 3022 | case SIOCGIFHWADDR: | ||
| 3023 | case SIOCGIFINDEX: | ||
| 3024 | case SIOCGIFADDR: | ||
| 3025 | case SIOCGIFBRDADDR: | ||
| 3026 | case SIOCGIFDSTADDR: | ||
| 3027 | case SIOCGIFNETMASK: | ||
| 3028 | case SIOCGIFPFLAGS: | ||
| 3029 | case SIOCGIFTXQLEN: | ||
| 3030 | case SIOCGMIIPHY: | ||
| 3031 | case SIOCGMIIREG: | ||
| 3032 | case SIOCGIFNAME: | ||
| 3033 | if (copy_in_user(uifr32, uifr, sizeof(*uifr32))) | ||
| 3034 | err = -EFAULT; | ||
| 3035 | break; | ||
| 3036 | } | ||
| 3037 | } | ||
| 3038 | return err; | ||
| 3039 | } | ||
| 3040 | |||
| 2997 | static int compat_sioc_ifmap(struct net *net, unsigned int cmd, | 3041 | static int compat_sioc_ifmap(struct net *net, unsigned int cmd, |
| 2998 | struct compat_ifreq __user *uifr32) | 3042 | struct compat_ifreq __user *uifr32) |
| 2999 | { | 3043 | { |
| @@ -3109,8 +3153,7 @@ static int routing_ioctl(struct net *net, struct socket *sock, | |||
| 3109 | } | 3153 | } |
| 3110 | 3154 | ||
| 3111 | set_fs(KERNEL_DS); | 3155 | set_fs(KERNEL_DS); |
| 3112 | ret = sock_do_ioctl(net, sock, cmd, (unsigned long) r, | 3156 | ret = sock_do_ioctl(net, sock, cmd, (unsigned long) r); |
| 3113 | sizeof(struct compat_ifreq)); | ||
| 3114 | set_fs(old_fs); | 3157 | set_fs(old_fs); |
| 3115 | 3158 | ||
| 3116 | out: | 3159 | out: |
| @@ -3210,21 +3253,22 @@ static int compat_sock_ioctl_trans(struct file *file, struct socket *sock, | |||
| 3210 | case SIOCSIFTXQLEN: | 3253 | case SIOCSIFTXQLEN: |
| 3211 | case SIOCBRADDIF: | 3254 | case SIOCBRADDIF: |
| 3212 | case SIOCBRDELIF: | 3255 | case SIOCBRDELIF: |
| 3256 | case SIOCGIFNAME: | ||
| 3213 | case SIOCSIFNAME: | 3257 | case SIOCSIFNAME: |
| 3214 | case SIOCGMIIPHY: | 3258 | case SIOCGMIIPHY: |
| 3215 | case SIOCGMIIREG: | 3259 | case SIOCGMIIREG: |
| 3216 | case SIOCSMIIREG: | 3260 | case SIOCSMIIREG: |
| 3217 | case SIOCSARP: | ||
| 3218 | case SIOCGARP: | ||
| 3219 | case SIOCDARP: | ||
| 3220 | case SIOCATMARK: | ||
| 3221 | case SIOCBONDENSLAVE: | 3261 | case SIOCBONDENSLAVE: |
| 3222 | case SIOCBONDRELEASE: | 3262 | case SIOCBONDRELEASE: |
| 3223 | case SIOCBONDSETHWADDR: | 3263 | case SIOCBONDSETHWADDR: |
| 3224 | case SIOCBONDCHANGEACTIVE: | 3264 | case SIOCBONDCHANGEACTIVE: |
| 3225 | case SIOCGIFNAME: | 3265 | return compat_ifreq_ioctl(net, sock, cmd, argp); |
| 3226 | return sock_do_ioctl(net, sock, cmd, arg, | 3266 | |
| 3227 | sizeof(struct compat_ifreq)); | 3267 | case SIOCSARP: |
| 3268 | case SIOCGARP: | ||
| 3269 | case SIOCDARP: | ||
| 3270 | case SIOCATMARK: | ||
| 3271 | return sock_do_ioctl(net, sock, cmd, arg); | ||
| 3228 | } | 3272 | } |
| 3229 | 3273 | ||
| 3230 | return -ENOIOCTLCMD; | 3274 | return -ENOIOCTLCMD; |
diff --git a/net/sunrpc/xprtrdma/svc_rdma_sendto.c b/net/sunrpc/xprtrdma/svc_rdma_sendto.c index cf51b8f9b15f..1f200119268c 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_sendto.c +++ b/net/sunrpc/xprtrdma/svc_rdma_sendto.c | |||
| @@ -537,6 +537,99 @@ void svc_rdma_sync_reply_hdr(struct svcxprt_rdma *rdma, | |||
| 537 | DMA_TO_DEVICE); | 537 | DMA_TO_DEVICE); |
| 538 | } | 538 | } |
| 539 | 539 | ||
| 540 | /* If the xdr_buf has more elements than the device can | ||
| 541 | * transmit in a single RDMA Send, then the reply will | ||
| 542 | * have to be copied into a bounce buffer. | ||
| 543 | */ | ||
| 544 | static bool svc_rdma_pull_up_needed(struct svcxprt_rdma *rdma, | ||
| 545 | struct xdr_buf *xdr, | ||
| 546 | __be32 *wr_lst) | ||
| 547 | { | ||
| 548 | int elements; | ||
| 549 | |||
| 550 | /* xdr->head */ | ||
| 551 | elements = 1; | ||
| 552 | |||
| 553 | /* xdr->pages */ | ||
| 554 | if (!wr_lst) { | ||
| 555 | unsigned int remaining; | ||
| 556 | unsigned long pageoff; | ||
| 557 | |||
| 558 | pageoff = xdr->page_base & ~PAGE_MASK; | ||
| 559 | remaining = xdr->page_len; | ||
| 560 | while (remaining) { | ||
| 561 | ++elements; | ||
| 562 | remaining -= min_t(u32, PAGE_SIZE - pageoff, | ||
| 563 | remaining); | ||
| 564 | pageoff = 0; | ||
| 565 | } | ||
| 566 | } | ||
| 567 | |||
| 568 | /* xdr->tail */ | ||
| 569 | if (xdr->tail[0].iov_len) | ||
| 570 | ++elements; | ||
| 571 | |||
| 572 | /* assume 1 SGE is needed for the transport header */ | ||
| 573 | return elements >= rdma->sc_max_send_sges; | ||
| 574 | } | ||
| 575 | |||
| 576 | /* The device is not capable of sending the reply directly. | ||
| 577 | * Assemble the elements of @xdr into the transport header | ||
| 578 | * buffer. | ||
| 579 | */ | ||
| 580 | static int svc_rdma_pull_up_reply_msg(struct svcxprt_rdma *rdma, | ||
| 581 | struct svc_rdma_send_ctxt *ctxt, | ||
| 582 | struct xdr_buf *xdr, __be32 *wr_lst) | ||
| 583 | { | ||
| 584 | unsigned char *dst, *tailbase; | ||
| 585 | unsigned int taillen; | ||
| 586 | |||
| 587 | dst = ctxt->sc_xprt_buf; | ||
| 588 | dst += ctxt->sc_sges[0].length; | ||
| 589 | |||
| 590 | memcpy(dst, xdr->head[0].iov_base, xdr->head[0].iov_len); | ||
| 591 | dst += xdr->head[0].iov_len; | ||
| 592 | |||
| 593 | tailbase = xdr->tail[0].iov_base; | ||
| 594 | taillen = xdr->tail[0].iov_len; | ||
| 595 | if (wr_lst) { | ||
| 596 | u32 xdrpad; | ||
| 597 | |||
| 598 | xdrpad = xdr_padsize(xdr->page_len); | ||
| 599 | if (taillen && xdrpad) { | ||
| 600 | tailbase += xdrpad; | ||
| 601 | taillen -= xdrpad; | ||
| 602 | } | ||
| 603 | } else { | ||
| 604 | unsigned int len, remaining; | ||
| 605 | unsigned long pageoff; | ||
| 606 | struct page **ppages; | ||
| 607 | |||
| 608 | ppages = xdr->pages + (xdr->page_base >> PAGE_SHIFT); | ||
| 609 | pageoff = xdr->page_base & ~PAGE_MASK; | ||
| 610 | remaining = xdr->page_len; | ||
| 611 | while (remaining) { | ||
| 612 | len = min_t(u32, PAGE_SIZE - pageoff, remaining); | ||
| 613 | |||
| 614 | memcpy(dst, page_address(*ppages), len); | ||
| 615 | remaining -= len; | ||
| 616 | dst += len; | ||
| 617 | pageoff = 0; | ||
| 618 | } | ||
| 619 | } | ||
| 620 | |||
| 621 | if (taillen) | ||
| 622 | memcpy(dst, tailbase, taillen); | ||
| 623 | |||
| 624 | ctxt->sc_sges[0].length += xdr->len; | ||
| 625 | ib_dma_sync_single_for_device(rdma->sc_pd->device, | ||
| 626 | ctxt->sc_sges[0].addr, | ||
| 627 | ctxt->sc_sges[0].length, | ||
| 628 | DMA_TO_DEVICE); | ||
| 629 | |||
| 630 | return 0; | ||
| 631 | } | ||
| 632 | |||
| 540 | /* svc_rdma_map_reply_msg - Map the buffer holding RPC message | 633 | /* svc_rdma_map_reply_msg - Map the buffer holding RPC message |
| 541 | * @rdma: controlling transport | 634 | * @rdma: controlling transport |
| 542 | * @ctxt: send_ctxt for the Send WR | 635 | * @ctxt: send_ctxt for the Send WR |
| @@ -559,8 +652,10 @@ int svc_rdma_map_reply_msg(struct svcxprt_rdma *rdma, | |||
| 559 | u32 xdr_pad; | 652 | u32 xdr_pad; |
| 560 | int ret; | 653 | int ret; |
| 561 | 654 | ||
| 562 | if (++ctxt->sc_cur_sge_no >= rdma->sc_max_send_sges) | 655 | if (svc_rdma_pull_up_needed(rdma, xdr, wr_lst)) |
| 563 | return -EIO; | 656 | return svc_rdma_pull_up_reply_msg(rdma, ctxt, xdr, wr_lst); |
| 657 | |||
| 658 | ++ctxt->sc_cur_sge_no; | ||
| 564 | ret = svc_rdma_dma_map_buf(rdma, ctxt, | 659 | ret = svc_rdma_dma_map_buf(rdma, ctxt, |
| 565 | xdr->head[0].iov_base, | 660 | xdr->head[0].iov_base, |
| 566 | xdr->head[0].iov_len); | 661 | xdr->head[0].iov_len); |
| @@ -591,8 +686,7 @@ int svc_rdma_map_reply_msg(struct svcxprt_rdma *rdma, | |||
| 591 | while (remaining) { | 686 | while (remaining) { |
| 592 | len = min_t(u32, PAGE_SIZE - page_off, remaining); | 687 | len = min_t(u32, PAGE_SIZE - page_off, remaining); |
| 593 | 688 | ||
| 594 | if (++ctxt->sc_cur_sge_no >= rdma->sc_max_send_sges) | 689 | ++ctxt->sc_cur_sge_no; |
| 595 | return -EIO; | ||
| 596 | ret = svc_rdma_dma_map_page(rdma, ctxt, *ppages++, | 690 | ret = svc_rdma_dma_map_page(rdma, ctxt, *ppages++, |
| 597 | page_off, len); | 691 | page_off, len); |
| 598 | if (ret < 0) | 692 | if (ret < 0) |
| @@ -606,8 +700,7 @@ int svc_rdma_map_reply_msg(struct svcxprt_rdma *rdma, | |||
| 606 | len = xdr->tail[0].iov_len; | 700 | len = xdr->tail[0].iov_len; |
| 607 | tail: | 701 | tail: |
| 608 | if (len) { | 702 | if (len) { |
| 609 | if (++ctxt->sc_cur_sge_no >= rdma->sc_max_send_sges) | 703 | ++ctxt->sc_cur_sge_no; |
| 610 | return -EIO; | ||
| 611 | ret = svc_rdma_dma_map_buf(rdma, ctxt, base, len); | 704 | ret = svc_rdma_dma_map_buf(rdma, ctxt, base, len); |
| 612 | if (ret < 0) | 705 | if (ret < 0) |
| 613 | return ret; | 706 | return ret; |
diff --git a/net/sunrpc/xprtrdma/svc_rdma_transport.c b/net/sunrpc/xprtrdma/svc_rdma_transport.c index 924c17d46903..57f86c63a463 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_transport.c +++ b/net/sunrpc/xprtrdma/svc_rdma_transport.c | |||
| @@ -419,12 +419,9 @@ static struct svc_xprt *svc_rdma_accept(struct svc_xprt *xprt) | |||
| 419 | /* Transport header, head iovec, tail iovec */ | 419 | /* Transport header, head iovec, tail iovec */ |
| 420 | newxprt->sc_max_send_sges = 3; | 420 | newxprt->sc_max_send_sges = 3; |
| 421 | /* Add one SGE per page list entry */ | 421 | /* Add one SGE per page list entry */ |
| 422 | newxprt->sc_max_send_sges += svcrdma_max_req_size / PAGE_SIZE; | 422 | newxprt->sc_max_send_sges += (svcrdma_max_req_size / PAGE_SIZE) + 1; |
| 423 | if (newxprt->sc_max_send_sges > dev->attrs.max_send_sge) { | 423 | if (newxprt->sc_max_send_sges > dev->attrs.max_send_sge) |
| 424 | pr_err("svcrdma: too few Send SGEs available (%d needed)\n", | 424 | newxprt->sc_max_send_sges = dev->attrs.max_send_sge; |
| 425 | newxprt->sc_max_send_sges); | ||
| 426 | goto errout; | ||
| 427 | } | ||
| 428 | newxprt->sc_max_req_size = svcrdma_max_req_size; | 425 | newxprt->sc_max_req_size = svcrdma_max_req_size; |
| 429 | newxprt->sc_max_requests = svcrdma_max_requests; | 426 | newxprt->sc_max_requests = svcrdma_max_requests; |
| 430 | newxprt->sc_max_bc_requests = svcrdma_max_bc_requests; | 427 | newxprt->sc_max_bc_requests = svcrdma_max_bc_requests; |
diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c index 11cdc8f7db63..bf5b54b513bc 100644 --- a/net/tls/tls_sw.c +++ b/net/tls/tls_sw.c | |||
| @@ -439,6 +439,8 @@ static int tls_do_encryption(struct sock *sk, | |||
| 439 | struct scatterlist *sge = sk_msg_elem(msg_en, start); | 439 | struct scatterlist *sge = sk_msg_elem(msg_en, start); |
| 440 | int rc; | 440 | int rc; |
| 441 | 441 | ||
| 442 | memcpy(rec->iv_data, tls_ctx->tx.iv, sizeof(rec->iv_data)); | ||
| 443 | |||
| 442 | sge->offset += tls_ctx->tx.prepend_size; | 444 | sge->offset += tls_ctx->tx.prepend_size; |
| 443 | sge->length -= tls_ctx->tx.prepend_size; | 445 | sge->length -= tls_ctx->tx.prepend_size; |
| 444 | 446 | ||
| @@ -448,7 +450,7 @@ static int tls_do_encryption(struct sock *sk, | |||
| 448 | aead_request_set_ad(aead_req, TLS_AAD_SPACE_SIZE); | 450 | aead_request_set_ad(aead_req, TLS_AAD_SPACE_SIZE); |
| 449 | aead_request_set_crypt(aead_req, rec->sg_aead_in, | 451 | aead_request_set_crypt(aead_req, rec->sg_aead_in, |
| 450 | rec->sg_aead_out, | 452 | rec->sg_aead_out, |
| 451 | data_len, tls_ctx->tx.iv); | 453 | data_len, rec->iv_data); |
| 452 | 454 | ||
| 453 | aead_request_set_callback(aead_req, CRYPTO_TFM_REQ_MAY_BACKLOG, | 455 | aead_request_set_callback(aead_req, CRYPTO_TFM_REQ_MAY_BACKLOG, |
| 454 | tls_encrypt_done, sk); | 456 | tls_encrypt_done, sk); |
| @@ -1792,7 +1794,9 @@ void tls_sw_free_resources_tx(struct sock *sk) | |||
| 1792 | if (atomic_read(&ctx->encrypt_pending)) | 1794 | if (atomic_read(&ctx->encrypt_pending)) |
| 1793 | crypto_wait_req(-EINPROGRESS, &ctx->async_wait); | 1795 | crypto_wait_req(-EINPROGRESS, &ctx->async_wait); |
| 1794 | 1796 | ||
| 1797 | release_sock(sk); | ||
| 1795 | cancel_delayed_work_sync(&ctx->tx_work.work); | 1798 | cancel_delayed_work_sync(&ctx->tx_work.work); |
| 1799 | lock_sock(sk); | ||
| 1796 | 1800 | ||
| 1797 | /* Tx whatever records we can transmit and abandon the rest */ | 1801 | /* Tx whatever records we can transmit and abandon the rest */ |
| 1798 | tls_tx_records(sk, -1); | 1802 | tls_tx_records(sk, -1); |
diff --git a/net/vmw_vsock/virtio_transport.c b/net/vmw_vsock/virtio_transport.c index 5d3cce9e8744..15eb5d3d4750 100644 --- a/net/vmw_vsock/virtio_transport.c +++ b/net/vmw_vsock/virtio_transport.c | |||
| @@ -75,6 +75,9 @@ static u32 virtio_transport_get_local_cid(void) | |||
| 75 | { | 75 | { |
| 76 | struct virtio_vsock *vsock = virtio_vsock_get(); | 76 | struct virtio_vsock *vsock = virtio_vsock_get(); |
| 77 | 77 | ||
| 78 | if (!vsock) | ||
| 79 | return VMADDR_CID_ANY; | ||
| 80 | |||
| 78 | return vsock->guest_cid; | 81 | return vsock->guest_cid; |
| 79 | } | 82 | } |
| 80 | 83 | ||
| @@ -584,10 +587,6 @@ static int virtio_vsock_probe(struct virtio_device *vdev) | |||
| 584 | 587 | ||
| 585 | virtio_vsock_update_guest_cid(vsock); | 588 | virtio_vsock_update_guest_cid(vsock); |
| 586 | 589 | ||
| 587 | ret = vsock_core_init(&virtio_transport.transport); | ||
| 588 | if (ret < 0) | ||
| 589 | goto out_vqs; | ||
| 590 | |||
| 591 | vsock->rx_buf_nr = 0; | 590 | vsock->rx_buf_nr = 0; |
| 592 | vsock->rx_buf_max_nr = 0; | 591 | vsock->rx_buf_max_nr = 0; |
| 593 | atomic_set(&vsock->queued_replies, 0); | 592 | atomic_set(&vsock->queued_replies, 0); |
| @@ -618,8 +617,6 @@ static int virtio_vsock_probe(struct virtio_device *vdev) | |||
| 618 | mutex_unlock(&the_virtio_vsock_mutex); | 617 | mutex_unlock(&the_virtio_vsock_mutex); |
| 619 | return 0; | 618 | return 0; |
| 620 | 619 | ||
| 621 | out_vqs: | ||
| 622 | vsock->vdev->config->del_vqs(vsock->vdev); | ||
| 623 | out: | 620 | out: |
| 624 | kfree(vsock); | 621 | kfree(vsock); |
| 625 | mutex_unlock(&the_virtio_vsock_mutex); | 622 | mutex_unlock(&the_virtio_vsock_mutex); |
| @@ -637,6 +634,9 @@ static void virtio_vsock_remove(struct virtio_device *vdev) | |||
| 637 | flush_work(&vsock->event_work); | 634 | flush_work(&vsock->event_work); |
| 638 | flush_work(&vsock->send_pkt_work); | 635 | flush_work(&vsock->send_pkt_work); |
| 639 | 636 | ||
| 637 | /* Reset all connected sockets when the device disappear */ | ||
| 638 | vsock_for_each_connected_socket(virtio_vsock_reset_sock); | ||
| 639 | |||
| 640 | vdev->config->reset(vdev); | 640 | vdev->config->reset(vdev); |
| 641 | 641 | ||
| 642 | mutex_lock(&vsock->rx_lock); | 642 | mutex_lock(&vsock->rx_lock); |
| @@ -669,7 +669,6 @@ static void virtio_vsock_remove(struct virtio_device *vdev) | |||
| 669 | 669 | ||
| 670 | mutex_lock(&the_virtio_vsock_mutex); | 670 | mutex_lock(&the_virtio_vsock_mutex); |
| 671 | the_virtio_vsock = NULL; | 671 | the_virtio_vsock = NULL; |
| 672 | vsock_core_exit(); | ||
| 673 | mutex_unlock(&the_virtio_vsock_mutex); | 672 | mutex_unlock(&the_virtio_vsock_mutex); |
| 674 | 673 | ||
| 675 | vdev->config->del_vqs(vdev); | 674 | vdev->config->del_vqs(vdev); |
| @@ -702,14 +701,28 @@ static int __init virtio_vsock_init(void) | |||
| 702 | virtio_vsock_workqueue = alloc_workqueue("virtio_vsock", 0, 0); | 701 | virtio_vsock_workqueue = alloc_workqueue("virtio_vsock", 0, 0); |
| 703 | if (!virtio_vsock_workqueue) | 702 | if (!virtio_vsock_workqueue) |
| 704 | return -ENOMEM; | 703 | return -ENOMEM; |
| 704 | |||
| 705 | ret = register_virtio_driver(&virtio_vsock_driver); | 705 | ret = register_virtio_driver(&virtio_vsock_driver); |
| 706 | if (ret) | 706 | if (ret) |
| 707 | destroy_workqueue(virtio_vsock_workqueue); | 707 | goto out_wq; |
| 708 | |||
| 709 | ret = vsock_core_init(&virtio_transport.transport); | ||
| 710 | if (ret) | ||
| 711 | goto out_vdr; | ||
| 712 | |||
| 713 | return 0; | ||
| 714 | |||
| 715 | out_vdr: | ||
| 716 | unregister_virtio_driver(&virtio_vsock_driver); | ||
| 717 | out_wq: | ||
| 718 | destroy_workqueue(virtio_vsock_workqueue); | ||
| 708 | return ret; | 719 | return ret; |
| 720 | |||
| 709 | } | 721 | } |
| 710 | 722 | ||
| 711 | static void __exit virtio_vsock_exit(void) | 723 | static void __exit virtio_vsock_exit(void) |
| 712 | { | 724 | { |
| 725 | vsock_core_exit(); | ||
| 713 | unregister_virtio_driver(&virtio_vsock_driver); | 726 | unregister_virtio_driver(&virtio_vsock_driver); |
| 714 | destroy_workqueue(virtio_vsock_workqueue); | 727 | destroy_workqueue(virtio_vsock_workqueue); |
| 715 | } | 728 | } |
diff --git a/net/wireless/ap.c b/net/wireless/ap.c index 882d97bdc6bf..550ac9d827fe 100644 --- a/net/wireless/ap.c +++ b/net/wireless/ap.c | |||
| @@ -41,6 +41,8 @@ int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev, | |||
| 41 | cfg80211_sched_dfs_chan_update(rdev); | 41 | cfg80211_sched_dfs_chan_update(rdev); |
| 42 | } | 42 | } |
| 43 | 43 | ||
| 44 | schedule_work(&cfg80211_disconnect_work); | ||
| 45 | |||
| 44 | return err; | 46 | return err; |
| 45 | } | 47 | } |
| 46 | 48 | ||
diff --git a/net/wireless/core.h b/net/wireless/core.h index c5d6f3418601..f6b40563dc63 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
| @@ -445,6 +445,8 @@ void cfg80211_process_wdev_events(struct wireless_dev *wdev); | |||
| 445 | bool cfg80211_does_bw_fit_range(const struct ieee80211_freq_range *freq_range, | 445 | bool cfg80211_does_bw_fit_range(const struct ieee80211_freq_range *freq_range, |
| 446 | u32 center_freq_khz, u32 bw_khz); | 446 | u32 center_freq_khz, u32 bw_khz); |
| 447 | 447 | ||
| 448 | extern struct work_struct cfg80211_disconnect_work; | ||
| 449 | |||
| 448 | /** | 450 | /** |
| 449 | * cfg80211_chandef_dfs_usable - checks if chandef is DFS usable | 451 | * cfg80211_chandef_dfs_usable - checks if chandef is DFS usable |
| 450 | * @wiphy: the wiphy to validate against | 452 | * @wiphy: the wiphy to validate against |
diff --git a/net/wireless/sme.c b/net/wireless/sme.c index f741d8376a46..7d34cb884840 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c | |||
| @@ -667,7 +667,7 @@ static void disconnect_work(struct work_struct *work) | |||
| 667 | rtnl_unlock(); | 667 | rtnl_unlock(); |
| 668 | } | 668 | } |
| 669 | 669 | ||
| 670 | static DECLARE_WORK(cfg80211_disconnect_work, disconnect_work); | 670 | DECLARE_WORK(cfg80211_disconnect_work, disconnect_work); |
| 671 | 671 | ||
| 672 | 672 | ||
| 673 | /* | 673 | /* |
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 934492bad8e0..ba0a4048c846 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c | |||
| @@ -680,16 +680,6 @@ static void xfrm_hash_resize(struct work_struct *work) | |||
| 680 | mutex_unlock(&hash_resize_mutex); | 680 | mutex_unlock(&hash_resize_mutex); |
| 681 | } | 681 | } |
| 682 | 682 | ||
| 683 | static void xfrm_hash_reset_inexact_table(struct net *net) | ||
| 684 | { | ||
| 685 | struct xfrm_pol_inexact_bin *b; | ||
| 686 | |||
| 687 | lockdep_assert_held(&net->xfrm.xfrm_policy_lock); | ||
| 688 | |||
| 689 | list_for_each_entry(b, &net->xfrm.inexact_bins, inexact_bins) | ||
| 690 | INIT_HLIST_HEAD(&b->hhead); | ||
| 691 | } | ||
| 692 | |||
| 693 | /* Make sure *pol can be inserted into fastbin. | 683 | /* Make sure *pol can be inserted into fastbin. |
| 694 | * Useful to check that later insert requests will be sucessful | 684 | * Useful to check that later insert requests will be sucessful |
| 695 | * (provided xfrm_policy_lock is held throughout). | 685 | * (provided xfrm_policy_lock is held throughout). |
| @@ -833,13 +823,13 @@ static void xfrm_policy_inexact_list_reinsert(struct net *net, | |||
| 833 | u16 family) | 823 | u16 family) |
| 834 | { | 824 | { |
| 835 | unsigned int matched_s, matched_d; | 825 | unsigned int matched_s, matched_d; |
| 836 | struct hlist_node *newpos = NULL; | ||
| 837 | struct xfrm_policy *policy, *p; | 826 | struct xfrm_policy *policy, *p; |
| 838 | 827 | ||
| 839 | matched_s = 0; | 828 | matched_s = 0; |
| 840 | matched_d = 0; | 829 | matched_d = 0; |
| 841 | 830 | ||
| 842 | list_for_each_entry_reverse(policy, &net->xfrm.policy_all, walk.all) { | 831 | list_for_each_entry_reverse(policy, &net->xfrm.policy_all, walk.all) { |
| 832 | struct hlist_node *newpos = NULL; | ||
| 843 | bool matches_s, matches_d; | 833 | bool matches_s, matches_d; |
| 844 | 834 | ||
| 845 | if (!policy->bydst_reinsert) | 835 | if (!policy->bydst_reinsert) |
| @@ -849,16 +839,19 @@ static void xfrm_policy_inexact_list_reinsert(struct net *net, | |||
| 849 | 839 | ||
| 850 | policy->bydst_reinsert = false; | 840 | policy->bydst_reinsert = false; |
| 851 | hlist_for_each_entry(p, &n->hhead, bydst) { | 841 | hlist_for_each_entry(p, &n->hhead, bydst) { |
| 852 | if (policy->priority >= p->priority) | 842 | if (policy->priority > p->priority) |
| 843 | newpos = &p->bydst; | ||
| 844 | else if (policy->priority == p->priority && | ||
| 845 | policy->pos > p->pos) | ||
| 853 | newpos = &p->bydst; | 846 | newpos = &p->bydst; |
| 854 | else | 847 | else |
| 855 | break; | 848 | break; |
| 856 | } | 849 | } |
| 857 | 850 | ||
| 858 | if (newpos) | 851 | if (newpos) |
| 859 | hlist_add_behind(&policy->bydst, newpos); | 852 | hlist_add_behind_rcu(&policy->bydst, newpos); |
| 860 | else | 853 | else |
| 861 | hlist_add_head(&policy->bydst, &n->hhead); | 854 | hlist_add_head_rcu(&policy->bydst, &n->hhead); |
| 862 | 855 | ||
| 863 | /* paranoia checks follow. | 856 | /* paranoia checks follow. |
| 864 | * Check that the reinserted policy matches at least | 857 | * Check that the reinserted policy matches at least |
| @@ -893,12 +886,13 @@ static void xfrm_policy_inexact_node_reinsert(struct net *net, | |||
| 893 | struct rb_root *new, | 886 | struct rb_root *new, |
| 894 | u16 family) | 887 | u16 family) |
| 895 | { | 888 | { |
| 896 | struct rb_node **p, *parent = NULL; | ||
| 897 | struct xfrm_pol_inexact_node *node; | 889 | struct xfrm_pol_inexact_node *node; |
| 890 | struct rb_node **p, *parent; | ||
| 898 | 891 | ||
| 899 | /* we should not have another subtree here */ | 892 | /* we should not have another subtree here */ |
| 900 | WARN_ON_ONCE(!RB_EMPTY_ROOT(&n->root)); | 893 | WARN_ON_ONCE(!RB_EMPTY_ROOT(&n->root)); |
| 901 | 894 | restart: | |
| 895 | parent = NULL; | ||
| 902 | p = &new->rb_node; | 896 | p = &new->rb_node; |
| 903 | while (*p) { | 897 | while (*p) { |
| 904 | u8 prefixlen; | 898 | u8 prefixlen; |
| @@ -918,12 +912,11 @@ static void xfrm_policy_inexact_node_reinsert(struct net *net, | |||
| 918 | } else { | 912 | } else { |
| 919 | struct xfrm_policy *tmp; | 913 | struct xfrm_policy *tmp; |
| 920 | 914 | ||
| 921 | hlist_for_each_entry(tmp, &node->hhead, bydst) | 915 | hlist_for_each_entry(tmp, &n->hhead, bydst) { |
| 922 | tmp->bydst_reinsert = true; | ||
| 923 | hlist_for_each_entry(tmp, &n->hhead, bydst) | ||
| 924 | tmp->bydst_reinsert = true; | 916 | tmp->bydst_reinsert = true; |
| 917 | hlist_del_rcu(&tmp->bydst); | ||
| 918 | } | ||
| 925 | 919 | ||
| 926 | INIT_HLIST_HEAD(&node->hhead); | ||
| 927 | xfrm_policy_inexact_list_reinsert(net, node, family); | 920 | xfrm_policy_inexact_list_reinsert(net, node, family); |
| 928 | 921 | ||
| 929 | if (node->prefixlen == n->prefixlen) { | 922 | if (node->prefixlen == n->prefixlen) { |
| @@ -935,8 +928,7 @@ static void xfrm_policy_inexact_node_reinsert(struct net *net, | |||
| 935 | kfree_rcu(n, rcu); | 928 | kfree_rcu(n, rcu); |
| 936 | n = node; | 929 | n = node; |
| 937 | n->prefixlen = prefixlen; | 930 | n->prefixlen = prefixlen; |
| 938 | *p = new->rb_node; | 931 | goto restart; |
| 939 | parent = NULL; | ||
| 940 | } | 932 | } |
| 941 | } | 933 | } |
| 942 | 934 | ||
| @@ -965,12 +957,11 @@ static void xfrm_policy_inexact_node_merge(struct net *net, | |||
| 965 | family); | 957 | family); |
| 966 | } | 958 | } |
| 967 | 959 | ||
| 968 | hlist_for_each_entry(tmp, &v->hhead, bydst) | 960 | hlist_for_each_entry(tmp, &v->hhead, bydst) { |
| 969 | tmp->bydst_reinsert = true; | ||
| 970 | hlist_for_each_entry(tmp, &n->hhead, bydst) | ||
| 971 | tmp->bydst_reinsert = true; | 961 | tmp->bydst_reinsert = true; |
| 962 | hlist_del_rcu(&tmp->bydst); | ||
| 963 | } | ||
| 972 | 964 | ||
| 973 | INIT_HLIST_HEAD(&n->hhead); | ||
| 974 | xfrm_policy_inexact_list_reinsert(net, n, family); | 965 | xfrm_policy_inexact_list_reinsert(net, n, family); |
| 975 | } | 966 | } |
| 976 | 967 | ||
| @@ -1235,6 +1226,7 @@ static void xfrm_hash_rebuild(struct work_struct *work) | |||
| 1235 | } while (read_seqretry(&net->xfrm.policy_hthresh.lock, seq)); | 1226 | } while (read_seqretry(&net->xfrm.policy_hthresh.lock, seq)); |
| 1236 | 1227 | ||
| 1237 | spin_lock_bh(&net->xfrm.xfrm_policy_lock); | 1228 | spin_lock_bh(&net->xfrm.xfrm_policy_lock); |
| 1229 | write_seqcount_begin(&xfrm_policy_hash_generation); | ||
| 1238 | 1230 | ||
| 1239 | /* make sure that we can insert the indirect policies again before | 1231 | /* make sure that we can insert the indirect policies again before |
| 1240 | * we start with destructive action. | 1232 | * we start with destructive action. |
| @@ -1278,10 +1270,14 @@ static void xfrm_hash_rebuild(struct work_struct *work) | |||
| 1278 | } | 1270 | } |
| 1279 | 1271 | ||
| 1280 | /* reset the bydst and inexact table in all directions */ | 1272 | /* reset the bydst and inexact table in all directions */ |
| 1281 | xfrm_hash_reset_inexact_table(net); | ||
| 1282 | |||
| 1283 | for (dir = 0; dir < XFRM_POLICY_MAX; dir++) { | 1273 | for (dir = 0; dir < XFRM_POLICY_MAX; dir++) { |
| 1284 | INIT_HLIST_HEAD(&net->xfrm.policy_inexact[dir]); | 1274 | struct hlist_node *n; |
| 1275 | |||
| 1276 | hlist_for_each_entry_safe(policy, n, | ||
| 1277 | &net->xfrm.policy_inexact[dir], | ||
| 1278 | bydst_inexact_list) | ||
| 1279 | hlist_del_init(&policy->bydst_inexact_list); | ||
| 1280 | |||
| 1285 | hmask = net->xfrm.policy_bydst[dir].hmask; | 1281 | hmask = net->xfrm.policy_bydst[dir].hmask; |
| 1286 | odst = net->xfrm.policy_bydst[dir].table; | 1282 | odst = net->xfrm.policy_bydst[dir].table; |
| 1287 | for (i = hmask; i >= 0; i--) | 1283 | for (i = hmask; i >= 0; i--) |
| @@ -1313,6 +1309,9 @@ static void xfrm_hash_rebuild(struct work_struct *work) | |||
| 1313 | newpos = NULL; | 1309 | newpos = NULL; |
| 1314 | chain = policy_hash_bysel(net, &policy->selector, | 1310 | chain = policy_hash_bysel(net, &policy->selector, |
| 1315 | policy->family, dir); | 1311 | policy->family, dir); |
| 1312 | |||
| 1313 | hlist_del_rcu(&policy->bydst); | ||
| 1314 | |||
| 1316 | if (!chain) { | 1315 | if (!chain) { |
| 1317 | void *p = xfrm_policy_inexact_insert(policy, dir, 0); | 1316 | void *p = xfrm_policy_inexact_insert(policy, dir, 0); |
| 1318 | 1317 | ||
| @@ -1334,6 +1333,7 @@ static void xfrm_hash_rebuild(struct work_struct *work) | |||
| 1334 | 1333 | ||
| 1335 | out_unlock: | 1334 | out_unlock: |
| 1336 | __xfrm_policy_inexact_flush(net); | 1335 | __xfrm_policy_inexact_flush(net); |
| 1336 | write_seqcount_end(&xfrm_policy_hash_generation); | ||
| 1337 | spin_unlock_bh(&net->xfrm.xfrm_policy_lock); | 1337 | spin_unlock_bh(&net->xfrm.xfrm_policy_lock); |
| 1338 | 1338 | ||
| 1339 | mutex_unlock(&hash_resize_mutex); | 1339 | mutex_unlock(&hash_resize_mutex); |
| @@ -2600,7 +2600,10 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy, | |||
| 2600 | dst_copy_metrics(dst1, dst); | 2600 | dst_copy_metrics(dst1, dst); |
| 2601 | 2601 | ||
| 2602 | if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) { | 2602 | if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) { |
| 2603 | __u32 mark = xfrm_smark_get(fl->flowi_mark, xfrm[i]); | 2603 | __u32 mark = 0; |
| 2604 | |||
| 2605 | if (xfrm[i]->props.smark.v || xfrm[i]->props.smark.m) | ||
| 2606 | mark = xfrm_smark_get(fl->flowi_mark, xfrm[i]); | ||
| 2604 | 2607 | ||
| 2605 | family = xfrm[i]->props.family; | 2608 | family = xfrm[i]->props.family; |
| 2606 | dst = xfrm_dst_lookup(xfrm[i], tos, fl->flowi_oif, | 2609 | dst = xfrm_dst_lookup(xfrm[i], tos, fl->flowi_oif, |
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 277c1c46fe94..c6d26afcf89d 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c | |||
| @@ -1488,10 +1488,15 @@ static int validate_tmpl(int nr, struct xfrm_user_tmpl *ut, u16 family) | |||
| 1488 | if (!ut[i].family) | 1488 | if (!ut[i].family) |
| 1489 | ut[i].family = family; | 1489 | ut[i].family = family; |
| 1490 | 1490 | ||
| 1491 | if ((ut[i].mode == XFRM_MODE_TRANSPORT) && | 1491 | switch (ut[i].mode) { |
| 1492 | (ut[i].family != prev_family)) | 1492 | case XFRM_MODE_TUNNEL: |
| 1493 | return -EINVAL; | 1493 | case XFRM_MODE_BEET: |
| 1494 | 1494 | break; | |
| 1495 | default: | ||
| 1496 | if (ut[i].family != prev_family) | ||
| 1497 | return -EINVAL; | ||
| 1498 | break; | ||
| 1499 | } | ||
| 1495 | if (ut[i].mode >= XFRM_MODE_MAX) | 1500 | if (ut[i].mode >= XFRM_MODE_MAX) |
| 1496 | return -EINVAL; | 1501 | return -EINVAL; |
| 1497 | 1502 | ||
