syslogd: add option to log to Linux kernel printk buffer

Why invent our own shared memory circular buffer when the kernel has a
perfectly fine one already?

This can be used as a smaller/simpler alternative to the syslogd IPC support
(as IPC shmem/klogd/logread aren't needed), while also allowing centralised
logging of everything (kernel messages, userspace bootup and syslog)
when used together with ttyprintk.

Notice that kernel 3.5+ is needed to store syslog facility in printk buffer,
otherwise only the priority is stored.

bloat-o-meter compared to IPC+klogd+logread:
function                                             old     new   delta
get_linux_version_code                                 -      84     +84
lbb_prepare                                           25      90     +65
applet_nameofs                                         6       -      -6
static.stdout@@GLIBC_2                                 8       -      -8
applet_names                                          23       9     -14
bb_msg_standard_output                                16       -     -16
init_sem                                              18       -     -18
xatoull_range                                         19       -     -19
overlapping_strcpy                                    21       -     -21
init_data                                             56      32     -24
applet_main                                           24       -     -24
main                                                 124      99     -25
full_write2_str                                       26       -     -26
error_exit                                            26       -     -26
bb_basename                                           30       -     -30
sem_up                                                32       -     -32
interrupted                                           35       -     -35
fflush_stdout_and_exit                                38       -     -38
bb_banner                                             46       -     -46
find_applet_by_name                                   59       -     -59
bb_signals_recursive_norestart                        90       -     -90
run_applet_no_and_exit                               104       -    -104
timestamp_and_log                                    651     523    -128
syslogd_main                                         798     581    -217
xstrtoull_range_sfx                                  267       -    -267
run_applet_and_exit                                  432       -    -432
klogd_main                                           490       -    -490
logread_main                                         508       -    -508
.rodata                                             1870     937    -933
bb_common_bufsiz1                                   8193       -   -8193
------------------------------------------------------------------------------
(add/remove: 2/26 grow/shrink: 1/6 up/down: 149/-11829)    Total: -11680 bytes

Signed-off-by: Peter Korsgaard <jacmet@sunsite.dk>
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
This commit is contained in:
Peter Korsgaard 2013-01-06 00:07:19 +01:00 committed by Mike Frysinger
parent d189b598b4
commit cd776cf967
2 changed files with 76 additions and 1 deletions

View File

@ -113,6 +113,19 @@ config FEATURE_LOGREAD_REDUCED_LOCKING
from circular buffer, minimizing semaphore from circular buffer, minimizing semaphore
contention at some minor memory expense. contention at some minor memory expense.
config FEATURE_KMSG_SYSLOG
bool "Linux kernel printk buffer support"
default y
depends on SYSLOGD
select PLATFORM_LINUX
help
When you enable this feature, the syslogd utility will
write system log message to the Linux kernel's printk buffer.
This can be used as a smaller alternative to the syslogd IPC
support, as klogd and logread aren't needed.
NOTICE: Syslog facilities in log entries needs kernel 3.5+.
config KLOGD config KLOGD
bool "klogd" bool "klogd"
default y default y
@ -123,6 +136,9 @@ config KLOGD
you wish to record the messages produced by the kernel, you wish to record the messages produced by the kernel,
you should enable this option. you should enable this option.
comment "klogd should not be used together with syslog to kernel printk buffer"
depends on KLOGD && FEATURE_KMSG_SYSLOG
config FEATURE_KLOGD_KLOGCTL config FEATURE_KLOGD_KLOGCTL
bool "Use the klogctl() interface" bool "Use the klogctl() interface"
default y default y

View File

@ -43,6 +43,9 @@
//usage: "\n -f FILE Use FILE as config (default:/etc/syslog.conf)" //usage: "\n -f FILE Use FILE as config (default:/etc/syslog.conf)"
//usage: ) //usage: )
/* //usage: "\n -m MIN Minutes between MARK lines (default:20, 0=off)" */ /* //usage: "\n -m MIN Minutes between MARK lines (default:20, 0=off)" */
//usage: IF_FEATURE_KMSG_SYSLOG(
//usage: "\n -K Log to kernel printk buffer (use dmesg to read it)"
//usage: )
//usage: //usage:
//usage:#define syslogd_example_usage //usage:#define syslogd_example_usage
//usage: "$ syslogd -R masterlog:514\n" //usage: "$ syslogd -R masterlog:514\n"
@ -140,6 +143,10 @@ IF_FEATURE_IPC_SYSLOG( \
) \ ) \
IF_FEATURE_SYSLOGD_CFG( \ IF_FEATURE_SYSLOGD_CFG( \
logRule_t *log_rules; \ logRule_t *log_rules; \
) \
IF_FEATURE_KMSG_SYSLOG( \
int kmsgfd; \
int primask; \
) )
struct init_globals { struct init_globals {
@ -212,6 +219,7 @@ enum {
IF_FEATURE_IPC_SYSLOG( OPTBIT_circularlog,) // -C IF_FEATURE_IPC_SYSLOG( OPTBIT_circularlog,) // -C
IF_FEATURE_SYSLOGD_DUP( OPTBIT_dup ,) // -D IF_FEATURE_SYSLOGD_DUP( OPTBIT_dup ,) // -D
IF_FEATURE_SYSLOGD_CFG( OPTBIT_cfg ,) // -f IF_FEATURE_SYSLOGD_CFG( OPTBIT_cfg ,) // -f
IF_FEATURE_KMSG_SYSLOG( OPTBIT_kmsg ,) // -K
OPT_mark = 1 << OPTBIT_mark , OPT_mark = 1 << OPTBIT_mark ,
OPT_nofork = 1 << OPTBIT_nofork , OPT_nofork = 1 << OPTBIT_nofork ,
@ -225,6 +233,8 @@ enum {
OPT_circularlog = IF_FEATURE_IPC_SYSLOG( (1 << OPTBIT_circularlog)) + 0, OPT_circularlog = IF_FEATURE_IPC_SYSLOG( (1 << OPTBIT_circularlog)) + 0,
OPT_dup = IF_FEATURE_SYSLOGD_DUP( (1 << OPTBIT_dup )) + 0, OPT_dup = IF_FEATURE_SYSLOGD_DUP( (1 << OPTBIT_dup )) + 0,
OPT_cfg = IF_FEATURE_SYSLOGD_CFG( (1 << OPTBIT_cfg )) + 0, OPT_cfg = IF_FEATURE_SYSLOGD_CFG( (1 << OPTBIT_cfg )) + 0,
OPT_kmsg = IF_FEATURE_KMSG_SYSLOG( (1 << OPTBIT_kmsg )) + 0,
}; };
#define OPTION_STR "m:nO:l:S" \ #define OPTION_STR "m:nO:l:S" \
IF_FEATURE_ROTATE_LOGFILE("s:" ) \ IF_FEATURE_ROTATE_LOGFILE("s:" ) \
@ -233,7 +243,8 @@ enum {
IF_FEATURE_REMOTE_LOG( "L" ) \ IF_FEATURE_REMOTE_LOG( "L" ) \
IF_FEATURE_IPC_SYSLOG( "C::") \ IF_FEATURE_IPC_SYSLOG( "C::") \
IF_FEATURE_SYSLOGD_DUP( "D" ) \ IF_FEATURE_SYSLOGD_DUP( "D" ) \
IF_FEATURE_SYSLOGD_CFG( "f:" ) IF_FEATURE_SYSLOGD_CFG( "f:" ) \
IF_FEATURE_KMSG_SYSLOG( "K" )
#define OPTION_DECL *opt_m, *opt_l \ #define OPTION_DECL *opt_m, *opt_l \
IF_FEATURE_ROTATE_LOGFILE(,*opt_s) \ IF_FEATURE_ROTATE_LOGFILE(,*opt_s) \
IF_FEATURE_ROTATE_LOGFILE(,*opt_b) \ IF_FEATURE_ROTATE_LOGFILE(,*opt_b) \
@ -523,6 +534,44 @@ void ipcsyslog_init(void);
void log_to_shmem(const char *msg); void log_to_shmem(const char *msg);
#endif /* FEATURE_IPC_SYSLOG */ #endif /* FEATURE_IPC_SYSLOG */
#if ENABLE_FEATURE_KMSG_SYSLOG
static void kmsg_init(void)
{
G.kmsgfd = xopen("/dev/kmsg", O_WRONLY);
/*
* kernel < 3.5 expects single char printk KERN_* priority prefix,
* from 3.5 onwards the full syslog facility/priority format is supported
*/
if (get_linux_version_code() < KERNEL_VERSION(3,5,0))
G.primask = LOG_PRIMASK;
else
G.primask = -1;
}
static void kmsg_cleanup(void)
{
if (ENABLE_FEATURE_CLEAN_UP)
close(G.kmsgfd);
}
/* Write message to /dev/kmsg */
static void log_to_kmsg(int pri, const char *msg)
{
/*
* kernel < 3.5 expects single char printk KERN_* priority prefix,
* from 3.5 onwards the full syslog facility/priority format is supported
*/
pri &= G.primask;
write(G.kmsgfd, G.printbuf, sprintf(G.printbuf, "<%d>%s\n", pri, msg));
}
#else
void kmsg_init(void);
void kmsg_cleanup(void);
void log_to_kmsg(int pri, const char *msg);
#endif /* FEATURE_KMSG_SYSLOG */
/* Print a message to the log file. */ /* Print a message to the log file. */
static void log_locally(time_t now, char *msg, logFile_t *log_file) static void log_locally(time_t now, char *msg, logFile_t *log_file)
{ {
@ -657,6 +706,11 @@ static void timestamp_and_log(int pri, char *msg, int len)
} }
timestamp[15] = '\0'; timestamp[15] = '\0';
if (ENABLE_FEATURE_KMSG_SYSLOG && (option_mask32 & OPT_kmsg)) {
log_to_kmsg(pri, msg);
return;
}
if (option_mask32 & OPT_small) if (option_mask32 & OPT_small)
sprintf(G.printbuf, "%s %s\n", timestamp, msg); sprintf(G.printbuf, "%s %s\n", timestamp, msg);
else { else {
@ -831,6 +885,9 @@ static void do_syslogd(void)
ipcsyslog_init(); ipcsyslog_init();
} }
if (ENABLE_FEATURE_KMSG_SYSLOG && (option_mask32 & OPT_kmsg))
kmsg_init();
timestamp_and_log_internal("syslogd started: BusyBox v" BB_VER); timestamp_and_log_internal("syslogd started: BusyBox v" BB_VER);
while (!bb_got_signal) { while (!bb_got_signal) {
@ -919,6 +976,8 @@ static void do_syslogd(void)
remove_pidfile(CONFIG_PID_FILE_PATH "/syslogd.pid"); remove_pidfile(CONFIG_PID_FILE_PATH "/syslogd.pid");
if (ENABLE_FEATURE_IPC_SYSLOG) if (ENABLE_FEATURE_IPC_SYSLOG)
ipcsyslog_cleanup(); ipcsyslog_cleanup();
if (ENABLE_FEATURE_KMSG_SYSLOG && (option_mask32 & OPT_kmsg))
kmsg_cleanup();
kill_myself_with_sig(bb_got_signal); kill_myself_with_sig(bb_got_signal);
#undef recvbuf #undef recvbuf
} }