1 /* SPDX-License-Identifier: LGPL-2.1+ */
13 #include "journal-def.h"
15 #include "mmap-cache.h"
17 #include "sparse-endian.h"
19 typedef struct JournalMetrics
{
20 /* For all these: -1 means "pick automatically", and 0 means "no limit enforced" */
21 uint64_t max_size
; /* how large journal files grow at max */
22 uint64_t min_size
; /* how large journal files grow at least */
23 uint64_t max_use
; /* how much disk space to use in total at max, keep_free permitting */
24 uint64_t min_use
; /* how much disk space to use in total at least, even if keep_free says not to */
25 uint64_t keep_free
; /* how much to keep free on disk */
26 uint64_t n_max_files
; /* how many files to keep around at max */
29 typedef enum direction
{
34 typedef enum LocationType
{
35 /* The first and last entries, resp. */
39 /* We already read the entry we currently point to, and the
40 * next one to read should probably not be this one again. */
43 /* We should seek to the precise location specified, and
44 * return it, as we haven't read it yet. */
48 typedef enum OfflineState
{
53 OFFLINE_AGAIN_FROM_SYNCING
,
54 OFFLINE_AGAIN_FROM_OFFLINING
,
58 typedef struct JournalFile
{
60 MMapFileDescriptor
*cache_fd
;
70 bool defrag_on_close
:1;
74 direction_t last_direction
;
75 LocationType location_type
;
76 uint64_t last_n_entries
;
79 struct stat last_stat
;
80 usec_t last_stat_usec
;
83 HashItem
*data_hash_table
;
84 HashItem
*field_hash_table
;
86 uint64_t current_offset
;
87 uint64_t current_seqnum
;
88 uint64_t current_realtime
;
89 uint64_t current_monotonic
;
90 sd_id128_t current_boot_id
;
91 uint64_t current_xor_hash
;
93 JournalMetrics metrics
;
96 sd_event_source
*post_change_timer
;
97 usec_t post_change_timer_period
;
99 OrderedHashmap
*chain_cache
;
101 pthread_t offline_thread
;
102 volatile OfflineState offline_state
;
104 unsigned last_seen_generation
;
106 uint64_t compress_threshold_bytes
;
107 #if HAVE_XZ || HAVE_LZ4
108 void *compress_buffer
;
109 size_t compress_buffer_size
;
117 size_t fss_file_size
;
119 uint64_t fss_start_usec
;
120 uint64_t fss_interval_usec
;
123 size_t fsprg_state_size
;
126 size_t fsprg_seed_size
;
130 int journal_file_open(
136 uint64_t compress_threshold_bytes
,
138 JournalMetrics
*metrics
,
139 MMapCache
*mmap_cache
,
140 Set
*deferred_closes
,
141 JournalFile
*template,
144 int journal_file_set_offline(JournalFile
*f
, bool wait
);
145 bool journal_file_is_offlining(JournalFile
*f
);
146 JournalFile
* journal_file_close(JournalFile
*j
);
148 int journal_file_open_reliably(
153 uint64_t compress_threshold_bytes
,
155 JournalMetrics
*metrics
,
156 MMapCache
*mmap_cache
,
157 Set
*deferred_closes
,
158 JournalFile
*template,
161 #define ALIGN64(x) (((x) + 7ULL) & ~7ULL)
162 #define VALID64(x) (((x) & 7ULL) == 0ULL)
164 /* Use six characters to cover the offsets common in smallish journal
165 * files without adding too many zeros. */
166 #define OFSfmt "%06"PRIx64
168 static inline bool VALID_REALTIME(uint64_t u
) {
169 /* This considers timestamps until the year 3112 valid. That should be plenty room... */
170 return u
> 0 && u
< (1ULL << 55);
173 static inline bool VALID_MONOTONIC(uint64_t u
) {
174 /* This considers timestamps until 1142 years of runtime valid. */
175 return u
< (1ULL << 55);
178 static inline bool VALID_EPOCH(uint64_t u
) {
179 /* This allows changing the key for 1142 years, every usec. */
180 return u
< (1ULL << 55);
183 #define JOURNAL_HEADER_CONTAINS(h, field) \
184 (le64toh((h)->header_size) >= offsetof(Header, field) + sizeof((h)->field))
186 #define JOURNAL_HEADER_SEALED(h) \
187 (!!(le32toh((h)->compatible_flags) & HEADER_COMPATIBLE_SEALED))
189 #define JOURNAL_HEADER_COMPRESSED_XZ(h) \
190 (!!(le32toh((h)->incompatible_flags) & HEADER_INCOMPATIBLE_COMPRESSED_XZ))
192 #define JOURNAL_HEADER_COMPRESSED_LZ4(h) \
193 (!!(le32toh((h)->incompatible_flags) & HEADER_INCOMPATIBLE_COMPRESSED_LZ4))
195 int journal_file_move_to_object(JournalFile
*f
, ObjectType type
, uint64_t offset
, Object
**ret
);
197 uint64_t journal_file_entry_n_items(Object
*o
) _pure_
;
198 uint64_t journal_file_entry_array_n_items(Object
*o
) _pure_
;
199 uint64_t journal_file_hash_table_n_items(Object
*o
) _pure_
;
201 int journal_file_append_object(JournalFile
*f
, ObjectType type
, uint64_t size
, Object
**ret
, uint64_t *offset
);
202 int journal_file_append_entry(
204 const dual_timestamp
*ts
,
205 const sd_id128_t
*boot_id
,
206 const struct iovec iovec
[], unsigned n_iovec
,
211 int journal_file_find_data_object(JournalFile
*f
, const void *data
, uint64_t size
, Object
**ret
, uint64_t *offset
);
212 int journal_file_find_data_object_with_hash(JournalFile
*f
, const void *data
, uint64_t size
, uint64_t hash
, Object
**ret
, uint64_t *offset
);
214 int journal_file_find_field_object(JournalFile
*f
, const void *field
, uint64_t size
, Object
**ret
, uint64_t *offset
);
215 int journal_file_find_field_object_with_hash(JournalFile
*f
, const void *field
, uint64_t size
, uint64_t hash
, Object
**ret
, uint64_t *offset
);
217 void journal_file_reset_location(JournalFile
*f
);
218 void journal_file_save_location(JournalFile
*f
, Object
*o
, uint64_t offset
);
219 int journal_file_compare_locations(JournalFile
*af
, JournalFile
*bf
);
220 int journal_file_next_entry(JournalFile
*f
, uint64_t p
, direction_t direction
, Object
**ret
, uint64_t *offset
);
222 int journal_file_next_entry_for_data(JournalFile
*f
, Object
*o
, uint64_t p
, uint64_t data_offset
, direction_t direction
, Object
**ret
, uint64_t *offset
);
224 int journal_file_move_to_entry_by_seqnum(JournalFile
*f
, uint64_t seqnum
, direction_t direction
, Object
**ret
, uint64_t *offset
);
225 int journal_file_move_to_entry_by_realtime(JournalFile
*f
, uint64_t realtime
, direction_t direction
, Object
**ret
, uint64_t *offset
);
226 int journal_file_move_to_entry_by_monotonic(JournalFile
*f
, sd_id128_t boot_id
, uint64_t monotonic
, direction_t direction
, Object
**ret
, uint64_t *offset
);
228 int journal_file_move_to_entry_by_offset_for_data(JournalFile
*f
, uint64_t data_offset
, uint64_t p
, direction_t direction
, Object
**ret
, uint64_t *offset
);
229 int journal_file_move_to_entry_by_seqnum_for_data(JournalFile
*f
, uint64_t data_offset
, uint64_t seqnum
, direction_t direction
, Object
**ret
, uint64_t *offset
);
230 int journal_file_move_to_entry_by_realtime_for_data(JournalFile
*f
, uint64_t data_offset
, uint64_t realtime
, direction_t direction
, Object
**ret
, uint64_t *offset
);
231 int journal_file_move_to_entry_by_monotonic_for_data(JournalFile
*f
, uint64_t data_offset
, sd_id128_t boot_id
, uint64_t monotonic
, direction_t direction
, Object
**ret
, uint64_t *offset
);
233 int journal_file_copy_entry(JournalFile
*from
, JournalFile
*to
, Object
*o
, uint64_t p
);
235 void journal_file_dump(JournalFile
*f
);
236 void journal_file_print_header(JournalFile
*f
);
238 int journal_file_archive(JournalFile
*f
);
239 JournalFile
* journal_initiate_close(JournalFile
*f
, Set
*deferred_closes
);
240 int journal_file_rotate(JournalFile
**f
, bool compress
, uint64_t compress_threshold_bytes
, bool seal
, Set
*deferred_closes
);
242 int journal_file_dispose(int dir_fd
, const char *fname
);
244 void journal_file_post_change(JournalFile
*f
);
245 int journal_file_enable_post_change_timer(JournalFile
*f
, sd_event
*e
, usec_t t
);
247 void journal_reset_metrics(JournalMetrics
*m
);
248 void journal_default_metrics(JournalMetrics
*m
, int fd
);
250 int journal_file_get_cutoff_realtime_usec(JournalFile
*f
, usec_t
*from
, usec_t
*to
);
251 int journal_file_get_cutoff_monotonic_usec(JournalFile
*f
, sd_id128_t boot
, usec_t
*from
, usec_t
*to
);
253 bool journal_file_rotate_suggested(JournalFile
*f
, usec_t max_file_usec
);
255 int journal_file_map_data_hash_table(JournalFile
*f
);
256 int journal_file_map_field_hash_table(JournalFile
*f
);
258 static inline bool JOURNAL_FILE_COMPRESS(JournalFile
*f
) {
260 return f
->compress_xz
|| f
->compress_lz4
;