From 55a0bb88563716672b78e8c17516321a0445bff6 Mon Sep 17 00:00:00 2001 From: Kelvin Zhang Date: Thu, 25 May 2023 17:45:21 -0700 Subject: [PATCH] Rotate logs on every boot Currently, recovery-persist only rotates the logs if it can parse /sys/fs/pstore/pmsg-ramoops-0 . Change this behavior to always rotate last kernel log if present. This helps collect more debug logs when troubleshooting boot failures. Test: reboot device, make sure logs are rotated Change-Id: I41da2eda3c6c241e90208af888e9e35bec0474fe --- recovery-persist.cpp | 58 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/recovery-persist.cpp b/recovery-persist.cpp index 55699b24..b5bb8011 100644 --- a/recovery-persist.cpp +++ b/recovery-persist.cpp @@ -35,10 +35,12 @@ #include #include +#include #include #include #include +#include #include /* private pmsg functions */ #include "recovery_utils/logging.h" @@ -114,6 +116,59 @@ ssize_t logsave( return android::base::WriteStringToFile(buffer, destination.c_str()); } +size_t file_size(const char* path) { + struct stat st {}; + if (stat(path, &st) < 0) { + return 0; + } + + return st.st_size; +} + +bool compare_file(const char* file1, const char* file2) { + if (!file_exists(file1) || !file_exists(file2)) { + return false; + } + if (file_size(file1) != file_size(file2)) { + return false; + } + std::array buf1{}; + std::array buf2{}; + android::base::unique_fd fd1(open(file1, O_RDONLY)); + android::base::unique_fd fd2(open(file2, O_RDONLY)); + auto bytes_remain = file_size(file1); + while (bytes_remain > 0) { + const auto bytes_to_read = std::min(bytes_remain, buf1.size()); + + if (!android::base::ReadFully(fd1, buf1.data(), bytes_to_read)) { + LOG(ERROR) << "Failed to read from " << file1; + return false; + } + if (!android::base::ReadFully(fd2, buf2.data(), bytes_to_read)) { + LOG(ERROR) << "Failed to read from " << file2; + return false; + } + if (memcmp(buf1.data(), buf2.data(), bytes_to_read) != 0) { + return false; + } + } + return true; +} + +void rotate_last_kmsg() { + if (rotated) { + return; + } + if (!file_exists(LAST_CONSOLE_FILE) && !file_exists(ALT_LAST_CONSOLE_FILE)) { + return; + } + if (!compare_file(LAST_KMSG_FILE, LAST_CONSOLE_FILE) && + !compare_file(LAST_KMSG_FILE, ALT_LAST_CONSOLE_FILE)) { + rotate_logs(LAST_LOG_FILE, LAST_KMSG_FILE); + rotated = true; + } +} + int main(int argc, char **argv) { /* Is /cache a mount?, we have been delivered where we are not wanted */ @@ -131,7 +186,7 @@ int main(int argc, char **argv) { } else { char *line = NULL; size_t len = 0; - ssize_t read; + ssize_t read{}; while ((read = getline(&line, &len, fp)) != -1) { if (strstr(line, " /cache ")) { has_cache = true; @@ -172,6 +227,7 @@ int main(int argc, char **argv) { PLOG(ERROR) << "Failed to unlink " << LAST_INSTALL_FILE; } } + rotate_last_kmsg(); /* Is there a last console log too? */ if (rotated) {