journal-file.c revision 48b617399d7d8446c5310b2568b2af6f13331b4c
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen This file is part of systemd.
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen Copyright 2011 Lennart Poettering
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen systemd is free software; you can redistribute it and/or modify it
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen under the terms of the GNU Lesser General Public License as published by
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen the Free Software Foundation; either version 2.1 of the License, or
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen (at your option) any later version.
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen systemd is distributed in the hope that it will be useful, but
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen WITHOUT ANY WARRANTY; without even the implied warranty of
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen Lesser General Public License for more details.
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen You should have received a copy of the GNU Lesser General Public License
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen along with systemd; If not, see <http://www.gnu.org/licenses/>.
c6f7c917a1b494d4455800823472227463f87438Tom Gundersen#define DEFAULT_DATA_HASH_TABLE_SIZE (2047ULL*sizeof(HashItem))
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering#define DEFAULT_FIELD_HASH_TABLE_SIZE (333ULL*sizeof(HashItem))
4e731273edfe852a3eee2949cd20f49fd5b4f6d7Lennart Poettering#define COMPRESSION_SIZE_THRESHOLD (512ULL)
8fcde01280adcbd07e8205b91ac52b06305b6208Lennart Poettering/* This is the minimum journal file size */
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering#define JOURNAL_FILE_SIZE_MIN (64ULL*1024ULL) /* 64 KiB */
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering/* These are the lower and upper bounds if we deduce the max_use value
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering * from the file system size */
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen#define DEFAULT_MAX_USE_LOWER (1ULL*1024ULL*1024ULL) /* 1 MiB */
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen#define DEFAULT_MAX_USE_UPPER (4ULL*1024ULL*1024ULL*1024ULL) /* 4 GiB */
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen/* This is the upper bound if we deduce max_size from max_use */
a501033335ed402c8f7e86fe41a15531ba69abd7Tom Gundersen#define DEFAULT_MAX_SIZE_UPPER (128ULL*1024ULL*1024ULL) /* 128 MiB */
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen/* This is the upper bound if we deduce the keep_free value from the
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen * file system size */
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen#define DEFAULT_KEEP_FREE_UPPER (4ULL*1024ULL*1024ULL*1024ULL) /* 4 GiB */
97f2d76d4f4dfab8b0629c09926a05a1e5621125Tom Gundersen/* This is the keep_free value when we can't determine the system
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen#define DEFAULT_KEEP_FREE (1024ULL*1024ULL) /* 1 MB */
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek/* n_data was the first entry we added after the initial file format design */
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek#define HEADER_SIZE_MIN ALIGN64(offsetof(Header, n_data))
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmekvoid journal_file_close(JournalFile *f) {
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek /* Write the final tag */
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen /* Sync everything to disk, before we mark the file offline */
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen /* Mark the file offline. Don't override the archived state if it already is set */
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen if (f->writable && f->header->state == STATE_ONLINE)
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen munmap(f->header, PAGE_ALIGN(sizeof(Header)));
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen if (f->fd >= 0)
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen munmap(f->fss_file, PAGE_ALIGN(f->fss_file_size));
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersenstatic int journal_file_init_header(JournalFile *f, JournalFile *template) {
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen htole32(f->compress ? HEADER_INCOMPATIBLE_COMPRESSED : 0);
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen htole32(f->seal ? HEADER_COMPATIBLE_SEALED : 0);
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen h.tail_entry_seqnum = template->header->tail_entry_seqnum;
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen if (k != sizeof(h))
187dc6e554f2d5b4b5a3bee72c73ff5df6418aa6Thomas Hindoe Paaboel Andersenstatic int journal_file_refresh_header(JournalFile *f) {
ecb08ec6a5c52f2d940f3b8147e2a480affd46e1Zbigniew Jędrzejewski-Szmek r = sd_id128_get_machine(&f->header->machine_id);
ed88bcfb7c15029f9fc95ee2380759a9eb782d46Zbigniew Jędrzejewski-Szmek r = sd_id128_get_boot(&boot_id);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen if (sd_id128_equal(boot_id, f->header->boot_id))
ecb08ec6a5c52f2d940f3b8147e2a480affd46e1Zbigniew Jędrzejewski-Szmek f->tail_entry_monotonic_valid = true;
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen /* Sync the online state to disk */
e9f3d2d508bfd9fb5b54e82994bda365a71eb864Zbigniew Jędrzejewski-Szmek msync(f->header, PAGE_ALIGN(sizeof(Header)), MS_SYNC);
36f822c4bd077f9121757e24b6516e5c7ada63b5Zbigniew Jędrzejewski-Szmekstatic int journal_file_verify_header(JournalFile *f) {
dab495dc23bf9a5ba0487a057bb594355555a0e9Tom Gundersen if (memcmp(f->header->signature, HEADER_SIGNATURE, 8))
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen /* In both read and write mode we refuse to open files with
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen * incompatible flags we don't know */
ecb08ec6a5c52f2d940f3b8147e2a480affd46e1Zbigniew Jędrzejewski-Szmek if ((le32toh(f->header->incompatible_flags) & ~HEADER_INCOMPATIBLE_COMPRESSED) != 0)
a2a5291b3f5ab6ed4c92f51d0fd10a03047380d8Zbigniew Jędrzejewski-Szmek /* When open for writing we refuse to open files with
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen * compatible flags, too */
74df0fca09b3c31ed19e14ba80f996fdff772417Lennart Poettering if ((le32toh(f->header->compatible_flags) & ~HEADER_COMPATIBLE_SEALED) != 0)
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen /* The first addition was n_data, so check that we are at least this large */
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen if (le64toh(f->header->header_size) < HEADER_SIZE_MIN)
edf029b7fd9a5853a87d3ca99aac2922bb8a277eTom Gundersen if (JOURNAL_HEADER_SEALED(f->header) && !JOURNAL_HEADER_CONTAINS(f->header, n_entry_arrays))
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen if ((le64toh(f->header->header_size) + le64toh(f->header->arena_size)) > (uint64_t) f->last_stat.st_size)
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen if (le64toh(f->header->tail_object_offset) > (le64toh(f->header->header_size) + le64toh(f->header->arena_size)))
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen if (!VALID64(le64toh(f->header->data_hash_table_offset)) ||
97f2d76d4f4dfab8b0629c09926a05a1e5621125Tom Gundersen !VALID64(le64toh(f->header->field_hash_table_offset)) ||
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek !VALID64(le64toh(f->header->tail_object_offset)) ||
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen !VALID64(le64toh(f->header->entry_array_offset)))
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt if (le64toh(f->header->data_hash_table_offset) < le64toh(f->header->header_size) ||
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen le64toh(f->header->field_hash_table_offset) < le64toh(f->header->header_size) ||
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen le64toh(f->header->tail_object_offset) < le64toh(f->header->header_size) ||
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen le64toh(f->header->entry_array_offset) < le64toh(f->header->header_size))
464cf22f17e0cf2d8bfa6d72b5e7a662d634f149Tom Gundersen if (!sd_id128_equal(machine_id, f->header->machine_id))
3b64e4d4f40baac56148c7d333d6a0053358ec7aTom Gundersen log_debug("Journal file %s is already online. Assuming unclean closing.", f->path);
7eb08da4b388b920c8a894b1500c9cc7dc1f31efTom Gundersen log_debug("Journal file %s has unknown state %u.", f->path, state);
eb7040ec50fbfe5aad9eaf305bd442a4a235abaaTom Gundersen f->compress = JOURNAL_HEADER_COMPRESSED(f->header);
32bc8adcd836baff68e4d0f53b9a382f358cccf8Tom Gundersenstatic int journal_file_allocate(JournalFile *f, uint64_t offset, uint64_t size) {
ca6038b89645c0c1bd547d6a420bf95eb3d6f4ccTom Gundersen /* We assume that this file is not sparse, and we know that
32bc8adcd836baff68e4d0f53b9a382f358cccf8Tom Gundersen * for sure, since we always call posix_fallocate()
32bc8adcd836baff68e4d0f53b9a382f358cccf8Tom Gundersen * ourselves */
ca6038b89645c0c1bd547d6a420bf95eb3d6f4ccTom Gundersen if (new_size < le64toh(f->header->header_size))
f1ac700248f231b7bdac2aafe8c35650efddb89fTom Gundersen /* Note that the glibc fallocate() fallback is very
f1ac700248f231b7bdac2aafe8c35650efddb89fTom Gundersen inefficient, hence we try to minimize the allocation area
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen as we can. */
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen r = posix_fallocate(f->fd, old_size, new_size - old_size);
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen f->header->arena_size = htole64(new_size - le64toh(f->header->header_size));
3c9b886068d99e5d3cbabcac32a4decf37244c54Tom Gundersenstatic int journal_file_move_to(JournalFile *f, int context, bool keep_always, uint64_t offset, uint64_t size, void **ret) {
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen /* Avoid SIGBUS on invalid accesses */
3c9b886068d99e5d3cbabcac32a4decf37244c54Tom Gundersen if (offset + size > (uint64_t) f->last_stat.st_size) {
3c9b886068d99e5d3cbabcac32a4decf37244c54Tom Gundersen /* Hmm, out of range? Let's refresh the fstat() data
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen * first, before we trust that check. */
3c9b886068d99e5d3cbabcac32a4decf37244c54Tom Gundersen offset + size > (uint64_t) f->last_stat.st_size)
3c9b886068d99e5d3cbabcac32a4decf37244c54Tom Gundersen return mmap_cache_get(f->mmap, f->fd, f->prot, context, keep_always, offset, size, &f->last_stat, ret);
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersenstatic uint64_t minimum_header_size(Object *o) {
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen [OBJECT_DATA_HASH_TABLE] = sizeof(HashTableObject),
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering [OBJECT_FIELD_HASH_TABLE] = sizeof(HashTableObject),
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen [OBJECT_ENTRY_ARRAY] = sizeof(EntryArrayObject),
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen if (o->object.type >= ELEMENTSOF(table) || table[o->object.type] <= 0)
55428d84f31b52da1c50b7469f14e15740547f20Tom Gundersen return sizeof(ObjectHeader);
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersenint journal_file_move_to_object(JournalFile *f, int type, uint64_t offset, Object **ret) {
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen /* Objects may only be located at multiple of 64 bit */
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen /* One context for each type, plus one catch-all for the rest */
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen context = type > 0 && type < _OBJECT_TYPE_MAX ? type : 0;
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen r = journal_file_move_to(f, context, false, offset, sizeof(ObjectHeader), &t);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen if (s < sizeof(ObjectHeader))
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen if (s > sizeof(ObjectHeader)) {
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen r = journal_file_move_to(f, o->object.type, false, offset, s, &t);
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersenstatic uint64_t journal_file_entry_seqnum(JournalFile *f, uint64_t *seqnum) {
e51660ae56bb747ece2cab8fe6eec37f4d06a438Tom Gundersen r = le64toh(f->header->tail_entry_seqnum) + 1;
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen /* If an external seqnum counter was passed, we update
daeb71a36a98834664e4d95773a3629b746f4db8Tom Gundersen * both the local and the external one, and set it to
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen * the maximum of both */
3c9b886068d99e5d3cbabcac32a4decf37244c54Tom Gundersenint journal_file_append_object(JournalFile *f, int type, uint64_t size, Object **ret, uint64_t *offset) {
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen r = journal_file_move_to_object(f, -1, p, &tail);
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen r = journal_file_move_to(f, type, false, p, size, &t);
d95b83b87d7d7c50e550f7128827f73a321c8934Tom Gundersen f->header->n_objects = htole64(le64toh(f->header->n_objects) + 1);
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersenstatic int journal_file_setup_data_hash_table(JournalFile *f) {
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen /* We estimate that we need 1 hash table entry per 768 of
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen journal file and we want to make sure we never get beyond
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen 75% fill level. Calculate the hash table size for the
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen maximum file size based on these metrics. */
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen s = (f->metrics.max_size * 4 / 768 / 3) * sizeof(HashItem);
66d3752e812915a549ebee01769ee761c1495667Jacob Keller log_debug("Reserving %llu entries in hash table.", (unsigned long long) (s / sizeof(HashItem)));
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen f->header->data_hash_table_offset = htole64(p + offsetof(Object, hash_table.items));
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersenstatic int journal_file_setup_field_hash_table(JournalFile *f) {
assert(f);
r = journal_file_append_object(f,
uint64_t s, p;
assert(f);
r = journal_file_move_to(f,
f->data_hash_table = t;
uint64_t s, p;
assert(f);
r = journal_file_move_to(f,
f->field_hash_table = t;
uint64_t p, h;
assert(f);
assert(o);
JournalFile *f,
assert(f);
return -EBADMSG;
Object *o;
goto next;
#ifdef HAVE_XZ
return -EBADMSG;
return -EBADMSG;
if (ret)
*ret = o;
if (offset)
*offset = p;
return -EPROTONOSUPPORT;
if (ret)
*ret = o;
if (offset)
*offset = p;
next:
JournalFile *f,
assert(f);
return journal_file_find_data_object_with_hash(f,
static int journal_file_append_data(
JournalFile *f,
Object *o;
bool compressed = false;
assert(f);
if (ret)
*ret = o;
if (offset)
*offset = p;
#ifdef HAVE_XZ
if (f->compress &&
if (compressed) {
#ifdef HAVE_GCRYPT
if (ret)
*ret = o;
if (offset)
*offset = p;
assert(o);
assert(o);
assert(o);
uint64_t p) {
Object *o;
assert(f);
assert(p > 0);
n = journal_file_entry_array_n_items(o);
ap = a;
if (hidx > n)
#ifdef HAVE_GCRYPT
if (ap == 0)
uint64_t p) {
assert(f);
assert(p > 0);
if (*idx == 0)
le64_t i;
uint64_t p;
assert(f);
assert(o);
return -EINVAL;
return link_entry_into_array_plus_one(f,
offset);
uint64_t n, i;
assert(f);
assert(o);
r = link_entry_into_array(f,
offset);
/* log_debug("=> %s seqnr=%lu n_entries=%lu", f->path, (unsigned long) o->entry.seqnum, (unsigned long) f->header->n_entries); */
f->tail_entry_monotonic_valid = true;
n = journal_file_entry_n_items(o);
static int journal_file_append_entry_internal(
JournalFile *f,
Object *o;
assert(f);
#ifdef HAVE_GCRYPT
if (ret)
*ret = o;
if (offset)
assert(f);
int journal_file_append_entry(JournalFile *f, const dual_timestamp *ts, const struct iovec iovec[], unsigned n_iovec, uint64_t *seqnum, Object **ret, uint64_t *offset) {
assert(f);
if (!f->writable)
return -EPERM;
if (!ts) {
if (f->tail_entry_monotonic_valid &&
return -EINVAL;
#ifdef HAVE_GCRYPT
for (i = 0; i < n_iovec; i++) {
uint64_t p;
Object *o;
uint64_t i,
Object *o;
uint64_t p = 0, a;
assert(f);
a = first;
uint64_t n;
n = journal_file_entry_array_n_items(o);
if (ret)
*ret = o;
if (offset)
*offset = p;
uint64_t i,
Object *o;
assert(f);
if (ret)
*ret = o;
if (offset)
uint64_t n,
bool subtract_one = false;
assert(f);
a = first;
if (right <= 0)
return -EBADMSG;
if (r == TEST_FOUND)
if (r == TEST_RIGHT) {
left = 0;
subtract_one = true;
i = left;
goto found;
return -EBADMSG;
if (r == TEST_FOUND)
if (r == TEST_RIGHT)
right = i;
subtract_one = true;
goto found;
if (subtract_one && t == 0 && i == 0)
if (subtract_one && i == 0)
p = last_p;
else if (subtract_one)
if (ret)
*ret = o;
if (offset)
*offset = p;
if (idx)
uint64_t n,
bool step_back = false;
Object *o;
assert(f);
if (r == TEST_FOUND)
if (r == TEST_LEFT)
if (r == TEST_RIGHT) {
goto found;
if (r == 0 && step_back)
goto found;
if (r > 0 && idx)
(*idx) ++;
if (ret)
*ret = o;
if (offset)
if (idx)
*idx = 0;
assert(f);
assert(p > 0);
if (p == needle)
return TEST_FOUND;
else if (p < needle)
return TEST_LEFT;
return TEST_RIGHT;
JournalFile *f,
uint64_t p,
return generic_array_bisect(f,
Object *o;
assert(f);
assert(p > 0);
return TEST_FOUND;
return TEST_LEFT;
return TEST_RIGHT;
JournalFile *f,
return generic_array_bisect(f,
Object *o;
assert(f);
assert(p > 0);
return TEST_FOUND;
return TEST_LEFT;
return TEST_RIGHT;
JournalFile *f,
return generic_array_bisect(f,
Object *o;
assert(f);
assert(p > 0);
return TEST_FOUND;
return TEST_LEFT;
return TEST_RIGHT;
JournalFile *f,
Object *o;
assert(f);
return -ENOENT;
return generic_array_bisect_plus_one(f,
JournalFile *f,
uint64_t i, n;
assert(f);
assert(p > 0 || !o);
return -EINVAL;
r = generic_array_bisect(f,
return generic_array_get(f,
JournalFile *f,
uint64_t i, n;
assert(f);
assert(o);
assert(p > 0);
return -EINVAL;
r = generic_array_bisect(f,
if (skip < 0) {
return -EBADMSG;
return generic_array_get(f,
JournalFile *f,
uint64_t n, i;
Object *d;
assert(f);
assert(p > 0 || !o);
return -EINVAL;
return generic_array_get_plus_one(f,
JournalFile *f,
uint64_t p,
Object *d;
assert(f);
return generic_array_bisect_plus_one(f,
JournalFile *f,
Object *o, *d;
uint64_t b, z;
assert(f);
return -ENOENT;
uint64_t p, q;
if (ret)
if (offset)
*offset = q;
JournalFile *f,
Object *d;
assert(f);
return generic_array_bisect_plus_one(f,
JournalFile *f,
Object *d;
assert(f);
return generic_array_bisect_plus_one(f,
Object *o;
uint64_t p;
assert(f);
goto fail;
case OBJECT_UNUSED:
case OBJECT_DATA:
case OBJECT_ENTRY:
case OBJECT_FIELD_HASH_TABLE:
case OBJECT_DATA_HASH_TABLE:
case OBJECT_ENTRY_ARRAY:
case OBJECT_TAG:
fail:
assert(f);
f->path,
100.0 * (double) le64toh(f->header->n_data) / ((double) (le64toh(f->header->data_hash_table_size) / sizeof(HashItem))));
100.0 * (double) le64toh(f->header->n_fields) / ((double) (le64toh(f->header->field_hash_table_size) / sizeof(HashItem))));
int journal_file_open(
const char *fname,
int flags,
bool compress,
bool seal,
JournalFile *f;
bool newly_created = false;
return -EINVAL;
return -EINVAL;
return -ENOMEM;
#ifdef HAVE_XZ
if (mmap_cache)
if (!f->mmap) {
r = -ENOMEM;
goto fail;
if (!f->path) {
r = -ENOMEM;
goto fail;
if (f->fd < 0) {
r = -errno;
goto fail;
r = -errno;
goto fail;
newly_created = true;
#ifdef HAVE_GCRYPT
r = journal_file_fss_load(f);
f->seal = false;
goto fail;
r = -errno;
goto fail;
r = -EIO;
goto fail;
r = -errno;
goto fail;
if (!newly_created) {
r = journal_file_verify_header(f);
goto fail;
#ifdef HAVE_GCRYPT
r = journal_file_fss_load(f);
goto fail;
if (f->writable) {
if (metrics) {
} else if (template)
r = journal_file_refresh_header(f);
goto fail;
#ifdef HAVE_GCRYPT
r = journal_file_hmac_setup(f);
goto fail;
if (newly_created) {
goto fail;
goto fail;
#ifdef HAVE_GCRYPT
r = journal_file_append_first_tag(f);
goto fail;
goto fail;
r = journal_file_map_data_hash_table(f);
goto fail;
if (ret)
*ret = f;
fail:
size_t l;
assert(f);
assert(*f);
old_file = *f;
return -EINVAL;
return -EINVAL;
return -ENOMEM;
free(p);
return -errno;
r = journal_file_open(old_file->path, old_file->flags, old_file->mode, compress, seal, NULL, old_file->mmap, old_file, &new_file);
*f = new_file;
const char *fname,
int flags,
bool compress,
bool seal,
size_t l;
random_ull()) < 0)
return -ENOMEM;
free(p);
return -errno;
int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint64_t p, uint64_t *seqnum, Object **ret, uint64_t *offset) {
uint64_t i, n;
assert(o);
assert(p);
return -EPERM;
return -EINVAL;
n = journal_file_entry_n_items(o);
uint64_t l, h;
size_t t;
void *data;
Object *u;
return -EBADMSG;
t = (size_t) l;
if ((uint64_t) t != l)
return -E2BIG;
#ifdef HAVE_XZ
if (!uncompress_blob(o->data.payload, l, &from->compress_buffer, &from->compress_buffer_size, &rsize))
return -EBADMSG;
l = rsize;
return -EPROTONOSUPPORT;
assert(m);
if (fs_size > 0) {
if (fs_size > 0) {
assert(f);
if (from) {
return -ENOENT;
if (to) {
return -ENOENT;
int journal_file_get_cutoff_monotonic_usec(JournalFile *f, sd_id128_t boot_id, usec_t *from, usec_t *to) {
Object *o;
uint64_t p;
assert(f);
if (from) {
if (to) {
r = generic_array_get_plus_one(f,
&o, NULL);
assert(f);
if (le64toh(f->header->n_data) * 4ULL > (le64toh(f->header->data_hash_table_size) / sizeof(HashItem)) * 3ULL) {
log_debug("Data hash table of %s has a fill level at %.1f (%llu of %llu items, %llu file size, %llu bytes per hash table item), suggesting rotation.",
f->path,
100.0 * (double) le64toh(f->header->n_data) / ((double) (le64toh(f->header->data_hash_table_size) / sizeof(HashItem))),
if (le64toh(f->header->n_fields) * 4ULL > (le64toh(f->header->field_hash_table_size) / sizeof(HashItem)) * 3ULL) {
log_debug("Field hash table of %s has a fill level at %.1f (%llu of %llu items), suggesting rotation.",
f->path,