]>
Commit | Line | Data |
---|---|---|
53e1b683 | 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ |
c2f1db8f | 2 | #pragma once |
87d2c1ff | 3 | |
87d2c1ff | 4 | #include <inttypes.h> |
f2dc22b4 | 5 | #include <sys/uio.h> |
87d2c1ff | 6 | |
349cc4a5 | 7 | #if HAVE_GCRYPT |
a03d4359 | 8 | # include <gcrypt.h> |
7560fffc LP |
9 | #endif |
10 | ||
a03d4359 | 11 | #include "sd-event.h" |
fa6ac760 | 12 | #include "sd-id128.h" |
81527be1 | 13 | |
71d35b6b | 14 | #include "hashmap.h" |
87d2c1ff | 15 | #include "journal-def.h" |
16e9f408 | 16 | #include "mmap-cache.h" |
71d35b6b | 17 | #include "sparse-endian.h" |
ca78ad1d | 18 | #include "time-util.h" |
de190aef | 19 | |
bc85bfee | 20 | typedef struct JournalMetrics { |
8580d1f7 LP |
21 | /* For all these: -1 means "pick automatically", and 0 means "no limit enforced" */ |
22 | uint64_t max_size; /* how large journal files grow at max */ | |
23 | uint64_t min_size; /* how large journal files grow at least */ | |
24 | uint64_t max_use; /* how much disk space to use in total at max, keep_free permitting */ | |
25 | uint64_t min_use; /* how much disk space to use in total at least, even if keep_free says not to */ | |
26 | uint64_t keep_free; /* how much to keep free on disk */ | |
27 | uint64_t n_max_files; /* how many files to keep around at max */ | |
bc85bfee LP |
28 | } JournalMetrics; |
29 | ||
87011c25 ZJS |
30 | typedef enum direction { |
31 | DIRECTION_UP, | |
32 | DIRECTION_DOWN | |
33 | } direction_t; | |
34 | ||
99cc7653 MS |
35 | typedef enum LocationType { |
36 | /* The first and last entries, resp. */ | |
37 | LOCATION_HEAD, | |
38 | LOCATION_TAIL, | |
39 | ||
40 | /* We already read the entry we currently point to, and the | |
41 | * next one to read should probably not be this one again. */ | |
42 | LOCATION_DISCRETE, | |
43 | ||
44 | /* We should seek to the precise location specified, and | |
45 | * return it, as we haven't read it yet. */ | |
46 | LOCATION_SEEK | |
47 | } LocationType; | |
48 | ||
ac2e41f5 VC |
49 | typedef enum OfflineState { |
50 | OFFLINE_JOINED, | |
51 | OFFLINE_SYNCING, | |
52 | OFFLINE_OFFLINING, | |
53 | OFFLINE_CANCEL, | |
54 | OFFLINE_AGAIN_FROM_SYNCING, | |
55 | OFFLINE_AGAIN_FROM_OFFLINING, | |
56 | OFFLINE_DONE | |
57 | } OfflineState; | |
58 | ||
f4b47811 LP |
59 | typedef struct JournalFile { |
60 | int fd; | |
be7cdd8e | 61 | MMapFileDescriptor *cache_fd; |
87011c25 | 62 | |
0ac38b70 | 63 | mode_t mode; |
7560fffc | 64 | |
0ac38b70 | 65 | int flags; |
f4b47811 | 66 | int prot; |
b8e891e6 | 67 | bool writable:1; |
d89c8fdf ZJS |
68 | bool compress_xz:1; |
69 | bool compress_lz4:1; | |
8653185a | 70 | bool compress_zstd:1; |
b8e891e6 | 71 | bool seal:1; |
f27a3864 | 72 | bool defrag_on_close:1; |
5d1ce257 | 73 | bool close_fd:1; |
8eb85171 | 74 | bool archive:1; |
4ce534f4 | 75 | bool keyed_hash:1; |
7560fffc | 76 | |
87011c25 | 77 | direction_t last_direction; |
6573ef05 | 78 | LocationType location_type; |
6e693b42 | 79 | uint64_t last_n_entries; |
87011c25 ZJS |
80 | |
81 | char *path; | |
82 | struct stat last_stat; | |
2678031a | 83 | usec_t last_stat_usec; |
87011c25 | 84 | |
f4b47811 | 85 | Header *header; |
de190aef LP |
86 | HashItem *data_hash_table; |
87 | HashItem *field_hash_table; | |
f4b47811 | 88 | |
f4b47811 | 89 | uint64_t current_offset; |
6573ef05 MS |
90 | uint64_t current_seqnum; |
91 | uint64_t current_realtime; | |
92 | uint64_t current_monotonic; | |
93 | sd_id128_t current_boot_id; | |
94 | uint64_t current_xor_hash; | |
bc85bfee LP |
95 | |
96 | JournalMetrics metrics; | |
16e9f408 | 97 | MMapCache *mmap; |
807e17f0 | 98 | |
7a24f3bf VC |
99 | sd_event_source *post_change_timer; |
100 | usec_t post_change_timer_period; | |
101 | ||
4743015d | 102 | OrderedHashmap *chain_cache; |
a4bcff5b | 103 | |
ac2e41f5 VC |
104 | pthread_t offline_thread; |
105 | volatile OfflineState offline_state; | |
106 | ||
858749f7 LP |
107 | unsigned last_seen_generation; |
108 | ||
57850536 | 109 | uint64_t compress_threshold_bytes; |
d80b051c | 110 | #if HAVE_COMPRESSION |
807e17f0 | 111 | void *compress_buffer; |
fa1c4b51 | 112 | size_t compress_buffer_size; |
807e17f0 | 113 | #endif |
7560fffc | 114 | |
349cc4a5 | 115 | #if HAVE_GCRYPT |
7560fffc LP |
116 | gcry_md_hd_t hmac; |
117 | bool hmac_running; | |
118 | ||
baed47c3 LP |
119 | FSSHeader *fss_file; |
120 | size_t fss_file_size; | |
121 | ||
122 | uint64_t fss_start_usec; | |
123 | uint64_t fss_interval_usec; | |
b7c9ae91 LP |
124 | |
125 | void *fsprg_state; | |
126 | size_t fsprg_state_size; | |
127 | ||
128 | void *fsprg_seed; | |
129 | size_t fsprg_seed_size; | |
7560fffc | 130 | #endif |
f4b47811 LP |
131 | } JournalFile; |
132 | ||
4a92baf3 | 133 | int journal_file_open( |
5d1ce257 | 134 | int fd, |
4a92baf3 LP |
135 | const char *fname, |
136 | int flags, | |
137 | mode_t mode, | |
7560fffc | 138 | bool compress, |
57850536 | 139 | uint64_t compress_threshold_bytes, |
baed47c3 | 140 | bool seal, |
4a92baf3 | 141 | JournalMetrics *metrics, |
27370278 | 142 | MMapCache *mmap_cache, |
b58c888f | 143 | Set *deferred_closes, |
4a92baf3 LP |
144 | JournalFile *template, |
145 | JournalFile **ret); | |
146 | ||
ac2e41f5 | 147 | int journal_file_set_offline(JournalFile *f, bool wait); |
b58c888f | 148 | bool journal_file_is_offlining(JournalFile *f); |
804ae586 | 149 | JournalFile* journal_file_close(JournalFile *j); |
28ca867a | 150 | int journal_file_fstat(JournalFile *f); |
627df1dc | 151 | DEFINE_TRIVIAL_CLEANUP_FUNC(JournalFile*, journal_file_close); |
87d2c1ff | 152 | |
4a92baf3 LP |
153 | int journal_file_open_reliably( |
154 | const char *fname, | |
155 | int flags, | |
156 | mode_t mode, | |
7560fffc | 157 | bool compress, |
57850536 | 158 | uint64_t compress_threshold_bytes, |
baed47c3 | 159 | bool seal, |
4a92baf3 | 160 | JournalMetrics *metrics, |
27370278 | 161 | MMapCache *mmap_cache, |
b58c888f | 162 | Set *deferred_closes, |
4a92baf3 LP |
163 | JournalFile *template, |
164 | JournalFile **ret); | |
9447a7f1 | 165 | |
0284adc6 | 166 | #define ALIGN64(x) (((x) + 7ULL) & ~7ULL) |
db11ac1a | 167 | #define VALID64(x) (((x) & 7ULL) == 0ULL) |
0284adc6 | 168 | |
ae97089d ZJS |
169 | /* Use six characters to cover the offsets common in smallish journal |
170 | * files without adding too many zeros. */ | |
171 | #define OFSfmt "%06"PRIx64 | |
172 | ||
fc89a139 LP |
173 | static inline bool VALID_REALTIME(uint64_t u) { |
174 | /* This considers timestamps until the year 3112 valid. That should be plenty room... */ | |
175 | return u > 0 && u < (1ULL << 55); | |
176 | } | |
177 | ||
178 | static inline bool VALID_MONOTONIC(uint64_t u) { | |
179 | /* This considers timestamps until 1142 years of runtime valid. */ | |
180 | return u < (1ULL << 55); | |
181 | } | |
182 | ||
183 | static inline bool VALID_EPOCH(uint64_t u) { | |
184 | /* This allows changing the key for 1142 years, every usec. */ | |
185 | return u < (1ULL << 55); | |
186 | } | |
187 | ||
0284adc6 LP |
188 | #define JOURNAL_HEADER_CONTAINS(h, field) \ |
189 | (le64toh((h)->header_size) >= offsetof(Header, field) + sizeof((h)->field)) | |
190 | ||
8088cbd3 | 191 | #define JOURNAL_HEADER_SEALED(h) \ |
a7656091 | 192 | FLAGS_SET(le32toh((h)->compatible_flags), HEADER_COMPATIBLE_SEALED) |
8088cbd3 | 193 | |
d89c8fdf | 194 | #define JOURNAL_HEADER_COMPRESSED_XZ(h) \ |
a7656091 | 195 | FLAGS_SET(le32toh((h)->incompatible_flags), HEADER_INCOMPATIBLE_COMPRESSED_XZ) |
d89c8fdf ZJS |
196 | |
197 | #define JOURNAL_HEADER_COMPRESSED_LZ4(h) \ | |
a7656091 | 198 | FLAGS_SET(le32toh((h)->incompatible_flags), HEADER_INCOMPATIBLE_COMPRESSED_LZ4) |
8088cbd3 | 199 | |
8653185a LP |
200 | #define JOURNAL_HEADER_COMPRESSED_ZSTD(h) \ |
201 | FLAGS_SET(le32toh((h)->incompatible_flags), HEADER_INCOMPATIBLE_COMPRESSED_ZSTD) | |
202 | ||
4ce534f4 LP |
203 | #define JOURNAL_HEADER_KEYED_HASH(h) \ |
204 | FLAGS_SET(le32toh((h)->incompatible_flags), HEADER_INCOMPATIBLE_KEYED_HASH) | |
205 | ||
78519831 | 206 | int journal_file_move_to_object(JournalFile *f, ObjectType type, uint64_t offset, Object **ret); |
87d2c1ff | 207 | |
44a6b1b6 ZJS |
208 | uint64_t journal_file_entry_n_items(Object *o) _pure_; |
209 | uint64_t journal_file_entry_array_n_items(Object *o) _pure_; | |
210 | uint64_t journal_file_hash_table_n_items(Object *o) _pure_; | |
87d2c1ff | 211 | |
78519831 | 212 | int journal_file_append_object(JournalFile *f, ObjectType type, uint64_t size, Object **ret, uint64_t *offset); |
d180c349 ZJS |
213 | int journal_file_append_entry( |
214 | JournalFile *f, | |
215 | const dual_timestamp *ts, | |
216 | const sd_id128_t *boot_id, | |
217 | const struct iovec iovec[], unsigned n_iovec, | |
218 | uint64_t *seqno, | |
219 | Object **ret, | |
220 | uint64_t *offset); | |
87d2c1ff | 221 | |
de190aef LP |
222 | int journal_file_find_data_object(JournalFile *f, const void *data, uint64_t size, Object **ret, uint64_t *offset); |
223 | int journal_file_find_data_object_with_hash(JournalFile *f, const void *data, uint64_t size, uint64_t hash, Object **ret, uint64_t *offset); | |
87d2c1ff | 224 | |
3c1668da LP |
225 | int journal_file_find_field_object(JournalFile *f, const void *field, uint64_t size, Object **ret, uint64_t *offset); |
226 | int journal_file_find_field_object_with_hash(JournalFile *f, const void *field, uint64_t size, uint64_t hash, Object **ret, uint64_t *offset); | |
227 | ||
1fc605b0 | 228 | void journal_file_reset_location(JournalFile *f); |
950c07d4 | 229 | void journal_file_save_location(JournalFile *f, Object *o, uint64_t offset); |
d8ae66d7 | 230 | int journal_file_compare_locations(JournalFile *af, JournalFile *bf); |
f534928a | 231 | int journal_file_next_entry(JournalFile *f, uint64_t p, direction_t direction, Object **ret, uint64_t *offset); |
87d2c1ff | 232 | |
de190aef LP |
233 | 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); |
234 | ||
235 | int journal_file_move_to_entry_by_seqnum(JournalFile *f, uint64_t seqnum, direction_t direction, Object **ret, uint64_t *offset); | |
236 | int journal_file_move_to_entry_by_realtime(JournalFile *f, uint64_t realtime, direction_t direction, Object **ret, uint64_t *offset); | |
237 | 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); | |
238 | ||
cbdca852 | 239 | 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); |
de190aef LP |
240 | 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); |
241 | 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); | |
cbdca852 | 242 | 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); |
87d2c1ff | 243 | |
5a271b08 | 244 | int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint64_t p); |
cf244689 | 245 | |
87d2c1ff | 246 | void journal_file_dump(JournalFile *f); |
dca6219e | 247 | void journal_file_print_header(JournalFile *f); |
87d2c1ff | 248 | |
7a4d21ad LP |
249 | int journal_file_archive(JournalFile *f); |
250 | JournalFile* journal_initiate_close(JournalFile *f, Set *deferred_closes); | |
57850536 | 251 | int journal_file_rotate(JournalFile **f, bool compress, uint64_t compress_threshold_bytes, bool seal, Set *deferred_closes); |
0ac38b70 | 252 | |
68127658 LP |
253 | int journal_file_dispose(int dir_fd, const char *fname); |
254 | ||
cf244689 | 255 | void journal_file_post_change(JournalFile *f); |
7a24f3bf | 256 | int journal_file_enable_post_change_timer(JournalFile *f, sd_event *e, usec_t t); |
cf244689 | 257 | |
8580d1f7 | 258 | void journal_reset_metrics(JournalMetrics *m); |
babfc091 LP |
259 | void journal_default_metrics(JournalMetrics *m, int fd); |
260 | ||
08984293 LP |
261 | int journal_file_get_cutoff_realtime_usec(JournalFile *f, usec_t *from, usec_t *to); |
262 | int journal_file_get_cutoff_monotonic_usec(JournalFile *f, sd_id128_t boot, usec_t *from, usec_t *to); | |
263 | ||
fb0951b0 | 264 | bool journal_file_rotate_suggested(JournalFile *f, usec_t max_file_usec); |
dade37d4 LP |
265 | |
266 | int journal_file_map_data_hash_table(JournalFile *f); | |
267 | int journal_file_map_field_hash_table(JournalFile *f); | |
d1afbcd2 LP |
268 | |
269 | static inline bool JOURNAL_FILE_COMPRESS(JournalFile *f) { | |
270 | assert(f); | |
8653185a | 271 | return f->compress_xz || f->compress_lz4 || f->compress_zstd; |
d1afbcd2 | 272 | } |
4ce534f4 LP |
273 | |
274 | uint64_t journal_file_hash_data(JournalFile *f, const void *data, size_t sz); |