journal-file.c revision 2765b7bb6924e2c26c7bf60bd692a4bc121d9582
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering This file is part of systemd.
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering Copyright 2011 Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering systemd is free software; you can redistribute it and/or modify it
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering under the terms of the GNU Lesser General Public License as published by
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering (at your option) any later version.
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering systemd is distributed in the hope that it will be useful, but
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering Lesser General Public License for more details.
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering You should have received a copy of the GNU Lesser General Public License
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering#define DEFAULT_DATA_HASH_TABLE_SIZE (2047ULL*sizeof(HashItem))
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering#define DEFAULT_FIELD_HASH_TABLE_SIZE (333ULL*sizeof(HashItem))
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering#define COMPRESSION_SIZE_THRESHOLD (512ULL)
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering/* This is the minimum journal file size */
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering#define JOURNAL_FILE_SIZE_MIN (4ULL*1024ULL*1024ULL) /* 4 MiB */
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering/* These are the lower and upper bounds if we deduce the max_use value
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering * from the file system size */
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering#define DEFAULT_MAX_USE_LOWER (1ULL*1024ULL*1024ULL) /* 1 MiB */
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering#define DEFAULT_MAX_USE_UPPER (4ULL*1024ULL*1024ULL*1024ULL) /* 4 GiB */
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering/* This is the upper bound if we deduce max_size from max_use */
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering#define DEFAULT_MAX_SIZE_UPPER (128ULL*1024ULL*1024ULL) /* 128 MiB */
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering/* This is the upper bound if we deduce the keep_free value from the
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering * file system size */
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering#define DEFAULT_KEEP_FREE_UPPER (4ULL*1024ULL*1024ULL*1024ULL) /* 4 GiB */
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering/* This is the keep_free value when we can't determine the system
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering#define DEFAULT_KEEP_FREE (1024ULL*1024ULL) /* 1 MB */
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering/* n_data was the first entry we added after the initial file format design */
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering#define HEADER_SIZE_MIN ALIGN64(offsetof(Header, n_data))
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering/* How many entries to keep in the entry array chain cache at max */
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poetteringint journal_file_set_online(JournalFile *f) {
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poetteringint journal_file_set_offline(JournalFile *f) {
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering /* Write the final tag */
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering /* Sync everything to disk, before we mark the file offline */
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering munmap(f->header, PAGE_ALIGN(sizeof(Header)));
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering munmap(f->fss_file, PAGE_ALIGN(f->fss_file_size));
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poetteringstatic int journal_file_init_header(JournalFile *f, JournalFile *template) {
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering memcpy(h.signature, HEADER_SIGNATURE, 8);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering h.header_size = htole64(ALIGN64(sizeof(h)));
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering htole32(f->compress ? HEADER_INCOMPATIBLE_COMPRESSED : 0);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering htole32(f->seal ? HEADER_COMPATIBLE_SEALED : 0);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering h.seqnum_id = template->header->seqnum_id;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering h.tail_entry_seqnum = template->header->tail_entry_seqnum;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (k != sizeof(h))
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poetteringstatic int journal_file_refresh_header(JournalFile *f) {
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering r = sd_id128_get_machine(&f->header->machine_id);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (sd_id128_equal(boot_id, f->header->boot_id))
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering /* Sync the online state to disk */
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering msync(f->header, PAGE_ALIGN(sizeof(Header)), MS_SYNC);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poetteringstatic int journal_file_verify_header(JournalFile *f) {
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (memcmp(f->header->signature, HEADER_SIGNATURE, 8))
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering /* In both read and write mode we refuse to open files with
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering * incompatible flags we don't know */
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if ((le32toh(f->header->incompatible_flags) & ~HEADER_INCOMPATIBLE_COMPRESSED) != 0)
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering /* When open for writing we refuse to open files with
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering * compatible flags, too */
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if ((le32toh(f->header->compatible_flags) & ~HEADER_COMPATIBLE_SEALED) != 0)
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering /* The first addition was n_data, so check that we are at least this large */
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (le64toh(f->header->header_size) < HEADER_SIZE_MIN)
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (JOURNAL_HEADER_SEALED(f->header) && !JOURNAL_HEADER_CONTAINS(f->header, n_entry_arrays))
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if ((le64toh(f->header->header_size) + le64toh(f->header->arena_size)) > (uint64_t) f->last_stat.st_size)
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (le64toh(f->header->tail_object_offset) > (le64toh(f->header->header_size) + le64toh(f->header->arena_size)))
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (!VALID64(le64toh(f->header->data_hash_table_offset)) ||
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering !VALID64(le64toh(f->header->field_hash_table_offset)) ||
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering !VALID64(le64toh(f->header->tail_object_offset)) ||
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering !VALID64(le64toh(f->header->entry_array_offset)))
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (le64toh(f->header->data_hash_table_offset) < le64toh(f->header->header_size) ||
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering le64toh(f->header->field_hash_table_offset) < le64toh(f->header->header_size) ||
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering le64toh(f->header->tail_object_offset) < le64toh(f->header->header_size) ||
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering le64toh(f->header->entry_array_offset) < le64toh(f->header->header_size))
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (!sd_id128_equal(machine_id, f->header->machine_id))
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering log_debug("Journal file %s is already online. Assuming unclean closing.", f->path);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering log_debug("Journal file %s has unknown state %u.", f->path, state);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering f->compress = JOURNAL_HEADER_COMPRESSED(f->header);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering f->seal = JOURNAL_HEADER_SEALED(f->header);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poetteringstatic int journal_file_allocate(JournalFile *f, uint64_t offset, uint64_t size) {
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering /* We assume that this file is not sparse, and we know that
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering * for sure, since we always call posix_fallocate()
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering * ourselves */
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (new_size < le64toh(f->header->header_size))
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering new_size = le64toh(f->header->header_size);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering /* Note that the glibc fallocate() fallback is very
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering inefficient, hence we try to minimize the allocation area
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering r = posix_fallocate(f->fd, old_size, new_size - old_size);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering f->header->arena_size = htole64(new_size - le64toh(f->header->header_size));
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poetteringstatic int journal_file_move_to(JournalFile *f, int context, bool keep_always, uint64_t offset, uint64_t size, void **ret) {
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering /* Avoid SIGBUS on invalid accesses */
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (offset + size > (uint64_t) f->last_stat.st_size) {
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering /* Hmm, out of range? Let's refresh the fstat() data
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering * first, before we trust that check. */
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering offset + size > (uint64_t) f->last_stat.st_size)
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return mmap_cache_get(f->mmap, f->fd, f->prot, context, keep_always, offset, size, &f->last_stat, ret);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poetteringstatic uint64_t minimum_header_size(Object *o) {
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering [OBJECT_DATA_HASH_TABLE] = sizeof(HashTableObject),
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering [OBJECT_FIELD_HASH_TABLE] = sizeof(HashTableObject),
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering [OBJECT_ENTRY_ARRAY] = sizeof(EntryArrayObject),
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (o->object.type >= ELEMENTSOF(table) || table[o->object.type] <= 0)
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poetteringint journal_file_move_to_object(JournalFile *f, int type, uint64_t offset, Object **ret) {
assert(f);
return -EFAULT;
o = (Object*) t;
if (s < sizeof(ObjectHeader))
return -EBADMSG;
return -EBADMSG;
if (s < minimum_header_size(o))
return -EBADMSG;
return -EBADMSG;
if (s > sizeof(ObjectHeader)) {
o = (Object*) t;
*ret = o;
uint64_t r;
assert(f);
if (seqnum) {
*seqnum = r;
int journal_file_append_object(JournalFile *f, int type, uint64_t size, Object **ret, uint64_t *offset) {
uint64_t p;
assert(f);
r = journal_file_set_online(f);
o = (Object*) t;
*ret = o;
*offset = p;
uint64_t s, p;
Object *o;
assert(f);
if (s < DEFAULT_DATA_HASH_TABLE_SIZE)
r = journal_file_append_object(f,
uint64_t s, p;
Object *o;
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;
static int journal_file_link_field(
JournalFile *f,
Object *o,
uint64_t p, h;
assert(f);
assert(o);
return -EINVAL;
static int journal_file_link_data(
JournalFile *f,
Object *o,
uint64_t p, h;
assert(f);
assert(o);
return -EINVAL;
JournalFile *f,
assert(f);
return -EBADMSG;
Object *o;
if (ret)
*ret = o;
if (offset)
*offset = p;
JournalFile *f,
assert(f);
return journal_file_find_field_object_with_hash(f,
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_field(
JournalFile *f,
Object *o;
assert(f);
if (ret)
*ret = o;
if (offset)
*offset = p;
#ifdef HAVE_GCRYPT
if (ret)
*ret = o;
if (offset)
*offset = p;
static int journal_file_append_data(
JournalFile *f,
Object *o;
bool compressed = false;
const void *eq;
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);
return -EINVAL;
r = link_entry_into_array(f,
offset);
/* log_debug("=> %s seqnr=%"PRIu64" n_entries=%"PRIu64, f->path, o->entry.seqnum, 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 (!ts) {
if (f->tail_entry_monotonic_valid &&
return -EINVAL;
#ifdef HAVE_GCRYPT
for (i = 0; i < n_iovec; i++) {
uint64_t p;
Object *o;
typedef struct ChainCacheItem {
static void chain_cache_put(
Hashmap *h,
if (!ci) {
if (!ci)
uint64_t i,
Object *o;
uint64_t p = 0, a, t = 0;
assert(f);
a = first;
uint64_t k;
k = journal_file_entry_array_n_items(o);
goto found;
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 (r == TEST_LEFT) {
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;
static inline int find_data_object_by_boot_id(
JournalFile *f,
Object **o,
uint64_t *b) {
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_FIELD:
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
#ifdef HAVE_GCRYPT
if (mmap_cache)
if (!f->mmap) {
r = -ENOMEM;
goto fail;
if (!f->path) {
r = -ENOMEM;
goto fail;
if (!f->chain_cache) {
r = -ENOMEM;
goto fail;
if (f->fd < 0) {
r = -errno;
goto fail;
r = -errno;
goto fail;
#ifdef HAVE_XATTR
#ifdef HAVE_GCRYPT
if (f->seal) {
r = journal_file_fss_load(f);
f->seal = false;
goto fail;
r = -errno;
goto fail;
newly_created = true;
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;
*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, 0))
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 (%"PRIu64" of %"PRIu64" items, %llu file size, %"PRIu64" 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 (%"PRIu64" of %"PRIu64" items), suggesting rotation.",
f->path,
100.0 * (double) le64toh(f->header->n_fields) / ((double) (le64toh(f->header->field_hash_table_size) / sizeof(HashItem))),
if (max_file_usec > 0) {
usec_t t, h;
if (h > 0 && t > h + max_file_usec)