commit:     ae3dadabd5058e845ed5bf34cbad53c580cfc6f9
Author:     Mike Pagano <mpagano <AT> gentoo <DOT> org>
AuthorDate: Sun Aug 13 16:36:48 2017 +0000
Commit:     Mike Pagano <mpagano <AT> gentoo <DOT> org>
CommitDate: Sun Aug 13 16:36:48 2017 +0000
URL:        https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=ae3dadab

Linux patch 4.12.7

 0000_README             |   4 +
 1006_linux-4.12.7.patch | 648 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 652 insertions(+)

diff --git a/0000_README b/0000_README
index b88e1e0..3a1bafb 100644
--- a/0000_README
+++ b/0000_README
@@ -67,6 +67,10 @@ Patch:  1005_linux-4.12.6.patch
 From:   http://www.kernel.org
 Desc:   Linux 4.12.6
 
+Patch:  1006_linux-4.12.7.patch
+From:   http://www.kernel.org
+Desc:   Linux 4.12.7
+
 Patch:  1500_XATTR_USER_PREFIX.patch
 From:   https://bugs.gentoo.org/show_bug.cgi?id=470644
 Desc:   Support for namespace user.pax.* on tmpfs.

diff --git a/1006_linux-4.12.7.patch b/1006_linux-4.12.7.patch
new file mode 100644
index 0000000..b130ed5
--- /dev/null
+++ b/1006_linux-4.12.7.patch
@@ -0,0 +1,648 @@
+diff --git a/Makefile b/Makefile
+index c8d80b50495a..ebe69a704bca 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,6 +1,6 @@
+ VERSION = 4
+ PATCHLEVEL = 12
+-SUBLEVEL = 6
++SUBLEVEL = 7
+ EXTRAVERSION =
+ NAME = Fearless Coyote
+ 
+diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c
+index 6e97a2e3fd8d..8cea684f1f53 100644
+--- a/arch/s390/net/bpf_jit_comp.c
++++ b/arch/s390/net/bpf_jit_comp.c
+@@ -1253,7 +1253,8 @@ static int bpf_jit_prog(struct bpf_jit *jit, struct 
bpf_prog *fp)
+               insn_count = bpf_jit_insn(jit, fp, i);
+               if (insn_count < 0)
+                       return -1;
+-              jit->addrs[i + 1] = jit->prg; /* Next instruction address */
++              /* Next instruction address */
++              jit->addrs[i + insn_count] = jit->prg;
+       }
+       bpf_jit_epilogue(jit);
+ 
+diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c 
b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
+index 77abd1813047..802f0e8bff3a 100644
+--- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c
++++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
+@@ -572,16 +572,21 @@ static inline __wsum get_fixed_vlan_csum(__wsum 
hw_checksum,
+  * header, the HW adds it. To address that, we are subtracting the pseudo
+  * header checksum from the checksum value provided by the HW.
+  */
+-static void get_fixed_ipv4_csum(__wsum hw_checksum, struct sk_buff *skb,
+-                              struct iphdr *iph)
++static int get_fixed_ipv4_csum(__wsum hw_checksum, struct sk_buff *skb,
++                             struct iphdr *iph)
+ {
+       __u16 length_for_csum = 0;
+       __wsum csum_pseudo_header = 0;
++      __u8 ipproto = iph->protocol;
++
++      if (unlikely(ipproto == IPPROTO_SCTP))
++              return -1;
+ 
+       length_for_csum = (be16_to_cpu(iph->tot_len) - (iph->ihl << 2));
+       csum_pseudo_header = csum_tcpudp_nofold(iph->saddr, iph->daddr,
+-                                              length_for_csum, iph->protocol, 
0);
++                                              length_for_csum, ipproto, 0);
+       skb->csum = csum_sub(hw_checksum, csum_pseudo_header);
++      return 0;
+ }
+ 
+ #if IS_ENABLED(CONFIG_IPV6)
+@@ -592,17 +597,20 @@ static void get_fixed_ipv4_csum(__wsum hw_checksum, 
struct sk_buff *skb,
+ static int get_fixed_ipv6_csum(__wsum hw_checksum, struct sk_buff *skb,
+                              struct ipv6hdr *ipv6h)
+ {
++      __u8 nexthdr = ipv6h->nexthdr;
+       __wsum csum_pseudo_hdr = 0;
+ 
+-      if (unlikely(ipv6h->nexthdr == IPPROTO_FRAGMENT ||
+-                   ipv6h->nexthdr == IPPROTO_HOPOPTS))
++      if (unlikely(nexthdr == IPPROTO_FRAGMENT ||
++                   nexthdr == IPPROTO_HOPOPTS ||
++                   nexthdr == IPPROTO_SCTP))
+               return -1;
+-      hw_checksum = csum_add(hw_checksum, (__force 
__wsum)htons(ipv6h->nexthdr));
++      hw_checksum = csum_add(hw_checksum, (__force __wsum)htons(nexthdr));
+ 
+       csum_pseudo_hdr = csum_partial(&ipv6h->saddr,
+                                      sizeof(ipv6h->saddr) + 
sizeof(ipv6h->daddr), 0);
+       csum_pseudo_hdr = csum_add(csum_pseudo_hdr, (__force 
__wsum)ipv6h->payload_len);
+-      csum_pseudo_hdr = csum_add(csum_pseudo_hdr, (__force 
__wsum)ntohs(ipv6h->nexthdr));
++      csum_pseudo_hdr = csum_add(csum_pseudo_hdr,
++                                 (__force __wsum)htons(nexthdr));
+ 
+       skb->csum = csum_sub(hw_checksum, csum_pseudo_hdr);
+       skb->csum = csum_add(skb->csum, csum_partial(ipv6h, sizeof(struct 
ipv6hdr), 0));
+@@ -625,11 +633,10 @@ static int check_csum(struct mlx4_cqe *cqe, struct 
sk_buff *skb, void *va,
+       }
+ 
+       if (cqe->status & cpu_to_be16(MLX4_CQE_STATUS_IPV4))
+-              get_fixed_ipv4_csum(hw_checksum, skb, hdr);
++              return get_fixed_ipv4_csum(hw_checksum, skb, hdr);
+ #if IS_ENABLED(CONFIG_IPV6)
+-      else if (cqe->status & cpu_to_be16(MLX4_CQE_STATUS_IPV6))
+-              if (unlikely(get_fixed_ipv6_csum(hw_checksum, skb, hdr)))
+-                      return -1;
++      if (cqe->status & cpu_to_be16(MLX4_CQE_STATUS_IPV6))
++              return get_fixed_ipv6_csum(hw_checksum, skb, hdr);
+ #endif
+       return 0;
+ }
+diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c
+index f9c0e62716ea..18fb00d55aa1 100644
+--- a/drivers/net/ppp/ppp_generic.c
++++ b/drivers/net/ppp/ppp_generic.c
+@@ -120,6 +120,7 @@ struct ppp {
+       int             n_channels;     /* how many channels are attached 54 */
+       spinlock_t      rlock;          /* lock for receive side 58 */
+       spinlock_t      wlock;          /* lock for transmit side 5c */
++      int             *xmit_recursion __percpu; /* xmit recursion detect */
+       int             mru;            /* max receive unit 60 */
+       unsigned int    flags;          /* control bits 64 */
+       unsigned int    xstate;         /* transmit state bits 68 */
+@@ -1025,6 +1026,7 @@ static int ppp_dev_configure(struct net *src_net, struct 
net_device *dev,
+       struct ppp *ppp = netdev_priv(dev);
+       int indx;
+       int err;
++      int cpu;
+ 
+       ppp->dev = dev;
+       ppp->ppp_net = src_net;
+@@ -1039,6 +1041,15 @@ static int ppp_dev_configure(struct net *src_net, 
struct net_device *dev,
+       INIT_LIST_HEAD(&ppp->channels);
+       spin_lock_init(&ppp->rlock);
+       spin_lock_init(&ppp->wlock);
++
++      ppp->xmit_recursion = alloc_percpu(int);
++      if (!ppp->xmit_recursion) {
++              err = -ENOMEM;
++              goto err1;
++      }
++      for_each_possible_cpu(cpu)
++              (*per_cpu_ptr(ppp->xmit_recursion, cpu)) = 0;
++
+ #ifdef CONFIG_PPP_MULTILINK
+       ppp->minseq = -1;
+       skb_queue_head_init(&ppp->mrq);
+@@ -1050,11 +1061,15 @@ static int ppp_dev_configure(struct net *src_net, 
struct net_device *dev,
+ 
+       err = ppp_unit_register(ppp, conf->unit, conf->ifname_is_set);
+       if (err < 0)
+-              return err;
++              goto err2;
+ 
+       conf->file->private_data = &ppp->file;
+ 
+       return 0;
++err2:
++      free_percpu(ppp->xmit_recursion);
++err1:
++      return err;
+ }
+ 
+ static const struct nla_policy ppp_nl_policy[IFLA_PPP_MAX + 1] = {
+@@ -1398,18 +1413,16 @@ static void __ppp_xmit_process(struct ppp *ppp)
+       ppp_xmit_unlock(ppp);
+ }
+ 
+-static DEFINE_PER_CPU(int, ppp_xmit_recursion);
+-
+ static void ppp_xmit_process(struct ppp *ppp)
+ {
+       local_bh_disable();
+ 
+-      if (unlikely(__this_cpu_read(ppp_xmit_recursion)))
++      if (unlikely(*this_cpu_ptr(ppp->xmit_recursion)))
+               goto err;
+ 
+-      __this_cpu_inc(ppp_xmit_recursion);
++      (*this_cpu_ptr(ppp->xmit_recursion))++;
+       __ppp_xmit_process(ppp);
+-      __this_cpu_dec(ppp_xmit_recursion);
++      (*this_cpu_ptr(ppp->xmit_recursion))--;
+ 
+       local_bh_enable();
+ 
+@@ -1900,23 +1913,23 @@ static void __ppp_channel_push(struct channel *pch)
+       spin_unlock_bh(&pch->downl);
+       /* see if there is anything from the attached unit to be sent */
+       if (skb_queue_empty(&pch->file.xq)) {
+-              read_lock_bh(&pch->upl);
+               ppp = pch->ppp;
+               if (ppp)
+                       __ppp_xmit_process(ppp);
+-              read_unlock_bh(&pch->upl);
+       }
+ }
+ 
+ static void ppp_channel_push(struct channel *pch)
+ {
+-      local_bh_disable();
+-
+-      __this_cpu_inc(ppp_xmit_recursion);
+-      __ppp_channel_push(pch);
+-      __this_cpu_dec(ppp_xmit_recursion);
+-
+-      local_bh_enable();
++      read_lock_bh(&pch->upl);
++      if (pch->ppp) {
++              (*this_cpu_ptr(pch->ppp->xmit_recursion))++;
++              __ppp_channel_push(pch);
++              (*this_cpu_ptr(pch->ppp->xmit_recursion))--;
++      } else {
++              __ppp_channel_push(pch);
++      }
++      read_unlock_bh(&pch->upl);
+ }
+ 
+ /*
+@@ -3055,6 +3068,7 @@ static void ppp_destroy_interface(struct ppp *ppp)
+ #endif /* CONFIG_PPP_FILTER */
+ 
+       kfree_skb(ppp->xmit_pending);
++      free_percpu(ppp->xmit_recursion);
+ 
+       free_netdev(ppp->dev);
+ }
+diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
+index 32a22f4e8356..c42153a985be 100644
+--- a/drivers/net/usb/qmi_wwan.c
++++ b/drivers/net/usb/qmi_wwan.c
+@@ -1340,10 +1340,14 @@ static int qmi_wwan_probe(struct usb_interface *intf,
+ static void qmi_wwan_disconnect(struct usb_interface *intf)
+ {
+       struct usbnet *dev = usb_get_intfdata(intf);
+-      struct qmi_wwan_state *info = (void *)&dev->data;
++      struct qmi_wwan_state *info;
+       struct list_head *iter;
+       struct net_device *ldev;
+ 
++      /* called twice if separate control and data intf */
++      if (!dev)
++              return;
++      info = (void *)&dev->data;
+       if (info->flags & QMI_WWAN_FLAG_MUX) {
+               if (!rtnl_trylock()) {
+                       restart_syscall();
+diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
+index 82c33a6edbea..aa6f1debeaa7 100644
+--- a/drivers/scsi/sg.c
++++ b/drivers/scsi/sg.c
+@@ -751,29 +751,6 @@ sg_new_write(Sg_fd *sfp, struct file *file, const char 
__user *buf,
+       return count;
+ }
+ 
+-static bool sg_is_valid_dxfer(sg_io_hdr_t *hp)
+-{
+-      switch (hp->dxfer_direction) {
+-      case SG_DXFER_NONE:
+-              if (hp->dxferp || hp->dxfer_len > 0)
+-                      return false;
+-              return true;
+-      case SG_DXFER_TO_DEV:
+-      case SG_DXFER_FROM_DEV:
+-      case SG_DXFER_TO_FROM_DEV:
+-              if (!hp->dxferp || hp->dxfer_len == 0)
+-                      return false;
+-              return true;
+-      case SG_DXFER_UNKNOWN:
+-              if ((!hp->dxferp && hp->dxfer_len) ||
+-                  (hp->dxferp && hp->dxfer_len == 0))
+-                      return false;
+-              return true;
+-      default:
+-              return false;
+-      }
+-}
+-
+ static int
+ sg_common_write(Sg_fd * sfp, Sg_request * srp,
+               unsigned char *cmnd, int timeout, int blocking)
+@@ -794,7 +771,7 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp,
+                       "sg_common_write:  scsi opcode=0x%02x, cmd_size=%d\n",
+                       (int) cmnd[0], (int) hp->cmd_len));
+ 
+-      if (!sg_is_valid_dxfer(hp))
++      if (hp->dxfer_len >= SZ_256M)
+               return -EINVAL;
+ 
+       k = sg_start_req(srp, cmnd);
+diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
+index 3ef90e91d8be..0c7b61f72478 100644
+--- a/fs/btrfs/extent_io.c
++++ b/fs/btrfs/extent_io.c
+@@ -4463,29 +4463,25 @@ static int emit_fiemap_extent(struct 
fiemap_extent_info *fieinfo,
+ }
+ 
+ /*
+- * Sanity check for fiemap cache
++ * Emit last fiemap cache
+  *
+- * All fiemap cache should be submitted by emit_fiemap_extent()
+- * Iteration should be terminated either by last fiemap extent or
+- * fieinfo->fi_extents_max.
+- * So no cached fiemap should exist.
++ * The last fiemap cache may still be cached in the following case:
++ * 0                4k                    8k
++ * |<- Fiemap range ->|
++ * |<------------  First extent ----------->|
++ *
++ * In this case, the first extent range will be cached but not emitted.
++ * So we must emit it before ending extent_fiemap().
+  */
+-static int check_fiemap_cache(struct btrfs_fs_info *fs_info,
+-                             struct fiemap_extent_info *fieinfo,
+-                             struct fiemap_cache *cache)
++static int emit_last_fiemap_cache(struct btrfs_fs_info *fs_info,
++                                struct fiemap_extent_info *fieinfo,
++                                struct fiemap_cache *cache)
+ {
+       int ret;
+ 
+       if (!cache->cached)
+               return 0;
+ 
+-      /* Small and recoverbale problem, only to info developer */
+-#ifdef CONFIG_BTRFS_DEBUG
+-      WARN_ON(1);
+-#endif
+-      btrfs_warn(fs_info,
+-                 "unhandled fiemap cache detected: offset=%llu phys=%llu 
len=%llu flags=0x%x",
+-                 cache->offset, cache->phys, cache->len, cache->flags);
+       ret = fiemap_fill_next_extent(fieinfo, cache->offset, cache->phys,
+                                     cache->len, cache->flags);
+       cache->cached = false;
+@@ -4701,7 +4697,7 @@ int extent_fiemap(struct inode *inode, struct 
fiemap_extent_info *fieinfo,
+       }
+ out_free:
+       if (!ret)
+-              ret = check_fiemap_cache(root->fs_info, fieinfo, &cache);
++              ret = emit_last_fiemap_cache(root->fs_info, fieinfo, &cache);
+       free_extent_map(em);
+ out:
+       btrfs_free_path(path);
+diff --git a/net/core/dev.c b/net/core/dev.c
+index 25f9461eff3f..528edc68a64a 100644
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -2670,7 +2670,7 @@ static inline bool skb_needs_check(struct sk_buff *skb, 
bool tx_path)
+ {
+       if (tx_path)
+               return skb->ip_summed != CHECKSUM_PARTIAL &&
+-                     skb->ip_summed != CHECKSUM_NONE;
++                     skb->ip_summed != CHECKSUM_UNNECESSARY;
+ 
+       return skb->ip_summed == CHECKSUM_NONE;
+ }
+diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
+index 58925b6597de..ab8ebd440423 100644
+--- a/net/ipv4/af_inet.c
++++ b/net/ipv4/af_inet.c
+@@ -1731,6 +1731,13 @@ static __net_init int inet_init_net(struct net *net)
+       net->ipv4.sysctl_ip_prot_sock = PROT_SOCK;
+ #endif
+ 
++      /* Some igmp sysctl, whose values are always used */
++      net->ipv4.sysctl_igmp_max_memberships = 20;
++      net->ipv4.sysctl_igmp_max_msf = 10;
++      /* IGMP reports for link-local multicast groups are enabled by default 
*/
++      net->ipv4.sysctl_igmp_llm_reports = 1;
++      net->ipv4.sysctl_igmp_qrv = 2;
++
+       return 0;
+ }
+ 
+diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
+index ec9a396fa466..3db1adb6b7a0 100644
+--- a/net/ipv4/igmp.c
++++ b/net/ipv4/igmp.c
+@@ -2974,12 +2974,6 @@ static int __net_init igmp_net_init(struct net *net)
+               goto out_sock;
+       }
+ 
+-      /* Sysctl initialization */
+-      net->ipv4.sysctl_igmp_max_memberships = 20;
+-      net->ipv4.sysctl_igmp_max_msf = 10;
+-      /* IGMP reports for link-local multicast groups are enabled by default 
*/
+-      net->ipv4.sysctl_igmp_llm_reports = 1;
+-      net->ipv4.sysctl_igmp_qrv = 2;
+       return 0;
+ 
+ out_sock:
+diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
+index 532b36e9ce2a..e5948c0c9759 100644
+--- a/net/ipv4/ip_output.c
++++ b/net/ipv4/ip_output.c
+@@ -964,11 +964,12 @@ static int __ip_append_data(struct sock *sk,
+               csummode = CHECKSUM_PARTIAL;
+ 
+       cork->length += length;
+-      if ((((length + (skb ? skb->len : fragheaderlen)) > mtu) ||
+-           (skb && skb_is_gso(skb))) &&
++      if ((skb && skb_is_gso(skb)) ||
++          (((length + (skb ? skb->len : fragheaderlen)) > mtu) &&
++          (skb_queue_len(queue) <= 1) &&
+           (sk->sk_protocol == IPPROTO_UDP) &&
+           (rt->dst.dev->features & NETIF_F_UFO) && !dst_xfrm(&rt->dst) &&
+-          (sk->sk_type == SOCK_DGRAM) && !sk->sk_no_check_tx) {
++          (sk->sk_type == SOCK_DGRAM) && !sk->sk_no_check_tx)) {
+               err = ip_ufo_append_data(sk, queue, getfrag, from, length,
+                                        hh_len, fragheaderlen, transhdrlen,
+                                        maxfraglen, flags);
+@@ -1287,6 +1288,7 @@ ssize_t  ip_append_page(struct sock *sk, struct flowi4 
*fl4, struct page *page,
+               return -EINVAL;
+ 
+       if ((size + skb->len > mtu) &&
++          (skb_queue_len(&sk->sk_write_queue) == 1) &&
+           (sk->sk_protocol == IPPROTO_UDP) &&
+           (rt->dst.dev->features & NETIF_F_UFO)) {
+               if (skb->ip_summed != CHECKSUM_PARTIAL)
+diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
+index 174d4376baa5..57bcae81fe42 100644
+--- a/net/ipv4/tcp_input.c
++++ b/net/ipv4/tcp_input.c
+@@ -2517,8 +2517,8 @@ static inline void tcp_end_cwnd_reduction(struct sock 
*sk)
+               return;
+ 
+       /* Reset cwnd to ssthresh in CWR or Recovery (unless it's undone) */
+-      if (inet_csk(sk)->icsk_ca_state == TCP_CA_CWR ||
+-          (tp->undo_marker && tp->snd_ssthresh < TCP_INFINITE_SSTHRESH)) {
++      if (tp->snd_ssthresh < TCP_INFINITE_SSTHRESH &&
++          (inet_csk(sk)->icsk_ca_state == TCP_CA_CWR || tp->undo_marker)) {
+               tp->snd_cwnd = tp->snd_ssthresh;
+               tp->snd_cwnd_stamp = tcp_time_stamp;
+       }
+diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
+index 4858e190f6ac..8963b8c5fb41 100644
+--- a/net/ipv4/tcp_output.c
++++ b/net/ipv4/tcp_output.c
+@@ -3361,6 +3361,9 @@ int tcp_connect(struct sock *sk)
+       struct sk_buff *buff;
+       int err;
+ 
++      if (inet_csk(sk)->icsk_af_ops->rebuild_header(sk))
++              return -EHOSTUNREACH; /* Routing failure or similar. */
++
+       tcp_connect_init(sk);
+ 
+       if (unlikely(tp->repair)) {
+diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
+index 14672543cf0b..0733ea7e17cd 100644
+--- a/net/ipv4/tcp_timer.c
++++ b/net/ipv4/tcp_timer.c
+@@ -654,7 +654,8 @@ static void tcp_keepalive_timer (unsigned long data)
+               goto death;
+       }
+ 
+-      if (!sock_flag(sk, SOCK_KEEPOPEN) || sk->sk_state == TCP_CLOSE)
++      if (!sock_flag(sk, SOCK_KEEPOPEN) ||
++          ((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_SYN_SENT)))
+               goto out;
+ 
+       elapsed = keepalive_time_when(tp);
+diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
+index b9a84eba60b8..c991b97cbb28 100644
+--- a/net/ipv4/udp.c
++++ b/net/ipv4/udp.c
+@@ -802,7 +802,7 @@ static int udp_send_skb(struct sk_buff *skb, struct flowi4 
*fl4)
+       if (is_udplite)                                  /*     UDP-Lite      */
+               csum = udplite_csum(skb);
+ 
+-      else if (sk->sk_no_check_tx) {   /* UDP csum disabled */
++      else if (sk->sk_no_check_tx && !skb_is_gso(skb)) {   /* UDP csum off */
+ 
+               skb->ip_summed = CHECKSUM_NONE;
+               goto send;
+diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c
+index 781250151d40..0932c85b42af 100644
+--- a/net/ipv4/udp_offload.c
++++ b/net/ipv4/udp_offload.c
+@@ -235,7 +235,7 @@ static struct sk_buff *udp4_ufo_fragment(struct sk_buff 
*skb,
+       if (uh->check == 0)
+               uh->check = CSUM_MANGLED_0;
+ 
+-      skb->ip_summed = CHECKSUM_NONE;
++      skb->ip_summed = CHECKSUM_UNNECESSARY;
+ 
+       /* If there is no outer header we can fake a checksum offload
+        * due to the fact that we have already done the checksum in
+diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
+index be0306778938..365d5108a326 100644
+--- a/net/ipv6/ip6_output.c
++++ b/net/ipv6/ip6_output.c
+@@ -1386,11 +1386,12 @@ static int __ip6_append_data(struct sock *sk,
+        */
+ 
+       cork->length += length;
+-      if ((((length + (skb ? skb->len : headersize)) > mtu) ||
+-           (skb && skb_is_gso(skb))) &&
++      if ((skb && skb_is_gso(skb)) ||
++          (((length + (skb ? skb->len : headersize)) > mtu) &&
++          (skb_queue_len(queue) <= 1) &&
+           (sk->sk_protocol == IPPROTO_UDP) &&
+           (rt->dst.dev->features & NETIF_F_UFO) && !dst_xfrm(&rt->dst) &&
+-          (sk->sk_type == SOCK_DGRAM) && !udp_get_no_check6_tx(sk)) {
++          (sk->sk_type == SOCK_DGRAM) && !udp_get_no_check6_tx(sk))) {
+               err = ip6_ufo_append_data(sk, queue, getfrag, from, length,
+                                         hh_len, fragheaderlen, exthdrlen,
+                                         transhdrlen, mtu, flags, fl6);
+diff --git a/net/ipv6/route.c b/net/ipv6/route.c
+index bc49f9a82994..aeb7097acc0a 100644
+--- a/net/ipv6/route.c
++++ b/net/ipv6/route.c
+@@ -2366,6 +2366,7 @@ static void rt6_do_redirect(struct dst_entry *dst, 
struct sock *sk, struct sk_bu
+       if (on_link)
+               nrt->rt6i_flags &= ~RTF_GATEWAY;
+ 
++      nrt->rt6i_protocol = RTPROT_REDIRECT;
+       nrt->rt6i_gateway = *(struct in6_addr *)neigh->primary_key;
+ 
+       if (ip6_ins_rt(nrt))
+@@ -2470,6 +2471,7 @@ static struct rt6_info *rt6_add_route_info(struct net 
*net,
+               .fc_dst_len     = prefixlen,
+               .fc_flags       = RTF_GATEWAY | RTF_ADDRCONF | RTF_ROUTEINFO |
+                                 RTF_UP | RTF_PREF(pref),
++              .fc_protocol = RTPROT_RA,
+               .fc_nlinfo.portid = 0,
+               .fc_nlinfo.nlh = NULL,
+               .fc_nlinfo.nl_net = net,
+@@ -2522,6 +2524,7 @@ struct rt6_info *rt6_add_dflt_router(const struct 
in6_addr *gwaddr,
+               .fc_ifindex     = dev->ifindex,
+               .fc_flags       = RTF_GATEWAY | RTF_ADDRCONF | RTF_DEFAULT |
+                                 RTF_UP | RTF_EXPIRES | RTF_PREF(pref),
++              .fc_protocol = RTPROT_RA,
+               .fc_nlinfo.portid = 0,
+               .fc_nlinfo.nlh = NULL,
+               .fc_nlinfo.nl_net = dev_net(dev),
+@@ -3434,14 +3437,6 @@ static int rt6_fill_node(struct net *net,
+       rtm->rtm_flags = 0;
+       rtm->rtm_scope = RT_SCOPE_UNIVERSE;
+       rtm->rtm_protocol = rt->rt6i_protocol;
+-      if (rt->rt6i_flags & RTF_DYNAMIC)
+-              rtm->rtm_protocol = RTPROT_REDIRECT;
+-      else if (rt->rt6i_flags & RTF_ADDRCONF) {
+-              if (rt->rt6i_flags & (RTF_DEFAULT | RTF_ROUTEINFO))
+-                      rtm->rtm_protocol = RTPROT_RA;
+-              else
+-                      rtm->rtm_protocol = RTPROT_KERNEL;
+-      }
+ 
+       if (rt->rt6i_flags & RTF_CACHE)
+               rtm->rtm_flags |= RTM_F_CLONED;
+diff --git a/net/ipv6/udp_offload.c b/net/ipv6/udp_offload.c
+index a2267f80febb..e7d378c032cb 100644
+--- a/net/ipv6/udp_offload.c
++++ b/net/ipv6/udp_offload.c
+@@ -72,7 +72,7 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb,
+               if (uh->check == 0)
+                       uh->check = CSUM_MANGLED_0;
+ 
+-              skb->ip_summed = CHECKSUM_NONE;
++              skb->ip_summed = CHECKSUM_UNNECESSARY;
+ 
+               /* If there is no outer header we can fake a checksum offload
+                * due to the fact that we have already done the checksum in
+diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
+index 0880e0a9d151..aa2d4000bafc 100644
+--- a/net/packet/af_packet.c
++++ b/net/packet/af_packet.c
+@@ -3705,14 +3705,19 @@ packet_setsockopt(struct socket *sock, int level, int 
optname, char __user *optv
+ 
+               if (optlen != sizeof(val))
+                       return -EINVAL;
+-              if (po->rx_ring.pg_vec || po->tx_ring.pg_vec)
+-                      return -EBUSY;
+               if (copy_from_user(&val, optval, sizeof(val)))
+                       return -EFAULT;
+               if (val > INT_MAX)
+                       return -EINVAL;
+-              po->tp_reserve = val;
+-              return 0;
++              lock_sock(sk);
++              if (po->rx_ring.pg_vec || po->tx_ring.pg_vec) {
++                      ret = -EBUSY;
++              } else {
++                      po->tp_reserve = val;
++                      ret = 0;
++              }
++              release_sock(sk);
++              return ret;
+       }
+       case PACKET_LOSS:
+       {
+diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c
+index 36f0ced9e60c..d516ba8178b8 100644
+--- a/net/sched/act_ipt.c
++++ b/net/sched/act_ipt.c
+@@ -36,8 +36,8 @@ static struct tc_action_ops act_ipt_ops;
+ static unsigned int xt_net_id;
+ static struct tc_action_ops act_xt_ops;
+ 
+-static int ipt_init_target(struct xt_entry_target *t, char *table,
+-                         unsigned int hook)
++static int ipt_init_target(struct net *net, struct xt_entry_target *t,
++                         char *table, unsigned int hook)
+ {
+       struct xt_tgchk_param par;
+       struct xt_target *target;
+@@ -49,8 +49,9 @@ static int ipt_init_target(struct xt_entry_target *t, char 
*table,
+               return PTR_ERR(target);
+ 
+       t->u.kernel.target = target;
++      memset(&par, 0, sizeof(par));
++      par.net       = net;
+       par.table     = table;
+-      par.entryinfo = NULL;
+       par.target    = target;
+       par.targinfo  = t->data;
+       par.hook_mask = hook;
+@@ -91,10 +92,11 @@ static const struct nla_policy ipt_policy[TCA_IPT_MAX + 1] 
= {
+       [TCA_IPT_TARG]  = { .len = sizeof(struct xt_entry_target) },
+ };
+ 
+-static int __tcf_ipt_init(struct tc_action_net *tn, struct nlattr *nla,
++static int __tcf_ipt_init(struct net *net, unsigned int id, struct nlattr 
*nla,
+                         struct nlattr *est, struct tc_action **a,
+                         const struct tc_action_ops *ops, int ovr, int bind)
+ {
++      struct tc_action_net *tn = net_generic(net, id);
+       struct nlattr *tb[TCA_IPT_MAX + 1];
+       struct tcf_ipt *ipt;
+       struct xt_entry_target *td, *t;
+@@ -159,7 +161,7 @@ static int __tcf_ipt_init(struct tc_action_net *tn, struct 
nlattr *nla,
+       if (unlikely(!t))
+               goto err2;
+ 
+-      err = ipt_init_target(t, tname, hook);
++      err = ipt_init_target(net, t, tname, hook);
+       if (err < 0)
+               goto err3;
+ 
+@@ -193,18 +195,16 @@ static int tcf_ipt_init(struct net *net, struct nlattr 
*nla,
+                       struct nlattr *est, struct tc_action **a, int ovr,
+                       int bind)
+ {
+-      struct tc_action_net *tn = net_generic(net, ipt_net_id);
+-
+-      return __tcf_ipt_init(tn, nla, est, a, &act_ipt_ops, ovr, bind);
++      return __tcf_ipt_init(net, ipt_net_id, nla, est, a, &act_ipt_ops, ovr,
++                            bind);
+ }
+ 
+ static int tcf_xt_init(struct net *net, struct nlattr *nla,
+                      struct nlattr *est, struct tc_action **a, int ovr,
+                      int bind)
+ {
+-      struct tc_action_net *tn = net_generic(net, xt_net_id);
+-
+-      return __tcf_ipt_init(tn, nla, est, a, &act_xt_ops, ovr, bind);
++      return __tcf_ipt_init(net, xt_net_id, nla, est, a, &act_xt_ops, ovr,
++                            bind);
+ }
+ 
+ static int tcf_ipt(struct sk_buff *skb, const struct tc_action *a,

Reply via email to