diff options
-rw-r--r-- | src/journal/journald.c | 61 | ||||
-rw-r--r-- | src/journal/journald.h | 2 | ||||
-rw-r--r-- | src/systemd/sd-messages.h | 1 |
3 files changed, 64 insertions, 0 deletions
diff --git a/src/journal/journald.c b/src/journal/journald.c index 765c0e3428..7c89689e84 100644 --- a/src/journal/journald.c +++ b/src/journal/journald.c @@ -29,6 +29,7 @@ #include <sys/ioctl.h> #include <linux/sockios.h> #include <sys/statvfs.h> +#include <sys/mman.h> #include <systemd/sd-journal.h> #include <systemd/sd-messages.h> @@ -1846,6 +1847,22 @@ static void dev_kmsg_record(Server *s, char *p, size_t l) { if (r < 0) return; + if (s->kernel_seqnum) { + /* We already read this one? */ + if (serial < *s->kernel_seqnum) + return; + + /* Did we lose any? */ + if (serial > *s->kernel_seqnum) + driver_message(s, SD_MESSAGE_JOURNAL_MISSED, "Missed %llu kernel messages", (unsigned long long) serial - *s->kernel_seqnum - 1); + + /* Make sure we never read this one again. Note that + * we always store the next message serial we expect + * here, simply because this makes handling the first + * message with serial 0 easy. */ + *s->kernel_seqnum = serial + 1; + } + l -= (e - p) + 1; p = e + 1; f = memchr(p, ';', l); @@ -2607,6 +2624,41 @@ static int open_dev_kmsg(Server *s) { return 0; } +static int open_kernel_seqnum(Server *s) { + int fd; + uint64_t *p; + + assert(s); + + /* We store the seqnum we last read in an mmaped file. That + * way we can just use it like a variable, but it is + * persistant and automatically flushed at reboot. */ + + 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"); + 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); + 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); + return 0; + } + + close_nointr_nofail(fd); + s->kernel_seqnum = p; + + return 0; +} + static int open_signalfd(Server *s) { sigset_t mask; struct epoll_event ev; @@ -2740,6 +2792,8 @@ static int server_init(Server *s) { server_parse_config_file(s); server_parse_proc_cmdline(s); + mkdir_p("/run/systemd/journal", 0755); + s->user_journals = hashmap_new(trivial_hash_func, trivial_compare_func); if (!s->user_journals) return log_oom(); @@ -2807,6 +2861,10 @@ static int server_init(Server *s) { if (r < 0) return r; + r = open_kernel_seqnum(s); + if (r < 0) + return r; + r = open_signalfd(s); if (r < 0) return r; @@ -2861,6 +2919,9 @@ static void server_done(Server *s) { if (s->rate_limit) journal_rate_limit_free(s->rate_limit); + if (s->kernel_seqnum) + munmap(s->kernel_seqnum, sizeof(uint64_t)); + free(s->buffer); free(s->tty_path); } diff --git a/src/journal/journald.h b/src/journal/journald.h index 7e23bfc2dc..d08a194780 100644 --- a/src/journal/journald.h +++ b/src/journal/journald.h @@ -94,6 +94,8 @@ typedef struct Server { Storage storage; bool dev_kmsg_readable; + + uint64_t *kernel_seqnum; } Server; /* gperf lookup function */ diff --git a/src/systemd/sd-messages.h b/src/systemd/sd-messages.h index 3f7eedd806..9b485b9a8b 100644 --- a/src/systemd/sd-messages.h +++ b/src/systemd/sd-messages.h @@ -31,6 +31,7 @@ extern "C" { #define SD_MESSAGE_JOURNAL_START SD_ID128_MAKE(f7,73,79,a8,49,0b,40,8b,be,5f,69,40,50,5a,77,7b) #define SD_MESSAGE_JOURNAL_STOP SD_ID128_MAKE(d9,3f,b3,c9,c2,4d,45,1a,97,ce,a6,15,ce,59,c0,0b) #define SD_MESSAGE_JOURNAL_DROPPED SD_ID128_MAKE(a5,96,d6,fe,7b,fa,49,94,82,8e,72,30,9e,95,d6,1e) +#define SD_MESSAGE_JOURNAL_MISSED SD_ID128_MAKE(e9,bf,28,e6,e8,34,48,1b,b6,f4,8f,54,8a,d1,36,06) #define SD_MESSAGE_COREDUMP SD_ID128_MAKE(fc,2e,22,bc,6e,e6,47,b6,b9,07,29,ab,34,a2,50,b1) |