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

Zbigniew Jędrzejewski-Szmek zbyszek at in.waw.pl
Sat Aug 30 14:46:12 PDT 2014


On Fri, Aug 29, 2014 at 06:11:35PM +0200, Jan Janssen wrote:
> 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.
We should fix the underlying problem, since query_unique and add_match weren't
supposed to change at all. Looking at the journal client code has been on my
TODO list for a long while...

Zbyszek

> > 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
> 
> _______________________________________________
> systemd-devel mailing list
> systemd-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/systemd-devel
> 


More information about the systemd-devel mailing list