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