diff --git a/src/journal/test-journal-interleaving.c b/src/journal/test-journal-interleaving.c index f7293ef4b4..21c5bdddae 100644 --- a/src/journal/test-journal-interleaving.c +++ b/src/journal/test-journal-interleaving.c @@ -173,126 +173,132 @@ static void test_skip_one(void (*setup)(void)) { /* Seek to head, iterate down. */ assert_ret(sd_journal_open_directory(&j, t, 0)); assert_ret(sd_journal_seek_head(j)); - assert_ret(sd_journal_next(j)); /* pointing the first entry */ + assert_se(sd_journal_next(j) == 1); /* pointing to the first entry */ test_check_numbers_down(j, 9); sd_journal_close(j); /* Seek to head, iterate down. */ assert_ret(sd_journal_open_directory(&j, t, 0)); assert_ret(sd_journal_seek_head(j)); - assert_ret(sd_journal_next(j)); /* pointing the first entry */ - assert_ret(sd_journal_previous(j)); /* no-op */ + assert_se(sd_journal_next(j) == 1); /* pointing to the first entry */ + assert_se(sd_journal_previous(j) == 0); /* no-op */ + test_check_numbers_down(j, 9); + sd_journal_close(j); + + /* Seek to head twice, iterate down. */ + assert_ret(sd_journal_open_directory(&j, t, 0)); + assert_ret(sd_journal_seek_head(j)); + assert_se(sd_journal_next(j) == 1); /* pointing to the first entry */ + assert_ret(sd_journal_seek_head(j)); + assert_se(sd_journal_next(j) == 1); /* pointing to the first entry */ test_check_numbers_down(j, 9); sd_journal_close(j); /* Seek to head, move to previous, then iterate down. */ assert_ret(sd_journal_open_directory(&j, t, 0)); assert_ret(sd_journal_seek_head(j)); - assert_ret(sd_journal_previous(j)); /* no-op */ - assert_ret(sd_journal_next(j)); /* pointing the first entry */ + assert_se(sd_journal_previous(j) == 0); /* no-op */ + assert_se(sd_journal_next(j) == 1); /* pointing to the first entry */ test_check_numbers_down(j, 9); sd_journal_close(j); /* Seek to head, walk several steps, then iterate down. */ assert_ret(sd_journal_open_directory(&j, t, 0)); assert_ret(sd_journal_seek_head(j)); - assert_ret(sd_journal_previous(j)); /* no-op */ - assert_ret(sd_journal_previous(j)); /* no-op */ - assert_ret(sd_journal_previous(j)); /* no-op */ - assert_ret(sd_journal_next(j)); /* pointing the first entry */ - assert_ret(sd_journal_previous(j)); /* no-op */ - assert_ret(sd_journal_previous(j)); /* no-op */ + assert_se(sd_journal_previous(j) == 0); /* no-op */ + assert_se(sd_journal_previous(j) == 0); /* no-op */ + assert_se(sd_journal_previous(j) == 0); /* no-op */ + assert_se(sd_journal_next(j) == 1); /* pointing to the first entry */ + assert_se(sd_journal_previous(j) == 0); /* no-op */ + assert_se(sd_journal_previous(j) == 0); /* no-op */ test_check_numbers_down(j, 9); sd_journal_close(j); /* Seek to tail, iterate up. */ assert_ret(sd_journal_open_directory(&j, t, 0)); assert_ret(sd_journal_seek_tail(j)); - assert_ret(sd_journal_previous(j)); + assert_se(sd_journal_previous(j) == 1); /* pointing to the last entry */ + test_check_numbers_up(j, 9); + sd_journal_close(j); + + /* Seek to tail twice, iterate up. */ + assert_ret(sd_journal_open_directory(&j, t, 0)); + assert_ret(sd_journal_seek_tail(j)); + assert_se(sd_journal_previous(j) == 1); /* pointing to the last entry */ + assert_ret(sd_journal_seek_tail(j)); + assert_se(sd_journal_previous(j) == 1); /* pointing to the last entry */ test_check_numbers_up(j, 9); sd_journal_close(j); /* Seek to tail, move to next, then iterate up. */ assert_ret(sd_journal_open_directory(&j, t, 0)); assert_ret(sd_journal_seek_tail(j)); - assert_ret(sd_journal_next(j)); /* no-op */ - assert_ret(sd_journal_previous(j)); /* pointing the first entry */ + assert_se(sd_journal_next(j) == 0); /* no-op */ + assert_se(sd_journal_previous(j) == 1); /* pointing to the last entry */ test_check_numbers_up(j, 9); sd_journal_close(j); /* Seek to tail, walk several steps, then iterate up. */ assert_ret(sd_journal_open_directory(&j, t, 0)); assert_ret(sd_journal_seek_tail(j)); - assert_ret(sd_journal_next(j)); /* no-op */ - assert_ret(sd_journal_next(j)); /* no-op */ - assert_ret(sd_journal_next(j)); /* no-op */ - assert_ret(sd_journal_previous(j)); /* pointing the last entry. */ - assert_ret(sd_journal_next(j)); /* no-op */ - assert_ret(sd_journal_next(j)); /* no-op */ + assert_se(sd_journal_next(j) == 0); /* no-op */ + assert_se(sd_journal_next(j) == 0); /* no-op */ + assert_se(sd_journal_next(j) == 0); /* no-op */ + assert_se(sd_journal_previous(j) == 1); /* pointing to the last entry. */ + assert_se(sd_journal_next(j) == 0); /* no-op */ + assert_se(sd_journal_next(j) == 0); /* no-op */ test_check_numbers_up(j, 9); sd_journal_close(j); /* Seek to tail, skip to head, iterate down. */ assert_ret(sd_journal_open_directory(&j, t, 0)); assert_ret(sd_journal_seek_tail(j)); - assert_ret(r = sd_journal_previous_skip(j, 9)); - assert_se(r == 9); + assert_se(sd_journal_previous_skip(j, 9) == 9); /* pointing to the first entry. */ test_check_numbers_down(j, 9); sd_journal_close(j); /* Seek to tail, skip to head in a more complex way, then iterate down. */ assert_ret(sd_journal_open_directory(&j, t, 0)); assert_ret(sd_journal_seek_tail(j)); - assert_ret(sd_journal_next(j)); /* no-op */ - assert_ret(r = sd_journal_previous_skip(j, 4)); - assert_se(r == 4); - assert_ret(r = sd_journal_previous_skip(j, 5)); - assert_se(r == 5); - assert_ret(sd_journal_previous(j)); /* no-op */ - assert_ret(r = sd_journal_previous_skip(j, 5)); - assert_se(r == 0); - assert_ret(sd_journal_next(j)); - assert_ret(r = sd_journal_previous_skip(j, 5)); - assert_se(r == 1); - assert_ret(sd_journal_next(j)); - assert_ret(sd_journal_next(j)); - assert_ret(sd_journal_previous(j)); - assert_ret(sd_journal_next(j)); - assert_ret(sd_journal_next(j)); - assert_ret(r = sd_journal_previous_skip(j, 5)); - assert_se(r == 3); + assert_se(sd_journal_next(j) == 0); + assert_se(sd_journal_previous_skip(j, 4) == 4); + assert_se(sd_journal_previous_skip(j, 5) == 5); + assert_se(sd_journal_previous(j) == 0); + assert_se(sd_journal_previous_skip(j, 5) == 0); + assert_se(sd_journal_next(j) == 1); + assert_se(sd_journal_previous_skip(j, 5) == 1); + assert_se(sd_journal_next(j) == 1); + assert_se(sd_journal_next(j) == 1); + assert_se(sd_journal_previous(j) == 1); + assert_se(sd_journal_next(j) == 1); + assert_se(sd_journal_next(j) == 1); + assert_se(sd_journal_previous_skip(j, 5) == 3); test_check_numbers_down(j, 9); sd_journal_close(j); /* Seek to head, skip to tail, iterate up. */ assert_ret(sd_journal_open_directory(&j, t, 0)); assert_ret(sd_journal_seek_head(j)); - assert_ret(r = sd_journal_next_skip(j, 9)); - assert_se(r == 9); + assert_se(sd_journal_next_skip(j, 9) == 9); test_check_numbers_up(j, 9); sd_journal_close(j); /* Seek to head, skip to tail in a more complex way, then iterate up. */ assert_ret(sd_journal_open_directory(&j, t, 0)); assert_ret(sd_journal_seek_head(j)); - assert_ret(sd_journal_previous(j)); /* no-op */ - assert_ret(r = sd_journal_next_skip(j, 4)); - assert_se(r == 4); - assert_ret(r = sd_journal_next_skip(j, 5)); - assert_se(r == 5); - assert_ret(sd_journal_next(j)); /* no-op */ - assert_ret(r = sd_journal_next_skip(j, 5)); - assert_se(r == 0); - assert_ret(sd_journal_previous(j)); - assert_ret(r = sd_journal_next_skip(j, 5)); - assert_se(r == 1); - assert_ret(sd_journal_previous(j)); - assert_ret(sd_journal_previous(j)); - assert_ret(sd_journal_next(j)); - assert_ret(sd_journal_previous(j)); - assert_ret(sd_journal_previous(j)); - assert_ret(r = sd_journal_next_skip(j, 5)); - assert_se(r == 3); + assert_se(sd_journal_previous(j) == 0); + assert_se(sd_journal_next_skip(j, 4) == 4); + assert_se(sd_journal_next_skip(j, 5) == 5); + assert_se(sd_journal_next(j) == 0); + assert_se(sd_journal_next_skip(j, 5) == 0); + assert_se(sd_journal_previous(j) == 1); + assert_se(sd_journal_next_skip(j, 5) == 1); + assert_se(sd_journal_previous(j) == 1); + assert_se(sd_journal_previous(j) == 1); + assert_se(sd_journal_next(j) == 1); + assert_se(sd_journal_previous(j) == 1); + assert_se(sd_journal_previous(j) == 1); + assert_se(r = sd_journal_next_skip(j, 5) == 3); test_check_numbers_up(j, 9); sd_journal_close(j); diff --git a/src/libsystemd/sd-journal/journal-file.c b/src/libsystemd/sd-journal/journal-file.c index 3aa6985b37..0447bcde57 100644 --- a/src/libsystemd/sd-journal/journal-file.c +++ b/src/libsystemd/sd-journal/journal-file.c @@ -3343,6 +3343,10 @@ void journal_file_reset_location(JournalFile *f) { f->current_monotonic = 0; zero(f->current_boot_id); f->current_xor_hash = 0; + + /* Also reset the previous reading direction. Otherwise, next_beyond_location() may wrongly handle we + * already hit EOF. See issue #29216. */ + f->last_direction = _DIRECTION_INVALID; } void journal_file_save_location(JournalFile *f, Object *o, uint64_t offset) { @@ -3939,6 +3943,7 @@ int journal_file_open( MAX(MIN_COMPRESS_THRESHOLD, compress_threshold_bytes), .strict_order = FLAGS_SET(file_flags, JOURNAL_STRICT_ORDER), .newest_boot_id_prioq_idx = PRIOQ_IDX_NULL, + .last_direction = _DIRECTION_INVALID, }; if (fname) { diff --git a/src/libsystemd/sd-journal/journal-file.h b/src/libsystemd/sd-journal/journal-file.h index a4d8912aa8..b018fd8788 100644 --- a/src/libsystemd/sd-journal/journal-file.h +++ b/src/libsystemd/sd-journal/journal-file.h @@ -31,7 +31,8 @@ typedef struct JournalMetrics { typedef enum direction { DIRECTION_UP, - DIRECTION_DOWN + DIRECTION_DOWN, + _DIRECTION_INVALID = -EINVAL, } direction_t; typedef enum LocationType {