From: Yu Watanabe Date: Fri, 26 Apr 2024 02:27:12 +0000 (+0900) Subject: journalctl: fix support of --boot=ID±offset format X-Git-Tag: v256-rc2~50^2~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a4675155190d7c17dc0fa6be9134837f32ad519a;p=thirdparty%2Fsystemd.git journalctl: fix support of --boot=ID±offset format Fixes a regression introduced by e44f06065bf20e8d0e4adacff61350ebd36f299e. After the offending commit, if a boot ID suffixed with an offset is specified to --boot=, the boot ID was ignored. This fixes the issue. To fix the issue, this merges journal_find_boot_by_id() and journal_find_boot_by_offset(). --- diff --git a/src/journal/journalctl-util.c b/src/journal/journalctl-util.c index 2e7e652fba7..32cdaf83812 100644 --- a/src/journal/journalctl-util.c +++ b/src/journal/journalctl-util.c @@ -94,24 +94,26 @@ int journal_acquire_boot(sd_journal *j) { if (r < 0) return log_error_errno(r, "Failed to get boot ID%s%s: %m", isempty(arg_machine) ? "" : " of container ", strempty(arg_machine)); - } else if (sd_id128_is_null(arg_boot_id)) { - r = journal_find_boot_by_offset(j, arg_boot_offset, &arg_boot_id); + } else { + sd_id128_t boot_id; + + r = journal_find_boot(j, arg_boot_id, arg_boot_offset, &boot_id); if (r < 0) - return log_error_errno(r, "Failed to find journal entry from the specified boot offset (%+i): %m", + return log_error_errno(r, "Failed to find journal entry from the specified boot (%s%+i): %m", + sd_id128_is_null(arg_boot_id) ? "" : SD_ID128_TO_STRING(arg_boot_id), arg_boot_offset); if (r == 0) return log_error_errno(SYNTHETIC_ERRNO(ENODATA), - "No journal boot entry found from the specified boot offset (%+i).", + "No journal boot entry found from the specified boot (%s%+i).", + sd_id128_is_null(arg_boot_id) ? "" : SD_ID128_TO_STRING(arg_boot_id), arg_boot_offset); - } else { - r = journal_find_boot_by_id(j, arg_boot_id); - if (r < 0) - return log_error_errno(r, "Failed to find journal entry from the specified boot ID (%s): %m", - SD_ID128_TO_STRING(arg_boot_id)); - if (r == 0) - return log_error_errno(SYNTHETIC_ERRNO(ENODATA), - "No journal boot entry found from the specified boot ID (%s).", - SD_ID128_TO_STRING(arg_boot_id)); + + log_debug("Found boot %s for %s%+i", + SD_ID128_TO_STRING(boot_id), + sd_id128_is_null(arg_boot_id) ? "" : SD_ID128_TO_STRING(arg_boot_id), + arg_boot_offset); + + arg_boot_id = boot_id; } return 1; diff --git a/src/libsystemd/sd-journal/test-journal-interleaving.c b/src/libsystemd/sd-journal/test-journal-interleaving.c index ed1918d1038..6f438915355 100644 --- a/src/libsystemd/sd-journal/test-journal-interleaving.c +++ b/src/libsystemd/sd-journal/test-journal-interleaving.c @@ -459,7 +459,7 @@ TEST(skip) { static void test_boot_id_one(void (*setup)(void), size_t n_boots_expected) { char t[] = "/var/tmp/journal-boot-id-XXXXXX"; - sd_journal *j; + _cleanup_(sd_journal_closep) sd_journal *j = NULL; _cleanup_free_ BootId *boots = NULL; size_t n_boots; @@ -471,24 +471,25 @@ static void test_boot_id_one(void (*setup)(void), size_t n_boots_expected) { assert_se(journal_get_boots(j, &boots, &n_boots) >= 0); assert_se(boots); assert_se(n_boots == n_boots_expected); - sd_journal_close(j); - FOREACH_ARRAY(b, boots, n_boots) { - assert_ret(sd_journal_open_directory(&j, t, SD_JOURNAL_ASSUME_IMMUTABLE)); - assert_se(journal_find_boot_by_id(j, b->id) == 1); - sd_journal_close(j); - } - - for (int i = - (int) n_boots + 1; i <= (int) n_boots; i++) { + for (size_t i = 0; i < n_boots; i++) { sd_id128_t id; - assert_ret(sd_journal_open_directory(&j, t, SD_JOURNAL_ASSUME_IMMUTABLE)); - assert_se(journal_find_boot_by_offset(j, i, &id) == 1); - if (i <= 0) - assert_se(sd_id128_equal(id, boots[n_boots + i - 1].id)); - else - assert_se(sd_id128_equal(id, boots[i - 1].id)); - sd_journal_close(j); + /* positive offset */ + assert_se(journal_find_boot(j, SD_ID128_NULL, (int) (i + 1), &id) == 1); + assert_se(sd_id128_equal(id, boots[i].id)); + + /* negative offset */ + assert_se(journal_find_boot(j, SD_ID128_NULL, (int) (i + 1) - (int) n_boots, &id) == 1); + assert_se(sd_id128_equal(id, boots[i].id)); + + for (size_t k = 0; k < n_boots; k++) { + int offset = (int) k - (int) i; + + /* relative offset */ + assert_se(journal_find_boot(j, boots[i].id, offset, &id) == 1); + assert_se(sd_id128_equal(id, boots[k].id)); + } } test_done(t); diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c index be797afdf6c..069fcde4bfe 100644 --- a/src/shared/logs-show.c +++ b/src/shared/logs-show.c @@ -1909,37 +1909,9 @@ static int discover_next_boot( } } -int journal_find_boot_by_id(sd_journal *j, sd_id128_t boot_id) { - int r; - - assert(j); - assert(!sd_id128_is_null(boot_id)); - - sd_journal_flush_matches(j); - - r = add_match_boot_id(j, boot_id); - if (r < 0) - return r; - - r = sd_journal_seek_head(j); /* seek to oldest */ - if (r < 0) - return r; - - r = sd_journal_next(j); /* read the oldest entry */ - if (r < 0) - return r; - - /* At this point the read pointer is positioned at the oldest occurrence of the reference boot ID. - * After flushing the matches, one more invocation of _previous() will hence place us at the - * following entry, which must then have an older boot ID */ - - sd_journal_flush_matches(j); - return r > 0; -} - -int journal_find_boot_by_offset(sd_journal *j, int offset, sd_id128_t *ret) { +int journal_find_boot(sd_journal *j, sd_id128_t boot_id, int offset, sd_id128_t *ret) { bool advance_older; - int r; + int r, offset_start; assert(j); assert(ret); @@ -1950,21 +1922,50 @@ int journal_find_boot_by_offset(sd_journal *j, int offset, sd_id128_t *ret) { sd_journal_flush_matches(j); - if (advance_older) - r = sd_journal_seek_tail(j); /* seek to newest */ - else - r = sd_journal_seek_head(j); /* seek to oldest */ - if (r < 0) - return r; + if (!sd_id128_is_null(boot_id)) { + r = add_match_boot_id(j, boot_id); + if (r < 0) + return r; - /* No sd_journal_next()/_previous() here. - * - * At this point the read pointer is positioned after the newest/before the oldest entry in the whole - * journal. The next invocation of _previous()/_next() will hence position us at the newest/oldest - * entry we have. */ + if (advance_older) + r = sd_journal_seek_head(j); /* seek to oldest */ + else + r = sd_journal_seek_tail(j); /* seek to newest */ + if (r < 0) + return r; - sd_id128_t boot_id = SD_ID128_NULL; - for (int off = !advance_older; ; off += advance_older ? -1 : 1) { + r = sd_journal_step_one(j, advance_older); + if (r < 0) + return r; + if (r == 0) { + sd_journal_flush_matches(j); + *ret = SD_ID128_NULL; + return false; + } + if (offset == 0) { + /* If boot ID is specified without an offset, then let's short cut the loop below. */ + sd_journal_flush_matches(j); + *ret = boot_id; + return true; + } + + offset_start = advance_older ? -1 : 1; + } else { + if (advance_older) + r = sd_journal_seek_tail(j); /* seek to newest */ + else + r = sd_journal_seek_head(j); /* seek to oldest */ + if (r < 0) + return r; + + offset_start = advance_older ? 0 : 1; + } + + /* At this point the cursor is positioned at the newest/oldest entry of the reference boot ID if + * specified, or whole journal otherwise. The next invocation of _previous()/_next() will hence + * position us at the newest/oldest entry we have. */ + + for (int off = offset_start; ; off += advance_older ? -1 : 1) { BootId boot; r = discover_next_boot(j, boot_id, advance_older, &boot); @@ -1978,12 +1979,11 @@ int journal_find_boot_by_offset(sd_journal *j, int offset, sd_id128_t *ret) { boot_id = boot.id; log_debug("Found boot ID %s by offset %i", SD_ID128_TO_STRING(boot_id), off); - if (off == offset) - break; + if (off == offset) { + *ret = boot_id; + return true; + } } - - *ret = boot_id; - return true; } int journal_get_boots(sd_journal *j, BootId **ret_boots, size_t *ret_n_boots) { diff --git a/src/shared/logs-show.h b/src/shared/logs-show.h index da1bbe04207..b1b42bdae76 100644 --- a/src/shared/logs-show.h +++ b/src/shared/logs-show.h @@ -70,6 +70,5 @@ void json_escape( size_t l, OutputFlags flags); -int journal_find_boot_by_id(sd_journal *j, sd_id128_t boot_id); -int journal_find_boot_by_offset(sd_journal *j, int offset, sd_id128_t *ret); +int journal_find_boot(sd_journal *j, sd_id128_t boot_id, int offset, sd_id128_t *ret); int journal_get_boots(sd_journal *j, BootId **ret_boots, size_t *ret_n_boots);