]> www.infradead.org Git - users/mchehab/rasdaemon.git/commitdiff
move ras events generic code into a separate file
authorMauro Carvalho Chehab <mchehab@redhat.com>
Fri, 3 May 2013 13:14:55 +0000 (10:14 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Fri, 3 May 2013 17:52:30 +0000 (14:52 -0300)
As we'll add other event types, move the ras events generic
code into a separate dir.

While here, get hid of the DEBUGFS define, replacing it by
a code that will discover where the debugfs got mounted on
the system.

Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Makefile.am
ras-events.c [moved from ras-mc-event.c with 61% similarity]
ras-events.h [moved from ras-mc-event.h with 75% similarity]
ras-mc-handler.c [new file with mode: 0644]
ras-mc-handler.h [new file with mode: 0644]
ras-record.c

index a20dd487d3ce333bc0cb24b2e591e0d5633325ed..eea60e937e8b17c047bb365876828420a6c0b248 100644 (file)
@@ -3,5 +3,5 @@ SUBDIRS = libtrace
 EXTRA_DIST = misc/rasdaemon.service
 
 sbin_PROGRAMS = rasdaemon
-rasdaemon_SOURCES = rasdaemon.c ras-record.c ras-mc-event.c
+rasdaemon_SOURCES = rasdaemon.c ras-record.c ras-events.c ras-mc-handler.c
 rasdaemon_LDADD = -lpthread -lsqlite3 libtrace/libtrace.a
similarity index 61%
rename from ras-mc-event.c
rename to ras-events.c
index 8e28d25d99e5bd1d2ea7a7cc957bf847c4b7b1df..ba34c4f264d9c9bb86578262b802ea1a779c7741 100644 (file)
@@ -27,7 +27,7 @@
 #include <sys/poll.h>
 #include "libtrace/kbuffer.h"
 #include "libtrace/event-parse.h"
-#include "ras-mc-event.h"
+#include "ras-mc-handler.h"
 #include "ras-record.h"
 #include "ras-logger.h"
 
        #define ENDIAN KBUFFER_ENDIAN_BIG
 #endif
 
-#define DEBUGFS "/sys/kernel/debug/"
-
 #define ENABLE_RAS_MC_EVENT  "ras:mc_event"
 #define DISABLE_RAS_MC_EVENT "!" ENABLE_RAS_MC_EVENT
 
+int get_debugfs_dir(char *tracing_dir, size_t len)
+{
+       FILE *fp;
+       char line[MAX_PATH + 1 + 256];
+       char *type, *dir;
+       int rc;
+
+       fp = fopen("/proc/mounts","r");
+       if (!fp) {
+               log(ALL, LOG_INFO, "Can't open /proc/mounts");
+               return errno;
+       }
+
+       do {
+               if (!fgets(line, sizeof(line), fp))
+                       break;
+
+               type = strtok(line, " \t");
+               if (!type)
+                       break;
+
+               dir = strtok(NULL, " \t");
+               if (!dir)
+                       break;
+
+               if (!strcmp(type, "debugfs")) {
+                       fclose(fp);
+                       strncpy(tracing_dir, dir, len - 1);
+                       tracing_dir[len - 1] = '\0';
+                       return 0;
+               }
+       } while(1);
+
+       fclose(fp);
+       log(ALL, LOG_INFO, "Can't find debugfs\n");
+       return ENOENT;
+}
+
+static int open_trace(struct ras_events *ras, char *name, int flags)
+{
+       char fname[MAX_PATH + 1];
+
+       strcpy(fname, ras->debugfs);
+       strcat(fname, "/");
+       strcat(fname, name);
+
+       return open(fname, flags);
+}
+
 /*
  * Tracing enable/disable code
  */
-int toggle_ras_mc_event(int enable)
+int toggle_ras_mc_event(struct ras_events *ras, int enable)
 {
        int fd, rc;
 
        /* Enable RAS events */
-       fd = open(DEBUGFS "tracing/set_event", O_RDWR | O_APPEND);
+       fd = open_trace(ras, "tracing/set_event", O_RDWR | O_APPEND);
        if (fd < 0) {
                log(ALL, LOG_WARNING, "Can't open set_event")
                return errno;
@@ -92,15 +139,7 @@ int toggle_ras_mc_event(int enable)
  * Tracing read code
  */
 
-/* Should match the code at Kernel's include/linux/edac.c */
-enum hw_event_mc_err_type {
-       HW_EVENT_ERR_CORRECTED,
-       HW_EVENT_ERR_UNCORRECTED,
-       HW_EVENT_ERR_FATAL,
-       HW_EVENT_ERR_INFO,
-};
-
-static char *mc_event_error_type(unsigned long long err_type)
+char *mc_event_error_type(unsigned long long err_type)
 {
        switch (err_type) {
        case HW_EVENT_ERR_CORRECTED:
@@ -115,11 +154,12 @@ static char *mc_event_error_type(unsigned long long err_type)
        }
 }
 
-static int get_pagesize(struct pevent *pevent) {
+static int get_pagesize(struct ras_events *ras, struct pevent *pevent)
+{
        int fd, len, page_size = 4096;
        char buf[page_size];
 
-       fd = open(DEBUGFS "tracing/events/header_page", O_RDONLY);
+       fd = open_trace(ras, "tracing/events/header_page", O_RDONLY);
        if (fd < 0)
                return page_size;
 
@@ -137,137 +177,6 @@ error:
 
 }
 
-static int ras_mc_event_handler(struct trace_seq *s,
-                               struct pevent_record *record,
-                               struct event_format *event, void *context)
-{
-       int len;
-       unsigned long long val;
-       struct ras_events *ras = context;
-       struct timeval tv;
-       struct tm *tm;
-       struct ras_mc_event ev;
-       char fmt[64];
-
-       tv.tv_sec = record->ts / 1000000L;
-       tv.tv_usec = record->ts % 1000000L;
-
-       /* FIXME:
-        * Trace timestamps don't have any start reference that can be used.
-        * This is a known issue on it, and it doesn't have any solution
-        * so far, except for a hack: produce a fake event and associate its
-        * timestamp with the one obtained via gettimeofday() a few times, and
-        * use the mean time drift to adjust the offset between machine's
-        * localtime and the tracing timestamp.
-        */
-       tm = localtime(&tv.tv_sec);
-       if(tm) {
-               strftime(fmt, sizeof(fmt), "%Y-%m-%d %H:%M:%S.%%06u %z", tm);
-               snprintf(ev.timestamp, sizeof(ev.timestamp), fmt, tv.tv_usec);
-       }
-       trace_seq_printf(s, "%s(%lld = %ld.%ld) ",
-                        ev.timestamp, record->ts,
-                        (long)tv.tv_sec, (long)tv.tv_usec);
-
-       if (pevent_get_field_val(s,  event, "error_count", record, &val, 1) < 0)
-               return -1;
-       ev.error_count = val;
-       trace_seq_printf(s, "%d ", ev.error_count);
-
-       if (pevent_get_field_val(s, event, "error_type", record, &val, 1) < 0)
-               return -1;
-       ev.error_type = mc_event_error_type(val);
-       trace_seq_puts(s, ev.error_type);
-       if (ev.error_count > 1)
-               trace_seq_puts(s, " errors:");
-       else
-               trace_seq_puts(s, " error:");
-
-       ev.msg = pevent_get_field_raw(s, event, "msg", record, &len, 1);
-       if (!ev.msg)
-               return -1;
-       if (*ev.msg) {
-               trace_seq_puts(s, " ");
-               trace_seq_puts(s, ev.msg);
-       }
-
-       ev.label = pevent_get_field_raw(s, event, "label", record, &len, 1);
-       if (!ev.label)
-               return -1;
-       if (*ev.label) {
-               trace_seq_puts(s, " on ");
-               trace_seq_puts(s, ev.label);
-       }
-
-       trace_seq_puts(s, " (");
-       if (pevent_get_field_val(s,  event, "mc_index", record, &val, 1) < 0)
-               return -1;
-       ev.mc_index = val;
-       trace_seq_printf(s, "mc: %d", ev.mc_index);
-
-       if (pevent_get_field_val(s,  event, "top_layer", record, &val, 1) < 0)
-               return -1;
-       ev.top_layer = (int) val;
-       if (pevent_get_field_val(s,  event, "middle_layer", record, &val, 1) < 0)
-               return -1;
-       ev.middle_layer = (int) val;
-       if (pevent_get_field_val(s,  event, "lower_layer", record, &val, 1) < 0)
-               return -1;
-       ev.lower_layer = (int) val;
-
-       if (ev.top_layer == 255)
-               ev.top_layer = -1;
-       if (ev.middle_layer == 255)
-               ev.middle_layer = -1;
-       if (ev.lower_layer == 255)
-               ev.lower_layer = -1;
-
-       if (ev.top_layer >= 0 || ev.middle_layer >= 0 || ev.lower_layer >= 0) {
-               if (ev.lower_layer >= 0)
-                       trace_seq_printf(s, " location: %d:%d:%d",
-                                       ev.top_layer, ev.middle_layer, ev.lower_layer);
-               else if (ev.middle_layer >= 0)
-                       trace_seq_printf(s, " location: %d:%d",
-                                        ev.top_layer, ev.middle_layer);
-               else
-                       trace_seq_printf(s, " location: %d", ev.top_layer);
-       }
-
-       if (pevent_get_field_val(s,  event, "address", record, &val, 1) < 0)
-               return -1;
-       ev.address = val;
-       if (ev.address)
-               trace_seq_printf(s, " address: 0x%08llx", ev.address);
-
-       if (pevent_get_field_val(s,  event, "grain_bits", record, &val, 1) < 0)
-               return -1;
-       ev.grain = val;
-       trace_seq_printf(s, " grain: %lld", ev.grain);
-
-
-       if (pevent_get_field_val(s,  event, "syndrome", record, &val, 1) < 0)
-               return -1;
-       ev.syndrome = val;
-       if (val)
-               trace_seq_printf(s, " syndrome: 0x%08llx", ev.syndrome);
-
-       ev.driver_detail = pevent_get_field_raw(s, event, "driver_detail", record,
-                                            &len, 1);
-       if (!ev.driver_detail)
-               return -1;
-       if (*ev.driver_detail) {
-               trace_seq_puts(s, " ");
-               trace_seq_puts(s, ev.driver_detail);
-       }
-       trace_seq_puts(s, ")");
-
-       /* Insert data into the SGBD */
-
-       ras_store_mc_event(ras, &ev);
-
-       return 0;
-}
-
 static void parse_ras_data(struct pthread_data *pdata, struct kbuffer *kbuf,
                           void *data, unsigned long long time_stamp)
 {
@@ -339,14 +248,18 @@ static int read_ras_event(int fd,
        } while (1);
 }
 
-static int get_num_cpus(void)
+static int get_num_cpus(struct ras_events *ras)
 {
+       char fname[MAX_PATH + 1];
        int num_cpus = 0;
 
        DIR             *dir;
        struct dirent   *entry;
 
-       dir = opendir(DEBUGFS "tracing/per_cpu/");
+       strcpy(fname, ras->debugfs);
+       strcat(fname, "/");
+       strcat(fname, "tracing/per_cpu/");
+       dir = opendir(fname);
        if (!dir)
                return -1;
 
@@ -382,10 +295,10 @@ static void *handle_ras_events_cpu(void *priv)
 
        /* FIXME: use select to open for all CPUs */
        snprintf(pipe_raw, sizeof(pipe_raw),
-                DEBUGFS "tracing/per_cpu/cpu%d/trace_pipe_raw",
+                "tracing/per_cpu/cpu%d/trace_pipe_raw",
                 pdata->cpu);
 
-       fd = open(pipe_raw, O_RDONLY);
+       fd = open_trace(pdata->ras, pipe_raw, O_RDONLY);
        if (fd < 0) {
                log(TERM, LOG_ERR, "Can't open trace_pipe_raw")
                kbuffer_free(kbuf);
@@ -412,16 +325,23 @@ int handle_ras_events(int record_events)
        struct ras_events *ras;
        void *page;
 
+       ras = calloc(sizeof(*data), 1);
+       if (!ras)
+               return errno;
+
+       get_debugfs_dir(ras->debugfs, sizeof(ras->debugfs));
+
        /* Enable RAS events */
-       rc = toggle_ras_mc_event(1);
+       rc = toggle_ras_mc_event(ras, 1);
 
        pevent = pevent_alloc();
        if (!pevent) {
                log(TERM, LOG_ERR, "Can't allocate pevent")
-               return errno;
+               rc = errno;
+               goto free_ras;
        }
 
-       fd = open(DEBUGFS "tracing/events/ras/mc_event/format",
+       fd = open_trace(ras, "tracing/events/ras/mc_event/format",
                  O_RDONLY);
        if (fd < 0) {
                log(TERM, LOG_ERR, "Open ras format")
@@ -429,7 +349,7 @@ int handle_ras_events(int record_events)
                goto free_pevent;
        }
 
-       page_size = get_pagesize(pevent);
+       page_size = get_pagesize(ras, pevent);
 
        page = malloc(page_size);
        if (!page) {
@@ -447,9 +367,6 @@ int handle_ras_events(int record_events)
                goto free_pevent;
        }
 
-       ras = calloc(sizeof(*data), 1);
-       if (!ras)
-               goto free_pevent;
        ras->pevent = pevent;
        ras->page_size = page_size;
 
@@ -464,7 +381,7 @@ int handle_ras_events(int record_events)
        if (rc)
                goto free_ras;
 
-       cpus = get_num_cpus();
+       cpus = get_num_cpus(ras);
        data = calloc(sizeof(*data), cpus);
        if (!data)
                goto free_ras;
@@ -490,10 +407,10 @@ int handle_ras_events(int record_events)
 
 free_threads:
        free(data);
-free_ras:
-       free(ras);
 
 free_pevent:
        pevent_free(pevent);
+free_ras:
+       free(ras);
        return rc;
 }
similarity index 75%
rename from ras-mc-event.h
rename to ras-events.h
index 5a048a7115b301571e72a4e342cb848af9f50f66..72fa422f8c931b29039c4845b7f0d42c4c1ab7dc 100644 (file)
 
 #include <pthread.h>
 
-#ifndef __RAS_MC_EVENT_H
-#define __RAS_MC_EVENT_H
+#ifndef __RAS_EVENTS_H
+#define __RAS_EVENTS_H
+
+#define MAX_PATH 1024
+#define STR(x) #x
+
 struct ras_events {
+       char debugfs[MAX_PATH + 1];
        struct pevent   *pevent;
        int             page_size;
 
@@ -39,6 +44,15 @@ struct pthread_data {
 };
 
 int handle_ras_events(int record_events);
-int toggle_ras_mc_event(int enable);
 
-#endif
\ No newline at end of file
+/* Should match the code at Kernel's include/linux/edac.c */
+enum hw_event_mc_err_type {
+       HW_EVENT_ERR_CORRECTED,
+       HW_EVENT_ERR_UNCORRECTED,
+       HW_EVENT_ERR_FATAL,
+       HW_EVENT_ERR_INFO,
+};
+
+char *mc_event_error_type(unsigned long long err_type);
+
+#endif
diff --git a/ras-mc-handler.c b/ras-mc-handler.c
new file mode 100644 (file)
index 0000000..4353ba5
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2013 Mauro Carvalho Chehab <mchehab@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/poll.h>
+#include "libtrace/kbuffer.h"
+#include "ras-mc-handler.h"
+#include "ras-record.h"
+#include "ras-logger.h"
+
+int ras_mc_event_handler(struct trace_seq *s,
+                        struct pevent_record *record,
+                        struct event_format *event, void *context)
+{
+       int len;
+       unsigned long long val;
+       struct ras_events *ras = context;
+       struct timeval tv;
+       struct tm *tm;
+       struct ras_mc_event ev;
+       char fmt[64];
+
+       tv.tv_sec = record->ts / 1000000L;
+       tv.tv_usec = record->ts % 1000000L;
+
+       /* FIXME:
+        * Trace timestamps don't have any start reference that can be used.
+        * This is a known issue on it, and it doesn't have any solution
+        * so far, except for a hack: produce a fake event and associate its
+        * timestamp with the one obtained via gettimeofday() a few times, and
+        * use the mean time drift to adjust the offset between machine's
+        * localtime and the tracing timestamp.
+        */
+       tm = localtime(&tv.tv_sec);
+       if(tm) {
+               strftime(fmt, sizeof(fmt), "%Y-%m-%d %H:%M:%S.%%06u %z", tm);
+               snprintf(ev.timestamp, sizeof(ev.timestamp), fmt, tv.tv_usec);
+       }
+       trace_seq_printf(s, "%s(%lld = %ld.%ld) ",
+                        ev.timestamp, record->ts,
+                        (long)tv.tv_sec, (long)tv.tv_usec);
+
+       if (pevent_get_field_val(s,  event, "error_count", record, &val, 1) < 0)
+               return -1;
+       ev.error_count = val;
+       trace_seq_printf(s, "%d ", ev.error_count);
+
+       if (pevent_get_field_val(s, event, "error_type", record, &val, 1) < 0)
+               return -1;
+       ev.error_type = mc_event_error_type(val);
+       trace_seq_puts(s, ev.error_type);
+       if (ev.error_count > 1)
+               trace_seq_puts(s, " errors:");
+       else
+               trace_seq_puts(s, " error:");
+
+       ev.msg = pevent_get_field_raw(s, event, "msg", record, &len, 1);
+       if (!ev.msg)
+               return -1;
+       if (*ev.msg) {
+               trace_seq_puts(s, " ");
+               trace_seq_puts(s, ev.msg);
+       }
+
+       ev.label = pevent_get_field_raw(s, event, "label", record, &len, 1);
+       if (!ev.label)
+               return -1;
+       if (*ev.label) {
+               trace_seq_puts(s, " on ");
+               trace_seq_puts(s, ev.label);
+       }
+
+       trace_seq_puts(s, " (");
+       if (pevent_get_field_val(s,  event, "mc_index", record, &val, 1) < 0)
+               return -1;
+       ev.mc_index = val;
+       trace_seq_printf(s, "mc: %d", ev.mc_index);
+
+       if (pevent_get_field_val(s,  event, "top_layer", record, &val, 1) < 0)
+               return -1;
+       ev.top_layer = (int) val;
+       if (pevent_get_field_val(s,  event, "middle_layer", record, &val, 1) < 0)
+               return -1;
+       ev.middle_layer = (int) val;
+       if (pevent_get_field_val(s,  event, "lower_layer", record, &val, 1) < 0)
+               return -1;
+       ev.lower_layer = (int) val;
+
+       if (ev.top_layer == 255)
+               ev.top_layer = -1;
+       if (ev.middle_layer == 255)
+               ev.middle_layer = -1;
+       if (ev.lower_layer == 255)
+               ev.lower_layer = -1;
+
+       if (ev.top_layer >= 0 || ev.middle_layer >= 0 || ev.lower_layer >= 0) {
+               if (ev.lower_layer >= 0)
+                       trace_seq_printf(s, " location: %d:%d:%d",
+                                       ev.top_layer, ev.middle_layer, ev.lower_layer);
+               else if (ev.middle_layer >= 0)
+                       trace_seq_printf(s, " location: %d:%d",
+                                        ev.top_layer, ev.middle_layer);
+               else
+                       trace_seq_printf(s, " location: %d", ev.top_layer);
+       }
+
+       if (pevent_get_field_val(s,  event, "address", record, &val, 1) < 0)
+               return -1;
+       ev.address = val;
+       if (ev.address)
+               trace_seq_printf(s, " address: 0x%08llx", ev.address);
+
+       if (pevent_get_field_val(s,  event, "grain_bits", record, &val, 1) < 0)
+               return -1;
+       ev.grain = val;
+       trace_seq_printf(s, " grain: %lld", ev.grain);
+
+
+       if (pevent_get_field_val(s,  event, "syndrome", record, &val, 1) < 0)
+               return -1;
+       ev.syndrome = val;
+       if (val)
+               trace_seq_printf(s, " syndrome: 0x%08llx", ev.syndrome);
+
+       ev.driver_detail = pevent_get_field_raw(s, event, "driver_detail", record,
+                                            &len, 1);
+       if (!ev.driver_detail)
+               return -1;
+       if (*ev.driver_detail) {
+               trace_seq_puts(s, " ");
+               trace_seq_puts(s, ev.driver_detail);
+       }
+       trace_seq_puts(s, ")");
+
+       /* Insert data into the SGBD */
+
+       ras_store_mc_event(ras, &ev);
+
+       return 0;
+}
diff --git a/ras-mc-handler.h b/ras-mc-handler.h
new file mode 100644 (file)
index 0000000..eaa1f95
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2013 Mauro Carvalho Chehab <mchehab@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef __RAS_MC_HANDLER_H
+#define __RAS_MC_HANDLER_H
+
+#include "ras-events.h"
+#include "libtrace/event-parse.h"
+
+int ras_mc_event_handler(struct trace_seq *s,
+                        struct pevent_record *record,
+                        struct event_format *event, void *context);
+
+#endif
index ea732ceb25595c6bc479b7f7251f8c844da7c0df..559fce582420da481977ec8a08018d4ef19dcfa0 100644 (file)
  * BuildRequires: sqlite-devel
  */
 
-#include "ras-mc-event.h"
-#include "ras-logger.h"
 #include <string.h>
 #include <stdio.h>
+#include "ras-events.h"
+#include "ras-mc-handler.h"
+#include "ras-logger.h"
 
 #define SQLITE_RAS_DB  "ras-mc_event.db"