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