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.
This commit is contained in:
Yu Watanabe
2023-09-30 12:03:13 +09:00
parent 7a56f6b2b9
commit a1b8d21fab
5 changed files with 67 additions and 11 deletions

View 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;

View 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);

View 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);

View 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);

View 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);