From a44a692476eb2458a44a41e70ea7f44b6463b3e9 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: May 15 2023 09:10:17 +0000 Subject: sd-journal: split out generic_array_bisect_one() from generic_array_bisect() This also makes journal corruption always handled gracefully, and drop potentially unsatisfied assertion on corrupted journal. Fixes #27533. --- diff --git a/src/libsystemd/sd-journal/journal-file.c b/src/libsystemd/sd-journal/journal-file.c index 4580b07..aa50bd3 100644 --- a/src/libsystemd/sd-journal/journal-file.c +++ b/src/libsystemd/sd-journal/journal-file.c @@ -2592,6 +2592,59 @@ enum { TEST_RIGHT }; +static int generic_array_bisect_one( + JournalFile *f, + uint64_t a, /* offset of entry array object. */ + uint64_t i, /* index of the entry item we will test. */ + uint64_t needle, + int (*test_object)(JournalFile *f, uint64_t p, uint64_t needle), + direction_t direction, + uint64_t *left, + uint64_t *right, + uint64_t *ret_offset) { + + Object *array; + uint64_t p; + int r; + + assert(f); + assert(test_object); + assert(left); + assert(right); + assert(*left <= i); + assert(i <= *right); + + r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &array); + if (r < 0) + return r; + + p = journal_file_entry_array_item(f, array, i); + if (p <= 0) + r = -EBADMSG; + else + r = test_object(f, p, needle); + if (IN_SET(r, -EBADMSG, -EADDRNOTAVAIL)) { + log_debug_errno(r, "Encountered invalid entry while bisecting, cutting algorithm short."); + *right = i; + return -ENOANO; /* recognizable error */ + } + if (r < 0) + return r; + + if (r == TEST_FOUND) + r = direction == DIRECTION_DOWN ? TEST_RIGHT : TEST_LEFT; + + if (r == TEST_RIGHT) + *right = i; + else + *left = i + 1; + + if (ret_offset) + *ret_offset = p; + + return r; +} + static int generic_array_bisect( JournalFile *f, uint64_t first, @@ -2654,7 +2707,7 @@ static int generic_array_bisect( } while (a > 0) { - uint64_t left, right, k, lp; + uint64_t left = 0, right, k, lp; r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &array); if (r < 0) @@ -2665,76 +2718,30 @@ static int generic_array_bisect( if (right <= 0) return 0; - i = right - 1; - lp = p = journal_file_entry_array_item(f, array, i); - if (p <= 0) - r = -EBADMSG; - else - r = test_object(f, p, needle); - if (IN_SET(r, -EBADMSG, -EADDRNOTAVAIL)) { - log_debug_errno(r, "Encountered invalid entry while bisecting, cutting algorithm short. (1)"); - n = i; + right--; + r = generic_array_bisect_one(f, a, right, needle, test_object, direction, &left, &right, &lp); + if (r == -ENOANO) { + n = right; continue; } if (r < 0) return r; - if (r == TEST_FOUND) - r = direction == DIRECTION_DOWN ? TEST_RIGHT : TEST_LEFT; - if (r == TEST_RIGHT) { - left = 0; - right -= 1; - - if (last_index != UINT64_MAX) { - assert(last_index <= right); - - /* If we cached the last index we - * looked at, let's try to not to jump - * too wildly around and see if we can - * limit the range to look at early to - * the immediate neighbors of the last - * index we looked at. */ - - if (last_index > 0) { - uint64_t x = last_index - 1; - - p = journal_file_entry_array_item(f, array, x); - if (p <= 0) - return -EBADMSG; - - r = test_object(f, p, needle); - if (r < 0) - return r; - - if (r == TEST_FOUND) - r = direction == DIRECTION_DOWN ? TEST_RIGHT : TEST_LEFT; + /* If we cached the last index we looked at, let's try to not to jump too wildly + * around and see if we can limit the range to look at early to the immediate + * neighbors of the last index we looked at. */ - if (r == TEST_RIGHT) - right = x; - else - left = x + 1; - } - - if (last_index < right) { - uint64_t y = last_index + 1; - - p = journal_file_entry_array_item(f, array, y); - if (p <= 0) - return -EBADMSG; - - r = test_object(f, p, needle); - if (r < 0) - return r; - - if (r == TEST_FOUND) - r = direction == DIRECTION_DOWN ? TEST_RIGHT : TEST_LEFT; + if (last_index > 0 && last_index - 1 < right) { + r = generic_array_bisect_one(f, a, last_index - 1, needle, test_object, direction, &left, &right, NULL); + if (r < 0 && r != -ENOANO) + return r; + } - if (r == TEST_RIGHT) - right = y; - else - left = y + 1; - } + if (last_index < right) { + r = generic_array_bisect_one(f, a, last_index + 1, needle, test_object, direction, &left, &right, NULL); + if (r < 0 && r != -ENOANO) + return r; } for (;;) { @@ -2749,26 +2756,9 @@ static int generic_array_bisect( assert(left < right); i = (left + right) / 2; - p = journal_file_entry_array_item(f, array, i); - if (p <= 0) - r = -EBADMSG; - else - r = test_object(f, p, needle); - if (IN_SET(r, -EBADMSG, -EADDRNOTAVAIL)) { - log_debug_errno(r, "Encountered invalid entry while bisecting, cutting algorithm short. (2)"); - right = n = i; - continue; - } - if (r < 0) + r = generic_array_bisect_one(f, a, i, needle, test_object, direction, &left, &right, NULL); + if (r < 0 && r != -ENOANO) return r; - - if (r == TEST_FOUND) - r = direction == DIRECTION_DOWN ? TEST_RIGHT : TEST_LEFT; - - if (r == TEST_RIGHT) - right = i; - else - left = i + 1; } }