]>
Commit | Line | Data |
---|---|---|
db9ecf05 | 1 | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
7a050b54 | 2 | |
7a050b54 | 3 | #include <fcntl.h> |
cf0fbc49 | 4 | #include <unistd.h> |
7a050b54 | 5 | |
3a9ca230 | 6 | #include "sd-id128.h" |
c6878637 | 7 | #include "sd-journal.h" |
6bedfcbb | 8 | |
b5efdb8a | 9 | #include "alloc-util.h" |
949082ac | 10 | #include "chattr-util.h" |
5cfa2c3d | 11 | #include "io-util.h" |
1e094703 | 12 | #include "journal-file-util.h" |
5cb24cd3 | 13 | #include "journal-vacuum.h" |
7a050b54 | 14 | #include "log.h" |
7c1784db | 15 | #include "logs-show.h" |
6bedfcbb | 16 | #include "parse-util.h" |
c6878637 | 17 | #include "rm-rf.h" |
317bb217 | 18 | #include "tests.h" |
7a050b54 | 19 | |
317bb217 | 20 | /* This program tests skipping around in a multi-file journal. */ |
7a050b54 | 21 | |
5cb24cd3 | 22 | static bool arg_keep = false; |
bb83c7c6 | 23 | static dual_timestamp previous_ts = {}; |
5cb24cd3 | 24 | |
c0f86d66 | 25 | _noreturn_ static void log_assert_errno(const char *text, int error, const char *file, unsigned line, const char *func) { |
9eec7d12 ZJS |
26 | log_internal(LOG_CRIT, error, file, line, func, |
27 | "'%s' failed at %s:%u (%s): %m", text, file, line, func); | |
7a050b54 MV |
28 | abort(); |
29 | } | |
30 | ||
31 | #define assert_ret(expr) \ | |
32 | do { \ | |
33 | int _r_ = (expr); \ | |
34 | if (_unlikely_(_r_ < 0)) \ | |
5a9b9157 | 35 | log_assert_errno(#expr, -_r_, PROJECT_FILE, __LINE__, __func__); \ |
7a050b54 MV |
36 | } while (false) |
37 | ||
45c0ecba | 38 | static JournalFile *test_open_internal(const char *name, JournalFileFlags flags) { |
74fb5be6 | 39 | _cleanup_(mmap_cache_unrefp) MMapCache *m = NULL; |
45c0ecba | 40 | JournalFile *f; |
74fb5be6 VC |
41 | |
42 | m = mmap_cache_new(); | |
43 | assert_se(m != NULL); | |
44 | ||
45c0ecba | 45 | assert_ret(journal_file_open(-1, name, O_RDWR|O_CREAT, flags, 0644, UINT64_MAX, NULL, m, NULL, &f)); |
7a050b54 MV |
46 | return f; |
47 | } | |
48 | ||
45c0ecba | 49 | static JournalFile *test_open(const char *name) { |
bb83c7c6 YW |
50 | return test_open_internal(name, JOURNAL_COMPRESS); |
51 | } | |
52 | ||
45c0ecba | 53 | static JournalFile *test_open_strict(const char *name) { |
bb83c7c6 YW |
54 | return test_open_internal(name, JOURNAL_COMPRESS | JOURNAL_STRICT_ORDER); |
55 | } | |
56 | ||
45c0ecba YW |
57 | static void test_close(JournalFile *f) { |
58 | (void) journal_file_offline_close(f); | |
7a050b54 MV |
59 | } |
60 | ||
45c0ecba | 61 | static void append_number(JournalFile *f, int n, const sd_id128_t *boot_id, uint64_t *seqnum) { |
7c1784db | 62 | _cleanup_free_ char *p = NULL, *q = NULL; |
7a050b54 | 63 | dual_timestamp ts; |
7c1784db YW |
64 | struct iovec iovec[2]; |
65 | size_t n_iov = 0; | |
7a050b54 MV |
66 | |
67 | dual_timestamp_get(&ts); | |
68 | ||
44cf96e3 LP |
69 | if (ts.monotonic <= previous_ts.monotonic) |
70 | ts.monotonic = previous_ts.monotonic + 1; | |
71 | ||
72 | if (ts.realtime <= previous_ts.realtime) | |
73 | ts.realtime = previous_ts.realtime + 1; | |
74 | ||
75 | previous_ts = ts; | |
76 | ||
7a050b54 | 77 | assert_se(asprintf(&p, "NUMBER=%d", n) >= 0); |
7c1784db YW |
78 | iovec[n_iov++] = IOVEC_MAKE_STRING(p); |
79 | ||
80 | if (boot_id) { | |
81 | assert_se(q = strjoin("_BOOT_ID=", SD_ID128_TO_STRING(*boot_id))); | |
82 | iovec[n_iov++] = IOVEC_MAKE_STRING(q); | |
83 | } | |
84 | ||
45c0ecba | 85 | assert_ret(journal_file_append_entry(f, &ts, boot_id, iovec, n_iov, seqnum, NULL, NULL, NULL)); |
7a050b54 MV |
86 | } |
87 | ||
45c0ecba | 88 | static void append_unreferenced_data(JournalFile *f, const sd_id128_t *boot_id) { |
bb83c7c6 YW |
89 | _cleanup_free_ char *q = NULL; |
90 | dual_timestamp ts; | |
91 | struct iovec iovec; | |
92 | ||
93 | assert(boot_id); | |
94 | ||
95 | ts.monotonic = usec_sub_unsigned(previous_ts.monotonic, 10); | |
96 | ts.realtime = usec_sub_unsigned(previous_ts.realtime, 10); | |
97 | ||
98 | assert_se(q = strjoin("_BOOT_ID=", SD_ID128_TO_STRING(*boot_id))); | |
99 | iovec = IOVEC_MAKE_STRING(q); | |
100 | ||
45c0ecba | 101 | assert_se(journal_file_append_entry(f, &ts, boot_id, &iovec, 1, NULL, NULL, NULL, NULL) == -EREMCHG); |
bb83c7c6 YW |
102 | } |
103 | ||
68da8adf | 104 | static void test_check_number(sd_journal *j, int n) { |
7c1784db | 105 | sd_id128_t boot_id; |
7a050b54 | 106 | const void *d; |
3d41b6b8 | 107 | _cleanup_free_ char *k = NULL; |
7a050b54 MV |
108 | size_t l; |
109 | int x; | |
110 | ||
7c1784db | 111 | assert_se(sd_journal_get_monotonic_usec(j, NULL, &boot_id) >= 0); |
7a050b54 MV |
112 | assert_ret(sd_journal_get_data(j, "NUMBER", &d, &l)); |
113 | assert_se(k = strndup(d, l)); | |
7c1784db | 114 | printf("%s %s (expected=%i)\n", SD_ID128_TO_STRING(boot_id), k, n); |
7a050b54 | 115 | |
43e460a5 | 116 | assert_se(safe_atoi(k + STRLEN("NUMBER="), &x) >= 0); |
7a050b54 MV |
117 | assert_se(n == x); |
118 | } | |
119 | ||
68da8adf | 120 | static void test_check_numbers_down(sd_journal *j, int count) { |
510b857f LP |
121 | int i; |
122 | ||
123 | for (i = 1; i <= count; i++) { | |
7a050b54 MV |
124 | int r; |
125 | test_check_number(j, i); | |
126 | assert_ret(r = sd_journal_next(j)); | |
127 | if (i == count) | |
128 | assert_se(r == 0); | |
129 | else | |
130 | assert_se(r == 1); | |
131 | } | |
132 | ||
133 | } | |
134 | ||
68da8adf | 135 | static void test_check_numbers_up(sd_journal *j, int count) { |
7a050b54 MV |
136 | for (int i = count; i >= 1; i--) { |
137 | int r; | |
138 | test_check_number(j, i); | |
139 | assert_ret(r = sd_journal_previous(j)); | |
140 | if (i == 1) | |
141 | assert_se(r == 0); | |
142 | else | |
143 | assert_se(r == 1); | |
144 | } | |
145 | ||
146 | } | |
147 | ||
148 | static void setup_sequential(void) { | |
45c0ecba | 149 | JournalFile *f1, *f2, *f3; |
7c1784db | 150 | sd_id128_t id; |
43e460a5 YW |
151 | |
152 | f1 = test_open("one.journal"); | |
153 | f2 = test_open("two.journal"); | |
154 | f3 = test_open("three.journal"); | |
7c1784db YW |
155 | assert_se(sd_id128_randomize(&id) >= 0); |
156 | log_info("boot_id: %s", SD_ID128_TO_STRING(id)); | |
157 | append_number(f1, 1, &id, NULL); | |
158 | append_number(f1, 2, &id, NULL); | |
159 | append_number(f1, 3, &id, NULL); | |
160 | append_number(f2, 4, &id, NULL); | |
161 | assert_se(sd_id128_randomize(&id) >= 0); | |
162 | log_info("boot_id: %s", SD_ID128_TO_STRING(id)); | |
163 | append_number(f2, 5, &id, NULL); | |
164 | append_number(f2, 6, &id, NULL); | |
165 | append_number(f3, 7, &id, NULL); | |
166 | append_number(f3, 8, &id, NULL); | |
167 | assert_se(sd_id128_randomize(&id) >= 0); | |
168 | log_info("boot_id: %s", SD_ID128_TO_STRING(id)); | |
169 | append_number(f3, 9, &id, NULL); | |
43e460a5 YW |
170 | test_close(f1); |
171 | test_close(f2); | |
172 | test_close(f3); | |
7a050b54 MV |
173 | } |
174 | ||
175 | static void setup_interleaved(void) { | |
45c0ecba | 176 | JournalFile *f1, *f2, *f3; |
7c1784db | 177 | sd_id128_t id; |
43e460a5 YW |
178 | |
179 | f1 = test_open("one.journal"); | |
180 | f2 = test_open("two.journal"); | |
181 | f3 = test_open("three.journal"); | |
7c1784db YW |
182 | assert_se(sd_id128_randomize(&id) >= 0); |
183 | log_info("boot_id: %s", SD_ID128_TO_STRING(id)); | |
184 | append_number(f1, 1, &id, NULL); | |
185 | append_number(f2, 2, &id, NULL); | |
186 | append_number(f3, 3, &id, NULL); | |
187 | append_number(f1, 4, &id, NULL); | |
188 | append_number(f2, 5, &id, NULL); | |
189 | append_number(f3, 6, &id, NULL); | |
190 | append_number(f1, 7, &id, NULL); | |
191 | append_number(f2, 8, &id, NULL); | |
192 | append_number(f3, 9, &id, NULL); | |
43e460a5 YW |
193 | test_close(f1); |
194 | test_close(f2); | |
195 | test_close(f3); | |
7a050b54 MV |
196 | } |
197 | ||
bb83c7c6 | 198 | static void setup_unreferenced_data(void) { |
45c0ecba | 199 | JournalFile *f1, *f2, *f3; |
bb83c7c6 YW |
200 | sd_id128_t id; |
201 | ||
202 | /* For issue #29275. */ | |
203 | ||
204 | f1 = test_open_strict("one.journal"); | |
205 | f2 = test_open_strict("two.journal"); | |
206 | f3 = test_open_strict("three.journal"); | |
207 | assert_se(sd_id128_randomize(&id) >= 0); | |
208 | log_info("boot_id: %s", SD_ID128_TO_STRING(id)); | |
209 | append_number(f1, 1, &id, NULL); | |
210 | append_number(f1, 2, &id, NULL); | |
211 | append_number(f1, 3, &id, NULL); | |
212 | assert_se(sd_id128_randomize(&id) >= 0); | |
213 | log_info("boot_id: %s", SD_ID128_TO_STRING(id)); | |
214 | append_unreferenced_data(f1, &id); | |
215 | append_number(f2, 4, &id, NULL); | |
216 | append_number(f2, 5, &id, NULL); | |
217 | append_number(f2, 6, &id, NULL); | |
218 | assert_se(sd_id128_randomize(&id) >= 0); | |
219 | log_info("boot_id: %s", SD_ID128_TO_STRING(id)); | |
220 | append_unreferenced_data(f2, &id); | |
221 | append_number(f3, 7, &id, NULL); | |
222 | append_number(f3, 8, &id, NULL); | |
223 | append_number(f3, 9, &id, NULL); | |
224 | test_close(f1); | |
225 | test_close(f2); | |
226 | test_close(f3); | |
227 | } | |
228 | ||
949082ac LP |
229 | static void mkdtemp_chdir_chattr(char *path) { |
230 | assert_se(mkdtemp(path)); | |
231 | assert_se(chdir(path) >= 0); | |
232 | ||
233 | /* Speed up things a bit on btrfs, ensuring that CoW is turned off for all files created in our | |
234 | * directory during the test run */ | |
235 | (void) chattr_path(path, FS_NOCOW_FL, FS_NOCOW_FL, NULL); | |
236 | } | |
237 | ||
68da8adf | 238 | static void test_skip_one(void (*setup)(void)) { |
949082ac | 239 | char t[] = "/var/tmp/journal-skip-XXXXXX"; |
7a050b54 MV |
240 | sd_journal *j; |
241 | int r; | |
242 | ||
949082ac | 243 | mkdtemp_chdir_chattr(t); |
7a050b54 MV |
244 | |
245 | setup(); | |
246 | ||
43e460a5 | 247 | /* Seek to head, iterate down. */ |
7a050b54 MV |
248 | assert_ret(sd_journal_open_directory(&j, t, 0)); |
249 | assert_ret(sd_journal_seek_head(j)); | |
836809d1 | 250 | assert_se(sd_journal_next(j) == 1); /* pointing to the first entry */ |
43e460a5 | 251 | test_check_numbers_down(j, 9); |
7a050b54 MV |
252 | sd_journal_close(j); |
253 | ||
43e460a5 YW |
254 | /* Seek to head, iterate down. */ |
255 | assert_ret(sd_journal_open_directory(&j, t, 0)); | |
256 | assert_ret(sd_journal_seek_head(j)); | |
836809d1 YW |
257 | assert_se(sd_journal_next(j) == 1); /* pointing to the first entry */ |
258 | assert_se(sd_journal_previous(j) == 0); /* no-op */ | |
43e460a5 YW |
259 | test_check_numbers_down(j, 9); |
260 | sd_journal_close(j); | |
261 | ||
45689fd2 YW |
262 | /* Seek to head twice, iterate down. */ |
263 | assert_ret(sd_journal_open_directory(&j, t, 0)); | |
264 | assert_ret(sd_journal_seek_head(j)); | |
265 | assert_se(sd_journal_next(j) == 1); /* pointing to the first entry */ | |
266 | assert_ret(sd_journal_seek_head(j)); | |
267 | assert_se(sd_journal_next(j) == 1); /* pointing to the first entry */ | |
268 | test_check_numbers_down(j, 9); | |
269 | sd_journal_close(j); | |
270 | ||
43e460a5 YW |
271 | /* Seek to head, move to previous, then iterate down. */ |
272 | assert_ret(sd_journal_open_directory(&j, t, 0)); | |
273 | assert_ret(sd_journal_seek_head(j)); | |
836809d1 YW |
274 | assert_se(sd_journal_previous(j) == 0); /* no-op */ |
275 | assert_se(sd_journal_next(j) == 1); /* pointing to the first entry */ | |
43e460a5 YW |
276 | test_check_numbers_down(j, 9); |
277 | sd_journal_close(j); | |
278 | ||
279 | /* Seek to head, walk several steps, then iterate down. */ | |
280 | assert_ret(sd_journal_open_directory(&j, t, 0)); | |
281 | assert_ret(sd_journal_seek_head(j)); | |
836809d1 YW |
282 | assert_se(sd_journal_previous(j) == 0); /* no-op */ |
283 | assert_se(sd_journal_previous(j) == 0); /* no-op */ | |
284 | assert_se(sd_journal_previous(j) == 0); /* no-op */ | |
285 | assert_se(sd_journal_next(j) == 1); /* pointing to the first entry */ | |
286 | assert_se(sd_journal_previous(j) == 0); /* no-op */ | |
287 | assert_se(sd_journal_previous(j) == 0); /* no-op */ | |
43e460a5 YW |
288 | test_check_numbers_down(j, 9); |
289 | sd_journal_close(j); | |
290 | ||
291 | /* Seek to tail, iterate up. */ | |
7a050b54 MV |
292 | assert_ret(sd_journal_open_directory(&j, t, 0)); |
293 | assert_ret(sd_journal_seek_tail(j)); | |
836809d1 | 294 | assert_se(sd_journal_previous(j) == 1); /* pointing to the last entry */ |
43e460a5 YW |
295 | test_check_numbers_up(j, 9); |
296 | sd_journal_close(j); | |
297 | ||
45689fd2 YW |
298 | /* Seek to tail twice, iterate up. */ |
299 | assert_ret(sd_journal_open_directory(&j, t, 0)); | |
300 | assert_ret(sd_journal_seek_tail(j)); | |
301 | assert_se(sd_journal_previous(j) == 1); /* pointing to the last entry */ | |
4aa33df8 YW |
302 | assert_ret(sd_journal_seek_tail(j)); |
303 | assert_se(sd_journal_previous(j) == 1); /* pointing to the last entry */ | |
45689fd2 YW |
304 | test_check_numbers_up(j, 9); |
305 | sd_journal_close(j); | |
306 | ||
43e460a5 YW |
307 | /* Seek to tail, move to next, then iterate up. */ |
308 | assert_ret(sd_journal_open_directory(&j, t, 0)); | |
309 | assert_ret(sd_journal_seek_tail(j)); | |
836809d1 YW |
310 | assert_se(sd_journal_next(j) == 0); /* no-op */ |
311 | assert_se(sd_journal_previous(j) == 1); /* pointing to the last entry */ | |
43e460a5 | 312 | test_check_numbers_up(j, 9); |
7a050b54 MV |
313 | sd_journal_close(j); |
314 | ||
43e460a5 | 315 | /* Seek to tail, walk several steps, then iterate up. */ |
7a050b54 MV |
316 | assert_ret(sd_journal_open_directory(&j, t, 0)); |
317 | assert_ret(sd_journal_seek_tail(j)); | |
836809d1 YW |
318 | assert_se(sd_journal_next(j) == 0); /* no-op */ |
319 | assert_se(sd_journal_next(j) == 0); /* no-op */ | |
320 | assert_se(sd_journal_next(j) == 0); /* no-op */ | |
321 | assert_se(sd_journal_previous(j) == 1); /* pointing to the last entry. */ | |
322 | assert_se(sd_journal_next(j) == 0); /* no-op */ | |
323 | assert_se(sd_journal_next(j) == 0); /* no-op */ | |
43e460a5 YW |
324 | test_check_numbers_up(j, 9); |
325 | sd_journal_close(j); | |
326 | ||
327 | /* Seek to tail, skip to head, iterate down. */ | |
328 | assert_ret(sd_journal_open_directory(&j, t, 0)); | |
329 | assert_ret(sd_journal_seek_tail(j)); | |
836809d1 | 330 | assert_se(sd_journal_previous_skip(j, 9) == 9); /* pointing to the first entry. */ |
43e460a5 YW |
331 | test_check_numbers_down(j, 9); |
332 | sd_journal_close(j); | |
333 | ||
9a27ef09 | 334 | /* Seek to tail, skip to head in a more complex way, then iterate down. */ |
43e460a5 YW |
335 | assert_ret(sd_journal_open_directory(&j, t, 0)); |
336 | assert_ret(sd_journal_seek_tail(j)); | |
836809d1 YW |
337 | assert_se(sd_journal_next(j) == 0); |
338 | assert_se(sd_journal_previous_skip(j, 4) == 4); | |
339 | assert_se(sd_journal_previous_skip(j, 5) == 5); | |
340 | assert_se(sd_journal_previous(j) == 0); | |
341 | assert_se(sd_journal_previous_skip(j, 5) == 0); | |
342 | assert_se(sd_journal_next(j) == 1); | |
343 | assert_se(sd_journal_previous_skip(j, 5) == 1); | |
344 | assert_se(sd_journal_next(j) == 1); | |
345 | assert_se(sd_journal_next(j) == 1); | |
346 | assert_se(sd_journal_previous(j) == 1); | |
347 | assert_se(sd_journal_next(j) == 1); | |
348 | assert_se(sd_journal_next(j) == 1); | |
349 | assert_se(sd_journal_previous_skip(j, 5) == 3); | |
43e460a5 YW |
350 | test_check_numbers_down(j, 9); |
351 | sd_journal_close(j); | |
352 | ||
353 | /* Seek to head, skip to tail, iterate up. */ | |
354 | assert_ret(sd_journal_open_directory(&j, t, 0)); | |
355 | assert_ret(sd_journal_seek_head(j)); | |
836809d1 | 356 | assert_se(sd_journal_next_skip(j, 9) == 9); |
43e460a5 | 357 | test_check_numbers_up(j, 9); |
7a050b54 MV |
358 | sd_journal_close(j); |
359 | ||
43e460a5 | 360 | /* Seek to head, skip to tail in a more complex way, then iterate up. */ |
7a050b54 MV |
361 | assert_ret(sd_journal_open_directory(&j, t, 0)); |
362 | assert_ret(sd_journal_seek_head(j)); | |
836809d1 YW |
363 | assert_se(sd_journal_previous(j) == 0); |
364 | assert_se(sd_journal_next_skip(j, 4) == 4); | |
365 | assert_se(sd_journal_next_skip(j, 5) == 5); | |
366 | assert_se(sd_journal_next(j) == 0); | |
367 | assert_se(sd_journal_next_skip(j, 5) == 0); | |
368 | assert_se(sd_journal_previous(j) == 1); | |
369 | assert_se(sd_journal_next_skip(j, 5) == 1); | |
370 | assert_se(sd_journal_previous(j) == 1); | |
371 | assert_se(sd_journal_previous(j) == 1); | |
372 | assert_se(sd_journal_next(j) == 1); | |
373 | assert_se(sd_journal_previous(j) == 1); | |
374 | assert_se(sd_journal_previous(j) == 1); | |
375 | assert_se(r = sd_journal_next_skip(j, 5) == 3); | |
43e460a5 | 376 | test_check_numbers_up(j, 9); |
7a050b54 MV |
377 | sd_journal_close(j); |
378 | ||
5cb24cd3 ZJS |
379 | log_info("Done..."); |
380 | ||
381 | if (arg_keep) | |
382 | log_info("Not removing %s", t); | |
383 | else { | |
8580d1f7 | 384 | journal_directory_vacuum(".", 3000000, 0, 0, NULL, true); |
5cb24cd3 | 385 | |
c6878637 | 386 | assert_se(rm_rf(t, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0); |
5cb24cd3 ZJS |
387 | } |
388 | ||
389 | puts("------------------------------------------------------------"); | |
390 | } | |
391 | ||
68da8adf JJ |
392 | TEST(skip) { |
393 | test_skip_one(setup_sequential); | |
394 | test_skip_one(setup_interleaved); | |
395 | } | |
5cb24cd3 | 396 | |
7c1784db YW |
397 | static void test_boot_id_one(void (*setup)(void), size_t n_boots_expected) { |
398 | char t[] = "/var/tmp/journal-boot-id-XXXXXX"; | |
399 | sd_journal *j; | |
400 | _cleanup_free_ BootId *boots = NULL; | |
401 | size_t n_boots; | |
402 | ||
403 | mkdtemp_chdir_chattr(t); | |
404 | ||
405 | setup(); | |
406 | ||
407 | assert_ret(sd_journal_open_directory(&j, t, 0)); | |
408 | assert_se(journal_get_boots(j, &boots, &n_boots) >= 0); | |
409 | assert_se(boots); | |
410 | assert_se(n_boots == n_boots_expected); | |
411 | sd_journal_close(j); | |
412 | ||
413 | FOREACH_ARRAY(b, boots, n_boots) { | |
414 | assert_ret(sd_journal_open_directory(&j, t, 0)); | |
415 | assert_se(journal_find_boot_by_id(j, b->id) == 1); | |
416 | sd_journal_close(j); | |
417 | } | |
418 | ||
419 | for (int i = - (int) n_boots + 1; i <= (int) n_boots; i++) { | |
420 | sd_id128_t id; | |
421 | ||
422 | assert_ret(sd_journal_open_directory(&j, t, 0)); | |
423 | assert_se(journal_find_boot_by_offset(j, i, &id) == 1); | |
424 | if (i <= 0) | |
425 | assert_se(sd_id128_equal(id, boots[n_boots + i - 1].id)); | |
426 | else | |
427 | assert_se(sd_id128_equal(id, boots[i - 1].id)); | |
428 | sd_journal_close(j); | |
429 | } | |
430 | ||
431 | log_info("Done..."); | |
432 | ||
433 | if (arg_keep) | |
434 | log_info("Not removing %s", t); | |
435 | else { | |
436 | journal_directory_vacuum(".", 3000000, 0, 0, NULL, true); | |
437 | ||
438 | assert_se(rm_rf(t, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0); | |
439 | } | |
440 | ||
441 | puts("------------------------------------------------------------"); | |
442 | } | |
443 | ||
444 | TEST(boot_id) { | |
445 | test_boot_id_one(setup_sequential, 3); | |
bb83c7c6 | 446 | test_boot_id_one(setup_unreferenced_data, 3); |
7c1784db YW |
447 | } |
448 | ||
c92f1ebe | 449 | static void test_sequence_numbers_one(void) { |
74fb5be6 | 450 | _cleanup_(mmap_cache_unrefp) MMapCache *m = NULL; |
949082ac | 451 | char t[] = "/var/tmp/journal-seq-XXXXXX"; |
45c0ecba | 452 | JournalFile *one, *two; |
5cb24cd3 ZJS |
453 | uint64_t seqnum = 0; |
454 | sd_id128_t seqnum_id; | |
455 | ||
74fb5be6 VC |
456 | m = mmap_cache_new(); |
457 | assert_se(m != NULL); | |
458 | ||
949082ac | 459 | mkdtemp_chdir_chattr(t); |
5cb24cd3 | 460 | |
45c0ecba YW |
461 | assert_se(journal_file_open(-1, "one.journal", O_RDWR|O_CREAT, JOURNAL_COMPRESS, 0644, |
462 | UINT64_MAX, NULL, m, NULL, &one) == 0); | |
5cb24cd3 | 463 | |
7c1784db | 464 | append_number(one, 1, NULL, &seqnum); |
5cb24cd3 | 465 | printf("seqnum=%"PRIu64"\n", seqnum); |
0c0cdb06 | 466 | assert_se(seqnum == 1); |
7c1784db | 467 | append_number(one, 2, NULL, &seqnum); |
5cb24cd3 | 468 | printf("seqnum=%"PRIu64"\n", seqnum); |
0c0cdb06 | 469 | assert_se(seqnum == 2); |
5cb24cd3 | 470 | |
45c0ecba YW |
471 | assert_se(one->header->state == STATE_ONLINE); |
472 | assert_se(!sd_id128_equal(one->header->file_id, one->header->machine_id)); | |
473 | assert_se(!sd_id128_equal(one->header->file_id, one->header->tail_entry_boot_id)); | |
474 | assert_se(sd_id128_equal(one->header->file_id, one->header->seqnum_id)); | |
5cb24cd3 | 475 | |
45c0ecba | 476 | memcpy(&seqnum_id, &one->header->seqnum_id, sizeof(sd_id128_t)); |
5cb24cd3 | 477 | |
45c0ecba YW |
478 | assert_se(journal_file_open(-1, "two.journal", O_RDWR|O_CREAT, JOURNAL_COMPRESS, 0644, |
479 | UINT64_MAX, NULL, m, one, &two) == 0); | |
5cb24cd3 | 480 | |
45c0ecba YW |
481 | assert_se(two->header->state == STATE_ONLINE); |
482 | assert_se(!sd_id128_equal(two->header->file_id, one->header->file_id)); | |
483 | assert_se(sd_id128_equal(two->header->machine_id, one->header->machine_id)); | |
484 | assert_se(sd_id128_is_null(two->header->tail_entry_boot_id)); /* Not written yet. */ | |
485 | assert_se(sd_id128_equal(two->header->seqnum_id, one->header->seqnum_id)); | |
5cb24cd3 | 486 | |
7c1784db | 487 | append_number(two, 3, NULL, &seqnum); |
5cb24cd3 | 488 | printf("seqnum=%"PRIu64"\n", seqnum); |
0c0cdb06 | 489 | assert_se(seqnum == 3); |
7c1784db | 490 | append_number(two, 4, NULL, &seqnum); |
5cb24cd3 | 491 | printf("seqnum=%"PRIu64"\n", seqnum); |
0c0cdb06 | 492 | assert_se(seqnum == 4); |
5cb24cd3 | 493 | |
1fa2ebbe | 494 | /* Verify tail_entry_boot_id. */ |
45c0ecba | 495 | assert_se(sd_id128_equal(two->header->tail_entry_boot_id, one->header->tail_entry_boot_id)); |
1fa2ebbe | 496 | |
5cb24cd3 ZJS |
497 | test_close(two); |
498 | ||
7c1784db | 499 | append_number(one, 5, NULL, &seqnum); |
5cb24cd3 | 500 | printf("seqnum=%"PRIu64"\n", seqnum); |
0c0cdb06 | 501 | assert_se(seqnum == 5); |
5cb24cd3 | 502 | |
7c1784db | 503 | append_number(one, 6, NULL, &seqnum); |
5cb24cd3 | 504 | printf("seqnum=%"PRIu64"\n", seqnum); |
0c0cdb06 | 505 | assert_se(seqnum == 6); |
5cb24cd3 ZJS |
506 | |
507 | test_close(one); | |
508 | ||
3a9ca230 NR |
509 | /* If the machine-id is not initialized, the header file verification |
510 | * (which happens when re-opening a journal file) will fail. */ | |
511 | if (sd_id128_get_machine(NULL) >= 0) { | |
512 | /* restart server */ | |
513 | seqnum = 0; | |
5cb24cd3 | 514 | |
45c0ecba YW |
515 | assert_se(journal_file_open(-1, "two.journal", O_RDWR, JOURNAL_COMPRESS, 0, |
516 | UINT64_MAX, NULL, m, NULL, &two) == 0); | |
5cb24cd3 | 517 | |
45c0ecba | 518 | assert_se(sd_id128_equal(two->header->seqnum_id, seqnum_id)); |
5cb24cd3 | 519 | |
7c1784db | 520 | append_number(two, 7, NULL, &seqnum); |
3a9ca230 NR |
521 | printf("seqnum=%"PRIu64"\n", seqnum); |
522 | assert_se(seqnum == 5); | |
5cb24cd3 | 523 | |
3a9ca230 NR |
524 | /* So..., here we have the same seqnum in two files with the |
525 | * same seqnum_id. */ | |
5cb24cd3 | 526 | |
3a9ca230 NR |
527 | test_close(two); |
528 | } | |
5cb24cd3 ZJS |
529 | |
530 | log_info("Done..."); | |
531 | ||
532 | if (arg_keep) | |
533 | log_info("Not removing %s", t); | |
534 | else { | |
8580d1f7 | 535 | journal_directory_vacuum(".", 3000000, 0, 0, NULL, true); |
5cb24cd3 | 536 | |
c6878637 | 537 | assert_se(rm_rf(t, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0); |
5cb24cd3 | 538 | } |
7a050b54 MV |
539 | } |
540 | ||
c92f1ebe DDM |
541 | TEST(sequence_numbers) { |
542 | assert_se(setenv("SYSTEMD_JOURNAL_COMPACT", "0", 1) >= 0); | |
543 | test_sequence_numbers_one(); | |
544 | ||
545 | assert_se(setenv("SYSTEMD_JOURNAL_COMPACT", "1", 1) >= 0); | |
546 | test_sequence_numbers_one(); | |
547 | } | |
548 | ||
68da8adf | 549 | static int intro(void) { |
45c0ecba | 550 | /* journal_file_open() requires a valid machine id */ |
317bb217 ZJS |
551 | if (access("/etc/machine-id", F_OK) != 0) |
552 | return log_tests_skipped("/etc/machine-id not found"); | |
143bfdaf | 553 | |
68da8adf | 554 | arg_keep = saved_argc > 1; |
7a050b54 | 555 | |
68da8adf | 556 | return EXIT_SUCCESS; |
7a050b54 | 557 | } |
68da8adf JJ |
558 | |
559 | DEFINE_TEST_MAIN_WITH_INTRO(LOG_DEBUG, intro); |