From 156323ef47484025abe812d9b73d0b953e1e070e Mon Sep 17 00:00:00 2001 From: Aucoto Zhang Date: Thu, 29 Oct 2026 09:26:32 +0800 Subject: [PATCH] logging: keep only log-max-files backup files when rotating With --log-rotate and --log-max-files 1, shift_backup_files() started its renaming loop at 2, moving .1 to .2 on every rotation. Together with the current log becoming .1, two backup files were left behind although only one was configured, so the log space used exceeded --log-max-files. Start the loop at opt_log_max_files directly: with log-max-files == 1 the loop does not run and the old .1 backup is atomically replaced by the rename() in perform_file_rotation(), keeping exactly one backup. Behavior for log-max-files >= 2 is unchanged. A regression test runs a container that produces enough output to rotate the log several times and asserts that only the .1 backup file is left behind. Fixes: 61c8da9 ("Add log rotation functionality as alternative to log truncation") Signed-off-by: Aucoto Zhang Co-Authored-By: AtomCode (glm-5.3) --- src/ctr_logging.c | 4 +--- test/02-ctr-logs.bats | 12 ++++++++++++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/ctr_logging.c b/src/ctr_logging.c index 33356afb..deff65ba 100644 --- a/src/ctr_logging.c +++ b/src/ctr_logging.c @@ -1038,9 +1038,7 @@ static gboolean shift_backup_files(void) close(validation_fd); /* Shift existing backups from highest to lowest: .N-1 -> .N, .N-2 -> .N-1, etc. */ - int loop_start = (opt_log_max_files > 1) ? opt_log_max_files : 2; - - for (int i = loop_start; i >= 2; i--) { + for (int i = opt_log_max_files; i >= 2; i--) { _cleanup_free_ char *from = g_strdup_printf("%s.%d", k8s_log_path, i - 1); _cleanup_free_ char *to = g_strdup_printf("%s.%d", k8s_log_path, i); diff --git a/test/02-ctr-logs.bats b/test/02-ctr-logs.bats index 88f07052..4493c52c 100644 --- a/test/02-ctr-logs.bats +++ b/test/02-ctr-logs.bats @@ -172,3 +172,15 @@ run_conmon_with_log_opts() { run cat "$LOG_PATH" assert "${output}" =~ "stdout P" } + +@test "ctr logs: should keep only log-max-files backup files" { + # The container's output rotates the 1024-byte log several times over, so + # with --log-max-files 1 a backup must exist, and it must be the only one + # left: rotation must atomically replace .1, not shift it to .2. + run_conmon_with_default_args \ + --log-path "k8s-file:$LOG_PATH" \ + --log-rotate --log-max-files 1 --log-size-max 1024 + + backups=("$LOG_PATH".*) + assert "${backups[*]}" == "$LOG_PATH.1" "only one backup file is left" +}