|
|
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 +-
|
|
|
de8967 |
src/journal/journalctl.c | 27 +++++++++++++++----
|
|
|
de8967 |
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 |
|