This patch adds posibility for journal to get process data from socket data (if available) instead of from procfs.
Additionally a new procinfo structure is added to store all process data in single place. This data include creditentials and status. To enable this functionality, SO_PASSPROC socket option must be set. This option is introduced in: http://lwn.net/Articles/600564/ With this patch journald cpu usage is decresed by about 20% Signed-off-by: Piotr Wilczek <[email protected]> --- src/journal/journald-kmsg.c | 2 +- src/journal/journald-native.c | 24 ++++---- src/journal/journald-native.h | 4 +- src/journal/journald-server.c | 131 +++++++++++++++++++++++++++++++++--------- src/journal/journald-server.h | 17 +++++- src/journal/journald-stream.c | 7 ++- src/journal/journald-syslog.c | 15 +++-- src/journal/journald-syslog.h | 2 +- 8 files changed, 155 insertions(+), 47 deletions(-) diff --git a/src/journal/journald-kmsg.c b/src/journal/journald-kmsg.c index 12992e7..0bac0df 100644 --- a/src/journal/journald-kmsg.c +++ b/src/journal/journald-kmsg.c @@ -304,7 +304,7 @@ static void dev_kmsg_record(Server *s, char *p, size_t l) { if (message) IOVEC_SET_STRING(iovec[n++], message); - server_dispatch_message(s, iovec, n, ELEMENTSOF(iovec), NULL, NULL, NULL, 0, NULL, priority, 0); + server_dispatch_message(s, iovec, n, ELEMENTSOF(iovec), NULL, NULL, priority, 0); finish: for (j = 0; j < z; j++) diff --git a/src/journal/journald-native.c b/src/journal/journald-native.c index c54f647..b2c44d6 100644 --- a/src/journal/journald-native.c +++ b/src/journal/journald-native.c @@ -75,9 +75,7 @@ static bool allow_object_pid(struct ucred *ucred) { void server_process_native_message( Server *s, const void *buffer, size_t buffer_size, - struct ucred *ucred, - struct timeval *tv, - const char *label, size_t label_len) { + struct procinfo *procinfo) { struct iovec *iovec = NULL; unsigned n = 0, j, tn = (unsigned) -1; @@ -87,12 +85,20 @@ void server_process_native_message( char *identifier = NULL, *message = NULL; pid_t object_pid = 0; + struct ucred *ucred = NULL; + struct timeval *tv = NULL; + assert(s); assert(buffer || buffer_size == 0); p = buffer; remaining = buffer_size; + if (procinfo) { + ucred = procinfo->ucred; + tv = procinfo->tv; + } + while (remaining > 0) { const char *e, *q; @@ -106,7 +112,7 @@ void server_process_native_message( if (e == p) { /* Entry separator */ - server_dispatch_message(s, iovec, n, m, ucred, tv, label, label_len, NULL, priority, object_pid); + server_dispatch_message(s, iovec, n, m, procinfo, NULL, priority, object_pid); n = 0; priority = LOG_INFO; @@ -266,7 +272,7 @@ void server_process_native_message( server_forward_wall(s, priority, identifier, message, ucred); } - server_dispatch_message(s, iovec, n, m, ucred, tv, label, label_len, NULL, priority, object_pid); + server_dispatch_message(s, iovec, n, m, procinfo, NULL, priority, object_pid); finish: for (j = 0; j < n; j++) { @@ -286,9 +292,7 @@ finish: void server_process_native_file( Server *s, int fd, - struct ucred *ucred, - struct timeval *tv, - const char *label, size_t label_len) { + struct procinfo *procinfo) { struct stat st; _cleanup_free_ void *p = NULL; @@ -298,7 +302,7 @@ void server_process_native_file( assert(s); assert(fd >= 0); - if (!ucred || ucred->uid != 0) { + if (!procinfo || !procinfo->ucred || procinfo->ucred->uid != 0) { _cleanup_free_ char *sl = NULL, *k = NULL; const char *e; @@ -362,7 +366,7 @@ void server_process_native_file( if (n < 0) log_error("Failed to read file, ignoring: %s", strerror(-n)); else if (n > 0) - server_process_native_message(s, p, n, ucred, tv, label, label_len); + server_process_native_message(s, p, n, procinfo); } int server_open_native_socket(Server*s) { diff --git a/src/journal/journald-native.h b/src/journal/journald-native.h index bf02fee..858a3d8 100644 --- a/src/journal/journald-native.h +++ b/src/journal/journald-native.h @@ -30,8 +30,8 @@ bool valid_user_field(const char *p, size_t l, bool allow_protected); -void server_process_native_message(Server *s, const void *buffer, size_t buffer_size, struct ucred *ucred, struct timeval *tv, const char *label, size_t label_len); +void server_process_native_message(Server *s, const void *buffer, size_t buffer_size, struct procinfo *procinfo); -void server_process_native_file(Server *s, int fd, struct ucred *ucred, struct timeval *tv, const char *label, size_t label_len); +void server_process_native_file(Server *s, int fd, struct procinfo *procinfo); int server_open_native_socket(Server*s); diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index 381d80a..6c029b3 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -533,12 +533,34 @@ static void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, unsigned server_schedule_sync(s, priority); } +static int get_cap(const char *status, const char *cap_name, char **cap_val) +{ + char *k, *l, *p; + + if (!status || !cap_name) + return -1; + + k = strstr(status, cap_name); + if (!k) + return -1; + k += strlen(cap_name); + + p = strchr(k, '\n'); + if (!p) + return -1; + l = strndup(k, p - k); + if (!l) + return -1; + + *cap_val = l; + + return 0; +} + static void dispatch_message_real( Server *s, struct iovec *iovec, unsigned n, unsigned m, - struct ucred *ucred, - struct timeval *tv, - const char *label, size_t label_len, + struct procinfo *procinfo, const char *unit_id, int priority, pid_t object_pid) { @@ -567,13 +589,19 @@ static void dispatch_message_real( uint32_t audit; uid_t loginuid; #endif + struct ucred *ucred = NULL; + struct timeval *tv = NULL; +#ifdef HAVE_SELINUX + const char *label = NULL; + size_t label_len = 0; +#endif assert(s); assert(iovec); assert(n > 0); assert(n + N_IOVEC_META_FIELDS + (object_pid ? N_IOVEC_OBJECT_FIELDS : 0) <= m); - if (ucred) { + if (procinfo && procinfo->ucred) { realuid = ucred->uid; sprintf(pid, "_PID="PID_FMT, ucred->pid); @@ -585,28 +613,47 @@ static void dispatch_message_real( sprintf(gid, "_GID="GID_FMT, ucred->gid); IOVEC_SET_STRING(iovec[n++], gid); - r = get_process_comm(ucred->pid, &t); - if (r >= 0) { - x = strappenda("_COMM=", t); - free(t); + if (procinfo->comm) { + x = strappenda("_COMM=", procinfo->comm); IOVEC_SET_STRING(iovec[n++], x); + } else { + r = get_process_comm(ucred->pid, &t); + if (r >= 0) { + x = strappenda("_COMM=", t); + free(t); + IOVEC_SET_STRING(iovec[n++], x); + } } - r = get_process_exe(ucred->pid, &t); - if (r >= 0) { - x = strappenda("_EXE=", t); - free(t); + if (procinfo->exe) { + x = strappenda("_EXE=", procinfo->exe); IOVEC_SET_STRING(iovec[n++], x); + } else { + r = get_process_exe(ucred->pid, &t); + if (r >= 0) { + x = strappenda("_EXE=", t); + free(t); + IOVEC_SET_STRING(iovec[n++], x); + } } - r = get_process_cmdline(ucred->pid, 0, false, &t); - if (r >= 0) { - x = strappenda("_CMDLINE=", t); - free(t); + if (procinfo->cmdline) { + x = strappenda("_CMDLINE=", procinfo->cmdline); IOVEC_SET_STRING(iovec[n++], x); + } else { + r = get_process_cmdline(ucred->pid, 0, false, &t); + if (r >= 0) { + x = strappenda("_CMDLINE=", t); + free(t); + IOVEC_SET_STRING(iovec[n++], x); + } } - r = get_process_capeff(ucred->pid, &t); + r = -1; + if (procinfo->status) + r = get_cap(procinfo->status, "CapEff:\t", &t); + if (r < 0) + r = get_process_capeff(ucred->pid, &t); if (r >= 0) { x = strappenda("_CAP_EFFECTIVE=", t); free(t); @@ -825,6 +872,7 @@ void server_driver_message(Server *s, sd_id128_t message_id, const char *format, int n = 0; va_list ap; struct ucred ucred = {}; + struct procinfo procinfo = {}; assert(s); assert(format); @@ -849,15 +897,15 @@ void server_driver_message(Server *s, sd_id128_t message_id, const char *format, ucred.uid = getuid(); ucred.gid = getgid(); - dispatch_message_real(s, iovec, n, ELEMENTSOF(iovec), &ucred, NULL, NULL, 0, NULL, LOG_INFO, 0); + procinfo.ucred = &ucred; + + dispatch_message_real(s, iovec, n, ELEMENTSOF(iovec), &procinfo, NULL, LOG_INFO, 0); } void server_dispatch_message( Server *s, struct iovec *iovec, unsigned n, unsigned m, - struct ucred *ucred, - struct timeval *tv, - const char *label, size_t label_len, + struct procinfo *procinfo, const char *unit_id, int priority, pid_t object_pid) { @@ -865,10 +913,14 @@ void server_dispatch_message( int rl, r; _cleanup_free_ char *path = NULL; char *c; + struct ucred *ucred = NULL; assert(s); assert(iovec || n == 0); + if (procinfo) + ucred = procinfo->ucred; + if (n == 0) return; @@ -915,7 +967,7 @@ void server_dispatch_message( "Suppressed %u messages from %s", rl - 1, path); finish: - dispatch_message_real(s, iovec, n, m, ucred, tv, label, label_len, unit_id, priority, object_pid); + dispatch_message_real(s, iovec, n, m, procinfo, unit_id, priority, object_pid); } @@ -1122,6 +1174,9 @@ int process_datagram(sd_event_source *es, int fd, uint32_t revents, void *userda char *label = NULL; size_t label_len = 0; struct iovec iovec; + struct procinfo procinfo; + + memset(&procinfo, 0x00, sizeof(struct procinfo)); union { struct cmsghdr cmsghdr; @@ -1136,7 +1191,7 @@ int process_datagram(sd_event_source *es, int fd, uint32_t revents, void *userda uint8_t buf[CMSG_SPACE(sizeof(struct ucred)) + CMSG_SPACE(sizeof(struct timeval)) + CMSG_SPACE(sizeof(int)) + /* fd */ - CMSG_SPACE(NAME_MAX)]; /* selinux label */ + CMSG_SPACE(PATH_MAX)]; /* selinux label */ } control = {}; struct msghdr msghdr = { .msg_iov = &iovec, @@ -1189,20 +1244,44 @@ int process_datagram(sd_event_source *es, int fd, uint32_t revents, void *userda fds = (int*) CMSG_DATA(cmsg); n_fds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int); } + else if (cmsg->cmsg_level == SOL_SOCKET && + cmsg->cmsg_type == SCM_PROCINFO) { + + unsigned int i; + char *ptr = CMSG_DATA(cmsg); + + procinfo.ucred = ucred; + procinfo.label = label; + procinfo.label_len = label_len; + procinfo.tv = tv; + + for (i = 0; i < cmsg->cmsg_len; i+=strlen(ptr+i)+1) { + if (strlen(ptr+i) == 0) + continue; + if (strncmp(ptr+i, "COMM=", strlen("COMM=")) == 0) + procinfo.comm = ptr+i+strlen("COMM="); + if (strncmp(ptr+i, "EXE=", strlen("EXE=")) == 0) + procinfo.exe = ptr+i+strlen("EXE="); + if (strncmp(ptr+i, "CMDLINE=", strlen("CMDLINE=")) == 0) + procinfo.cmdline = ptr+i+strlen("CMDLINE="); + if (strncmp(ptr+i, "STATUS=", strlen("STATUS=")) == 0) + procinfo.status = ptr+i+strlen("STATUS="); + } + } } if (fd == s->syslog_fd) { if (n > 0 && n_fds == 0) { s->buffer[n] = 0; - server_process_syslog_message(s, strstrip(s->buffer), ucred, tv, label, label_len); + server_process_syslog_message(s, strstrip(s->buffer), &procinfo); } else if (n_fds > 0) log_warning("Got file descriptors via syslog socket. Ignoring."); } else { if (n > 0 && n_fds == 0) - server_process_native_message(s, s->buffer, n, ucred, tv, label, label_len); + server_process_native_message(s, s->buffer, n, &procinfo); else if (n == 0 && n_fds == 1) - server_process_native_file(s, fds[0], ucred, tv, label, label_len); + server_process_native_file(s, fds[0], &procinfo); else if (n_fds > 0) log_warning("Got too many file descriptors via native socket. Ignoring."); } diff --git a/src/journal/journald-server.h b/src/journal/journald-server.h index e468b82..3f9b43f 100644 --- a/src/journal/journald-server.h +++ b/src/journal/journald-server.h @@ -143,12 +143,27 @@ typedef struct Server { char *cgroup_root; } Server; +#ifndef SCM_PROCINFO +#define SCM_PROCINFO 0x05 +#endif + +struct procinfo { + struct ucred *ucred; + struct timeval *tv; + char *label; + size_t label_len; + char *comm; + char *exe; + char *cmdline; + char *status; +}; + #define N_IOVEC_META_FIELDS 20 #define N_IOVEC_KERNEL_FIELDS 64 #define N_IOVEC_UDEV_FIELDS 32 #define N_IOVEC_OBJECT_FIELDS 11 -void server_dispatch_message(Server *s, struct iovec *iovec, unsigned n, unsigned m, struct ucred *ucred, struct timeval *tv, const char *label, size_t label_len, const char *unit_id, int priority, pid_t object_pid); +void server_dispatch_message(Server *s, struct iovec *iovec, unsigned n, unsigned m, struct procinfo *procinfo, const char *unit_id, int priority, pid_t object_pid); void server_driver_message(Server *s, sd_id128_t message_id, const char *format, ...) _printf_(3,4); /* gperf lookup function */ diff --git a/src/journal/journald-stream.c b/src/journal/journald-stream.c index 89da150..1a62462 100644 --- a/src/journal/journald-stream.c +++ b/src/journal/journald-stream.c @@ -86,6 +86,7 @@ static int stdout_stream_log(StdoutStream *s, const char *p) { unsigned n = 0; char *label = NULL; size_t label_len = 0; + struct procinfo procinfo = { 0 }; assert(s); assert(p); @@ -137,7 +138,11 @@ static int stdout_stream_log(StdoutStream *s, const char *p) { } #endif - server_dispatch_message(s->server, iovec, n, ELEMENTSOF(iovec), &s->ucred, NULL, label, label_len, s->unit_id, priority, 0); + procinfo.ucred = &s->ucred; + procinfo.label = label; + procinfo.label_len = label_len; + + server_dispatch_message(s->server, iovec, n, ELEMENTSOF(iovec), &procinfo, s->unit_id, priority, 0); return 0; } diff --git a/src/journal/journald-syslog.c b/src/journal/journald-syslog.c index 434eac4..4bbc389 100644 --- a/src/journal/journald-syslog.c +++ b/src/journal/journald-syslog.c @@ -351,10 +351,7 @@ static void syslog_skip_date(char **buf) { void server_process_syslog_message( Server *s, const char *buf, - struct ucred *ucred, - struct timeval *tv, - const char *label, - size_t label_len) { + struct procinfo *procinfo) { char *message = NULL, *syslog_priority = NULL, *syslog_facility = NULL, *syslog_identifier = NULL, *syslog_pid = NULL; struct iovec iovec[N_IOVEC_META_FIELDS + 6]; @@ -363,9 +360,17 @@ void server_process_syslog_message( char *identifier = NULL, *pid = NULL; const char *orig; + struct ucred *ucred = NULL; + struct timeval *tv = NULL; + assert(s); assert(buf); + if (procinfo) { + ucred = procinfo->ucred; + tv = procinfo->tv; + } + orig = buf; syslog_parse_priority(&buf, &priority, true); @@ -409,7 +414,7 @@ void server_process_syslog_message( if (message) IOVEC_SET_STRING(iovec[n++], message); - server_dispatch_message(s, iovec, n, ELEMENTSOF(iovec), ucred, tv, label, label_len, NULL, priority, 0); + server_dispatch_message(s, iovec, n, ELEMENTSOF(iovec), procinfo, NULL, priority, 0); free(message); free(identifier); diff --git a/src/journal/journald-syslog.h b/src/journal/journald-syslog.h index 057ea79..79f6949 100644 --- a/src/journal/journald-syslog.h +++ b/src/journal/journald-syslog.h @@ -30,7 +30,7 @@ size_t syslog_parse_identifier(const char **buf, char **identifier, char **pid); void server_forward_syslog(Server *s, int priority, const char *identifier, const char *message, struct ucred *ucred, struct timeval *tv); -void server_process_syslog_message(Server *s, const char *buf, struct ucred *ucred, struct timeval *tv, const char *label, size_t label_len); +void server_process_syslog_message(Server *s, const char *buf, struct procinfo *procinfo); int server_open_syslog_socket(Server *s); void server_maybe_warn_forward_syslog_missed(Server *s); -- 1.9.1 _______________________________________________ systemd-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/systemd-devel
