|
|
6f381c |
From 5ac15c7dc49476e7cd7cc3a4b507282c9f78d528 Mon Sep 17 00:00:00 2001
|
|
|
6f381c |
From: Eric DeVolder <eric.devolder@oracle.com>
|
|
|
6f381c |
Date: Mon, 21 Nov 2022 11:27:27 -0500
|
|
|
6f381c |
Subject: [PATCH] pstore: fixes for dmesg.txt reconstruction
|
|
|
6f381c |
|
|
|
6f381c |
This patch fixes problems with the re-assembly of the dmesg
|
|
|
6f381c |
from the records stored in pstore.
|
|
|
6f381c |
|
|
|
6f381c |
The current code simply ignores the last 6 characters of the
|
|
|
6f381c |
file name to form a base record id, which then groups any
|
|
|
6f381c |
pstore files with this base id into the reconstructed dmesg.txt.
|
|
|
6f381c |
This approach fails when the following oops generated the
|
|
|
6f381c |
following in pstore:
|
|
|
6f381c |
|
|
|
6f381c |
-rw-------. 1 root root 1808 Oct 27 22:07 dmesg-efi-166692286101001
|
|
|
6f381c |
-rw-------. 1 root root 1341 Oct 27 22:07 dmesg-efi-166692286101002
|
|
|
6f381c |
-rw-------. 1 root root 1812 Oct 27 22:07 dmesg-efi-166692286102001
|
|
|
6f381c |
-rw-------. 1 root root 1820 Oct 27 22:07 dmesg-efi-166692286102002
|
|
|
6f381c |
-rw-------. 1 root root 1807 Oct 27 22:07 dmesg-efi-166692286103001
|
|
|
6f381c |
-rw-------. 1 root root 1791 Oct 27 22:07 dmesg-efi-166692286103002
|
|
|
6f381c |
-rw-------. 1 root root 1773 Oct 27 22:07 dmesg-efi-166692286104001
|
|
|
6f381c |
-rw-------. 1 root root 1801 Oct 27 22:07 dmesg-efi-166692286104002
|
|
|
6f381c |
-rw-------. 1 root root 1821 Oct 27 22:07 dmesg-efi-166692286105001
|
|
|
6f381c |
-rw-------. 1 root root 1809 Oct 27 22:07 dmesg-efi-166692286105002
|
|
|
6f381c |
-rw-------. 1 root root 1804 Oct 27 22:07 dmesg-efi-166692286106001
|
|
|
6f381c |
-rw-------. 1 root root 1817 Oct 27 22:07 dmesg-efi-166692286106002
|
|
|
6f381c |
-rw-------. 1 root root 1792 Oct 27 22:07 dmesg-efi-166692286107001
|
|
|
6f381c |
-rw-------. 1 root root 1810 Oct 27 22:07 dmesg-efi-166692286107002
|
|
|
6f381c |
-rw-------. 1 root root 1717 Oct 27 22:07 dmesg-efi-166692286108001
|
|
|
6f381c |
-rw-------. 1 root root 1808 Oct 27 22:07 dmesg-efi-166692286108002
|
|
|
6f381c |
-rw-------. 1 root root 1764 Oct 27 22:07 dmesg-efi-166692286109001
|
|
|
6f381c |
-rw-------. 1 root root 1765 Oct 27 22:07 dmesg-efi-166692286109002
|
|
|
6f381c |
-rw-------. 1 root root 1796 Oct 27 22:07 dmesg-efi-166692286110001
|
|
|
6f381c |
-rw-------. 1 root root 1816 Oct 27 22:07 dmesg-efi-166692286110002
|
|
|
6f381c |
-rw-------. 1 root root 1793 Oct 27 22:07 dmesg-efi-166692286111001
|
|
|
6f381c |
-rw-------. 1 root root 1751 Oct 27 22:07 dmesg-efi-166692286111002
|
|
|
6f381c |
-rw-------. 1 root root 1813 Oct 27 22:07 dmesg-efi-166692286112001
|
|
|
6f381c |
-rw-------. 1 root root 1786 Oct 27 22:07 dmesg-efi-166692286112002
|
|
|
6f381c |
-rw-------. 1 root root 1754 Oct 27 22:07 dmesg-efi-166692286113001
|
|
|
6f381c |
-rw-------. 1 root root 1752 Oct 27 22:07 dmesg-efi-166692286113002
|
|
|
6f381c |
-rw-------. 1 root root 1803 Oct 27 22:07 dmesg-efi-166692286114001
|
|
|
6f381c |
-rw-------. 1 root root 1759 Oct 27 22:07 dmesg-efi-166692286114002
|
|
|
6f381c |
-rw-------. 1 root root 1805 Oct 27 22:07 dmesg-efi-166692286115001
|
|
|
6f381c |
-rw-------. 1 root root 1787 Oct 27 22:07 dmesg-efi-166692286115002
|
|
|
6f381c |
-rw-------. 1 root root 1815 Oct 27 22:07 dmesg-efi-166692286116001
|
|
|
6f381c |
-rw-------. 1 root root 1771 Oct 27 22:07 dmesg-efi-166692286116002
|
|
|
6f381c |
-rw-------. 1 root root 1816 Oct 27 22:07 dmesg-efi-166692286117002
|
|
|
6f381c |
-rw-------. 1 root root 1388 Oct 27 22:07 dmesg-efi-166692286701003
|
|
|
6f381c |
-rw-------. 1 root root 1824 Oct 27 22:07 dmesg-efi-166692286702003
|
|
|
6f381c |
-rw-------. 1 root root 1795 Oct 27 22:07 dmesg-efi-166692286703003
|
|
|
6f381c |
-rw-------. 1 root root 1805 Oct 27 22:07 dmesg-efi-166692286704003
|
|
|
6f381c |
-rw-------. 1 root root 1813 Oct 27 22:07 dmesg-efi-166692286705003
|
|
|
6f381c |
-rw-------. 1 root root 1821 Oct 27 22:07 dmesg-efi-166692286706003
|
|
|
6f381c |
-rw-------. 1 root root 1814 Oct 27 22:07 dmesg-efi-166692286707003
|
|
|
6f381c |
-rw-------. 1 root root 1812 Oct 27 22:07 dmesg-efi-166692286708003
|
|
|
6f381c |
-rw-------. 1 root root 1769 Oct 27 22:07 dmesg-efi-166692286709003
|
|
|
6f381c |
-rw-------. 1 root root 1820 Oct 27 22:07 dmesg-efi-166692286710003
|
|
|
6f381c |
-rw-------. 1 root root 1755 Oct 27 22:07 dmesg-efi-166692286711003
|
|
|
6f381c |
-rw-------. 1 root root 1790 Oct 27 22:07 dmesg-efi-166692286712003
|
|
|
6f381c |
-rw-------. 1 root root 1756 Oct 27 22:07 dmesg-efi-166692286713003
|
|
|
6f381c |
-rw-------. 1 root root 1763 Oct 27 22:07 dmesg-efi-166692286714003
|
|
|
6f381c |
-rw-------. 1 root root 1791 Oct 27 22:07 dmesg-efi-166692286715003
|
|
|
6f381c |
-rw-------. 1 root root 1775 Oct 27 22:07 dmesg-efi-166692286716003
|
|
|
6f381c |
-rw-------. 1 root root 1820 Oct 27 22:07 dmesg-efi-166692286717003
|
|
|
6f381c |
|
|
|
6f381c |
The "reconstructed" dmesg.txt that resulted from the above contained
|
|
|
6f381c |
the following (ignoring actual contents, just providing the Part info):
|
|
|
6f381c |
|
|
|
6f381c |
Emergency#3 Part17
|
|
|
6f381c |
Emergency#3 Part16
|
|
|
6f381c |
Emergency#3 Part15
|
|
|
6f381c |
Emergency#3 Part14
|
|
|
6f381c |
Emergency#3 Part13
|
|
|
6f381c |
Emergency#3 Part12
|
|
|
6f381c |
Emergency#3 Part11
|
|
|
6f381c |
Emergency#3 Part10
|
|
|
6f381c |
Emergency#3 Part9
|
|
|
6f381c |
Emergency#3 Part8
|
|
|
6f381c |
Emergency#3 Part7
|
|
|
6f381c |
Emergency#3 Part6
|
|
|
6f381c |
Emergency#3 Part5
|
|
|
6f381c |
Emergency#3 Part4
|
|
|
6f381c |
Emergency#3 Part3
|
|
|
6f381c |
Emergency#3 Part2
|
|
|
6f381c |
Emergency#3 Part1
|
|
|
6f381c |
Panic#2 Part17
|
|
|
6f381c |
Panic#2 Part16
|
|
|
6f381c |
Oops#1 Part16
|
|
|
6f381c |
Panic#2 Part15
|
|
|
6f381c |
Oops#1 Part15
|
|
|
6f381c |
Panic#2 Part14
|
|
|
6f381c |
Oops#1 Part14
|
|
|
6f381c |
Panic#2 Part13
|
|
|
6f381c |
Oops#1 Part13
|
|
|
6f381c |
Panic#2 Part12
|
|
|
6f381c |
Oops#1 Part12
|
|
|
6f381c |
Panic#2 Part11
|
|
|
6f381c |
Oops#1 Part11
|
|
|
6f381c |
Panic#2 Part10
|
|
|
6f381c |
Oops#1 Part10
|
|
|
6f381c |
Panic#2 Part9
|
|
|
6f381c |
Oops#1 Part9
|
|
|
6f381c |
Panic#2 Part8
|
|
|
6f381c |
Oops#1 Part8
|
|
|
6f381c |
Panic#2 Part7
|
|
|
6f381c |
Oops#1 Part7
|
|
|
6f381c |
Panic#2 Part6
|
|
|
6f381c |
Oops#1 Part6
|
|
|
6f381c |
Panic#2 Part5
|
|
|
6f381c |
Oops#1 Part5
|
|
|
6f381c |
Panic#2 Part4
|
|
|
6f381c |
Oops#1 Part4
|
|
|
6f381c |
Panic#2 Part3
|
|
|
6f381c |
Oops#1 Part3
|
|
|
6f381c |
Panic#2 Part2
|
|
|
6f381c |
Oops#1 Part2
|
|
|
6f381c |
Panic#2 Part1
|
|
|
6f381c |
Oops#1 Part1
|
|
|
6f381c |
|
|
|
6f381c |
The above is a interleaved mess of three dmesg dumps.
|
|
|
6f381c |
|
|
|
6f381c |
This patch fixes the above problems, and simplifies the dmesg
|
|
|
6f381c |
reconstruction process. The code now distinguishes between
|
|
|
6f381c |
records on EFI vs ERST, which have differently formatted
|
|
|
6f381c |
record identifiers. Using knowledge of the format of the
|
|
|
6f381c |
record ids allows vastly improved reconstruction process.
|
|
|
6f381c |
|
|
|
6f381c |
With this change in place, the above pstore records now
|
|
|
6f381c |
result in the following:
|
|
|
6f381c |
|
|
|
6f381c |
# ls -alR /var/lib/systemd/pstore
|
|
|
6f381c |
1666922861:
|
|
|
6f381c |
total 8
|
|
|
6f381c |
drwxr-xr-x. 4 root root 28 Nov 18 14:58 .
|
|
|
6f381c |
drwxr-xr-x. 7 root root 144 Nov 18 14:58 ..
|
|
|
6f381c |
drwxr-xr-x. 2 root root 4096 Nov 18 14:58 001
|
|
|
6f381c |
drwxr-xr-x. 2 root root 4096 Nov 18 14:58 002
|
|
|
6f381c |
|
|
|
6f381c |
1666922861/001:
|
|
|
6f381c |
total 100
|
|
|
6f381c |
drwxr-xr-x. 2 root root 4096 Nov 18 14:58 .
|
|
|
6f381c |
drwxr-xr-x. 4 root root 28 Nov 18 14:58 ..
|
|
|
6f381c |
-rw-------. 1 root root 1808 Oct 27 22:07 dmesg-efi-166692286101001
|
|
|
6f381c |
-rw-------. 1 root root 1812 Oct 27 22:07 dmesg-efi-166692286102001
|
|
|
6f381c |
-rw-------. 1 root root 1807 Oct 27 22:07 dmesg-efi-166692286103001
|
|
|
6f381c |
-rw-------. 1 root root 1773 Oct 27 22:07 dmesg-efi-166692286104001
|
|
|
6f381c |
-rw-------. 1 root root 1821 Oct 27 22:07 dmesg-efi-166692286105001
|
|
|
6f381c |
-rw-------. 1 root root 1804 Oct 27 22:07 dmesg-efi-166692286106001
|
|
|
6f381c |
-rw-------. 1 root root 1792 Oct 27 22:07 dmesg-efi-166692286107001
|
|
|
6f381c |
-rw-------. 1 root root 1717 Oct 27 22:07 dmesg-efi-166692286108001
|
|
|
6f381c |
-rw-------. 1 root root 1764 Oct 27 22:07 dmesg-efi-166692286109001
|
|
|
6f381c |
-rw-------. 1 root root 1796 Oct 27 22:07 dmesg-efi-166692286110001
|
|
|
6f381c |
-rw-------. 1 root root 1793 Oct 27 22:07 dmesg-efi-166692286111001
|
|
|
6f381c |
-rw-------. 1 root root 1813 Oct 27 22:07 dmesg-efi-166692286112001
|
|
|
6f381c |
-rw-------. 1 root root 1754 Oct 27 22:07 dmesg-efi-166692286113001
|
|
|
6f381c |
-rw-------. 1 root root 1803 Oct 27 22:07 dmesg-efi-166692286114001
|
|
|
6f381c |
-rw-------. 1 root root 1805 Oct 27 22:07 dmesg-efi-166692286115001
|
|
|
6f381c |
-rw-------. 1 root root 1815 Oct 27 22:07 dmesg-efi-166692286116001
|
|
|
6f381c |
-rw-r-----. 1 root root 28677 Nov 18 14:58 dmesg.txt
|
|
|
6f381c |
|
|
|
6f381c |
1666922861/002:
|
|
|
6f381c |
total 104
|
|
|
6f381c |
drwxr-xr-x. 2 root root 4096 Nov 18 14:58 .
|
|
|
6f381c |
drwxr-xr-x. 4 root root 28 Nov 18 14:58 ..
|
|
|
6f381c |
-rw-------. 1 root root 1341 Oct 27 22:07 dmesg-efi-166692286101002
|
|
|
6f381c |
-rw-------. 1 root root 1820 Oct 27 22:07 dmesg-efi-166692286102002
|
|
|
6f381c |
-rw-------. 1 root root 1791 Oct 27 22:07 dmesg-efi-166692286103002
|
|
|
6f381c |
-rw-------. 1 root root 1801 Oct 27 22:07 dmesg-efi-166692286104002
|
|
|
6f381c |
-rw-------. 1 root root 1809 Oct 27 22:07 dmesg-efi-166692286105002
|
|
|
6f381c |
-rw-------. 1 root root 1817 Oct 27 22:07 dmesg-efi-166692286106002
|
|
|
6f381c |
-rw-------. 1 root root 1810 Oct 27 22:07 dmesg-efi-166692286107002
|
|
|
6f381c |
-rw-------. 1 root root 1808 Oct 27 22:07 dmesg-efi-166692286108002
|
|
|
6f381c |
-rw-------. 1 root root 1765 Oct 27 22:07 dmesg-efi-166692286109002
|
|
|
6f381c |
-rw-------. 1 root root 1816 Oct 27 22:07 dmesg-efi-166692286110002
|
|
|
6f381c |
-rw-------. 1 root root 1751 Oct 27 22:07 dmesg-efi-166692286111002
|
|
|
6f381c |
-rw-------. 1 root root 1786 Oct 27 22:07 dmesg-efi-166692286112002
|
|
|
6f381c |
-rw-------. 1 root root 1752 Oct 27 22:07 dmesg-efi-166692286113002
|
|
|
6f381c |
-rw-------. 1 root root 1759 Oct 27 22:07 dmesg-efi-166692286114002
|
|
|
6f381c |
-rw-------. 1 root root 1787 Oct 27 22:07 dmesg-efi-166692286115002
|
|
|
6f381c |
-rw-------. 1 root root 1771 Oct 27 22:07 dmesg-efi-166692286116002
|
|
|
6f381c |
-rw-------. 1 root root 1816 Oct 27 22:07 dmesg-efi-166692286117002
|
|
|
6f381c |
-rw-r-----. 1 root root 30000 Nov 18 14:58 dmesg.txt
|
|
|
6f381c |
|
|
|
6f381c |
1666922867:
|
|
|
6f381c |
total 4
|
|
|
6f381c |
drwxr-xr-x. 3 root root 17 Nov 18 14:58 .
|
|
|
6f381c |
drwxr-xr-x. 7 root root 144 Nov 18 14:58 ..
|
|
|
6f381c |
drwxr-xr-x. 2 root root 4096 Nov 18 14:58 003
|
|
|
6f381c |
|
|
|
6f381c |
1666922867/003:
|
|
|
6f381c |
total 104
|
|
|
6f381c |
drwxr-xr-x. 2 root root 4096 Nov 18 14:58 .
|
|
|
6f381c |
drwxr-xr-x. 3 root root 17 Nov 18 14:58 ..
|
|
|
6f381c |
-rw-------. 1 root root 1388 Oct 27 22:07 dmesg-efi-166692286701003
|
|
|
6f381c |
-rw-------. 1 root root 1824 Oct 27 22:07 dmesg-efi-166692286702003
|
|
|
6f381c |
-rw-------. 1 root root 1795 Oct 27 22:07 dmesg-efi-166692286703003
|
|
|
6f381c |
-rw-------. 1 root root 1805 Oct 27 22:07 dmesg-efi-166692286704003
|
|
|
6f381c |
-rw-------. 1 root root 1813 Oct 27 22:07 dmesg-efi-166692286705003
|
|
|
6f381c |
-rw-------. 1 root root 1821 Oct 27 22:07 dmesg-efi-166692286706003
|
|
|
6f381c |
-rw-------. 1 root root 1814 Oct 27 22:07 dmesg-efi-166692286707003
|
|
|
6f381c |
-rw-------. 1 root root 1812 Oct 27 22:07 dmesg-efi-166692286708003
|
|
|
6f381c |
-rw-------. 1 root root 1769 Oct 27 22:07 dmesg-efi-166692286709003
|
|
|
6f381c |
-rw-------. 1 root root 1820 Oct 27 22:07 dmesg-efi-166692286710003
|
|
|
6f381c |
-rw-------. 1 root root 1755 Oct 27 22:07 dmesg-efi-166692286711003
|
|
|
6f381c |
-rw-------. 1 root root 1790 Oct 27 22:07 dmesg-efi-166692286712003
|
|
|
6f381c |
-rw-------. 1 root root 1756 Oct 27 22:07 dmesg-efi-166692286713003
|
|
|
6f381c |
-rw-------. 1 root root 1763 Oct 27 22:07 dmesg-efi-166692286714003
|
|
|
6f381c |
-rw-------. 1 root root 1791 Oct 27 22:07 dmesg-efi-166692286715003
|
|
|
6f381c |
-rw-------. 1 root root 1775 Oct 27 22:07 dmesg-efi-166692286716003
|
|
|
6f381c |
-rw-------. 1 root root 1820 Oct 27 22:07 dmesg-efi-166692286717003
|
|
|
6f381c |
-rw-r-----. 1 root root 30111 Nov 18 14:58 dmesg.txt
|
|
|
6f381c |
|
|
|
6f381c |
Furthemore, pstore records on ERST are now able to accurately
|
|
|
6f381c |
identify the change in timestamp sequence in order to start a
|
|
|
6f381c |
new dmesg.txt, as needed.
|
|
|
6f381c |
|
|
|
6f381c |
(cherry picked from commit 5fbaa757077bde2db8d33b1c358518c41b990339)
|
|
|
6f381c |
|
|
|
6f381c |
Related: #2158832
|
|
|
6f381c |
---
|
|
|
6f381c |
src/pstore/pstore.c | 216 +++++++++++++++++++-------------------------
|
|
|
6f381c |
1 file changed, 92 insertions(+), 124 deletions(-)
|
|
|
6f381c |
|
|
|
6f381c |
diff --git a/src/pstore/pstore.c b/src/pstore/pstore.c
|
|
|
6f381c |
index d70e142b4d..9f61e8f7f8 100644
|
|
|
6f381c |
--- a/src/pstore/pstore.c
|
|
|
6f381c |
+++ b/src/pstore/pstore.c
|
|
|
6f381c |
@@ -112,8 +112,8 @@ static int compare_pstore_entries(const void *_a, const void *_b) {
|
|
|
6f381c |
return strcmp(a->dirent.d_name, b->dirent.d_name);
|
|
|
6f381c |
}
|
|
|
6f381c |
|
|
|
6f381c |
-static int move_file(PStoreEntry *pe, const char *subdir) {
|
|
|
6f381c |
- _cleanup_free_ char *ifd_path = NULL, *ofd_path = NULL;
|
|
|
6f381c |
+static int move_file(PStoreEntry *pe, const char *subdir1, const char *subdir2) {
|
|
|
6f381c |
+ _cleanup_free_ char *ifd_path = NULL, *ofd_path = NULL, *ofd_path_base = NULL;
|
|
|
6f381c |
_cleanup_free_ void *field = NULL;
|
|
|
6f381c |
const char *suffix, *message;
|
|
|
6f381c |
struct iovec iovec[2];
|
|
|
6f381c |
@@ -126,7 +126,11 @@ static int move_file(PStoreEntry *pe, const char *subdir) {
|
|
|
6f381c |
if (!ifd_path)
|
|
|
6f381c |
return log_oom();
|
|
|
6f381c |
|
|
|
6f381c |
- ofd_path = path_join(arg_archivedir, subdir, pe->dirent.d_name);
|
|
|
6f381c |
+ ofd_path_base = path_join(arg_archivedir, subdir1, subdir2);
|
|
|
6f381c |
+ if (!ofd_path_base)
|
|
|
6f381c |
+ return log_oom();
|
|
|
6f381c |
+
|
|
|
6f381c |
+ ofd_path = path_join(NULL, ofd_path_base, pe->dirent.d_name);
|
|
|
6f381c |
if (!ofd_path)
|
|
|
6f381c |
return log_oom();
|
|
|
6f381c |
|
|
|
6f381c |
@@ -169,155 +173,119 @@ static int move_file(PStoreEntry *pe, const char *subdir) {
|
|
|
6f381c |
return 0;
|
|
|
6f381c |
}
|
|
|
6f381c |
|
|
|
6f381c |
-static int write_dmesg(const char *dmesg, size_t size, const char *id) {
|
|
|
6f381c |
- _cleanup_(unlink_and_freep) char *tmp_path = NULL;
|
|
|
6f381c |
- _cleanup_free_ char *ofd_path = NULL;
|
|
|
6f381c |
+static int append_dmesg(PStoreEntry *pe, const char *subdir1, const char *subdir2) {
|
|
|
6f381c |
+ /* Append dmesg chunk to end, create if needed */
|
|
|
6f381c |
+ _cleanup_free_ char *ofd_path = NULL, *ofd_path_base = NULL;
|
|
|
6f381c |
_cleanup_close_ int ofd = -1;
|
|
|
6f381c |
ssize_t wr;
|
|
|
6f381c |
- int r;
|
|
|
6f381c |
|
|
|
6f381c |
- if (size == 0)
|
|
|
6f381c |
- return 0;
|
|
|
6f381c |
+ assert(pe);
|
|
|
6f381c |
|
|
|
6f381c |
- assert(dmesg);
|
|
|
6f381c |
+ if (pe->content_size == 0)
|
|
|
6f381c |
+ return 0;
|
|
|
6f381c |
|
|
|
6f381c |
- /* log_info("Record ID %s", id); */
|
|
|
6f381c |
+ ofd_path_base = path_join(arg_archivedir, subdir1, subdir2);
|
|
|
6f381c |
+ if (!ofd_path_base)
|
|
|
6f381c |
+ return log_oom();
|
|
|
6f381c |
|
|
|
6f381c |
- ofd_path = path_join(arg_archivedir, id, "dmesg.txt");
|
|
|
6f381c |
+ ofd_path = path_join(NULL, ofd_path_base, "dmesg.txt");
|
|
|
6f381c |
if (!ofd_path)
|
|
|
6f381c |
return log_oom();
|
|
|
6f381c |
|
|
|
6f381c |
- ofd = open_tmpfile_linkable(ofd_path, O_CLOEXEC|O_CREAT|O_TRUNC|O_WRONLY, &tmp_path);
|
|
|
6f381c |
+ ofd = open(ofd_path, O_CREAT|O_NOFOLLOW|O_NOCTTY|O_CLOEXEC|O_APPEND|O_WRONLY, 0640);
|
|
|
6f381c |
if (ofd < 0)
|
|
|
6f381c |
- return log_error_errno(ofd, "Failed to open temporary file %s: %m", ofd_path);
|
|
|
6f381c |
- wr = write(ofd, dmesg, size);
|
|
|
6f381c |
+ return log_error_errno(ofd, "Failed to open file %s: %m", ofd_path);
|
|
|
6f381c |
+ wr = write(ofd, pe->content, pe->content_size);
|
|
|
6f381c |
if (wr < 0)
|
|
|
6f381c |
return log_error_errno(errno, "Failed to store dmesg to %s: %m", ofd_path);
|
|
|
6f381c |
- if (wr != (ssize_t)size)
|
|
|
6f381c |
- return log_error_errno(-EIO, "Failed to store dmesg to %s. %zu bytes are lost.", ofd_path, size - wr);
|
|
|
6f381c |
- r = link_tmpfile(ofd, tmp_path, ofd_path);
|
|
|
6f381c |
- if (r < 0)
|
|
|
6f381c |
- return log_error_errno(r, "Failed to write temporary file %s: %m", ofd_path);
|
|
|
6f381c |
- tmp_path = mfree(tmp_path);
|
|
|
6f381c |
+ if ((size_t)wr != pe->content_size)
|
|
|
6f381c |
+ return log_error_errno(-EIO, "Failed to store dmesg to %s. %zu bytes are lost.", ofd_path, pe->content_size - wr);
|
|
|
6f381c |
|
|
|
6f381c |
return 0;
|
|
|
6f381c |
}
|
|
|
6f381c |
|
|
|
6f381c |
-static void process_dmesg_files(PStoreList *list) {
|
|
|
6f381c |
+static int process_dmesg_files(PStoreList *list) {
|
|
|
6f381c |
/* Move files, reconstruct dmesg.txt */
|
|
|
6f381c |
- _cleanup_free_ char *dmesg = NULL, *dmesg_id = NULL;
|
|
|
6f381c |
- size_t dmesg_size = 0, dmesg_allocated = 0;
|
|
|
6f381c |
- bool dmesg_bad = false;
|
|
|
6f381c |
- PStoreEntry *pe;
|
|
|
6f381c |
+ _cleanup_free_ char *erst_subdir = NULL;
|
|
|
6f381c |
+ uint64_t last_record_id = 0;
|
|
|
6f381c |
+
|
|
|
6f381c |
+ /* When dmesg is written into pstore, it is done so in small chunks, whatever the exchange buffer
|
|
|
6f381c |
+ * size is with the underlying pstore backend (ie. EFI may be ~2KiB), which means an example
|
|
|
6f381c |
+ * pstore with approximately 64KB of storage may have up to roughly 32 dmesg files, some likely
|
|
|
6f381c |
+ * related.
|
|
|
6f381c |
+ *
|
|
|
6f381c |
+ * Here we look at the dmesg filename and try to discern if files are part of a related group,
|
|
|
6f381c |
+ * meaning the same original dmesg.
|
|
|
6f381c |
+ *
|
|
|
6f381c |
+ * The dmesg- filename contains the backend-type and the Common Platform Error Record, CPER,
|
|
|
6f381c |
+ * record id, a 64-bit number.
|
|
|
6f381c |
+ *
|
|
|
6f381c |
+ * Files are processed in reverse lexigraphical order so as to properly reconstruct original dmesg.*/
|
|
|
6f381c |
|
|
|
6f381c |
- /* Handle each dmesg file: files processed in reverse
|
|
|
6f381c |
- * order so as to properly reconstruct original dmesg */
|
|
|
6f381c |
for (size_t n = list->n_entries; n > 0; n--) {
|
|
|
6f381c |
- bool move_file_and_continue = false;
|
|
|
6f381c |
- _cleanup_free_ char *pe_id = NULL;
|
|
|
6f381c |
+ PStoreEntry *pe;
|
|
|
6f381c |
char *p;
|
|
|
6f381c |
- size_t plen;
|
|
|
6f381c |
|
|
|
6f381c |
pe = &list->entries[n-1];
|
|
|
6f381c |
|
|
|
6f381c |
if (pe->handled)
|
|
|
6f381c |
continue;
|
|
|
6f381c |
- if (!startswith(pe->dirent.d_name, "dmesg-"))
|
|
|
6f381c |
- continue;
|
|
|
6f381c |
-
|
|
|
6f381c |
if (endswith(pe->dirent.d_name, ".enc.z")) /* indicates a problem */
|
|
|
6f381c |
- move_file_and_continue = true;
|
|
|
6f381c |
- p = strrchr(pe->dirent.d_name, '-');
|
|
|
6f381c |
- if (!p)
|
|
|
6f381c |
- move_file_and_continue = true;
|
|
|
6f381c |
-
|
|
|
6f381c |
- if (move_file_and_continue) {
|
|
|
6f381c |
- /* A dmesg file on which we do NO additional processing */
|
|
|
6f381c |
- (void) move_file(pe, NULL);
|
|
|
6f381c |
continue;
|
|
|
6f381c |
- }
|
|
|
6f381c |
-
|
|
|
6f381c |
- /* See if this file is one of a related group of files
|
|
|
6f381c |
- * in order to reconstruct dmesg */
|
|
|
6f381c |
-
|
|
|
6f381c |
- /* When dmesg is written into pstore, it is done so in
|
|
|
6f381c |
- * small chunks, whatever the exchange buffer size is
|
|
|
6f381c |
- * with the underlying pstore backend (ie. EFI may be
|
|
|
6f381c |
- * ~2KiB), which means an example pstore with approximately
|
|
|
6f381c |
- * 64KB of storage may have up to roughly 32 dmesg files
|
|
|
6f381c |
- * that could be related, depending upon the size of the
|
|
|
6f381c |
- * original dmesg.
|
|
|
6f381c |
- *
|
|
|
6f381c |
- * Here we look at the dmesg filename and try to discern
|
|
|
6f381c |
- * if files are part of a related group, meaning the same
|
|
|
6f381c |
- * original dmesg.
|
|
|
6f381c |
- *
|
|
|
6f381c |
- * The two known pstore backends are EFI and ERST. These
|
|
|
6f381c |
- * backends store data in the Common Platform Error
|
|
|
6f381c |
- * Record, CPER, format. The dmesg- filename contains the
|
|
|
6f381c |
- * CPER record id, a 64bit number (in decimal notation).
|
|
|
6f381c |
- * In Linux, the record id is encoded with two digits for
|
|
|
6f381c |
- * the dmesg part (chunk) number and 3 digits for the
|
|
|
6f381c |
- * count number. So allowing an additional digit to
|
|
|
6f381c |
- * compensate for advancing time, this code ignores the
|
|
|
6f381c |
- * last six digits of the filename in determining the
|
|
|
6f381c |
- * record id.
|
|
|
6f381c |
- *
|
|
|
6f381c |
- * For the EFI backend, the record id encodes an id in the
|
|
|
6f381c |
- * upper 32 bits, and a timestamp in the lower 32-bits.
|
|
|
6f381c |
- * So ignoring the least significant 6 digits has proven
|
|
|
6f381c |
- * to generally identify related dmesg entries. */
|
|
|
6f381c |
-#define PSTORE_FILENAME_IGNORE 6
|
|
|
6f381c |
-
|
|
|
6f381c |
- /* determine common portion of record id */
|
|
|
6f381c |
- ++p; /* move beyond dmesg- */
|
|
|
6f381c |
- plen = strlen(p);
|
|
|
6f381c |
- if (plen > PSTORE_FILENAME_IGNORE) {
|
|
|
6f381c |
- pe_id = memdup_suffix0(p, plen - PSTORE_FILENAME_IGNORE);
|
|
|
6f381c |
- if (!pe_id) {
|
|
|
6f381c |
- log_oom();
|
|
|
6f381c |
- return;
|
|
|
6f381c |
- }
|
|
|
6f381c |
- } else
|
|
|
6f381c |
- pe_id = mfree(pe_id);
|
|
|
6f381c |
-
|
|
|
6f381c |
- /* Now move file from pstore to archive storage */
|
|
|
6f381c |
- move_file(pe, pe_id);
|
|
|
6f381c |
-
|
|
|
6f381c |
- if (dmesg_bad)
|
|
|
6f381c |
+ if (!startswith(pe->dirent.d_name, "dmesg-"))
|
|
|
6f381c |
continue;
|
|
|
6f381c |
|
|
|
6f381c |
- /* If the current record id is NOT the same as the
|
|
|
6f381c |
- * previous record id, then start a new dmesg.txt file */
|
|
|
6f381c |
- if (!streq_ptr(pe_id, dmesg_id)) {
|
|
|
6f381c |
- /* Encountered a new dmesg group, close out old one, open new one */
|
|
|
6f381c |
- (void) write_dmesg(dmesg, dmesg_size, dmesg_id);
|
|
|
6f381c |
- dmesg_size = 0;
|
|
|
6f381c |
-
|
|
|
6f381c |
- /* now point dmesg_id to storage of pe_id */
|
|
|
6f381c |
- free_and_replace(dmesg_id, pe_id);
|
|
|
6f381c |
- }
|
|
|
6f381c |
-
|
|
|
6f381c |
- /* Reconstruction of dmesg is done as a useful courtesy: do not fail, but don't write garbled
|
|
|
6f381c |
- * output either. */
|
|
|
6f381c |
- size_t needed = strlen(pe->dirent.d_name) + strlen(":\n") + pe->content_size + 1;
|
|
|
6f381c |
- if (!GREEDY_REALLOC(dmesg, dmesg_allocated, dmesg_size + needed)) {
|
|
|
6f381c |
- log_warning_errno(ENOMEM, "Failed to write dmesg file: %m");
|
|
|
6f381c |
- dmesg_bad = true;
|
|
|
6f381c |
- continue;
|
|
|
6f381c |
- }
|
|
|
6f381c |
-
|
|
|
6f381c |
- dmesg_size += sprintf(dmesg + dmesg_size, "%s:\n", pe->dirent.d_name);
|
|
|
6f381c |
- if (pe->content) {
|
|
|
6f381c |
- memcpy(dmesg + dmesg_size, pe->content, pe->content_size);
|
|
|
6f381c |
- dmesg_size += pe->content_size;
|
|
|
6f381c |
- }
|
|
|
6f381c |
-
|
|
|
6f381c |
- pe_id = mfree(pe_id);
|
|
|
6f381c |
+ if ((p = startswith(pe->dirent.d_name, "dmesg-efi-"))) {
|
|
|
6f381c |
+ /* For the EFI backend, the 3 least significant digits of record id encodes a
|
|
|
6f381c |
+ * "count" number, the next 2 least significant digits for the dmesg part
|
|
|
6f381c |
+ * (chunk) number, and the remaining digits as the timestamp. See
|
|
|
6f381c |
+ * linux/drivers/firmware/efi/efi-pstore.c in efi_pstore_write(). */
|
|
|
6f381c |
+ _cleanup_free_ char *subdir1 = NULL, *subdir2 = NULL;
|
|
|
6f381c |
+ size_t plen = strlen(p);
|
|
|
6f381c |
+
|
|
|
6f381c |
+ if (plen < 6)
|
|
|
6f381c |
+ continue;
|
|
|
6f381c |
+
|
|
|
6f381c |
+ /* Extract base record id */
|
|
|
6f381c |
+ subdir1 = strndup(p, plen - 5);
|
|
|
6f381c |
+ if (!subdir1)
|
|
|
6f381c |
+ return log_oom();
|
|
|
6f381c |
+ /* Extract "count" field */
|
|
|
6f381c |
+ subdir2 = strndup(p + plen - 3, 3);
|
|
|
6f381c |
+ if (!subdir2)
|
|
|
6f381c |
+ return log_oom();
|
|
|
6f381c |
+
|
|
|
6f381c |
+ /* Now move file from pstore to archive storage */
|
|
|
6f381c |
+ (void) move_file(pe, subdir1, subdir2);
|
|
|
6f381c |
+
|
|
|
6f381c |
+ /* Append to the dmesg */
|
|
|
6f381c |
+ (void) append_dmesg(pe, subdir1, subdir2);
|
|
|
6f381c |
+ } else if ((p = startswith(pe->dirent.d_name, "dmesg-erst-"))) {
|
|
|
6f381c |
+ /* For the ERST backend, the record is a monotonically increasing number, seeded as
|
|
|
6f381c |
+ * a timestamp. See linux/drivers/acpi/apei/erst.c in erst_writer(). */
|
|
|
6f381c |
+ uint64_t record_id;
|
|
|
6f381c |
+
|
|
|
6f381c |
+ if (safe_atou64(p, &record_id) < 0)
|
|
|
6f381c |
+ continue;
|
|
|
6f381c |
+ if (last_record_id - 1 != record_id)
|
|
|
6f381c |
+ /* A discontinuity in the number has been detected, this current record id
|
|
|
6f381c |
+ * will become the directory name for all pieces of the dmesg in this
|
|
|
6f381c |
+ * series. */
|
|
|
6f381c |
+ if (free_and_strdup(&erst_subdir, p) < 0)
|
|
|
6f381c |
+ return log_oom();
|
|
|
6f381c |
+
|
|
|
6f381c |
+ /* Now move file from pstore to archive storage */
|
|
|
6f381c |
+ (void) move_file(pe, erst_subdir, NULL);
|
|
|
6f381c |
+
|
|
|
6f381c |
+ /* Append to the dmesg */
|
|
|
6f381c |
+ (void) append_dmesg(pe, erst_subdir, NULL);
|
|
|
6f381c |
+
|
|
|
6f381c |
+ /* Update, but keep erst_subdir for next file */
|
|
|
6f381c |
+ last_record_id = record_id;
|
|
|
6f381c |
+ } else
|
|
|
6f381c |
+ log_debug("Unknown backend, ignoring \"%s\".", pe->dirent.d_name);
|
|
|
6f381c |
}
|
|
|
6f381c |
-
|
|
|
6f381c |
- if (!dmesg_bad)
|
|
|
6f381c |
- (void) write_dmesg(dmesg, dmesg_size, dmesg_id);
|
|
|
6f381c |
+ return 0;
|
|
|
6f381c |
}
|
|
|
6f381c |
|
|
|
6f381c |
static int list_files(PStoreList *list, const char *sourcepath) {
|
|
|
6f381c |
@@ -394,11 +362,11 @@ static int run(int argc, char *argv[]) {
|
|
|
6f381c |
qsort_safe(list.entries, list.n_entries, sizeof(PStoreEntry), compare_pstore_entries);
|
|
|
6f381c |
|
|
|
6f381c |
/* Process known file types */
|
|
|
6f381c |
- process_dmesg_files(&list);
|
|
|
6f381c |
+ (void) process_dmesg_files(&list);
|
|
|
6f381c |
|
|
|
6f381c |
/* Move left over files out of pstore */
|
|
|
6f381c |
for (size_t n = 0; n < list.n_entries; n++)
|
|
|
6f381c |
- move_file(&list.entries[n], NULL);
|
|
|
6f381c |
+ (void) move_file(&list.entries[n], NULL, NULL);
|
|
|
6f381c |
|
|
|
6f381c |
return 0;
|
|
|
6f381c |
}
|