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.
206 lines
8.2 KiB
206 lines
8.2 KiB
From 1c33de9e1370bc56e10f3b5306e27c8aa6a18873 Mon Sep 17 00:00:00 2001 |
|
From: Michal Sekletar <msekleta@redhat.com> |
|
Date: Mon, 1 Feb 2016 10:44:58 +0100 |
|
Subject: [PATCH] journalctl: make "journalctl /dev/sda" work |
|
|
|
Currently when journalctl is called with path to block device node we |
|
add following match _KERNEL_DEVICE=b$MAJOR:$MINOR. |
|
|
|
That is not sufficient to actually obtain logs about the disk because |
|
dev_printk() kernel helper puts to /dev/kmsg information about the |
|
device in following format, +$SUBSYSTEM:$ADDRESS, |
|
e.g. "+pci:pci:0000:00:14.0". |
|
|
|
Now we will walk upward the syspath and add match for every device in |
|
format produced by dev_printk() as well as match for its device node if |
|
it exists. |
|
|
|
Cherry-picked from: 795ab08f783e78e85f1493879f13ac44cb113b00 |
|
Resolves: #947636 |
|
--- |
|
Makefile.am | 3 +- |
|
src/journal/journalctl.c | 118 +++++++++++++++++++++++++++++++-------- |
|
2 files changed, 97 insertions(+), 24 deletions(-) |
|
|
|
diff --git a/Makefile.am b/Makefile.am |
|
index 2645f66bc1..255937643e 100644 |
|
--- a/Makefile.am |
|
+++ b/Makefile.am |
|
@@ -4245,7 +4245,8 @@ journalctl_LDADD = \ |
|
libsystemd-journal-internal.la \ |
|
libsystemd-internal.la \ |
|
libsystemd-logs.la \ |
|
- libsystemd-shared.la |
|
+ libsystemd-shared.la \ |
|
+ libudev-core.la |
|
|
|
if HAVE_ACL |
|
journalctl_LDADD += \ |
|
diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c |
|
index 836d7d2141..3db1cd24ef 100644 |
|
--- a/src/journal/journalctl.c |
|
+++ b/src/journal/journalctl.c |
|
@@ -63,6 +63,8 @@ |
|
#include "mkdir.h" |
|
#include "bus-util.h" |
|
#include "bus-error.h" |
|
+#include "udev.h" |
|
+#include "udev-util.h" |
|
|
|
#define DEFAULT_FSS_INTERVAL_USEC (15*USEC_PER_MINUTE) |
|
|
|
@@ -134,6 +136,80 @@ typedef struct boot_id_t { |
|
LIST_FIELDS(struct boot_id_t, boot_list); |
|
} boot_id_t; |
|
|
|
+static int add_matches_for_device(sd_journal *j, const char *devpath) { |
|
+ int r; |
|
+ _cleanup_udev_unref_ struct udev *udev = NULL; |
|
+ _cleanup_udev_device_unref_ struct udev_device *device = NULL; |
|
+ struct udev_device *d = NULL; |
|
+ struct stat st; |
|
+ |
|
+ assert(j); |
|
+ assert(devpath); |
|
+ |
|
+ if (!path_startswith(devpath, "/dev/")) { |
|
+ log_error("Devpath does not start with /dev/"); |
|
+ return -EINVAL; |
|
+ } |
|
+ |
|
+ udev = udev_new(); |
|
+ if (!udev) |
|
+ return log_oom(); |
|
+ |
|
+ r = stat(devpath, &st); |
|
+ if (r < 0) |
|
+ log_error_errno(errno, "Couldn't stat file: %m"); |
|
+ |
|
+ d = device = udev_device_new_from_devnum(udev, S_ISBLK(st.st_mode) ? 'b' : 'c', st.st_rdev); |
|
+ if (!device) |
|
+ return log_error_errno(errno, "Failed to get udev device from devnum %u:%u: %m", major(st.st_rdev), minor(st.st_rdev)); |
|
+ |
|
+ while (d) { |
|
+ _cleanup_free_ char *match = NULL; |
|
+ const char *subsys, *sysname, *devnode; |
|
+ |
|
+ subsys = udev_device_get_subsystem(d); |
|
+ if (!subsys) { |
|
+ d = udev_device_get_parent(d); |
|
+ continue; |
|
+ } |
|
+ |
|
+ sysname = udev_device_get_sysname(d); |
|
+ if (!sysname) { |
|
+ d = udev_device_get_parent(d); |
|
+ continue; |
|
+ } |
|
+ |
|
+ match = strjoin("_KERNEL_DEVICE=+", subsys, ":", sysname, NULL); |
|
+ if (!match) |
|
+ return log_oom(); |
|
+ |
|
+ r = sd_journal_add_match(j, match, 0); |
|
+ if (r < 0) |
|
+ return log_error_errno(r, "Failed to add match: %m"); |
|
+ |
|
+ devnode = udev_device_get_devnode(d); |
|
+ if (devnode) { |
|
+ _cleanup_free_ char *match1 = NULL; |
|
+ |
|
+ r = stat(devnode, &st); |
|
+ if (r < 0) |
|
+ return log_error_errno(r, "Failed to stat() device node \"%s\": %m", devnode); |
|
+ |
|
+ r = asprintf(&match1, "_KERNEL_DEVICE=%c%u:%u", S_ISBLK(st.st_mode) ? 'b' : 'c', major(st.st_rdev), minor(st.st_rdev)); |
|
+ if (r < 0) |
|
+ return log_oom(); |
|
+ |
|
+ r = sd_journal_add_match(j, match1, 0); |
|
+ if (r < 0) |
|
+ return log_error_errno(r, "Failed to add match: %m"); |
|
+ } |
|
+ |
|
+ d = udev_device_get_parent(d); |
|
+ } |
|
+ |
|
+ return 0; |
|
+} |
|
+ |
|
static void pager_open_if_enabled(void) { |
|
|
|
if (arg_no_pager) |
|
@@ -788,13 +864,12 @@ static int add_matches(sd_journal *j, char **args) { |
|
have_term = false; |
|
|
|
} else if (path_is_absolute(*i)) { |
|
- _cleanup_free_ char *p, *t = NULL, *t2 = NULL; |
|
+ _cleanup_free_ char *p, *t = NULL, *t2 = NULL, *interpreter = NULL; |
|
const char *path; |
|
- _cleanup_free_ char *interpreter = NULL; |
|
struct stat st; |
|
|
|
p = canonicalize_file_name(*i); |
|
- path = p ? p : *i; |
|
+ path = p ?: *i; |
|
|
|
if (stat(path, &st) < 0) |
|
return log_error_errno(errno, "Couldn't stat file: %m"); |
|
@@ -808,40 +883,37 @@ static int add_matches(sd_journal *j, char **args) { |
|
return log_oom(); |
|
|
|
t = strappend("_COMM=", comm); |
|
+ if (!t) |
|
+ return log_oom(); |
|
|
|
/* Append _EXE only if the interpreter is not a link. |
|
Otherwise, it might be outdated often. */ |
|
- if (lstat(interpreter, &st) == 0 && |
|
- !S_ISLNK(st.st_mode)) { |
|
+ if (lstat(interpreter, &st) == 0 && !S_ISLNK(st.st_mode)) { |
|
t2 = strappend("_EXE=", interpreter); |
|
if (!t2) |
|
return log_oom(); |
|
} |
|
- } else |
|
+ } else { |
|
t = strappend("_EXE=", path); |
|
- } else if (S_ISCHR(st.st_mode)) { |
|
- if (asprintf(&t, "_KERNEL_DEVICE=c%u:%u", |
|
- major(st.st_rdev), |
|
- minor(st.st_rdev)) < 0) |
|
- return -ENOMEM; |
|
- } else if (S_ISBLK(st.st_mode)) { |
|
- if (asprintf(&t, "_KERNEL_DEVICE=b%u:%u", |
|
- major(st.st_rdev), |
|
- minor(st.st_rdev)) < 0) |
|
- return -ENOMEM; |
|
+ if (!t) |
|
+ return log_oom(); |
|
+ } |
|
+ |
|
+ r = sd_journal_add_match(j, t, 0); |
|
+ |
|
+ if (r >=0 && t2) |
|
+ r = sd_journal_add_match(j, t2, 0); |
|
+ |
|
+ } else if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) { |
|
+ r = add_matches_for_device(j, path); |
|
+ if (r < 0) |
|
+ return r; |
|
} else { |
|
log_error("File is neither a device node, nor regular file, nor executable: %s", *i); |
|
return -EINVAL; |
|
} |
|
|
|
- if (!t) |
|
- return log_oom(); |
|
- |
|
- r = sd_journal_add_match(j, t, 0); |
|
- if (t2) |
|
- r = sd_journal_add_match(j, t2, 0); |
|
have_term = true; |
|
- |
|
} else { |
|
r = sd_journal_add_match(j, *i, 0); |
|
have_term = true;
|
|
|