From 234c0d1924f3751ddedcada63f1ec67ac06f5304 Mon Sep 17 00:00:00 2001 From: Michal Bloch Date: Tue, 23 Jan 2024 12:41:01 +0100 Subject: [PATCH] dlog_logger: handle zero-copy backend Change-Id: I13168087ef460e74c203ab0f0311b91f6f2421f2 --- Makefile.am | 2 + src/logger/logger.c | 45 +++++++++++++++-- src/logger/logger_internal.h | 7 +++ src/logger/reader_zero_copy.c | 111 ++++++++++++++++++++++++++++++++++++++++++ src/logger/reader_zero_copy.h | 18 +++++++ 5 files changed, 179 insertions(+), 4 deletions(-) create mode 100644 src/logger/reader_zero_copy.c create mode 100644 src/logger/reader_zero_copy.h diff --git a/Makefile.am b/Makefile.am index 0628605..85735ab 100644 --- a/Makefile.am +++ b/Makefile.am @@ -163,12 +163,14 @@ dlog_logger_SOURCES = \ src/logger/reader_logger.c \ src/logger/reader_pipe.c \ src/logger/reader_memory.c \ + src/logger/reader_zero_copy.c \ src/logger/subreader_dlogutil.c \ src/logger/subreader_file.c \ src/logger/subreader_memory.c \ src/logger/subreader_metrics.c \ src/logger/socket.c \ src/logger/writer.c \ + src/libdlogutil/fdi_zero_copy.c \ src/shared/backend_androidlogger.c \ src/shared/buffer_traits.c \ src/shared/ptrs_list.c \ diff --git a/src/logger/logger.c b/src/logger/logger.c index 286ccb5..3377c0f 100644 --- a/src/logger/logger.c +++ b/src/logger/logger.c @@ -548,6 +548,24 @@ int logger_create(struct logger_config_data *data, struct logger *l, struct sign // If no path, assume first time first_time = true; + if (g_backend.use_zero_copy) { + assert(!g_backend.zero_copy_reader); + int r = reader_zero_copy_init(&g_backend.zero_copy_reader, l, !first_time); + if (r < 0) + return r; + + assert(g_backend.zero_copy_reader); + + if (l->qos) { + r = reader_add_subreader_metrics(&g_backend.zero_copy_reader->common, l->qos); + if (r < 0) { + reader_free(&g_backend.zero_copy_reader->common); + g_backend.zero_copy_reader = NULL; + return r; + } + } + } + if (g_backend.use_logger_by_default) for (log_id_t id = 0; id < LOG_ID_MAX; ++id) { if (!is_core_buffer(id)) @@ -877,8 +895,10 @@ int prepare_config_data(struct logger_config_data *data) if (is_core_buffer(i)) data->is_buffer_enabled[i] = true; g_backend.use_logger_by_default = false; + g_backend.use_zero_copy = false; } else if (!strcmp(backend, "logger")) { g_backend.use_logger_by_default = true; + g_backend.use_zero_copy = false; for (log_id_t buf_id = 0; buf_id < LOG_ID_MAX; ++buf_id) { const char *const logger_device = log_config_get(&conf, log_name_by_id(buf_id)); if (!logger_device) @@ -899,11 +919,8 @@ int prepare_config_data(struct logger_config_data *data) g_backend.lazy_polling_sleep = 1; } else if (!strcmp(backend, "zero-copy")) { - /* At some point the daemon should learn how to read external - * logs for the purpose of writing persistent /var/log/files. - * - * For now, let it just handle KMSG. */ g_backend.use_logger_by_default = false; + g_backend.use_zero_copy = true; } else { ret = -ENOENT; goto end; @@ -985,6 +1002,20 @@ void parse_logfile_config(void *value, void *userdata) /* The reader is not yet complete, further subreaders can get added via other config lines. * Finalisation happens later, in `finalize_init`. */ + } else if (g_backend.use_zero_copy && core) { + if (!g_backend.zero_copy_reader) { + r = -ENOENT; + goto fail; + } + + r = params.compression + ? create_memory_subreader_from_dlogutil_line(&g_backend.zero_copy_reader->common, ¶ms, server) + : create_file_subreader_from_dlogutil_line(&g_backend.zero_copy_reader->common, ¶ms, DLOGUTIL_SORT_SENT_MONO) + ; + if (r) + goto fail; + + // ditto } else { struct reader_pipe *reader = NULL; r = create_reader_pipe_from_dlogutil_line(¶ms, server, &reader); @@ -1158,6 +1189,12 @@ static int finalize_init(struct logger_config_data *data, struct logger *server) return r; } + if (g_backend.zero_copy_reader) { + r = reader_cleanup_subless_and_run(&g_backend.zero_copy_reader, server); + if (r < 0) + return r; + } + return 0; } diff --git a/src/logger/logger_internal.h b/src/logger/logger_internal.h index f0c4387..98e3596 100644 --- a/src/logger/logger_internal.h +++ b/src/logger/logger_internal.h @@ -31,6 +31,7 @@ #include "fd_entity.h" #include "reader_common.h" #include "reader_logger.h" +#include "reader_zero_copy.h" #include "reader_memory.h" #include "reader_pipe.h" #include "socket.h" @@ -103,6 +104,12 @@ extern struct backend_data { * and to unclog pipes. */ int lazy_polling_total; int lazy_polling_sleep; + + /* I'm not exactly happy with this struct having grown into just + * a collection of globals but I am out of mana to prevent it. */ + bool use_zero_copy; + struct reader_zero_copy *zero_copy_reader; + } g_backend; diff --git a/src/logger/reader_zero_copy.c b/src/logger/reader_zero_copy.c new file mode 100644 index 0000000..52924a5 --- /dev/null +++ b/src/logger/reader_zero_copy.c @@ -0,0 +1,111 @@ +// SPDX-License-Identifier: Apache 2.0 +// (c) 2024 Samsung Electronics + +// POSIX +#include +#include + +// DLog +#include +#include +#include + +// dlog_logger +#include "logger_internal.h" +#include "reader_common.h" +#include "reader_zero_copy.h" + +static void *reader_zero_copy_thread(void *userdata); + +static void free_reader_zero_copy(struct reader_common *_reader) +{ + struct reader_zero_copy *const reader = (struct reader_zero_copy *) _reader; + assert(reader); +} + +static const struct reader_ops zero_copy_ops = (struct reader_ops) { + .destroy = free_reader_zero_copy, + .thread_func = reader_zero_copy_thread, +}; + +static struct reader_zero_copy *reader_zero_copy_alloc(struct logger *server) +{ + __attribute__((cleanup(free_ptr))) uint16_t *last_offsets = calloc(ZLOGGER_BLOCK_COUNT, sizeof *last_offsets); + if (!last_offsets) + return NULL; + + __attribute__((cleanup(free_ptr))) char *bitmap = malloc(ZLOGGER_BITMAP_SIZE); + if (!bitmap) + return NULL; + + __attribute__((cleanup(close_fd))) int fd = open(ZERO_COPY_DUMP_DEVICE_NAME, O_RDONLY | O_CLOEXEC); + if (fd < 0) + return NULL; + + struct reader_zero_copy *const reader = calloc(1, sizeof *reader); + if (!reader) + return NULL; + + reader->bitmap = bitmap; + reader->last_offsets = last_offsets; + reader->fd = fd; + + fd = -1; + last_offsets = NULL; + bitmap = NULL; + + return reader; +} + +int reader_zero_copy_init(struct reader_zero_copy **reader, struct logger *server, bool skip) +{ + __attribute__((cleanup(reader_free_ptr))) struct reader_zero_copy *ret = reader_zero_copy_alloc(server); + if (!ret) + return -ENOMEM; + + reader_common_init(&ret->common, server, &zero_copy_ops); + + ret->dump_initial = !skip; + + *reader = ret; + ret = NULL; + + return 0; +} + +static void dump_logs_as_indicated_by_bitmap(struct reader_zero_copy *reader) +{ + int r = zero_copy_read_buffer(reader->fd, &reader->items, reader->bitmap, reader->last_offsets); + assert(r != -EAGAIN); + + while (reader->items) { + struct zlog_entry_list *const item = reader->items; + reader->items = item->next; + + dlogutil_entry_s *const entry = item->entry; + (void) reader_apply_log_to_subs(&reader->common, entry); + free(item); + } +} + +static void *reader_zero_copy_thread(void *userdata) +{ + struct reader_zero_copy *reader = (struct reader_zero_copy *) userdata; + + if (reader->dump_initial) { + memset(reader->bitmap, ~(char)0, ZLOGGER_BITMAP_SIZE); + dump_logs_as_indicated_by_bitmap(reader); + } + + const int period = reader->common.server->epolltime * USEC_PER_MSEC; + while (!reader->common.server->sigmar->exit_signal_received) { + (void) ioctl(reader->fd, ZLOGGER_IOCTL_COMMAND_GET_BITMAP, reader->bitmap); + dump_logs_as_indicated_by_bitmap(reader); + usleep (period); + } + + reader_service(&reader->common); + reader_thread_finished(&reader->common); + return NULL; +} + diff --git a/src/logger/reader_zero_copy.h b/src/logger/reader_zero_copy.h new file mode 100644 index 0000000..16a9514 --- /dev/null +++ b/src/logger/reader_zero_copy.h @@ -0,0 +1,18 @@ +#pragma once + +#include +#include +#include "reader_common.h" +#include "../libdlogutil/fdi_zero_copy.h" + +struct reader_zero_copy { + struct reader_common common; + struct zlog_entry_list *items; + uint16_t *last_offsets; + char *bitmap; + int fd; + bool dump_initial; +}; + +int reader_zero_copy_init(struct reader_zero_copy **reader, struct logger *server, bool skip); + -- 2.7.4