move fence_wdog_check_timer check to dev_hard_start_xmit from dev_hard_xmit
Author: Dmitry Guryanov Email: dgurya...@parallels.com Subject: WATCHDOG: schedule work in case of halt action Date: Wed, 22 May 2013 13:50:53 +0400 It's not possible to do a halt or poweroff from an atomic context. So let's schedule work and drop all outgoing network packets after time exhausted. fix for bug https://jira.sw.ru/browse/PSBM-20034 Signed-off-by: Dmitry Guryanov <dgurya...@parallels.com> Acked-by: Stanislav Kinsbursky <skinsbur...@parallels.com> Changes in v2: * don't specify cpu in schedule_work * use atomic_inc_not_zero instead of atomic_add_unless * return NETDEV_TX_OK instead of 0 from dev_hard_xmit Changes in v3: * use halt instead of poweroff Signed-off-by: Pavel Tikhomirov <ptikhomi...@virtuozzo.com> --- include/linux/fence-watchdog.h | 2 +- kernel/fence-watchdog.c | 35 ++++++++++++++++++++++++----------- net/core/dev.c | 14 +++++++++++--- 3 files changed, 36 insertions(+), 15 deletions(-) diff --git a/include/linux/fence-watchdog.h b/include/linux/fence-watchdog.h index 9cb41e9..b1e61bc 100644 --- a/include/linux/fence-watchdog.h +++ b/include/linux/fence-watchdog.h @@ -1,6 +1,6 @@ #ifndef _LINUX_FENCE_WATCHDOG_H_ #define _LINUX_FENCE_WATCHDOG_H_ -inline void fence_wdog_check_timer(void); +inline int fence_wdog_check_timer(void); #endif diff --git a/kernel/fence-watchdog.c b/kernel/fence-watchdog.c index e65e73d..e7b7152 100644 --- a/kernel/fence-watchdog.c +++ b/kernel/fence-watchdog.c @@ -32,15 +32,27 @@ const char *action_names[] = {"crash", "reboot", "halt", NULL}; DEFINE_VVAR(volatile unsigned long, fence_wdog_jiffies64) = MAX_U64; static int fence_wdog_action = FENCE_WDOG_CRASH; +static atomic_t not_fenced = ATOMIC_INIT(-1); + +static void do_halt(struct work_struct *dummy) +{ + printk(KERN_EMERG"fence-watchdog: %s\n", + action_names[fence_wdog_action]); + kernel_halt(); +} + +static DECLARE_WORK(halt_work, do_halt); void fence_wdog_do_fence(void) { char *killer = NULL; - bust_spinlocks(1); - printk(KERN_EMERG"fence-watchdog: %s\n", + if (fence_wdog_action != FENCE_WDOG_POWEROFF) { + bust_spinlocks(1); + printk(KERN_EMERG"fence-watchdog: %s\n", action_names[fence_wdog_action]); - bust_spinlocks(0); + bust_spinlocks(0); + } switch (fence_wdog_action) { case FENCE_WDOG_CRASH: @@ -54,19 +66,20 @@ void fence_wdog_do_fence(void) emergency_restart(); break; case FENCE_WDOG_POWEROFF: - lockdep_off(); - local_irq_enable(); - sysdev_shutdown(); - kmsg_dump(KMSG_DUMP_HALT); - machine_halt(); + schedule_work(&halt_work); break; } } -inline void fence_wdog_check_timer(void) +inline int fence_wdog_check_timer(void) { - if (get_jiffies_64() > fence_wdog_jiffies64) - fence_wdog_do_fence(); + if (unlikely(get_jiffies_64() > fence_wdog_jiffies64)) { + if (atomic_inc_not_zero(¬_fenced)) + fence_wdog_do_fence(); + return 1; + } + + return 0; } static ssize_t fence_wdog_timer_show(struct kobject *kobj, diff --git a/net/core/dev.c b/net/core/dev.c index 5002d76..a8dd551 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2501,6 +2501,13 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev, int rc = NETDEV_TX_OK; unsigned int skb_len; +#ifdef CONFIG_FENCE_WATCHDOG + if (unlikely(fence_wdog_check_timer())) { + kfree_skb(skb); + return NETDEV_TX_OK; + } +#endif + if (likely(!skb->next)) { netdev_features_t features; @@ -4282,6 +4289,10 @@ static void net_rx_action(struct softirq_action *h) local_irq_disable(); +#ifdef CONFIG_FENCE_WATCHDOG + fence_wdog_check_timer(); +#endif + while (!list_empty(&sd->poll_list)) { struct napi_struct *n; int work, weight; @@ -4352,9 +4363,6 @@ static void net_rx_action(struct softirq_action *h) out: net_rps_action_and_irq_enable(sd); -#ifdef CONFIG_FENCE_WATCHDOG - fence_wdog_check_timer(); -#endif return; softnet_break: -- 1.9.3 _______________________________________________ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel