From: Greg Kroah-Hartman Date: Thu, 14 Nov 2013 02:55:13 +0000 (+0900) Subject: 3.10-stable patches X-Git-Tag: v3.4.70~30 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=fc38f05b9bb20e5da467c0935a6ecbf69648caa9;p=thirdparty%2Fkernel%2Fstable-queue.git 3.10-stable patches added patches: cxgb3-fix-length-calculation-in-write_ofld_wr-on-32-bit-architectures.patch ip_gre-fix-wccpv2-header-parsing.patch ipv6-ip6_dst_check-needs-to-check-for-expired-dst_entries.patch ipv6-reset-dst.expires-value-when-clearing-expire-flag.patch net-flow_dissector-fail-on-evil-iph-ihl.patch net-mlx4_core-fix-call-to-__mlx4_unregister_mac.patch series virtio-net-correctly-handle-cpu-hotplug-notifier-during-resuming.patch xen-netback-handle-backend-state-transitions-in-a-more-robust-way.patch xen-netback-transition-to-closed-when-removing-a-vif.patch xen-netback-use-jiffies_64-value-to-calculate-credit-timeout.patch --- diff --git a/queue-3.10/cxgb3-fix-length-calculation-in-write_ofld_wr-on-32-bit-architectures.patch b/queue-3.10/cxgb3-fix-length-calculation-in-write_ofld_wr-on-32-bit-architectures.patch new file mode 100644 index 00000000000..b52c22c95d3 --- /dev/null +++ b/queue-3.10/cxgb3-fix-length-calculation-in-write_ofld_wr-on-32-bit-architectures.patch @@ -0,0 +1,45 @@ +From 932bc4212eab5f74cf876ee60989b23eddaae8f8 Mon Sep 17 00:00:00 2001 +From: Ben Hutchings +Date: Sun, 27 Oct 2013 21:02:39 +0000 +Subject: cxgb3: Fix length calculation in write_ofld_wr() on 32-bit architectures + +From: Ben Hutchings + +[ Upstream commit 262e827fe745642589450ae241b7afd3912c3f25 ] + +The length calculation here is now invalid on 32-bit architectures, +since sk_buff::tail is a pointer and sk_buff::transport_header is +an integer offset: + +drivers/net/ethernet/chelsio/cxgb3/sge.c: In function 'write_ofld_wr': +drivers/net/ethernet/chelsio/cxgb3/sge.c:1603:9: warning: passing argument 4 of 'make_sgl' makes integer from pointer without a cast [enabled by default] + adap->pdev); + ^ +drivers/net/ethernet/chelsio/cxgb3/sge.c:964:28: note: expected 'unsigned int' but argument is of type 'sk_buff_data_t' + static inline unsigned int make_sgl(const struct sk_buff *skb, + ^ + +Use the appropriate skb accessor functions. + +Compile-tested only. + +Signed-off-by: Ben Hutchings +Fixes: 1a37e412a022 ('net: Use 16bits for *_headers fields of struct skbuff') +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/chelsio/cxgb3/sge.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/net/ethernet/chelsio/cxgb3/sge.c ++++ b/drivers/net/ethernet/chelsio/cxgb3/sge.c +@@ -1600,7 +1600,8 @@ static void write_ofld_wr(struct adapter + flits = skb_transport_offset(skb) / 8; + sgp = ndesc == 1 ? (struct sg_ent *)&d->flit[flits] : sgl; + sgl_flits = make_sgl(skb, sgp, skb_transport_header(skb), +- skb->tail - skb->transport_header, ++ skb_tail_pointer(skb) - ++ skb_transport_header(skb), + adap->pdev); + if (need_skb_unmap()) { + setup_deferred_unmapping(skb, adap->pdev, sgp, sgl_flits); diff --git a/queue-3.10/ip_gre-fix-wccpv2-header-parsing.patch b/queue-3.10/ip_gre-fix-wccpv2-header-parsing.patch new file mode 100644 index 00000000000..a0f6ef61149 --- /dev/null +++ b/queue-3.10/ip_gre-fix-wccpv2-header-parsing.patch @@ -0,0 +1,79 @@ +From 29811f1bf697e68ee5c9c0c8b9f464c16d82d6c7 Mon Sep 17 00:00:00 2001 +From: Pravin B Shelar +Date: Mon, 28 Oct 2013 10:38:55 -0700 +Subject: ip_gre: Fix WCCPv2 header parsing. + +From: Pravin B Shelar + +[ No applicable upstream commit, the upstream implementation is + now completely different and doesn't have this bug. ] + +In case of WCCPv2 GRE header has extra four bytes. Following +patch pull those extra four bytes so that skb offsets are set +correctly. + +CC: Eric Dumazet +Reported-by: Peter Schmitt +Tested-by: Peter Schmitt +Signed-off-by: Pravin B Shelar +Signed-off-by: Greg Kroah-Hartman +--- + include/net/ip_tunnels.h | 2 +- + net/ipv4/ip_gre.c | 2 +- + net/ipv4/ip_tunnel.c | 4 ++-- + net/ipv4/ipip.c | 2 +- + 4 files changed, 5 insertions(+), 5 deletions(-) + +--- a/include/net/ip_tunnels.h ++++ b/include/net/ip_tunnels.h +@@ -113,7 +113,7 @@ struct ip_tunnel *ip_tunnel_lookup(struc + __be32 key); + + int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb, +- const struct tnl_ptk_info *tpi, bool log_ecn_error); ++ const struct tnl_ptk_info *tpi, int hdr_len, bool log_ecn_error); + int ip_tunnel_changelink(struct net_device *dev, struct nlattr *tb[], + struct ip_tunnel_parm *p); + int ip_tunnel_newlink(struct net_device *dev, struct nlattr *tb[], +--- a/net/ipv4/ip_gre.c ++++ b/net/ipv4/ip_gre.c +@@ -335,7 +335,7 @@ static int ipgre_rcv(struct sk_buff *skb + iph->saddr, iph->daddr, tpi.key); + + if (tunnel) { +- ip_tunnel_rcv(tunnel, skb, &tpi, log_ecn_error); ++ ip_tunnel_rcv(tunnel, skb, &tpi, hdr_len, log_ecn_error); + return 0; + } + icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); +--- a/net/ipv4/ip_tunnel.c ++++ b/net/ipv4/ip_tunnel.c +@@ -402,7 +402,7 @@ static struct ip_tunnel *ip_tunnel_creat + } + + int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb, +- const struct tnl_ptk_info *tpi, bool log_ecn_error) ++ const struct tnl_ptk_info *tpi, int hdr_len, bool log_ecn_error) + { + struct pcpu_tstats *tstats; + const struct iphdr *iph = ip_hdr(skb); +@@ -413,7 +413,7 @@ int ip_tunnel_rcv(struct ip_tunnel *tunn + skb->protocol = tpi->proto; + + skb->mac_header = skb->network_header; +- __pskb_pull(skb, tunnel->hlen); ++ __pskb_pull(skb, hdr_len); + skb_postpull_rcsum(skb, skb_transport_header(skb), tunnel->hlen); + #ifdef CONFIG_NET_IPGRE_BROADCAST + if (ipv4_is_multicast(iph->daddr)) { +--- a/net/ipv4/ipip.c ++++ b/net/ipv4/ipip.c +@@ -195,7 +195,7 @@ static int ipip_rcv(struct sk_buff *skb) + if (tunnel) { + if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) + goto drop; +- return ip_tunnel_rcv(tunnel, skb, &tpi, log_ecn_error); ++ return ip_tunnel_rcv(tunnel, skb, &tpi, 0, log_ecn_error); + } + + return -1; diff --git a/queue-3.10/ipv6-ip6_dst_check-needs-to-check-for-expired-dst_entries.patch b/queue-3.10/ipv6-ip6_dst_check-needs-to-check-for-expired-dst_entries.patch new file mode 100644 index 00000000000..271c70b482c --- /dev/null +++ b/queue-3.10/ipv6-ip6_dst_check-needs-to-check-for-expired-dst_entries.patch @@ -0,0 +1,68 @@ +From 4f2a19b55d944b754a564552cc8bcbdfa6675b1f Mon Sep 17 00:00:00 2001 +From: Hannes Frederic Sowa +Date: Thu, 24 Oct 2013 07:48:24 +0200 +Subject: ipv6: ip6_dst_check needs to check for expired dst_entries + +From: Hannes Frederic Sowa + +[ Upstream commit e3bc10bd95d7fcc3f2ac690c6ff22833ea6781d6 ] + +On receiving a packet too big icmp error we check if our current cached +dst_entry in the socket is still valid. This validation check did not +care about the expiration of the (cached) route. + +The error path I traced down: +The socket receives a packet too big mtu notification. It still has a +valid dst_entry and thus issues the ip6_rt_pmtu_update on this dst_entry, +setting RTF_EXPIRE and updates the dst.expiration value (which could +fail because of not up-to-date expiration values, see previous patch). + +In some seldom cases we race with a) the ip6_fib gc or b) another routing +lookup which would result in a recreation of the cached rt6_info from its +parent non-cached rt6_info. While copying the rt6_info we reinitialize the +metrics store by copying it over from the parent thus invalidating the +just installed pmtu update (both dsts use the same key to the inetpeer +storage). The dst_entry with the just invalidated metrics data would +just get its RTF_EXPIRES flag cleared and would continue to stay valid +for the socket. + +We should have not issued the pmtu update on the already expired dst_entry +in the first placed. By checking the expiration on the dst entry and +doing a relookup in case it is out of date we close the race because +we would install a new rt6_info into the fib before we issue the pmtu +update, thus closing this race. + +Not reliably updating the dst.expire value was fixed by the patch "ipv6: +reset dst.expires value when clearing expire flag". + +Reported-by: Steinar H. Gunderson +Reported-by: Valentijn Sessink +Cc: YOSHIFUJI Hideaki +Signed-off-by: Hannes Frederic Sowa +Reviewed-by: Eric Dumazet +Tested-by: Valentijn Sessink +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv6/route.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +--- a/net/ipv6/route.c ++++ b/net/ipv6/route.c +@@ -1084,10 +1084,13 @@ static struct dst_entry *ip6_dst_check(s + if (rt->rt6i_genid != rt_genid(dev_net(rt->dst.dev))) + return NULL; + +- if (rt->rt6i_node && (rt->rt6i_node->fn_sernum == cookie)) +- return dst; ++ if (!rt->rt6i_node || (rt->rt6i_node->fn_sernum != cookie)) ++ return NULL; ++ ++ if (rt6_check_expired(rt)) ++ return NULL; + +- return NULL; ++ return dst; + } + + static struct dst_entry *ip6_negative_advice(struct dst_entry *dst) diff --git a/queue-3.10/ipv6-reset-dst.expires-value-when-clearing-expire-flag.patch b/queue-3.10/ipv6-reset-dst.expires-value-when-clearing-expire-flag.patch new file mode 100644 index 00000000000..41477794b0d --- /dev/null +++ b/queue-3.10/ipv6-reset-dst.expires-value-when-clearing-expire-flag.patch @@ -0,0 +1,54 @@ +From 42e8e1242b39e258b3178fcbcade59eda1bb0a73 Mon Sep 17 00:00:00 2001 +From: Hannes Frederic Sowa +Date: Thu, 24 Oct 2013 10:14:27 +0200 +Subject: ipv6: reset dst.expires value when clearing expire flag + +From: Hannes Frederic Sowa + +[ Upstream commit 01ba16d6ec85a1ec4669c75513a76b61ec53ee50 ] + +On receiving a packet too big icmp error we update the expire value by +calling rt6_update_expires. This function uses dst_set_expires which is +implemented that it can only reduce the expiration value of the dst entry. + +If we insert new routing non-expiry information into the ipv6 fib where +we already have a matching rt6_info we only clear the RTF_EXPIRES flag +in rt6i_flags and leave the dst.expires value as is. + +When new mtu information arrives for that cached dst_entry we again +call dst_set_expires. This time it won't update the dst.expire value +because we left the dst.expire value intact from the last update. So +dst_set_expires won't touch dst.expires. + +Fix this by resetting dst.expires when clearing the RTF_EXPIRE flag. +dst_set_expires checks for a zero expiration and updates the +dst.expires. + +In the past this (not updating dst.expires) was necessary because +dst.expire was placed in a union with the dst_entry *from reference +and rt6_clean_expires did assign NULL to it. This split happend in +ecd9883724b78cc72ed92c98bcb1a46c764fff21 ("ipv6: fix race condition +regarding dst->expires and dst->from"). + +Reported-by: Steinar H. Gunderson +Reported-by: Valentijn Sessink +Cc: YOSHIFUJI Hideaki +Acked-by: Eric Dumazet +Tested-by: Valentijn Sessink +Signed-off-by: Hannes Frederic Sowa +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + include/net/ip6_fib.h | 1 + + 1 file changed, 1 insertion(+) + +--- a/include/net/ip6_fib.h ++++ b/include/net/ip6_fib.h +@@ -165,6 +165,7 @@ static inline struct inet6_dev *ip6_dst_ + static inline void rt6_clean_expires(struct rt6_info *rt) + { + rt->rt6i_flags &= ~RTF_EXPIRES; ++ rt->dst.expires = 0; + } + + static inline void rt6_set_expires(struct rt6_info *rt, unsigned long expires) diff --git a/queue-3.10/net-flow_dissector-fail-on-evil-iph-ihl.patch b/queue-3.10/net-flow_dissector-fail-on-evil-iph-ihl.patch new file mode 100644 index 00000000000..f38cc297a1f --- /dev/null +++ b/queue-3.10/net-flow_dissector-fail-on-evil-iph-ihl.patch @@ -0,0 +1,39 @@ +From 66c176a08e33daf7b619441c46c657adcda93889 Mon Sep 17 00:00:00 2001 +From: Jason Wang +Date: Fri, 1 Nov 2013 15:01:10 +0800 +Subject: net: flow_dissector: fail on evil iph->ihl + +From: Jason Wang + +[ Upstream commit 6f092343855a71e03b8d209815d8c45bf3a27fcd ] + +We don't validate iph->ihl which may lead a dead loop if we meet a IPIP +skb whose iph->ihl is zero. Fix this by failing immediately when iph->ihl +is evil (less than 5). + +This issue were introduced by commit ec5efe7946280d1e84603389a1030ccec0a767ae +(rps: support IPIP encapsulation). + +Signed-off-by: Jason Wang +Cc: Eric Dumazet +Cc: Petr Matousek +Cc: Michael S. Tsirkin +Cc: Daniel Borkmann +Acked-by: Eric Dumazet +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/core/flow_dissector.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/core/flow_dissector.c ++++ b/net/core/flow_dissector.c +@@ -40,7 +40,7 @@ again: + struct iphdr _iph; + ip: + iph = skb_header_pointer(skb, nhoff, sizeof(_iph), &_iph); +- if (!iph) ++ if (!iph || iph->ihl < 5) + return false; + + if (ip_is_fragment(iph)) diff --git a/queue-3.10/net-mlx4_core-fix-call-to-__mlx4_unregister_mac.patch b/queue-3.10/net-mlx4_core-fix-call-to-__mlx4_unregister_mac.patch new file mode 100644 index 00000000000..66c48a678a7 --- /dev/null +++ b/queue-3.10/net-mlx4_core-fix-call-to-__mlx4_unregister_mac.patch @@ -0,0 +1,31 @@ +From d6de8d2b18605c5a5f01cf001bce1bf6ef8765fe Mon Sep 17 00:00:00 2001 +From: Jack Morgenstein +Date: Sun, 3 Nov 2013 10:04:07 +0200 +Subject: net/mlx4_core: Fix call to __mlx4_unregister_mac + +From: Jack Morgenstein + +[ Upstream commit c32b7dfbb1dfb3f0a68f250deff65103c8bb704a ] + +In function mlx4_master_deactivate_admin_state() __mlx4_unregister_mac was +called using the MAC index. It should be called with the value of the MAC itself. + +Signed-off-by: Jack Morgenstein +Signed-off-by: Or Gerlitz +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/mellanox/mlx4/cmd.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/ethernet/mellanox/mlx4/cmd.c ++++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c +@@ -1544,7 +1544,7 @@ static void mlx4_master_deactivate_admin + vp_oper->vlan_idx = NO_INDX; + } + if (NO_INDX != vp_oper->mac_idx) { +- __mlx4_unregister_mac(&priv->dev, port, vp_oper->mac_idx); ++ __mlx4_unregister_mac(&priv->dev, port, vp_oper->state.mac); + vp_oper->mac_idx = NO_INDX; + } + } diff --git a/queue-3.10/series b/queue-3.10/series new file mode 100644 index 00000000000..bfa876f629d --- /dev/null +++ b/queue-3.10/series @@ -0,0 +1,10 @@ +ip_gre-fix-wccpv2-header-parsing.patch +ipv6-ip6_dst_check-needs-to-check-for-expired-dst_entries.patch +ipv6-reset-dst.expires-value-when-clearing-expire-flag.patch +cxgb3-fix-length-calculation-in-write_ofld_wr-on-32-bit-architectures.patch +xen-netback-use-jiffies_64-value-to-calculate-credit-timeout.patch +virtio-net-correctly-handle-cpu-hotplug-notifier-during-resuming.patch +net-flow_dissector-fail-on-evil-iph-ihl.patch +net-mlx4_core-fix-call-to-__mlx4_unregister_mac.patch +xen-netback-handle-backend-state-transitions-in-a-more-robust-way.patch +xen-netback-transition-to-closed-when-removing-a-vif.patch diff --git a/queue-3.10/virtio-net-correctly-handle-cpu-hotplug-notifier-during-resuming.patch b/queue-3.10/virtio-net-correctly-handle-cpu-hotplug-notifier-during-resuming.patch new file mode 100644 index 00000000000..5947cf1b0ad --- /dev/null +++ b/queue-3.10/virtio-net-correctly-handle-cpu-hotplug-notifier-during-resuming.patch @@ -0,0 +1,116 @@ +From c2ad10d575684b896ca1a57c353c038a76dd1d30 Mon Sep 17 00:00:00 2001 +From: Jason Wang +Date: Tue, 29 Oct 2013 15:11:07 +0800 +Subject: virtio-net: correctly handle cpu hotplug notifier during resuming + +From: Jason Wang + +[ Upstream commit ec9debbd9a88d8ea86c488d6ffcac419ee7d46d9 ] + +commit 3ab098df35f8b98b6553edc2e40234af512ba877 (virtio-net: don't respond to +cpu hotplug notifier if we're not ready) tries to bypass the cpu hotplug +notifier by checking the config_enable and does nothing is it was false. So it +need to try to hold the config_lock mutex which may happen in atomic +environment which leads the following warnings: + +[ 622.944441] CPU0 attaching NULL sched-domain. +[ 622.944446] CPU1 attaching NULL sched-domain. +[ 622.944485] CPU0 attaching NULL sched-domain. +[ 622.950795] BUG: sleeping function called from invalid context at kernel/mutex.c:616 +[ 622.950796] in_atomic(): 1, irqs_disabled(): 1, pid: 10, name: migration/1 +[ 622.950796] no locks held by migration/1/10. +[ 622.950798] CPU: 1 PID: 10 Comm: migration/1 Not tainted 3.12.0-rc5-wl-01249-gb91e82d #317 +[ 622.950799] Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011 +[ 622.950802] 0000000000000000 ffff88001d42dba0 ffffffff81a32f22 ffff88001bfb9c70 +[ 622.950803] ffff88001d42dbb0 ffffffff810edb02 ffff88001d42dc38 ffffffff81a396ed +[ 622.950805] 0000000000000046 ffff88001d42dbe8 ffffffff810e861d 0000000000000000 +[ 622.950805] Call Trace: +[ 622.950810] [] dump_stack+0x54/0x74 +[ 622.950815] [] __might_sleep+0x112/0x114 +[ 622.950817] [] mutex_lock_nested+0x3c/0x3c6 +[ 622.950818] [] ? up+0x39/0x3e +[ 622.950821] [] ? acpi_os_signal_semaphore+0x21/0x2d +[ 622.950824] [] ? acpi_ut_release_mutex+0x5e/0x62 +[ 622.950828] [] virtnet_cpu_callback+0x33/0x87 +[ 622.950830] [] notifier_call_chain+0x3c/0x5e +[ 622.950832] [] __raw_notifier_call_chain+0xe/0x10 +[ 622.950835] [] __cpu_notify+0x20/0x37 +[ 622.950836] [] cpu_notify+0x13/0x15 +[ 622.950838] [] take_cpu_down+0x27/0x3a +[ 622.950841] [] stop_machine_cpu_stop+0x93/0xf1 +[ 622.950842] [] cpu_stopper_thread+0xa0/0x12f +[ 622.950844] [] ? cpu_stopper_thread+0x12f/0x12f +[ 622.950847] [] ? lock_release_holdtime.part.7+0xa3/0xa8 +[ 622.950848] [] ? cpu_stop_should_run+0x3f/0x47 +[ 622.950850] [] smpboot_thread_fn+0x1c5/0x1e3 +[ 622.950852] [] ? lg_global_unlock+0x67/0x67 +[ 622.950854] [] kthread+0xd8/0xe0 +[ 622.950857] [] ? wait_for_common+0x12f/0x164 +[ 622.950859] [] ? kthread_create_on_node+0x124/0x124 +[ 622.950861] [] ret_from_fork+0x7c/0xb0 +[ 622.950862] [] ? kthread_create_on_node+0x124/0x124 +[ 622.950876] smpboot: CPU 1 is now offline +[ 623.194556] SMP alternatives: lockdep: fixing up alternatives +[ 623.194559] smpboot: Booting Node 0 Processor 1 APIC 0x1 +... + +A correct fix is to unregister the hotcpu notifier during restore and register a +new one in resume. + +Reported-by: Fengguang Wu +Tested-by: Fengguang Wu +Cc: Wanlong Gao +Cc: Rusty Russell +Cc: Michael S. Tsirkin +Signed-off-by: Jason Wang +Acked-by: Michael S. Tsirkin +Reviewed-by: Wanlong Gao +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/virtio_net.c | 13 ++++++------- + 1 file changed, 6 insertions(+), 7 deletions(-) + +--- a/drivers/net/virtio_net.c ++++ b/drivers/net/virtio_net.c +@@ -1096,11 +1096,6 @@ static int virtnet_cpu_callback(struct n + { + struct virtnet_info *vi = container_of(nfb, struct virtnet_info, nb); + +- mutex_lock(&vi->config_lock); +- +- if (!vi->config_enable) +- goto done; +- + switch(action & ~CPU_TASKS_FROZEN) { + case CPU_ONLINE: + case CPU_DOWN_FAILED: +@@ -1114,8 +1109,6 @@ static int virtnet_cpu_callback(struct n + break; + } + +-done: +- mutex_unlock(&vi->config_lock); + return NOTIFY_OK; + } + +@@ -1672,6 +1665,8 @@ static int virtnet_freeze(struct virtio_ + struct virtnet_info *vi = vdev->priv; + int i; + ++ unregister_hotcpu_notifier(&vi->nb); ++ + /* Prevent config work handler from accessing the device */ + mutex_lock(&vi->config_lock); + vi->config_enable = false; +@@ -1720,6 +1715,10 @@ static int virtnet_restore(struct virtio + virtnet_set_queues(vi, vi->curr_queue_pairs); + rtnl_unlock(); + ++ err = register_hotcpu_notifier(&vi->nb); ++ if (err) ++ return err; ++ + return 0; + } + #endif diff --git a/queue-3.10/xen-netback-handle-backend-state-transitions-in-a-more-robust-way.patch b/queue-3.10/xen-netback-handle-backend-state-transitions-in-a-more-robust-way.patch new file mode 100644 index 00000000000..47e1cd21b6a --- /dev/null +++ b/queue-3.10/xen-netback-handle-backend-state-transitions-in-a-more-robust-way.patch @@ -0,0 +1,249 @@ +From 3541fc8387b844547671fba0a0725381cf4b1016 Mon Sep 17 00:00:00 2001 +From: Paul Durrant +Date: Thu, 26 Sep 2013 12:09:52 +0100 +Subject: xen-netback: Handle backend state transitions in a more robust way + +From: Paul Durrant + +[ Upstream commit ea732dff5cfa10789007bf4a5b935388a0bb2a8f ] + +When the frontend state changes netback now specifies its desired state to +a new function, set_backend_state(), which transitions through any +necessary intermediate states. +This fixes an issue observed with some old Windows frontend drivers where +they failed to transition through the Closing state and netback would not +behave correctly. + +Signed-off-by: Paul Durrant +Cc: Ian Campbell +Cc: Wei Liu +Cc: David Vrabel +Acked-by: Ian Campbell +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/xen-netback/xenbus.c | 149 ++++++++++++++++++++++++++++++--------- + 1 file changed, 118 insertions(+), 31 deletions(-) + +--- a/drivers/net/xen-netback/xenbus.c ++++ b/drivers/net/xen-netback/xenbus.c +@@ -24,6 +24,12 @@ + struct backend_info { + struct xenbus_device *dev; + struct xenvif *vif; ++ ++ /* This is the state that will be reflected in xenstore when any ++ * active hotplug script completes. ++ */ ++ enum xenbus_state state; ++ + enum xenbus_state frontend_state; + struct xenbus_watch hotplug_status_watch; + u8 have_hotplug_status_watch:1; +@@ -126,6 +132,8 @@ static int netback_probe(struct xenbus_d + if (err) + goto fail; + ++ be->state = XenbusStateInitWait; ++ + /* This kicks hotplug scripts, so do it immediately. */ + backend_create_xenvif(be); + +@@ -198,24 +206,113 @@ static void backend_create_xenvif(struct + kobject_uevent(&dev->dev.kobj, KOBJ_ONLINE); + } + +- +-static void disconnect_backend(struct xenbus_device *dev) ++static void backend_disconnect(struct backend_info *be) + { +- struct backend_info *be = dev_get_drvdata(&dev->dev); +- + if (be->vif) + xenvif_disconnect(be->vif); + } + +-static void destroy_backend(struct xenbus_device *dev) ++static void backend_connect(struct backend_info *be) + { +- struct backend_info *be = dev_get_drvdata(&dev->dev); ++ if (be->vif) ++ connect(be); ++} + +- if (be->vif) { +- kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE); +- xenbus_rm(XBT_NIL, dev->nodename, "hotplug-status"); +- xenvif_free(be->vif); +- be->vif = NULL; ++static inline void backend_switch_state(struct backend_info *be, ++ enum xenbus_state state) ++{ ++ struct xenbus_device *dev = be->dev; ++ ++ pr_debug("%s -> %s\n", dev->nodename, xenbus_strstate(state)); ++ be->state = state; ++ ++ /* If we are waiting for a hotplug script then defer the ++ * actual xenbus state change. ++ */ ++ if (!be->have_hotplug_status_watch) ++ xenbus_switch_state(dev, state); ++} ++ ++/* Handle backend state transitions: ++ * ++ * The backend state starts in InitWait and the following transitions are ++ * allowed. ++ * ++ * InitWait -> Connected ++ * ++ * ^ \ | ++ * | \ | ++ * | \ | ++ * | \ | ++ * | \ | ++ * | \ | ++ * | V V ++ * ++ * Closed <-> Closing ++ * ++ * The state argument specifies the eventual state of the backend and the ++ * function transitions to that state via the shortest path. ++ */ ++static void set_backend_state(struct backend_info *be, ++ enum xenbus_state state) ++{ ++ while (be->state != state) { ++ switch (be->state) { ++ case XenbusStateClosed: ++ switch (state) { ++ case XenbusStateInitWait: ++ case XenbusStateConnected: ++ pr_info("%s: prepare for reconnect\n", ++ be->dev->nodename); ++ backend_switch_state(be, XenbusStateInitWait); ++ break; ++ case XenbusStateClosing: ++ backend_switch_state(be, XenbusStateClosing); ++ break; ++ default: ++ BUG(); ++ } ++ break; ++ case XenbusStateInitWait: ++ switch (state) { ++ case XenbusStateConnected: ++ backend_connect(be); ++ backend_switch_state(be, XenbusStateConnected); ++ break; ++ case XenbusStateClosing: ++ case XenbusStateClosed: ++ backend_switch_state(be, XenbusStateClosing); ++ break; ++ default: ++ BUG(); ++ } ++ break; ++ case XenbusStateConnected: ++ switch (state) { ++ case XenbusStateInitWait: ++ case XenbusStateClosing: ++ case XenbusStateClosed: ++ backend_disconnect(be); ++ backend_switch_state(be, XenbusStateClosing); ++ break; ++ default: ++ BUG(); ++ } ++ break; ++ case XenbusStateClosing: ++ switch (state) { ++ case XenbusStateInitWait: ++ case XenbusStateConnected: ++ case XenbusStateClosed: ++ backend_switch_state(be, XenbusStateClosed); ++ break; ++ default: ++ BUG(); ++ } ++ break; ++ default: ++ BUG(); ++ } + } + } + +@@ -227,41 +324,33 @@ static void frontend_changed(struct xenb + { + struct backend_info *be = dev_get_drvdata(&dev->dev); + +- pr_debug("frontend state %s", xenbus_strstate(frontend_state)); ++ pr_debug("%s -> %s\n", dev->otherend, xenbus_strstate(frontend_state)); + + be->frontend_state = frontend_state; + + switch (frontend_state) { + case XenbusStateInitialising: +- if (dev->state == XenbusStateClosed) { +- printk(KERN_INFO "%s: %s: prepare for reconnect\n", +- __func__, dev->nodename); +- xenbus_switch_state(dev, XenbusStateInitWait); +- } ++ set_backend_state(be, XenbusStateInitWait); + break; + + case XenbusStateInitialised: + break; + + case XenbusStateConnected: +- if (dev->state == XenbusStateConnected) +- break; +- if (be->vif) +- connect(be); ++ set_backend_state(be, XenbusStateConnected); + break; + + case XenbusStateClosing: +- disconnect_backend(dev); +- xenbus_switch_state(dev, XenbusStateClosing); ++ set_backend_state(be, XenbusStateClosing); + break; + + case XenbusStateClosed: +- xenbus_switch_state(dev, XenbusStateClosed); ++ set_backend_state(be, XenbusStateClosed); + if (xenbus_dev_is_online(dev)) + break; +- destroy_backend(dev); + /* fall through if not online */ + case XenbusStateUnknown: ++ set_backend_state(be, XenbusStateClosed); + device_unregister(&dev->dev); + break; + +@@ -354,7 +443,9 @@ static void hotplug_status_changed(struc + if (IS_ERR(str)) + return; + if (len == sizeof("connected")-1 && !memcmp(str, "connected", len)) { +- xenbus_switch_state(be->dev, XenbusStateConnected); ++ /* Complete any pending state change */ ++ xenbus_switch_state(be->dev, be->state); ++ + /* Not interested in this watch anymore. */ + unregister_hotplug_status_watch(be); + } +@@ -384,12 +475,8 @@ static void connect(struct backend_info + err = xenbus_watch_pathfmt(dev, &be->hotplug_status_watch, + hotplug_status_changed, + "%s/%s", dev->nodename, "hotplug-status"); +- if (err) { +- /* Switch now, since we can't do a watch. */ +- xenbus_switch_state(dev, XenbusStateConnected); +- } else { ++ if (!err) + be->have_hotplug_status_watch = 1; +- } + + netif_wake_queue(be->vif->dev); + } diff --git a/queue-3.10/xen-netback-transition-to-closed-when-removing-a-vif.patch b/queue-3.10/xen-netback-transition-to-closed-when-removing-a-vif.patch new file mode 100644 index 00000000000..6751f0c52b3 --- /dev/null +++ b/queue-3.10/xen-netback-transition-to-closed-when-removing-a-vif.patch @@ -0,0 +1,50 @@ +From 619a333e10f36740f152463d3768b9d69a611068 Mon Sep 17 00:00:00 2001 +From: David Vrabel +Date: Mon, 7 Oct 2013 13:55:19 +0100 +Subject: xen-netback: transition to CLOSED when removing a VIF + +From: David Vrabel + +[ Upstream commit dc62ccaccfb139d9b04bbc5a2688a4402adbfab3 ] + +If a guest is destroyed without transitioning its frontend to CLOSED, +the domain becomes a zombie as netback was not grant unmapping the +shared rings. + +When removing a VIF, transition the backend to CLOSED so the VIF is +disconnected if necessary (which will unmap the shared rings etc). + +This fixes a regression introduced by +279f438e36c0a70b23b86d2090aeec50155034a9 (xen-netback: Don't destroy +the netdev until the vif is shut down). + +Signed-off-by: David Vrabel +Cc: Ian Campbell +Cc: Wei Liu +Cc: Paul Durrant +Acked-by: Wei Liu +Reviewed-by: Paul Durrant +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/xen-netback/xenbus.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/net/xen-netback/xenbus.c ++++ b/drivers/net/xen-netback/xenbus.c +@@ -39,11 +39,15 @@ static int connect_rings(struct backend_ + static void connect(struct backend_info *); + static void backend_create_xenvif(struct backend_info *be); + static void unregister_hotplug_status_watch(struct backend_info *be); ++static void set_backend_state(struct backend_info *be, ++ enum xenbus_state state); + + static int netback_remove(struct xenbus_device *dev) + { + struct backend_info *be = dev_get_drvdata(&dev->dev); + ++ set_backend_state(be, XenbusStateClosed); ++ + unregister_hotplug_status_watch(be); + if (be->vif) { + kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE); diff --git a/queue-3.10/xen-netback-use-jiffies_64-value-to-calculate-credit-timeout.patch b/queue-3.10/xen-netback-use-jiffies_64-value-to-calculate-credit-timeout.patch new file mode 100644 index 00000000000..737e2d04303 --- /dev/null +++ b/queue-3.10/xen-netback-use-jiffies_64-value-to-calculate-credit-timeout.patch @@ -0,0 +1,87 @@ +From d279fe2fe398bfd41a7d614ceeb7ad73941e0a51 Mon Sep 17 00:00:00 2001 +From: Wei Liu +Date: Mon, 28 Oct 2013 12:07:57 +0000 +Subject: xen-netback: use jiffies_64 value to calculate credit timeout + +From: Wei Liu + +[ Upstream commit 059dfa6a93b779516321e5112db9d7621b1367ba ] + +time_after_eq() only works if the delta is < MAX_ULONG/2. + +For a 32bit Dom0, if netfront sends packets at a very low rate, the time +between subsequent calls to tx_credit_exceeded() may exceed MAX_ULONG/2 +and the test for timer_after_eq() will be incorrect. Credit will not be +replenished and the guest may become unable to send packets (e.g., if +prior to the long gap, all credit was exhausted). + +Use jiffies_64 variant to mitigate this problem for 32bit Dom0. + +Suggested-by: Jan Beulich +Signed-off-by: Wei Liu +Reviewed-by: David Vrabel +Cc: Ian Campbell +Cc: Jason Luan +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/xen-netback/common.h | 1 + + drivers/net/xen-netback/interface.c | 3 +-- + drivers/net/xen-netback/netback.c | 10 +++++----- + 3 files changed, 7 insertions(+), 7 deletions(-) + +--- a/drivers/net/xen-netback/common.h ++++ b/drivers/net/xen-netback/common.h +@@ -88,6 +88,7 @@ struct xenvif { + unsigned long credit_usec; + unsigned long remaining_credit; + struct timer_list credit_timeout; ++ u64 credit_window_start; + + /* Statistics */ + unsigned long rx_gso_checksum_fixup; +--- a/drivers/net/xen-netback/interface.c ++++ b/drivers/net/xen-netback/interface.c +@@ -275,8 +275,7 @@ struct xenvif *xenvif_alloc(struct devic + vif->credit_bytes = vif->remaining_credit = ~0UL; + vif->credit_usec = 0UL; + init_timer(&vif->credit_timeout); +- /* Initialize 'expires' now: it's used to track the credit window. */ +- vif->credit_timeout.expires = jiffies; ++ vif->credit_window_start = get_jiffies_64(); + + dev->netdev_ops = &xenvif_netdev_ops; + dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO; +--- a/drivers/net/xen-netback/netback.c ++++ b/drivers/net/xen-netback/netback.c +@@ -1423,9 +1423,8 @@ out: + + static bool tx_credit_exceeded(struct xenvif *vif, unsigned size) + { +- unsigned long now = jiffies; +- unsigned long next_credit = +- vif->credit_timeout.expires + ++ u64 now = get_jiffies_64(); ++ u64 next_credit = vif->credit_window_start + + msecs_to_jiffies(vif->credit_usec / 1000); + + /* Timer could already be pending in rare cases. */ +@@ -1433,8 +1432,8 @@ static bool tx_credit_exceeded(struct xe + return true; + + /* Passed the point where we can replenish credit? */ +- if (time_after_eq(now, next_credit)) { +- vif->credit_timeout.expires = now; ++ if (time_after_eq64(now, next_credit)) { ++ vif->credit_window_start = now; + tx_add_credit(vif); + } + +@@ -1446,6 +1445,7 @@ static bool tx_credit_exceeded(struct xe + tx_credit_callback; + mod_timer(&vif->credit_timeout, + next_credit); ++ vif->credit_window_start = next_credit; + + return true; + }