summaryrefslogtreecommitdiffstats
path: root/src/libsystemd
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2023-09-30 05:03:13 +0200
committerYu Watanabe <watanabe.yu+github@gmail.com>2023-11-04 03:47:55 +0100
commita1b8d21fab0708d055aeb63e17f83c2df501c185 (patch)
tree858a2d1597a5481ed5be8b90bdfe2a5fe864f352 /src/libsystemd
parentmmap-cache: introduce window_matches_by_addr() (diff)
downloadsystemd-a1b8d21fab0708d055aeb63e17f83c2df501c185.tar.xz
systemd-a1b8d21fab0708d055aeb63e17f83c2df501c185.zip
sd-journal: introduce journal_file_pin_object()
Previously, OBJECT_UNUSED was used for 'pinning' the mmap cache for an object. But, OBJECT_UNUSED is also used for reading object when type cannot be determined before read, e.g. when reading the tail object. Let's introduce another category for pinning mmap cache, and use it when we want to temporary pin an object.
Diffstat (limited to 'src/libsystemd')
-rw-r--r--src/libsystemd/sd-journal/journal-file.c10
-rw-r--r--src/libsystemd/sd-journal/journal-file.h1
-rw-r--r--src/libsystemd/sd-journal/mmap-cache.c43
-rw-r--r--src/libsystemd/sd-journal/mmap-cache.h8
-rw-r--r--src/libsystemd/sd-journal/sd-journal.c16
5 files changed, 67 insertions, 11 deletions
diff --git a/src/libsystemd/sd-journal/journal-file.c b/src/libsystemd/sd-journal/journal-file.c
index 4466142784..d803bbfca3 100644
--- a/src/libsystemd/sd-journal/journal-file.c
+++ b/src/libsystemd/sd-journal/journal-file.c
@@ -1125,6 +1125,16 @@ int journal_file_move_to_object(JournalFile *f, ObjectType type, uint64_t offset
return 0;
}
+int journal_file_pin_object(JournalFile *f, Object *o) {
+ assert(f);
+ assert(o);
+
+ /* This attaches the mmap window that provides the object to the 'pinning' category. So, reading
+ * another object with the same type will not invalidate the object, until this function is called
+ * for another object. */
+ return mmap_cache_fd_pin(f->cache_fd, type_to_category(o->object.type), o, le64toh(o->object.size));
+}
+
int journal_file_read_object_header(JournalFile *f, ObjectType type, uint64_t offset, Object *ret) {
ssize_t n;
Object o;
diff --git a/src/libsystemd/sd-journal/journal-file.h b/src/libsystemd/sd-journal/journal-file.h
index 6c46dff4c4..183a5e43bb 100644
--- a/src/libsystemd/sd-journal/journal-file.h
+++ b/src/libsystemd/sd-journal/journal-file.h
@@ -208,6 +208,7 @@ static inline bool VALID_EPOCH(uint64_t u) {
FLAGS_SET(le32toh((h)->incompatible_flags), HEADER_INCOMPATIBLE_COMPACT)
int journal_file_move_to_object(JournalFile *f, ObjectType type, uint64_t offset, Object **ret);
+int journal_file_pin_object(JournalFile *f, Object *o);
int journal_file_read_object_header(JournalFile *f, ObjectType type, uint64_t offset, Object *ret);
int journal_file_tail_end_by_pread(JournalFile *f, uint64_t *ret_offset);
diff --git a/src/libsystemd/sd-journal/mmap-cache.c b/src/libsystemd/sd-journal/mmap-cache.c
index 3f22d83b28..973ade64c0 100644
--- a/src/libsystemd/sd-journal/mmap-cache.c
+++ b/src/libsystemd/sd-journal/mmap-cache.c
@@ -384,6 +384,49 @@ found:
return 0;
}
+int mmap_cache_fd_pin(
+ MMapFileDescriptor *f,
+ MMapCacheCategory c,
+ void *addr,
+ size_t size) {
+
+ MMapCache *m = mmap_cache_fd_cache(f);
+ Window *w;
+
+ assert(addr);
+ assert(c >= 0 && c < _MMAP_CACHE_CATEGORY_MAX);
+ assert(size > 0);
+
+ if (f->sigbus)
+ return -EIO;
+
+ /* Check if the current category is the right one. */
+ if (window_matches_by_addr(m->windows_by_category[c], f, addr, size)) {
+ m->n_category_cache_hit++;
+ w = m->windows_by_category[c];
+ goto found;
+ }
+
+ /* Search for a matching mmap. */
+ LIST_FOREACH(windows, i, f->windows)
+ if (window_matches_by_addr(i, f, addr, size)) {
+ m->n_window_list_hit++;
+ w = i;
+ goto found;
+ }
+
+ m->n_missed++;
+ return -EADDRNOTAVAIL; /* Not found. */
+
+found:
+ if (FLAGS_SET(w->flags, WINDOW_KEEP_ALWAYS))
+ return 0; /* The window will never unmapped. */
+
+ /* Attach the window to the 'pinning' category. */
+ category_attach_window(m, MMAP_CACHE_CATEGORY_PIN, w);
+ return 1;
+}
+
void mmap_cache_stats_log_debug(MMapCache *m) {
assert(m);
diff --git a/src/libsystemd/sd-journal/mmap-cache.h b/src/libsystemd/sd-journal/mmap-cache.h
index 7568746e93..1fbc236bda 100644
--- a/src/libsystemd/sd-journal/mmap-cache.h
+++ b/src/libsystemd/sd-journal/mmap-cache.h
@@ -20,6 +20,7 @@ typedef enum MMapCacheCategory {
MMAP_CACHE_CATEGORY_ENTRY_ARRAY = OBJECT_ENTRY_ARRAY,
MMAP_CACHE_CATEGORY_TAG = OBJECT_TAG,
MMAP_CACHE_CATEGORY_HEADER, /* for reading file header */
+ MMAP_CACHE_CATEGORY_PIN, /* for temporary pinning a object */
_MMAP_CACHE_CATEGORY_MAX,
_MMAP_CACHE_CATEGORY_INVALID = -EINVAL,
} MMapCacheCategory;
@@ -43,6 +44,13 @@ int mmap_cache_fd_get(
size_t size,
struct stat *st,
void **ret);
+
+int mmap_cache_fd_pin(
+ MMapFileDescriptor *f,
+ MMapCacheCategory c,
+ void *addr,
+ size_t size);
+
int mmap_cache_add_fd(MMapCache *m, int fd, int prot, MMapFileDescriptor **ret);
MMapCache* mmap_cache_fd_cache(MMapFileDescriptor *f);
MMapFileDescriptor* mmap_cache_fd_free(MMapFileDescriptor *f);
diff --git a/src/libsystemd/sd-journal/sd-journal.c b/src/libsystemd/sd-journal/sd-journal.c
index c61573f860..73a65da750 100644
--- a/src/libsystemd/sd-journal/sd-journal.c
+++ b/src/libsystemd/sd-journal/sd-journal.c
@@ -3190,20 +3190,14 @@ _public_ int sd_journal_enumerate_unique(
continue;
}
- /* We do not use OBJECT_DATA context here, but OBJECT_UNUSED
- * instead, so that we can look at this data object at the same
- * time as one on another file */
- r = journal_file_move_to_object(j->unique_file, OBJECT_UNUSED, j->unique_offset, &o);
+ r = journal_file_move_to_object(j->unique_file, OBJECT_DATA, j->unique_offset, &o);
if (r < 0)
return r;
- /* Let's do the type check by hand, since we used 0 context above. */
- if (o->object.type != OBJECT_DATA)
- return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG),
- "%s:offset " OFSfmt ": object has type %d, expected %d",
- j->unique_file->path,
- j->unique_offset,
- o->object.type, OBJECT_DATA);
+ /* Let's pin the data object, so we can look at it at the same time as one on another file. */
+ r = journal_file_pin_object(j->unique_file, o);
+ if (r < 0)
+ return r;
r = journal_file_data_payload(j->unique_file, o, j->unique_offset, NULL, 0,
j->data_threshold, &odata, &ol);