dd65c9
From 9f7b08ba18ac3d4fd51e70d78d44b60ffb65411f Mon Sep 17 00:00:00 2001
de541a
From: Lennart Poettering <lennart@poettering.net>
de541a
Date: Mon, 2 Nov 2015 23:37:05 +0100
de541a
Subject: [PATCH] journalctl: when we fail to open a journal file, print why
de541a
de541a
When we enumerate journal files and encounter an invalid one, remember
de541a
which this, and show it to the user.
de541a
de541a
Note the possibly slightly surprising logic here: we store only one path
de541a
per error code. This means we show all error kinds but not every actual
de541a
error we encounter. This has the benefit of not requiring us to keep a
de541a
potentially unbounded list of errors with their sources around, but can
de541a
still provide a pretty complete overview on the errors we encountered.
de541a
de541a
Fixes #1669.
de541a
de541a
(cherry picked from commit 5768d2594940668506bb4cafa078f654cc20dc5a)
de541a
de541a
Resolves: #1465759
de541a
---
de541a
 src/journal/journal-internal.h |  2 +-
23b3cf
 src/journal/journalctl.c       | 27 +++++++++++++++----
23b3cf
 src/journal/sd-journal.c       | 49 +++++++++++++++++++++++++++-------
de541a
 3 files changed, 63 insertions(+), 15 deletions(-)
de541a
de541a
diff --git a/src/journal/journal-internal.h b/src/journal/journal-internal.h
Pablo Greco 48fc63
index 115d7776da..eb23ac28ad 100644
de541a
--- a/src/journal/journal-internal.h
de541a
+++ b/src/journal/journal-internal.h
de541a
@@ -123,7 +123,7 @@ struct sd_journal {
de541a
         Hashmap *directories_by_path;
de541a
         Hashmap *directories_by_wd;
de541a
 
de541a
-        Set *errors;
de541a
+        Hashmap *errors;
de541a
 };
de541a
 
de541a
 char *journal_make_match_string(sd_journal *j);
de541a
diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
Pablo Greco 48fc63
index 8c83797328..0be70764ef 100644
de541a
--- a/src/journal/journalctl.c
de541a
+++ b/src/journal/journalctl.c
de541a
@@ -1783,33 +1783,50 @@ static int access_check_var_log_journal(sd_journal *j) {
de541a
 static int access_check(sd_journal *j) {
de541a
         Iterator it;
de541a
         void *code;
de541a
+        char *path;
de541a
         int r = 0;
de541a
 
de541a
         assert(j);
de541a
 
de541a
-        if (set_isempty(j->errors)) {
de541a
+        if (hashmap_isempty(j->errors)) {
de541a
                 if (ordered_hashmap_isempty(j->files))
de541a
                         log_notice("No journal files were found.");
de541a
 
de541a
                 return 0;
de541a
         }
de541a
 
de541a
-        if (set_contains(j->errors, INT_TO_PTR(-EACCES))) {
de541a
+        if (hashmap_contains(j->errors, INT_TO_PTR(-EACCES))) {
de541a
                 (void) access_check_var_log_journal(j);
de541a
 
de541a
                 if (ordered_hashmap_isempty(j->files))
de541a
                         r = log_error_errno(EACCES, "No journal files were opened due to insufficient permissions.");
de541a
         }
de541a
 
de541a
-        SET_FOREACH(code, j->errors, it) {
de541a
+        HASHMAP_FOREACH_KEY(path, code, j->errors, it) {
de541a
                 int err;
de541a
 
de541a
                 err = abs(PTR_TO_INT(code));
de541a
 
de541a
-                if (err == EACCES)
de541a
+                switch (err) {
de541a
+                case EACCES:
de541a
                         continue;
de541a
 
de541a
-                log_warning_errno(err, "An error was encountered while opening journal files, ignoring: %m");
de541a
+                case ENODATA:
de541a
+                        log_warning_errno(err, "Journal file %s is truncated, ignoring file.", path);
de541a
+                        break;
de541a
+
de541a
+                case EPROTONOSUPPORT:
de541a
+                        log_warning_errno(err, "Journal file %s uses an unsupported feature, ignoring file.", path);
de541a
+                        break;
de541a
+
de541a
+                case EBADMSG:
de541a
+                        log_warning_errno(err, "Journal file %s corrupted, ignoring file.", path);
de541a
+                        break;
de541a
+
de541a
+                default:
de541a
+                        log_warning_errno(err, "An error was encountered while opening journal file %s, ignoring file.", path);
de541a
+                        break;
de541a
+                }
de541a
         }
de541a
 
de541a
         return r;
de541a
diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c
Pablo Greco 48fc63
index 9895d9608f..14b65cfedd 100644
de541a
--- a/src/journal/sd-journal.c
de541a
+++ b/src/journal/sd-journal.c
de541a
@@ -62,19 +62,46 @@ static bool journal_pid_changed(sd_journal *j) {
de541a
         return j->original_pid != getpid();
de541a
 }
de541a
 
de541a
-/* We return an error here only if we didn't manage to
de541a
-   memorize the real error. */
de541a
-static int set_put_error(sd_journal *j, int r) {
de541a
+static int journal_put_error(sd_journal *j, int r, const char *path) {
de541a
+        char *copy;
de541a
         int k;
de541a
 
de541a
+        /* Memorize an error we encountered, and store which
de541a
+         * file/directory it was generated from. Note that we store
de541a
+         * only *one* path per error code, as the error code is the
de541a
+         * key into the hashmap, and the path is the value. This means
de541a
+         * we keep track only of all error kinds, but not of all error
de541a
+         * locations. This has the benefit that the hashmap cannot
de541a
+         * grow beyond bounds.
de541a
+         *
de541a
+         * We return an error here only if we didn't manage to
de541a
+         * memorize the real error. */
de541a
+
de541a
         if (r >= 0)
de541a
                 return r;
de541a
 
de541a
-        k = set_ensure_allocated(&j->errors, NULL);
de541a
+        k = hashmap_ensure_allocated(&j->errors, NULL);
de541a
         if (k < 0)
de541a
                 return k;
de541a
 
de541a
-        return set_put(j->errors, INT_TO_PTR(r));
de541a
+        if (path) {
de541a
+                copy = strdup(path);
de541a
+                if (!copy)
de541a
+                        return -ENOMEM;
de541a
+        } else
de541a
+                copy = NULL;
de541a
+
de541a
+        k = hashmap_put(j->errors, INT_TO_PTR(r), copy);
de541a
+        if (k < 0) {
de541a
+                free(copy);
de541a
+
de541a
+                if (k == -EEXIST)
de541a
+                        return 0;
de541a
+
de541a
+                return k;
de541a
+        }
de541a
+
de541a
+        return 0;
de541a
 }
de541a
 
de541a
 static void detach_location(sd_journal *j) {
de541a
@@ -1234,7 +1261,7 @@ static int add_any_file(sd_journal *j, const char *path) {
de541a
         return 0;
de541a
 
de541a
 fail:
de541a
-        k = set_put_error(j, r);
de541a
+        k = journal_put_error(j, r, path);
de541a
         if (k < 0)
de541a
                 return k;
de541a
 
de541a
@@ -1396,7 +1423,7 @@ static int add_directory(sd_journal *j, const char *prefix, const char *dirname)
de541a
         return 0;
de541a
 
de541a
 fail:
de541a
-        k = set_put_error(j, r);
de541a
+        k = journal_put_error(j, r, path ?: dirname);
de541a
         if (k < 0)
de541a
                 return k;
de541a
 
de541a
@@ -1487,7 +1514,7 @@ static int add_root_directory(sd_journal *j, const char *p, bool missing_ok) {
de541a
         return 0;
de541a
 
de541a
 fail:
de541a
-        k = set_put_error(j, r);
de541a
+        k = journal_put_error(j, r, p);
de541a
         if (k < 0)
de541a
                 return k;
de541a
 
de541a
@@ -1732,6 +1759,7 @@ fail:
de541a
 _public_ void sd_journal_close(sd_journal *j) {
de541a
         Directory *d;
de541a
         JournalFile *f;
de541a
+        char *p;
de541a
 
de541a
         if (!j)
de541a
                 return;
de541a
@@ -1759,10 +1787,13 @@ _public_ void sd_journal_close(sd_journal *j) {
de541a
                 mmap_cache_unref(j->mmap);
de541a
         }
de541a
 
de541a
+        while ((p = hashmap_steal_first(j->errors)))
de541a
+                free(p);
de541a
+        hashmap_free(j->errors);
de541a
+
de541a
         free(j->path);
de541a
         free(j->prefix);
de541a
         free(j->unique_field);
de541a
-        set_free(j->errors);
de541a
         free(j);
de541a
 }
de541a