]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sd-journal: introduce journal_file_pin_object()
authorYu Watanabe <watanabe.yu+github@gmail.com>
Sat, 30 Sep 2023 03:03:13 +0000 (12:03 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Sat, 4 Nov 2023 02:47:55 +0000 (11:47 +0900)
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.

src/libsystemd/sd-journal/journal-file.c
src/libsystemd/sd-journal/journal-file.h
src/libsystemd/sd-journal/mmap-cache.c
src/libsystemd/sd-journal/mmap-cache.h
src/libsystemd/sd-journal/sd-journal.c

index 4466142784267320b7676cf2fad588e4a6d4b18b..d803bbfca30c9f503dfa1e0ed42194c050d742d8 100644 (file)
@@ -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;
index 6c46dff4c45cfe3381dc5a27189898b4f39720e5..183a5e43bb434bc838abfdf46c326b7dc524c94a 100644 (file)
@@ -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);
index 3f22d83b2827d0dc0869792e3c2994342e358a17..973ade64c0f57ead0f24b787316e42f4e0cf7ee4 100644 (file)
@@ -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);
 
index 7568746e9322d274260876f75906ab502b991705..1fbc236bda9096af52b350320780c8f97ddb2fd3 100644 (file)
@@ -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);
index c61573f86067af50bd90bc291a6ede3e23ddf8d5..73a65da7502068fbea58b82fa36ef2a5b2ffceff 100644 (file)
@@ -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);