mirror of
https://github.com/schoebel/mars
synced 2025-03-25 04:26:49 +00:00
usability: added /proc/sys/mars/{errors,warnings}
This commit is contained in:
parent
ff37572045
commit
7ee39d8dfa
16
brick.h
16
brick.h
@ -28,22 +28,22 @@ extern int brick_msleep(int msecs, bool shorten);
|
||||
#define BRICK_INFO "BRICK_INFO "
|
||||
#define BRICK_DEBUG "BRICK_DEBUG "
|
||||
|
||||
#define _BRICK_MSG(_dump, PREFIX, _fmt, _args...) \
|
||||
brick_say(_dump, PREFIX, __BASE_FILE__, __LINE__, __FUNCTION__, _fmt, ##_args)
|
||||
#define _BRICK_MSG(_class, _dump, PREFIX, _fmt, _args...) \
|
||||
brick_say(_class, _dump, PREFIX, __BASE_FILE__, __LINE__, __FUNCTION__, _fmt, ##_args)
|
||||
|
||||
#define BRICK_FAT(_fmt, _args...) _BRICK_MSG(true, BRICK_FATAL, _fmt, ##_args)
|
||||
#define BRICK_ERR(_fmt, _args...) _BRICK_MSG(true, BRICK_ERROR, _fmt, ##_args)
|
||||
#define BRICK_WRN(_fmt, _args...) _BRICK_MSG(false, BRICK_WARNING, _fmt, ##_args)
|
||||
#define BRICK_INF(_fmt, _args...) _BRICK_MSG(false, BRICK_INFO, _fmt, ##_args)
|
||||
#define BRICK_FAT(_fmt, _args...) _BRICK_MSG(1, true, BRICK_FATAL, _fmt, ##_args)
|
||||
#define BRICK_ERR(_fmt, _args...) _BRICK_MSG(1, true, BRICK_ERROR, _fmt, ##_args)
|
||||
#define BRICK_WRN(_fmt, _args...) _BRICK_MSG(0, false, BRICK_WARNING, _fmt, ##_args)
|
||||
#define BRICK_INF(_fmt, _args...) _BRICK_MSG(-1, false, BRICK_INFO, _fmt, ##_args)
|
||||
|
||||
#ifdef BRICK_DEBUGGING
|
||||
#define BRICK_DBG(_fmt, _args...) _BRICK_MSG(false, BRICK_DEBUG, _fmt, ##_args)
|
||||
#define BRICK_DBG(_fmt, _args...) _BRICK_MSG(-1, false, BRICK_DEBUG, _fmt, ##_args)
|
||||
#else
|
||||
#define BRICK_DBG(_args...) /**/
|
||||
#endif
|
||||
|
||||
#ifdef IO_DEBUGGING
|
||||
#define BRICK_IO(_fmt, _args...) _BRICK_MSG(false, BRICK_DEBUG, _fmt, ##_args)
|
||||
#define BRICK_IO(_fmt, _args...) _BRICK_MSG(-1, false, BRICK_DEBUG, _fmt, ##_args)
|
||||
#else
|
||||
#define BRICK_IO(_args...) /*empty*/
|
||||
#endif
|
||||
|
@ -30,13 +30,13 @@
|
||||
#define INT_ACCESS(ptr,offset) (*(int*)(((char*)(ptr)) + (offset)))
|
||||
|
||||
#define _BRICK_FMT(_fmt) __BASE_FILE__ " %d %s(): " _fmt, __LINE__, __FUNCTION__
|
||||
#define _BRICK_MSG(_dump, PREFIX, _fmt, _args...) do { say(PREFIX _BRICK_FMT(_fmt), ##_args); if (_dump) dump_stack(); } while (0)
|
||||
#define _BRICK_MSG(_class, _dump, PREFIX, _fmt, _args...) do { say(_class, PREFIX _BRICK_FMT(_fmt), ##_args); if (_dump) dump_stack(); } while (0)
|
||||
#define BRICK_ERROR "MEM_ERROR "
|
||||
#define BRICK_WARNING "MEM_WARN "
|
||||
#define BRICK_INFO "MEM_INFO "
|
||||
#define BRICK_ERR(_fmt, _args...) _BRICK_MSG(true, BRICK_ERROR, _fmt, ##_args)
|
||||
#define BRICK_WRN(_fmt, _args...) _BRICK_MSG(false, BRICK_WARNING, _fmt, ##_args)
|
||||
#define BRICK_INF(_fmt, _args...) _BRICK_MSG(false, BRICK_INFO, _fmt, ##_args)
|
||||
#define BRICK_ERR(_fmt, _args...) _BRICK_MSG(1, true, BRICK_ERROR, _fmt, ##_args)
|
||||
#define BRICK_WRN(_fmt, _args...) _BRICK_MSG(0, false, BRICK_WARNING, _fmt, ##_args)
|
||||
#define BRICK_INF(_fmt, _args...) _BRICK_MSG(-1, false, BRICK_INFO, _fmt, ##_args)
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
107
brick_say.c
107
brick_say.c
@ -31,8 +31,48 @@ static int say_index[NR_CPUS] = {};
|
||||
static int dump_max = 5;
|
||||
static atomic_t overflow = ATOMIC_INIT(0);
|
||||
|
||||
static spinlock_t proc_lock = SPIN_LOCK_UNLOCKED;
|
||||
static char *proc_buf1[MAX_SAY_CLASS] = {};
|
||||
static char *proc_buf2[MAX_SAY_CLASS] = {};
|
||||
static int proc_index1[MAX_SAY_CLASS] = {};
|
||||
static int proc_index2[MAX_SAY_CLASS] = {};
|
||||
static long long proc_stamp[MAX_SAY_CLASS] = {};
|
||||
|
||||
static struct file *log_file = NULL;
|
||||
|
||||
const char *proc_say_get(int class, int *len)
|
||||
{
|
||||
*len = 0;
|
||||
if (class >= 0 && class < MAX_SAY_CLASS) {
|
||||
*len = proc_index2[class];
|
||||
return proc_buf2[class];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(proc_say_get);
|
||||
|
||||
void proc_say_commit(void)
|
||||
{
|
||||
unsigned long flags;
|
||||
int class;
|
||||
|
||||
spin_lock_irqsave(&proc_lock, flags);
|
||||
|
||||
for (class = 0; class < MAX_SAY_CLASS; class++) {
|
||||
char *tmp = proc_buf1[class];
|
||||
if (!tmp || (!proc_index1[class] && proc_stamp[class] - (long long)jiffies < 60 * HZ))
|
||||
continue;
|
||||
proc_buf1[class] = proc_buf2[class];
|
||||
proc_buf2[class] = tmp;
|
||||
proc_index2[class] = proc_index1[class];
|
||||
proc_index1[class] = 0;
|
||||
proc_stamp[class] = jiffies;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&proc_lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(proc_say_commit);
|
||||
|
||||
static inline
|
||||
void say_alloc(unsigned long cpu, bool use_atomic)
|
||||
{
|
||||
@ -119,11 +159,13 @@ void say_mark(void)
|
||||
EXPORT_SYMBOL_GPL(say_mark);
|
||||
|
||||
static
|
||||
void _say(unsigned long cpu, va_list args, bool use_args, const char *fmt, ...)
|
||||
void _say(int class, unsigned long cpu, va_list args, bool use_args, const char *fmt, ...) __attribute__ ((format (printf, 5, 6)));
|
||||
static
|
||||
void _say(int class, unsigned long cpu, va_list args, bool use_args, const char *fmt, ...)
|
||||
{
|
||||
char *start;
|
||||
char *start = NULL;
|
||||
int rest;
|
||||
int written;
|
||||
int written = 0;
|
||||
|
||||
if (!say_buf[cpu])
|
||||
goto done;
|
||||
@ -151,9 +193,33 @@ void _say(unsigned long cpu, va_list args, bool use_args, const char *fmt, ...)
|
||||
} else {
|
||||
// indicate overflow
|
||||
start[0] = '\0';
|
||||
written = 0;
|
||||
atomic_inc(&overflow);
|
||||
}
|
||||
done: ;
|
||||
|
||||
done:
|
||||
if (class >= 0 && class < MAX_SAY_CLASS && start && written > 0) {
|
||||
char *pstart;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&proc_lock, flags);
|
||||
|
||||
if (!proc_buf1[class])
|
||||
goto proc_done;
|
||||
|
||||
rest = SAY_BUFMAX - proc_index1[class];
|
||||
if (rest <= 0)
|
||||
goto proc_done;
|
||||
|
||||
if (likely(rest > written)) {
|
||||
pstart = proc_buf1[class] + proc_index1[class];
|
||||
memcpy(pstart, start, written);
|
||||
pstart[written] = '\0';
|
||||
proc_index1[class] += written;
|
||||
}
|
||||
proc_done:
|
||||
spin_unlock_irqrestore(&proc_lock, flags);
|
||||
}
|
||||
}
|
||||
|
||||
static inline
|
||||
@ -163,12 +229,12 @@ void _check_overflow(unsigned long cpu)
|
||||
atomic_xchg(&overflow, count);
|
||||
if (unlikely(count > 0)) {
|
||||
if (likely(say_index[cpu] < SAY_BUFMAX - 8)) {
|
||||
_say(cpu, NULL, true, "#%d#\n", count);
|
||||
_say(0, cpu, NULL, true, "#%d#\n", count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void say(const char *fmt, ...)
|
||||
void say(int class, const char *fmt, ...)
|
||||
{
|
||||
unsigned long cpu = get_cpu();
|
||||
va_list args;
|
||||
@ -179,7 +245,7 @@ void say(const char *fmt, ...)
|
||||
_check_overflow(cpu);
|
||||
|
||||
va_start(args, fmt);
|
||||
_say(cpu, args, false, fmt);
|
||||
_say(class, cpu, args, false, fmt);
|
||||
va_end(args);
|
||||
|
||||
_say_mark(cpu);
|
||||
@ -188,7 +254,7 @@ done:
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(say);
|
||||
|
||||
void brick_say(bool dump, const char *prefix, const char *file, int line, const char *func, const char *fmt, ...)
|
||||
void brick_say(int class, bool dump, const char *prefix, const char *file, int line, const char *func, const char *fmt, ...)
|
||||
{
|
||||
struct timespec now = CURRENT_TIME;
|
||||
unsigned long cpu = get_cpu();
|
||||
@ -205,9 +271,9 @@ void brick_say(bool dump, const char *prefix, const char *file, int line, const
|
||||
if (filelen > MAX_FILELEN)
|
||||
file += filelen - MAX_FILELEN;
|
||||
|
||||
_say(cpu, NULL, true, "%ld.%09ld %s %s[%d] %s %d %s(): ", now.tv_sec, now.tv_nsec, prefix, current->comm, (int)cpu, file, line, func);
|
||||
_say(class, cpu, NULL, true, "%ld.%09ld %s %s[%d] %s %d %s(): ", now.tv_sec, now.tv_nsec, prefix, current->comm, (int)cpu, file, line, func);
|
||||
va_start(args, fmt);
|
||||
_say(cpu, args, false, fmt);
|
||||
_say(class, cpu, args, false, fmt);
|
||||
va_end(args);
|
||||
|
||||
_say_mark(cpu);
|
||||
@ -239,9 +305,9 @@ void check_open(const char *filename, bool must_exist)
|
||||
if (unlikely(IS_ERR(log_file))) {
|
||||
int status = PTR_ERR(log_file);
|
||||
log_file = NULL;
|
||||
say("cannot open logfile '%s', status = %d\n", filename, status);
|
||||
say(1, "cannot open logfile '%s', status = %d\n", filename, status);
|
||||
} else {
|
||||
say("opened logfile '%s' %p\n", filename, log_file);
|
||||
say(0, "opened logfile '%s' %p\n", filename, log_file);
|
||||
}
|
||||
}
|
||||
|
||||
@ -262,12 +328,12 @@ void check_close(const char *filename, bool force, bool re_open)
|
||||
if (force) {
|
||||
if (log_file) {
|
||||
struct file *old;
|
||||
say("closing logfile....\n");
|
||||
say(0, "closing logfile....\n");
|
||||
old = log_file;
|
||||
log_file = NULL;
|
||||
// FIXME: this may race against vfs_write(). Use rcu here.
|
||||
filp_close(old, NULL);
|
||||
say("closed logfile.\n");
|
||||
say(0, "closed logfile.\n");
|
||||
}
|
||||
if (re_open)
|
||||
check_open(filename, true);
|
||||
@ -276,6 +342,11 @@ void check_close(const char *filename, bool force, bool re_open)
|
||||
|
||||
void init_say(void)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_SAY_CLASS; i++) {
|
||||
proc_buf1[i] = (void*)__get_free_pages(GFP_KERNEL, SAY_ORDER);
|
||||
proc_buf2[i] = (void*)__get_free_pages(GFP_KERNEL, SAY_ORDER);
|
||||
}
|
||||
check_open(CONFIG_MARS_LOGFILE, true);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(init_say);
|
||||
@ -290,6 +361,14 @@ void exit_say(void)
|
||||
say_buf[i] = NULL;
|
||||
}
|
||||
check_close(CONFIG_MARS_LOGFILE, true, false);
|
||||
for (i = 0; i < MAX_SAY_CLASS; i++) {
|
||||
if (proc_buf1[i])
|
||||
__free_pages(virt_to_page((unsigned long)proc_buf1[i]), SAY_ORDER);
|
||||
if (proc_buf2[i])
|
||||
__free_pages(virt_to_page((unsigned long)proc_buf2[i]), SAY_ORDER);
|
||||
proc_buf1[i] = NULL;
|
||||
proc_buf2[i] = NULL;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(exit_say);
|
||||
|
||||
|
@ -6,13 +6,18 @@
|
||||
|
||||
// printk() replacements
|
||||
|
||||
#define MAX_SAY_CLASS 2
|
||||
|
||||
extern const char *proc_say_get(int class, int *len);
|
||||
extern void proc_say_commit(void);
|
||||
|
||||
extern void check_open(const char *filename, bool must_exist);
|
||||
extern void check_close(const char *filename, bool force, bool re_open);
|
||||
|
||||
extern void say(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
|
||||
extern void say(int class, const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
|
||||
extern void say_mark(void);
|
||||
|
||||
extern void brick_say(bool dump, const char *prefix, const char *file, int line, const char *func, const char *fmt, ...) __attribute__ ((format (printf, 6, 7)));
|
||||
extern void brick_say(int class, bool dump, const char *prefix, const char *file, int line, const char *func, const char *fmt, ...) __attribute__ ((format (printf, 7, 8)));
|
||||
|
||||
extern void init_say(void);
|
||||
extern void exit_say(void);
|
||||
|
16
mars.h
16
mars.h
@ -29,22 +29,22 @@
|
||||
#define MARS_INFO "MARS_INFO "
|
||||
#define MARS_DEBUG "MARS_DEBUG "
|
||||
|
||||
#define _MARS_MSG(_dump, PREFIX, _fmt, _args...) \
|
||||
brick_say(_dump, PREFIX, __BASE_FILE__, __LINE__, __FUNCTION__, _fmt, ##_args)
|
||||
#define _MARS_MSG(_class, _dump, PREFIX, _fmt, _args...) \
|
||||
brick_say(_class, _dump, PREFIX, __BASE_FILE__, __LINE__, __FUNCTION__, _fmt, ##_args)
|
||||
|
||||
#define MARS_FAT(_fmt, _args...) _MARS_MSG(true, MARS_FATAL, _fmt, ##_args)
|
||||
#define MARS_ERR(_fmt, _args...) _MARS_MSG(true, MARS_ERROR, _fmt, ##_args)
|
||||
#define MARS_WRN(_fmt, _args...) _MARS_MSG(false, MARS_WARNING, _fmt, ##_args)
|
||||
#define MARS_INF(_fmt, _args...) _MARS_MSG(false, MARS_INFO, _fmt, ##_args)
|
||||
#define MARS_FAT(_fmt, _args...) _MARS_MSG(1, true, MARS_FATAL, _fmt, ##_args)
|
||||
#define MARS_ERR(_fmt, _args...) _MARS_MSG(1, true, MARS_ERROR, _fmt, ##_args)
|
||||
#define MARS_WRN(_fmt, _args...) _MARS_MSG(0, false, MARS_WARNING, _fmt, ##_args)
|
||||
#define MARS_INF(_fmt, _args...) _MARS_MSG(-1, false, MARS_INFO, _fmt, ##_args)
|
||||
|
||||
#ifdef MARS_DEBUGGING
|
||||
#define MARS_DBG(_fmt, _args...) _MARS_MSG(false, MARS_DEBUG, _fmt, ##_args)
|
||||
#define MARS_DBG(_fmt, _args...) _MARS_MSG(-1, false, MARS_DEBUG, _fmt, ##_args)
|
||||
#else
|
||||
#define MARS_DBG(_args...) /**/
|
||||
#endif
|
||||
|
||||
#ifdef IO_DEBUGGING
|
||||
#define MARS_IO(_fmt, _args...) _MARS_MSG(false, MARS_DEBUG, _fmt, ##_args)
|
||||
#define MARS_IO(_fmt, _args...) _MARS_MSG(-1, false, MARS_DEBUG, _fmt, ##_args)
|
||||
#else
|
||||
#define MARS_IO(_args...) /*empty*/
|
||||
#endif
|
||||
|
@ -111,14 +111,14 @@ static void dump_mem(void *data, int len)
|
||||
unsigned char byte = ((unsigned char*)data)[i];
|
||||
if (!(i % 8)) {
|
||||
if (tmp != buf) {
|
||||
say("%4d: %s\n", i, buf);
|
||||
say(-1, "%4d: %s\n", i, buf);
|
||||
}
|
||||
tmp = buf;
|
||||
}
|
||||
tmp += snprintf(tmp, 1024 - i * 3, " %02x", byte);
|
||||
}
|
||||
if (tmp != buf) {
|
||||
say("%4d: %s\n", i, buf);
|
||||
say(-1, "%4d: %s\n", i, buf);
|
||||
}
|
||||
brick_string_free(buf);
|
||||
}
|
||||
|
@ -1555,7 +1555,7 @@ int _check_versionlink(struct mars_global *global, const char *parent_path, int
|
||||
MARS_DBG("VERSION OK '%s'\n", my_data);
|
||||
status = 1;
|
||||
} else {
|
||||
MARS_DBG("VERSION MISMATCH '%s' != '%s'\n", my_data, other_data);
|
||||
MARS_WRN("VERSION MISMATCH '%s' != '%s' => check for SPLIT BRAIN!\n", my_data, other_data);
|
||||
status = 0;
|
||||
}
|
||||
|
||||
@ -3541,6 +3541,8 @@ static int light_thread(void *data)
|
||||
status = mars_kill_brick_when_possible(&_global, &_global.brick_anchor, false, (void*)&sio_brick_type, false);
|
||||
MARS_DBG("kill sio bricks (when possible) = %d\n", status);
|
||||
|
||||
proc_say_commit();
|
||||
|
||||
_show_status_all(&_global);
|
||||
#ifdef STAT_DEBUGGING
|
||||
_show_statist(&_global);
|
||||
|
@ -17,11 +17,12 @@
|
||||
mars_info_fn mars_info = NULL;
|
||||
|
||||
static
|
||||
int trigger_sysctl_handler(ctl_table *table,
|
||||
int write,
|
||||
void __user *buffer,
|
||||
size_t *length,
|
||||
loff_t *ppos)
|
||||
int trigger_sysctl_handler(
|
||||
ctl_table *table,
|
||||
int write,
|
||||
void __user *buffer,
|
||||
size_t *length,
|
||||
loff_t *ppos)
|
||||
{
|
||||
ssize_t res = 0;
|
||||
size_t len = *length;
|
||||
@ -80,6 +81,70 @@ done:
|
||||
return res;
|
||||
}
|
||||
|
||||
static
|
||||
int _proc_sysctl_handler(
|
||||
int class,
|
||||
int write,
|
||||
void __user *buffer,
|
||||
size_t *length,
|
||||
loff_t *ppos)
|
||||
{
|
||||
ssize_t res = 0;
|
||||
size_t len = *length;
|
||||
|
||||
MARS_DBG("write = %d len = %ld pos = %lld\n", write, len, *ppos);
|
||||
|
||||
if (!len || *ppos > 0) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (write) {
|
||||
res = len; // fake consumption of all data
|
||||
} else {
|
||||
int len;
|
||||
const char *answer = proc_say_get(class, &len);
|
||||
|
||||
if (answer) {
|
||||
res = len;
|
||||
if (copy_to_user(buffer, answer, len)) {
|
||||
MARS_ERR("write %d bytes at %p failed\n", len, answer);
|
||||
res = -EFAULT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
MARS_DBG("res = %ld\n", res);
|
||||
*length = res;
|
||||
if (res >= 0) {
|
||||
*ppos += res;
|
||||
return 0;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static
|
||||
int warnings_sysctl_handler(
|
||||
ctl_table *table,
|
||||
int write,
|
||||
void __user *buffer,
|
||||
size_t *length,
|
||||
loff_t *ppos)
|
||||
{
|
||||
return _proc_sysctl_handler(0, write, buffer, length, ppos);
|
||||
}
|
||||
|
||||
static
|
||||
int errors_sysctl_handler(
|
||||
ctl_table *table,
|
||||
int write,
|
||||
void __user *buffer,
|
||||
size_t *length,
|
||||
loff_t *ppos)
|
||||
{
|
||||
return _proc_sysctl_handler(1, write, buffer, length, ppos);
|
||||
}
|
||||
|
||||
static
|
||||
ctl_table mars_table[] = {
|
||||
{
|
||||
@ -88,6 +153,18 @@ ctl_table mars_table[] = {
|
||||
.mode = 0200,
|
||||
.proc_handler = &trigger_sysctl_handler,
|
||||
},
|
||||
{
|
||||
.ctl_name = CTL_UNNUMBERED,
|
||||
.procname = "warnings",
|
||||
.mode = 0400,
|
||||
.proc_handler = &warnings_sysctl_handler,
|
||||
},
|
||||
{
|
||||
.ctl_name = CTL_UNNUMBERED,
|
||||
.procname = "errors",
|
||||
.mode = 0400,
|
||||
.proc_handler = &errors_sysctl_handler,
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user