X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fjournal%2Fjournald-kmsg.c;h=c4216c4043370bb8047c99a07faf9336cc9bfe16;hp=4f5e7a0c52f2ad3c5df5e48a07f25b4ef03ffe26;hb=3b97fcbd28f92a1e51887fef5de8844a89bde523;hpb=b2e6df73aa508cc09b1b536a2fb9f90f152b89fa diff --git a/src/journal/journald-kmsg.c b/src/journal/journald-kmsg.c index 4f5e7a0c5..c4216c404 100644 --- a/src/journal/journald-kmsg.c +++ b/src/journal/journald-kmsg.c @@ -25,10 +25,10 @@ #include #include -#include +#include "systemd/sd-messages.h" #include -#include "journald.h" +#include "journald-server.h" #include "journald-kmsg.h" #include "journald-syslog.h" @@ -37,10 +37,11 @@ void server_forward_kmsg( int priority, const char *identifier, const char *message, - struct ucred *ucred) { + const struct ucred *ucred) { struct iovec iovec[5]; - char header_priority[6], header_pid[16]; + char header_priority[DECIMAL_STR_MAX(priority) + 3], + header_pid[sizeof("[]: ")-1 + DECIMAL_STR_MAX(pid_t) + 1]; int n = 0; char *ident_buf = NULL; @@ -60,8 +61,7 @@ void server_forward_kmsg( priority = syslog_fixup_facility(priority); /* First: priority field */ - snprintf(header_priority, sizeof(header_priority), "<%i>", priority); - char_array_0(header_priority); + xsprintf(header_priority, "<%i>", priority); IOVEC_SET_STRING(iovec[n++], header_priority); /* Second: identifier and PID */ @@ -71,8 +71,7 @@ void server_forward_kmsg( identifier = ident_buf; } - snprintf(header_pid, sizeof(header_pid), "[%lu]: ", (unsigned long) ucred->pid); - char_array_0(header_pid); + xsprintf(header_pid, "["PID_FMT"]: ", ucred->pid); if (identifier) IOVEC_SET_STRING(iovec[n++], identifier); @@ -88,7 +87,7 @@ void server_forward_kmsg( IOVEC_SET_STRING(iovec[n++], "\n"); if (writev(s->dev_kmsg_fd, iovec, n) < 0) - log_debug("Failed to write to /dev/kmsg for logging: %s", strerror(errno)); + log_debug_errno(errno, "Failed to write to /dev/kmsg for logging: %m"); free(ident_buf); } @@ -104,12 +103,12 @@ static bool is_us(const char *pid) { return t == getpid(); } -static void dev_kmsg_record(Server *s, char *p, size_t l) { +static void dev_kmsg_record(Server *s, const char *p, size_t l) { struct iovec iovec[N_IOVEC_META_FIELDS + 7 + N_IOVEC_KERNEL_FIELDS + 2 + N_IOVEC_UDEV_FIELDS]; char *message = NULL, *syslog_priority = NULL, *syslog_pid = NULL, *syslog_facility = NULL, *syslog_identifier = NULL, *source_time = NULL; int priority, r; unsigned n = 0, z = 0, j; - usec_t usec; + unsigned long long usec; char *identifier = NULL, *pid = NULL, *e, *f, *k; uint64_t serial; size_t pl; @@ -151,7 +150,8 @@ static void dev_kmsg_record(Server *s, char *p, size_t l) { /* Did we lose any? */ if (serial > *s->kernel_seqnum) - server_driver_message(s, SD_MESSAGE_JOURNAL_MISSED, "Missed %llu kernel messages", (unsigned long long) serial - *s->kernel_seqnum - 1); + server_driver_message(s, SD_MESSAGE_JOURNAL_MISSED, "Missed %"PRIu64" kernel messages", + serial - *s->kernel_seqnum); /* Make sure we never read this one again. Note that * we always store the next message serial we expect @@ -171,7 +171,7 @@ static void dev_kmsg_record(Server *s, char *p, size_t l) { e = f; *e = 0; - r = parse_usec(p, &usec); + r = safe_atollu(p, &usec); if (r < 0) return; @@ -250,10 +250,12 @@ static void dev_kmsg_record(Server *s, char *p, size_t l) { break; g = udev_list_entry_get_name(ll); - b = strappend("_UDEV_DEVLINK=", g); if (g) { - IOVEC_SET_STRING(iovec[n++], b); - z++; + b = strappend("_UDEV_DEVLINK=", g); + if (b) { + IOVEC_SET_STRING(iovec[n++], b); + z++; + } } j++; @@ -263,8 +265,7 @@ static void dev_kmsg_record(Server *s, char *p, size_t l) { } } - if (asprintf(&source_time, "_SOURCE_MONOTONIC_TIMESTAMP=%llu", - (unsigned long long) usec) >= 0) + if (asprintf(&source_time, "_SOURCE_MONOTONIC_TIMESTAMP=%llu", usec) >= 0) IOVEC_SET_STRING(iovec[n++], source_time); IOVEC_SET_STRING(iovec[n++], "_TRANSPORT=kernel"); @@ -272,10 +273,13 @@ static void dev_kmsg_record(Server *s, char *p, size_t l) { if (asprintf(&syslog_priority, "PRIORITY=%i", priority & LOG_PRIMASK) >= 0) IOVEC_SET_STRING(iovec[n++], syslog_priority); + if (asprintf(&syslog_facility, "SYSLOG_FACILITY=%i", LOG_FAC(priority)) >= 0) + IOVEC_SET_STRING(iovec[n++], syslog_facility); + if ((priority & LOG_FACMASK) == LOG_KERN) IOVEC_SET_STRING(iovec[n++], "SYSLOG_IDENTIFIER=kernel"); else { - syslog_parse_identifier((const char**) &p, &identifier, &pid); + pl -= syslog_parse_identifier((const char**) &p, &identifier, &pid); /* Avoid any messages we generated ourselves via * log_info() and friends. */ @@ -293,16 +297,13 @@ static void dev_kmsg_record(Server *s, char *p, size_t l) { if (syslog_pid) IOVEC_SET_STRING(iovec[n++], syslog_pid); } - - if (asprintf(&syslog_facility, "SYSLOG_FACILITY=%i", LOG_FAC(priority)) >= 0) - IOVEC_SET_STRING(iovec[n++], syslog_facility); } message = cunescape_length_with_prefix(p, pl, "MESSAGE="); if (message) IOVEC_SET_STRING(iovec[n++], message); - server_dispatch_message(s, iovec, n, ELEMENTSOF(iovec), NULL, NULL, NULL, 0, NULL, priority); + server_dispatch_message(s, iovec, n, ELEMENTSOF(iovec), NULL, NULL, NULL, 0, NULL, priority, 0); finish: for (j = 0; j < z; j++) @@ -318,7 +319,7 @@ finish: free(pid); } -int server_read_dev_kmsg(Server *s) { +static int server_read_dev_kmsg(Server *s) { char buffer[8192+1]; /* the kernel-side limit per record is 8K currently */ ssize_t l; @@ -333,14 +334,14 @@ int server_read_dev_kmsg(Server *s) { * return EINVAL when we try. So handle this cleanly, * but don' try to ever read from it again. */ if (errno == EINVAL) { - epoll_ctl(s->epoll_fd, EPOLL_CTL_DEL, s->dev_kmsg_fd, NULL); + s->dev_kmsg_event_source = sd_event_source_unref(s->dev_kmsg_event_source); return 0; } if (errno == EAGAIN || errno == EINTR || errno == EPIPE) return 0; - log_error("Failed to read from kernel: %m"); + log_error_errno(errno, "Failed to read from kernel: %m"); return -errno; } @@ -373,38 +374,67 @@ int server_flush_dev_kmsg(Server *s) { return 0; } +static int dispatch_dev_kmsg(sd_event_source *es, int fd, uint32_t revents, void *userdata) { + Server *s = userdata; + + assert(es); + assert(fd == s->dev_kmsg_fd); + assert(s); + + if (revents & EPOLLERR) + log_warning("/dev/kmsg buffer overrun, some messages lost."); + + if (!(revents & EPOLLIN)) + log_error("Got invalid event from epoll for /dev/kmsg: %"PRIx32, revents); + + return server_read_dev_kmsg(s); +} + int server_open_dev_kmsg(Server *s) { - struct epoll_event ev; + int r; assert(s); s->dev_kmsg_fd = open("/dev/kmsg", O_RDWR|O_CLOEXEC|O_NONBLOCK|O_NOCTTY); if (s->dev_kmsg_fd < 0) { - log_warning("Failed to open /dev/kmsg, ignoring: %m"); + log_full(errno == ENOENT ? LOG_DEBUG : LOG_WARNING, + "Failed to open /dev/kmsg, ignoring: %m"); return 0; } - zero(ev); - ev.events = EPOLLIN; - ev.data.fd = s->dev_kmsg_fd; - if (epoll_ctl(s->epoll_fd, EPOLL_CTL_ADD, s->dev_kmsg_fd, &ev) < 0) { + r = sd_event_add_io(s->event, &s->dev_kmsg_event_source, s->dev_kmsg_fd, EPOLLIN, dispatch_dev_kmsg, s); + if (r < 0) { /* This will fail with EPERM on older kernels where * /dev/kmsg is not readable. */ - if (errno == EPERM) - return 0; + if (r == -EPERM) { + r = 0; + goto fail; + } - log_error("Failed to add /dev/kmsg fd to epoll object: %m"); - return -errno; + log_error_errno(r, "Failed to add /dev/kmsg fd to event loop: %m"); + goto fail; + } + + r = sd_event_source_set_priority(s->dev_kmsg_event_source, SD_EVENT_PRIORITY_IMPORTANT+10); + if (r < 0) { + log_error_errno(r, "Failed to adjust priority of kmsg event source: %m"); + goto fail; } s->dev_kmsg_readable = true; return 0; + +fail: + s->dev_kmsg_event_source = sd_event_source_unref(s->dev_kmsg_event_source); + s->dev_kmsg_fd = safe_close(s->dev_kmsg_fd); + + return r; } int server_open_kernel_seqnum(Server *s) { - int fd; + _cleanup_close_ int fd; uint64_t *p; assert(s); @@ -415,24 +445,21 @@ int server_open_kernel_seqnum(Server *s) { fd = open("/run/systemd/journal/kernel-seqnum", O_RDWR|O_CREAT|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0644); if (fd < 0) { - log_error("Failed to open /run/systemd/journal/kernel-seqnum, ignoring: %m"); + log_error_errno(errno, "Failed to open /run/systemd/journal/kernel-seqnum, ignoring: %m"); return 0; } if (posix_fallocate(fd, 0, sizeof(uint64_t)) < 0) { - log_error("Failed to allocate sequential number file, ignoring: %m"); - close_nointr_nofail(fd); + log_error_errno(errno, "Failed to allocate sequential number file, ignoring: %m"); return 0; } p = mmap(NULL, sizeof(uint64_t), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); if (p == MAP_FAILED) { - log_error("Failed to map sequential number file, ignoring: %m"); - close_nointr_nofail(fd); + log_error_errno(errno, "Failed to map sequential number file, ignoring: %m"); return 0; } - close_nointr_nofail(fd); s->kernel_seqnum = p; return 0;