[systemd-devel] [PATCH] journalctl: Fix --list-boots and --boot

Jan Janssen medhefgo at web.de
Fri Aug 29 09:11:35 PDT 2014


For some reason, sd_journal_query_unique() and sd_journal_add_match() don't
work as they used to. There's a chance boots will be skipped; in my
case only 60 of 393 boots show up. Therefore, do sd_journal_query_unique() first
and then iterate over those to query their timespec.

https://bugs.freedesktop.org/show_bug.cgi?id=79380
---
 src/journal/journalctl.c | 124 ++++++++++++++++++++---------------------------
 1 file changed, 53 insertions(+), 71 deletions(-)

diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
index f3680d1..0aec5fb 100644
--- a/src/journal/journalctl.c
+++ b/src/journal/journalctl.c
@@ -804,33 +804,45 @@ static int boot_id_cmp(const void *a, const void *b) {
         return _a < _b ? -1 : (_a > _b ? 1 : 0);
 }
 
-static int list_boots(sd_journal *j) {
+static int get_boots(sd_journal *j, boot_id_t **boot_ids, unsigned int *count, boot_id_t *query_ref_boot_id) {
         int r;
+        boot_id_t *id;
         const void *data;
-        unsigned int count = 0;
-        int w, i;
         size_t length, allocated = 0;
-        boot_id_t *id;
-        _cleanup_free_ boot_id_t *all_ids = NULL;
+
+        assert(j);
+        assert(boot_ids);
+        assert(count);
 
         r = sd_journal_query_unique(j, "_BOOT_ID");
         if (r < 0)
                 return r;
 
+        *count = 0;
         SD_JOURNAL_FOREACH_UNIQUE(j, data, length) {
                 if (length < strlen("_BOOT_ID="))
                         continue;
 
-                if (!GREEDY_REALLOC(all_ids, allocated, count + 1))
+                if (!GREEDY_REALLOC(*boot_ids, allocated, *count + 1))
                         return log_oom();
 
-                id = &all_ids[count];
+                id = *boot_ids + *count;
 
                 r = sd_id128_from_string(((const char *)data) + strlen("_BOOT_ID="), &id->id);
                 if (r < 0)
                         continue;
 
-                r = sd_journal_add_match(j, data, length);
+                (*count)++;
+                id->first = id->last = 0;
+        }
+
+        for (id = *boot_ids; id < *boot_ids + *count; id++) {
+                char boot_id_str[9+32+1] = "_BOOT_ID=";
+
+                sd_journal_flush_matches(j);
+                sd_id128_to_string(id->id, boot_id_str + 9);
+
+                r = sd_journal_add_match(j, boot_id_str, strlen(boot_id_str));
                 if (r < 0)
                         return r;
 
@@ -839,35 +851,47 @@ static int list_boots(sd_journal *j) {
                         return r;
 
                 r = sd_journal_next(j);
-                if (r < 0)
+                if (r <= 0)
                         return r;
-                else if (r == 0)
-                        goto flush;
 
                 r = sd_journal_get_realtime_usec(j, &id->first);
                 if (r < 0)
                         return r;
 
+                if (query_ref_boot_id) {
+                        if (sd_id128_equal(id->id, query_ref_boot_id->id))
+                                *query_ref_boot_id = *id;
+                        continue;
+                }
+
                 r = sd_journal_seek_tail(j);
                 if (r < 0)
                         return r;
 
                 r = sd_journal_previous(j);
-                if (r < 0)
+                if (r <= 0)
                         return r;
-                else if (r == 0)
-                        goto flush;
 
                 r = sd_journal_get_realtime_usec(j, &id->last);
                 if (r < 0)
                         return r;
-
-                count++;
-        flush:
-                sd_journal_flush_matches(j);
         }
 
-        qsort_safe(all_ids, count, sizeof(boot_id_t), boot_id_cmp);
+        sd_journal_flush_matches(j);
+        qsort_safe(*boot_ids, *count, sizeof(boot_id_t), boot_id_cmp);
+
+        return 0;
+}
+
+static int list_boots(sd_journal *j) {
+        int r, w, i;
+        unsigned int count = 0;
+        boot_id_t *id;
+        _cleanup_free_ boot_id_t *all_ids = NULL;
+
+        r = get_boots(j, &all_ids, &count, NULL);
+        if (r < 0)
+                return r;
 
         /* numbers are one less, but we need an extra char for the sign */
         w = DECIMAL_STR_WIDTH(count - 1) + 1;
@@ -885,76 +909,34 @@ static int list_boots(sd_journal *j) {
         return 0;
 }
 
-static int get_relative_boot_id(sd_journal *j, sd_id128_t *boot_id, int relative) {
+static int get_boot_id_by_offset(sd_journal *j, sd_id128_t *boot_id, int offset) {
         int r;
-        const void *data;
         unsigned int count = 0;
-        size_t length, allocated = 0;
-        boot_id_t ref_boot_id = {SD_ID128_NULL}, *id;
+        boot_id_t ref_boot_id = {}, *id;
         _cleanup_free_ boot_id_t *all_ids = NULL;
 
         assert(j);
         assert(boot_id);
 
-        r = sd_journal_query_unique(j, "_BOOT_ID");
+        ref_boot_id.id = *boot_id;
+        r = get_boots(j, &all_ids, &count, &ref_boot_id);
         if (r < 0)
                 return r;
 
-        SD_JOURNAL_FOREACH_UNIQUE(j, data, length) {
-                if (length < strlen("_BOOT_ID="))
-                        continue;
-
-                if (!GREEDY_REALLOC(all_ids, allocated, count + 1))
-                        return log_oom();
-
-                id = &all_ids[count];
-
-                r = sd_id128_from_string(((const char *)data) + strlen("_BOOT_ID="), &id->id);
-                if (r < 0)
-                        continue;
-
-                r = sd_journal_add_match(j, data, length);
-                if (r < 0)
-                        return r;
-
-                r = sd_journal_seek_head(j);
-                if (r < 0)
-                        return r;
-
-                r = sd_journal_next(j);
-                if (r < 0)
-                        return r;
-                else if (r == 0)
-                        goto flush;
-
-                r = sd_journal_get_realtime_usec(j, &id->first);
-                if (r < 0)
-                        return r;
-
-                if (sd_id128_equal(id->id, *boot_id))
-                        ref_boot_id = *id;
-
-                count++;
-        flush:
-                sd_journal_flush_matches(j);
-        }
-
-        qsort_safe(all_ids, count, sizeof(boot_id_t), boot_id_cmp);
-
         if (sd_id128_equal(*boot_id, SD_ID128_NULL)) {
-                if (relative > (int) count || relative <= -(int)count)
+                if (offset > (int) count || offset <= -(int)count)
                         return -EADDRNOTAVAIL;
 
-                *boot_id = all_ids[(relative <= 0)*count + relative - 1].id;
+                *boot_id = all_ids[(offset <= 0)*count + offset - 1].id;
         } else {
                 id = bsearch(&ref_boot_id, all_ids, count, sizeof(boot_id_t), boot_id_cmp);
 
                 if (!id ||
-                    relative <= 0 ? (id - all_ids) + relative < 0 :
-                                    (id - all_ids) + relative >= (int) count)
+                    offset <= 0 ? (id - all_ids) + offset < 0 :
+                                    (id - all_ids) + offset >= (int) count)
                         return -EADDRNOTAVAIL;
 
-                *boot_id = (id + relative)->id;
+                *boot_id = (id + offset)->id;
         }
 
         return 0;
@@ -972,7 +954,7 @@ static int add_boot(sd_journal *j) {
         if (arg_boot_offset == 0 && sd_id128_equal(arg_boot_id, SD_ID128_NULL))
                 return add_match_this_boot(j, arg_machine);
 
-        r = get_relative_boot_id(j, &arg_boot_id, arg_boot_offset);
+        r = get_boot_id_by_offset(j, &arg_boot_id, arg_boot_offset);
         if (r < 0) {
                 if (sd_id128_equal(arg_boot_id, SD_ID128_NULL))
                         log_error("Failed to look up boot %+i: %s", arg_boot_offset, strerror(-r));
-- 
2.1.0



More information about the systemd-devel mailing list