From: Vito Caputo Date: Sat, 14 Nov 2020 22:06:48 +0000 (-0800) Subject: journal-file: truncate archived journals X-Git-Tag: v249-rc1~64 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=592d419ce6e283c443901be4a69c95984821ff06;p=thirdparty%2Fsystemd.git journal-file: truncate archived journals 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 --- diff --git a/src/libsystemd/sd-journal/journal-file.c b/src/libsystemd/sd-journal/journal-file.c index 5f63633bf17..03c2c50eccd 100644 --- a/src/libsystemd/sd-journal/journal-file.c +++ b/src/libsystemd/sd-journal/journal-file.c @@ -89,6 +89,41 @@ # 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)