From 99e6f682d3627c2c06d99bb3c3756e448e8d9bd1 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 3 Jan 2024 04:27:59 +0900 Subject: [PATCH] sd-journal: cache last entry offset and journal file state When the offset of the last entry object (or last object for journal files generated by an old journald) is not changed, the timestamps should be updated by journal_file_read_tail_timestamp() are unchanged. So, we can drop to call fstat() in the function. As, the journal header is always mapped, so we can read the offset and journal file state without calling fstat. Still, when the last entry offset is changed, we may need to call fstat() to read the entry object. But, hopefully the number of fstat() call can be reduced. --- src/libsystemd/sd-journal/journal-file.c | 1 - src/libsystemd/sd-journal/journal-file.h | 3 ++- src/libsystemd/sd-journal/sd-journal.c | 18 +++++++++++------- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/libsystemd/sd-journal/journal-file.c b/src/libsystemd/sd-journal/journal-file.c index 64bf8ef9af..8039b2aaf9 100644 --- a/src/libsystemd/sd-journal/journal-file.c +++ b/src/libsystemd/sd-journal/journal-file.c @@ -2244,7 +2244,6 @@ static int journal_file_link_entry( f->header->tail_entry_monotonic = o->entry.monotonic; if (JOURNAL_HEADER_CONTAINS(f->header, tail_entry_offset)) f->header->tail_entry_offset = htole64(offset); - f->newest_mtime = 0; /* we have a new tail entry now, explicitly invalidate newest boot id/timestamp info */ /* Link up the items */ for (uint64_t i = 0; i < n_items; i++) { diff --git a/src/libsystemd/sd-journal/journal-file.h b/src/libsystemd/sd-journal/journal-file.h index 81fafb9bec..6b378a2039 100644 --- a/src/libsystemd/sd-journal/journal-file.h +++ b/src/libsystemd/sd-journal/journal-file.h @@ -129,7 +129,8 @@ typedef struct JournalFile { uint64_t newest_monotonic_usec; uint64_t newest_realtime_usec; unsigned newest_boot_id_prioq_idx; - usec_t newest_mtime; + uint64_t newest_entry_offset; + uint8_t newest_state; } JournalFile; typedef enum JournalFileFlags { diff --git a/src/libsystemd/sd-journal/sd-journal.c b/src/libsystemd/sd-journal/sd-journal.c index 5a8c8a8579..d7136d250e 100644 --- a/src/libsystemd/sd-journal/sd-journal.c +++ b/src/libsystemd/sd-journal/sd-journal.c @@ -2428,11 +2428,10 @@ static int journal_file_read_tail_timestamp(sd_journal *j, JournalFile *f) { /* Tries to read the timestamp of the most recently written entry. */ - r = journal_file_fstat(f); - if (r < 0) - return r; - if (f->newest_mtime == timespec_load(&f->last_stat.st_mtim)) - return 0; /* mtime didn't change since last time, don't bother */ + if (f->header->state == f->newest_state && + f->header->state == STATE_ARCHIVED && + f->newest_entry_offset != 0) + return 0; /* We have already read archived file. */ if (JOURNAL_HEADER_CONTAINS(f->header, tail_entry_offset)) { offset = le64toh(READ_NOW(f->header->tail_entry_offset)); @@ -2443,6 +2442,8 @@ static int journal_file_read_tail_timestamp(sd_journal *j, JournalFile *f) { } if (offset == 0) return -ENODATA; /* not a single object/entry, hence no tail timestamp */ + if (offset == f->newest_entry_offset) + return 0; /* No new entry is added after we read last time. */ /* Move to the last object in the journal file, in the hope it is an entry (which it usually will * be). If we lack the "tail_entry_offset" field in the header, we specify the type as OBJECT_UNUSED @@ -2452,6 +2453,7 @@ static int journal_file_read_tail_timestamp(sd_journal *j, JournalFile *f) { if (r < 0) { log_debug_errno(r, "Failed to move to last object in journal file, ignoring: %m"); o = NULL; + offset = 0; } if (o && o->object.type == OBJECT_ENTRY) { /* Yay, last object is an entry, let's use the data. */ @@ -2469,10 +2471,11 @@ static int journal_file_read_tail_timestamp(sd_journal *j, JournalFile *f) { mo = le64toh(f->header->tail_entry_monotonic); rt = le64toh(f->header->tail_entry_realtime); id = f->header->tail_entry_boot_id; + offset = UINT64_MAX; } else { /* Otherwise let's find the last entry manually (this possibly means traversing the * chain of entry arrays, till the end */ - r = journal_file_next_entry(f, 0, DIRECTION_UP, &o, NULL); + r = journal_file_next_entry(f, 0, DIRECTION_UP, &o, offset == 0 ? &offset : NULL); if (r < 0) return r; if (r == 0) @@ -2494,7 +2497,8 @@ static int journal_file_read_tail_timestamp(sd_journal *j, JournalFile *f) { f->newest_monotonic_usec = mo; f->newest_realtime_usec = rt; f->newest_machine_id = f->header->machine_id; - f->newest_mtime = timespec_load(&f->last_stat.st_mtim); + f->newest_entry_offset = offset; + f->newest_state = f->header->state; r = journal_file_reshuffle_newest_by_boot_id(j, f); if (r < 0)