]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
journal-file: truncate archived journals
authorVito Caputo <vcaputo@pengaru.com>
Sat, 14 Nov 2020 22:06:48 +0000 (14:06 -0800)
committerLennart Poettering <lennart@poettering.net>
Tue, 8 Jun 2021 19:36:47 +0000 (21:36 +0200)
Journal files have space allocated in 8MiB-aligned increments.

This can add up to substantial wasted space as many archived journals
accumulate without using all the allocated space.

This commit introduces truncating to the offset a subsequent append
would get written at when archiving.

Fixes https://github.com/systemd/systemd/issues/17613

src/libsystemd/sd-journal/journal-file.c

index 5f63633bf1796a3cc0be80a6e7f751cad2cb24ba..03c2c50eccd1731b776293b0020e4fa1d252c06c 100644 (file)
 #  pragma GCC diagnostic ignored "-Waddress-of-packed-member"
 #endif
 
+static int journal_file_tail_end(JournalFile *f, uint64_t *ret_offset) {
+        Object *tail;
+        uint64_t p;
+        int r;
+
+        assert(f);
+        assert(f->header);
+        assert(ret_offset);
+
+        p = le64toh(f->header->tail_object_offset);
+        if (p == 0)
+                p = le64toh(f->header->header_size);
+        else {
+                uint64_t sz;
+
+                r = journal_file_move_to_object(f, OBJECT_UNUSED, p, &tail);
+                if (r < 0)
+                        return r;
+
+                sz = le64toh(READ_NOW(tail->object.size));
+                if (sz > UINT64_MAX - sizeof(uint64_t) + 1)
+                        return -EBADMSG;
+
+                sz = ALIGN64(sz);
+                if (p > UINT64_MAX - sz)
+                        return -EBADMSG;
+
+                p += sz;
+        }
+
+        *ret_offset = p;
+
+        return 0;
+}
+
 /* This may be called from a separate thread to prevent blocking the caller for the duration of fsync().
  * As a result we use atomic operations on f->offline_state for inter-thread communications with
  * journal_file_set_offline() and journal_file_set_online(). */
@@ -122,6 +157,25 @@ static void journal_file_set_offline_internal(JournalFile *f) {
 
                         f->header->state = f->archive ? STATE_ARCHIVED : STATE_OFFLINE;
                         (void) fsync(f->fd);
+
+                        if (f->archive) {
+                                uint64_t p;
+                                int r;
+
+                                /* truncate excess from the end of archives */
+                                r = journal_file_tail_end(f, &p);
+                                if (r < 0)
+                                        log_debug_errno(r, "Failed to determine end of tail object, ignoring: %m");
+                                else {
+                                        /* arena_size can't exceed the file size, ensure it's updated before truncating */
+                                        f->header->arena_size = htole64(p - le64toh(f->header->header_size));
+
+                                        (void) fsync(f->fd);
+
+                                        if (ftruncate(f->fd, p) < 0)
+                                                log_debug_errno(errno, "Failed to truncate archive at end of tail object, ignoring: %m");
+                                }
+                        }
                         break;
 
                 case OFFLINE_OFFLINING:
@@ -1054,7 +1108,7 @@ int journal_file_append_object(
 
         int r;
         uint64_t p;
-        Object *tail, *o;
+        Object *o;
         void *t;
 
         assert(f);
@@ -1066,26 +1120,9 @@ int journal_file_append_object(
         if (r < 0)
                 return r;
 
-        p = le64toh(f->header->tail_object_offset);
-        if (p == 0)
-                p = le64toh(f->header->header_size);
-        else {
-                uint64_t sz;
-
-                r = journal_file_move_to_object(f, OBJECT_UNUSED, p, &tail);
-                if (r < 0)
-                        return r;
-
-                sz = le64toh(READ_NOW(tail->object.size));
-                if (sz > UINT64_MAX - sizeof(uint64_t) + 1)
-                        return -EBADMSG;
-
-                sz = ALIGN64(sz);
-                if (p > UINT64_MAX - sz)
-                        return -EBADMSG;
-
-                p += sz;
-        }
+        r = journal_file_tail_end(f, &p);
+        if (r < 0)
+                return r;
 
         r = journal_file_allocate(f, p, size);
         if (r < 0)