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
This commit is contained in:
Vito Caputo
2021-06-08 21:36:47 +02:00
committed by Lennart Poettering
parent 7f7a50dd15
commit 592d419ce6
+58 -21
View File
@@ -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)