mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-03-06 12:58:22 +03:00
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.
This commit is contained in:
parent
dcabda4155
commit
795ab08f78
@ -4027,7 +4027,8 @@ journalctl_SOURCES = \
|
||||
src/journal/journalctl.c
|
||||
|
||||
journalctl_LDADD = \
|
||||
libshared.la
|
||||
libshared.la \
|
||||
libudev-core.la
|
||||
|
||||
if HAVE_QRENCODE
|
||||
journalctl_SOURCES += \
|
||||
|
@ -69,6 +69,8 @@
|
||||
#include "strv.h"
|
||||
#include "syslog-util.h"
|
||||
#include "terminal-util.h"
|
||||
#include "udev.h"
|
||||
#include "udev-util.h"
|
||||
#include "unit-name.h"
|
||||
#include "user-util.h"
|
||||
|
||||
@ -145,6 +147,80 @@ typedef struct BootId {
|
||||
LIST_FIELDS(struct BootId, boot_list);
|
||||
} BootId;
|
||||
|
||||
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)
|
||||
@ -825,13 +901,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 (lstat(path, &st) < 0)
|
||||
return log_error_errno(errno, "Couldn't stat file: %m");
|
||||
@ -845,34 +920,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))
|
||||
(void) asprintf(&t, "_KERNEL_DEVICE=c%u:%u", major(st.st_rdev), minor(st.st_rdev));
|
||||
else if (S_ISBLK(st.st_mode))
|
||||
(void) asprintf(&t, "_KERNEL_DEVICE=b%u:%u", major(st.st_rdev), minor(st.st_rdev));
|
||||
else {
|
||||
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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user