|
|
ac32bf |
From c6ed1e1af9356cdce1eaa652061dd6e4eb32d283 Mon Sep 17 00:00:00 2001
|
|
|
ac32bf |
From: Junliang Li <lijunliang.dna@gmail.com>
|
|
|
ac32bf |
Date: Thu, 13 Feb 2014 10:39:53 +0800
|
|
|
ac32bf |
Subject: [PATCH 23/32] add abrt suppport for rasdaemon
|
|
|
ac32bf |
|
|
|
ac32bf |
Adds abrt as another error mechanism for the rasdaemon.
|
|
|
ac32bf |
This patch does:
|
|
|
ac32bf |
|
|
|
ac32bf |
1) read ras event (mc,mce and aer)
|
|
|
ac32bf |
|
|
|
ac32bf |
2) setup a abrt-server unix socket
|
|
|
ac32bf |
|
|
|
ac32bf |
3) write messages follow ABRT server protocol, set event
|
|
|
ac32bf |
info into backtrace zone.
|
|
|
ac32bf |
|
|
|
ac32bf |
4) commit report.
|
|
|
ac32bf |
|
|
|
ac32bf |
For now, it depends on ABRT to limit flood reports.
|
|
|
ac32bf |
|
|
|
ac32bf |
Signed-off-by: Junliang Li <lijunliang.dna@gmail.com>
|
|
|
ac32bf |
Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
|
|
|
ac32bf |
---
|
|
|
ac32bf |
Makefile.am | 5 +-
|
|
|
ac32bf |
configure.ac | 9 +
|
|
|
ac32bf |
ras-aer-handler.c | 6 +
|
|
|
ac32bf |
ras-events.h | 3 +
|
|
|
ac32bf |
ras-mc-handler.c | 7 +
|
|
|
ac32bf |
ras-mce-handler.c | 6 +
|
|
|
ac32bf |
ras-report.c | 429 +++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
ac32bf |
ras-report.h | 39 +++++
|
|
|
ac32bf |
8 files changed, 503 insertions(+), 1 deletions(-)
|
|
|
ac32bf |
create mode 100644 ras-report.c
|
|
|
ac32bf |
create mode 100644 ras-report.h
|
|
|
ac32bf |
|
|
|
ac32bf |
diff --git a/Makefile.am b/Makefile.am
|
|
|
ac32bf |
index 473ce98..c1668b4 100644
|
|
|
ac32bf |
--- a/Makefile.am
|
|
|
ac32bf |
+++ b/Makefile.am
|
|
|
ac32bf |
@@ -17,10 +17,13 @@ if WITH_MCE
|
|
|
ac32bf |
mce-intel-dunnington.c mce-intel-tulsa.c \
|
|
|
ac32bf |
mce-intel-sb.c mce-intel-ivb.c
|
|
|
ac32bf |
endif
|
|
|
ac32bf |
+if WITH_ABRT_REPORT
|
|
|
ac32bf |
+ rasdaemon_SOURCES += ras-report.c
|
|
|
ac32bf |
+endif
|
|
|
ac32bf |
rasdaemon_LDADD = -lpthread $(SQLITE3_LIBS) libtrace/libtrace.a
|
|
|
ac32bf |
|
|
|
ac32bf |
include_HEADERS = config.h ras-events.h ras-logger.h ras-mc-handler.h \
|
|
|
ac32bf |
- ras-aer-handler.h ras-mce-handler.h ras-record.h bitfield.h
|
|
|
ac32bf |
+ ras-aer-handler.h ras-mce-handler.h ras-record.h bitfield.h ras-report.h
|
|
|
ac32bf |
|
|
|
ac32bf |
# This rule can't be called with more than one Makefile job (like make -j8)
|
|
|
ac32bf |
# I can't figure out a way to fix that
|
|
|
ac32bf |
diff --git a/configure.ac b/configure.ac
|
|
|
ac32bf |
index 4fe6ef2..0ea962e 100644
|
|
|
ac32bf |
--- a/configure.ac
|
|
|
ac32bf |
+++ b/configure.ac
|
|
|
ac32bf |
@@ -53,6 +53,15 @@ AS_IF([test "x$enable_mce" = "xyes"], [
|
|
|
ac32bf |
])
|
|
|
ac32bf |
AM_CONDITIONAL([WITH_MCE], [test x$enable_mce = xyes])
|
|
|
ac32bf |
|
|
|
ac32bf |
+AC_ARG_ENABLE([abrt_report],
|
|
|
ac32bf |
+ AS_HELP_STRING([--enable-abrt-report], [enable report event to ABRT (currently experimental)]))
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+AS_IF([test "x$enable_abrt_report" = "xyes"], [
|
|
|
ac32bf |
+ AC_DEFINE(HAVE_ABRT_REPORT,1,"have report event to ABRT")
|
|
|
ac32bf |
+ AC_SUBST([WITH_ABRT_REPORT])
|
|
|
ac32bf |
+])
|
|
|
ac32bf |
+AM_CONDITIONAL([WITH_ABRT_REPORT], [test x$enable_abrt_report = xyes])
|
|
|
ac32bf |
+
|
|
|
ac32bf |
test "$sysconfdir" = '${prefix}/etc' && sysconfdir=/etc
|
|
|
ac32bf |
|
|
|
ac32bf |
CFLAGS="$CFLAGS -Wall -Wmissing-prototypes -Wstrict-prototypes"
|
|
|
ac32bf |
diff --git a/ras-aer-handler.c b/ras-aer-handler.c
|
|
|
ac32bf |
index e5abaca..50526af 100644
|
|
|
ac32bf |
--- a/ras-aer-handler.c
|
|
|
ac32bf |
+++ b/ras-aer-handler.c
|
|
|
ac32bf |
@@ -24,6 +24,7 @@
|
|
|
ac32bf |
#include "ras-record.h"
|
|
|
ac32bf |
#include "ras-logger.h"
|
|
|
ac32bf |
#include "bitfield.h"
|
|
|
ac32bf |
+#include "ras-report.h"
|
|
|
ac32bf |
|
|
|
ac32bf |
static const char *aer_errors[32] = {
|
|
|
ac32bf |
/* Correctable errors */
|
|
|
ac32bf |
@@ -115,5 +116,10 @@ int ras_aer_event_handler(struct trace_seq *s,
|
|
|
ac32bf |
ras_store_aer_event(ras, &ev;;
|
|
|
ac32bf |
#endif
|
|
|
ac32bf |
|
|
|
ac32bf |
+#ifdef HAVE_ABRT_REPORT
|
|
|
ac32bf |
+ /* Report event to ABRT */
|
|
|
ac32bf |
+ ras_report_aer_event(ras, &ev;;
|
|
|
ac32bf |
+#endif
|
|
|
ac32bf |
+
|
|
|
ac32bf |
return 0;
|
|
|
ac32bf |
}
|
|
|
ac32bf |
diff --git a/ras-events.h b/ras-events.h
|
|
|
ac32bf |
index 554a95e..64e045a 100644
|
|
|
ac32bf |
--- a/ras-events.h
|
|
|
ac32bf |
+++ b/ras-events.h
|
|
|
ac32bf |
@@ -47,6 +47,9 @@ struct ras_events {
|
|
|
ac32bf |
|
|
|
ac32bf |
/* For the mce handler */
|
|
|
ac32bf |
struct mce_priv *mce_priv;
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ /* For ABRT socket*/
|
|
|
ac32bf |
+ int socketfd;
|
|
|
ac32bf |
};
|
|
|
ac32bf |
|
|
|
ac32bf |
struct pthread_data {
|
|
|
ac32bf |
diff --git a/ras-mc-handler.c b/ras-mc-handler.c
|
|
|
ac32bf |
index 5c24f65..ffb3805 100644
|
|
|
ac32bf |
--- a/ras-mc-handler.c
|
|
|
ac32bf |
+++ b/ras-mc-handler.c
|
|
|
ac32bf |
@@ -23,6 +23,7 @@
|
|
|
ac32bf |
#include "ras-mc-handler.h"
|
|
|
ac32bf |
#include "ras-record.h"
|
|
|
ac32bf |
#include "ras-logger.h"
|
|
|
ac32bf |
+#include "ras-report.h"
|
|
|
ac32bf |
|
|
|
ac32bf |
int ras_mc_event_handler(struct trace_seq *s,
|
|
|
ac32bf |
struct pevent_record *record,
|
|
|
ac32bf |
@@ -189,6 +190,12 @@ int ras_mc_event_handler(struct trace_seq *s,
|
|
|
ac32bf |
/* Insert data into the SGBD */
|
|
|
ac32bf |
|
|
|
ac32bf |
ras_store_mc_event(ras, &ev;;
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+#ifdef HAVE_ABRT_REPORT
|
|
|
ac32bf |
+ /* Report event to ABRT */
|
|
|
ac32bf |
+ ras_report_mc_event(ras, &ev;;
|
|
|
ac32bf |
+#endif
|
|
|
ac32bf |
+
|
|
|
ac32bf |
return 0;
|
|
|
ac32bf |
|
|
|
ac32bf |
parse_error:
|
|
|
ac32bf |
diff --git a/ras-mce-handler.c b/ras-mce-handler.c
|
|
|
ac32bf |
index 59e8d05..1431049 100644
|
|
|
ac32bf |
--- a/ras-mce-handler.c
|
|
|
ac32bf |
+++ b/ras-mce-handler.c
|
|
|
ac32bf |
@@ -26,6 +26,7 @@
|
|
|
ac32bf |
#include "ras-mce-handler.h"
|
|
|
ac32bf |
#include "ras-record.h"
|
|
|
ac32bf |
#include "ras-logger.h"
|
|
|
ac32bf |
+#include "ras-report.h"
|
|
|
ac32bf |
|
|
|
ac32bf |
/*
|
|
|
ac32bf |
* The code below were adapted from Andi Kleen/Intel/SuSe mcelog code,
|
|
|
ac32bf |
@@ -401,5 +402,10 @@ int ras_mce_event_handler(struct trace_seq *s,
|
|
|
ac32bf |
ras_store_mce_record(ras, &e);
|
|
|
ac32bf |
#endif
|
|
|
ac32bf |
|
|
|
ac32bf |
+#ifdef HAVE_ABRT_REPORT
|
|
|
ac32bf |
+ /* Report event to ABRT */
|
|
|
ac32bf |
+ ras_report_mce_event(ras, &e);
|
|
|
ac32bf |
+#endif
|
|
|
ac32bf |
+
|
|
|
ac32bf |
return 0;
|
|
|
ac32bf |
}
|
|
|
ac32bf |
diff --git a/ras-report.c b/ras-report.c
|
|
|
ac32bf |
new file mode 100644
|
|
|
ac32bf |
index 0000000..d3e4a79
|
|
|
ac32bf |
--- /dev/null
|
|
|
ac32bf |
+++ b/ras-report.c
|
|
|
ac32bf |
@@ -0,0 +1,429 @@
|
|
|
ac32bf |
+#include <stdio.h>
|
|
|
ac32bf |
+#include <string.h>
|
|
|
ac32bf |
+#include <unistd.h>
|
|
|
ac32bf |
+#include <sys/types.h>
|
|
|
ac32bf |
+#include <sys/utsname.h>
|
|
|
ac32bf |
+#include <sys/socket.h>
|
|
|
ac32bf |
+#include <sys/un.h>
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+#include "ras-report.h"
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+static int setup_report_socket(void){
|
|
|
ac32bf |
+ int sockfd = -1;
|
|
|
ac32bf |
+ int rc = -1;
|
|
|
ac32bf |
+ struct sockaddr_un addr;
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
|
|
|
ac32bf |
+ if (sockfd < 0){
|
|
|
ac32bf |
+ return -1;
|
|
|
ac32bf |
+ }
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ memset(&addr, 0, sizeof(struct sockaddr_un));
|
|
|
ac32bf |
+ addr.sun_family = AF_UNIX;
|
|
|
ac32bf |
+ strncpy(addr.sun_path, ABRT_SOCKET, strlen(ABRT_SOCKET));
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ rc = connect(sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr_un));
|
|
|
ac32bf |
+ if (rc < 0){
|
|
|
ac32bf |
+ return -1;
|
|
|
ac32bf |
+ }
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ return sockfd;
|
|
|
ac32bf |
+}
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+static int commit_report_basic(int sockfd){
|
|
|
ac32bf |
+ char buf[INPUT_BUFFER_SIZE];
|
|
|
ac32bf |
+ struct utsname un;
|
|
|
ac32bf |
+ int rc = -1;
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ if(sockfd < 0){
|
|
|
ac32bf |
+ return rc;
|
|
|
ac32bf |
+ }
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ memset(buf, 0, INPUT_BUFFER_SIZE);
|
|
|
ac32bf |
+ memset(&un, 0, sizeof(struct utsname));
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ rc = uname(&un;;
|
|
|
ac32bf |
+ if(rc < 0){
|
|
|
ac32bf |
+ return rc;
|
|
|
ac32bf |
+ }
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ /*
|
|
|
ac32bf |
+ * ABRT server protocol
|
|
|
ac32bf |
+ */
|
|
|
ac32bf |
+ sprintf(buf, "PUT / HTTP/1.1\r\n\r\n");
|
|
|
ac32bf |
+ rc = write(sockfd, buf, strlen(buf) + 1);
|
|
|
ac32bf |
+ if(rc < strlen(buf) + 1){
|
|
|
ac32bf |
+ return -1;
|
|
|
ac32bf |
+ }
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ sprintf(buf, "PID=%d", (int)getpid());
|
|
|
ac32bf |
+ rc = write(sockfd, buf, strlen(buf) + 1);
|
|
|
ac32bf |
+ if(rc < strlen(buf) + 1){
|
|
|
ac32bf |
+ return -1;
|
|
|
ac32bf |
+ }
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ sprintf(buf, "EXECUTABLE=/boot/vmlinuz-%s", un.release);
|
|
|
ac32bf |
+ rc = write(sockfd, buf, strlen(buf) + 1);
|
|
|
ac32bf |
+ if(rc < strlen(buf) + 1){
|
|
|
ac32bf |
+ return -1;
|
|
|
ac32bf |
+ }
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ sprintf(buf, "BASENAME=%s", "rasdaemon");
|
|
|
ac32bf |
+ rc = write(sockfd, buf, strlen(buf) + 1);
|
|
|
ac32bf |
+ if(rc < strlen(buf) + 1){
|
|
|
ac32bf |
+ return -1;
|
|
|
ac32bf |
+ }
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ return 0;
|
|
|
ac32bf |
+}
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+/*
|
|
|
ac32bf |
+ * add "DONE" string to finish message.
|
|
|
ac32bf |
+ */
|
|
|
ac32bf |
+static int commit_report_done(int sockfd){
|
|
|
ac32bf |
+ int rc = -1;
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ if(sockfd < 0){
|
|
|
ac32bf |
+ return -1;
|
|
|
ac32bf |
+ }
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ rc = write(sockfd, "DONE\0", strlen("DONE\0"));
|
|
|
ac32bf |
+ if(rc < strlen("DONE\0")){
|
|
|
ac32bf |
+ return -1;
|
|
|
ac32bf |
+ }
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ return 0;
|
|
|
ac32bf |
+}
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+static int set_mc_event_backtrace(char *buf, struct ras_mc_event *ev){
|
|
|
ac32bf |
+ char bt_buf[MAX_BACKTRACE_SIZE];
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ if(!buf || !ev)
|
|
|
ac32bf |
+ return -1;
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ sprintf(bt_buf, "BACKTRACE= " \
|
|
|
ac32bf |
+ "timestamp=%s\n" \
|
|
|
ac32bf |
+ "error_count=%d\n" \
|
|
|
ac32bf |
+ "error_type=%s\n" \
|
|
|
ac32bf |
+ "msg=%s\n" \
|
|
|
ac32bf |
+ "label=%s\n" \
|
|
|
ac32bf |
+ "mc_index=%c\n" \
|
|
|
ac32bf |
+ "top_layer=%c\n" \
|
|
|
ac32bf |
+ "middle_layer=%c\n" \
|
|
|
ac32bf |
+ "lower_layer=%c\n" \
|
|
|
ac32bf |
+ "address=%llu\n" \
|
|
|
ac32bf |
+ "grain=%llu\n" \
|
|
|
ac32bf |
+ "syndrome=%llu\n" \
|
|
|
ac32bf |
+ "driver_detail=%s\n", \
|
|
|
ac32bf |
+ ev->timestamp, \
|
|
|
ac32bf |
+ ev->error_count, \
|
|
|
ac32bf |
+ ev->error_type, \
|
|
|
ac32bf |
+ ev->msg, \
|
|
|
ac32bf |
+ ev->label, \
|
|
|
ac32bf |
+ ev->mc_index, \
|
|
|
ac32bf |
+ ev->top_layer, \
|
|
|
ac32bf |
+ ev->middle_layer, \
|
|
|
ac32bf |
+ ev->lower_layer, \
|
|
|
ac32bf |
+ ev->address, \
|
|
|
ac32bf |
+ ev->grain, \
|
|
|
ac32bf |
+ ev->syndrome, \
|
|
|
ac32bf |
+ ev->driver_detail);
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ strcat(buf, bt_buf);
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ return 0;
|
|
|
ac32bf |
+}
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+static int set_mce_event_backtrace(char *buf, struct mce_event *ev){
|
|
|
ac32bf |
+ char bt_buf[MAX_BACKTRACE_SIZE];
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ if(!buf || !ev)
|
|
|
ac32bf |
+ return -1;
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ sprintf(bt_buf, "BACKTRACE=" \
|
|
|
ac32bf |
+ "timestamp=%s\n" \
|
|
|
ac32bf |
+ "bank_name=%s\n" \
|
|
|
ac32bf |
+ "error_msg=%s\n" \
|
|
|
ac32bf |
+ "mcgstatus_msg=%s\n" \
|
|
|
ac32bf |
+ "mcistatus_msg=%s\n" \
|
|
|
ac32bf |
+ "mcastatus_msg=%s\n" \
|
|
|
ac32bf |
+ "user_action=%s\n" \
|
|
|
ac32bf |
+ "mc_location=%s\n" \
|
|
|
ac32bf |
+ "mcgcap=%lu\n" \
|
|
|
ac32bf |
+ "mcgstatus=%lu\n" \
|
|
|
ac32bf |
+ "status=%lu\n" \
|
|
|
ac32bf |
+ "addr=%lu\n" \
|
|
|
ac32bf |
+ "misc=%lu\n" \
|
|
|
ac32bf |
+ "ip=%lu\n" \
|
|
|
ac32bf |
+ "tsc=%lu\n" \
|
|
|
ac32bf |
+ "walltime=%lu\n" \
|
|
|
ac32bf |
+ "cpu=%u\n" \
|
|
|
ac32bf |
+ "cpuid=%u\n" \
|
|
|
ac32bf |
+ "apicid=%u\n" \
|
|
|
ac32bf |
+ "socketid=%u\n" \
|
|
|
ac32bf |
+ "cs=%d\n" \
|
|
|
ac32bf |
+ "bank=%d\n" \
|
|
|
ac32bf |
+ "cpuvendor=%d\n", \
|
|
|
ac32bf |
+ ev->timestamp, \
|
|
|
ac32bf |
+ ev->bank_name, \
|
|
|
ac32bf |
+ ev->error_msg, \
|
|
|
ac32bf |
+ ev->mcgstatus_msg, \
|
|
|
ac32bf |
+ ev->mcistatus_msg, \
|
|
|
ac32bf |
+ ev->mcastatus_msg, \
|
|
|
ac32bf |
+ ev->user_action, \
|
|
|
ac32bf |
+ ev->mc_location, \
|
|
|
ac32bf |
+ ev->mcgcap, \
|
|
|
ac32bf |
+ ev->mcgstatus, \
|
|
|
ac32bf |
+ ev->status, \
|
|
|
ac32bf |
+ ev->addr, \
|
|
|
ac32bf |
+ ev->misc, \
|
|
|
ac32bf |
+ ev->ip, \
|
|
|
ac32bf |
+ ev->tsc, \
|
|
|
ac32bf |
+ ev->walltime, \
|
|
|
ac32bf |
+ ev->cpu, \
|
|
|
ac32bf |
+ ev->cpuid, \
|
|
|
ac32bf |
+ ev->apicid, \
|
|
|
ac32bf |
+ ev->socketid, \
|
|
|
ac32bf |
+ ev->cs, \
|
|
|
ac32bf |
+ ev->bank, \
|
|
|
ac32bf |
+ ev->cpuvendor);
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ strcat(buf, bt_buf);
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ return 0;
|
|
|
ac32bf |
+}
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+static int set_aer_event_backtrace(char *buf, struct ras_aer_event *ev){
|
|
|
ac32bf |
+ char bt_buf[MAX_BACKTRACE_SIZE];
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ if(!buf || !ev)
|
|
|
ac32bf |
+ return -1;
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ sprintf(bt_buf, "BACKTRACE=" \
|
|
|
ac32bf |
+ "timestamp=%s\n" \
|
|
|
ac32bf |
+ "error_type=%s\n" \
|
|
|
ac32bf |
+ "dev_name=%s\n" \
|
|
|
ac32bf |
+ "msg=%s\n", \
|
|
|
ac32bf |
+ ev->timestamp, \
|
|
|
ac32bf |
+ ev->error_type, \
|
|
|
ac32bf |
+ ev->dev_name, \
|
|
|
ac32bf |
+ ev->msg);
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ strcat(buf, bt_buf);
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ return 0;
|
|
|
ac32bf |
+}
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+static int commit_report_backtrace(int sockfd, int type, void *ev){
|
|
|
ac32bf |
+ char buf[MAX_BACKTRACE_SIZE];
|
|
|
ac32bf |
+ char *pbuf = buf;
|
|
|
ac32bf |
+ int rc = -1;
|
|
|
ac32bf |
+ int buf_len = 0;
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ if(sockfd < 0 || !ev){
|
|
|
ac32bf |
+ return -1;
|
|
|
ac32bf |
+ }
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ memset(buf, 0, MAX_BACKTRACE_SIZE);
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ switch(type){
|
|
|
ac32bf |
+ case MC_EVENT:
|
|
|
ac32bf |
+ rc = set_mc_event_backtrace(buf, (struct ras_mc_event *)ev);
|
|
|
ac32bf |
+ break;
|
|
|
ac32bf |
+ case AER_EVENT:
|
|
|
ac32bf |
+ rc = set_aer_event_backtrace(buf, (struct ras_aer_event *)ev);
|
|
|
ac32bf |
+ break;
|
|
|
ac32bf |
+ case MCE_EVENT:
|
|
|
ac32bf |
+ rc = set_mce_event_backtrace(buf, (struct mce_event *)ev);
|
|
|
ac32bf |
+ break;
|
|
|
ac32bf |
+ default:
|
|
|
ac32bf |
+ return -1;
|
|
|
ac32bf |
+ }
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ if(rc < 0){
|
|
|
ac32bf |
+ return -1;
|
|
|
ac32bf |
+ }
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ buf_len = strlen(buf);
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ for(;buf_len > INPUT_BUFFER_SIZE - 1; buf_len -= (INPUT_BUFFER_SIZE - 1)){
|
|
|
ac32bf |
+ rc = write(sockfd, pbuf, INPUT_BUFFER_SIZE - 1);
|
|
|
ac32bf |
+ if(rc < INPUT_BUFFER_SIZE - 1){
|
|
|
ac32bf |
+ return -1;
|
|
|
ac32bf |
+ }
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ pbuf = pbuf + INPUT_BUFFER_SIZE - 1;
|
|
|
ac32bf |
+ }
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ rc = write(sockfd, pbuf, buf_len + 1);
|
|
|
ac32bf |
+ if(rc < buf_len){
|
|
|
ac32bf |
+ return -1;
|
|
|
ac32bf |
+ }
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ return 0;
|
|
|
ac32bf |
+}
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+int ras_report_mc_event(struct ras_events *ras, struct ras_mc_event *ev){
|
|
|
ac32bf |
+ char buf[MAX_MESSAGE_SIZE];
|
|
|
ac32bf |
+ int sockfd = -1;
|
|
|
ac32bf |
+ int done = 0;
|
|
|
ac32bf |
+ int rc = -1;
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ memset(buf, 0, sizeof(buf));
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ sockfd = setup_report_socket();
|
|
|
ac32bf |
+ if(sockfd < 0){
|
|
|
ac32bf |
+ return -1;
|
|
|
ac32bf |
+ }
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ rc = commit_report_basic(sockfd);
|
|
|
ac32bf |
+ if(rc < 0){
|
|
|
ac32bf |
+ goto mc_fail;
|
|
|
ac32bf |
+ }
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ rc = commit_report_backtrace(sockfd, MC_EVENT, ev);
|
|
|
ac32bf |
+ if(rc < 0){
|
|
|
ac32bf |
+ goto mc_fail;
|
|
|
ac32bf |
+ }
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ sprintf(buf, "ANALYZER=%s", "rasdaemon-mc");
|
|
|
ac32bf |
+ rc = write(sockfd, buf, strlen(buf) + 1);
|
|
|
ac32bf |
+ if(rc < strlen(buf) + 1){
|
|
|
ac32bf |
+ goto mc_fail;
|
|
|
ac32bf |
+ }
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ sprintf(buf, "REASON=%s", "EDAC driver report problem");
|
|
|
ac32bf |
+ rc = write(sockfd, buf, strlen(buf) + 1);
|
|
|
ac32bf |
+ if(rc < strlen(buf) + 1){
|
|
|
ac32bf |
+ goto mc_fail;
|
|
|
ac32bf |
+ }
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ rc = commit_report_done(sockfd);
|
|
|
ac32bf |
+ if(rc < 0){
|
|
|
ac32bf |
+ goto mc_fail;
|
|
|
ac32bf |
+ }
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ done = 1;
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+mc_fail:
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ if(sockfd > 0){
|
|
|
ac32bf |
+ close(sockfd);
|
|
|
ac32bf |
+ }
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ if(done){
|
|
|
ac32bf |
+ return 0;
|
|
|
ac32bf |
+ }else{
|
|
|
ac32bf |
+ return -1;
|
|
|
ac32bf |
+ }
|
|
|
ac32bf |
+}
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+int ras_report_aer_event(struct ras_events *ras, struct ras_aer_event *ev){
|
|
|
ac32bf |
+ char buf[MAX_MESSAGE_SIZE];
|
|
|
ac32bf |
+ int sockfd = 0;
|
|
|
ac32bf |
+ int done = 0;
|
|
|
ac32bf |
+ int rc = -1;
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ memset(buf, 0, sizeof(buf));
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ sockfd = setup_report_socket();
|
|
|
ac32bf |
+ if(sockfd < 0){
|
|
|
ac32bf |
+ return -1;
|
|
|
ac32bf |
+ }
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ rc = commit_report_basic(sockfd);
|
|
|
ac32bf |
+ if(rc < 0){
|
|
|
ac32bf |
+ goto aer_fail;
|
|
|
ac32bf |
+ }
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ rc = commit_report_backtrace(sockfd, AER_EVENT, ev);
|
|
|
ac32bf |
+ if(rc < 0){
|
|
|
ac32bf |
+ goto aer_fail;
|
|
|
ac32bf |
+ }
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ sprintf(buf, "ANALYZER=%s", "rasdaemon-aer");
|
|
|
ac32bf |
+ rc = write(sockfd, buf, strlen(buf) + 1);
|
|
|
ac32bf |
+ if(rc < strlen(buf) + 1){
|
|
|
ac32bf |
+ goto aer_fail;
|
|
|
ac32bf |
+ }
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ sprintf(buf, "REASON=%s", "PCIe AER driver report problem");
|
|
|
ac32bf |
+ rc = write(sockfd, buf, strlen(buf) + 1);
|
|
|
ac32bf |
+ if(rc < strlen(buf) + 1){
|
|
|
ac32bf |
+ goto aer_fail;
|
|
|
ac32bf |
+ }
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ rc = commit_report_done(sockfd);
|
|
|
ac32bf |
+ if(rc < 0){
|
|
|
ac32bf |
+ goto aer_fail;
|
|
|
ac32bf |
+ }
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ done = 1;
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+aer_fail:
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ if(sockfd > 0){
|
|
|
ac32bf |
+ close(sockfd);
|
|
|
ac32bf |
+ }
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ if(done){
|
|
|
ac32bf |
+ return 0;
|
|
|
ac32bf |
+ }else{
|
|
|
ac32bf |
+ return -1;
|
|
|
ac32bf |
+ }
|
|
|
ac32bf |
+}
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+int ras_report_mce_event(struct ras_events *ras, struct mce_event *ev){
|
|
|
ac32bf |
+ char buf[MAX_MESSAGE_SIZE];
|
|
|
ac32bf |
+ int sockfd = 0;
|
|
|
ac32bf |
+ int done = 0;
|
|
|
ac32bf |
+ int rc = -1;
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ memset(buf, 0, sizeof(buf));
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ sockfd = setup_report_socket();
|
|
|
ac32bf |
+ if(sockfd < 0){
|
|
|
ac32bf |
+ return -1;
|
|
|
ac32bf |
+ }
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ rc = commit_report_basic(sockfd);
|
|
|
ac32bf |
+ if(rc < 0){
|
|
|
ac32bf |
+ goto mce_fail;
|
|
|
ac32bf |
+ }
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ rc = commit_report_backtrace(sockfd, MCE_EVENT, ev);
|
|
|
ac32bf |
+ if(rc < 0){
|
|
|
ac32bf |
+ goto mce_fail;
|
|
|
ac32bf |
+ }
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ sprintf(buf, "ANALYZER=%s", "rasdaemon-mce");
|
|
|
ac32bf |
+ rc = write(sockfd, buf, strlen(buf) + 1);
|
|
|
ac32bf |
+ if(rc < strlen(buf) + 1){
|
|
|
ac32bf |
+ goto mce_fail;
|
|
|
ac32bf |
+ }
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ sprintf(buf, "REASON=%s", "Machine Check driver report problem");
|
|
|
ac32bf |
+ rc = write(sockfd, buf, strlen(buf) + 1);
|
|
|
ac32bf |
+ if(rc < strlen(buf) + 1){
|
|
|
ac32bf |
+ goto mce_fail;
|
|
|
ac32bf |
+ }
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ rc = commit_report_done(sockfd);
|
|
|
ac32bf |
+ if(rc < 0){
|
|
|
ac32bf |
+ goto mce_fail;
|
|
|
ac32bf |
+ }
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ done = 1;
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+mce_fail:
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ if(sockfd > 0){
|
|
|
ac32bf |
+ close(sockfd);
|
|
|
ac32bf |
+ }
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+ if(done){
|
|
|
ac32bf |
+ return 0;
|
|
|
ac32bf |
+ }else{
|
|
|
ac32bf |
+ return -1;
|
|
|
ac32bf |
+ }
|
|
|
ac32bf |
+}
|
|
|
ac32bf |
diff --git a/ras-report.h b/ras-report.h
|
|
|
ac32bf |
new file mode 100644
|
|
|
ac32bf |
index 0000000..7920cdf
|
|
|
ac32bf |
--- /dev/null
|
|
|
ac32bf |
+++ b/ras-report.h
|
|
|
ac32bf |
@@ -0,0 +1,39 @@
|
|
|
ac32bf |
+#ifndef __RAS_REPORT_H
|
|
|
ac32bf |
+#define __RAS_REPORT_H
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+#include "ras-record.h"
|
|
|
ac32bf |
+#include "ras-events.h"
|
|
|
ac32bf |
+#include "ras-mc-handler.h"
|
|
|
ac32bf |
+#include "ras-mce-handler.h"
|
|
|
ac32bf |
+#include "ras-aer-handler.h"
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+/* Maximal length of backtrace. */
|
|
|
ac32bf |
+#define MAX_BACKTRACE_SIZE (1024*1024)
|
|
|
ac32bf |
+/* Amount of data received from one client for a message before reporting error. */
|
|
|
ac32bf |
+#define MAX_MESSAGE_SIZE (4*MAX_BACKTRACE_SIZE)
|
|
|
ac32bf |
+/* Maximal number of characters read from socket at once. */
|
|
|
ac32bf |
+#define INPUT_BUFFER_SIZE (8*1024)
|
|
|
ac32bf |
+/* ABRT socket file */
|
|
|
ac32bf |
+#define ABRT_SOCKET "/var/run/abrt/abrt.socket"
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+enum {
|
|
|
ac32bf |
+ MC_EVENT,
|
|
|
ac32bf |
+ MCE_EVENT,
|
|
|
ac32bf |
+ AER_EVENT
|
|
|
ac32bf |
+};
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+#ifdef HAVE_ABRT_REPORT
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+int ras_report_mc_event(struct ras_events *ras, struct ras_mc_event *ev);
|
|
|
ac32bf |
+int ras_report_aer_event(struct ras_events *ras, struct ras_aer_event *ev);
|
|
|
ac32bf |
+int ras_report_mce_event(struct ras_events *ras, struct mce_event *ev);
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+#else
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+static inline int ras_report_mc_event(struct ras_events *ras, struct ras_mc_event *ev) { return 0; };
|
|
|
ac32bf |
+static inline int ras_report_aer_event(struct ras_events *ras, struct ras_aer_event *ev) { return 0; };
|
|
|
ac32bf |
+static inline int ras_report_mce_event(struct ras_events *ras, struct mce_event *ev) { return 0; };
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+#endif
|
|
|
ac32bf |
+
|
|
|
ac32bf |
+#endif
|
|
|
ac32bf |
--
|
|
|
ac32bf |
1.7.1
|
|
|
ac32bf |
|