[Devel] [PATCH RH7 5/9] Port: diff-fence-watchdog-schedule-work -in-case-of-halt-action
Pavel Tikhomirov
ptikhomirov at virtuozzo.com
Tue Oct 13 07:52:55 PDT 2015
move fence_wdog_check_timer check to dev_hard_start_xmit
from dev_hard_xmit
Author: Dmitry Guryanov
Email: dguryanov at 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 <dguryanov at parallels.com>
Acked-by: Stanislav Kinsbursky <skinsbursky at 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 <ptikhomirov at 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
More information about the Devel
mailing list