If watchdog was triggered, that means that userspace is unreliable
and we can't expect kernel messages are logged by userspace logger,
thus we need ourselfs write info about watchdog triggered to special
file configured through sysfs /sys/kernel/watchdog_log_path, so that
users can see that watchdog was triggered but not some other event.

https://jira.sw.ru/browse/PSBM-54747
Signed-off-by: Pavel Tikhomirov <ptikhomi...@virtuozzo.com>
---
 kernel/fence-watchdog.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 73 insertions(+)

diff --git a/kernel/fence-watchdog.c b/kernel/fence-watchdog.c
index f5c2347f..607045a 100644
--- a/kernel/fence-watchdog.c
+++ b/kernel/fence-watchdog.c
@@ -23,6 +23,8 @@
 #include <linux/fence-watchdog.h>
 #include <linux/device.h>
 #include <linux/kmsg_dump.h>
+#include <linux/fs.h>
+#include <linux/string.h>
 
 #define MAX_U64                        (~(u64)0)
 #define MAX_JIFFIES_DELTA      (10 * 365UL * 24UL * 3600UL * HZ)
@@ -41,11 +43,63 @@ const char *action_names[] = {"crash", "reboot", "halt", 
"netfilter", 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 char fence_wdog_log_path[PATH_MAX] = "/fence_wdog.log";
+
+#define MSG_LEN 32
+
+void fence_wdog_log(void)
+{
+       char msg[MSG_LEN] = "fence-watchdog: ";
+       struct file *file;
+       int ret;
+
+       ret = sprintf(msg+strlen(msg), "%s\n", action_names[fence_wdog_action]);
+       if (ret != strlen(action_names[fence_wdog_action]) + 1) {
+               printk(KERN_EMERG"fence-watchdog: Failed to sprintf msg\n");
+               return;
+       }
+
+       file = filp_open(fence_wdog_log_path,
+                        O_CREAT | O_WRONLY | O_APPEND | O_NOFOLLOW | 
O_LARGEFILE,
+                        0600);
+       if (IS_ERR(file)) {
+               printk(KERN_EMERG"fence-watchdog: Failed to open log path\n");
+               return;
+       }
+
+       if (!S_ISREG(file_inode(file)->i_mode)) {
+               printk(KERN_EMERG"fence-watchdog: Wrong type of log file\n");
+               goto close;
+       }
+
+       if (!file->f_op->write) {
+               printk(KERN_EMERG"fence-watchdog: No write op for log file\n");
+               goto close;
+       }
+
+       ret = file->f_op->write(file, msg, strlen(msg), &file->f_pos);
+       if (ret != strlen(msg))
+               printk(KERN_EMERG"fence-watchdog: Failed to write msg, 
ret=%d\n", ret);
+
+       ret = vfs_fsync(file, 0);
+       if (ret < 0)
+               printk(KERN_EMERG"fence-watchdog: Failed to fsync log file 
ret=%d\n", ret);
+
+close:
+       ret = filp_close(file, NULL);
+       if (ret < 0)
+               printk(KERN_EMERG"fence-watchdog: Failed to close log file 
ret=%d\n", ret);
+
+       return;
+}
 
 static void do_halt_or_reboot(struct work_struct *dummy)
 {
        printk(KERN_EMERG"fence-watchdog: %s\n",
               action_names[fence_wdog_action]);
+
+       fence_wdog_log();
+
        switch (fence_wdog_action) {
        case FENCE_WDOG_REBOOT:
                emergency_restart();
@@ -166,6 +220,20 @@ static ssize_t fence_wdog_available_actions_show(struct 
kobject *kobj,
        return ret;
 }
 
+static ssize_t fence_wdog_log_path_show(struct kobject *kobj,
+               struct kobj_attribute *attr, char *buf)
+{
+       return sprintf(buf, "%s\n", fence_wdog_log_path);
+}
+
+static ssize_t fence_wdog_log_path_store(struct kobject *kobj,
+               struct kobj_attribute *attr, const char *buf, size_t count)
+{
+       if (sscanf(buf, "%s", fence_wdog_log_path) != 1)
+               return -EINVAL;
+       return 0;
+}
+
 static struct kobj_attribute fence_wdog_timer_attr =
        __ATTR(watchdog_timer, 0644,
                fence_wdog_timer_show, fence_wdog_timer_store);
@@ -178,10 +246,15 @@ static struct kobj_attribute 
fence_wdog_available_actions_attr =
        __ATTR(watchdog_available_actions, 0644,
                fence_wdog_available_actions_show, NULL);
 
+static struct kobj_attribute fence_wdog_log_path_attr =
+       __ATTR(watchdog_log_path, 0644,
+               fence_wdog_log_path_show, fence_wdog_log_path_store);
+
 static struct attribute *fence_wdog_attrs[] = {
        &fence_wdog_timer_attr.attr,
        &fence_wdog_action_attr.attr,
        &fence_wdog_available_actions_attr.attr,
+       &fence_wdog_log_path_attr.attr,
        NULL,
 };
 
-- 
2.9.4

_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to