From 57c4817fabd186777dfccfb9896800b1a333bbe1 Mon Sep 17 00:00:00 2001 From: Michal Bloch Date: Thu, 22 Nov 2018 20:17:42 +0100 Subject: [PATCH] dlog_logger: read /dev/kmsg in a throttled loop KMSG only returns one entry per read() - do it in a throttled loop for efficiency. This is similar to how Android Logger devices are handled. Change-Id: I0f95dc657898a9d68bcfd96f9d2e2daab5814176 Signed-off-by: Michal Bloch --- src/logger/logger.c | 48 +++++++++++++++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/src/logger/logger.c b/src/logger/logger.c index 158915e..811435d 100644 --- a/src/logger/logger.c +++ b/src/logger/logger.c @@ -572,7 +572,7 @@ static int service_socket_dummy(struct logger *server, struct writer *wr, struct */ static int create_kmsg_writer(struct writer ** writer, struct log_buffer *log_buffer) { - int fd = open("/dev/kmsg", O_RDONLY); + int fd = open("/dev/kmsg", O_RDONLY | O_NONBLOCK); if (fd < 0) return -errno; return writer_create(writer, fd, log_buffer, service_writer_kmsg, service_socket_dummy); @@ -1578,25 +1578,39 @@ static int service_writer_kmsg(struct logger* server, struct writer* wr, struct if (!(event->events & EPOLLIN)) return 0; - int r = read(wr->fd_entity.fd, wr->buffer, sizeof wr->buffer - 1); + /* The KMSG device returns just 1 log per read() so it is done in a loop. + * In theory this could starve everything else out if logs appeared faster + * than the daemon could process them, which would then necessitate some + * sort of throttling. In practice, KMSG doesn't really get flooded with + * logs the same way Android Logger devices are so the throttling is mostly + * there because we get it for free anyway and consistency doesn't hurt. */ - if (r == -1 && (errno == EAGAIN || errno == EPIPE)) - return 0; - else if ((r == 0 || r == -1) && event->events & EPOLLHUP) - return -EINVAL; - else if (r == 0) - return -EBADF; - else if (r == -1) - return -errno; + int max_loop_iterations = g_backend.logger_device_throttling[LOG_ID_KMSG]; + while (max_loop_iterations--) { + int r = read(wr->fd_entity.fd, wr->buffer, sizeof wr->buffer - 1); - wr->buffer[r] = '\0'; - struct logger_entry_with_msg lem; - if (parse_kmsg_message(wr->buffer, &lem, r)) { - // don't signal an error: KMSG writer is too important to remove; besides, it would not get fixed that way. - return 0; + if (r == -1 && (errno == EAGAIN || errno == EPIPE)) + return 0; + else if ((r == 0 || r == -1) && event->events & EPOLLHUP) + return -EINVAL; + else if (r == 0) + return -EBADF; + else if (r == -1) + return -errno; + + wr->buffer[r] = '\0'; + struct logger_entry_with_msg lem; + if (parse_kmsg_message(wr->buffer, &lem, r)) { + // don't signal an error: KMSG writer is too important to remove; besides, it would not get fixed that way. + return 0; + } + add_recv_timestamp(&lem.header); + r = buffer_append(&lem.header, wr->buf_ptr); + if (r < 0) + return r; } - add_recv_timestamp(&lem.header); - return buffer_append(&lem.header, wr->buf_ptr); + + return 0; } /** -- 2.7.4