tdecacqu / rpms / systemd

Forked from rpms/systemd 3 years ago
Clone
Blob Blame History Raw
From a2c483fc0b311519da3dc853c94989450052ec52 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Mon, 24 Jun 2013 21:00:28 -0400
Subject: [PATCH] journald: always vacuum empty offline files

Corrupted empty files are relatively common. I think they are created
when a coredump for a user who never logged anything before is
attempted to be written, but the write does not succeed because the
coredump is too big, but there are probably other ways to create
those, especially if the machine crashes at the right time.
Non-corrupted empty files can also happen, e.g. if a journal file is
opened, but nothing is ever successfully written to it and it is
rotated because of MaxFileSec=. Either way, each "empty" journal file
costs around 3 MB, and there's little point in keeping them around.
---
 src/journal/journal-vacuum.c | 29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)

diff --git a/src/journal/journal-vacuum.c b/src/journal/journal-vacuum.c
index 1ddb043..79572f1 100644
--- a/src/journal/journal-vacuum.c
+++ b/src/journal/journal-vacuum.c
@@ -128,6 +128,24 @@ static void patch_realtime(
 #endif
 }
 
+static int journal_file_empty(int dir_fd, const char *name) {
+        int fd, r;
+        le64_t n_entries;
+
+        fd = openat(dir_fd, name, O_RDONLY|O_CLOEXEC|O_NOFOLLOW|O_NONBLOCK);
+        if (fd < 0)
+                return -errno;
+
+        if (lseek(fd, offsetof(Header, n_entries), SEEK_SET) < 0)
+                return -errno;
+
+        r = read(fd, &n_entries, sizeof(n_entries));
+        if (r != sizeof(n_entries))
+                return r == 0 ? -EINVAL : -errno;
+
+        return le64toh(n_entries) == 0;
+}
+
 int journal_directory_vacuum(
                 const char *directory,
                 uint64_t max_use,
@@ -247,6 +265,17 @@ int journal_directory_vacuum(
                         /* We do not vacuum active files or unknown files! */
                         continue;
 
+                if (journal_file_empty(dirfd(d), de->d_name)) {
+
+                        /* Always vacuum empty non-online files. */
+
+                        if (unlinkat(dirfd(d), de->d_name, 0) >= 0)
+                                log_debug("Deleted empty journal %s/%s.", directory, de->d_name);
+                        else if (errno != ENOENT)
+                                log_warning("Failed to delete %s/%s: %m", directory, de->d_name);
+                        continue;
+                }
+
                 patch_realtime(directory, de->d_name, &st, &realtime);
 
                 GREEDY_REALLOC(list, n_allocated, n_list + 1);