dlog_logger: read /dev/kmsg in a throttled loop 26/193726/3
authorMichal Bloch <m.bloch@samsung.com>
Thu, 22 Nov 2018 19:17:42 +0000 (20:17 +0100)
committerHyotaek Shim <hyotaek.shim@samsung.com>
Thu, 29 Nov 2018 00:46:46 +0000 (00:46 +0000)
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 <m.bloch@samsung.com>
src/logger/logger.c

index 158915e..811435d 100644 (file)
@@ -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;
 }
 
 /**