ACLOCAL_AMFLAGS=-I m4
SUBDIRS = libtrace
+EXTRA_DIST = misc/rasdaemon.service
-bin_PROGRAMS = rasdaemon
+sbin_PROGRAMS = rasdaemon
rasdaemon_SOURCES = rasdaemon.c ras-record.c ras-mc-event.c
rasdaemon_LDADD = -lpthread -lsqlite3 libtrace/libtrace.a
--- /dev/null
+[Unit]
+Description=RAS daemon to log the RAS events
+After=syslog.target
+
+[Service]
+ExecStart=/usr/local/sbin/rasdaemon -f
+Restart=on-abort
+
+[Install]
+WantedBy=multi-user.target
--- /dev/null
+/*
+ * Copyright (C) 2013 Petr Holasek <pholasek@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_LOGGER_H
+
+#include <syslog.h>
+
+/*
+ * Logging macros
+ */
+
+#ifndef TOOL_NAME
+ #define TOOL_NAME "rasdaemon"
+#endif
+
+#define SYSLOG (1 << 0)
+#define TERM (1 << 1)
+#define ALL (SYSLOG | TERM)
+/* TODO: global logging limit mask */
+
+#define log(where, level, fmt, args...) \
+{\
+ if (where & SYSLOG)\
+ syslog(level, fmt, ##args);\
+ if (where & TERM) {\
+ fprintf(stderr, "%s: ", TOOL_NAME);\
+ fprintf(stderr, fmt, ##args);\
+ fflush(stderr);\
+ }\
+}
+
+#define __RAS_LOGGER_H
+#endif
#include "libtrace/event-parse.h"
#include "ras-mc-event.h"
#include "ras-record.h"
+#include "ras-logger.h"
/*
* Polling time, if read() doesn't block. Currently, trace_pipe_raw never
/* Enable RAS events */
fd = open(DEBUGFS "tracing/set_event", O_RDWR | O_APPEND);
if (fd < 0) {
- perror("Open set_event");
+ log(ALL, LOG_WARNING, "Can't open set_event")
return errno;
}
if (enable)
rc = write(fd, DISABLE_RAS_MC_EVENT,
sizeof(DISABLE_RAS_MC_EVENT));
if (rc < 0) {
- perror("can't write to set_event");
+ log(ALL, LOG_WARNING, "Can't write to set_event")
close(fd);
return rc;
}
close(fd);
if (!rc) {
- fprintf(stderr, "nothing was written on set_event\n");
+ log(ALL, LOG_WARNING, "Nothing was written on set_event\n")
return EIO;
}
if (enable)
- printf("RAS events enabled\n");
+ log(ALL, LOG_INFO, "RAS events enabled\n")
else
- printf("RAS events disabled\n");
+ log(ALL, LOG_INFO, "RAS events disabled\n")
return 0;
}
record.missed_events = kbuffer_missed_events(kbuf);
record.record_size = kbuffer_curr_size(kbuf);
+ /* TODO - logging */
trace_seq_init(&s);
printf("cpu %02d:", pdata->cpu);
fflush(stdout);
do {
ready = poll(&fds, 1, -1);
if (ready < 0) {
- perror("poll");
+ log(TERM, LOG_WARNING, "poll")
}
size = read(fd, page, pdata->ras->page_size);
if (size < 0) {
- perror ("read");
+ log(TERM, LOG_WARNING, "read")
return -1;
} else if (size > 0) {
kbuffer_load_subbuffer(kbuf, page);
* need to sleep for a while
*/
if (!warn_sleep) {
- printf("Old kernel: need to sleep\n");
+ log(ALL, LOG_INFO, "Old kernel: need to sleep\n")
warn_sleep = 1;
}
sleep(POLLING_TIME);
page = malloc(pdata->ras->page_size);
if (!page) {
- perror("Can't allocate page");
+ log(TERM, LOG_ERR, "Can't allocate page")
return NULL;
}
kbuf = kbuffer_alloc(KBUFFER_LSIZE_8, ENDIAN);
if (!kbuf) {
- perror("Can't allocate kbuf");
+ log(TERM, LOG_ERR, "Can't allocate kbuf")
free(page);
return NULL;
}
fd = open(pipe_raw, O_RDONLY);
if (fd < 0) {
- perror("Can't open trace_pipe_raw");
+ log(TERM, LOG_ERR, "Can't open trace_pipe_raw")
kbuffer_free(kbuf);
free(page);
return NULL;
pevent = pevent_alloc();
if (!pevent) {
- perror("Can't allocate pevent");
+ log(TERM, LOG_ERR, "Can't allocate pevent")
return errno;
}
fd = open(DEBUGFS "tracing/events/ras/mc_event/format",
O_RDONLY);
if (fd < 0) {
- perror("Open ras format");
+ log(TERM, LOG_ERR, "Open ras format")
rc = errno;
goto free_pevent;
}
page = malloc(page_size);
if (!page) {
- perror("Can't allocate page to read event format");
+ log(TERM, LOG_ERR, "Can't allocate page to read event format")
rc = errno;
close(fd);
goto free_pevent;
if (!data)
goto free_ras;
- printf("Opening one thread per cpu (%d threads)\n", cpus);
+ log(SYSLOG, LOG_INFO, "Opening one thread per cpu (%d threads)\n", cpus)
for (i = 0; i < cpus; i++) {
data[i].ras = ras;
data[i].cpu = i;
*/
#include "ras-mc-event.h"
+#include "ras-logger.h"
#include <string.h>
#include <stdio.h>
rc = sqlite3_prepare_v2(ras->db, sql, -1, &ras->stmt, NULL);
if (rc != SQLITE_OK)
- printf("Failed to prepare insert db on %s: error = %s\n",
- SQLITE_RAS_DB, sqlite3_errmsg(ras->db));
+ log(TERM, LOG_ERR, "Failed to prepare insert db on %s: error = %s\n",
+ SQLITE_RAS_DB, sqlite3_errmsg(ras->db))
return rc;
}
rc = sqlite3_initialize();
if (rc != SQLITE_OK) {
- printf("Failed to initialize sqlite: error = %d\n", rc);
+ log(TERM, LOG_ERR, "Failed to initialize sqlite: error = %d\n", rc)
return NULL;
}
rc = sqlite3_open_v2(SQLITE_RAS_DB, &db,
SQLITE_OPEN_FULLMUTEX | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
if (rc != SQLITE_OK) {
- printf("Failed to connect to %s: error = %d\n",
- SQLITE_RAS_DB, rc);
+ log(TERM, LOG_ERR, "Failed to connect to %s: error = %d\n",
+ SQLITE_RAS_DB, rc)
return NULL;
}
strcat(sql, mc_event_db_create_fields);
rc = sqlite3_exec(db, sql, NULL, NULL, NULL);
if (rc != SQLITE_OK) {
- printf("Failed to create db on %s: error = %d\n",
- SQLITE_RAS_DB, rc);
+ log(TERM, LOG_ERR, "Failed to create db on %s: error = %d\n",
+ SQLITE_RAS_DB, rc)
return NULL;
}
rc = ras_mc_prepare_stmt(ras);
if (rc == SQLITE_OK)
- printf("Recording events at %s\n", SQLITE_RAS_DB, rc);
+ log(TERM, LOG_INFO, "Recording events at %s\n", SQLITE_RAS_DB, rc)
return db;
}
{
int rc;
- printf("store_event: %p\n", ras->stmt);
+ log(TERM, LOG_INFO, "store_event: %p\n", ras->stmt)
if (!ras->stmt)
return 0;
sqlite3_bind_text(ras->stmt, 13, ev->driver_detail, -1, NULL);
rc = sqlite3_step(ras->stmt);
if (rc != SQLITE_OK && rc != SQLITE_DONE)
- printf("Failed to do step on sqlite: error = %d\n", rc);
+ log(TERM, LOG_ERR, "Failed to do step on sqlite: error = %d\n", rc)
rc = sqlite3_finalize(ras->stmt);
if (rc != SQLITE_OK && rc != SQLITE_DONE)
- printf("Failed to do finalize insert on sqlite: error = %d\n",
- rc);
- printf("register interted at db\n");
+ log(TERM, LOG_ERR, "Failed to do finalize insert on sqlite: error = %d\n",
+ rc)
+ log(TERM, LOG_INFO, "register interted at db\n")
return rc;
}
#include <argp.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include "ras-record.h"
+#include "ras-logger.h"
/*
* Arguments(argp) handling logic and main
struct arguments {
int record_events;
int enable_ras;
+ int foreground;
};
static error_t parse_opt(int k, char *arg, struct argp_state *state)
case 'r':
args->record_events++;
break;
+ case 'f':
+ args->foreground++;
+ break;
default:
return ARGP_ERR_UNKNOWN;
}
{"enable", 'e', 0, 0, "enable RAS events and exit", 0},
{"disable", 'd', 0, 0, "disable RAS events and exit", 0},
{"record", 'r', 0, 0, "record events via sqlite3", 0},
+ {"foreground", 'f', 0, 0, "run foreground, not daemonize"},
{ 0, 0, 0, 0, 0, 0 }
};
else if (args.enable_ras < 0)
toggle_ras_mc_event(0);
- if (!args.enable_ras)
- handle_ras_events(args.record_events);
+ if (args.enable_ras)
+ return 0;
+
+ openlog(TOOL_NAME, 0, LOG_DAEMON);
+ if (!args.foreground)
+ if (daemon(0,0))
+ exit(EXIT_FAILURE);
+
+ handle_ras_events(args.record_events);
return 0;
}