journal-file.c revision dc4ebc0787a299f064553e6d28a7f35574ce1c2a
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering This file is part of systemd.
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering Copyright 2011 Lennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering systemd is free software; you can redistribute it and/or modify it
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering under the terms of the GNU Lesser General Public License as published by
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering the Free Software Foundation; either version 2.1 of the License, or
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering (at your option) any later version.
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering systemd is distributed in the hope that it will be useful, but
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering Lesser General Public License for more details.
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering You should have received a copy of the GNU Lesser General Public License
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering#define DEFAULT_DATA_HASH_TABLE_SIZE (2047ULL*sizeof(HashItem))
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering#define DEFAULT_FIELD_HASH_TABLE_SIZE (333ULL*sizeof(HashItem))
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering#define COMPRESSION_SIZE_THRESHOLD (512ULL)
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering/* This is the minimum journal file size */
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering#define JOURNAL_FILE_SIZE_MIN (4ULL*1024ULL*1024ULL) /* 4 MiB */
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering/* These are the lower and upper bounds if we deduce the max_use value
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering * from the file system size */
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering#define DEFAULT_MAX_USE_LOWER (1ULL*1024ULL*1024ULL) /* 1 MiB */
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering#define DEFAULT_MAX_USE_UPPER (4ULL*1024ULL*1024ULL*1024ULL) /* 4 GiB */
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering/* This is the upper bound if we deduce max_size from max_use */
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering#define DEFAULT_MAX_SIZE_UPPER (128ULL*1024ULL*1024ULL) /* 128 MiB */
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering/* This is the upper bound if we deduce the keep_free value from the
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering * file system size */
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering#define DEFAULT_KEEP_FREE_UPPER (4ULL*1024ULL*1024ULL*1024ULL) /* 4 GiB */
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering/* This is the keep_free value when we can't determine the system
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering#define DEFAULT_KEEP_FREE (1024ULL*1024ULL) /* 1 MB */
d0bbc21caa6e68693a47db60c93e99422bf2a858Lennart Poettering/* n_data was the first entry we added after the initial file format design */
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering#define HEADER_SIZE_MIN ALIGN64(offsetof(Header, n_data))
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering/* How many entries to keep in the entry array chain cache at max */
a5344d2c3b0f14e954ce1c0ef905c5b44bc5bf0aLennart Poettering/* How much to increase the journal file size at once each time we allocate something new. */
d0bbc21caa6e68693a47db60c93e99422bf2a858Lennart Poettering#define FILE_SIZE_INCREASE (8ULL*1024ULL*1024ULL) /* 8MB */
d0bbc21caa6e68693a47db60c93e99422bf2a858Lennart Poettering/* Reread fstat() of the file for detecting deletions at least this often */
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering#define LAST_STAT_REFRESH_USEC (5*USEC_PER_SEC)
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering/* The mmap context to use for the header we pick as one above the last defined typed */
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poetteringstatic int journal_file_set_online(JournalFile *f) {
d0bbc21caa6e68693a47db60c93e99422bf2a858Lennart Poettering if (mmap_cache_got_sigbus(f->mmap, f->fd))
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poetteringint journal_file_set_offline(JournalFile *f) {
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering if (mmap_cache_got_sigbus(f->mmap, f->fd))
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering if (mmap_cache_got_sigbus(f->mmap, f->fd))
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering /* Write the final tag */
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering /* Be friendly to btrfs: turn COW back on again now,
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering * and defragment the file. We won't write to the file
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering * ever again, hence remove all fragmentation, and
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering * reenable all the good bits COW usually provides
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering * (such as data checksumming). */
a5344d2c3b0f14e954ce1c0ef905c5b44bc5bf0aLennart Poettering ordered_hashmap_free_free(f->chain_cache);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering munmap(f->fss_file, PAGE_ALIGN(f->fss_file_size));
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poetteringstatic int journal_file_init_header(JournalFile *f, JournalFile *template) {
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering memcpy(h.signature, HEADER_SIGNATURE, 8);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering h.header_size = htole64(ALIGN64(sizeof(h)));
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering f->compress_xz * HEADER_INCOMPATIBLE_COMPRESSED_XZ |
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering f->compress_lz4 * HEADER_INCOMPATIBLE_COMPRESSED_LZ4);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering h.seqnum_id = template->header->seqnum_id;
5ba081b0fb02380cee4c2ff5bc7e05f869eb8415Lennart Poettering h.tail_entry_seqnum = template->header->tail_entry_seqnum;
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering if (k != sizeof(h))
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poetteringstatic int journal_file_refresh_header(JournalFile *f) {
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering r = sd_id128_get_machine(&f->header->machine_id);
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering if (sd_id128_equal(boot_id, f->header->boot_id))
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering /* Sync the online state to disk */
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poetteringstatic int journal_file_verify_header(JournalFile *f) {
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering if (memcmp(f->header->signature, HEADER_SIGNATURE, 8))
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering /* In both read and write mode we refuse to open files with
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering * incompatible flags we don't know */
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering flags = le32toh(f->header->incompatible_flags);
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering if (flags & ~HEADER_INCOMPATIBLE_SUPPORTED) {
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering log_debug("Journal file %s has unknown incompatible flags %"PRIx32,
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering f->path, flags & ~HEADER_INCOMPATIBLE_ANY);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering flags = (flags & HEADER_INCOMPATIBLE_ANY) & ~HEADER_INCOMPATIBLE_SUPPORTED;
4cd9a9d9ecf3a8835e21930f3215a5f5b74144beLennart Poettering log_debug("Journal file %s uses incompatible flags %"PRIx32
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering " disabled at compilation time.", f->path, flags);
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering /* When open for writing we refuse to open files with
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering * compatible flags, too */
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering flags = le32toh(f->header->compatible_flags);
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering if (f->writable && (flags & ~HEADER_COMPATIBLE_SUPPORTED)) {
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering log_debug("Journal file %s has unknown compatible flags %"PRIx32,
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering f->path, flags & ~HEADER_COMPATIBLE_ANY);
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering flags = (flags & HEADER_COMPATIBLE_ANY) & ~HEADER_COMPATIBLE_SUPPORTED;
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering log_debug("Journal file %s uses compatible flags %"PRIx32
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering " disabled at compilation time.", f->path, flags);
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering /* The first addition was n_data, so check that we are at least this large */
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering if (le64toh(f->header->header_size) < HEADER_SIZE_MIN)
86b9b8e70d54e79db3ff4f67bbd5280ecfc82537Lennart Poettering if (JOURNAL_HEADER_SEALED(f->header) && !JOURNAL_HEADER_CONTAINS(f->header, n_entry_arrays))
4cd9a9d9ecf3a8835e21930f3215a5f5b74144beLennart Poettering if ((le64toh(f->header->header_size) + le64toh(f->header->arena_size)) > (uint64_t) f->last_stat.st_size)
4cd9a9d9ecf3a8835e21930f3215a5f5b74144beLennart Poettering if (le64toh(f->header->tail_object_offset) > (le64toh(f->header->header_size) + le64toh(f->header->arena_size)))
4cd9a9d9ecf3a8835e21930f3215a5f5b74144beLennart Poettering if (!VALID64(le64toh(f->header->data_hash_table_offset)) ||
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering !VALID64(le64toh(f->header->field_hash_table_offset)) ||
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering !VALID64(le64toh(f->header->tail_object_offset)) ||
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering !VALID64(le64toh(f->header->entry_array_offset)))
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering if (!sd_id128_equal(machine_id, f->header->machine_id))
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering log_debug("Journal file %s is already online. Assuming unclean closing.", f->path);
return -EBUSY;
assert(f);
return -errno;
return -EIDRM;
assert(f);
return -EIO;
old_size =
return journal_file_fstat(f);
return -E2BIG;
available = 0;
return -E2BIG;
return journal_file_fstat(f);
static int journal_file_move_to(JournalFile *f, ObjectType type, bool keep_always, uint64_t offset, uint64_t size, void **ret) {
assert(f);
if (size <= 0)
return -EINVAL;
r = journal_file_fstat(f);
return -EADDRNOTAVAIL;
return mmap_cache_get(f->mmap, f->fd, f->prot, type_to_context(type), keep_always, offset, size, &f->last_stat, ret);
return sizeof(ObjectHeader);
Object *o;
uint64_t s;
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, ObjectType 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);
if (f->data_hash_table)
r = journal_file_move_to(f,
f->data_hash_table = t;
uint64_t s, p;
assert(f);
if (f->field_hash_table)
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, m;
assert(f);
assert(o);
return -EINVAL;
return -EBADMSG;
h = hash % m;
static int journal_file_link_data(
JournalFile *f,
Object *o,
uint64_t p, h, m;
assert(f);
assert(o);
return -EINVAL;
return -EBADMSG;
h = hash % m;
JournalFile *f,
assert(f);
return -EBADMSG;
h = hash % m;
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);
r = journal_file_map_data_hash_table(f);
return -EBADMSG;
h = hash % m;
Object *o;
goto next;
uint64_t l;
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;
int r, compression = 0;
const void *eq;
assert(f);
if (ret)
*ret = o;
if (offset)
*offset = p;
if (f->compress_xz &&
if (compression) {
if (!data)
#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;
r = -EIO;
typedef struct ChainCacheItem {
static void chain_cache_put(
OrderedHashmap *h,
if (!ci) {
if (!ci)
static int generic_array_get(
JournalFile *f,
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;
static int generic_array_get_plus_one(
JournalFile *f,
uint64_t i,
Object *o;
assert(f);
if (ret)
*ret = o;
if (offset)
static int generic_array_bisect(
JournalFile *f,
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;
if (last_index > 0) {
return -EBADMSG;
if (r == TEST_FOUND)
if (r == TEST_RIGHT)
right = x;
return -EBADMSG;
if (r == TEST_FOUND)
if (r == TEST_RIGHT)
right = y;
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)
chain_cache_put(f->chain_cache, ci, first, a, le64toh(array->entry_array.items[0]), t, subtract_one ? (i > 0 ? i-1 : (uint64_t) -1) : i);
if (subtract_one && i == 0)
p = last_p;
else if (subtract_one)
if (ret)
*ret = o;
if (offset)
*offset = p;
if (idx)
static int generic_array_bisect_plus_one(
JournalFile *f,
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;
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 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,
f->current_offset = 0;
f->current_seqnum = 0;
f->current_realtime = 0;
f->current_monotonic = 0;
f->current_xor_hash = 0;
JournalFile *f,
uint64_t p,
assert(f);
r = generic_array_bisect(f,
r = generic_array_get(f,
f->path, i);
return -EBADMSG;
if (offset)
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))));
unsigned attrs;
assert(f);
int journal_file_open(
const char *fname,
int flags,
bool compress,
bool seal,
bool newly_created = false;
JournalFile *f;
return -EINVAL;
return -EINVAL;
return -ENOMEM;
#if defined(HAVE_LZ4)
#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 = journal_file_fstat(f);
goto fail;
(void) journal_file_warn_btrfs(f);
#ifdef HAVE_GCRYPT
if (f->seal) {
r = journal_file_fss_load(f);
f->seal = false;
goto fail;
r = journal_file_fstat(f);
goto fail;
newly_created = true;
r = -EIO;
goto fail;
r = mmap_cache_get(f->mmap, f->fd, f->prot, CONTEXT_HEADER, true, 0, PAGE_ALIGN(sizeof(Header)), &f->last_stat, &h);
goto fail;
f->header = h;
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;
r = -EIO;
goto fail;
*ret = f;
fail:
r = -EIO;
size_t l;
assert(f);
assert(*f);
old_file = *f;
return -EINVAL;
return -EINVAL;
return -ENOMEM;
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;
if (!IN_SET(r,
random_u64()) < 0)
return -ENOMEM;
return -errno;
(void) btrfs_defrag(p);
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;
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;
l = rsize;
return -EPROTONOSUPPORT;
return -EIO;
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)