From 202fd896e516bbd7379bf2e2bcc224d3ec2356cd Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 11 Oct 2016 19:12:41 +0200 Subject: journal: when we encounter a broken journal file, add some debug logging Let's make it easier to figure out when we see an invalid journal file, why we consider it invalid, and add some minimal debug logging for it. This log output is normally not seen (after all, this all is library code), unless debug logging is exlicitly turned on. --- src/journal/journal-file.c | 24 ++++++++++++++++++------ src/journal/journalctl.c | 4 +++- 2 files changed, 21 insertions(+), 7 deletions(-) (limited to 'src/journal') diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index 349ef74e81..953f4e5ce6 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -747,12 +747,16 @@ int journal_file_move_to_object(JournalFile *f, ObjectType type, uint64_t offset assert(ret); /* Objects may only be located at multiple of 64 bit */ - if (!VALID64(offset)) + if (!VALID64(offset)) { + log_debug("Attempt to move to object at non-64bit boundary: %" PRIu64, offset); return -EBADMSG; + } /* Object may not be located in the file header */ - if (offset < le64toh(f->header->header_size)) + if (offset < le64toh(f->header->header_size)) { + log_debug("Attempt to move to object located in file header: %" PRIu64, offset); return -EBADMSG; + } r = journal_file_move_to(f, type, false, offset, sizeof(ObjectHeader), &t); if (r < 0) @@ -761,17 +765,25 @@ int journal_file_move_to_object(JournalFile *f, ObjectType type, uint64_t offset o = (Object*) t; s = le64toh(o->object.size); - if (s < sizeof(ObjectHeader)) + if (s < sizeof(ObjectHeader)) { + log_debug("Attempt to move to overly short object: %" PRIu64, offset); return -EBADMSG; + } - if (o->object.type <= OBJECT_UNUSED) + if (o->object.type <= OBJECT_UNUSED) { + log_debug("Attempt to move to object with invalid type: %" PRIu64, offset); return -EBADMSG; + } - if (s < minimum_header_size(o)) + if (s < minimum_header_size(o)) { + log_debug("Attempt to move to truncated object: %" PRIu64, offset); return -EBADMSG; + } - if (type > OBJECT_UNUSED && o->object.type != type) + if (type > OBJECT_UNUSED && o->object.type != type) { + log_debug("Attempt to move to object of unexpected type: %" PRIu64, offset); return -EBADMSG; + } if (s > sizeof(ObjectHeader)) { r = journal_file_move_to(f, type, false, offset, s, &t); diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 13e3b44f06..f753435888 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -1091,8 +1091,10 @@ static int discover_next_boot(sd_journal *j, r = sd_journal_previous(j); if (r < 0) return r; - else if (r == 0) + else if (r == 0) { + log_debug("Whoopsie! We found a boot ID but can't read its last entry."); return -ENODATA; /* This shouldn't happen. We just came from this very boot ID. */ + } r = sd_journal_get_realtime_usec(j, &next_boot->last); if (r < 0) -- cgit v1.2.3-54-g00ecf From aa598ba5b63b70273d6295fce3cb8c304716a205 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 12 Oct 2016 11:54:36 +0200 Subject: journal: split out array index inc/dec code into a new call bump_array_index() This allows us to share a bit more code between journal_file_next_entry() and journal_file_next_entry_for_data(). --- src/journal/journal-file.c | 48 ++++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 23 deletions(-) (limited to 'src/journal') diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index 953f4e5ce6..8e47ebb944 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -2484,6 +2484,25 @@ int journal_file_compare_locations(JournalFile *af, JournalFile *bf) { return 0; } +static int bump_array_index(uint64_t *i, direction_t direction, uint64_t n) { + + /* Increase or decrease the specified index, in the right direction. */ + + if (direction == DIRECTION_DOWN) { + if (*i >= n - 1) + return 0; + + (*i) ++; + } else { + if (*i <= 0) + return 0; + + (*i) --; + } + + return 1; +} + int journal_file_next_entry( JournalFile *f, uint64_t p, @@ -2514,17 +2533,9 @@ int journal_file_next_entry( if (r <= 0) return r; - if (direction == DIRECTION_DOWN) { - if (i >= n - 1) - return 0; - - i++; - } else { - if (i <= 0) - return 0; - - i--; - } + r = bump_array_index(&i, direction, n); + if (r <= 0) + return r; } /* And jump to it */ @@ -2594,18 +2605,9 @@ int journal_file_next_entry_for_data( if (r <= 0) return r; - if (direction == DIRECTION_DOWN) { - if (i >= n - 1) - return 0; - - i++; - } else { - if (i <= 0) - return 0; - - i--; - } - + r = bump_array_index(&i, direction, n); + if (r <= 0) + return r; } return generic_array_get_plus_one(f, -- cgit v1.2.3-54-g00ecf From b6da4ed0450ced53a911d974c8b1da6ad9ff212a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 12 Oct 2016 12:12:05 +0200 Subject: journal: split out check for properly ordered arrays into its own function This adds a new call check_properly_ordered(), which we can reuse later, and makes the code a bit more readable. --- src/journal/journal-file.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'src/journal') diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index 8e47ebb944..52562cd0b8 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -2503,6 +2503,18 @@ static int bump_array_index(uint64_t *i, direction_t direction, uint64_t n) { return 1; } +static bool check_properly_ordered(uint64_t new_offset, uint64_t old_offset, direction_t direction) { + + /* Consider it an error if any of the two offsets is uninitialized */ + if (old_offset == 0 || new_offset == 0) + return false; + + /* If we go down, the new offset must be larger than the old one. */ + return direction == DIRECTION_DOWN ? + new_offset > old_offset : + new_offset < old_offset; +} + int journal_file_next_entry( JournalFile *f, uint64_t p, @@ -2552,9 +2564,9 @@ int journal_file_next_entry( if (r <= 0) return r; - if (p > 0 && - (direction == DIRECTION_DOWN ? ofs <= p : ofs >= p)) { - log_debug("%s: entry array corrupted at entry %" PRIu64, f->path, i); + /* Ensure our array is properly ordered. */ + if (p > 0 && !check_properly_ordered(ofs, p, direction)) { + log_debug("%s: entry array not properly ordered at entry %" PRIu64, f->path, i); return -EBADMSG; } -- cgit v1.2.3-54-g00ecf From ded5034e7a3e7b3330bbe4f5dd13ca994785d6cb Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 12 Oct 2016 12:12:58 +0200 Subject: journal: also check that our entry arrays are properly ordered Let's and extra check, reusing check_properly_ordered() also for journal_file_next_entry_for_data(). --- src/journal/journal-file.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) (limited to 'src/journal') diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index 52562cd0b8..f59858277e 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -2583,7 +2583,7 @@ int journal_file_next_entry_for_data( direction_t direction, Object **ret, uint64_t *offset) { - uint64_t n, i; + uint64_t i, n, ofs; int r; Object *d; @@ -2622,11 +2622,24 @@ int journal_file_next_entry_for_data( return r; } - return generic_array_get_plus_one(f, - le64toh(d->data.entry_offset), - le64toh(d->data.entry_array_offset), - i, - ret, offset); + r = generic_array_get_plus_one(f, + le64toh(d->data.entry_offset), + le64toh(d->data.entry_array_offset), + i, + ret, &ofs); + if (r <= 0) + return r; + + /* Ensure our array is properly ordered. */ + if (p > 0 && check_properly_ordered(ofs, p, direction)) { + log_debug("%s data entry array not properly ordered at entry %" PRIu64, f->path, i); + return -EBADMSG; + } + + if (offset) + *offset = ofs; + + return 1; } int journal_file_move_to_entry_by_offset_for_data( -- cgit v1.2.3-54-g00ecf From 1c69f0966a86e3c9ae0120e6222709414b68e186 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 12 Oct 2016 12:22:57 +0200 Subject: journal: add an explicit check for uninitialized objects Let's make dissecting of borked journal files more expressive: if we encounter an object whose first 8 bytes are all zeroes, then let's assume the object was simply never initialized, and say so. Previously, this would be detected as "overly short object", which is true too in a away, but it's a lot more helpful printing different debug options for the case where the size is not initialized at all and where the size is initialized to some bogus value. No function behaviour change, only a different log messages for both cases. --- src/journal/journal-file.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/journal') diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index f59858277e..3f1afdaf1f 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -765,6 +765,10 @@ int journal_file_move_to_object(JournalFile *f, ObjectType type, uint64_t offset o = (Object*) t; s = le64toh(o->object.size); + if (s == 0) { + log_debug("Attempt to move to uninitialized object: %" PRIu64, offset); + return -EBADMSG; + } if (s < sizeof(ObjectHeader)) { log_debug("Attempt to move to overly short object: %" PRIu64, offset); return -EBADMSG; -- cgit v1.2.3-54-g00ecf From 989793d341e730f452175fa18cf0f7ef4529d62c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 12 Oct 2016 12:36:01 +0200 Subject: journal: when iterating through entry arrays and we hit an invalid one keep going When iterating through partially synced journal files we need to be prepared for hitting with invalid entries (specifically: non-initialized). Instead of generated an error and giving up, let's simply try to preceed with the next one that is valid (and debug log about this). This reworks the logic introduced with caeab8f626e709569cc492b75eb7e119076059e7 to iteration in both directions, and tries to look for valid entries located after the invalid one. It also extends the behaviour to both iterating through the global entry array and per-data object entry arrays. Fixes: #4088 --- src/journal/journal-file.c | 54 ++++++++++++++++++++++++++++++---------------- 1 file changed, 35 insertions(+), 19 deletions(-) (limited to 'src/journal') diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index 3f1afdaf1f..e26c8223d8 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -2555,18 +2555,24 @@ int journal_file_next_entry( } /* And jump to it */ - r = generic_array_get(f, - le64toh(f->header->entry_array_offset), - i, - ret, &ofs); - if (r == -EBADMSG && direction == DIRECTION_DOWN) { - /* Special case: when we iterate throught the journal file linearly, and hit an entry we can't read, - * consider this the end of the journal file. */ - log_debug_errno(r, "Encountered entry we can't read while iterating through journal file. Considering this the end of the file."); - return 0; + for (;;) { + r = generic_array_get(f, + le64toh(f->header->entry_array_offset), + i, + ret, &ofs); + if (r > 0) + break; + if (r != -EBADMSG) + return r; + + /* OK, so this entry is borked. Most likely some entry didn't get synced to disk properly, let's see if + * the next one might work for us instead. */ + log_debug_errno(r, "Entry item %" PRIu64 " is bad, skipping over it.", i); + + r = bump_array_index(&i, direction, n); + if (r <= 0) + return r; } - if (r <= 0) - return r; /* Ensure our array is properly ordered. */ if (p > 0 && !check_properly_ordered(ofs, p, direction)) { @@ -2588,8 +2594,8 @@ int journal_file_next_entry_for_data( Object **ret, uint64_t *offset) { uint64_t i, n, ofs; - int r; Object *d; + int r; assert(f); assert(p > 0 || !o); @@ -2626,13 +2632,23 @@ int journal_file_next_entry_for_data( return r; } - r = generic_array_get_plus_one(f, - le64toh(d->data.entry_offset), - le64toh(d->data.entry_array_offset), - i, - ret, &ofs); - if (r <= 0) - return r; + for (;;) { + r = generic_array_get_plus_one(f, + le64toh(d->data.entry_offset), + le64toh(d->data.entry_array_offset), + i, + ret, &ofs); + if (r > 0) + break; + if (r != -EBADMSG) + return r; + + log_debug_errno(r, "Data entry item %" PRIu64 " is bad, skipping over it.", i); + + r = bump_array_index(&i, direction, n); + if (r <= 0) + return r; + } /* Ensure our array is properly ordered. */ if (p > 0 && check_properly_ordered(ofs, p, direction)) { -- cgit v1.2.3-54-g00ecf From 0f972d66d439789afacbbcfba9a786965dd9e4b3 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 12 Oct 2016 18:46:07 +0200 Subject: journald: use the event loop dispatch timestamp for journal entries Let's use the earliest linearized event timestamp for journal entries we have: the event dispatch timestamp from the event loop, instead of requerying the timestamp at the time of writing. This makes the time a bit more accurate, allows us to query the kernel time one time less per event loop, and also makes sure we always use the same timestamp for both attempts to write an entry to a journal file. --- src/journal/journald-server.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'src/journal') diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index f01cf1d937..7227c80c86 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -627,14 +627,21 @@ static bool shall_try_append_again(JournalFile *f, int r) { } static void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, unsigned n, int priority) { - JournalFile *f; + struct dual_timestamp ts; bool vacuumed = false; + JournalFile *f; int r; assert(s); assert(iovec); assert(n > 0); + /* Get the closest, linearized time we have for this log event from the event loop. (Note that we do not use + * the source time, and not even the time the event was originally seen, but instead simply the time we started + * processing it, as we want strictly linear ordering in what we write out.) */ + assert_se(sd_event_now(s->event, CLOCK_REALTIME, &ts.realtime) >= 0); + assert_se(sd_event_now(s->event, CLOCK_MONOTONIC, &ts.monotonic) >= 0); + f = find_journal(s, uid); if (!f) return; @@ -650,7 +657,7 @@ static void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, unsigned return; } - r = journal_file_append_entry(f, NULL, iovec, n, &s->seqnum, NULL, NULL); + r = journal_file_append_entry(f, &ts, iovec, n, &s->seqnum, NULL, NULL); if (r >= 0) { server_schedule_sync(s, priority); return; @@ -669,7 +676,7 @@ static void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, unsigned return; log_debug("Retrying write."); - r = journal_file_append_entry(f, NULL, iovec, n, &s->seqnum, NULL, NULL); + r = journal_file_append_entry(f, &ts, iovec, n, &s->seqnum, NULL, NULL); if (r < 0) log_error_errno(r, "Failed to write entry (%d items, %zu bytes) despite vacuuming, ignoring: %m", n, IOVEC_TOTAL_SIZE(iovec, n)); else -- cgit v1.2.3-54-g00ecf From 7c07001711ee1f0aa7a3db7b63b354a4800cadcc Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 12 Oct 2016 18:49:51 +0200 Subject: journald: automatically rotate journal files when the clock jumps backwards As soon as we notice that the clock jumps backwards, rotate journal files. This is beneficial, as this makes sure that the entries in journal files remain strictly ordered internally, and thus the bisection algorithm applied on it is not confused. This should help avoiding borked wallclock-based bisection on journal files as witnessed in #4278. --- src/journal/journald-server.c | 29 +++++++++++++++++++++++------ src/journal/journald-server.h | 2 ++ 2 files changed, 25 insertions(+), 6 deletions(-) (limited to 'src/journal') diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index 7227c80c86..28aea35d18 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -627,8 +627,8 @@ static bool shall_try_append_again(JournalFile *f, int r) { } static void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, unsigned n, int priority) { + bool vacuumed = false, rotate = false; struct dual_timestamp ts; - bool vacuumed = false; JournalFile *f; int r; @@ -642,12 +642,27 @@ static void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, unsigned assert_se(sd_event_now(s->event, CLOCK_REALTIME, &ts.realtime) >= 0); assert_se(sd_event_now(s->event, CLOCK_MONOTONIC, &ts.monotonic) >= 0); - f = find_journal(s, uid); - if (!f) - return; + if (ts.realtime < s->last_realtime_clock) { + /* When the time jumps backwards, let's immediately rotate. Of course, this should not happen during + * regular operation. However, when it does happen, then we should make sure that we start fresh files + * to ensure that the entries in the journal files are strictly ordered by time, in order to ensure + * bisection works correctly. */ - if (journal_file_rotate_suggested(f, s->max_file_usec)) { - log_debug("%s: Journal header limits reached or header out-of-date, rotating.", f->path); + log_debug("Time jumped backwards, rotating."); + rotate = true; + } else { + + f = find_journal(s, uid); + if (!f) + return; + + if (journal_file_rotate_suggested(f, s->max_file_usec)) { + log_debug("%s: Journal header limits reached or header out-of-date, rotating.", f->path); + rotate = true; + } + } + + if (rotate) { server_rotate(s); server_vacuum(s, false, false); vacuumed = true; @@ -657,6 +672,8 @@ static void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, unsigned return; } + s->last_realtime_clock = ts.realtime; + r = journal_file_append_entry(f, &ts, iovec, n, &s->seqnum, NULL, NULL); if (r >= 0) { server_schedule_sync(s, priority); diff --git a/src/journal/journald-server.h b/src/journal/journald-server.h index dfb5724794..cc68a0a690 100644 --- a/src/journal/journald-server.h +++ b/src/journal/journald-server.h @@ -149,6 +149,8 @@ struct Server { char *cgroup_root; usec_t watchdog_usec; + + usec_t last_realtime_clock; }; #define SERVER_MACHINE_ID(s) ((s)->machine_id_field + strlen("_MACHINE_ID=")) -- cgit v1.2.3-54-g00ecf From ae739cc1edc7cfa9d1afb4b7087c434aadf61a7a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 12 Oct 2016 18:53:35 +0200 Subject: journal: refuse opening journal files from the future for writing Never permit that we write to journal files that have newer timestamps than our local wallclock has. If we'd accept that, then the entries in the file might end up not being ordered strictly. Let's refuse this with ETXTBSY, and then immediately rotate to use a new file, so that each file remains strictly ordered also be wallclock internally. --- src/journal/journal-file.c | 13 +++++++++++-- src/journal/journald-server.c | 12 ++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) (limited to 'src/journal') diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index e26c8223d8..49199b269f 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -568,8 +568,8 @@ static int journal_file_verify_header(JournalFile *f) { return -ENODATA; if (f->writable) { - uint8_t state; sd_id128_t machine_id; + uint8_t state; int r; r = sd_id128_get_machine(&machine_id); @@ -590,6 +590,14 @@ static int journal_file_verify_header(JournalFile *f) { log_debug("Journal file %s has unknown state %i.", f->path, state); return -EBUSY; } + + /* Don't permit appending to files from the future. Because otherwise the realtime timestamps wouldn't + * be strictly ordered in the entries in the file anymore, and we can't have that since it breaks + * bisection. */ + if (le64toh(f->header->tail_entry_realtime) > now(CLOCK_REALTIME)) { + log_debug("Journal file %s is from the future, refusing to append new data to it that'd be older.", f->path); + return -ETXTBSY; + } } f->compress_xz = JOURNAL_HEADER_COMPRESSED_XZ(f->header); @@ -3330,7 +3338,8 @@ int journal_file_open_reliably( -EBUSY, /* unclean shutdown */ -ESHUTDOWN, /* already archived */ -EIO, /* IO error, including SIGBUS on mmap */ - -EIDRM /* File has been deleted */)) + -EIDRM, /* File has been deleted */ + -ETXTBSY)) /* File is from the future */ return r; if ((flags & O_ACCMODE) == O_RDONLY) diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index 28aea35d18..3224bdbf5f 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -595,32 +595,44 @@ static void server_cache_hostname(Server *s) { static bool shall_try_append_again(JournalFile *f, int r) { switch(r) { + case -E2BIG: /* Hit configured limit */ case -EFBIG: /* Hit fs limit */ case -EDQUOT: /* Quota limit hit */ case -ENOSPC: /* Disk full */ log_debug("%s: Allocation limit reached, rotating.", f->path); return true; + case -EIO: /* I/O error of some kind (mmap) */ log_warning("%s: IO error, rotating.", f->path); return true; + case -EHOSTDOWN: /* Other machine */ log_info("%s: Journal file from other machine, rotating.", f->path); return true; + case -EBUSY: /* Unclean shutdown */ log_info("%s: Unclean shutdown, rotating.", f->path); return true; + case -EPROTONOSUPPORT: /* Unsupported feature */ log_info("%s: Unsupported feature, rotating.", f->path); return true; + case -EBADMSG: /* Corrupted */ case -ENODATA: /* Truncated */ case -ESHUTDOWN: /* Already archived */ log_warning("%s: Journal file corrupted, rotating.", f->path); return true; + case -EIDRM: /* Journal file has been deleted */ log_warning("%s: Journal file has been deleted, rotating.", f->path); return true; + + case -ETXTBSY: /* Journal file is from the future */ + log_warning("%s: Journal file is from the future, rotateing.", f->path); + return true; + default: return false; } -- cgit v1.2.3-54-g00ecf From 8da830bca9f3b3fb34b1538dba70455749238fe0 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 12 Oct 2016 20:20:53 +0200 Subject: journalctl: don't claim the journal was stored on disk Let's just say that the journal takes up space in the file system, not on disk, as tmpfs is definitely a file system, but not a disk. Fixes: #4059 --- src/journal/journalctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/journal') diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index f753435888..7f997487b4 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -2266,7 +2266,7 @@ int main(int argc, char *argv[]) { if (r < 0) goto finish; - printf("Archived and active journals take up %s on disk.\n", + printf("Archived and active journals take up %s in the file system.\n", format_bytes(sbytes, sizeof(sbytes), bytes)); goto finish; } -- cgit v1.2.3-54-g00ecf From 3cc44bf91babddb667c877706e29c927c27ebb62 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 12 Oct 2016 20:23:43 +0200 Subject: journalctl: say in which directory we vacuum stuff Fixes: #4060 --- src/journal/journal-vacuum.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/journal') diff --git a/src/journal/journal-vacuum.c b/src/journal/journal-vacuum.c index f09dc66e03..12ce2fd56c 100644 --- a/src/journal/journal-vacuum.c +++ b/src/journal/journal-vacuum.c @@ -343,7 +343,7 @@ finish: free(list[i].filename); free(list); - log_full(verbose ? LOG_INFO : LOG_DEBUG, "Vacuuming done, freed %s of archived journals on disk.", format_bytes(sbytes, sizeof(sbytes), freed)); + log_full(verbose ? LOG_INFO : LOG_DEBUG, "Vacuuming done, freed %s of archived journals from %s.", format_bytes(sbytes, sizeof(sbytes), freed), directory); return r; } -- cgit v1.2.3-54-g00ecf