Bug Summary

File:build-scan/../src/journal/journal-file.c
Warning:line 2320, column 49
Although the value stored to 'n' is used in the enclosing expression, the value is never actually read from 'n'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name journal-file.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -menable-no-infs -menable-no-nans -menable-unsafe-fp-math -fno-signed-zeros -mreassociate -freciprocal-math -fdenormal-fp-math=preserve-sign,preserve-sign -ffp-contract=fast -fno-rounding-math -ffast-math -ffinite-math-only -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/12.0.0 -include config.h -I src/journal/libjournal-client.a.p -I src/journal -I ../src/journal -I src/basic -I ../src/basic -I src/shared -I ../src/shared -I src/systemd -I ../src/systemd -I src/journal-remote -I ../src/journal-remote -I src/nspawn -I ../src/nspawn -I src/resolve -I ../src/resolve -I src/timesync -I ../src/timesync -I ../src/time-wait-sync -I src/login -I ../src/login -I src/udev -I ../src/udev -I src/libudev -I ../src/libudev -I src/core -I ../src/core -I ../src/libsystemd/sd-bus -I ../src/libsystemd/sd-device -I ../src/libsystemd/sd-hwdb -I ../src/libsystemd/sd-id128 -I ../src/libsystemd/sd-netlink -I ../src/libsystemd/sd-network -I src/libsystemd-network -I ../src/libsystemd-network -I . -I .. -D _FILE_OFFSET_BITS=64 -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/12.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wwrite-strings -Wno-unused-parameter -Wno-missing-field-initializers -Wno-unused-result -Wno-format-signedness -Wno-error=nonnull -std=gnu99 -fconst-strings -fdebug-compilation-dir /home/mrc0mmand/repos/@redhat-plumbers/systemd-rhel8/build-scan -ferror-limit 19 -fvisibility default -stack-protector 2 -fgnuc-version=4.2.1 -fcolor-diagnostics -analyzer-output=html -faddrsig -o /tmp/scan-build-2021-07-16-221226-1465241-1 -x c ../src/journal/journal-file.c
1/* SPDX-License-Identifier: LGPL-2.1+ */
2
3#include <errno(*__errno_location ()).h>
4#include <fcntl.h>
5#include <linux1/fs.h>
6#include <pthread.h>
7#include <stddef.h>
8#include <sys/mman.h>
9#include <sys/statvfs.h>
10#include <sys/uio.h>
11#include <unistd.h>
12
13#include "alloc-util.h"
14#include "btrfs-util.h"
15#include "chattr-util.h"
16#include "compress.h"
17#include "fd-util.h"
18#include "fs-util.h"
19#include "journal-authenticate.h"
20#include "journal-def.h"
21#include "journal-file.h"
22#include "lookup3.h"
23#include "parse-util.h"
24#include "path-util.h"
25#include "random-util.h"
26#include "sd-event.h"
27#include "set.h"
28#include "stat-util.h"
29#include "string-util.h"
30#include "strv.h"
31#include "xattr-util.h"
32
33#define DEFAULT_DATA_HASH_TABLE_SIZE(2047ULL*sizeof(HashItem)) (2047ULL*sizeof(HashItem))
34#define DEFAULT_FIELD_HASH_TABLE_SIZE(333ULL*sizeof(HashItem)) (333ULL*sizeof(HashItem))
35
36#define DEFAULT_COMPRESS_THRESHOLD(512ULL) (512ULL)
37#define MIN_COMPRESS_THRESHOLD(8ULL) (8ULL)
38
39/* This is the minimum journal file size */
40#define JOURNAL_FILE_SIZE_MIN(512ULL*1024ULL) (512ULL*1024ULL) /* 512 KiB */
41
42/* These are the lower and upper bounds if we deduce the max_use value
43 * from the file system size */
44#define DEFAULT_MAX_USE_LOWER(1ULL*1024ULL*1024ULL) (1ULL*1024ULL*1024ULL) /* 1 MiB */
45#define DEFAULT_MAX_USE_UPPER(4ULL*1024ULL*1024ULL*1024ULL) (4ULL*1024ULL*1024ULL*1024ULL) /* 4 GiB */
46
47/* This is the default minimal use limit, how much we'll use even if keep_free suggests otherwise. */
48#define DEFAULT_MIN_USE(1ULL*1024ULL*1024ULL) (1ULL*1024ULL*1024ULL) /* 1 MiB */
49
50/* This is the upper bound if we deduce max_size from max_use */
51#define DEFAULT_MAX_SIZE_UPPER(128ULL*1024ULL*1024ULL) (128ULL*1024ULL*1024ULL) /* 128 MiB */
52
53/* This is the upper bound if we deduce the keep_free value from the
54 * file system size */
55#define DEFAULT_KEEP_FREE_UPPER(4ULL*1024ULL*1024ULL*1024ULL) (4ULL*1024ULL*1024ULL*1024ULL) /* 4 GiB */
56
57/* This is the keep_free value when we can't determine the system
58 * size */
59#define DEFAULT_KEEP_FREE(1024ULL*1024ULL) (1024ULL*1024ULL) /* 1 MB */
60
61/* This is the default maximum number of journal files to keep around. */
62#define DEFAULT_N_MAX_FILES(100) (100)
63
64/* n_data was the first entry we added after the initial file format design */
65#define HEADER_SIZE_MIN(((__builtin_offsetof(Header, n_data)) + 7ULL) & ~7ULL) ALIGN64(offsetof(Header, n_data))(((__builtin_offsetof(Header, n_data)) + 7ULL) & ~7ULL)
66
67/* How many entries to keep in the entry array chain cache at max */
68#define CHAIN_CACHE_MAX20 20
69
70/* How much to increase the journal file size at once each time we allocate something new. */
71#define FILE_SIZE_INCREASE(8ULL*1024ULL*1024ULL) (8ULL*1024ULL*1024ULL) /* 8MB */
72
73/* Reread fstat() of the file for detecting deletions at least this often */
74#define LAST_STAT_REFRESH_USEC(5*((usec_t) 1000000ULL)) (5*USEC_PER_SEC((usec_t) 1000000ULL))
75
76/* The mmap context to use for the header we pick as one above the last defined typed */
77#define CONTEXT_HEADER_OBJECT_TYPE_MAX _OBJECT_TYPE_MAX
78
79#ifdef __clang__1
80# pragma GCC diagnostic ignored "-Waddress-of-packed-member"
81#endif
82
83/* This may be called from a separate thread to prevent blocking the caller for the duration of fsync().
84 * As a result we use atomic operations on f->offline_state for inter-thread communications with
85 * journal_file_set_offline() and journal_file_set_online(). */
86static void journal_file_set_offline_internal(JournalFile *f) {
87 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 87
, __PRETTY_FUNCTION__); } while (0)
;
88 assert(f->fd >= 0)do { if ((__builtin_expect(!!(!(f->fd >= 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f->fd >= 0"), "../src/journal/journal-file.c"
, 88, __PRETTY_FUNCTION__); } while (0)
;
89 assert(f->header)do { if ((__builtin_expect(!!(!(f->header)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f->header"), "../src/journal/journal-file.c"
, 89, __PRETTY_FUNCTION__); } while (0)
;
90
91 for (;;) {
92 switch (f->offline_state) {
93 case OFFLINE_CANCEL:
94 if (!__sync_bool_compare_and_swap(&f->offline_state, OFFLINE_CANCEL, OFFLINE_DONE))
95 continue;
96 return;
97
98 case OFFLINE_AGAIN_FROM_SYNCING:
99 if (!__sync_bool_compare_and_swap(&f->offline_state, OFFLINE_AGAIN_FROM_SYNCING, OFFLINE_SYNCING))
100 continue;
101 break;
102
103 case OFFLINE_AGAIN_FROM_OFFLINING:
104 if (!__sync_bool_compare_and_swap(&f->offline_state, OFFLINE_AGAIN_FROM_OFFLINING, OFFLINE_SYNCING))
105 continue;
106 break;
107
108 case OFFLINE_SYNCING:
109 (void) fsync(f->fd);
110
111 if (!__sync_bool_compare_and_swap(&f->offline_state, OFFLINE_SYNCING, OFFLINE_OFFLINING))
112 continue;
113
114 f->header->state = f->archive ? STATE_ARCHIVED : STATE_OFFLINE;
115 (void) fsync(f->fd);
116 break;
117
118 case OFFLINE_OFFLINING:
119 if (!__sync_bool_compare_and_swap(&f->offline_state, OFFLINE_OFFLINING, OFFLINE_DONE))
120 continue;
121 _fallthrough_;
122 case OFFLINE_DONE:
123 return;
124
125 case OFFLINE_JOINED:
126 log_debug("OFFLINE_JOINED unexpected offline state for journal_file_set_offline_internal()")({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 126, __func__, "OFFLINE_JOINED unexpected offline state for journal_file_set_offline_internal()"
) : -abs(_e); })
;
127 return;
128 }
129 }
130}
131
132static void * journal_file_set_offline_thread(void *arg) {
133 JournalFile *f = arg;
134
135 (void) pthread_setname_np(pthread_self(), "journal-offline");
136
137 journal_file_set_offline_internal(f);
138
139 return NULL((void*)0);
140}
141
142static int journal_file_set_offline_thread_join(JournalFile *f) {
143 int r;
144
145 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 145
, __PRETTY_FUNCTION__); } while (0)
;
146
147 if (f->offline_state == OFFLINE_JOINED)
148 return 0;
149
150 r = pthread_join(f->offline_thread, NULL((void*)0));
151 if (r)
152 return -r;
153
154 f->offline_state = OFFLINE_JOINED;
155
156 if (mmap_cache_got_sigbus(f->mmap, f->cache_fd))
157 return -EIO5;
158
159 return 0;
160}
161
162/* Trigger a restart if the offline thread is mid-flight in a restartable state. */
163static bool_Bool journal_file_set_offline_try_restart(JournalFile *f) {
164 for (;;) {
165 switch (f->offline_state) {
166 case OFFLINE_AGAIN_FROM_SYNCING:
167 case OFFLINE_AGAIN_FROM_OFFLINING:
168 return true1;
169
170 case OFFLINE_CANCEL:
171 if (!__sync_bool_compare_and_swap(&f->offline_state, OFFLINE_CANCEL, OFFLINE_AGAIN_FROM_SYNCING))
172 continue;
173 return true1;
174
175 case OFFLINE_SYNCING:
176 if (!__sync_bool_compare_and_swap(&f->offline_state, OFFLINE_SYNCING, OFFLINE_AGAIN_FROM_SYNCING))
177 continue;
178 return true1;
179
180 case OFFLINE_OFFLINING:
181 if (!__sync_bool_compare_and_swap(&f->offline_state, OFFLINE_OFFLINING, OFFLINE_AGAIN_FROM_OFFLINING))
182 continue;
183 return true1;
184
185 default:
186 return false0;
187 }
188 }
189}
190
191/* Sets a journal offline.
192 *
193 * If wait is false then an offline is dispatched in a separate thread for a
194 * subsequent journal_file_set_offline() or journal_file_set_online() of the
195 * same journal to synchronize with.
196 *
197 * If wait is true, then either an existing offline thread will be restarted
198 * and joined, or if none exists the offline is simply performed in this
199 * context without involving another thread.
200 */
201int journal_file_set_offline(JournalFile *f, bool_Bool wait) {
202 bool_Bool restarted;
203 int r;
204
205 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 205
, __PRETTY_FUNCTION__); } while (0)
;
206
207 if (!f->writable)
208 return -EPERM1;
209
210 if (f->fd < 0 || !f->header)
211 return -EINVAL22;
212
213 /* An offlining journal is implicitly online and may modify f->header->state,
214 * we must also join any potentially lingering offline thread when not online. */
215 if (!journal_file_is_offlining(f) && f->header->state != STATE_ONLINE)
216 return journal_file_set_offline_thread_join(f);
217
218 /* Restart an in-flight offline thread and wait if needed, or join a lingering done one. */
219 restarted = journal_file_set_offline_try_restart(f);
220 if ((restarted && wait) || !restarted) {
221 r = journal_file_set_offline_thread_join(f);
222 if (r < 0)
223 return r;
224 }
225
226 if (restarted)
227 return 0;
228
229 /* Initiate a new offline. */
230 f->offline_state = OFFLINE_SYNCING;
231
232 if (wait) /* Without using a thread if waiting. */
233 journal_file_set_offline_internal(f);
234 else {
235 sigset_t ss, saved_ss;
236 int k;
237
238 if (sigfillset(&ss) < 0)
239 return -errno(*__errno_location ());
240
241 r = pthread_sigmask(SIG_BLOCK0, &ss, &saved_ss);
242 if (r > 0)
243 return -r;
244
245 r = pthread_create(&f->offline_thread, NULL((void*)0), journal_file_set_offline_thread, f);
246
247 k = pthread_sigmask(SIG_SETMASK2, &saved_ss, NULL((void*)0));
248 if (r > 0) {
249 f->offline_state = OFFLINE_JOINED;
250 return -r;
251 }
252 if (k > 0)
253 return -k;
254 }
255
256 return 0;
257}
258
259static int journal_file_set_online(JournalFile *f) {
260 bool_Bool wait = true1;
261
262 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 262
, __PRETTY_FUNCTION__); } while (0)
;
263
264 if (!f->writable)
265 return -EPERM1;
266
267 if (f->fd < 0 || !f->header)
268 return -EINVAL22;
269
270 while (wait) {
271 switch (f->offline_state) {
272 case OFFLINE_JOINED:
273 /* No offline thread, no need to wait. */
274 wait = false0;
275 break;
276
277 case OFFLINE_SYNCING:
278 if (!__sync_bool_compare_and_swap(&f->offline_state, OFFLINE_SYNCING, OFFLINE_CANCEL))
279 continue;
280 /* Canceled syncing prior to offlining, no need to wait. */
281 wait = false0;
282 break;
283
284 case OFFLINE_AGAIN_FROM_SYNCING:
285 if (!__sync_bool_compare_and_swap(&f->offline_state, OFFLINE_AGAIN_FROM_SYNCING, OFFLINE_CANCEL))
286 continue;
287 /* Canceled restart from syncing, no need to wait. */
288 wait = false0;
289 break;
290
291 case OFFLINE_AGAIN_FROM_OFFLINING:
292 if (!__sync_bool_compare_and_swap(&f->offline_state, OFFLINE_AGAIN_FROM_OFFLINING, OFFLINE_CANCEL))
293 continue;
294 /* Canceled restart from offlining, must wait for offlining to complete however. */
295 _fallthrough_;
296 default: {
297 int r;
298
299 r = journal_file_set_offline_thread_join(f);
300 if (r < 0)
301 return r;
302
303 wait = false0;
304 break;
305 }
306 }
307 }
308
309 if (mmap_cache_got_sigbus(f->mmap, f->cache_fd))
310 return -EIO5;
311
312 switch (f->header->state) {
313 case STATE_ONLINE:
314 return 0;
315
316 case STATE_OFFLINE:
317 f->header->state = STATE_ONLINE;
318 (void) fsync(f->fd);
319 return 0;
320
321 default:
322 return -EINVAL22;
323 }
324}
325
326bool_Bool journal_file_is_offlining(JournalFile *f) {
327 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 327
, __PRETTY_FUNCTION__); } while (0)
;
328
329 __sync_synchronize();
330
331 if (IN_SET(f->offline_state, OFFLINE_DONE, OFFLINE_JOINED)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){OFFLINE_DONE, OFFLINE_JOINED})/sizeof(int
)]; switch(f->offline_state) { case OFFLINE_DONE: case OFFLINE_JOINED
: _found = 1; break; default: break; } _found; })
)
332 return false0;
333
334 return true1;
335}
336
337JournalFile* journal_file_close(JournalFile *f) {
338 if (!f)
339 return NULL((void*)0);
340
341#if HAVE_GCRYPT1
342 /* Write the final tag */
343 if (f->seal && f->writable) {
344 int r;
345
346 r = journal_file_append_tag(f);
347 if (r < 0)
348 log_error_errno(r, "Failed to append tag when closing journal: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 348, __func__, "Failed to append tag when closing journal: %m"
) : -abs(_e); })
;
349 }
350#endif
351
352 if (f->post_change_timer) {
353 int enabled;
354
355 if (sd_event_source_get_enabled(f->post_change_timer, &enabled) >= 0)
356 if (enabled == SD_EVENT_ONESHOT)
357 journal_file_post_change(f);
358
359 (void) sd_event_source_set_enabled(f->post_change_timer, SD_EVENT_OFF);
360 sd_event_source_unref(f->post_change_timer);
361 }
362
363 journal_file_set_offline(f, true1);
364
365 if (f->mmap && f->cache_fd)
366 mmap_cache_free_fd(f->mmap, f->cache_fd);
367
368 if (f->fd >= 0 && f->defrag_on_close) {
369
370 /* Be friendly to btrfs: turn COW back on again now,
371 * and defragment the file. We won't write to the file
372 * ever again, hence remove all fragmentation, and
373 * reenable all the good bits COW usually provides
374 * (such as data checksumming). */
375
376 (void) chattr_fd(f->fd, 0, FS_NOCOW_FL0x00800000);
377 (void) btrfs_defrag_fd(f->fd);
378 }
379
380 if (f->close_fd)
381 safe_close(f->fd);
382 free(f->path);
383
384 mmap_cache_unref(f->mmap);
385
386 ordered_hashmap_free_free(f->chain_cache);
387
388#if HAVE_XZ1 || HAVE_LZ41
389 free(f->compress_buffer);
390#endif
391
392#if HAVE_GCRYPT1
393 if (f->fss_file)
394 munmap(f->fss_file, PAGE_ALIGN(f->fss_file_size)ALIGN_TO((f->fss_file_size), page_size()));
395 else
396 free(f->fsprg_state);
397
398 free(f->fsprg_seed);
399
400 if (f->hmac)
401 gcry_md_close(f->hmac);
402#endif
403
404 return mfree(f);
405}
406
407static int journal_file_init_header(JournalFile *f, JournalFile *template) {
408 Header h = {};
409 ssize_t k;
410 int r;
411
412 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 412
, __PRETTY_FUNCTION__); } while (0)
;
413
414 memcpy(h.signature, HEADER_SIGNATURE((char[]) { 'L', 'P', 'K', 'S', 'H', 'H', 'R', 'H' }), 8);
415 h.header_size = htole64(ALIGN64(sizeof(h))(((sizeof(h)) + 7ULL) & ~7ULL));
416
417 h.incompatible_flags |= htole32(
418 f->compress_xz * HEADER_INCOMPATIBLE_COMPRESSED_XZ |
419 f->compress_lz4 * HEADER_INCOMPATIBLE_COMPRESSED_LZ4);
420
421 h.compatible_flags = htole32(
422 f->seal * HEADER_COMPATIBLE_SEALED);
423
424 r = sd_id128_randomize(&h.file_id);
425 if (r < 0)
426 return r;
427
428 if (template) {
429 h.seqnum_id = template->header->seqnum_id;
430 h.tail_entry_seqnum = template->header->tail_entry_seqnum;
431 } else
432 h.seqnum_id = h.file_id;
433
434 k = pwrite(f->fd, &h, sizeof(h), 0);
435 if (k < 0)
436 return -errno(*__errno_location ());
437
438 if (k != sizeof(h))
439 return -EIO5;
440
441 return 0;
442}
443
444static int journal_file_refresh_header(JournalFile *f) {
445 sd_id128_t boot_id;
446 int r;
447
448 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 448
, __PRETTY_FUNCTION__); } while (0)
;
449 assert(f->header)do { if ((__builtin_expect(!!(!(f->header)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f->header"), "../src/journal/journal-file.c"
, 449, __PRETTY_FUNCTION__); } while (0)
;
450
451 r = sd_id128_get_machine(&f->header->machine_id);
452 if (IN_SET(r, -ENOENT, -ENOMEDIUM)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){-2, -123})/sizeof(int)]; switch(r) { case
-2: case -123: _found = 1; break; default: break; } _found; }
)
)
453 /* We don't have a machine-id, let's continue without */
454 zero(f->header->machine_id)(({ size_t _l_ = (sizeof(f->header->machine_id)); void *
_x_ = (&(f->header->machine_id)); _l_ == 0 ? _x_ : memset
(_x_, 0, _l_); }))
;
455 else if (r < 0)
456 return r;
457
458 r = sd_id128_get_boot(&boot_id);
459 if (r < 0)
460 return r;
461
462 f->header->boot_id = boot_id;
463
464 r = journal_file_set_online(f);
465
466 /* Sync the online state to disk */
467 (void) fsync(f->fd);
468
469 /* We likely just created a new file, also sync the directory this file is located in. */
470 (void) fsync_directory_of_file(f->fd);
471
472 return r;
473}
474
475static bool_Bool warn_wrong_flags(const JournalFile *f, bool_Bool compatible) {
476 const uint32_t any = compatible ? HEADER_COMPATIBLE_ANYHEADER_COMPATIBLE_SEALED : HEADER_INCOMPATIBLE_ANY(HEADER_INCOMPATIBLE_COMPRESSED_XZ|HEADER_INCOMPATIBLE_COMPRESSED_LZ4
)
,
477 supported = compatible ? HEADER_COMPATIBLE_SUPPORTEDHEADER_COMPATIBLE_SEALED : HEADER_INCOMPATIBLE_SUPPORTED(HEADER_INCOMPATIBLE_COMPRESSED_XZ|HEADER_INCOMPATIBLE_COMPRESSED_LZ4
)
;
478 const char *type = compatible ? "compatible" : "incompatible";
479 uint32_t flags;
480
481 flags = le32toh(compatible ? f->header->compatible_flags : f->header->incompatible_flags);
482
483 if (flags & ~supported) {
484 if (flags & ~any)
485 log_debug("Journal file %s has unknown %s flags 0x%"PRIx32,({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 486, __func__, "Journal file %s has unknown %s flags 0x%"
"x", f->path, type, flags & ~any) : -abs(_e); })
486 f->path, type, flags & ~any)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 486, __func__, "Journal file %s has unknown %s flags 0x%"
"x", f->path, type, flags & ~any) : -abs(_e); })
;
487 flags = (flags & any) & ~supported;
488 if (flags) {
489 const char* strv[3];
490 unsigned n = 0;
491 _cleanup_free___attribute__((cleanup(freep))) char *t = NULL((void*)0);
492
493 if (compatible && (flags & HEADER_COMPATIBLE_SEALED))
494 strv[n++] = "sealed";
495 if (!compatible && (flags & HEADER_INCOMPATIBLE_COMPRESSED_XZ))
496 strv[n++] = "xz-compressed";
497 if (!compatible && (flags & HEADER_INCOMPATIBLE_COMPRESSED_LZ4))
498 strv[n++] = "lz4-compressed";
499 strv[n] = NULL((void*)0);
500 assert(n < ELEMENTSOF(strv))do { if ((__builtin_expect(!!(!(n < __extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(strv), typeof(&*(strv
))), sizeof(strv)/sizeof((strv)[0]), ((void)0))))),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("n < ELEMENTSOF(strv)"), "../src/journal/journal-file.c"
, 500, __PRETTY_FUNCTION__); } while (0)
;
501
502 t = strv_join((char**) strv, ", ");
503 log_debug("Journal file %s uses %s %s %s disabled at compilation time.",({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 504, __func__, "Journal file %s uses %s %s %s disabled at compilation time."
, f->path, type, n > 1 ? "flags" : "flag", strnull(t)) :
-abs(_e); })
504 f->path, type, n > 1 ? "flags" : "flag", strnull(t))({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 504, __func__, "Journal file %s uses %s %s %s disabled at compilation time."
, f->path, type, n > 1 ? "flags" : "flag", strnull(t)) :
-abs(_e); })
;
505 }
506 return true1;
507 }
508
509 return false0;
510}
511
512static int journal_file_verify_header(JournalFile *f) {
513 uint64_t arena_size, header_size;
514
515 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 515
, __PRETTY_FUNCTION__); } while (0)
;
516 assert(f->header)do { if ((__builtin_expect(!!(!(f->header)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f->header"), "../src/journal/journal-file.c"
, 516, __PRETTY_FUNCTION__); } while (0)
;
517
518 if (memcmp(f->header->signature, HEADER_SIGNATURE((char[]) { 'L', 'P', 'K', 'S', 'H', 'H', 'R', 'H' }), 8))
519 return -EBADMSG74;
520
521 /* In both read and write mode we refuse to open files with incompatible
522 * flags we don't know. */
523 if (warn_wrong_flags(f, false0))
524 return -EPROTONOSUPPORT93;
525
526 /* When open for writing we refuse to open files with compatible flags, too. */
527 if (f->writable && warn_wrong_flags(f, true1))
528 return -EPROTONOSUPPORT93;
529
530 if (f->header->state >= _STATE_MAX)
531 return -EBADMSG74;
532
533 header_size = le64toh(f->header->header_size);
534
535 /* The first addition was n_data, so check that we are at least this large */
536 if (header_size < HEADER_SIZE_MIN(((__builtin_offsetof(Header, n_data)) + 7ULL) & ~7ULL))
537 return -EBADMSG74;
538
539 if (JOURNAL_HEADER_SEALED(f->header)(!!(le32toh((f->header)->compatible_flags) & HEADER_COMPATIBLE_SEALED
))
&& !JOURNAL_HEADER_CONTAINS(f->header, n_entry_arrays)(le64toh((f->header)->header_size) >= __builtin_offsetof
(Header, n_entry_arrays) + sizeof((f->header)->n_entry_arrays
))
)
540 return -EBADMSG74;
541
542 arena_size = le64toh(f->header->arena_size);
543
544 if (UINT64_MAX(18446744073709551615UL) - header_size < arena_size || header_size + arena_size > (uint64_t) f->last_stat.st_size)
545 return -ENODATA61;
546
547 if (le64toh(f->header->tail_object_offset) > header_size + arena_size)
548 return -ENODATA61;
549
550 if (!VALID64(le64toh(f->header->data_hash_table_offset))(((le64toh(f->header->data_hash_table_offset)) & 7ULL
) == 0ULL)
||
551 !VALID64(le64toh(f->header->field_hash_table_offset))(((le64toh(f->header->field_hash_table_offset)) & 7ULL
) == 0ULL)
||
552 !VALID64(le64toh(f->header->tail_object_offset))(((le64toh(f->header->tail_object_offset)) & 7ULL) ==
0ULL)
||
553 !VALID64(le64toh(f->header->entry_array_offset))(((le64toh(f->header->entry_array_offset)) & 7ULL) ==
0ULL)
)
554 return -ENODATA61;
555
556 if (f->writable) {
557 sd_id128_t machine_id;
558 uint8_t state;
559 int r;
560
561 r = sd_id128_get_machine(&machine_id);
562 if (r < 0)
563 return r;
564
565 if (!sd_id128_equal(machine_id, f->header->machine_id))
566 return -EHOSTDOWN112;
567
568 state = f->header->state;
569
570 if (state == STATE_ARCHIVED)
571 return -ESHUTDOWN108; /* Already archived */
572 else if (state == STATE_ONLINE) {
573 log_debug("Journal file %s is already online. Assuming unclean closing.", f->path)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 573, __func__, "Journal file %s is already online. Assuming unclean closing."
, f->path) : -abs(_e); })
;
574 return -EBUSY16;
575 } else if (state != STATE_OFFLINE) {
576 log_debug("Journal file %s has unknown state %i.", f->path, state)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 576, __func__, "Journal file %s has unknown state %i."
, f->path, state) : -abs(_e); })
;
577 return -EBUSY16;
578 }
579
580 if (f->header->field_hash_table_size == 0 || f->header->data_hash_table_size == 0)
581 return -EBADMSG74;
582
583 /* Don't permit appending to files from the future. Because otherwise the realtime timestamps wouldn't
584 * be strictly ordered in the entries in the file anymore, and we can't have that since it breaks
585 * bisection. */
586 if (le64toh(f->header->tail_entry_realtime) > now(CLOCK_REALTIME0)) {
587 log_debug("Journal file %s is from the future, refusing to append new data to it that'd be older.", f->path)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 587, __func__, "Journal file %s is from the future, refusing to append new data to it that'd be older."
, f->path) : -abs(_e); })
;
588 return -ETXTBSY26;
589 }
590 }
591
592 f->compress_xz = JOURNAL_HEADER_COMPRESSED_XZ(f->header)(!!(le32toh((f->header)->incompatible_flags) & HEADER_INCOMPATIBLE_COMPRESSED_XZ
))
;
593 f->compress_lz4 = JOURNAL_HEADER_COMPRESSED_LZ4(f->header)(!!(le32toh((f->header)->incompatible_flags) & HEADER_INCOMPATIBLE_COMPRESSED_LZ4
))
;
594
595 f->seal = JOURNAL_HEADER_SEALED(f->header)(!!(le32toh((f->header)->compatible_flags) & HEADER_COMPATIBLE_SEALED
))
;
596
597 return 0;
598}
599
600int journal_file_fstat(JournalFile *f) {
601 int r;
602
603 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 603
, __PRETTY_FUNCTION__); } while (0)
;
604 assert(f->fd >= 0)do { if ((__builtin_expect(!!(!(f->fd >= 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f->fd >= 0"), "../src/journal/journal-file.c"
, 604, __PRETTY_FUNCTION__); } while (0)
;
605
606 if (fstat(f->fd, &f->last_stat) < 0)
607 return -errno(*__errno_location ());
608
609 f->last_stat_usec = now(CLOCK_MONOTONIC1);
610
611 /* Refuse dealing with with files that aren't regular */
612 r = stat_verify_regular(&f->last_stat);
613 if (r < 0)
614 return r;
615
616 /* Refuse appending to files that are already deleted */
617 if (f->last_stat.st_nlink <= 0)
618 return -EIDRM43;
619
620 return 0;
621}
622
623static int journal_file_allocate(JournalFile *f, uint64_t offset, uint64_t size) {
624 uint64_t old_size, new_size;
625 int r;
626
627 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 627
, __PRETTY_FUNCTION__); } while (0)
;
628 assert(f->header)do { if ((__builtin_expect(!!(!(f->header)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f->header"), "../src/journal/journal-file.c"
, 628, __PRETTY_FUNCTION__); } while (0)
;
629
630 /* We assume that this file is not sparse, and we know that
631 * for sure, since we always call posix_fallocate()
632 * ourselves */
633
634 if (mmap_cache_got_sigbus(f->mmap, f->cache_fd))
635 return -EIO5;
636
637 old_size =
638 le64toh(f->header->header_size) +
639 le64toh(f->header->arena_size);
640
641 new_size = PAGE_ALIGN(offset + size)ALIGN_TO((offset + size), page_size());
642 if (new_size < le64toh(f->header->header_size))
643 new_size = le64toh(f->header->header_size);
644
645 if (new_size <= old_size) {
646
647 /* We already pre-allocated enough space, but before
648 * we write to it, let's check with fstat() if the
649 * file got deleted, in order make sure we don't throw
650 * away the data immediately. Don't check fstat() for
651 * all writes though, but only once ever 10s. */
652
653 if (f->last_stat_usec + LAST_STAT_REFRESH_USEC(5*((usec_t) 1000000ULL)) > now(CLOCK_MONOTONIC1))
654 return 0;
655
656 return journal_file_fstat(f);
657 }
658
659 /* Allocate more space. */
660
661 if (f->metrics.max_size > 0 && new_size > f->metrics.max_size)
662 return -E2BIG7;
663
664 if (new_size > f->metrics.min_size && f->metrics.keep_free > 0) {
665 struct statvfs svfs;
666
667 if (fstatvfs(f->fd, &svfs) >= 0) {
668 uint64_t available;
669
670 available = LESS_BY((uint64_t) svfs.f_bfree * (uint64_t) svfs.f_bsize, f->metrics.keep_free)__extension__ ({ const typeof(((uint64_t) svfs.f_bfree * (uint64_t
) svfs.f_bsize)) __unique_prefix_A22 = (((uint64_t) svfs.f_bfree
* (uint64_t) svfs.f_bsize)); const typeof((f->metrics.keep_free
)) __unique_prefix_B23 = ((f->metrics.keep_free)); __unique_prefix_A22
> __unique_prefix_B23 ? __unique_prefix_A22 - __unique_prefix_B23
: 0; })
;
671
672 if (new_size - old_size > available)
673 return -E2BIG7;
674 }
675 }
676
677 /* Increase by larger blocks at once */
678 new_size = DIV_ROUND_UP(new_size, FILE_SIZE_INCREASE)({ const typeof((new_size)) __unique_prefix_X24 = ((new_size)
); const typeof(((8ULL*1024ULL*1024ULL))) __unique_prefix_Y25
= (((8ULL*1024ULL*1024ULL))); (__unique_prefix_X24 / __unique_prefix_Y25
+ !!(__unique_prefix_X24 % __unique_prefix_Y25)); })
* FILE_SIZE_INCREASE(8ULL*1024ULL*1024ULL);
679 if (f->metrics.max_size > 0 && new_size > f->metrics.max_size)
680 new_size = f->metrics.max_size;
681
682 /* Note that the glibc fallocate() fallback is very
683 inefficient, hence we try to minimize the allocation area
684 as we can. */
685 r = posix_fallocate(f->fd, old_size, new_size - old_size);
686 if (r != 0)
687 return -r;
688
689 f->header->arena_size = htole64(new_size - le64toh(f->header->header_size));
690
691 return journal_file_fstat(f);
692}
693
694static unsigned type_to_context(ObjectType type) {
695 /* One context for each type, plus one catch-all for the rest */
696 assert_cc(_OBJECT_TYPE_MAX <= MMAP_CACHE_MAX_CONTEXTS)GCC diagnostic push ; GCC diagnostic ignored "-Wdeclaration-after-statement"
; struct _assert_struct_26 { char x[(_OBJECT_TYPE_MAX <= 9
) ? 0 : -1]; }; GCC diagnostic pop
;
697 assert_cc(CONTEXT_HEADER < MMAP_CACHE_MAX_CONTEXTS)GCC diagnostic push ; GCC diagnostic ignored "-Wdeclaration-after-statement"
; struct _assert_struct_27 { char x[(_OBJECT_TYPE_MAX < 9
) ? 0 : -1]; }; GCC diagnostic pop
;
698 return type > OBJECT_UNUSED && type < _OBJECT_TYPE_MAX ? type : 0;
699}
700
701static int journal_file_move_to(JournalFile *f, ObjectType type, bool_Bool keep_always, uint64_t offset, uint64_t size, void **ret, size_t *ret_size) {
702 int r;
703
704 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 704
, __PRETTY_FUNCTION__); } while (0)
;
705 assert(ret)do { if ((__builtin_expect(!!(!(ret)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ret"), "../src/journal/journal-file.c",
705, __PRETTY_FUNCTION__); } while (0)
;
706
707 if (size <= 0)
708 return -EINVAL22;
709
710 /* Avoid SIGBUS on invalid accesses */
711 if (offset + size > (uint64_t) f->last_stat.st_size) {
712 /* Hmm, out of range? Let's refresh the fstat() data
713 * first, before we trust that check. */
714
715 r = journal_file_fstat(f);
716 if (r < 0)
717 return r;
718
719 if (offset + size > (uint64_t) f->last_stat.st_size)
720 return -EADDRNOTAVAIL99;
721 }
722
723 return mmap_cache_get(f->mmap, f->cache_fd, f->prot, type_to_context(type), keep_always, offset, size, &f->last_stat, ret, ret_size);
724}
725
726static uint64_t minimum_header_size(Object *o) {
727
728 static const uint64_t table[] = {
729 [OBJECT_DATA] = sizeof(DataObject),
730 [OBJECT_FIELD] = sizeof(FieldObject),
731 [OBJECT_ENTRY] = sizeof(EntryObject),
732 [OBJECT_DATA_HASH_TABLE] = sizeof(HashTableObject),
733 [OBJECT_FIELD_HASH_TABLE] = sizeof(HashTableObject),
734 [OBJECT_ENTRY_ARRAY] = sizeof(EntryArrayObject),
735 [OBJECT_TAG] = sizeof(TagObject),
736 };
737
738 if (o->object.type >= ELEMENTSOF(table)__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(table), typeof(&*(table))), sizeof(table)/sizeof(
(table)[0]), ((void)0)))
|| table[o->object.type] <= 0)
739 return sizeof(ObjectHeader);
740
741 return table[o->object.type];
742}
743
744/* Lightweight object checks. We want this to be fast, so that we won't
745 * slowdown every journal_file_move_to_object() call too much. */
746static int journal_file_check_object(JournalFile *f, uint64_t offset, Object *o) {
747 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 747
, __PRETTY_FUNCTION__); } while (0)
;
748 assert(o)do { if ((__builtin_expect(!!(!(o)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("o"), "../src/journal/journal-file.c", 748
, __PRETTY_FUNCTION__); } while (0)
;
749
750 switch (o->object.type) {
751
752 case OBJECT_DATA: {
753 if ((le64toh(o->data.entry_offset) == 0) ^ (le64toh(o->data.n_entries) == 0)) {
754 log_debug("Bad n_entries: %"PRIu64": %"PRIu64,({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 755, __func__, "Bad n_entries: %"
"l" "u"": %""l" "u", le64toh(o->data.n_entries), offset) :
-abs(_e); })
755 le64toh(o->data.n_entries), offset)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 755, __func__, "Bad n_entries: %"
"l" "u"": %""l" "u", le64toh(o->data.n_entries), offset) :
-abs(_e); })
;
756 return -EBADMSG74;
757 }
758
759 if (le64toh(o->object.size) - offsetof(DataObject, payload)__builtin_offsetof(DataObject, payload) <= 0) {
760 log_debug("Bad object size (<= %zu): %"PRIu64": %"PRIu64,({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 763, __func__, "Bad object size (<= %zu): %"
"l" "u"": %""l" "u", __builtin_offsetof(DataObject, payload),
le64toh(o->object.size), offset) : -abs(_e); })
761 offsetof(DataObject, payload),({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 763, __func__, "Bad object size (<= %zu): %"
"l" "u"": %""l" "u", __builtin_offsetof(DataObject, payload),
le64toh(o->object.size), offset) : -abs(_e); })
762 le64toh(o->object.size),({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 763, __func__, "Bad object size (<= %zu): %"
"l" "u"": %""l" "u", __builtin_offsetof(DataObject, payload),
le64toh(o->object.size), offset) : -abs(_e); })
763 offset)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 763, __func__, "Bad object size (<= %zu): %"
"l" "u"": %""l" "u", __builtin_offsetof(DataObject, payload),
le64toh(o->object.size), offset) : -abs(_e); })
;
764 return -EBADMSG74;
765 }
766
767 if (!VALID64(le64toh(o->data.next_hash_offset))(((le64toh(o->data.next_hash_offset)) & 7ULL) == 0ULL) ||
768 !VALID64(le64toh(o->data.next_field_offset))(((le64toh(o->data.next_field_offset)) & 7ULL) == 0ULL
)
||
769 !VALID64(le64toh(o->data.entry_offset))(((le64toh(o->data.entry_offset)) & 7ULL) == 0ULL) ||
770 !VALID64(le64toh(o->data.entry_array_offset))(((le64toh(o->data.entry_array_offset)) & 7ULL) == 0ULL
)
) {
771 log_debug("Invalid offset, next_hash_offset="OFSfmt", next_field_offset="OFSfmt({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 777, __func__, "Invalid offset, next_hash_offset="
"%06""l" "x"", next_field_offset=""%06""l" "x" ", entry_offset="
"%06""l" "x"", entry_array_offset=""%06""l" "x"": %""l" "u", le64toh
(o->data.next_hash_offset), le64toh(o->data.next_field_offset
), le64toh(o->data.entry_offset), le64toh(o->data.entry_array_offset
), offset) : -abs(_e); })
772 ", entry_offset="OFSfmt", entry_array_offset="OFSfmt": %"PRIu64,({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 777, __func__, "Invalid offset, next_hash_offset="
"%06""l" "x"", next_field_offset=""%06""l" "x" ", entry_offset="
"%06""l" "x"", entry_array_offset=""%06""l" "x"": %""l" "u", le64toh
(o->data.next_hash_offset), le64toh(o->data.next_field_offset
), le64toh(o->data.entry_offset), le64toh(o->data.entry_array_offset
), offset) : -abs(_e); })
773 le64toh(o->data.next_hash_offset),({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 777, __func__, "Invalid offset, next_hash_offset="
"%06""l" "x"", next_field_offset=""%06""l" "x" ", entry_offset="
"%06""l" "x"", entry_array_offset=""%06""l" "x"": %""l" "u", le64toh
(o->data.next_hash_offset), le64toh(o->data.next_field_offset
), le64toh(o->data.entry_offset), le64toh(o->data.entry_array_offset
), offset) : -abs(_e); })
774 le64toh(o->data.next_field_offset),({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 777, __func__, "Invalid offset, next_hash_offset="
"%06""l" "x"", next_field_offset=""%06""l" "x" ", entry_offset="
"%06""l" "x"", entry_array_offset=""%06""l" "x"": %""l" "u", le64toh
(o->data.next_hash_offset), le64toh(o->data.next_field_offset
), le64toh(o->data.entry_offset), le64toh(o->data.entry_array_offset
), offset) : -abs(_e); })
775 le64toh(o->data.entry_offset),({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 777, __func__, "Invalid offset, next_hash_offset="
"%06""l" "x"", next_field_offset=""%06""l" "x" ", entry_offset="
"%06""l" "x"", entry_array_offset=""%06""l" "x"": %""l" "u", le64toh
(o->data.next_hash_offset), le64toh(o->data.next_field_offset
), le64toh(o->data.entry_offset), le64toh(o->data.entry_array_offset
), offset) : -abs(_e); })
776 le64toh(o->data.entry_array_offset),({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 777, __func__, "Invalid offset, next_hash_offset="
"%06""l" "x"", next_field_offset=""%06""l" "x" ", entry_offset="
"%06""l" "x"", entry_array_offset=""%06""l" "x"": %""l" "u", le64toh
(o->data.next_hash_offset), le64toh(o->data.next_field_offset
), le64toh(o->data.entry_offset), le64toh(o->data.entry_array_offset
), offset) : -abs(_e); })
777 offset)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 777, __func__, "Invalid offset, next_hash_offset="
"%06""l" "x"", next_field_offset=""%06""l" "x" ", entry_offset="
"%06""l" "x"", entry_array_offset=""%06""l" "x"": %""l" "u", le64toh
(o->data.next_hash_offset), le64toh(o->data.next_field_offset
), le64toh(o->data.entry_offset), le64toh(o->data.entry_array_offset
), offset) : -abs(_e); })
;
778 return -EBADMSG74;
779 }
780
781 break;
782 }
783
784 case OBJECT_FIELD:
785 if (le64toh(o->object.size) - offsetof(FieldObject, payload)__builtin_offsetof(FieldObject, payload) <= 0) {
786 log_debug(({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 790, __func__, "Bad field size (<= %zu): %"
"l" "u"": %""l" "u", __builtin_offsetof(FieldObject, payload)
, le64toh(o->object.size), offset) : -abs(_e); })
787 "Bad field size (<= %zu): %"PRIu64": %"PRIu64,({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 790, __func__, "Bad field size (<= %zu): %"
"l" "u"": %""l" "u", __builtin_offsetof(FieldObject, payload)
, le64toh(o->object.size), offset) : -abs(_e); })
788 offsetof(FieldObject, payload),({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 790, __func__, "Bad field size (<= %zu): %"
"l" "u"": %""l" "u", __builtin_offsetof(FieldObject, payload)
, le64toh(o->object.size), offset) : -abs(_e); })
789 le64toh(o->object.size),({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 790, __func__, "Bad field size (<= %zu): %"
"l" "u"": %""l" "u", __builtin_offsetof(FieldObject, payload)
, le64toh(o->object.size), offset) : -abs(_e); })
790 offset)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 790, __func__, "Bad field size (<= %zu): %"
"l" "u"": %""l" "u", __builtin_offsetof(FieldObject, payload)
, le64toh(o->object.size), offset) : -abs(_e); })
;
791 return -EBADMSG74;
792 }
793
794 if (!VALID64(le64toh(o->field.next_hash_offset))(((le64toh(o->field.next_hash_offset)) & 7ULL) == 0ULL
)
||
795 !VALID64(le64toh(o->field.head_data_offset))(((le64toh(o->field.head_data_offset)) & 7ULL) == 0ULL
)
) {
796 log_debug(({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 801, __func__, "Invalid offset, next_hash_offset="
"%06""l" "x" ", head_data_offset=""%06""l" "x"": %""l" "u", le64toh
(o->field.next_hash_offset), le64toh(o->field.head_data_offset
), offset) : -abs(_e); })
797 "Invalid offset, next_hash_offset="OFSfmt({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 801, __func__, "Invalid offset, next_hash_offset="
"%06""l" "x" ", head_data_offset=""%06""l" "x"": %""l" "u", le64toh
(o->field.next_hash_offset), le64toh(o->field.head_data_offset
), offset) : -abs(_e); })
798 ", head_data_offset="OFSfmt": %"PRIu64,({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 801, __func__, "Invalid offset, next_hash_offset="
"%06""l" "x" ", head_data_offset=""%06""l" "x"": %""l" "u", le64toh
(o->field.next_hash_offset), le64toh(o->field.head_data_offset
), offset) : -abs(_e); })
799 le64toh(o->field.next_hash_offset),({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 801, __func__, "Invalid offset, next_hash_offset="
"%06""l" "x" ", head_data_offset=""%06""l" "x"": %""l" "u", le64toh
(o->field.next_hash_offset), le64toh(o->field.head_data_offset
), offset) : -abs(_e); })
800 le64toh(o->field.head_data_offset),({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 801, __func__, "Invalid offset, next_hash_offset="
"%06""l" "x" ", head_data_offset=""%06""l" "x"": %""l" "u", le64toh
(o->field.next_hash_offset), le64toh(o->field.head_data_offset
), offset) : -abs(_e); })
801 offset)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 801, __func__, "Invalid offset, next_hash_offset="
"%06""l" "x" ", head_data_offset=""%06""l" "x"": %""l" "u", le64toh
(o->field.next_hash_offset), le64toh(o->field.head_data_offset
), offset) : -abs(_e); })
;
802 return -EBADMSG74;
803 }
804 break;
805
806 case OBJECT_ENTRY:
807 if ((le64toh(o->object.size) - offsetof(EntryObject, items)__builtin_offsetof(EntryObject, items)) % sizeof(EntryItem) != 0) {
808 log_debug(({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 812, __func__, "Bad entry size (<= %zu): %"
"l" "u"": %""l" "u", __builtin_offsetof(EntryObject, items), le64toh
(o->object.size), offset) : -abs(_e); })
809 "Bad entry size (<= %zu): %"PRIu64": %"PRIu64,({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 812, __func__, "Bad entry size (<= %zu): %"
"l" "u"": %""l" "u", __builtin_offsetof(EntryObject, items), le64toh
(o->object.size), offset) : -abs(_e); })
810 offsetof(EntryObject, items),({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 812, __func__, "Bad entry size (<= %zu): %"
"l" "u"": %""l" "u", __builtin_offsetof(EntryObject, items), le64toh
(o->object.size), offset) : -abs(_e); })
811 le64toh(o->object.size),({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 812, __func__, "Bad entry size (<= %zu): %"
"l" "u"": %""l" "u", __builtin_offsetof(EntryObject, items), le64toh
(o->object.size), offset) : -abs(_e); })
812 offset)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 812, __func__, "Bad entry size (<= %zu): %"
"l" "u"": %""l" "u", __builtin_offsetof(EntryObject, items), le64toh
(o->object.size), offset) : -abs(_e); })
;
813 return -EBADMSG74;
814 }
815
816 if ((le64toh(o->object.size) - offsetof(EntryObject, items)__builtin_offsetof(EntryObject, items)) / sizeof(EntryItem) <= 0) {
817 log_debug(({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 820, __func__, "Invalid number items in entry: %"
"l" "u"": %""l" "u", (le64toh(o->object.size) - __builtin_offsetof
(EntryObject, items)) / sizeof(EntryItem), offset) : -abs(_e)
; })
818 "Invalid number items in entry: %"PRIu64": %"PRIu64,({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 820, __func__, "Invalid number items in entry: %"
"l" "u"": %""l" "u", (le64toh(o->object.size) - __builtin_offsetof
(EntryObject, items)) / sizeof(EntryItem), offset) : -abs(_e)
; })
819 (le64toh(o->object.size) - offsetof(EntryObject, items)) / sizeof(EntryItem),({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 820, __func__, "Invalid number items in entry: %"
"l" "u"": %""l" "u", (le64toh(o->object.size) - __builtin_offsetof
(EntryObject, items)) / sizeof(EntryItem), offset) : -abs(_e)
; })
820 offset)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 820, __func__, "Invalid number items in entry: %"
"l" "u"": %""l" "u", (le64toh(o->object.size) - __builtin_offsetof
(EntryObject, items)) / sizeof(EntryItem), offset) : -abs(_e)
; })
;
821 return -EBADMSG74;
822 }
823
824 if (le64toh(o->entry.seqnum) <= 0) {
825 log_debug(({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 828, __func__, "Invalid entry seqnum: %"
"l" "x"": %""l" "u", le64toh(o->entry.seqnum), offset) : -
abs(_e); })
826 "Invalid entry seqnum: %"PRIx64": %"PRIu64,({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 828, __func__, "Invalid entry seqnum: %"
"l" "x"": %""l" "u", le64toh(o->entry.seqnum), offset) : -
abs(_e); })
827 le64toh(o->entry.seqnum),({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 828, __func__, "Invalid entry seqnum: %"
"l" "x"": %""l" "u", le64toh(o->entry.seqnum), offset) : -
abs(_e); })
828 offset)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 828, __func__, "Invalid entry seqnum: %"
"l" "x"": %""l" "u", le64toh(o->entry.seqnum), offset) : -
abs(_e); })
;
829 return -EBADMSG74;
830 }
831
832 if (!VALID_REALTIME(le64toh(o->entry.realtime))) {
833 log_debug(({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 836, __func__, "Invalid entry realtime timestamp: %"
"l" "u"": %""l" "u", le64toh(o->entry.realtime), offset) :
-abs(_e); })
834 "Invalid entry realtime timestamp: %"PRIu64": %"PRIu64,({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 836, __func__, "Invalid entry realtime timestamp: %"
"l" "u"": %""l" "u", le64toh(o->entry.realtime), offset) :
-abs(_e); })
835 le64toh(o->entry.realtime),({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 836, __func__, "Invalid entry realtime timestamp: %"
"l" "u"": %""l" "u", le64toh(o->entry.realtime), offset) :
-abs(_e); })
836 offset)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 836, __func__, "Invalid entry realtime timestamp: %"
"l" "u"": %""l" "u", le64toh(o->entry.realtime), offset) :
-abs(_e); })
;
837 return -EBADMSG74;
838 }
839
840 if (!VALID_MONOTONIC(le64toh(o->entry.monotonic))) {
841 log_debug(({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 844, __func__, "Invalid entry monotonic timestamp: %"
"l" "u"": %""l" "u", le64toh(o->entry.monotonic), offset) :
-abs(_e); })
842 "Invalid entry monotonic timestamp: %"PRIu64": %"PRIu64,({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 844, __func__, "Invalid entry monotonic timestamp: %"
"l" "u"": %""l" "u", le64toh(o->entry.monotonic), offset) :
-abs(_e); })
843 le64toh(o->entry.monotonic),({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 844, __func__, "Invalid entry monotonic timestamp: %"
"l" "u"": %""l" "u", le64toh(o->entry.monotonic), offset) :
-abs(_e); })
844 offset)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 844, __func__, "Invalid entry monotonic timestamp: %"
"l" "u"": %""l" "u", le64toh(o->entry.monotonic), offset) :
-abs(_e); })
;
845 return -EBADMSG74;
846 }
847
848 break;
849
850 case OBJECT_DATA_HASH_TABLE:
851 case OBJECT_FIELD_HASH_TABLE:
852 if ((le64toh(o->object.size) - offsetof(HashTableObject, items)__builtin_offsetof(HashTableObject, items)) % sizeof(HashItem) != 0 ||
853 (le64toh(o->object.size) - offsetof(HashTableObject, items)__builtin_offsetof(HashTableObject, items)) / sizeof(HashItem) <= 0) {
854 log_debug(({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 858, __func__, "Invalid %s hash table size: %"
"l" "u"": %""l" "u", o->object.type == OBJECT_DATA_HASH_TABLE
? "data" : "field", le64toh(o->object.size), offset) : -abs
(_e); })
855 "Invalid %s hash table size: %"PRIu64": %"PRIu64,({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 858, __func__, "Invalid %s hash table size: %"
"l" "u"": %""l" "u", o->object.type == OBJECT_DATA_HASH_TABLE
? "data" : "field", le64toh(o->object.size), offset) : -abs
(_e); })
856 o->object.type == OBJECT_DATA_HASH_TABLE ? "data" : "field",({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 858, __func__, "Invalid %s hash table size: %"
"l" "u"": %""l" "u", o->object.type == OBJECT_DATA_HASH_TABLE
? "data" : "field", le64toh(o->object.size), offset) : -abs
(_e); })
857 le64toh(o->object.size),({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 858, __func__, "Invalid %s hash table size: %"
"l" "u"": %""l" "u", o->object.type == OBJECT_DATA_HASH_TABLE
? "data" : "field", le64toh(o->object.size), offset) : -abs
(_e); })
858 offset)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 858, __func__, "Invalid %s hash table size: %"
"l" "u"": %""l" "u", o->object.type == OBJECT_DATA_HASH_TABLE
? "data" : "field", le64toh(o->object.size), offset) : -abs
(_e); })
;
859 return -EBADMSG74;
860 }
861
862 break;
863
864 case OBJECT_ENTRY_ARRAY:
865 if ((le64toh(o->object.size) - offsetof(EntryArrayObject, items)__builtin_offsetof(EntryArrayObject, items)) % sizeof(le64_t) != 0 ||
866 (le64toh(o->object.size) - offsetof(EntryArrayObject, items)__builtin_offsetof(EntryArrayObject, items)) / sizeof(le64_t) <= 0) {
867 log_debug(({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 870, __func__, "Invalid object entry array size: %"
"l" "u"": %""l" "u", le64toh(o->object.size), offset) : -abs
(_e); })
868 "Invalid object entry array size: %"PRIu64": %"PRIu64,({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 870, __func__, "Invalid object entry array size: %"
"l" "u"": %""l" "u", le64toh(o->object.size), offset) : -abs
(_e); })
869 le64toh(o->object.size),({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 870, __func__, "Invalid object entry array size: %"
"l" "u"": %""l" "u", le64toh(o->object.size), offset) : -abs
(_e); })
870 offset)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 870, __func__, "Invalid object entry array size: %"
"l" "u"": %""l" "u", le64toh(o->object.size), offset) : -abs
(_e); })
;
871 return -EBADMSG74;
872 }
873
874 if (!VALID64(le64toh(o->entry_array.next_entry_array_offset))(((le64toh(o->entry_array.next_entry_array_offset)) & 7ULL
) == 0ULL)
) {
875 log_debug(({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 878, __func__, "Invalid object entry array next_entry_array_offset: "
"%06""l" "x"": %""l" "u", le64toh(o->entry_array.next_entry_array_offset
), offset) : -abs(_e); })
876 "Invalid object entry array next_entry_array_offset: "OFSfmt": %"PRIu64,({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 878, __func__, "Invalid object entry array next_entry_array_offset: "
"%06""l" "x"": %""l" "u", le64toh(o->entry_array.next_entry_array_offset
), offset) : -abs(_e); })
877 le64toh(o->entry_array.next_entry_array_offset),({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 878, __func__, "Invalid object entry array next_entry_array_offset: "
"%06""l" "x"": %""l" "u", le64toh(o->entry_array.next_entry_array_offset
), offset) : -abs(_e); })
878 offset)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 878, __func__, "Invalid object entry array next_entry_array_offset: "
"%06""l" "x"": %""l" "u", le64toh(o->entry_array.next_entry_array_offset
), offset) : -abs(_e); })
;
879 return -EBADMSG74;
880 }
881
882 break;
883
884 case OBJECT_TAG:
885 if (le64toh(o->object.size) != sizeof(TagObject)) {
886 log_debug(({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 889, __func__, "Invalid object tag size: %"
"l" "u"": %""l" "u", le64toh(o->object.size), offset) : -abs
(_e); })
887 "Invalid object tag size: %"PRIu64": %"PRIu64,({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 889, __func__, "Invalid object tag size: %"
"l" "u"": %""l" "u", le64toh(o->object.size), offset) : -abs
(_e); })
888 le64toh(o->object.size),({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 889, __func__, "Invalid object tag size: %"
"l" "u"": %""l" "u", le64toh(o->object.size), offset) : -abs
(_e); })
889 offset)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 889, __func__, "Invalid object tag size: %"
"l" "u"": %""l" "u", le64toh(o->object.size), offset) : -abs
(_e); })
;
890 return -EBADMSG74;
891 }
892
893 if (!VALID_EPOCH(le64toh(o->tag.epoch))) {
894 log_debug(({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 897, __func__, "Invalid object tag epoch: %"
"l" "u"": %""l" "u", le64toh(o->tag.epoch), offset) : -abs
(_e); })
895 "Invalid object tag epoch: %"PRIu64": %"PRIu64,({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 897, __func__, "Invalid object tag epoch: %"
"l" "u"": %""l" "u", le64toh(o->tag.epoch), offset) : -abs
(_e); })
896 le64toh(o->tag.epoch),({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 897, __func__, "Invalid object tag epoch: %"
"l" "u"": %""l" "u", le64toh(o->tag.epoch), offset) : -abs
(_e); })
897 offset)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 897, __func__, "Invalid object tag epoch: %"
"l" "u"": %""l" "u", le64toh(o->tag.epoch), offset) : -abs
(_e); })
;
898 return -EBADMSG74;
899 }
900
901 break;
902 }
903
904 return 0;
905}
906
907int journal_file_move_to_object(JournalFile *f, ObjectType type, uint64_t offset, Object **ret) {
908 int r;
909 void *t;
910 size_t tsize;
911 Object *o;
912 uint64_t s;
913
914 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 914
, __PRETTY_FUNCTION__); } while (0)
;
915 assert(ret)do { if ((__builtin_expect(!!(!(ret)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ret"), "../src/journal/journal-file.c",
915, __PRETTY_FUNCTION__); } while (0)
;
916
917 /* Objects may only be located at multiple of 64 bit */
918 if (!VALID64(offset)(((offset) & 7ULL) == 0ULL)) {
919 log_debug("Attempt to move to object at non-64bit boundary: %" PRIu64, offset)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 919, __func__, "Attempt to move to object at non-64bit boundary: %"
"l" "u", offset) : -abs(_e); })
;
920 return -EBADMSG74;
921 }
922
923 /* Object may not be located in the file header */
924 if (offset < le64toh(f->header->header_size)) {
925 log_debug("Attempt to move to object located in file header: %" PRIu64, offset)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 925, __func__, "Attempt to move to object located in file header: %"
"l" "u", offset) : -abs(_e); })
;
926 return -EBADMSG74;
927 }
928
929 r = journal_file_move_to(f, type, false0, offset, sizeof(ObjectHeader), &t, &tsize);
930 if (r < 0)
931 return r;
932
933 o = (Object*) t;
934 s = le64toh(o->object.size);
935
936 if (s == 0) {
937 log_debug("Attempt to move to uninitialized object: %" PRIu64, offset)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 937, __func__, "Attempt to move to uninitialized object: %"
"l" "u", offset) : -abs(_e); })
;
938 return -EBADMSG74;
939 }
940 if (s < sizeof(ObjectHeader)) {
941 log_debug("Attempt to move to overly short object: %" PRIu64, offset)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 941, __func__, "Attempt to move to overly short object: %"
"l" "u", offset) : -abs(_e); })
;
942 return -EBADMSG74;
943 }
944
945 if (o->object.type <= OBJECT_UNUSED) {
946 log_debug("Attempt to move to object with invalid type: %" PRIu64, offset)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 946, __func__, "Attempt to move to object with invalid type: %"
"l" "u", offset) : -abs(_e); })
;
947 return -EBADMSG74;
948 }
949
950 if (s < minimum_header_size(o)) {
951 log_debug("Attempt to move to truncated object: %" PRIu64, offset)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 951, __func__, "Attempt to move to truncated object: %"
"l" "u", offset) : -abs(_e); })
;
952 return -EBADMSG74;
953 }
954
955 if (type > OBJECT_UNUSED && o->object.type != type) {
956 log_debug("Attempt to move to object of unexpected type: %" PRIu64, offset)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 956, __func__, "Attempt to move to object of unexpected type: %"
"l" "u", offset) : -abs(_e); })
;
957 return -EBADMSG74;
958 }
959
960 if (s > tsize) {
961 r = journal_file_move_to(f, type, false0, offset, s, &t, NULL((void*)0));
962 if (r < 0)
963 return r;
964
965 o = (Object*) t;
966 }
967
968 r = journal_file_check_object(f, offset, o);
969 if (r < 0)
970 return r;
971
972 *ret = o;
973 return 0;
974}
975
976static uint64_t journal_file_entry_seqnum(JournalFile *f, uint64_t *seqnum) {
977 uint64_t r;
978
979 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 979
, __PRETTY_FUNCTION__); } while (0)
;
980 assert(f->header)do { if ((__builtin_expect(!!(!(f->header)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f->header"), "../src/journal/journal-file.c"
, 980, __PRETTY_FUNCTION__); } while (0)
;
981
982 r = le64toh(f->header->tail_entry_seqnum) + 1;
983
984 if (seqnum) {
985 /* If an external seqnum counter was passed, we update
986 * both the local and the external one, and set it to
987 * the maximum of both */
988
989 if (*seqnum + 1 > r)
990 r = *seqnum + 1;
991
992 *seqnum = r;
993 }
994
995 f->header->tail_entry_seqnum = htole64(r);
996
997 if (f->header->head_entry_seqnum == 0)
998 f->header->head_entry_seqnum = htole64(r);
999
1000 return r;
1001}
1002
1003int journal_file_append_object(JournalFile *f, ObjectType type, uint64_t size, Object **ret, uint64_t *offset) {
1004 int r;
1005 uint64_t p;
1006 Object *tail, *o;
1007 void *t;
1008
1009 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 1009
, __PRETTY_FUNCTION__); } while (0)
;
1010 assert(f->header)do { if ((__builtin_expect(!!(!(f->header)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f->header"), "../src/journal/journal-file.c"
, 1010, __PRETTY_FUNCTION__); } while (0)
;
1011 assert(type > OBJECT_UNUSED && type < _OBJECT_TYPE_MAX)do { if ((__builtin_expect(!!(!(type > OBJECT_UNUSED &&
type < _OBJECT_TYPE_MAX)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("type > OBJECT_UNUSED && type < _OBJECT_TYPE_MAX"
), "../src/journal/journal-file.c", 1011, __PRETTY_FUNCTION__
); } while (0)
;
1012 assert(size >= sizeof(ObjectHeader))do { if ((__builtin_expect(!!(!(size >= sizeof(ObjectHeader
))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("size >= sizeof(ObjectHeader)"
), "../src/journal/journal-file.c", 1012, __PRETTY_FUNCTION__
); } while (0)
;
1013 assert(offset)do { if ((__builtin_expect(!!(!(offset)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("offset"), "../src/journal/journal-file.c"
, 1013, __PRETTY_FUNCTION__); } while (0)
;
1014 assert(ret)do { if ((__builtin_expect(!!(!(ret)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ret"), "../src/journal/journal-file.c",
1014, __PRETTY_FUNCTION__); } while (0)
;
1015
1016 r = journal_file_set_online(f);
1017 if (r < 0)
1018 return r;
1019
1020 p = le64toh(f->header->tail_object_offset);
1021 if (p == 0)
1022 p = le64toh(f->header->header_size);
1023 else {
1024 r = journal_file_move_to_object(f, OBJECT_UNUSED, p, &tail);
1025 if (r < 0)
1026 return r;
1027
1028 p += ALIGN64(le64toh(tail->object.size))(((le64toh(tail->object.size)) + 7ULL) & ~7ULL);
1029 }
1030
1031 r = journal_file_allocate(f, p, size);
1032 if (r < 0)
1033 return r;
1034
1035 r = journal_file_move_to(f, type, false0, p, size, &t, NULL((void*)0));
1036 if (r < 0)
1037 return r;
1038
1039 o = (Object*) t;
1040
1041 zero(o->object)(({ size_t _l_ = (sizeof(o->object)); void *_x_ = (&(o
->object)); _l_ == 0 ? _x_ : memset(_x_, 0, _l_); }))
;
1042 o->object.type = type;
1043 o->object.size = htole64(size);
1044
1045 f->header->tail_object_offset = htole64(p);
1046 f->header->n_objects = htole64(le64toh(f->header->n_objects) + 1);
1047
1048 *ret = o;
1049 *offset = p;
1050
1051 return 0;
1052}
1053
1054static int journal_file_setup_data_hash_table(JournalFile *f) {
1055 uint64_t s, p;
1056 Object *o;
1057 int r;
1058
1059 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 1059
, __PRETTY_FUNCTION__); } while (0)
;
1060 assert(f->header)do { if ((__builtin_expect(!!(!(f->header)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f->header"), "../src/journal/journal-file.c"
, 1060, __PRETTY_FUNCTION__); } while (0)
;
1061
1062 /* We estimate that we need 1 hash table entry per 768 bytes
1063 of journal file and we want to make sure we never get
1064 beyond 75% fill level. Calculate the hash table size for
1065 the maximum file size based on these metrics. */
1066
1067 s = (f->metrics.max_size * 4 / 768 / 3) * sizeof(HashItem);
1068 if (s < DEFAULT_DATA_HASH_TABLE_SIZE(2047ULL*sizeof(HashItem)))
1069 s = DEFAULT_DATA_HASH_TABLE_SIZE(2047ULL*sizeof(HashItem));
1070
1071 log_debug("Reserving %"PRIu64" entries in hash table.", s / sizeof(HashItem))({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 1071, __func__, "Reserving %"
"l" "u"" entries in hash table.", s / sizeof(HashItem)) : -abs
(_e); })
;
1072
1073 r = journal_file_append_object(f,
1074 OBJECT_DATA_HASH_TABLE,
1075 offsetof(Object, hash_table.items)__builtin_offsetof(Object, hash_table.items) + s,
1076 &o, &p);
1077 if (r < 0)
1078 return r;
1079
1080 memzero(o->hash_table.items, s)({ size_t _l_ = (s); void *_x_ = (o->hash_table.items); _l_
== 0 ? _x_ : memset(_x_, 0, _l_); })
;
1081
1082 f->header->data_hash_table_offset = htole64(p + offsetof(Object, hash_table.items)__builtin_offsetof(Object, hash_table.items));
1083 f->header->data_hash_table_size = htole64(s);
1084
1085 return 0;
1086}
1087
1088static int journal_file_setup_field_hash_table(JournalFile *f) {
1089 uint64_t s, p;
1090 Object *o;
1091 int r;
1092
1093 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 1093
, __PRETTY_FUNCTION__); } while (0)
;
1094 assert(f->header)do { if ((__builtin_expect(!!(!(f->header)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f->header"), "../src/journal/journal-file.c"
, 1094, __PRETTY_FUNCTION__); } while (0)
;
1095
1096 /* We use a fixed size hash table for the fields as this
1097 * number should grow very slowly only */
1098
1099 s = DEFAULT_FIELD_HASH_TABLE_SIZE(333ULL*sizeof(HashItem));
1100 r = journal_file_append_object(f,
1101 OBJECT_FIELD_HASH_TABLE,
1102 offsetof(Object, hash_table.items)__builtin_offsetof(Object, hash_table.items) + s,
1103 &o, &p);
1104 if (r < 0)
1105 return r;
1106
1107 memzero(o->hash_table.items, s)({ size_t _l_ = (s); void *_x_ = (o->hash_table.items); _l_
== 0 ? _x_ : memset(_x_, 0, _l_); })
;
1108
1109 f->header->field_hash_table_offset = htole64(p + offsetof(Object, hash_table.items)__builtin_offsetof(Object, hash_table.items));
1110 f->header->field_hash_table_size = htole64(s);
1111
1112 return 0;
1113}
1114
1115int journal_file_map_data_hash_table(JournalFile *f) {
1116 uint64_t s, p;
1117 void *t;
1118 int r;
1119
1120 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 1120
, __PRETTY_FUNCTION__); } while (0)
;
1121 assert(f->header)do { if ((__builtin_expect(!!(!(f->header)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f->header"), "../src/journal/journal-file.c"
, 1121, __PRETTY_FUNCTION__); } while (0)
;
1122
1123 if (f->data_hash_table)
1124 return 0;
1125
1126 p = le64toh(f->header->data_hash_table_offset);
1127 s = le64toh(f->header->data_hash_table_size);
1128
1129 r = journal_file_move_to(f,
1130 OBJECT_DATA_HASH_TABLE,
1131 true1,
1132 p, s,
1133 &t, NULL((void*)0));
1134 if (r < 0)
1135 return r;
1136
1137 f->data_hash_table = t;
1138 return 0;
1139}
1140
1141int journal_file_map_field_hash_table(JournalFile *f) {
1142 uint64_t s, p;
1143 void *t;
1144 int r;
1145
1146 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 1146
, __PRETTY_FUNCTION__); } while (0)
;
1147 assert(f->header)do { if ((__builtin_expect(!!(!(f->header)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f->header"), "../src/journal/journal-file.c"
, 1147, __PRETTY_FUNCTION__); } while (0)
;
1148
1149 if (f->field_hash_table)
1150 return 0;
1151
1152 p = le64toh(f->header->field_hash_table_offset);
1153 s = le64toh(f->header->field_hash_table_size);
1154
1155 r = journal_file_move_to(f,
1156 OBJECT_FIELD_HASH_TABLE,
1157 true1,
1158 p, s,
1159 &t, NULL((void*)0));
1160 if (r < 0)
1161 return r;
1162
1163 f->field_hash_table = t;
1164 return 0;
1165}
1166
1167static int journal_file_link_field(
1168 JournalFile *f,
1169 Object *o,
1170 uint64_t offset,
1171 uint64_t hash) {
1172
1173 uint64_t p, h, m;
1174 int r;
1175
1176 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 1176
, __PRETTY_FUNCTION__); } while (0)
;
1177 assert(f->header)do { if ((__builtin_expect(!!(!(f->header)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f->header"), "../src/journal/journal-file.c"
, 1177, __PRETTY_FUNCTION__); } while (0)
;
1178 assert(f->field_hash_table)do { if ((__builtin_expect(!!(!(f->field_hash_table)),0)))
log_assert_failed_realm(LOG_REALM_SYSTEMD, ("f->field_hash_table"
), "../src/journal/journal-file.c", 1178, __PRETTY_FUNCTION__
); } while (0)
;
1179 assert(o)do { if ((__builtin_expect(!!(!(o)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("o"), "../src/journal/journal-file.c", 1179
, __PRETTY_FUNCTION__); } while (0)
;
1180 assert(offset > 0)do { if ((__builtin_expect(!!(!(offset > 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("offset > 0"), "../src/journal/journal-file.c"
, 1180, __PRETTY_FUNCTION__); } while (0)
;
1181
1182 if (o->object.type != OBJECT_FIELD)
1183 return -EINVAL22;
1184
1185 m = le64toh(f->header->field_hash_table_size) / sizeof(HashItem);
1186 if (m <= 0)
1187 return -EBADMSG74;
1188
1189 /* This might alter the window we are looking at */
1190 o->field.next_hash_offset = o->field.head_data_offset = 0;
1191
1192 h = hash % m;
1193 p = le64toh(f->field_hash_table[h].tail_hash_offset);
1194 if (p == 0)
1195 f->field_hash_table[h].head_hash_offset = htole64(offset);
1196 else {
1197 r = journal_file_move_to_object(f, OBJECT_FIELD, p, &o);
1198 if (r < 0)
1199 return r;
1200
1201 o->field.next_hash_offset = htole64(offset);
1202 }
1203
1204 f->field_hash_table[h].tail_hash_offset = htole64(offset);
1205
1206 if (JOURNAL_HEADER_CONTAINS(f->header, n_fields)(le64toh((f->header)->header_size) >= __builtin_offsetof
(Header, n_fields) + sizeof((f->header)->n_fields))
)
1207 f->header->n_fields = htole64(le64toh(f->header->n_fields) + 1);
1208
1209 return 0;
1210}
1211
1212static int journal_file_link_data(
1213 JournalFile *f,
1214 Object *o,
1215 uint64_t offset,
1216 uint64_t hash) {
1217
1218 uint64_t p, h, m;
1219 int r;
1220
1221 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 1221
, __PRETTY_FUNCTION__); } while (0)
;
1222 assert(f->header)do { if ((__builtin_expect(!!(!(f->header)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f->header"), "../src/journal/journal-file.c"
, 1222, __PRETTY_FUNCTION__); } while (0)
;
1223 assert(f->data_hash_table)do { if ((__builtin_expect(!!(!(f->data_hash_table)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f->data_hash_table"), "../src/journal/journal-file.c"
, 1223, __PRETTY_FUNCTION__); } while (0)
;
1224 assert(o)do { if ((__builtin_expect(!!(!(o)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("o"), "../src/journal/journal-file.c", 1224
, __PRETTY_FUNCTION__); } while (0)
;
1225 assert(offset > 0)do { if ((__builtin_expect(!!(!(offset > 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("offset > 0"), "../src/journal/journal-file.c"
, 1225, __PRETTY_FUNCTION__); } while (0)
;
1226
1227 if (o->object.type != OBJECT_DATA)
1228 return -EINVAL22;
1229
1230 m = le64toh(f->header->data_hash_table_size) / sizeof(HashItem);
1231 if (m <= 0)
1232 return -EBADMSG74;
1233
1234 /* This might alter the window we are looking at */
1235 o->data.next_hash_offset = o->data.next_field_offset = 0;
1236 o->data.entry_offset = o->data.entry_array_offset = 0;
1237 o->data.n_entries = 0;
1238
1239 h = hash % m;
1240 p = le64toh(f->data_hash_table[h].tail_hash_offset);
1241 if (p == 0)
1242 /* Only entry in the hash table is easy */
1243 f->data_hash_table[h].head_hash_offset = htole64(offset);
1244 else {
1245 /* Move back to the previous data object, to patch in
1246 * pointer */
1247
1248 r = journal_file_move_to_object(f, OBJECT_DATA, p, &o);
1249 if (r < 0)
1250 return r;
1251
1252 o->data.next_hash_offset = htole64(offset);
1253 }
1254
1255 f->data_hash_table[h].tail_hash_offset = htole64(offset);
1256
1257 if (JOURNAL_HEADER_CONTAINS(f->header, n_data)(le64toh((f->header)->header_size) >= __builtin_offsetof
(Header, n_data) + sizeof((f->header)->n_data))
)
1258 f->header->n_data = htole64(le64toh(f->header->n_data) + 1);
1259
1260 return 0;
1261}
1262
1263int journal_file_find_field_object_with_hash(
1264 JournalFile *f,
1265 const void *field, uint64_t size, uint64_t hash,
1266 Object **ret, uint64_t *offset) {
1267
1268 uint64_t p, osize, h, m;
1269 int r;
1270
1271 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 1271
, __PRETTY_FUNCTION__); } while (0)
;
1272 assert(f->header)do { if ((__builtin_expect(!!(!(f->header)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f->header"), "../src/journal/journal-file.c"
, 1272, __PRETTY_FUNCTION__); } while (0)
;
1273 assert(field && size > 0)do { if ((__builtin_expect(!!(!(field && size > 0)
),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("field && size > 0"
), "../src/journal/journal-file.c", 1273, __PRETTY_FUNCTION__
); } while (0)
;
1274
1275 /* If the field hash table is empty, we can't find anything */
1276 if (le64toh(f->header->field_hash_table_size) <= 0)
1277 return 0;
1278
1279 /* Map the field hash table, if it isn't mapped yet. */
1280 r = journal_file_map_field_hash_table(f);
1281 if (r < 0)
1282 return r;
1283
1284 osize = offsetof(Object, field.payload)__builtin_offsetof(Object, field.payload) + size;
1285
1286 m = le64toh(f->header->field_hash_table_size) / sizeof(HashItem);
1287 if (m <= 0)
1288 return -EBADMSG74;
1289
1290 h = hash % m;
1291 p = le64toh(f->field_hash_table[h].head_hash_offset);
1292
1293 while (p > 0) {
1294 Object *o;
1295
1296 r = journal_file_move_to_object(f, OBJECT_FIELD, p, &o);
1297 if (r < 0)
1298 return r;
1299
1300 if (le64toh(o->field.hash) == hash &&
1301 le64toh(o->object.size) == osize &&
1302 memcmp(o->field.payload, field, size) == 0) {
1303
1304 if (ret)
1305 *ret = o;
1306 if (offset)
1307 *offset = p;
1308
1309 return 1;
1310 }
1311
1312 p = le64toh(o->field.next_hash_offset);
1313 }
1314
1315 return 0;
1316}
1317
1318int journal_file_find_field_object(
1319 JournalFile *f,
1320 const void *field, uint64_t size,
1321 Object **ret, uint64_t *offset) {
1322
1323 uint64_t hash;
1324
1325 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 1325
, __PRETTY_FUNCTION__); } while (0)
;
1326 assert(field && size > 0)do { if ((__builtin_expect(!!(!(field && size > 0)
),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("field && size > 0"
), "../src/journal/journal-file.c", 1326, __PRETTY_FUNCTION__
); } while (0)
;
1327
1328 hash = hash64(field, size);
1329
1330 return journal_file_find_field_object_with_hash(f,
1331 field, size, hash,
1332 ret, offset);
1333}
1334
1335int journal_file_find_data_object_with_hash(
1336 JournalFile *f,
1337 const void *data, uint64_t size, uint64_t hash,
1338 Object **ret, uint64_t *offset) {
1339
1340 uint64_t p, osize, h, m;
1341 int r;
1342
1343 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 1343
, __PRETTY_FUNCTION__); } while (0)
;
1344 assert(f->header)do { if ((__builtin_expect(!!(!(f->header)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f->header"), "../src/journal/journal-file.c"
, 1344, __PRETTY_FUNCTION__); } while (0)
;
1345 assert(data || size == 0)do { if ((__builtin_expect(!!(!(data || size == 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("data || size == 0"), "../src/journal/journal-file.c"
, 1345, __PRETTY_FUNCTION__); } while (0)
;
1346
1347 /* If there's no data hash table, then there's no entry. */
1348 if (le64toh(f->header->data_hash_table_size) <= 0)
1349 return 0;
1350
1351 /* Map the data hash table, if it isn't mapped yet. */
1352 r = journal_file_map_data_hash_table(f);
1353 if (r < 0)
1354 return r;
1355
1356 osize = offsetof(Object, data.payload)__builtin_offsetof(Object, data.payload) + size;
1357
1358 m = le64toh(f->header->data_hash_table_size) / sizeof(HashItem);
1359 if (m <= 0)
1360 return -EBADMSG74;
1361
1362 h = hash % m;
1363 p = le64toh(f->data_hash_table[h].head_hash_offset);
1364
1365 while (p > 0) {
1366 Object *o;
1367
1368 r = journal_file_move_to_object(f, OBJECT_DATA, p, &o);
1369 if (r < 0)
1370 return r;
1371
1372 if (le64toh(o->data.hash) != hash)
1373 goto next;
1374
1375 if (o->object.flags & OBJECT_COMPRESSION_MASK(OBJECT_COMPRESSED_XZ | OBJECT_COMPRESSED_LZ4)) {
1376#if HAVE_XZ1 || HAVE_LZ41
1377 uint64_t l;
1378 size_t rsize = 0;
1379
1380 l = le64toh(o->object.size);
1381 if (l <= offsetof(Object, data.payload)__builtin_offsetof(Object, data.payload))
1382 return -EBADMSG74;
1383
1384 l -= offsetof(Object, data.payload)__builtin_offsetof(Object, data.payload);
1385
1386 r = decompress_blob(o->object.flags & OBJECT_COMPRESSION_MASK(OBJECT_COMPRESSED_XZ | OBJECT_COMPRESSED_LZ4),
1387 o->data.payload, l, &f->compress_buffer, &f->compress_buffer_size, &rsize, 0);
1388 if (r < 0)
1389 return r;
1390
1391 if (rsize == size &&
1392 memcmp(f->compress_buffer, data, size) == 0) {
1393
1394 if (ret)
1395 *ret = o;
1396
1397 if (offset)
1398 *offset = p;
1399
1400 return 1;
1401 }
1402#else
1403 return -EPROTONOSUPPORT93;
1404#endif
1405 } else if (le64toh(o->object.size) == osize &&
1406 memcmp(o->data.payload, data, size) == 0) {
1407
1408 if (ret)
1409 *ret = o;
1410
1411 if (offset)
1412 *offset = p;
1413
1414 return 1;
1415 }
1416
1417 next:
1418 p = le64toh(o->data.next_hash_offset);
1419 }
1420
1421 return 0;
1422}
1423
1424int journal_file_find_data_object(
1425 JournalFile *f,
1426 const void *data, uint64_t size,
1427 Object **ret, uint64_t *offset) {
1428
1429 uint64_t hash;
1430
1431 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 1431
, __PRETTY_FUNCTION__); } while (0)
;
1432 assert(data || size == 0)do { if ((__builtin_expect(!!(!(data || size == 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("data || size == 0"), "../src/journal/journal-file.c"
, 1432, __PRETTY_FUNCTION__); } while (0)
;
1433
1434 hash = hash64(data, size);
1435
1436 return journal_file_find_data_object_with_hash(f,
1437 data, size, hash,
1438 ret, offset);
1439}
1440
1441static int journal_file_append_field(
1442 JournalFile *f,
1443 const void *field, uint64_t size,
1444 Object **ret, uint64_t *offset) {
1445
1446 uint64_t hash, p;
1447 uint64_t osize;
1448 Object *o;
1449 int r;
1450
1451 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 1451
, __PRETTY_FUNCTION__); } while (0)
;
1452 assert(field && size > 0)do { if ((__builtin_expect(!!(!(field && size > 0)
),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("field && size > 0"
), "../src/journal/journal-file.c", 1452, __PRETTY_FUNCTION__
); } while (0)
;
1453
1454 hash = hash64(field, size);
1455
1456 r = journal_file_find_field_object_with_hash(f, field, size, hash, &o, &p);
1457 if (r < 0)
1458 return r;
1459 else if (r > 0) {
1460
1461 if (ret)
1462 *ret = o;
1463
1464 if (offset)
1465 *offset = p;
1466
1467 return 0;
1468 }
1469
1470 osize = offsetof(Object, field.payload)__builtin_offsetof(Object, field.payload) + size;
1471 r = journal_file_append_object(f, OBJECT_FIELD, osize, &o, &p);
1472 if (r < 0)
1473 return r;
1474
1475 o->field.hash = htole64(hash);
1476 memcpy(o->field.payload, field, size);
1477
1478 r = journal_file_link_field(f, o, p, hash);
1479 if (r < 0)
1480 return r;
1481
1482 /* The linking might have altered the window, so let's
1483 * refresh our pointer */
1484 r = journal_file_move_to_object(f, OBJECT_FIELD, p, &o);
1485 if (r < 0)
1486 return r;
1487
1488#if HAVE_GCRYPT1
1489 r = journal_file_hmac_put_object(f, OBJECT_FIELD, o, p);
1490 if (r < 0)
1491 return r;
1492#endif
1493
1494 if (ret)
1495 *ret = o;
1496
1497 if (offset)
1498 *offset = p;
1499
1500 return 0;
1501}
1502
1503static int journal_file_append_data(
1504 JournalFile *f,
1505 const void *data, uint64_t size,
1506 Object **ret, uint64_t *offset) {
1507
1508 uint64_t hash, p;
1509 uint64_t osize;
1510 Object *o;
1511 int r, compression = 0;
1512 const void *eq;
1513
1514 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 1514
, __PRETTY_FUNCTION__); } while (0)
;
1515 assert(data || size == 0)do { if ((__builtin_expect(!!(!(data || size == 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("data || size == 0"), "../src/journal/journal-file.c"
, 1515, __PRETTY_FUNCTION__); } while (0)
;
1516
1517 hash = hash64(data, size);
1518
1519 r = journal_file_find_data_object_with_hash(f, data, size, hash, &o, &p);
1520 if (r < 0)
1521 return r;
1522 if (r > 0) {
1523
1524 if (ret)
1525 *ret = o;
1526
1527 if (offset)
1528 *offset = p;
1529
1530 return 0;
1531 }
1532
1533 osize = offsetof(Object, data.payload)__builtin_offsetof(Object, data.payload) + size;
1534 r = journal_file_append_object(f, OBJECT_DATA, osize, &o, &p);
1535 if (r < 0)
1536 return r;
1537
1538 o->data.hash = htole64(hash);
1539
1540#if HAVE_XZ1 || HAVE_LZ41
1541 if (JOURNAL_FILE_COMPRESS(f) && size >= f->compress_threshold_bytes) {
1542 size_t rsize = 0;
1543
1544 compression = compress_blob(data, size, o->data.payload, size - 1, &rsize);
1545
1546 if (compression >= 0) {
1547 o->object.size = htole64(offsetof(Object, data.payload)__builtin_offsetof(Object, data.payload) + rsize);
1548 o->object.flags |= compression;
1549
1550 log_debug("Compressed data object %"PRIu64" -> %zu using %s",({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 1551, __func__, "Compressed data object %"
"l" "u"" -> %zu using %s", size, rsize, object_compressed_to_string
(compression)) : -abs(_e); })
1551 size, rsize, object_compressed_to_string(compression))({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 1551, __func__, "Compressed data object %"
"l" "u"" -> %zu using %s", size, rsize, object_compressed_to_string
(compression)) : -abs(_e); })
;
1552 } else
1553 /* Compression didn't work, we don't really care why, let's continue without compression */
1554 compression = 0;
1555 }
1556#endif
1557
1558 if (compression == 0)
1559 memcpy_safe(o->data.payload, data, size);
1560
1561 r = journal_file_link_data(f, o, p, hash);
1562 if (r < 0)
1563 return r;
1564
1565#if HAVE_GCRYPT1
1566 r = journal_file_hmac_put_object(f, OBJECT_DATA, o, p);
1567 if (r < 0)
1568 return r;
1569#endif
1570
1571 /* The linking might have altered the window, so let's
1572 * refresh our pointer */
1573 r = journal_file_move_to_object(f, OBJECT_DATA, p, &o);
1574 if (r < 0)
1575 return r;
1576
1577 if (!data)
1578 eq = NULL((void*)0);
1579 else
1580 eq = memchr(data, '=', size);
1581 if (eq && eq > data) {
1582 Object *fo = NULL((void*)0);
1583 uint64_t fp;
1584
1585 /* Create field object ... */
1586 r = journal_file_append_field(f, data, (uint8_t*) eq - (uint8_t*) data, &fo, &fp);
1587 if (r < 0)
1588 return r;
1589
1590 /* ... and link it in. */
1591 o->data.next_field_offset = fo->field.head_data_offset;
1592 fo->field.head_data_offset = le64toh(p);
1593 }
1594
1595 if (ret)
1596 *ret = o;
1597
1598 if (offset)
1599 *offset = p;
1600
1601 return 0;
1602}
1603
1604uint64_t journal_file_entry_n_items(Object *o) {
1605 assert(o)do { if ((__builtin_expect(!!(!(o)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("o"), "../src/journal/journal-file.c", 1605
, __PRETTY_FUNCTION__); } while (0)
;
1606
1607 if (o->object.type != OBJECT_ENTRY)
1608 return 0;
1609
1610 return (le64toh(o->object.size) - offsetof(Object, entry.items)__builtin_offsetof(Object, entry.items)) / sizeof(EntryItem);
1611}
1612
1613uint64_t journal_file_entry_array_n_items(Object *o) {
1614 assert(o)do { if ((__builtin_expect(!!(!(o)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("o"), "../src/journal/journal-file.c", 1614
, __PRETTY_FUNCTION__); } while (0)
;
1615
1616 if (o->object.type != OBJECT_ENTRY_ARRAY)
1617 return 0;
1618
1619 return (le64toh(o->object.size) - offsetof(Object, entry_array.items)__builtin_offsetof(Object, entry_array.items)) / sizeof(uint64_t);
1620}
1621
1622uint64_t journal_file_hash_table_n_items(Object *o) {
1623 assert(o)do { if ((__builtin_expect(!!(!(o)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("o"), "../src/journal/journal-file.c", 1623
, __PRETTY_FUNCTION__); } while (0)
;
1624
1625 if (!IN_SET(o->object.type, OBJECT_DATA_HASH_TABLE, OBJECT_FIELD_HASH_TABLE)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){OBJECT_DATA_HASH_TABLE, OBJECT_FIELD_HASH_TABLE
})/sizeof(int)]; switch(o->object.type) { case OBJECT_DATA_HASH_TABLE
: case OBJECT_FIELD_HASH_TABLE: _found = 1; break; default: break
; } _found; })
)
1626 return 0;
1627
1628 return (le64toh(o->object.size) - offsetof(Object, hash_table.items)__builtin_offsetof(Object, hash_table.items)) / sizeof(HashItem);
1629}
1630
1631static int link_entry_into_array(JournalFile *f,
1632 le64_t *first,
1633 le64_t *idx,
1634 uint64_t p) {
1635 int r;
1636 uint64_t n = 0, ap = 0, q, i, a, hidx;
1637 Object *o;
1638
1639 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 1639
, __PRETTY_FUNCTION__); } while (0)
;
1640 assert(f->header)do { if ((__builtin_expect(!!(!(f->header)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f->header"), "../src/journal/journal-file.c"
, 1640, __PRETTY_FUNCTION__); } while (0)
;
1641 assert(first)do { if ((__builtin_expect(!!(!(first)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("first"), "../src/journal/journal-file.c"
, 1641, __PRETTY_FUNCTION__); } while (0)
;
1642 assert(idx)do { if ((__builtin_expect(!!(!(idx)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("idx"), "../src/journal/journal-file.c",
1642, __PRETTY_FUNCTION__); } while (0)
;
1643 assert(p > 0)do { if ((__builtin_expect(!!(!(p > 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("p > 0"), "../src/journal/journal-file.c"
, 1643, __PRETTY_FUNCTION__); } while (0)
;
1644
1645 a = le64toh(*first);
1646 i = hidx = le64toh(*idx);
1647 while (a > 0) {
1648
1649 r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &o);
1650 if (r < 0)
1651 return r;
1652
1653 n = journal_file_entry_array_n_items(o);
1654 if (i < n) {
1655 o->entry_array.items[i] = htole64(p);
1656 *idx = htole64(hidx + 1);
1657 return 0;
1658 }
1659
1660 i -= n;
1661 ap = a;
1662 a = le64toh(o->entry_array.next_entry_array_offset);
1663 }
1664
1665 if (hidx > n)
1666 n = (hidx+1) * 2;
1667 else
1668 n = n * 2;
1669
1670 if (n < 4)
1671 n = 4;
1672
1673 r = journal_file_append_object(f, OBJECT_ENTRY_ARRAY,
1674 offsetof(Object, entry_array.items)__builtin_offsetof(Object, entry_array.items) + n * sizeof(uint64_t),
1675 &o, &q);
1676 if (r < 0)
1677 return r;
1678
1679#if HAVE_GCRYPT1
1680 r = journal_file_hmac_put_object(f, OBJECT_ENTRY_ARRAY, o, q);
1681 if (r < 0)
1682 return r;
1683#endif
1684
1685 o->entry_array.items[i] = htole64(p);
1686
1687 if (ap == 0)
1688 *first = htole64(q);
1689 else {
1690 r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, ap, &o);
1691 if (r < 0)
1692 return r;
1693
1694 o->entry_array.next_entry_array_offset = htole64(q);
1695 }
1696
1697 if (JOURNAL_HEADER_CONTAINS(f->header, n_entry_arrays)(le64toh((f->header)->header_size) >= __builtin_offsetof
(Header, n_entry_arrays) + sizeof((f->header)->n_entry_arrays
))
)
1698 f->header->n_entry_arrays = htole64(le64toh(f->header->n_entry_arrays) + 1);
1699
1700 *idx = htole64(hidx + 1);
1701
1702 return 0;
1703}
1704
1705static int link_entry_into_array_plus_one(JournalFile *f,
1706 le64_t *extra,
1707 le64_t *first,
1708 le64_t *idx,
1709 uint64_t p) {
1710
1711 int r;
1712
1713 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 1713
, __PRETTY_FUNCTION__); } while (0)
;
1714 assert(extra)do { if ((__builtin_expect(!!(!(extra)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("extra"), "../src/journal/journal-file.c"
, 1714, __PRETTY_FUNCTION__); } while (0)
;
1715 assert(first)do { if ((__builtin_expect(!!(!(first)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("first"), "../src/journal/journal-file.c"
, 1715, __PRETTY_FUNCTION__); } while (0)
;
1716 assert(idx)do { if ((__builtin_expect(!!(!(idx)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("idx"), "../src/journal/journal-file.c",
1716, __PRETTY_FUNCTION__); } while (0)
;
1717 assert(p > 0)do { if ((__builtin_expect(!!(!(p > 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("p > 0"), "../src/journal/journal-file.c"
, 1717, __PRETTY_FUNCTION__); } while (0)
;
1718
1719 if (*idx == 0)
1720 *extra = htole64(p);
1721 else {
1722 le64_t i;
1723
1724 i = htole64(le64toh(*idx) - 1);
1725 r = link_entry_into_array(f, first, &i, p);
1726 if (r < 0)
1727 return r;
1728 }
1729
1730 *idx = htole64(le64toh(*idx) + 1);
1731 return 0;
1732}
1733
1734static int journal_file_link_entry_item(JournalFile *f, Object *o, uint64_t offset, uint64_t i) {
1735 uint64_t p;
1736 int r;
1737 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 1737
, __PRETTY_FUNCTION__); } while (0)
;
1738 assert(o)do { if ((__builtin_expect(!!(!(o)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("o"), "../src/journal/journal-file.c", 1738
, __PRETTY_FUNCTION__); } while (0)
;
1739 assert(offset > 0)do { if ((__builtin_expect(!!(!(offset > 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("offset > 0"), "../src/journal/journal-file.c"
, 1739, __PRETTY_FUNCTION__); } while (0)
;
1740
1741 p = le64toh(o->entry.items[i].object_offset);
1742 if (p == 0)
1743 return -EINVAL22;
1744
1745 r = journal_file_move_to_object(f, OBJECT_DATA, p, &o);
1746 if (r < 0)
1747 return r;
1748
1749 return link_entry_into_array_plus_one(f,
1750 &o->data.entry_offset,
1751 &o->data.entry_array_offset,
1752 &o->data.n_entries,
1753 offset);
1754}
1755
1756static int journal_file_link_entry(JournalFile *f, Object *o, uint64_t offset) {
1757 uint64_t n, i;
1758 int r;
1759
1760 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 1760
, __PRETTY_FUNCTION__); } while (0)
;
1761 assert(f->header)do { if ((__builtin_expect(!!(!(f->header)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f->header"), "../src/journal/journal-file.c"
, 1761, __PRETTY_FUNCTION__); } while (0)
;
1762 assert(o)do { if ((__builtin_expect(!!(!(o)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("o"), "../src/journal/journal-file.c", 1762
, __PRETTY_FUNCTION__); } while (0)
;
1763 assert(offset > 0)do { if ((__builtin_expect(!!(!(offset > 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("offset > 0"), "../src/journal/journal-file.c"
, 1763, __PRETTY_FUNCTION__); } while (0)
;
1764
1765 if (o->object.type != OBJECT_ENTRY)
1766 return -EINVAL22;
1767
1768 __sync_synchronize();
1769
1770 /* Link up the entry itself */
1771 r = link_entry_into_array(f,
1772 &f->header->entry_array_offset,
1773 &f->header->n_entries,
1774 offset);
1775 if (r < 0)
1776 return r;
1777
1778 /* log_debug("=> %s seqnr=%"PRIu64" n_entries=%"PRIu64, f->path, o->entry.seqnum, f->header->n_entries); */
1779
1780 if (f->header->head_entry_realtime == 0)
1781 f->header->head_entry_realtime = o->entry.realtime;
1782
1783 f->header->tail_entry_realtime = o->entry.realtime;
1784 f->header->tail_entry_monotonic = o->entry.monotonic;
1785
1786 /* Link up the items */
1787 n = journal_file_entry_n_items(o);
1788 for (i = 0; i < n; i++) {
1789 r = journal_file_link_entry_item(f, o, offset, i);
1790 if (r < 0)
1791 return r;
1792 }
1793
1794 return 0;
1795}
1796
1797static int journal_file_append_entry_internal(
1798 JournalFile *f,
1799 const dual_timestamp *ts,
1800 const sd_id128_t *boot_id,
1801 uint64_t xor_hash,
1802 const EntryItem items[], unsigned n_items,
1803 uint64_t *seqnum,
1804 Object **ret, uint64_t *offset) {
1805 uint64_t np;
1806 uint64_t osize;
1807 Object *o;
1808 int r;
1809
1810 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 1810
, __PRETTY_FUNCTION__); } while (0)
;
1811 assert(f->header)do { if ((__builtin_expect(!!(!(f->header)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f->header"), "../src/journal/journal-file.c"
, 1811, __PRETTY_FUNCTION__); } while (0)
;
1812 assert(items || n_items == 0)do { if ((__builtin_expect(!!(!(items || n_items == 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("items || n_items == 0"), "../src/journal/journal-file.c"
, 1812, __PRETTY_FUNCTION__); } while (0)
;
1813 assert(ts)do { if ((__builtin_expect(!!(!(ts)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ts"), "../src/journal/journal-file.c", 1813
, __PRETTY_FUNCTION__); } while (0)
;
1814
1815 osize = offsetof(Object, entry.items)__builtin_offsetof(Object, entry.items) + (n_items * sizeof(EntryItem));
1816
1817 r = journal_file_append_object(f, OBJECT_ENTRY, osize, &o, &np);
1818 if (r < 0)
1819 return r;
1820
1821 o->entry.seqnum = htole64(journal_file_entry_seqnum(f, seqnum));
1822 memcpy_safe(o->entry.items, items, n_items * sizeof(EntryItem));
1823 o->entry.realtime = htole64(ts->realtime);
1824 o->entry.monotonic = htole64(ts->monotonic);
1825 o->entry.xor_hash = htole64(xor_hash);
1826 o->entry.boot_id = boot_id ? *boot_id : f->header->boot_id;
1827
1828#if HAVE_GCRYPT1
1829 r = journal_file_hmac_put_object(f, OBJECT_ENTRY, o, np);
1830 if (r < 0)
1831 return r;
1832#endif
1833
1834 r = journal_file_link_entry(f, o, np);
1835 if (r < 0)
1836 return r;
1837
1838 if (ret)
1839 *ret = o;
1840
1841 if (offset)
1842 *offset = np;
1843
1844 return 0;
1845}
1846
1847void journal_file_post_change(JournalFile *f) {
1848 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 1848
, __PRETTY_FUNCTION__); } while (0)
;
1849
1850 if (f->fd < 0)
1851 return;
1852
1853 /* inotify() does not receive IN_MODIFY events from file
1854 * accesses done via mmap(). After each access we hence
1855 * trigger IN_MODIFY by truncating the journal file to its
1856 * current size which triggers IN_MODIFY. */
1857
1858 __sync_synchronize();
1859
1860 if (ftruncate(f->fd, f->last_stat.st_size) < 0)
1861 log_debug_errno(errno, "Failed to truncate file to its own size: %m")({ int _level = ((7)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/journal/journal-file.c", 1861, __func__
, "Failed to truncate file to its own size: %m") : -abs(_e); }
)
;
1862}
1863
1864static int post_change_thunk(sd_event_source *timer, uint64_t usec, void *userdata) {
1865 assert(userdata)do { if ((__builtin_expect(!!(!(userdata)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("userdata"), "../src/journal/journal-file.c"
, 1865, __PRETTY_FUNCTION__); } while (0)
;
1866
1867 journal_file_post_change(userdata);
1868
1869 return 1;
1870}
1871
1872static void schedule_post_change(JournalFile *f) {
1873 sd_event_source *timer;
1874 int enabled, r;
1875 uint64_t now;
1876
1877 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 1877
, __PRETTY_FUNCTION__); } while (0)
;
1878 assert(f->post_change_timer)do { if ((__builtin_expect(!!(!(f->post_change_timer)),0))
) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("f->post_change_timer"
), "../src/journal/journal-file.c", 1878, __PRETTY_FUNCTION__
); } while (0)
;
1879
1880 timer = f->post_change_timer;
1881
1882 r = sd_event_source_get_enabled(timer, &enabled);
1883 if (r < 0) {
1884 log_debug_errno(r, "Failed to get ftruncate timer state: %m")({ int _level = ((7)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 1884, __func__, "Failed to get ftruncate timer state: %m"
) : -abs(_e); })
;
1885 goto fail;
1886 }
1887
1888 if (enabled == SD_EVENT_ONESHOT)
1889 return;
1890
1891 r = sd_event_now(sd_event_source_get_event(timer), CLOCK_MONOTONIC1, &now);
1892 if (r < 0) {
1893 log_debug_errno(r, "Failed to get clock's now for scheduling ftruncate: %m")({ int _level = ((7)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 1893, __func__, "Failed to get clock's now for scheduling ftruncate: %m"
) : -abs(_e); })
;
1894 goto fail;
1895 }
1896
1897 r = sd_event_source_set_time(timer, now+f->post_change_timer_period);
1898 if (r < 0) {
1899 log_debug_errno(r, "Failed to set time for scheduling ftruncate: %m")({ int _level = ((7)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 1899, __func__, "Failed to set time for scheduling ftruncate: %m"
) : -abs(_e); })
;
1900 goto fail;
1901 }
1902
1903 r = sd_event_source_set_enabled(timer, SD_EVENT_ONESHOT);
1904 if (r < 0) {
1905 log_debug_errno(r, "Failed to enable scheduled ftruncate: %m")({ int _level = ((7)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 1905, __func__, "Failed to enable scheduled ftruncate: %m"
) : -abs(_e); })
;
1906 goto fail;
1907 }
1908
1909 return;
1910
1911fail:
1912 /* On failure, let's simply post the change immediately. */
1913 journal_file_post_change(f);
1914}
1915
1916/* Enable coalesced change posting in a timer on the provided sd_event instance */
1917int journal_file_enable_post_change_timer(JournalFile *f, sd_event *e, usec_t t) {
1918 _cleanup_(sd_event_source_unrefp)__attribute__((cleanup(sd_event_source_unrefp))) sd_event_source *timer = NULL((void*)0);
1919 int r;
1920
1921 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 1921
, __PRETTY_FUNCTION__); } while (0)
;
1922 assert_return(!f->post_change_timer, -EINVAL)do { if (!(((__builtin_expect(!!(!f->post_change_timer),1)
)) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD,
("!f->post_change_timer"), "../src/journal/journal-file.c"
, 1922, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
1923 assert(e)do { if ((__builtin_expect(!!(!(e)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("e"), "../src/journal/journal-file.c", 1923
, __PRETTY_FUNCTION__); } while (0)
;
1924 assert(t)do { if ((__builtin_expect(!!(!(t)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("t"), "../src/journal/journal-file.c", 1924
, __PRETTY_FUNCTION__); } while (0)
;
1925
1926 r = sd_event_add_time(e, &timer, CLOCK_MONOTONIC1, 0, 0, post_change_thunk, f);
1927 if (r < 0)
1928 return r;
1929
1930 r = sd_event_source_set_enabled(timer, SD_EVENT_OFF);
1931 if (r < 0)
1932 return r;
1933
1934 f->post_change_timer = TAKE_PTR(timer)({ typeof(timer) _ptr_ = (timer); (timer) = ((void*)0); _ptr_
; })
;
1935 f->post_change_timer_period = t;
1936
1937 return r;
1938}
1939
1940static int entry_item_cmp(const void *_a, const void *_b) {
1941 const EntryItem *a = _a, *b = _b;
1942
1943 if (le64toh(a->object_offset) < le64toh(b->object_offset))
1944 return -1;
1945 if (le64toh(a->object_offset) > le64toh(b->object_offset))
1946 return 1;
1947 return 0;
1948}
1949
1950int journal_file_append_entry(
1951 JournalFile *f,
1952 const dual_timestamp *ts,
1953 const sd_id128_t *boot_id,
1954 const struct iovec iovec[], unsigned n_iovec,
1955 uint64_t *seqnum,
1956 Object **ret, uint64_t *offset) {
1957
1958 unsigned i;
1959 EntryItem *items;
1960 int r;
1961 uint64_t xor_hash = 0;
1962 struct dual_timestamp _ts;
1963
1964 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 1964
, __PRETTY_FUNCTION__); } while (0)
;
1965 assert(f->header)do { if ((__builtin_expect(!!(!(f->header)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f->header"), "../src/journal/journal-file.c"
, 1965, __PRETTY_FUNCTION__); } while (0)
;
1966 assert(iovec || n_iovec == 0)do { if ((__builtin_expect(!!(!(iovec || n_iovec == 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("iovec || n_iovec == 0"), "../src/journal/journal-file.c"
, 1966, __PRETTY_FUNCTION__); } while (0)
;
1967
1968 if (ts) {
1969 if (!VALID_REALTIME(ts->realtime)) {
1970 log_debug("Invalid realtime timestamp %"PRIu64", refusing entry.", ts->realtime)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 1970, __func__, "Invalid realtime timestamp %"
"l" "u"", refusing entry.", ts->realtime) : -abs(_e); })
;
1971 return -EBADMSG74;
1972 }
1973 if (!VALID_MONOTONIC(ts->monotonic)) {
1974 log_debug("Invalid monotomic timestamp %"PRIu64", refusing entry.", ts->monotonic)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 1974, __func__, "Invalid monotomic timestamp %"
"l" "u"", refusing entry.", ts->monotonic) : -abs(_e); })
;
1975 return -EBADMSG74;
1976 }
1977 } else {
1978 dual_timestamp_get(&_ts);
1979 ts = &_ts;
1980 }
1981
1982#if HAVE_GCRYPT1
1983 r = journal_file_maybe_append_tag(f, ts->realtime);
1984 if (r < 0)
1985 return r;
1986#endif
1987
1988 /* alloca() can't take 0, hence let's allocate at least one */
1989 items = newa(EntryItem, MAX(1u, n_iovec))({ do { if ((__builtin_expect(!!(!(!size_multiply_overflow(sizeof
(EntryItem), __extension__ ({ const typeof((1u)) __unique_prefix_A28
= ((1u)); const typeof((n_iovec)) __unique_prefix_B29 = ((n_iovec
)); __unique_prefix_A28 > __unique_prefix_B29 ? __unique_prefix_A28
: __unique_prefix_B29; })))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("!size_multiply_overflow(sizeof(EntryItem), __extension__ ({ const typeof((1u)) __unique_prefix_A28 = ((1u)); const typeof((n_iovec)) __unique_prefix_B29 = ((n_iovec)); __unique_prefix_A28 > __unique_prefix_B29 ? __unique_prefix_A28 : __unique_prefix_B29; }))"
), "../src/journal/journal-file.c", 1989, __PRETTY_FUNCTION__
); } while (0); (EntryItem*) __builtin_alloca (sizeof(EntryItem
)*(__extension__ ({ const typeof((1u)) __unique_prefix_A28 = (
(1u)); const typeof((n_iovec)) __unique_prefix_B29 = ((n_iovec
)); __unique_prefix_A28 > __unique_prefix_B29 ? __unique_prefix_A28
: __unique_prefix_B29; }))); })
;
1990
1991 for (i = 0; i < n_iovec; i++) {
1992 uint64_t p;
1993 Object *o;
1994
1995 r = journal_file_append_data(f, iovec[i].iov_base, iovec[i].iov_len, &o, &p);
1996 if (r < 0)
1997 return r;
1998
1999 xor_hash ^= le64toh(o->data.hash);
2000 items[i].object_offset = htole64(p);
2001 items[i].hash = o->data.hash;
2002 }
2003
2004 /* Order by the position on disk, in order to improve seek
2005 * times for rotating media. */
2006 qsort_safe(items, n_iovec, sizeof(EntryItem), entry_item_cmp);
2007
2008 r = journal_file_append_entry_internal(f, ts, boot_id, xor_hash, items, n_iovec, seqnum, ret, offset);
2009
2010 /* If the memory mapping triggered a SIGBUS then we return an
2011 * IO error and ignore the error code passed down to us, since
2012 * it is very likely just an effect of a nullified replacement
2013 * mapping page */
2014
2015 if (mmap_cache_got_sigbus(f->mmap, f->cache_fd))
2016 r = -EIO5;
2017
2018 if (f->post_change_timer)
2019 schedule_post_change(f);
2020 else
2021 journal_file_post_change(f);
2022
2023 return r;
2024}
2025
2026typedef struct ChainCacheItem {
2027 uint64_t first; /* the array at the beginning of the chain */
2028 uint64_t array; /* the cached array */
2029 uint64_t begin; /* the first item in the cached array */
2030 uint64_t total; /* the total number of items in all arrays before this one in the chain */
2031 uint64_t last_index; /* the last index we looked at, to optimize locality when bisecting */
2032} ChainCacheItem;
2033
2034static void chain_cache_put(
2035 OrderedHashmap *h,
2036 ChainCacheItem *ci,
2037 uint64_t first,
2038 uint64_t array,
2039 uint64_t begin,
2040 uint64_t total,
2041 uint64_t last_index) {
2042
2043 if (!ci) {
2044 /* If the chain item to cache for this chain is the
2045 * first one it's not worth caching anything */
2046 if (array == first)
2047 return;
2048
2049 if (ordered_hashmap_size(h) >= CHAIN_CACHE_MAX20) {
2050 ci = ordered_hashmap_steal_first(h);
2051 assert(ci)do { if ((__builtin_expect(!!(!(ci)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ci"), "../src/journal/journal-file.c", 2051
, __PRETTY_FUNCTION__); } while (0)
;
2052 } else {
2053 ci = new(ChainCacheItem, 1)((ChainCacheItem*) malloc_multiply(sizeof(ChainCacheItem), (1
)))
;
2054 if (!ci)
2055 return;
2056 }
2057
2058 ci->first = first;
2059
2060 if (ordered_hashmap_put(h, &ci->first, ci) < 0) {
2061 free(ci);
2062 return;
2063 }
2064 } else
2065 assert(ci->first == first)do { if ((__builtin_expect(!!(!(ci->first == first)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ci->first == first"), "../src/journal/journal-file.c"
, 2065, __PRETTY_FUNCTION__); } while (0)
;
2066
2067 ci->array = array;
2068 ci->begin = begin;
2069 ci->total = total;
2070 ci->last_index = last_index;
2071}
2072
2073static int generic_array_get(
2074 JournalFile *f,
2075 uint64_t first,
2076 uint64_t i,
2077 Object **ret, uint64_t *offset) {
2078
2079 Object *o;
2080 uint64_t p = 0, a, t = 0;
2081 int r;
2082 ChainCacheItem *ci;
2083
2084 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 2084
, __PRETTY_FUNCTION__); } while (0)
;
2085
2086 a = first;
2087
2088 /* Try the chain cache first */
2089 ci = ordered_hashmap_get(f->chain_cache, &first);
2090 if (ci && i > ci->total) {
2091 a = ci->array;
2092 i -= ci->total;
2093 t = ci->total;
2094 }
2095
2096 while (a > 0) {
2097 uint64_t k;
2098
2099 r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &o);
2100 if (r < 0)
2101 return r;
2102
2103 k = journal_file_entry_array_n_items(o);
2104 if (i < k) {
2105 p = le64toh(o->entry_array.items[i]);
2106 goto found;
2107 }
2108
2109 i -= k;
2110 t += k;
2111 a = le64toh(o->entry_array.next_entry_array_offset);
2112 }
2113
2114 return 0;
2115
2116found:
2117 /* Let's cache this item for the next invocation */
2118 chain_cache_put(f->chain_cache, ci, first, a, le64toh(o->entry_array.items[0]), t, i);
2119
2120 r = journal_file_move_to_object(f, OBJECT_ENTRY, p, &o);
2121 if (r < 0)
2122 return r;
2123
2124 if (ret)
2125 *ret = o;
2126
2127 if (offset)
2128 *offset = p;
2129
2130 return 1;
2131}
2132
2133static int generic_array_get_plus_one(
2134 JournalFile *f,
2135 uint64_t extra,
2136 uint64_t first,
2137 uint64_t i,
2138 Object **ret, uint64_t *offset) {
2139
2140 Object *o;
2141
2142 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 2142
, __PRETTY_FUNCTION__); } while (0)
;
2143
2144 if (i == 0) {
2145 int r;
2146
2147 r = journal_file_move_to_object(f, OBJECT_ENTRY, extra, &o);
2148 if (r < 0)
2149 return r;
2150
2151 if (ret)
2152 *ret = o;
2153
2154 if (offset)
2155 *offset = extra;
2156
2157 return 1;
2158 }
2159
2160 return generic_array_get(f, first, i-1, ret, offset);
2161}
2162
2163enum {
2164 TEST_FOUND,
2165 TEST_LEFT,
2166 TEST_RIGHT
2167};
2168
2169static int generic_array_bisect(
2170 JournalFile *f,
2171 uint64_t first,
2172 uint64_t n,
2173 uint64_t needle,
2174 int (*test_object)(JournalFile *f, uint64_t p, uint64_t needle),
2175 direction_t direction,
2176 Object **ret,
2177 uint64_t *offset,
2178 uint64_t *idx) {
2179
2180 uint64_t a, p, t = 0, i = 0, last_p = 0, last_index = (uint64_t) -1;
2181 bool_Bool subtract_one = false0;
2182 Object *o, *array = NULL((void*)0);
2183 int r;
2184 ChainCacheItem *ci;
2185
2186 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 2186
, __PRETTY_FUNCTION__); } while (0)
;
2187 assert(test_object)do { if ((__builtin_expect(!!(!(test_object)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("test_object"), "../src/journal/journal-file.c"
, 2187, __PRETTY_FUNCTION__); } while (0)
;
2188
2189 /* Start with the first array in the chain */
2190 a = first;
2191
2192 ci = ordered_hashmap_get(f->chain_cache, &first);
2193 if (ci && n > ci->total && ci->begin != 0) {
2194 /* Ah, we have iterated this bisection array chain
2195 * previously! Let's see if we can skip ahead in the
2196 * chain, as far as the last time. But we can't jump
2197 * backwards in the chain, so let's check that
2198 * first. */
2199
2200 r = test_object(f, ci->begin, needle);
2201 if (r < 0)
2202 return r;
2203
2204 if (r == TEST_LEFT) {
2205 /* OK, what we are looking for is right of the
2206 * begin of this EntryArray, so let's jump
2207 * straight to previously cached array in the
2208 * chain */
2209
2210 a = ci->array;
2211 n -= ci->total;
2212 t = ci->total;
2213 last_index = ci->last_index;
2214 }
2215 }
2216
2217 while (a > 0) {
2218 uint64_t left, right, k, lp;
2219
2220 r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &array);
2221 if (r < 0)
2222 return r;
2223
2224 k = journal_file_entry_array_n_items(array);
2225 right = MIN(k, n)__extension__ ({ const typeof((k)) __unique_prefix_A30 = ((k)
); const typeof((n)) __unique_prefix_B31 = ((n)); __unique_prefix_A30
< __unique_prefix_B31 ? __unique_prefix_A30 : __unique_prefix_B31
; })
;
2226 if (right <= 0)
2227 return 0;
2228
2229 i = right - 1;
2230 lp = p = le64toh(array->entry_array.items[i]);
2231 if (p <= 0)
2232 r = -EBADMSG74;
2233 else
2234 r = test_object(f, p, needle);
2235 if (r == -EBADMSG74) {
2236 log_debug_errno(r, "Encountered invalid entry while bisecting, cutting algorithm short. (1)")({ int _level = ((7)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 2236, __func__, "Encountered invalid entry while bisecting, cutting algorithm short. (1)"
) : -abs(_e); })
;
2237 n = i;
2238 continue;
2239 }
2240 if (r < 0)
2241 return r;
2242
2243 if (r == TEST_FOUND)
2244 r = direction == DIRECTION_DOWN ? TEST_RIGHT : TEST_LEFT;
2245
2246 if (r == TEST_RIGHT) {
2247 left = 0;
2248 right -= 1;
2249
2250 if (last_index != (uint64_t) -1) {
2251 assert(last_index <= right)do { if ((__builtin_expect(!!(!(last_index <= right)),0)))
log_assert_failed_realm(LOG_REALM_SYSTEMD, ("last_index <= right"
), "../src/journal/journal-file.c", 2251, __PRETTY_FUNCTION__
); } while (0)
;
2252
2253 /* If we cached the last index we
2254 * looked at, let's try to not to jump
2255 * too wildly around and see if we can
2256 * limit the range to look at early to
2257 * the immediate neighbors of the last
2258 * index we looked at. */
2259
2260 if (last_index > 0) {
2261 uint64_t x = last_index - 1;
2262
2263 p = le64toh(array->entry_array.items[x]);
2264 if (p <= 0)
2265 return -EBADMSG74;
2266
2267 r = test_object(f, p, needle);
2268 if (r < 0)
2269 return r;
2270
2271 if (r == TEST_FOUND)
2272 r = direction == DIRECTION_DOWN ? TEST_RIGHT : TEST_LEFT;
2273
2274 if (r == TEST_RIGHT)
2275 right = x;
2276 else
2277 left = x + 1;
2278 }
2279
2280 if (last_index < right) {
2281 uint64_t y = last_index + 1;
2282
2283 p = le64toh(array->entry_array.items[y]);
2284 if (p <= 0)
2285 return -EBADMSG74;
2286
2287 r = test_object(f, p, needle);
2288 if (r < 0)
2289 return r;
2290
2291 if (r == TEST_FOUND)
2292 r = direction == DIRECTION_DOWN ? TEST_RIGHT : TEST_LEFT;
2293
2294 if (r == TEST_RIGHT)
2295 right = y;
2296 else
2297 left = y + 1;
2298 }
2299 }
2300
2301 for (;;) {
2302 if (left == right) {
2303 if (direction == DIRECTION_UP)
2304 subtract_one = true1;
2305
2306 i = left;
2307 goto found;
2308 }
2309
2310 assert(left < right)do { if ((__builtin_expect(!!(!(left < right)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("left < right"), "../src/journal/journal-file.c"
, 2310, __PRETTY_FUNCTION__); } while (0)
;
2311 i = (left + right) / 2;
2312
2313 p = le64toh(array->entry_array.items[i]);
2314 if (p <= 0)
2315 r = -EBADMSG74;
2316 else
2317 r = test_object(f, p, needle);
2318 if (r == -EBADMSG74) {
2319 log_debug_errno(r, "Encountered invalid entry while bisecting, cutting algorithm short. (2)")({ int _level = ((7)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 2319, __func__, "Encountered invalid entry while bisecting, cutting algorithm short. (2)"
) : -abs(_e); })
;
2320 right = n = i;
Although the value stored to 'n' is used in the enclosing expression, the value is never actually read from 'n'
2321 continue;
2322 }
2323 if (r < 0)
2324 return r;
2325
2326 if (r == TEST_FOUND)
2327 r = direction == DIRECTION_DOWN ? TEST_RIGHT : TEST_LEFT;
2328
2329 if (r == TEST_RIGHT)
2330 right = i;
2331 else
2332 left = i + 1;
2333 }
2334 }
2335
2336 if (k >= n) {
2337 if (direction == DIRECTION_UP) {
2338 i = n;
2339 subtract_one = true1;
2340 goto found;
2341 }
2342
2343 return 0;
2344 }
2345
2346 last_p = lp;
2347
2348 n -= k;
2349 t += k;
2350 last_index = (uint64_t) -1;
2351 a = le64toh(array->entry_array.next_entry_array_offset);
2352 }
2353
2354 return 0;
2355
2356found:
2357 if (subtract_one && t == 0 && i == 0)
2358 return 0;
2359
2360 /* Let's cache this item for the next invocation */
2361 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);
2362
2363 if (subtract_one && i == 0)
2364 p = last_p;
2365 else if (subtract_one)
2366 p = le64toh(array->entry_array.items[i-1]);
2367 else
2368 p = le64toh(array->entry_array.items[i]);
2369
2370 r = journal_file_move_to_object(f, OBJECT_ENTRY, p, &o);
2371 if (r < 0)
2372 return r;
2373
2374 if (ret)
2375 *ret = o;
2376
2377 if (offset)
2378 *offset = p;
2379
2380 if (idx)
2381 *idx = t + i + (subtract_one ? -1 : 0);
2382
2383 return 1;
2384}
2385
2386static int generic_array_bisect_plus_one(
2387 JournalFile *f,
2388 uint64_t extra,
2389 uint64_t first,
2390 uint64_t n,
2391 uint64_t needle,
2392 int (*test_object)(JournalFile *f, uint64_t p, uint64_t needle),
2393 direction_t direction,
2394 Object **ret,
2395 uint64_t *offset,
2396 uint64_t *idx) {
2397
2398 int r;
2399 bool_Bool step_back = false0;
2400 Object *o;
2401
2402 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 2402
, __PRETTY_FUNCTION__); } while (0)
;
2403 assert(test_object)do { if ((__builtin_expect(!!(!(test_object)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("test_object"), "../src/journal/journal-file.c"
, 2403, __PRETTY_FUNCTION__); } while (0)
;
2404
2405 if (n <= 0)
2406 return 0;
2407
2408 /* This bisects the array in object 'first', but first checks
2409 * an extra */
2410 r = test_object(f, extra, needle);
2411 if (r < 0)
2412 return r;
2413
2414 if (r == TEST_FOUND)
2415 r = direction == DIRECTION_DOWN ? TEST_RIGHT : TEST_LEFT;
2416
2417 /* if we are looking with DIRECTION_UP then we need to first
2418 see if in the actual array there is a matching entry, and
2419 return the last one of that. But if there isn't any we need
2420 to return this one. Hence remember this, and return it
2421 below. */
2422 if (r == TEST_LEFT)
2423 step_back = direction == DIRECTION_UP;
2424
2425 if (r == TEST_RIGHT) {
2426 if (direction == DIRECTION_DOWN)
2427 goto found;
2428 else
2429 return 0;
2430 }
2431
2432 r = generic_array_bisect(f, first, n-1, needle, test_object, direction, ret, offset, idx);
2433
2434 if (r == 0 && step_back)
2435 goto found;
2436
2437 if (r > 0 && idx)
2438 (*idx)++;
2439
2440 return r;
2441
2442found:
2443 r = journal_file_move_to_object(f, OBJECT_ENTRY, extra, &o);
2444 if (r < 0)
2445 return r;
2446
2447 if (ret)
2448 *ret = o;
2449
2450 if (offset)
2451 *offset = extra;
2452
2453 if (idx)
2454 *idx = 0;
2455
2456 return 1;
2457}
2458
2459_pure___attribute__ ((pure)) static int test_object_offset(JournalFile *f, uint64_t p, uint64_t needle) {
2460 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 2460
, __PRETTY_FUNCTION__); } while (0)
;
2461 assert(p > 0)do { if ((__builtin_expect(!!(!(p > 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("p > 0"), "../src/journal/journal-file.c"
, 2461, __PRETTY_FUNCTION__); } while (0)
;
2462
2463 if (p == needle)
2464 return TEST_FOUND;
2465 else if (p < needle)
2466 return TEST_LEFT;
2467 else
2468 return TEST_RIGHT;
2469}
2470
2471static int test_object_seqnum(JournalFile *f, uint64_t p, uint64_t needle) {
2472 Object *o;
2473 int r;
2474
2475 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 2475
, __PRETTY_FUNCTION__); } while (0)
;
2476 assert(p > 0)do { if ((__builtin_expect(!!(!(p > 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("p > 0"), "../src/journal/journal-file.c"
, 2476, __PRETTY_FUNCTION__); } while (0)
;
2477
2478 r = journal_file_move_to_object(f, OBJECT_ENTRY, p, &o);
2479 if (r < 0)
2480 return r;
2481
2482 if (le64toh(o->entry.seqnum) == needle)
2483 return TEST_FOUND;
2484 else if (le64toh(o->entry.seqnum) < needle)
2485 return TEST_LEFT;
2486 else
2487 return TEST_RIGHT;
2488}
2489
2490int journal_file_move_to_entry_by_seqnum(
2491 JournalFile *f,
2492 uint64_t seqnum,
2493 direction_t direction,
2494 Object **ret,
2495 uint64_t *offset) {
2496 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 2496
, __PRETTY_FUNCTION__); } while (0)
;
2497 assert(f->header)do { if ((__builtin_expect(!!(!(f->header)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f->header"), "../src/journal/journal-file.c"
, 2497, __PRETTY_FUNCTION__); } while (0)
;
2498
2499 return generic_array_bisect(f,
2500 le64toh(f->header->entry_array_offset),
2501 le64toh(f->header->n_entries),
2502 seqnum,
2503 test_object_seqnum,
2504 direction,
2505 ret, offset, NULL((void*)0));
2506}
2507
2508static int test_object_realtime(JournalFile *f, uint64_t p, uint64_t needle) {
2509 Object *o;
2510 int r;
2511
2512 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 2512
, __PRETTY_FUNCTION__); } while (0)
;
2513 assert(p > 0)do { if ((__builtin_expect(!!(!(p > 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("p > 0"), "../src/journal/journal-file.c"
, 2513, __PRETTY_FUNCTION__); } while (0)
;
2514
2515 r = journal_file_move_to_object(f, OBJECT_ENTRY, p, &o);
2516 if (r < 0)
2517 return r;
2518
2519 if (le64toh(o->entry.realtime) == needle)
2520 return TEST_FOUND;
2521 else if (le64toh(o->entry.realtime) < needle)
2522 return TEST_LEFT;
2523 else
2524 return TEST_RIGHT;
2525}
2526
2527int journal_file_move_to_entry_by_realtime(
2528 JournalFile *f,
2529 uint64_t realtime,
2530 direction_t direction,
2531 Object **ret,
2532 uint64_t *offset) {
2533 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 2533
, __PRETTY_FUNCTION__); } while (0)
;
2534 assert(f->header)do { if ((__builtin_expect(!!(!(f->header)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f->header"), "../src/journal/journal-file.c"
, 2534, __PRETTY_FUNCTION__); } while (0)
;
2535
2536 return generic_array_bisect(f,
2537 le64toh(f->header->entry_array_offset),
2538 le64toh(f->header->n_entries),
2539 realtime,
2540 test_object_realtime,
2541 direction,
2542 ret, offset, NULL((void*)0));
2543}
2544
2545static int test_object_monotonic(JournalFile *f, uint64_t p, uint64_t needle) {
2546 Object *o;
2547 int r;
2548
2549 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 2549
, __PRETTY_FUNCTION__); } while (0)
;
2550 assert(p > 0)do { if ((__builtin_expect(!!(!(p > 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("p > 0"), "../src/journal/journal-file.c"
, 2550, __PRETTY_FUNCTION__); } while (0)
;
2551
2552 r = journal_file_move_to_object(f, OBJECT_ENTRY, p, &o);
2553 if (r < 0)
2554 return r;
2555
2556 if (le64toh(o->entry.monotonic) == needle)
2557 return TEST_FOUND;
2558 else if (le64toh(o->entry.monotonic) < needle)
2559 return TEST_LEFT;
2560 else
2561 return TEST_RIGHT;
2562}
2563
2564static int find_data_object_by_boot_id(
2565 JournalFile *f,
2566 sd_id128_t boot_id,
2567 Object **o,
2568 uint64_t *b) {
2569
2570 char t[STRLEN("_BOOT_ID=")(sizeof("""_BOOT_ID=""") - 1) + 32 + 1] = "_BOOT_ID=";
2571
2572 sd_id128_to_string(boot_id, t + 9);
2573 return journal_file_find_data_object(f, t, sizeof(t) - 1, o, b);
2574}
2575
2576int journal_file_move_to_entry_by_monotonic(
2577 JournalFile *f,
2578 sd_id128_t boot_id,
2579 uint64_t monotonic,
2580 direction_t direction,
2581 Object **ret,
2582 uint64_t *offset) {
2583
2584 Object *o;
2585 int r;
2586
2587 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 2587
, __PRETTY_FUNCTION__); } while (0)
;
2588
2589 r = find_data_object_by_boot_id(f, boot_id, &o, NULL((void*)0));
2590 if (r < 0)
2591 return r;
2592 if (r == 0)
2593 return -ENOENT2;
2594
2595 return generic_array_bisect_plus_one(f,
2596 le64toh(o->data.entry_offset),
2597 le64toh(o->data.entry_array_offset),
2598 le64toh(o->data.n_entries),
2599 monotonic,
2600 test_object_monotonic,
2601 direction,
2602 ret, offset, NULL((void*)0));
2603}
2604
2605void journal_file_reset_location(JournalFile *f) {
2606 f->location_type = LOCATION_HEAD;
2607 f->current_offset = 0;
2608 f->current_seqnum = 0;
2609 f->current_realtime = 0;
2610 f->current_monotonic = 0;
2611 zero(f->current_boot_id)(({ size_t _l_ = (sizeof(f->current_boot_id)); void *_x_ =
(&(f->current_boot_id)); _l_ == 0 ? _x_ : memset(_x_,
0, _l_); }))
;
2612 f->current_xor_hash = 0;
2613}
2614
2615void journal_file_save_location(JournalFile *f, Object *o, uint64_t offset) {
2616 f->location_type = LOCATION_SEEK;
2617 f->current_offset = offset;
2618 f->current_seqnum = le64toh(o->entry.seqnum);
2619 f->current_realtime = le64toh(o->entry.realtime);
2620 f->current_monotonic = le64toh(o->entry.monotonic);
2621 f->current_boot_id = o->entry.boot_id;
2622 f->current_xor_hash = le64toh(o->entry.xor_hash);
2623}
2624
2625int journal_file_compare_locations(JournalFile *af, JournalFile *bf) {
2626 assert(af)do { if ((__builtin_expect(!!(!(af)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("af"), "../src/journal/journal-file.c", 2626
, __PRETTY_FUNCTION__); } while (0)
;
2627 assert(af->header)do { if ((__builtin_expect(!!(!(af->header)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("af->header"), "../src/journal/journal-file.c"
, 2627, __PRETTY_FUNCTION__); } while (0)
;
2628 assert(bf)do { if ((__builtin_expect(!!(!(bf)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("bf"), "../src/journal/journal-file.c", 2628
, __PRETTY_FUNCTION__); } while (0)
;
2629 assert(bf->header)do { if ((__builtin_expect(!!(!(bf->header)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("bf->header"), "../src/journal/journal-file.c"
, 2629, __PRETTY_FUNCTION__); } while (0)
;
2630 assert(af->location_type == LOCATION_SEEK)do { if ((__builtin_expect(!!(!(af->location_type == LOCATION_SEEK
)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("af->location_type == LOCATION_SEEK"
), "../src/journal/journal-file.c", 2630, __PRETTY_FUNCTION__
); } while (0)
;
2631 assert(bf->location_type == LOCATION_SEEK)do { if ((__builtin_expect(!!(!(bf->location_type == LOCATION_SEEK
)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("bf->location_type == LOCATION_SEEK"
), "../src/journal/journal-file.c", 2631, __PRETTY_FUNCTION__
); } while (0)
;
2632
2633 /* If contents and timestamps match, these entries are
2634 * identical, even if the seqnum does not match */
2635 if (sd_id128_equal(af->current_boot_id, bf->current_boot_id) &&
2636 af->current_monotonic == bf->current_monotonic &&
2637 af->current_realtime == bf->current_realtime &&
2638 af->current_xor_hash == bf->current_xor_hash)
2639 return 0;
2640
2641 if (sd_id128_equal(af->header->seqnum_id, bf->header->seqnum_id)) {
2642
2643 /* If this is from the same seqnum source, compare
2644 * seqnums */
2645 if (af->current_seqnum < bf->current_seqnum)
2646 return -1;
2647 if (af->current_seqnum > bf->current_seqnum)
2648 return 1;
2649
2650 /* Wow! This is weird, different data but the same
2651 * seqnums? Something is borked, but let's make the
2652 * best of it and compare by time. */
2653 }
2654
2655 if (sd_id128_equal(af->current_boot_id, bf->current_boot_id)) {
2656
2657 /* If the boot id matches, compare monotonic time */
2658 if (af->current_monotonic < bf->current_monotonic)
2659 return -1;
2660 if (af->current_monotonic > bf->current_monotonic)
2661 return 1;
2662 }
2663
2664 /* Otherwise, compare UTC time */
2665 if (af->current_realtime < bf->current_realtime)
2666 return -1;
2667 if (af->current_realtime > bf->current_realtime)
2668 return 1;
2669
2670 /* Finally, compare by contents */
2671 if (af->current_xor_hash < bf->current_xor_hash)
2672 return -1;
2673 if (af->current_xor_hash > bf->current_xor_hash)
2674 return 1;
2675
2676 return 0;
2677}
2678
2679static int bump_array_index(uint64_t *i, direction_t direction, uint64_t n) {
2680
2681 /* Increase or decrease the specified index, in the right direction. */
2682
2683 if (direction == DIRECTION_DOWN) {
2684 if (*i >= n - 1)
2685 return 0;
2686
2687 (*i) ++;
2688 } else {
2689 if (*i <= 0)
2690 return 0;
2691
2692 (*i) --;
2693 }
2694
2695 return 1;
2696}
2697
2698static bool_Bool check_properly_ordered(uint64_t new_offset, uint64_t old_offset, direction_t direction) {
2699
2700 /* Consider it an error if any of the two offsets is uninitialized */
2701 if (old_offset == 0 || new_offset == 0)
2702 return false0;
2703
2704 /* If we go down, the new offset must be larger than the old one. */
2705 return direction == DIRECTION_DOWN ?
2706 new_offset > old_offset :
2707 new_offset < old_offset;
2708}
2709
2710int journal_file_next_entry(
2711 JournalFile *f,
2712 uint64_t p,
2713 direction_t direction,
2714 Object **ret, uint64_t *offset) {
2715
2716 uint64_t i, n, ofs;
2717 int r;
2718
2719 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 2719
, __PRETTY_FUNCTION__); } while (0)
;
2720 assert(f->header)do { if ((__builtin_expect(!!(!(f->header)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f->header"), "../src/journal/journal-file.c"
, 2720, __PRETTY_FUNCTION__); } while (0)
;
2721
2722 n = le64toh(f->header->n_entries);
2723 if (n <= 0)
2724 return 0;
2725
2726 if (p == 0)
2727 i = direction == DIRECTION_DOWN ? 0 : n - 1;
2728 else {
2729 r = generic_array_bisect(f,
2730 le64toh(f->header->entry_array_offset),
2731 le64toh(f->header->n_entries),
2732 p,
2733 test_object_offset,
2734 DIRECTION_DOWN,
2735 NULL((void*)0), NULL((void*)0),
2736 &i);
2737 if (r <= 0)
2738 return r;
2739
2740 r = bump_array_index(&i, direction, n);
2741 if (r <= 0)
2742 return r;
2743 }
2744
2745 /* And jump to it */
2746 for (;;) {
2747 r = generic_array_get(f,
2748 le64toh(f->header->entry_array_offset),
2749 i,
2750 ret, &ofs);
2751 if (r > 0)
2752 break;
2753 if (r != -EBADMSG74)
2754 return r;
2755
2756 /* OK, so this entry is borked. Most likely some entry didn't get synced to disk properly, let's see if
2757 * the next one might work for us instead. */
2758 log_debug_errno(r, "Entry item %" PRIu64 " is bad, skipping over it.", i)({ int _level = ((7)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 2758, __func__, "Entry item %"
"l" "u" " is bad, skipping over it.", i) : -abs(_e); })
;
2759
2760 r = bump_array_index(&i, direction, n);
2761 if (r <= 0)
2762 return r;
2763 }
2764
2765 /* Ensure our array is properly ordered. */
2766 if (p > 0 && !check_properly_ordered(ofs, p, direction)) {
2767 log_debug("%s: entry array not properly ordered at entry %" PRIu64, f->path, i)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 2767, __func__, "%s: entry array not properly ordered at entry %"
"l" "u", f->path, i) : -abs(_e); })
;
2768 return -EBADMSG74;
2769 }
2770
2771 if (offset)
2772 *offset = ofs;
2773
2774 return 1;
2775}
2776
2777int journal_file_next_entry_for_data(
2778 JournalFile *f,
2779 Object *o, uint64_t p,
2780 uint64_t data_offset,
2781 direction_t direction,
2782 Object **ret, uint64_t *offset) {
2783
2784 uint64_t i, n, ofs;
2785 Object *d;
2786 int r;
2787
2788 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 2788
, __PRETTY_FUNCTION__); } while (0)
;
2789 assert(p > 0 || !o)do { if ((__builtin_expect(!!(!(p > 0 || !o)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("p > 0 || !o"), "../src/journal/journal-file.c"
, 2789, __PRETTY_FUNCTION__); } while (0)
;
2790
2791 r = journal_file_move_to_object(f, OBJECT_DATA, data_offset, &d);
2792 if (r < 0)
2793 return r;
2794
2795 n = le64toh(d->data.n_entries);
2796 if (n <= 0)
2797 return n;
2798
2799 if (!o)
2800 i = direction == DIRECTION_DOWN ? 0 : n - 1;
2801 else {
2802 if (o->object.type != OBJECT_ENTRY)
2803 return -EINVAL22;
2804
2805 r = generic_array_bisect_plus_one(f,
2806 le64toh(d->data.entry_offset),
2807 le64toh(d->data.entry_array_offset),
2808 le64toh(d->data.n_entries),
2809 p,
2810 test_object_offset,
2811 DIRECTION_DOWN,
2812 NULL((void*)0), NULL((void*)0),
2813 &i);
2814
2815 if (r <= 0)
2816 return r;
2817
2818 r = bump_array_index(&i, direction, n);
2819 if (r <= 0)
2820 return r;
2821 }
2822
2823 for (;;) {
2824 r = generic_array_get_plus_one(f,
2825 le64toh(d->data.entry_offset),
2826 le64toh(d->data.entry_array_offset),
2827 i,
2828 ret, &ofs);
2829 if (r > 0)
2830 break;
2831 if (r != -EBADMSG74)
2832 return r;
2833
2834 log_debug_errno(r, "Data entry item %" PRIu64 " is bad, skipping over it.", i)({ int _level = ((7)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 2834, __func__, "Data entry item %"
"l" "u" " is bad, skipping over it.", i) : -abs(_e); })
;
2835
2836 r = bump_array_index(&i, direction, n);
2837 if (r <= 0)
2838 return r;
2839 }
2840
2841 /* Ensure our array is properly ordered. */
2842 if (p > 0 && check_properly_ordered(ofs, p, direction)) {
2843 log_debug("%s data entry array not properly ordered at entry %" PRIu64, f->path, i)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 2843, __func__, "%s data entry array not properly ordered at entry %"
"l" "u", f->path, i) : -abs(_e); })
;
2844 return -EBADMSG74;
2845 }
2846
2847 if (offset)
2848 *offset = ofs;
2849
2850 return 1;
2851}
2852
2853int journal_file_move_to_entry_by_offset_for_data(
2854 JournalFile *f,
2855 uint64_t data_offset,
2856 uint64_t p,
2857 direction_t direction,
2858 Object **ret, uint64_t *offset) {
2859
2860 int r;
2861 Object *d;
2862
2863 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 2863
, __PRETTY_FUNCTION__); } while (0)
;
2864
2865 r = journal_file_move_to_object(f, OBJECT_DATA, data_offset, &d);
2866 if (r < 0)
2867 return r;
2868
2869 return generic_array_bisect_plus_one(f,
2870 le64toh(d->data.entry_offset),
2871 le64toh(d->data.entry_array_offset),
2872 le64toh(d->data.n_entries),
2873 p,
2874 test_object_offset,
2875 direction,
2876 ret, offset, NULL((void*)0));
2877}
2878
2879int journal_file_move_to_entry_by_monotonic_for_data(
2880 JournalFile *f,
2881 uint64_t data_offset,
2882 sd_id128_t boot_id,
2883 uint64_t monotonic,
2884 direction_t direction,
2885 Object **ret, uint64_t *offset) {
2886
2887 Object *o, *d;
2888 int r;
2889 uint64_t b, z;
2890
2891 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 2891
, __PRETTY_FUNCTION__); } while (0)
;
2892
2893 /* First, seek by time */
2894 r = find_data_object_by_boot_id(f, boot_id, &o, &b);
2895 if (r < 0)
2896 return r;
2897 if (r == 0)
2898 return -ENOENT2;
2899
2900 r = generic_array_bisect_plus_one(f,
2901 le64toh(o->data.entry_offset),
2902 le64toh(o->data.entry_array_offset),
2903 le64toh(o->data.n_entries),
2904 monotonic,
2905 test_object_monotonic,
2906 direction,
2907 NULL((void*)0), &z, NULL((void*)0));
2908 if (r <= 0)
2909 return r;
2910
2911 /* And now, continue seeking until we find an entry that
2912 * exists in both bisection arrays */
2913
2914 for (;;) {
2915 Object *qo;
2916 uint64_t p, q;
2917
2918 r = journal_file_move_to_object(f, OBJECT_DATA, data_offset, &d);
2919 if (r < 0)
2920 return r;
2921
2922 r = generic_array_bisect_plus_one(f,
2923 le64toh(d->data.entry_offset),
2924 le64toh(d->data.entry_array_offset),
2925 le64toh(d->data.n_entries),
2926 z,
2927 test_object_offset,
2928 direction,
2929 NULL((void*)0), &p, NULL((void*)0));
2930 if (r <= 0)
2931 return r;
2932
2933 r = journal_file_move_to_object(f, OBJECT_DATA, b, &o);
2934 if (r < 0)
2935 return r;
2936
2937 r = generic_array_bisect_plus_one(f,
2938 le64toh(o->data.entry_offset),
2939 le64toh(o->data.entry_array_offset),
2940 le64toh(o->data.n_entries),
2941 p,
2942 test_object_offset,
2943 direction,
2944 &qo, &q, NULL((void*)0));
2945
2946 if (r <= 0)
2947 return r;
2948
2949 if (p == q) {
2950 if (ret)
2951 *ret = qo;
2952 if (offset)
2953 *offset = q;
2954
2955 return 1;
2956 }
2957
2958 z = q;
2959 }
2960}
2961
2962int journal_file_move_to_entry_by_seqnum_for_data(
2963 JournalFile *f,
2964 uint64_t data_offset,
2965 uint64_t seqnum,
2966 direction_t direction,
2967 Object **ret, uint64_t *offset) {
2968
2969 Object *d;
2970 int r;
2971
2972 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 2972
, __PRETTY_FUNCTION__); } while (0)
;
2973
2974 r = journal_file_move_to_object(f, OBJECT_DATA, data_offset, &d);
2975 if (r < 0)
2976 return r;
2977
2978 return generic_array_bisect_plus_one(f,
2979 le64toh(d->data.entry_offset),
2980 le64toh(d->data.entry_array_offset),
2981 le64toh(d->data.n_entries),
2982 seqnum,
2983 test_object_seqnum,
2984 direction,
2985 ret, offset, NULL((void*)0));
2986}
2987
2988int journal_file_move_to_entry_by_realtime_for_data(
2989 JournalFile *f,
2990 uint64_t data_offset,
2991 uint64_t realtime,
2992 direction_t direction,
2993 Object **ret, uint64_t *offset) {
2994
2995 Object *d;
2996 int r;
2997
2998 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 2998
, __PRETTY_FUNCTION__); } while (0)
;
2999
3000 r = journal_file_move_to_object(f, OBJECT_DATA, data_offset, &d);
3001 if (r < 0)
3002 return r;
3003
3004 return generic_array_bisect_plus_one(f,
3005 le64toh(d->data.entry_offset),
3006 le64toh(d->data.entry_array_offset),
3007 le64toh(d->data.n_entries),
3008 realtime,
3009 test_object_realtime,
3010 direction,
3011 ret, offset, NULL((void*)0));
3012}
3013
3014void journal_file_dump(JournalFile *f) {
3015 Object *o;
3016 int r;
3017 uint64_t p;
3018
3019 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 3019
, __PRETTY_FUNCTION__); } while (0)
;
3020 assert(f->header)do { if ((__builtin_expect(!!(!(f->header)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f->header"), "../src/journal/journal-file.c"
, 3020, __PRETTY_FUNCTION__); } while (0)
;
3021
3022 journal_file_print_header(f);
3023
3024 p = le64toh(f->header->header_size);
3025 while (p != 0) {
3026 r = journal_file_move_to_object(f, OBJECT_UNUSED, p, &o);
3027 if (r < 0)
3028 goto fail;
3029
3030 switch (o->object.type) {
3031
3032 case OBJECT_UNUSED:
3033 printf("Type: OBJECT_UNUSED\n");
3034 break;
3035
3036 case OBJECT_DATA:
3037 printf("Type: OBJECT_DATA\n");
3038 break;
3039
3040 case OBJECT_FIELD:
3041 printf("Type: OBJECT_FIELD\n");
3042 break;
3043
3044 case OBJECT_ENTRY:
3045 printf("Type: OBJECT_ENTRY seqnum=%"PRIu64"l" "u"" monotonic=%"PRIu64"l" "u"" realtime=%"PRIu64"l" "u""\n",
3046 le64toh(o->entry.seqnum),
3047 le64toh(o->entry.monotonic),
3048 le64toh(o->entry.realtime));
3049 break;
3050
3051 case OBJECT_FIELD_HASH_TABLE:
3052 printf("Type: OBJECT_FIELD_HASH_TABLE\n");
3053 break;
3054
3055 case OBJECT_DATA_HASH_TABLE:
3056 printf("Type: OBJECT_DATA_HASH_TABLE\n");
3057 break;
3058
3059 case OBJECT_ENTRY_ARRAY:
3060 printf("Type: OBJECT_ENTRY_ARRAY\n");
3061 break;
3062
3063 case OBJECT_TAG:
3064 printf("Type: OBJECT_TAG seqnum=%"PRIu64"l" "u"" epoch=%"PRIu64"l" "u""\n",
3065 le64toh(o->tag.seqnum),
3066 le64toh(o->tag.epoch));
3067 break;
3068
3069 default:
3070 printf("Type: unknown (%i)\n", o->object.type);
3071 break;
3072 }
3073
3074 if (o->object.flags & OBJECT_COMPRESSION_MASK(OBJECT_COMPRESSED_XZ | OBJECT_COMPRESSED_LZ4))
3075 printf("Flags: %s\n",
3076 object_compressed_to_string(o->object.flags & OBJECT_COMPRESSION_MASK(OBJECT_COMPRESSED_XZ | OBJECT_COMPRESSED_LZ4)));
3077
3078 if (p == le64toh(f->header->tail_object_offset))
3079 p = 0;
3080 else
3081 p = p + ALIGN64(le64toh(o->object.size))(((le64toh(o->object.size)) + 7ULL) & ~7ULL);
3082 }
3083
3084 return;
3085fail:
3086 log_error("File corrupt")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 3086, __func__, "File corrupt"
) : -abs(_e); })
;
3087}
3088
3089static const char* format_timestamp_safe(char *buf, size_t l, usec_t t) {
3090 const char *x;
3091
3092 x = format_timestamp(buf, l, t);
3093 if (x)
3094 return x;
3095 return " --- ";
3096}
3097
3098void journal_file_print_header(JournalFile *f) {
3099 char a[33], b[33], c[33], d[33];
3100 char x[FORMAT_TIMESTAMP_MAX(3+1+10+1+8+1+6+1+6+1)], y[FORMAT_TIMESTAMP_MAX(3+1+10+1+8+1+6+1+6+1)], z[FORMAT_TIMESTAMP_MAX(3+1+10+1+8+1+6+1+6+1)];
3101 struct stat st;
3102 char bytes[FORMAT_BYTES_MAX8];
3103
3104 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 3104
, __PRETTY_FUNCTION__); } while (0)
;
3105 assert(f->header)do { if ((__builtin_expect(!!(!(f->header)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f->header"), "../src/journal/journal-file.c"
, 3105, __PRETTY_FUNCTION__); } while (0)
;
3106
3107 printf("File Path: %s\n"
3108 "File ID: %s\n"
3109 "Machine ID: %s\n"
3110 "Boot ID: %s\n"
3111 "Sequential Number ID: %s\n"
3112 "State: %s\n"
3113 "Compatible Flags:%s%s\n"
3114 "Incompatible Flags:%s%s%s\n"
3115 "Header size: %"PRIu64"l" "u""\n"
3116 "Arena size: %"PRIu64"l" "u""\n"
3117 "Data Hash Table Size: %"PRIu64"l" "u""\n"
3118 "Field Hash Table Size: %"PRIu64"l" "u""\n"
3119 "Rotate Suggested: %s\n"
3120 "Head Sequential Number: %"PRIu64"l" "u"" (%"PRIx64"l" "x"")\n"
3121 "Tail Sequential Number: %"PRIu64"l" "u"" (%"PRIx64"l" "x"")\n"
3122 "Head Realtime Timestamp: %s (%"PRIx64"l" "x"")\n"
3123 "Tail Realtime Timestamp: %s (%"PRIx64"l" "x"")\n"
3124 "Tail Monotonic Timestamp: %s (%"PRIx64"l" "x"")\n"
3125 "Objects: %"PRIu64"l" "u""\n"
3126 "Entry Objects: %"PRIu64"l" "u""\n",
3127 f->path,
3128 sd_id128_to_string(f->header->file_id, a),
3129 sd_id128_to_string(f->header->machine_id, b),
3130 sd_id128_to_string(f->header->boot_id, c),
3131 sd_id128_to_string(f->header->seqnum_id, d),
3132 f->header->state == STATE_OFFLINE ? "OFFLINE" :
3133 f->header->state == STATE_ONLINE ? "ONLINE" :
3134 f->header->state == STATE_ARCHIVED ? "ARCHIVED" : "UNKNOWN",
3135 JOURNAL_HEADER_SEALED(f->header)(!!(le32toh((f->header)->compatible_flags) & HEADER_COMPATIBLE_SEALED
))
? " SEALED" : "",
3136 (le32toh(f->header->compatible_flags) & ~HEADER_COMPATIBLE_ANYHEADER_COMPATIBLE_SEALED) ? " ???" : "",
3137 JOURNAL_HEADER_COMPRESSED_XZ(f->header)(!!(le32toh((f->header)->incompatible_flags) & HEADER_INCOMPATIBLE_COMPRESSED_XZ
))
? " COMPRESSED-XZ" : "",
3138 JOURNAL_HEADER_COMPRESSED_LZ4(f->header)(!!(le32toh((f->header)->incompatible_flags) & HEADER_INCOMPATIBLE_COMPRESSED_LZ4
))
? " COMPRESSED-LZ4" : "",
3139 (le32toh(f->header->incompatible_flags) & ~HEADER_INCOMPATIBLE_ANY(HEADER_INCOMPATIBLE_COMPRESSED_XZ|HEADER_INCOMPATIBLE_COMPRESSED_LZ4
)
) ? " ???" : "",
3140 le64toh(f->header->header_size),
3141 le64toh(f->header->arena_size),
3142 le64toh(f->header->data_hash_table_size) / sizeof(HashItem),
3143 le64toh(f->header->field_hash_table_size) / sizeof(HashItem),
3144 yes_no(journal_file_rotate_suggested(f, 0)),
3145 le64toh(f->header->head_entry_seqnum), le64toh(f->header->head_entry_seqnum),
3146 le64toh(f->header->tail_entry_seqnum), le64toh(f->header->tail_entry_seqnum),
3147 format_timestamp_safe(x, sizeof(x), le64toh(f->header->head_entry_realtime)), le64toh(f->header->head_entry_realtime),
3148 format_timestamp_safe(y, sizeof(y), le64toh(f->header->tail_entry_realtime)), le64toh(f->header->tail_entry_realtime),
3149 format_timespan(z, sizeof(z), le64toh(f->header->tail_entry_monotonic), USEC_PER_MSEC((usec_t) 1000ULL)), le64toh(f->header->tail_entry_monotonic),
3150 le64toh(f->header->n_objects),
3151 le64toh(f->header->n_entries));
3152
3153 if (JOURNAL_HEADER_CONTAINS(f->header, n_data)(le64toh((f->header)->header_size) >= __builtin_offsetof
(Header, n_data) + sizeof((f->header)->n_data))
)
3154 printf("Data Objects: %"PRIu64"l" "u""\n"
3155 "Data Hash Table Fill: %.1f%%\n",
3156 le64toh(f->header->n_data),
3157 100.0 * (double) le64toh(f->header->n_data) / ((double) (le64toh(f->header->data_hash_table_size) / sizeof(HashItem))));
3158
3159 if (JOURNAL_HEADER_CONTAINS(f->header, n_fields)(le64toh((f->header)->header_size) >= __builtin_offsetof
(Header, n_fields) + sizeof((f->header)->n_fields))
)
3160 printf("Field Objects: %"PRIu64"l" "u""\n"
3161 "Field Hash Table Fill: %.1f%%\n",
3162 le64toh(f->header->n_fields),
3163 100.0 * (double) le64toh(f->header->n_fields) / ((double) (le64toh(f->header->field_hash_table_size) / sizeof(HashItem))));
3164
3165 if (JOURNAL_HEADER_CONTAINS(f->header, n_tags)(le64toh((f->header)->header_size) >= __builtin_offsetof
(Header, n_tags) + sizeof((f->header)->n_tags))
)
3166 printf("Tag Objects: %"PRIu64"l" "u""\n",
3167 le64toh(f->header->n_tags));
3168 if (JOURNAL_HEADER_CONTAINS(f->header, n_entry_arrays)(le64toh((f->header)->header_size) >= __builtin_offsetof
(Header, n_entry_arrays) + sizeof((f->header)->n_entry_arrays
))
)
3169 printf("Entry Array Objects: %"PRIu64"l" "u""\n",
3170 le64toh(f->header->n_entry_arrays));
3171
3172 if (fstat(f->fd, &st) >= 0)
3173 printf("Disk usage: %s\n", format_bytes(bytes, sizeof(bytes), (uint64_t) st.st_blocks * 512ULL));
3174}
3175
3176static int journal_file_warn_btrfs(JournalFile *f) {
3177 unsigned attrs;
3178 int r;
3179
3180 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 3180
, __PRETTY_FUNCTION__); } while (0)
;
3181
3182 /* Before we write anything, check if the COW logic is turned
3183 * off on btrfs. Given our write pattern that is quite
3184 * unfriendly to COW file systems this should greatly improve
3185 * performance on COW file systems, such as btrfs, at the
3186 * expense of data integrity features (which shouldn't be too
3187 * bad, given that we do our own checksumming). */
3188
3189 r = btrfs_is_filesystem(f->fd);
3190 if (r < 0)
3191 return log_warning_errno(r, "Failed to determine if journal is on btrfs: %m")({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 3191, __func__, "Failed to determine if journal is on btrfs: %m"
) : -abs(_e); })
;
3192 if (!r)
3193 return 0;
3194
3195 r = read_attr_fd(f->fd, &attrs);
3196 if (r < 0)
3197 return log_warning_errno(r, "Failed to read file attributes: %m")({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 3197, __func__, "Failed to read file attributes: %m"
) : -abs(_e); })
;
3198
3199 if (attrs & FS_NOCOW_FL0x00800000) {
3200 log_debug("Detected btrfs file system with copy-on-write disabled, all is good.")({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 3200, __func__, "Detected btrfs file system with copy-on-write disabled, all is good."
) : -abs(_e); })
;
3201 return 0;
3202 }
3203
3204 log_notice("Creating journal file %s on a btrfs file system, and copy-on-write is enabled. "({ int _level = (((5))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 3206, __func__, "Creating journal file %s on a btrfs file system, and copy-on-write is enabled. "
"This is likely to slow down journal access substantially, please consider turning "
"off the copy-on-write file attribute on the journal directory, using chattr +C."
, f->path) : -abs(_e); })
3205 "This is likely to slow down journal access substantially, please consider turning "({ int _level = (((5))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 3206, __func__, "Creating journal file %s on a btrfs file system, and copy-on-write is enabled. "
"This is likely to slow down journal access substantially, please consider turning "
"off the copy-on-write file attribute on the journal directory, using chattr +C."
, f->path) : -abs(_e); })
3206 "off the copy-on-write file attribute on the journal directory, using chattr +C.", f->path)({ int _level = (((5))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 3206, __func__, "Creating journal file %s on a btrfs file system, and copy-on-write is enabled. "
"This is likely to slow down journal access substantially, please consider turning "
"off the copy-on-write file attribute on the journal directory, using chattr +C."
, f->path) : -abs(_e); })
;
3207
3208 return 1;
3209}
3210
3211int journal_file_open(
3212 int fd,
3213 const char *fname,
3214 int flags,
3215 mode_t mode,
3216 bool_Bool compress,
3217 uint64_t compress_threshold_bytes,
3218 bool_Bool seal,
3219 JournalMetrics *metrics,
3220 MMapCache *mmap_cache,
3221 Set *deferred_closes,
3222 JournalFile *template,
3223 JournalFile **ret) {
3224
3225 bool_Bool newly_created = false0;
3226 JournalFile *f;
3227 void *h;
3228 int r;
3229 char bytes[FORMAT_BYTES_MAX8];
3230
3231 assert(ret)do { if ((__builtin_expect(!!(!(ret)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ret"), "../src/journal/journal-file.c",
3231, __PRETTY_FUNCTION__); } while (0)
;
3232 assert(fd >= 0 || fname)do { if ((__builtin_expect(!!(!(fd >= 0 || fname)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("fd >= 0 || fname"), "../src/journal/journal-file.c"
, 3232, __PRETTY_FUNCTION__); } while (0)
;
3233
3234 if (!IN_SET((flags & O_ACCMODE), O_RDONLY, O_RDWR)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){00, 02})/sizeof(int)]; switch((flags &
0003)) { case 00: case 02: _found = 1; break; default: break
; } _found; })
)
3235 return -EINVAL22;
3236
3237 if (fname && (flags & O_CREAT0100) && !endswith(fname, ".journal"))
3238 return -EINVAL22;
3239
3240 f = new0(JournalFile, 1)((JournalFile*) calloc((1), sizeof(JournalFile)));
3241 if (!f)
3242 return -ENOMEM12;
3243
3244 f->fd = fd;
3245 f->mode = mode;
3246
3247 f->flags = flags;
3248 f->prot = prot_from_flags(flags);
3249 f->writable = (flags & O_ACCMODE0003) != O_RDONLY00;
3250#if HAVE_LZ41
3251 f->compress_lz4 = compress;
3252#elif HAVE_XZ1
3253 f->compress_xz = compress;
3254#endif
3255
3256 if (compress_threshold_bytes == (uint64_t) -1)
3257 f->compress_threshold_bytes = DEFAULT_COMPRESS_THRESHOLD(512ULL);
3258 else
3259 f->compress_threshold_bytes = MAX(MIN_COMPRESS_THRESHOLD, compress_threshold_bytes)__extension__ ({ const typeof(((8ULL))) __unique_prefix_A32 =
(((8ULL))); const typeof((compress_threshold_bytes)) __unique_prefix_B33
= ((compress_threshold_bytes)); __unique_prefix_A32 > __unique_prefix_B33
? __unique_prefix_A32 : __unique_prefix_B33; })
;
3260
3261#if HAVE_GCRYPT1
3262 f->seal = seal;
3263#endif
3264
3265 log_debug("Journal effective settings seal=%s compress=%s compress_threshold_bytes=%s",({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 3267, __func__, "Journal effective settings seal=%s compress=%s compress_threshold_bytes=%s"
, yes_no(f->seal), yes_no(JOURNAL_FILE_COMPRESS(f)), format_bytes
(bytes, sizeof(bytes), f->compress_threshold_bytes)) : -abs
(_e); })
3266 yes_no(f->seal), yes_no(JOURNAL_FILE_COMPRESS(f)),({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 3267, __func__, "Journal effective settings seal=%s compress=%s compress_threshold_bytes=%s"
, yes_no(f->seal), yes_no(JOURNAL_FILE_COMPRESS(f)), format_bytes
(bytes, sizeof(bytes), f->compress_threshold_bytes)) : -abs
(_e); })
3267 format_bytes(bytes, sizeof(bytes), f->compress_threshold_bytes))({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 3267, __func__, "Journal effective settings seal=%s compress=%s compress_threshold_bytes=%s"
, yes_no(f->seal), yes_no(JOURNAL_FILE_COMPRESS(f)), format_bytes
(bytes, sizeof(bytes), f->compress_threshold_bytes)) : -abs
(_e); })
;
3268
3269 if (mmap_cache)
3270 f->mmap = mmap_cache_ref(mmap_cache);
3271 else {
3272 f->mmap = mmap_cache_new();
3273 if (!f->mmap) {
3274 r = -ENOMEM12;
3275 goto fail;
3276 }
3277 }
3278
3279 if (fname) {
3280 f->path = strdup(fname);
3281 if (!f->path) {
3282 r = -ENOMEM12;
3283 goto fail;
3284 }
3285 } else {
3286 assert(fd >= 0)do { if ((__builtin_expect(!!(!(fd >= 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("fd >= 0"), "../src/journal/journal-file.c"
, 3286, __PRETTY_FUNCTION__); } while (0)
;
3287
3288 /* If we don't know the path, fill in something explanatory and vaguely useful */
3289 if (asprintf(&f->path, "/proc/self/%i", fd) < 0) {
3290 r = -ENOMEM12;
3291 goto fail;
3292 }
3293 }
3294
3295 f->chain_cache = ordered_hashmap_new(&uint64_hash_ops)internal_ordered_hashmap_new(&uint64_hash_ops );
3296 if (!f->chain_cache) {
3297 r = -ENOMEM12;
3298 goto fail;
3299 }
3300
3301 if (f->fd < 0) {
3302 /* We pass O_NONBLOCK here, so that in case somebody pointed us to some character device node or FIFO
3303 * or so, we likely fail quickly than block for long. For regular files O_NONBLOCK has no effect, hence
3304 * it doesn't hurt in that case. */
3305
3306 f->fd = open(f->path, f->flags|O_CLOEXEC02000000|O_NONBLOCK04000, f->mode);
3307 if (f->fd < 0) {
3308 r = -errno(*__errno_location ());
3309 goto fail;
3310 }
3311
3312 /* fds we opened here by us should also be closed by us. */
3313 f->close_fd = true1;
3314
3315 r = fd_nonblock(f->fd, false0);
3316 if (r < 0)
3317 goto fail;
3318 }
3319
3320 f->cache_fd = mmap_cache_add_fd(f->mmap, f->fd);
3321 if (!f->cache_fd) {
3322 r = -ENOMEM12;
3323 goto fail;
3324 }
3325
3326 r = journal_file_fstat(f);
3327 if (r < 0)
3328 goto fail;
3329
3330 if (f->last_stat.st_size == 0 && f->writable) {
3331
3332 (void) journal_file_warn_btrfs(f);
3333
3334 /* Let's attach the creation time to the journal file, so that the vacuuming code knows the age of this
3335 * file even if the file might end up corrupted one day... Ideally we'd just use the creation time many
3336 * file systems maintain for each file, but the API to query this is very new, hence let's emulate this
3337 * via extended attributes. If extended attributes are not supported we'll just skip this, and rely
3338 * solely on mtime/atime/ctime of the file. */
3339 (void) fd_setcrtime(f->fd, 0);
3340
3341#if HAVE_GCRYPT1
3342 /* Try to load the FSPRG state, and if we can't, then
3343 * just don't do sealing */
3344 if (f->seal) {
3345 r = journal_file_fss_load(f);
3346 if (r < 0)
3347 f->seal = false0;
3348 }
3349#endif
3350
3351 r = journal_file_init_header(f, template);
3352 if (r < 0)
3353 goto fail;
3354
3355 r = journal_file_fstat(f);
3356 if (r < 0)
3357 goto fail;
3358
3359 newly_created = true1;
3360 }
3361
3362 if (f->last_stat.st_size < (off_t) HEADER_SIZE_MIN(((__builtin_offsetof(Header, n_data)) + 7ULL) & ~7ULL)) {
3363 r = -ENODATA61;
3364 goto fail;
3365 }
3366
3367 r = mmap_cache_get(f->mmap, f->cache_fd, f->prot, CONTEXT_HEADER_OBJECT_TYPE_MAX, true1, 0, PAGE_ALIGN(sizeof(Header))ALIGN_TO((sizeof(Header)), page_size()), &f->last_stat, &h, NULL((void*)0));
3368 if (r < 0)
3369 goto fail;
3370
3371 f->header = h;
3372
3373 if (!newly_created) {
3374 set_clear_with_destructor(deferred_closes, journal_file_close)({ void *_item; while ((_item = set_steal_first(deferred_closes
))) journal_file_close(_item); })
;
3375
3376 r = journal_file_verify_header(f);
3377 if (r < 0)
3378 goto fail;
3379 }
3380
3381#if HAVE_GCRYPT1
3382 if (!newly_created && f->writable) {
3383 r = journal_file_fss_load(f);
3384 if (r < 0)
3385 goto fail;
3386 }
3387#endif
3388
3389 if (f->writable) {
3390 if (metrics) {
3391 journal_default_metrics(metrics, f->fd);
3392 f->metrics = *metrics;
3393 } else if (template)
3394 f->metrics = template->metrics;
3395
3396 r = journal_file_refresh_header(f);
3397 if (r < 0)
3398 goto fail;
3399 }
3400
3401#if HAVE_GCRYPT1
3402 r = journal_file_hmac_setup(f);
3403 if (r < 0)
3404 goto fail;
3405#endif
3406
3407 if (newly_created) {
3408 r = journal_file_setup_field_hash_table(f);
3409 if (r < 0)
3410 goto fail;
3411
3412 r = journal_file_setup_data_hash_table(f);
3413 if (r < 0)
3414 goto fail;
3415
3416#if HAVE_GCRYPT1
3417 r = journal_file_append_first_tag(f);
3418 if (r < 0)
3419 goto fail;
3420#endif
3421 }
3422
3423 if (mmap_cache_got_sigbus(f->mmap, f->cache_fd)) {
3424 r = -EIO5;
3425 goto fail;
3426 }
3427
3428 if (template && template->post_change_timer) {
3429 r = journal_file_enable_post_change_timer(
3430 f,
3431 sd_event_source_get_event(template->post_change_timer),
3432 template->post_change_timer_period);
3433
3434 if (r < 0)
3435 goto fail;
3436 }
3437
3438 /* The file is opened now successfully, thus we take possession of any passed in fd. */
3439 f->close_fd = true1;
3440
3441 *ret = f;
3442 return 0;
3443
3444fail:
3445 if (f->cache_fd && mmap_cache_got_sigbus(f->mmap, f->cache_fd))
3446 r = -EIO5;
3447
3448 (void) journal_file_close(f);
3449
3450 return r;
3451}
3452
3453int journal_file_rotate(JournalFile **f, bool_Bool compress, uint64_t compress_threshold_bytes, bool_Bool seal, Set *deferred_closes) {
3454 _cleanup_free___attribute__((cleanup(freep))) char *p = NULL((void*)0);
3455 size_t l;
3456 JournalFile *old_file, *new_file = NULL((void*)0);
3457 int r;
3458
3459 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 3459
, __PRETTY_FUNCTION__); } while (0)
;
3460 assert(*f)do { if ((__builtin_expect(!!(!(*f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("*f"), "../src/journal/journal-file.c", 3460
, __PRETTY_FUNCTION__); } while (0)
;
3461
3462 old_file = *f;
3463
3464 if (!old_file->writable)
3465 return -EINVAL22;
3466
3467 /* Is this a journal file that was passed to us as fd? If so, we synthesized a path name for it, and we refuse
3468 * rotation, since we don't know the actual path, and couldn't rename the file hence. */
3469 if (path_startswith(old_file->path, "/proc/self/fd"))
3470 return -EINVAL22;
3471
3472 if (!endswith(old_file->path, ".journal"))
3473 return -EINVAL22;
3474
3475 l = strlen(old_file->path);
3476 r = asprintf(&p, "%.*s@" SD_ID128_FORMAT_STR"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" "-%016"PRIx64"l" "x""-%016"PRIx64"l" "x"".journal",
3477 (int) l - 8, old_file->path,
3478 SD_ID128_FORMAT_VAL(old_file->header->seqnum_id)(old_file->header->seqnum_id).bytes[0], (old_file->header
->seqnum_id).bytes[1], (old_file->header->seqnum_id)
.bytes[2], (old_file->header->seqnum_id).bytes[3], (old_file
->header->seqnum_id).bytes[4], (old_file->header->
seqnum_id).bytes[5], (old_file->header->seqnum_id).bytes
[6], (old_file->header->seqnum_id).bytes[7], (old_file->
header->seqnum_id).bytes[8], (old_file->header->seqnum_id
).bytes[9], (old_file->header->seqnum_id).bytes[10], (old_file
->header->seqnum_id).bytes[11], (old_file->header->
seqnum_id).bytes[12], (old_file->header->seqnum_id).bytes
[13], (old_file->header->seqnum_id).bytes[14], (old_file
->header->seqnum_id).bytes[15]
,
3479 le64toh((*f)->header->head_entry_seqnum),
3480 le64toh((*f)->header->head_entry_realtime));
3481 if (r < 0)
3482 return -ENOMEM12;
3483
3484 /* Try to rename the file to the archived version. If the file
3485 * already was deleted, we'll get ENOENT, let's ignore that
3486 * case. */
3487 r = rename(old_file->path, p);
3488 if (r < 0 && errno(*__errno_location ()) != ENOENT2)
3489 return -errno(*__errno_location ());
3490
3491 /* Sync the rename to disk */
3492 (void) fsync_directory_of_file(old_file->fd);
3493
3494 /* Set as archive so offlining commits w/state=STATE_ARCHIVED.
3495 * Previously we would set old_file->header->state to STATE_ARCHIVED directly here,
3496 * but journal_file_set_offline() short-circuits when state != STATE_ONLINE, which
3497 * would result in the rotated journal never getting fsync() called before closing.
3498 * Now we simply queue the archive state by setting an archive bit, leaving the state
3499 * as STATE_ONLINE so proper offlining occurs. */
3500 old_file->archive = true1;
3501
3502 /* Currently, btrfs is not very good with out write patterns
3503 * and fragments heavily. Let's defrag our journal files when
3504 * we archive them */
3505 old_file->defrag_on_close = true1;
3506
3507 r = journal_file_open(-1, old_file->path, old_file->flags, old_file->mode, compress,
3508 compress_threshold_bytes, seal, NULL((void*)0), old_file->mmap, deferred_closes,
3509 old_file, &new_file);
3510
3511 if (deferred_closes &&
3512 set_put(deferred_closes, old_file) >= 0)
3513 (void) journal_file_set_offline(old_file, false0);
3514 else
3515 (void) journal_file_close(old_file);
3516
3517 *f = new_file;
3518 return r;
3519}
3520
3521int journal_file_open_reliably(
3522 const char *fname,
3523 int flags,
3524 mode_t mode,
3525 bool_Bool compress,
3526 uint64_t compress_threshold_bytes,
3527 bool_Bool seal,
3528 JournalMetrics *metrics,
3529 MMapCache *mmap_cache,
3530 Set *deferred_closes,
3531 JournalFile *template,
3532 JournalFile **ret) {
3533
3534 int r;
3535 size_t l;
3536 _cleanup_free___attribute__((cleanup(freep))) char *p = NULL((void*)0);
3537
3538 r = journal_file_open(-1, fname, flags, mode, compress, compress_threshold_bytes, seal, metrics, mmap_cache,
3539 deferred_closes, template, ret);
3540 if (!IN_SET(r,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){-74, -61, -112, -93, -16, -108, -5, -43,
-26})/sizeof(int)]; switch(r) { case -74: case -61: case -112
: case -93: case -16: case -108: case -5: case -43: case -26:
_found = 1; break; default: break; } _found; })
3541 -EBADMSG, /* Corrupted */({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){-74, -61, -112, -93, -16, -108, -5, -43,
-26})/sizeof(int)]; switch(r) { case -74: case -61: case -112
: case -93: case -16: case -108: case -5: case -43: case -26:
_found = 1; break; default: break; } _found; })
3542 -ENODATA, /* Truncated */({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){-74, -61, -112, -93, -16, -108, -5, -43,
-26})/sizeof(int)]; switch(r) { case -74: case -61: case -112
: case -93: case -16: case -108: case -5: case -43: case -26:
_found = 1; break; default: break; } _found; })
3543 -EHOSTDOWN, /* Other machine */({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){-74, -61, -112, -93, -16, -108, -5, -43,
-26})/sizeof(int)]; switch(r) { case -74: case -61: case -112
: case -93: case -16: case -108: case -5: case -43: case -26:
_found = 1; break; default: break; } _found; })
3544 -EPROTONOSUPPORT, /* Incompatible feature */({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){-74, -61, -112, -93, -16, -108, -5, -43,
-26})/sizeof(int)]; switch(r) { case -74: case -61: case -112
: case -93: case -16: case -108: case -5: case -43: case -26:
_found = 1; break; default: break; } _found; })
3545 -EBUSY, /* Unclean shutdown */({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){-74, -61, -112, -93, -16, -108, -5, -43,
-26})/sizeof(int)]; switch(r) { case -74: case -61: case -112
: case -93: case -16: case -108: case -5: case -43: case -26:
_found = 1; break; default: break; } _found; })
3546 -ESHUTDOWN, /* Already archived */({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){-74, -61, -112, -93, -16, -108, -5, -43,
-26})/sizeof(int)]; switch(r) { case -74: case -61: case -112
: case -93: case -16: case -108: case -5: case -43: case -26:
_found = 1; break; default: break; } _found; })
3547 -EIO, /* IO error, including SIGBUS on mmap */({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){-74, -61, -112, -93, -16, -108, -5, -43,
-26})/sizeof(int)]; switch(r) { case -74: case -61: case -112
: case -93: case -16: case -108: case -5: case -43: case -26:
_found = 1; break; default: break; } _found; })
3548 -EIDRM, /* File has been deleted */({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){-74, -61, -112, -93, -16, -108, -5, -43,
-26})/sizeof(int)]; switch(r) { case -74: case -61: case -112
: case -93: case -16: case -108: case -5: case -43: case -26:
_found = 1; break; default: break; } _found; })
3549 -ETXTBSY)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){-74, -61, -112, -93, -16, -108, -5, -43,
-26})/sizeof(int)]; switch(r) { case -74: case -61: case -112
: case -93: case -16: case -108: case -5: case -43: case -26:
_found = 1; break; default: break; } _found; })
) /* File is from the future */
3550 return r;
3551
3552 if ((flags & O_ACCMODE0003) == O_RDONLY00)
3553 return r;
3554
3555 if (!(flags & O_CREAT0100))
3556 return r;
3557
3558 if (!endswith(fname, ".journal"))
3559 return r;
3560
3561 /* The file is corrupted. Rotate it away and try it again (but only once) */
3562
3563 l = strlen(fname);
3564 if (asprintf(&p, "%.*s@%016"PRIx64"l" "x" "-%016"PRIx64"l" "x" ".journal~",
3565 (int) l - 8, fname,
3566 now(CLOCK_REALTIME0),
3567 random_u64()) < 0)
3568 return -ENOMEM12;
3569
3570 if (rename(fname, p) < 0)
3571 return -errno(*__errno_location ());
3572
3573 /* btrfs doesn't cope well with our write pattern and
3574 * fragments heavily. Let's defrag all files we rotate */
3575
3576 (void) chattr_path(p, 0, FS_NOCOW_FL0x00800000);
3577 (void) btrfs_defrag(p);
3578
3579 log_warning_errno(r, "File %s corrupted or uncleanly shut down, renaming and replacing.", fname)({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 3579, __func__, "File %s corrupted or uncleanly shut down, renaming and replacing."
, fname) : -abs(_e); })
;
3580
3581 return journal_file_open(-1, fname, flags, mode, compress, compress_threshold_bytes, seal, metrics, mmap_cache,
3582 deferred_closes, template, ret);
3583}
3584
3585int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint64_t p) {
3586 uint64_t i, n;
3587 uint64_t q, xor_hash = 0;
3588 int r;
3589 EntryItem *items;
3590 dual_timestamp ts;
3591 const sd_id128_t *boot_id;
3592
3593 assert(from)do { if ((__builtin_expect(!!(!(from)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("from"), "../src/journal/journal-file.c"
, 3593, __PRETTY_FUNCTION__); } while (0)
;
3594 assert(to)do { if ((__builtin_expect(!!(!(to)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("to"), "../src/journal/journal-file.c", 3594
, __PRETTY_FUNCTION__); } while (0)
;
3595 assert(o)do { if ((__builtin_expect(!!(!(o)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("o"), "../src/journal/journal-file.c", 3595
, __PRETTY_FUNCTION__); } while (0)
;
3596 assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("p"), "../src/journal/journal-file.c", 3596
, __PRETTY_FUNCTION__); } while (0)
;
3597
3598 if (!to->writable)
3599 return -EPERM1;
3600
3601 ts.monotonic = le64toh(o->entry.monotonic);
3602 ts.realtime = le64toh(o->entry.realtime);
3603 boot_id = &o->entry.boot_id;
3604
3605 n = journal_file_entry_n_items(o);
3606 /* alloca() can't take 0, hence let's allocate at least one */
3607 items = newa(EntryItem, MAX(1u, n))({ do { if ((__builtin_expect(!!(!(!size_multiply_overflow(sizeof
(EntryItem), __extension__ ({ const typeof((1u)) __unique_prefix_A34
= ((1u)); const typeof((n)) __unique_prefix_B35 = ((n)); __unique_prefix_A34
> __unique_prefix_B35 ? __unique_prefix_A34 : __unique_prefix_B35
; })))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("!size_multiply_overflow(sizeof(EntryItem), __extension__ ({ const typeof((1u)) __unique_prefix_A34 = ((1u)); const typeof((n)) __unique_prefix_B35 = ((n)); __unique_prefix_A34 > __unique_prefix_B35 ? __unique_prefix_A34 : __unique_prefix_B35; }))"
), "../src/journal/journal-file.c", 3607, __PRETTY_FUNCTION__
); } while (0); (EntryItem*) __builtin_alloca (sizeof(EntryItem
)*(__extension__ ({ const typeof((1u)) __unique_prefix_A34 = (
(1u)); const typeof((n)) __unique_prefix_B35 = ((n)); __unique_prefix_A34
> __unique_prefix_B35 ? __unique_prefix_A34 : __unique_prefix_B35
; }))); })
;
3608
3609 for (i = 0; i < n; i++) {
3610 uint64_t l, h;
3611 le64_t le_hash;
3612 size_t t;
3613 void *data;
3614 Object *u;
3615
3616 q = le64toh(o->entry.items[i].object_offset);
3617 le_hash = o->entry.items[i].hash;
3618
3619 r = journal_file_move_to_object(from, OBJECT_DATA, q, &o);
3620 if (r < 0)
3621 return r;
3622
3623 if (le_hash != o->data.hash)
3624 return -EBADMSG74;
3625
3626 l = le64toh(o->object.size) - offsetof(Object, data.payload)__builtin_offsetof(Object, data.payload);
3627 t = (size_t) l;
3628
3629 /* We hit the limit on 32bit machines */
3630 if ((uint64_t) t != l)
3631 return -E2BIG7;
3632
3633 if (o->object.flags & OBJECT_COMPRESSION_MASK(OBJECT_COMPRESSED_XZ | OBJECT_COMPRESSED_LZ4)) {
3634#if HAVE_XZ1 || HAVE_LZ41
3635 size_t rsize = 0;
3636
3637 r = decompress_blob(o->object.flags & OBJECT_COMPRESSION_MASK(OBJECT_COMPRESSED_XZ | OBJECT_COMPRESSED_LZ4),
3638 o->data.payload, l, &from->compress_buffer, &from->compress_buffer_size, &rsize, 0);
3639 if (r < 0)
3640 return r;
3641
3642 data = from->compress_buffer;
3643 l = rsize;
3644#else
3645 return -EPROTONOSUPPORT93;
3646#endif
3647 } else
3648 data = o->data.payload;
3649
3650 r = journal_file_append_data(to, data, l, &u, &h);
3651 if (r < 0)
3652 return r;
3653
3654 xor_hash ^= le64toh(u->data.hash);
3655 items[i].object_offset = htole64(h);
3656 items[i].hash = u->data.hash;
3657
3658 r = journal_file_move_to_object(from, OBJECT_ENTRY, p, &o);
3659 if (r < 0)
3660 return r;
3661 }
3662
3663 r = journal_file_append_entry_internal(to, &ts, boot_id, xor_hash, items, n,
3664 NULL((void*)0), NULL((void*)0), NULL((void*)0));
3665
3666 if (mmap_cache_got_sigbus(to->mmap, to->cache_fd))
3667 return -EIO5;
3668
3669 return r;
3670}
3671
3672void journal_reset_metrics(JournalMetrics *m) {
3673 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/journal/journal-file.c", 3673
, __PRETTY_FUNCTION__); } while (0)
;
3674
3675 /* Set everything to "pick automatic values". */
3676
3677 *m = (JournalMetrics) {
3678 .min_use = (uint64_t) -1,
3679 .max_use = (uint64_t) -1,
3680 .min_size = (uint64_t) -1,
3681 .max_size = (uint64_t) -1,
3682 .keep_free = (uint64_t) -1,
3683 .n_max_files = (uint64_t) -1,
3684 };
3685}
3686
3687void journal_default_metrics(JournalMetrics *m, int fd) {
3688 char a[FORMAT_BYTES_MAX8], b[FORMAT_BYTES_MAX8], c[FORMAT_BYTES_MAX8], d[FORMAT_BYTES_MAX8], e[FORMAT_BYTES_MAX8];
3689 struct statvfs ss;
3690 uint64_t fs_size;
3691
3692 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/journal/journal-file.c", 3692
, __PRETTY_FUNCTION__); } while (0)
;
3693 assert(fd >= 0)do { if ((__builtin_expect(!!(!(fd >= 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("fd >= 0"), "../src/journal/journal-file.c"
, 3693, __PRETTY_FUNCTION__); } while (0)
;
3694
3695 if (fstatvfs(fd, &ss) >= 0)
3696 fs_size = ss.f_frsize * ss.f_blocks;
3697 else {
3698 log_debug_errno(errno, "Failed to determine disk size: %m")({ int _level = ((7)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/journal/journal-file.c", 3698, __func__
, "Failed to determine disk size: %m") : -abs(_e); })
;
3699 fs_size = 0;
3700 }
3701
3702 if (m->max_use == (uint64_t) -1) {
3703
3704 if (fs_size > 0) {
3705 m->max_use = PAGE_ALIGN(fs_size / 10)ALIGN_TO((fs_size / 10), page_size()); /* 10% of file system size */
3706
3707 if (m->max_use > DEFAULT_MAX_USE_UPPER(4ULL*1024ULL*1024ULL*1024ULL))
3708 m->max_use = DEFAULT_MAX_USE_UPPER(4ULL*1024ULL*1024ULL*1024ULL);
3709
3710 if (m->max_use < DEFAULT_MAX_USE_LOWER(1ULL*1024ULL*1024ULL))
3711 m->max_use = DEFAULT_MAX_USE_LOWER(1ULL*1024ULL*1024ULL);
3712 } else
3713 m->max_use = DEFAULT_MAX_USE_LOWER(1ULL*1024ULL*1024ULL);
3714 } else {
3715 m->max_use = PAGE_ALIGN(m->max_use)ALIGN_TO((m->max_use), page_size());
3716
3717 if (m->max_use != 0 && m->max_use < JOURNAL_FILE_SIZE_MIN(512ULL*1024ULL)*2)
3718 m->max_use = JOURNAL_FILE_SIZE_MIN(512ULL*1024ULL)*2;
3719 }
3720
3721 if (m->min_use == (uint64_t) -1)
3722 m->min_use = DEFAULT_MIN_USE(1ULL*1024ULL*1024ULL);
3723
3724 if (m->min_use > m->max_use)
3725 m->min_use = m->max_use;
3726
3727 if (m->max_size == (uint64_t) -1) {
3728 m->max_size = PAGE_ALIGN(m->max_use / 8)ALIGN_TO((m->max_use / 8), page_size()); /* 8 chunks */
3729
3730 if (m->max_size > DEFAULT_MAX_SIZE_UPPER(128ULL*1024ULL*1024ULL))
3731 m->max_size = DEFAULT_MAX_SIZE_UPPER(128ULL*1024ULL*1024ULL);
3732 } else
3733 m->max_size = PAGE_ALIGN(m->max_size)ALIGN_TO((m->max_size), page_size());
3734
3735 if (m->max_size != 0) {
3736 if (m->max_size < JOURNAL_FILE_SIZE_MIN(512ULL*1024ULL))
3737 m->max_size = JOURNAL_FILE_SIZE_MIN(512ULL*1024ULL);
3738
3739 if (m->max_use != 0 && m->max_size*2 > m->max_use)
3740 m->max_use = m->max_size*2;
3741 }
3742
3743 if (m->min_size == (uint64_t) -1)
3744 m->min_size = JOURNAL_FILE_SIZE_MIN(512ULL*1024ULL);
3745 else {
3746 m->min_size = PAGE_ALIGN(m->min_size)ALIGN_TO((m->min_size), page_size());
3747
3748 if (m->min_size < JOURNAL_FILE_SIZE_MIN(512ULL*1024ULL))
3749 m->min_size = JOURNAL_FILE_SIZE_MIN(512ULL*1024ULL);
3750
3751 if (m->max_size != 0 && m->min_size > m->max_size)
3752 m->max_size = m->min_size;
3753 }
3754
3755 if (m->keep_free == (uint64_t) -1) {
3756
3757 if (fs_size > 0) {
3758 m->keep_free = PAGE_ALIGN(fs_size * 3 / 20)ALIGN_TO((fs_size * 3 / 20), page_size()); /* 15% of file system size */
3759
3760 if (m->keep_free > DEFAULT_KEEP_FREE_UPPER(4ULL*1024ULL*1024ULL*1024ULL))
3761 m->keep_free = DEFAULT_KEEP_FREE_UPPER(4ULL*1024ULL*1024ULL*1024ULL);
3762
3763 } else
3764 m->keep_free = DEFAULT_KEEP_FREE(1024ULL*1024ULL);
3765 }
3766
3767 if (m->n_max_files == (uint64_t) -1)
3768 m->n_max_files = DEFAULT_N_MAX_FILES(100);
3769
3770 log_debug("Fixed min_use=%s max_use=%s max_size=%s min_size=%s keep_free=%s n_max_files=%" PRIu64,({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 3776, __func__, "Fixed min_use=%s max_use=%s max_size=%s min_size=%s keep_free=%s n_max_files=%"
"l" "u", format_bytes(a, sizeof(a), m->min_use), format_bytes
(b, sizeof(b), m->max_use), format_bytes(c, sizeof(c), m->
max_size), format_bytes(d, sizeof(d), m->min_size), format_bytes
(e, sizeof(e), m->keep_free), m->n_max_files) : -abs(_e
); })
3771 format_bytes(a, sizeof(a), m->min_use),({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 3776, __func__, "Fixed min_use=%s max_use=%s max_size=%s min_size=%s keep_free=%s n_max_files=%"
"l" "u", format_bytes(a, sizeof(a), m->min_use), format_bytes
(b, sizeof(b), m->max_use), format_bytes(c, sizeof(c), m->
max_size), format_bytes(d, sizeof(d), m->min_size), format_bytes
(e, sizeof(e), m->keep_free), m->n_max_files) : -abs(_e
); })
3772 format_bytes(b, sizeof(b), m->max_use),({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 3776, __func__, "Fixed min_use=%s max_use=%s max_size=%s min_size=%s keep_free=%s n_max_files=%"
"l" "u", format_bytes(a, sizeof(a), m->min_use), format_bytes
(b, sizeof(b), m->max_use), format_bytes(c, sizeof(c), m->
max_size), format_bytes(d, sizeof(d), m->min_size), format_bytes
(e, sizeof(e), m->keep_free), m->n_max_files) : -abs(_e
); })
3773 format_bytes(c, sizeof(c), m->max_size),({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 3776, __func__, "Fixed min_use=%s max_use=%s max_size=%s min_size=%s keep_free=%s n_max_files=%"
"l" "u", format_bytes(a, sizeof(a), m->min_use), format_bytes
(b, sizeof(b), m->max_use), format_bytes(c, sizeof(c), m->
max_size), format_bytes(d, sizeof(d), m->min_size), format_bytes
(e, sizeof(e), m->keep_free), m->n_max_files) : -abs(_e
); })
3774 format_bytes(d, sizeof(d), m->min_size),({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 3776, __func__, "Fixed min_use=%s max_use=%s max_size=%s min_size=%s keep_free=%s n_max_files=%"
"l" "u", format_bytes(a, sizeof(a), m->min_use), format_bytes
(b, sizeof(b), m->max_use), format_bytes(c, sizeof(c), m->
max_size), format_bytes(d, sizeof(d), m->min_size), format_bytes
(e, sizeof(e), m->keep_free), m->n_max_files) : -abs(_e
); })
3775 format_bytes(e, sizeof(e), m->keep_free),({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 3776, __func__, "Fixed min_use=%s max_use=%s max_size=%s min_size=%s keep_free=%s n_max_files=%"
"l" "u", format_bytes(a, sizeof(a), m->min_use), format_bytes
(b, sizeof(b), m->max_use), format_bytes(c, sizeof(c), m->
max_size), format_bytes(d, sizeof(d), m->min_size), format_bytes
(e, sizeof(e), m->keep_free), m->n_max_files) : -abs(_e
); })
3776 m->n_max_files)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 3776, __func__, "Fixed min_use=%s max_use=%s max_size=%s min_size=%s keep_free=%s n_max_files=%"
"l" "u", format_bytes(a, sizeof(a), m->min_use), format_bytes
(b, sizeof(b), m->max_use), format_bytes(c, sizeof(c), m->
max_size), format_bytes(d, sizeof(d), m->min_size), format_bytes
(e, sizeof(e), m->keep_free), m->n_max_files) : -abs(_e
); })
;
3777}
3778
3779int journal_file_get_cutoff_realtime_usec(JournalFile *f, usec_t *from, usec_t *to) {
3780 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 3780
, __PRETTY_FUNCTION__); } while (0)
;
3781 assert(f->header)do { if ((__builtin_expect(!!(!(f->header)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f->header"), "../src/journal/journal-file.c"
, 3781, __PRETTY_FUNCTION__); } while (0)
;
3782 assert(from || to)do { if ((__builtin_expect(!!(!(from || to)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("from || to"), "../src/journal/journal-file.c"
, 3782, __PRETTY_FUNCTION__); } while (0)
;
3783
3784 if (from) {
3785 if (f->header->head_entry_realtime == 0)
3786 return -ENOENT2;
3787
3788 *from = le64toh(f->header->head_entry_realtime);
3789 }
3790
3791 if (to) {
3792 if (f->header->tail_entry_realtime == 0)
3793 return -ENOENT2;
3794
3795 *to = le64toh(f->header->tail_entry_realtime);
3796 }
3797
3798 return 1;
3799}
3800
3801int journal_file_get_cutoff_monotonic_usec(JournalFile *f, sd_id128_t boot_id, usec_t *from, usec_t *to) {
3802 Object *o;
3803 uint64_t p;
3804 int r;
3805
3806 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 3806
, __PRETTY_FUNCTION__); } while (0)
;
3807 assert(from || to)do { if ((__builtin_expect(!!(!(from || to)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("from || to"), "../src/journal/journal-file.c"
, 3807, __PRETTY_FUNCTION__); } while (0)
;
3808
3809 r = find_data_object_by_boot_id(f, boot_id, &o, &p);
3810 if (r <= 0)
3811 return r;
3812
3813 if (le64toh(o->data.n_entries) <= 0)
3814 return 0;
3815
3816 if (from) {
3817 r = journal_file_move_to_object(f, OBJECT_ENTRY, le64toh(o->data.entry_offset), &o);
3818 if (r < 0)
3819 return r;
3820
3821 *from = le64toh(o->entry.monotonic);
3822 }
3823
3824 if (to) {
3825 r = journal_file_move_to_object(f, OBJECT_DATA, p, &o);
3826 if (r < 0)
3827 return r;
3828
3829 r = generic_array_get_plus_one(f,
3830 le64toh(o->data.entry_offset),
3831 le64toh(o->data.entry_array_offset),
3832 le64toh(o->data.n_entries)-1,
3833 &o, NULL((void*)0));
3834 if (r <= 0)
3835 return r;
3836
3837 *to = le64toh(o->entry.monotonic);
3838 }
3839
3840 return 1;
3841}
3842
3843bool_Bool journal_file_rotate_suggested(JournalFile *f, usec_t max_file_usec) {
3844 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/journal/journal-file.c", 3844
, __PRETTY_FUNCTION__); } while (0)
;
3845 assert(f->header)do { if ((__builtin_expect(!!(!(f->header)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f->header"), "../src/journal/journal-file.c"
, 3845, __PRETTY_FUNCTION__); } while (0)
;
3846
3847 /* If we gained new header fields we gained new features,
3848 * hence suggest a rotation */
3849 if (le64toh(f->header->header_size) < sizeof(Header)) {
3850 log_debug("%s uses an outdated header, suggesting rotation.", f->path)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 3850, __func__, "%s uses an outdated header, suggesting rotation."
, f->path) : -abs(_e); })
;
3851 return true1;
3852 }
3853
3854 /* Let's check if the hash tables grew over a certain fill
3855 * level (75%, borrowing this value from Java's hash table
3856 * implementation), and if so suggest a rotation. To calculate
3857 * the fill level we need the n_data field, which only exists
3858 * in newer versions. */
3859
3860 if (JOURNAL_HEADER_CONTAINS(f->header, n_data)(le64toh((f->header)->header_size) >= __builtin_offsetof
(Header, n_data) + sizeof((f->header)->n_data))
)
3861 if (le64toh(f->header->n_data) * 4ULL > (le64toh(f->header->data_hash_table_size) / sizeof(HashItem)) * 3ULL) {
3862 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.",({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 3868, __func__, "Data hash table of %s has a fill level at %.1f (%"
"l" "u"" of %""l" "u"" items, %llu file size, %""l" "u"" 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))), le64toh(f->header->n_data), le64toh
(f->header->data_hash_table_size) / sizeof(HashItem), (
unsigned long long) f->last_stat.st_size, f->last_stat.
st_size / le64toh(f->header->n_data)) : -abs(_e); })
3863 f->path,({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 3868, __func__, "Data hash table of %s has a fill level at %.1f (%"
"l" "u"" of %""l" "u"" items, %llu file size, %""l" "u"" 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))), le64toh(f->header->n_data), le64toh
(f->header->data_hash_table_size) / sizeof(HashItem), (
unsigned long long) f->last_stat.st_size, f->last_stat.
st_size / le64toh(f->header->n_data)) : -abs(_e); })
3864 100.0 * (double) le64toh(f->header->n_data) / ((double) (le64toh(f->header->data_hash_table_size) / sizeof(HashItem))),({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 3868, __func__, "Data hash table of %s has a fill level at %.1f (%"
"l" "u"" of %""l" "u"" items, %llu file size, %""l" "u"" 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))), le64toh(f->header->n_data), le64toh
(f->header->data_hash_table_size) / sizeof(HashItem), (
unsigned long long) f->last_stat.st_size, f->last_stat.
st_size / le64toh(f->header->n_data)) : -abs(_e); })
3865 le64toh(f->header->n_data),({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 3868, __func__, "Data hash table of %s has a fill level at %.1f (%"
"l" "u"" of %""l" "u"" items, %llu file size, %""l" "u"" 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))), le64toh(f->header->n_data), le64toh
(f->header->data_hash_table_size) / sizeof(HashItem), (
unsigned long long) f->last_stat.st_size, f->last_stat.
st_size / le64toh(f->header->n_data)) : -abs(_e); })
3866 le64toh(f->header->data_hash_table_size) / sizeof(HashItem),({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 3868, __func__, "Data hash table of %s has a fill level at %.1f (%"
"l" "u"" of %""l" "u"" items, %llu file size, %""l" "u"" 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))), le64toh(f->header->n_data), le64toh
(f->header->data_hash_table_size) / sizeof(HashItem), (
unsigned long long) f->last_stat.st_size, f->last_stat.
st_size / le64toh(f->header->n_data)) : -abs(_e); })
3867 (unsigned long long) f->last_stat.st_size,({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 3868, __func__, "Data hash table of %s has a fill level at %.1f (%"
"l" "u"" of %""l" "u"" items, %llu file size, %""l" "u"" 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))), le64toh(f->header->n_data), le64toh
(f->header->data_hash_table_size) / sizeof(HashItem), (
unsigned long long) f->last_stat.st_size, f->last_stat.
st_size / le64toh(f->header->n_data)) : -abs(_e); })
3868 f->last_stat.st_size / le64toh(f->header->n_data))({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 3868, __func__, "Data hash table of %s has a fill level at %.1f (%"
"l" "u"" of %""l" "u"" items, %llu file size, %""l" "u"" 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))), le64toh(f->header->n_data), le64toh
(f->header->data_hash_table_size) / sizeof(HashItem), (
unsigned long long) f->last_stat.st_size, f->last_stat.
st_size / le64toh(f->header->n_data)) : -abs(_e); })
;
3869 return true1;
3870 }
3871
3872 if (JOURNAL_HEADER_CONTAINS(f->header, n_fields)(le64toh((f->header)->header_size) >= __builtin_offsetof
(Header, n_fields) + sizeof((f->header)->n_fields))
)
3873 if (le64toh(f->header->n_fields) * 4ULL > (le64toh(f->header->field_hash_table_size) / sizeof(HashItem)) * 3ULL) {
3874 log_debug("Field hash table of %s has a fill level at %.1f (%"PRIu64" of %"PRIu64" items), suggesting rotation.",({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 3878, __func__, "Field hash table of %s has a fill level at %.1f (%"
"l" "u"" of %""l" "u"" items), suggesting rotation.", f->path
, 100.0 * (double) le64toh(f->header->n_fields) / ((double
) (le64toh(f->header->field_hash_table_size) / sizeof(HashItem
))), le64toh(f->header->n_fields), le64toh(f->header
->field_hash_table_size) / sizeof(HashItem)) : -abs(_e); }
)
3875 f->path,({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 3878, __func__, "Field hash table of %s has a fill level at %.1f (%"
"l" "u"" of %""l" "u"" items), suggesting rotation.", f->path
, 100.0 * (double) le64toh(f->header->n_fields) / ((double
) (le64toh(f->header->field_hash_table_size) / sizeof(HashItem
))), le64toh(f->header->n_fields), le64toh(f->header
->field_hash_table_size) / sizeof(HashItem)) : -abs(_e); }
)
3876 100.0 * (double) le64toh(f->header->n_fields) / ((double) (le64toh(f->header->field_hash_table_size) / sizeof(HashItem))),({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 3878, __func__, "Field hash table of %s has a fill level at %.1f (%"
"l" "u"" of %""l" "u"" items), suggesting rotation.", f->path
, 100.0 * (double) le64toh(f->header->n_fields) / ((double
) (le64toh(f->header->field_hash_table_size) / sizeof(HashItem
))), le64toh(f->header->n_fields), le64toh(f->header
->field_hash_table_size) / sizeof(HashItem)) : -abs(_e); }
)
3877 le64toh(f->header->n_fields),({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 3878, __func__, "Field hash table of %s has a fill level at %.1f (%"
"l" "u"" of %""l" "u"" items), suggesting rotation.", f->path
, 100.0 * (double) le64toh(f->header->n_fields) / ((double
) (le64toh(f->header->field_hash_table_size) / sizeof(HashItem
))), le64toh(f->header->n_fields), le64toh(f->header
->field_hash_table_size) / sizeof(HashItem)) : -abs(_e); }
)
3878 le64toh(f->header->field_hash_table_size) / sizeof(HashItem))({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal/journal-file.c", 3878, __func__, "Field hash table of %s has a fill level at %.1f (%"
"l" "u"" of %""l" "u"" items), suggesting rotation.", f->path
, 100.0 * (double) le64toh(f->header->n_fields) / ((double
) (le64toh(f->header->field_hash_table_size) / sizeof(HashItem
))), le64toh(f->header->n_fields), le64toh(f->header
->field_hash_table_size) / sizeof(HashItem)) : -abs(_e); }
)
;
3879 return true1;
3880 }
3881
3882 /* Are the data objects properly indexed by field objects? */
3883 if (JOURNAL_HEADER_CONTAINS(f->header, n_data)(le64toh((f->header)->header_size) >= __builtin_offsetof
(Header, n_data) + sizeof((f->header)->n_data))
&&
3884 JOURNAL_HEADER_CONTAINS(f->header, n_fields)(le64toh((f->header)->header_size) >= __builtin_offsetof
(Header, n_fields) + sizeof((f->header)->n_fields))
&&
3885 le64toh(f->header->n_data) > 0 &&
3886 le64toh(f->header->n_fields) == 0)
3887 return true1;
3888
3889 if (max_file_usec > 0) {
3890 usec_t t, h;
3891
3892 h = le64toh(f->header->head_entry_realtime);
3893 t = now(CLOCK_REALTIME0);
3894
3895 if (h > 0 && t > h + max_file_usec)
3896 return true1;
3897 }
3898
3899 return false0;
3900}