1
0
mirror of https://github.com/systemd/systemd.git synced 2025-02-03 17:47:28 +03:00

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.
This commit is contained in:
Yu Watanabe 2024-01-03 04:27:59 +09:00
parent 4ebf678f1f
commit 99e6f682d3
3 changed files with 13 additions and 9 deletions

View File

@ -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++) {

View File

@ -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 {

View File

@ -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)