diff --git a/SOURCES/0873-journald-add-API-to-move-logging-from-var-to-run-aga.patch b/SOURCES/0873-journald-add-API-to-move-logging-from-var-to-run-aga.patch
new file mode 100644
index 0000000..f44f50b
--- /dev/null
+++ b/SOURCES/0873-journald-add-API-to-move-logging-from-var-to-run-aga.patch
@@ -0,0 +1,176 @@
+From 8f0a91b5192b72eb8b0f06e04ef3515d0397fcb8 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Fri, 5 Apr 2019 18:20:25 +0200
+Subject: [PATCH] journald: add API to move logging from /var to /run again
+
+We now have this nice little Varlink API, let's beef it up a bit.
+
+[dtardon: This diverges from the upstream commit in two ways: One is
+that the new action is bound to a signal, as varlink is not available.
+The other is that this introduces a new "flag" file
+/run/systemd/journal/relinquished, which is essentially the opposite of
+/run/systemd/journal/flushed (hence at most one of them may exist at any
+time).]
+
+(cherry picked from commit b4e26d1d8e582d78e67ed766177f10e8e194404c)
+
+Related: #1873540
+---
+ src/journal/journald-server.c | 64 ++++++++++++++++++++++++++++-------
+ 1 file changed, 51 insertions(+), 13 deletions(-)
+
+diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c
+index 7632e2d9d0..279a32768c 100644
+--- a/src/journal/journald-server.c
++++ b/src/journal/journald-server.c
+@@ -283,13 +283,14 @@ static bool flushed_flag_is_set(void) {
+         return access("/run/systemd/journal/flushed", F_OK) >= 0;
+ }
+ 
+-static int system_journal_open(Server *s, bool flush_requested) {
++static int system_journal_open(Server *s, bool flush_requested, bool relinquish_requested) {
+         const char *fn;
+         int r = 0;
+ 
+         if (!s->system_journal &&
+             IN_SET(s->storage, STORAGE_PERSISTENT, STORAGE_AUTO) &&
+-            (flush_requested || flushed_flag_is_set())) {
++            (flush_requested || flushed_flag_is_set()) &&
++            !relinquish_requested) {
+ 
+                 /* If in auto mode: first try to create the machine
+                  * path, but not the prefix.
+@@ -331,7 +332,7 @@ static int system_journal_open(Server *s, bool flush_requested) {
+ 
+                 fn = strjoina(s->runtime_storage.path, "/system.journal");
+ 
+-                if (s->system_journal) {
++                if (s->system_journal && !relinquish_requested) {
+ 
+                         /* Try to open the runtime journal, but only
+                          * if it already exists, so that we can flush
+@@ -386,7 +387,7 @@ static JournalFile* find_journal(Server *s, uid_t uid) {
+          * else that's left the journals as NULL).
+          *
+          * Fixes https://github.com/systemd/systemd/issues/3968 */
+-        (void) system_journal_open(s, false);
++        (void) system_journal_open(s, false, false);
+ 
+         /* We split up user logs only on /var, not on /run. If the
+          * runtime file is open, we write to it exclusively, in order
+@@ -964,7 +965,7 @@ int server_flush_to_var(Server *s, bool require_flag_file) {
+         char ts[FORMAT_TIMESPAN_MAX];
+         usec_t start;
+         unsigned n = 0;
+-        int r;
++        int r, k;
+ 
+         assert(s);
+ 
+@@ -977,7 +978,7 @@ int server_flush_to_var(Server *s, bool require_flag_file) {
+         if (require_flag_file && !flushed_flag_is_set())
+                 return 0;
+ 
+-        (void) system_journal_open(s, true);
++        (void) system_journal_open(s, true, false);
+ 
+         if (!s->system_journal)
+                 return 0;
+@@ -1056,6 +1057,13 @@ finish:
+                                           n),
+                               NULL);
+ 
++        if (unlink("/run/systemd/journal/relinquished") < 0 && errno != ENOENT)
++                log_warning_errno(errno, "Failed to unlink /run/systemd/journal/relinquished, ignoring: %m");
++
++        k = touch("/run/systemd/journal/flushed");
++        if (k < 0)
++                log_warning_errno(k, "Failed to touch /run/systemd/journal/flushed, ignoring: %m");
++
+         return r;
+ }
+ 
+@@ -1180,7 +1188,6 @@ int server_process_datagram(sd_event_source *es, int fd, uint32_t revents, void
+ 
+ static int dispatch_sigusr1(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) {
+         Server *s = userdata;
+-        int r;
+ 
+         assert(s);
+ 
+@@ -1190,10 +1197,6 @@ static int dispatch_sigusr1(sd_event_source *es, const struct signalfd_siginfo *
+         server_sync(s);
+         server_vacuum(s, false);
+ 
+-        r = touch("/run/systemd/journal/flushed");
+-        if (r < 0)
+-                log_warning_errno(r, "Failed to touch /run/systemd/journal/flushed, ignoring: %m");
+-
+         server_space_usage_message(s, NULL);
+         return 0;
+ }
+@@ -1250,12 +1253,43 @@ static int dispatch_sigrtmin1(sd_event_source *es, const struct signalfd_siginfo
+         return 0;
+ }
+ 
++
++static int dispatch_sigrtmin2(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) {
++        Server *s = userdata;
++        int r;
++
++        assert(s);
++
++        if (s->storage == STORAGE_NONE)
++                return 0;
++
++        if (s->runtime_journal && !s->system_journal)
++                return 0;
++
++        log_debug("Received request to relinquish /var from PID " PID_FMT, si->ssi_pid);
++
++        (void) system_journal_open(s, false, true);
++
++        s->system_journal = journal_file_close(s->system_journal);
++        ordered_hashmap_clear_with_destructor(s->user_journals, journal_file_close);
++        set_clear_with_destructor(s->deferred_closes, journal_file_close);
++
++        if (unlink("/run/systemd/journal/flushed") < 0 && errno != ENOENT)
++                log_warning_errno(errno, "Failed to unlink /run/systemd/journal/flushed, ignoring: %m")  ;
++
++        r = write_timestamp_file_atomic("/run/systemd/journal/relinquished", now(CLOCK_MONOTONIC));
++        if (r < 0)
++                log_warning_errno(r, "Failed to write /run/systemd/journal/relinquished, ignoring: %m");
++
++        return 0;
++}
++
+ static int setup_signals(Server *s) {
+         int r;
+ 
+         assert(s);
+ 
+-        assert_se(sigprocmask_many(SIG_SETMASK, NULL, SIGINT, SIGTERM, SIGUSR1, SIGUSR2, SIGRTMIN+1, -1) >= 0);
++        assert_se(sigprocmask_many(SIG_SETMASK, NULL, SIGINT, SIGTERM, SIGUSR1, SIGUSR2, SIGRTMIN+1, SIGRTMIN+2, -1) >= 0);
+ 
+         r = sd_event_add_signal(s->event, &s->sigusr1_event_source, SIGUSR1, dispatch_sigusr1, s);
+         if (r < 0)
+@@ -1294,6 +1328,10 @@ static int setup_signals(Server *s) {
+         if (r < 0)
+                 return r;
+ 
++        r = sd_event_add_signal(s->event, &s->sigrtmin1_event_source, SIGRTMIN+2, dispatch_sigrtmin2, s);
++        if (r < 0)
++                return r;
++
+         r = sd_event_source_set_priority(s->sigrtmin1_event_source, SD_EVENT_PRIORITY_NORMAL+15);
+         if (r < 0)
+                 return r;
+@@ -1876,7 +1914,7 @@ int server_init(Server *s) {
+ 
+         (void) client_context_acquire_default(s);
+ 
+-        return system_journal_open(s, false);
++        return system_journal_open(s, false, false);
+ }
+ 
+ void server_maybe_append_tags(Server *s) {
diff --git a/SOURCES/0874-journalctl-add-new-relinquish-and-smart-relinquish-o.patch b/SOURCES/0874-journalctl-add-new-relinquish-and-smart-relinquish-o.patch
new file mode 100644
index 0000000..65b8ac3
--- /dev/null
+++ b/SOURCES/0874-journalctl-add-new-relinquish-and-smart-relinquish-o.patch
@@ -0,0 +1,242 @@
+From fa93a97bdf18906d9517f4183802456986490c89 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Fri, 5 Apr 2019 18:21:02 +0200
+Subject: [PATCH] journalctl: add new --relinquish and --smart-relinquish
+ options
+
+The latter is identical to the former, but becomes a NOP if
+/var/log/journal is on the same mount as /, and thus during shutdown
+unmounting /var is not necessary and hence we can keep logging until the
+very end.
+
+[dtardon: The only divergence from the upstream commit is the impl. of
+relinquish_var().]
+
+(cherry picked from commit c0dfcb318c28d87e1176a8ad87ac7cc4ecc50305)
+
+Related: #1873540
+---
+ src/journal/journalctl.c | 161 +++++++++++++++++++++++++--------------
+ 1 file changed, 103 insertions(+), 58 deletions(-)
+
+diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
+index 228cfe7e49..6928c79a06 100644
+--- a/src/journal/journalctl.c
++++ b/src/journal/journalctl.c
+@@ -47,6 +47,7 @@
+ #include "log.h"
+ #include "logs-show.h"
+ #include "mkdir.h"
++#include "mount-util.h"
+ #include "pager.h"
+ #include "parse-util.h"
+ #include "path-util.h"
+@@ -162,6 +163,7 @@ static enum {
+         ACTION_UPDATE_CATALOG,
+         ACTION_LIST_BOOTS,
+         ACTION_FLUSH,
++        ACTION_RELINQUISH_VAR,
+         ACTION_SYNC,
+         ACTION_ROTATE,
+         ACTION_VACUUM,
+@@ -358,6 +360,8 @@ static void help(void) {
+                "     --vacuum-time=TIME      Remove journal files older than specified time\n"
+                "     --verify                Verify journal file consistency\n"
+                "     --sync                  Synchronize unwritten journal messages to disk\n"
++               "     --relinquish-var        Stop logging to disk, log to temporary file system\n"
++               "     --smart-relinquish-var  Similar, but NOP if log directory is on root mount\n"
+                "     --flush                 Flush all journal data from /run into /var\n"
+                "     --rotate                Request immediate rotation of the journal files\n"
+                "     --header                Show journal header information\n"
+@@ -402,6 +406,8 @@ static int parse_argv(int argc, char *argv[]) {
+                 ARG_UTC,
+                 ARG_SYNC,
+                 ARG_FLUSH,
++                ARG_RELINQUISH_VAR,
++                ARG_SMART_RELINQUISH_VAR,
+                 ARG_ROTATE,
+                 ARG_VACUUM_SIZE,
+                 ARG_VACUUM_FILES,
+@@ -411,64 +417,66 @@ static int parse_argv(int argc, char *argv[]) {
+         };
+ 
+         static const struct option options[] = {
+-                { "help",           no_argument,       NULL, 'h'                },
+-                { "version" ,       no_argument,       NULL, ARG_VERSION        },
+-                { "no-pager",       no_argument,       NULL, ARG_NO_PAGER       },
+-                { "pager-end",      no_argument,       NULL, 'e'                },
+-                { "follow",         no_argument,       NULL, 'f'                },
+-                { "force",          no_argument,       NULL, ARG_FORCE          },
+-                { "output",         required_argument, NULL, 'o'                },
+-                { "all",            no_argument,       NULL, 'a'                },
+-                { "full",           no_argument,       NULL, 'l'                },
+-                { "no-full",        no_argument,       NULL, ARG_NO_FULL        },
+-                { "lines",          optional_argument, NULL, 'n'                },
+-                { "no-tail",        no_argument,       NULL, ARG_NO_TAIL        },
+-                { "new-id128",      no_argument,       NULL, ARG_NEW_ID128      },
+-                { "quiet",          no_argument,       NULL, 'q'                },
+-                { "merge",          no_argument,       NULL, 'm'                },
+-                { "this-boot",      no_argument,       NULL, ARG_THIS_BOOT      }, /* deprecated */
+-                { "boot",           optional_argument, NULL, 'b'                },
+-                { "list-boots",     no_argument,       NULL, ARG_LIST_BOOTS     },
+-                { "dmesg",          no_argument,       NULL, 'k'                },
+-                { "system",         no_argument,       NULL, ARG_SYSTEM         },
+-                { "user",           no_argument,       NULL, ARG_USER           },
+-                { "directory",      required_argument, NULL, 'D'                },
+-                { "file",           required_argument, NULL, ARG_FILE           },
+-                { "root",           required_argument, NULL, ARG_ROOT           },
+-                { "header",         no_argument,       NULL, ARG_HEADER         },
+-                { "identifier",     required_argument, NULL, 't'                },
+-                { "priority",       required_argument, NULL, 'p'                },
+-                { "grep",           required_argument, NULL, 'g'                },
+-                { "case-sensitive", optional_argument, NULL, ARG_CASE_SENSITIVE },
+-                { "setup-keys",     no_argument,       NULL, ARG_SETUP_KEYS     },
+-                { "interval",       required_argument, NULL, ARG_INTERVAL       },
+-                { "verify",         no_argument,       NULL, ARG_VERIFY         },
+-                { "verify-key",     required_argument, NULL, ARG_VERIFY_KEY     },
+-                { "disk-usage",     no_argument,       NULL, ARG_DISK_USAGE     },
+-                { "cursor",         required_argument, NULL, 'c'                },
+-                { "after-cursor",   required_argument, NULL, ARG_AFTER_CURSOR   },
+-                { "show-cursor",    no_argument,       NULL, ARG_SHOW_CURSOR    },
+-                { "since",          required_argument, NULL, 'S'                },
+-                { "until",          required_argument, NULL, 'U'                },
+-                { "unit",           required_argument, NULL, 'u'                },
+-                { "user-unit",      required_argument, NULL, ARG_USER_UNIT      },
+-                { "field",          required_argument, NULL, 'F'                },
+-                { "fields",         no_argument,       NULL, 'N'                },
+-                { "catalog",        no_argument,       NULL, 'x'                },
+-                { "list-catalog",   no_argument,       NULL, ARG_LIST_CATALOG   },
+-                { "dump-catalog",   no_argument,       NULL, ARG_DUMP_CATALOG   },
+-                { "update-catalog", no_argument,       NULL, ARG_UPDATE_CATALOG },
+-                { "reverse",        no_argument,       NULL, 'r'                },
+-                { "machine",        required_argument, NULL, 'M'                },
+-                { "utc",            no_argument,       NULL, ARG_UTC            },
+-                { "flush",          no_argument,       NULL, ARG_FLUSH          },
+-                { "sync",           no_argument,       NULL, ARG_SYNC           },
+-                { "rotate",         no_argument,       NULL, ARG_ROTATE         },
+-                { "vacuum-size",    required_argument, NULL, ARG_VACUUM_SIZE    },
+-                { "vacuum-files",   required_argument, NULL, ARG_VACUUM_FILES   },
+-                { "vacuum-time",    required_argument, NULL, ARG_VACUUM_TIME    },
+-                { "no-hostname",    no_argument,       NULL, ARG_NO_HOSTNAME    },
+-                { "output-fields",  required_argument, NULL, ARG_OUTPUT_FIELDS  },
++                { "help",                 no_argument,       NULL, 'h'                      },
++                { "version" ,             no_argument,       NULL, ARG_VERSION              },
++                { "no-pager",             no_argument,       NULL, ARG_NO_PAGER             },
++                { "pager-end",            no_argument,       NULL, 'e'                      },
++                { "follow",               no_argument,       NULL, 'f'                      },
++                { "force",                no_argument,       NULL, ARG_FORCE                },
++                { "output",               required_argument, NULL, 'o'                      },
++                { "all",                  no_argument,       NULL, 'a'                      },
++                { "full",                 no_argument,       NULL, 'l'                      },
++                { "no-full",              no_argument,       NULL, ARG_NO_FULL              },
++                { "lines",                optional_argument, NULL, 'n'                      },
++                { "no-tail",              no_argument,       NULL, ARG_NO_TAIL              },
++                { "new-id128",            no_argument,       NULL, ARG_NEW_ID128            }, /* deprecated */
++                { "quiet",                no_argument,       NULL, 'q'                      },
++                { "merge",                no_argument,       NULL, 'm'                      },
++                { "this-boot",            no_argument,       NULL, ARG_THIS_BOOT            }, /* deprecated */
++                { "boot",                 optional_argument, NULL, 'b'                      },
++                { "list-boots",           no_argument,       NULL, ARG_LIST_BOOTS           },
++                { "dmesg",                no_argument,       NULL, 'k'                      },
++                { "system",               no_argument,       NULL, ARG_SYSTEM               },
++                { "user",                 no_argument,       NULL, ARG_USER                 },
++                { "directory",            required_argument, NULL, 'D'                      },
++                { "file",                 required_argument, NULL, ARG_FILE                 },
++                { "root",                 required_argument, NULL, ARG_ROOT                 },
++                { "header",               no_argument,       NULL, ARG_HEADER               },
++                { "identifier",           required_argument, NULL, 't'                      },
++                { "priority",             required_argument, NULL, 'p'                      },
++                { "grep",                 required_argument, NULL, 'g'                      },
++                { "case-sensitive",       optional_argument, NULL, ARG_CASE_SENSITIVE       },
++                { "setup-keys",           no_argument,       NULL, ARG_SETUP_KEYS           },
++                { "interval",             required_argument, NULL, ARG_INTERVAL             },
++                { "verify",               no_argument,       NULL, ARG_VERIFY               },
++                { "verify-key",           required_argument, NULL, ARG_VERIFY_KEY           },
++                { "disk-usage",           no_argument,       NULL, ARG_DISK_USAGE           },
++                { "cursor",               required_argument, NULL, 'c'                      },
++                { "after-cursor",         required_argument, NULL, ARG_AFTER_CURSOR         },
++                { "show-cursor",          no_argument,       NULL, ARG_SHOW_CURSOR          },
++                { "since",                required_argument, NULL, 'S'                      },
++                { "until",                required_argument, NULL, 'U'                      },
++                { "unit",                 required_argument, NULL, 'u'                      },
++                { "user-unit",            required_argument, NULL, ARG_USER_UNIT            },
++                { "field",                required_argument, NULL, 'F'                      },
++                { "fields",               no_argument,       NULL, 'N'                      },
++                { "catalog",              no_argument,       NULL, 'x'                      },
++                { "list-catalog",         no_argument,       NULL, ARG_LIST_CATALOG         },
++                { "dump-catalog",         no_argument,       NULL, ARG_DUMP_CATALOG         },
++                { "update-catalog",       no_argument,       NULL, ARG_UPDATE_CATALOG       },
++                { "reverse",              no_argument,       NULL, 'r'                      },
++                { "machine",              required_argument, NULL, 'M'                      },
++                { "utc",                  no_argument,       NULL, ARG_UTC                  },
++                { "flush",                no_argument,       NULL, ARG_FLUSH                },
++                { "relinquish-var",       no_argument,       NULL, ARG_RELINQUISH_VAR       },
++                { "smart-relinquish-var", no_argument,       NULL, ARG_SMART_RELINQUISH_VAR },
++                { "sync",                 no_argument,       NULL, ARG_SYNC                 },
++                { "rotate",               no_argument,       NULL, ARG_ROTATE               },
++                { "vacuum-size",          required_argument, NULL, ARG_VACUUM_SIZE          },
++                { "vacuum-files",         required_argument, NULL, ARG_VACUUM_FILES         },
++                { "vacuum-time",          required_argument, NULL, ARG_VACUUM_TIME          },
++                { "no-hostname",          no_argument,       NULL, ARG_NO_HOSTNAME          },
++                { "output-fields",        required_argument, NULL, ARG_OUTPUT_FIELDS        },
+                 {}
+         };
+ 
+@@ -893,6 +901,35 @@ static int parse_argv(int argc, char *argv[]) {
+                         arg_action = ACTION_FLUSH;
+                         break;
+ 
++                case ARG_SMART_RELINQUISH_VAR: {
++                        int root_mnt_id, log_mnt_id;
++
++                        /* Try to be smart about relinquishing access to /var/log/journal/ during shutdown:
++                         * if it's on the same mount as the root file system there's no point in
++                         * relinquishing access and we can leave journald write to it until the very last
++                         * moment. */
++
++                        r = path_get_mnt_id("/", &root_mnt_id);
++                        if (r < 0)
++                                log_debug_errno(r, "Failed to get root mount ID, ignoring: %m");
++                        else {
++                                r = path_get_mnt_id("/var/log/journal/", &log_mnt_id);
++                                if (r < 0)
++                                        log_debug_errno(r, "Failed to get journal directory mount ID, ignoring: %m");
++                                else if (root_mnt_id == log_mnt_id) {
++                                        log_debug("/var/log/journal/ is on root file system, not relinquishing access to /var.");
++                                        return 0;
++                                } else
++                                        log_debug("/var/log/journal/ is not on the root file system, relinquishing access to it.");
++                        }
++
++                        _fallthrough_;
++                }
++
++                case ARG_RELINQUISH_VAR:
++                        arg_action = ACTION_RELINQUISH_VAR;
++                        break;
++
+                 case ARG_ROTATE:
+                         arg_action = ACTION_ROTATE;
+                         break;
+@@ -2056,6 +2093,10 @@ static int send_signal_and_wait(int sig, const char *watch_path) {
+         return 0;
+ }
+ 
++static int relinquish_var(void) {
++        return send_signal_and_wait(SIGRTMIN+2, "/run/systemd/journal/relinquished");
++}
++
+ static int rotate(void) {
+         return send_signal_and_wait(SIGUSR2, "/run/systemd/journal/rotated");
+ }
+@@ -2171,6 +2212,10 @@ int main(int argc, char *argv[]) {
+                 r = flush_to_var();
+                 goto finish;
+ 
++        case ACTION_RELINQUISH_VAR:
++                r = relinquish_var();
++                goto finish;
++
+         case ACTION_SYNC:
+                 r = sync_journal();
+                 goto finish;
diff --git a/SOURCES/0875-units-automatically-revert-to-run-logging-on-shutdow.patch b/SOURCES/0875-units-automatically-revert-to-run-logging-on-shutdow.patch
new file mode 100644
index 0000000..e5b3898
--- /dev/null
+++ b/SOURCES/0875-units-automatically-revert-to-run-logging-on-shutdow.patch
@@ -0,0 +1,26 @@
+From ce6531045b337c3f793d1d74f1e5641e658805bb Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Fri, 5 Apr 2019 18:22:31 +0200
+Subject: [PATCH] units: automatically revert to /run logging on shutdown if
+ necessary
+
+Fixes: #867
+(cherry picked from commit 1e187d2dd52cbb4f0bb30e4d96acf7f72a145b91)
+
+Resolves: #1873540
+---
+ units/systemd-journal-flush.service.in | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/units/systemd-journal-flush.service.in b/units/systemd-journal-flush.service.in
+index 439f5f3f76..653dcebe0e 100644
+--- a/units/systemd-journal-flush.service.in
++++ b/units/systemd-journal-flush.service.in
+@@ -19,6 +19,7 @@ RequiresMountsFor=/var/log/journal
+ 
+ [Service]
+ ExecStart=@rootbindir@/journalctl --flush
++ExecStop=@rootbindir@/journalctl --smart-relinquish-var
+ Type=oneshot
+ RemainAfterExit=yes
+ TimeoutSec=90s
diff --git a/SOURCES/0876-pstore-Tool-to-archive-contents-of-pstore.patch b/SOURCES/0876-pstore-Tool-to-archive-contents-of-pstore.patch
new file mode 100644
index 0000000..be1c25a
--- /dev/null
+++ b/SOURCES/0876-pstore-Tool-to-archive-contents-of-pstore.patch
@@ -0,0 +1,929 @@
+From 2f75df5cd6dcd56775fec9e89fc79672e702d826 Mon Sep 17 00:00:00 2001
+From: Eric DeVolder <eric.devolder@oracle.com>
+Date: Thu, 16 May 2019 08:59:01 -0500
+Subject: [PATCH] pstore: Tool to archive contents of pstore
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This patch introduces the systemd pstore service which will archive the
+contents of the Linux persistent storage filesystem, pstore, to other storage,
+thus preserving the existing information contained in the pstore, and clearing
+pstore storage for future error events.
+
+Linux provides a persistent storage file system, pstore[1], that can store
+error records when the kernel dies (or reboots or powers-off). These records in
+turn can be referenced to debug kernel problems (currently the kernel stuffs
+the tail of the dmesg, which also contains a stack backtrace, into pstore).
+
+The pstore file system supports a variety of backends that map onto persistent
+storage, such as the ACPI ERST[2, Section 18.5 Error Serialization] and UEFI
+variables[3 Appendix N Common Platform Error Record]. The pstore backends
+typically offer a relatively small amount of persistent storage, e.g. 64KiB,
+which can quickly fill up and thus prevent subsequent kernel crashes from
+recording errors. Thus there is a need to monitor and extract the pstore
+contents so that future kernel problems can also record information in the
+pstore.
+
+The pstore service is independent of the kdump service. In cloud environments
+specifically, host and guest filesystems are on remote filesystems (eg. iSCSI
+or NFS), thus kdump relies [implicitly and/or explicitly] upon proper operation
+of networking software *and* hardware *and* infrastructure.  Thus it may not be
+possible to capture a kernel coredump to a file since writes over the network
+may not be possible.
+
+The pstore backend, on the other hand, is completely local and provides a path
+to store error records which will survive a reboot and aid in post-mortem
+debugging.
+
+Usage Notes:
+This tool moves files from /sys/fs/pstore into /var/lib/systemd/pstore.
+
+To enable kernel recording of error records into pstore, one must either pass
+crash_kexec_post_notifiers[4] to the kernel command line or enable via 'echo Y
+ > /sys/module/kernel/parameters/crash_kexec_post_notifiers'. This option
+invokes the recording of errors into pstore *before* an attempt to kexec/kdump
+on a kernel crash.
+
+Optionally, to record reboots and shutdowns in the pstore, one can either pass
+the printk.always_kmsg_dump[4] to the kernel command line or enable via 'echo Y >
+/sys/module/printk/parameters/always_kmsg_dump'. This option enables code on the
+shutdown path to record information via pstore.
+
+This pstore service is a oneshot service. When run, the service invokes
+systemd-pstore which is a tool that performs the following:
+ - reads the pstore.conf configuration file
+ - collects the lists of files in the pstore (eg. /sys/fs/pstore)
+ - for certain file types (eg. dmesg) a handler is invoked
+ - for all other files, the file is moved from pstore
+
+ - In the case of dmesg handler, final processing occurs as such:
+   - files processed in reverse lexigraphical order to faciliate
+     reconstruction of original dmesg
+   - the filename is examined to determine which dmesg it is a part
+   - the file is appended to the reconstructed dmesg
+
+For example, the following pstore contents:
+
+ root@vm356:~# ls -al /sys/fs/pstore
+ total 0
+ drwxr-x--- 2 root root    0 May  9 09:50 .
+ drwxr-xr-x 7 root root    0 May  9 09:50 ..
+ -r--r--r-- 1 root root 1610 May  9 09:49 dmesg-efi-155741337601001
+ -r--r--r-- 1 root root 1778 May  9 09:49 dmesg-efi-155741337602001
+ -r--r--r-- 1 root root 1726 May  9 09:49 dmesg-efi-155741337603001
+ -r--r--r-- 1 root root 1746 May  9 09:49 dmesg-efi-155741337604001
+ -r--r--r-- 1 root root 1686 May  9 09:49 dmesg-efi-155741337605001
+ -r--r--r-- 1 root root 1690 May  9 09:49 dmesg-efi-155741337606001
+ -r--r--r-- 1 root root 1775 May  9 09:49 dmesg-efi-155741337607001
+ -r--r--r-- 1 root root 1811 May  9 09:49 dmesg-efi-155741337608001
+ -r--r--r-- 1 root root 1817 May  9 09:49 dmesg-efi-155741337609001
+ -r--r--r-- 1 root root 1795 May  9 09:49 dmesg-efi-155741337710001
+ -r--r--r-- 1 root root 1770 May  9 09:49 dmesg-efi-155741337711001
+ -r--r--r-- 1 root root 1796 May  9 09:49 dmesg-efi-155741337712001
+ -r--r--r-- 1 root root 1787 May  9 09:49 dmesg-efi-155741337713001
+ -r--r--r-- 1 root root 1808 May  9 09:49 dmesg-efi-155741337714001
+ -r--r--r-- 1 root root 1754 May  9 09:49 dmesg-efi-155741337715001
+
+results in the following:
+
+ root@vm356:~# ls -al /var/lib/systemd/pstore/155741337/
+ total 92
+ drwxr-xr-x 2 root root  4096 May  9 09:50 .
+ drwxr-xr-x 4 root root    40 May  9 09:50 ..
+ -rw-r--r-- 1 root root  1610 May  9 09:50 dmesg-efi-155741337601001
+ -rw-r--r-- 1 root root  1778 May  9 09:50 dmesg-efi-155741337602001
+ -rw-r--r-- 1 root root  1726 May  9 09:50 dmesg-efi-155741337603001
+ -rw-r--r-- 1 root root  1746 May  9 09:50 dmesg-efi-155741337604001
+ -rw-r--r-- 1 root root  1686 May  9 09:50 dmesg-efi-155741337605001
+ -rw-r--r-- 1 root root  1690 May  9 09:50 dmesg-efi-155741337606001
+ -rw-r--r-- 1 root root  1775 May  9 09:50 dmesg-efi-155741337607001
+ -rw-r--r-- 1 root root  1811 May  9 09:50 dmesg-efi-155741337608001
+ -rw-r--r-- 1 root root  1817 May  9 09:50 dmesg-efi-155741337609001
+ -rw-r--r-- 1 root root  1795 May  9 09:50 dmesg-efi-155741337710001
+ -rw-r--r-- 1 root root  1770 May  9 09:50 dmesg-efi-155741337711001
+ -rw-r--r-- 1 root root  1796 May  9 09:50 dmesg-efi-155741337712001
+ -rw-r--r-- 1 root root  1787 May  9 09:50 dmesg-efi-155741337713001
+ -rw-r--r-- 1 root root  1808 May  9 09:50 dmesg-efi-155741337714001
+ -rw-r--r-- 1 root root  1754 May  9 09:50 dmesg-efi-155741337715001
+ -rw-r--r-- 1 root root 26754 May  9 09:50 dmesg.txt
+
+where dmesg.txt is reconstructed from the group of related
+dmesg-efi-155741337* files.
+
+Configuration file:
+The pstore.conf configuration file has four settings, described below.
+ - Storage : one of "none", "external", or "journal". With "none", this
+   tool leaves the contents of pstore untouched. With "external", the
+   contents of the pstore are moved into the /var/lib/systemd/pstore,
+   as well as logged into the journal.  With "journal", the contents of
+   the pstore are recorded only in the systemd journal. The default is
+   "external".
+ - Unlink : is a boolean. When "true", the default, then files in the
+   pstore are removed once processed. When "false", processing of the
+   pstore occurs normally, but the pstore files remain.
+
+References:
+[1] "Persistent storage for a kernel's dying breath",
+    March 23, 2011.
+    https://lwn.net/Articles/434821/
+
+[2] "Advanced Configuration and Power Interface Specification",
+    version 6.2, May 2017.
+    https://www.uefi.org/sites/default/files/resources/ACPI_6_2.pdf
+
+[3] "Unified Extensible Firmware Interface Specification",
+    version 2.8, March 2019.
+    https://uefi.org/sites/default/files/resources/UEFI_Spec_2_8_final.pdf
+
+[4] "The kernel’s command-line parameters",
+    https://static.lwn.net/kerneldoc/admin-guide/kernel-parameters.html
+
+(cherry picked from commit 9b4abc69b201e5d7295e1b0762883659f053e747)
+
+Resolves: #2158832
+---
+ man/pstore.conf.xml             |  89 +++++++
+ man/rules/meson.build           |   2 +
+ man/systemd-pstore.xml          |  99 ++++++++
+ meson.build                     |  20 ++
+ meson_options.txt               |   2 +
+ src/pstore/meson.build          |  10 +
+ src/pstore/pstore.c             | 395 ++++++++++++++++++++++++++++++++
+ src/pstore/pstore.conf          |  16 ++
+ units/meson.build               |   1 +
+ units/systemd-pstore.service.in |  24 ++
+ 10 files changed, 658 insertions(+)
+ create mode 100644 man/pstore.conf.xml
+ create mode 100644 man/systemd-pstore.xml
+ create mode 100644 src/pstore/meson.build
+ create mode 100644 src/pstore/pstore.c
+ create mode 100644 src/pstore/pstore.conf
+ create mode 100644 units/systemd-pstore.service.in
+
+diff --git a/man/pstore.conf.xml b/man/pstore.conf.xml
+new file mode 100644
+index 0000000000..b5cda47d02
+--- /dev/null
++++ b/man/pstore.conf.xml
+@@ -0,0 +1,89 @@
++<?xml version='1.0'?>
++<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
++  "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
++<!-- SPDX-License-Identifier: LGPL-2.1+ -->
++
++<refentry id="pstore.conf" conditional="ENABLE_PSTORE"
++          xmlns:xi="http://www.w3.org/2001/XInclude">
++  <refentryinfo>
++    <title>pstore.conf</title>
++    <productname>systemd</productname>
++  </refentryinfo>
++
++  <refmeta>
++    <refentrytitle>pstore.conf</refentrytitle>
++    <manvolnum>5</manvolnum>
++  </refmeta>
++
++  <refnamediv>
++    <refname>pstore.conf</refname>
++    <refname>pstore.conf.d</refname>
++    <refpurpose>PStore configuration file</refpurpose>
++  </refnamediv>
++
++  <refsynopsisdiv>
++    <para>
++    <filename>/etc/systemd/pstore.conf</filename>
++    <filename>/etc/systemd/pstore.conf.d/*</filename>
++    </para>
++  </refsynopsisdiv>
++
++  <refsect1>
++    <title>Description</title>
++
++    <para>This file configures the behavior of
++    <citerefentry><refentrytitle>systemd-pstore</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
++    a tool for archiving the contents of the persistent storage filesystem,
++    <ulink url="https://www.kernel.org/doc/Documentation/ABI/testing/pstore">pstore</ulink>.
++    </para>
++  </refsect1>
++
++  <xi:include href="standard-conf.xml" xpointer="main-conf" />
++
++  <refsect1>
++    <title>Options</title>
++
++    <para>All options are configured in the
++    <literal>[PStore]</literal> section:</para>
++
++    <variablelist>
++
++      <varlistentry>
++        <term><varname>Storage=</varname></term>
++
++        <listitem><para>Controls where to archive (i.e. copy) files from the pstore filesystem. One of <literal>none</literal>,
++        <literal>external</literal>, and <literal>journal</literal>. When
++        <literal>none</literal>, the tool exits without processing files in the pstore filesystem.
++        When <literal>external</literal> (the default), files are archived into <filename>/var/lib/systemd/pstore/</filename>,
++        and logged into the journal.
++        When <literal>journal</literal>, pstore file contents are logged only in the journal.</para>
++        </listitem>
++
++      </varlistentry>
++
++      <varlistentry>
++        <term><varname>Unlink=</varname></term>
++
++        <listitem><para>Controls whether or not files are removed from pstore after processing.
++        Takes a boolean value. When true, a pstore file is removed from the pstore once it has been
++        archived (either to disk or into the journal). When false, processing of pstore files occurs
++        normally, but the files remain in the pstore.
++        The default is true in order to maintain the pstore in a nearly empty state, so that the pstore
++        has storage available for the next kernel error event.
++        </para></listitem>
++      </varlistentry>
++    </variablelist>
++
++    <para>The defaults for all values are listed as comments in the
++    template <filename>/etc/systemd/pstore.conf</filename> file that
++    is installed by default.</para>
++  </refsect1>
++
++  <refsect1>
++    <title>See Also</title>
++    <para>
++      <citerefentry><refentrytitle>systemd-journald.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
++    </para>
++  </refsect1>
++
++</refentry>
+diff --git a/man/rules/meson.build b/man/rules/meson.build
+index e6c0a99bbd..6295330c5e 100644
+--- a/man/rules/meson.build
++++ b/man/rules/meson.build
+@@ -44,6 +44,7 @@ manpages = [
+  ['os-release', '5', [], ''],
+  ['pam_systemd', '8', [], 'HAVE_PAM'],
+  ['portablectl', '1', [], 'ENABLE_PORTABLED'],
++ ['pstore.conf', '5', ['pstore.conf.d'], 'ENABLE_PSTORE'],
+  ['resolvectl', '1', ['resolvconf'], 'ENABLE_RESOLVE'],
+  ['resolved.conf', '5', ['resolved.conf.d'], 'ENABLE_RESOLVE'],
+  ['runlevel', '8', [], 'ENABLE_UTMP'],
+@@ -633,6 +634,7 @@ manpages = [
+  ['systemd-nspawn', '1', [], ''],
+  ['systemd-path', '1', [], ''],
+  ['systemd-portabled.service', '8', ['systemd-portabled'], 'ENABLE_PORTABLED'],
++ ['systemd-pstore', '8', ['systemd-pstore.service'], 'ENABLE_PSTORE'],
+  ['systemd-quotacheck.service',
+   '8',
+   ['systemd-quotacheck'],
+diff --git a/man/systemd-pstore.xml b/man/systemd-pstore.xml
+new file mode 100644
+index 0000000000..dd1aa5e83b
+--- /dev/null
++++ b/man/systemd-pstore.xml
+@@ -0,0 +1,99 @@
++<?xml version='1.0'?>
++<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
++  "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
++<!-- SPDX-License-Identifier: LGPL-2.1+ -->
++
++<refentry id="systemd-pstore" conditional='ENABLE_PSTORE'
++          xmlns:xi="http://www.w3.org/2001/XInclude">
++
++  <refentryinfo>
++    <title>systemd-pstore</title>
++    <productname>systemd</productname>
++  </refentryinfo>
++
++  <refmeta>
++    <refentrytitle>systemd-pstore</refentrytitle>
++    <manvolnum>8</manvolnum>
++  </refmeta>
++
++  <refnamediv>
++    <refname>systemd-pstore</refname>
++    <refname>systemd-pstore.service</refname>
++    <refpurpose>Tool to archive contents of the persistent storage filesytem</refpurpose>
++  </refnamediv>
++
++  <refsynopsisdiv>
++    <para><filename>/usr/lib/systemd/systemd-pstore</filename></para>
++    <para><filename>systemd-pstore.service</filename></para>
++  </refsynopsisdiv>
++
++  <refsect1>
++    <title>Description</title>
++    <para><filename>systemd-pstore.service</filename> is a system service that archives the
++    contents of the Linux persistent storage filesystem, pstore, to other storage,
++    thus preserving the existing information contained in the pstore, and clearing
++    pstore storage for future error events.</para>
++
++    <para>Linux provides a persistent storage file system, pstore, that can store
++    error records when the kernel dies (or reboots or powers-off). These records in
++    turn can be referenced to debug kernel problems (currently the kernel stuffs
++    the tail of the dmesg, which also contains a stack backtrace, into pstore).</para>
++
++    <para>The pstore file system supports a variety of backends that map onto persistent
++    storage, such as the ACPI ERST and UEFI variables. The pstore backends
++    typically offer a relatively small amount of persistent storage, e.g. 64KiB,
++    which can quickly fill up and thus prevent subsequent kernel crashes from
++    recording errors. Thus there is a need to monitor and extract the pstore
++    contents so that future kernel problems can also record information in the
++    pstore.</para>
++
++    <para>The pstore service is independent of the kdump service. In cloud environments
++    specifically, host and guest filesystems are on remote filesystems (eg. iSCSI
++    or NFS), thus kdump relies [implicitly and/or explicitly] upon proper operation
++    of networking software *and* hardware *and* infrastructure.  Thus it may not be
++    possible to capture a kernel coredump to a file since writes over the network
++    may not be possible.</para>
++
++    <para>The pstore backend, on the other hand, is completely local and provides a path
++    to store error records which will survive a reboot and aid in post-mortem
++    debugging.</para>
++
++    <para>The <command>systemd-pstore</command> executable does the actual work. Upon starting,
++    the <filename>pstore.conf</filename> is read to obtain options, then the /sys/fs/pstore
++    directory contents are processed according to the options. Pstore files are written to the
++    journal, and optionally saved into /var/lib/systemd/pstore.</para>
++  </refsect1>
++
++  <refsect1>
++    <title>Configuration</title>
++
++    <para>The behavior of <command>systemd-pstore</command> is configured through the configuration file
++    <filename>/etc/systemd/pstore.conf</filename> and corresponding snippets
++    <filename>/etc/systemd/pstore.conf.d/*.conf</filename>, see
++    <citerefentry><refentrytitle>pstore.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
++    </para>
++
++    <refsect2>
++      <title>Disabling pstore processing</title>
++
++      <para>To disable pstore processing by <command>systemd-pstore</command>,
++      set <programlisting>Storage=none</programlisting> in
++      <citerefentry><refentrytitle>pstore.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
++      </para>
++    </refsect2>
++  </refsect1>
++
++  <refsect1>
++    <title>Usage</title>
++    <para>Data stored in the journal can be viewed with
++    <citerefentry><refentrytitle>journalctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
++    as usual.</para>
++  </refsect1>
++
++  <refsect1>
++    <title>See Also</title>
++    <para>
++      <citerefentry><refentrytitle>pstore.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>
++    </para>
++  </refsect1>
++</refentry>
+diff --git a/meson.build b/meson.build
+index af4cf331da..972a8fb6f7 100644
+--- a/meson.build
++++ b/meson.build
+@@ -1224,6 +1224,7 @@ foreach term : ['utmp',
+                 'environment-d',
+                 'binfmt',
+                 'coredump',
++                'pstore',
+                 'resolve',
+                 'logind',
+                 'hostnamed',
+@@ -1439,6 +1440,7 @@ subdir('src/network')
+ subdir('src/analyze')
+ subdir('src/journal-remote')
+ subdir('src/coredump')
++subdir('src/pstore')
+ subdir('src/hostname')
+ subdir('src/import')
+ subdir('src/kernel-install')
+@@ -2151,6 +2153,23 @@ if conf.get('ENABLE_COREDUMP') == 1
+         public_programs += [exe]
+ endif
+ 
++if conf.get('ENABLE_PSTORE') == 1
++        executable('systemd-pstore',
++                   systemd_pstore_sources,
++                   include_directories : includes,
++                   link_with : [libshared],
++                   dependencies : [threads,
++                                   libacl,
++                                   libdw,
++                                   libxz,
++                                   liblz4],
++                   install_rpath : rootlibexecdir,
++                   install : true,
++                   install_dir : rootlibexecdir)
++
++        public_programs += exe
++endif
++
+ if conf.get('ENABLE_BINFMT') == 1
+         exe = executable('systemd-binfmt',
+                          'src/binfmt/binfmt.c',
+@@ -3014,6 +3033,7 @@ foreach tuple : [
+         ['resolve'],
+         ['DNS-over-TLS'],
+         ['coredump'],
++        ['pstore'],
+         ['polkit'],
+         ['legacy pkla',      install_polkit_pkla],
+         ['efi'],
+diff --git a/meson_options.txt b/meson_options.txt
+index 213079ac15..5624304bf4 100644
+--- a/meson_options.txt
++++ b/meson_options.txt
+@@ -76,6 +76,8 @@ option('binfmt', type : 'boolean',
+        description : 'support for custom binary formats')
+ option('coredump', type : 'boolean',
+        description : 'install the coredump handler')
++option('pstore', type : 'boolean',
++       description : 'install the pstore archival tool')
+ option('logind', type : 'boolean',
+        description : 'install the systemd-logind stack')
+ option('hostnamed', type : 'boolean',
+diff --git a/src/pstore/meson.build b/src/pstore/meson.build
+new file mode 100644
+index 0000000000..adbac24b54
+--- /dev/null
++++ b/src/pstore/meson.build
+@@ -0,0 +1,10 @@
++# SPDX-License-Identifier: LGPL-2.1+
++
++systemd_pstore_sources = files('''
++        pstore.c
++'''.split())
++
++if conf.get('ENABLE_PSTORE') == 1
++        install_data('pstore.conf',
++                     install_dir : pkgsysconfdir)
++endif
+diff --git a/src/pstore/pstore.c b/src/pstore/pstore.c
+new file mode 100644
+index 0000000000..f95e016eb6
+--- /dev/null
++++ b/src/pstore/pstore.c
+@@ -0,0 +1,395 @@
++/* SPDX-License-Identifier: LGPL-2.1+ */
++
++/* Copyright © 2019 Oracle and/or its affiliates. */
++
++/* Generally speaking, the pstore contains a small number of files
++ * that in turn contain a small amount of data.  */
++#include <errno.h>
++#include <stdio.h>
++#include <stdio_ext.h>
++#include <sys/prctl.h>
++#include <sys/xattr.h>
++#include <unistd.h>
++
++#include "sd-daemon.h"
++#include "sd-journal.h"
++#include "sd-login.h"
++#include "sd-messages.h"
++
++#include "acl-util.h"
++#include "alloc-util.h"
++#include "capability-util.h"
++#include "cgroup-util.h"
++#include "compress.h"
++#include "conf-parser.h"
++#include "copy.h"
++#include "dirent-util.h"
++#include "escape.h"
++#include "fd-util.h"
++#include "fileio.h"
++#include "fs-util.h"
++#include "io-util.h"
++#include "journal-importer.h"
++#include "log.h"
++#include "macro.h"
++#include "missing.h"
++#include "mkdir.h"
++#include "parse-util.h"
++#include "process-util.h"
++#include "signal-util.h"
++#include "socket-util.h"
++#include "special.h"
++#include "string-table.h"
++#include "string-util.h"
++#include "strv.h"
++#include "user-util.h"
++#include "util.h"
++
++/* Command line argument handling */
++typedef enum PStoreStorage {
++        PSTORE_STORAGE_NONE,
++        PSTORE_STORAGE_EXTERNAL,
++        PSTORE_STORAGE_JOURNAL,
++        _PSTORE_STORAGE_MAX,
++        _PSTORE_STORAGE_INVALID = -1
++} PStoreStorage;
++
++static const char* const pstore_storage_table[_PSTORE_STORAGE_MAX] = {
++        [PSTORE_STORAGE_NONE] = "none",
++        [PSTORE_STORAGE_EXTERNAL] = "external",
++        [PSTORE_STORAGE_JOURNAL] = "journal",
++};
++
++DEFINE_PRIVATE_STRING_TABLE_LOOKUP(pstore_storage, PStoreStorage);
++static DEFINE_CONFIG_PARSE_ENUM(config_parse_pstore_storage, pstore_storage, PStoreStorage, "Failed to parse storage setting");
++
++static PStoreStorage arg_storage = PSTORE_STORAGE_EXTERNAL;
++
++static bool arg_unlink = true;
++static const char *arg_sourcedir = "/sys/fs/pstore";
++static const char *arg_archivedir = "/var/lib/systemd/pstore";
++
++static int parse_config(void) {
++        static const ConfigTableItem items[] = {
++                { "PStore", "Unlink",  config_parse_bool,           0, &arg_unlink },
++                { "PStore", "Storage", config_parse_pstore_storage, 0, &arg_storage },
++                {}
++        };
++
++        return config_parse_many_nulstr(PKGSYSCONFDIR "/pstore.conf",
++                                        CONF_PATHS_NULSTR("systemd/pstore.conf.d"),
++                                        "PStore\0",
++                                        config_item_table_lookup, items,
++                                        CONFIG_PARSE_WARN, NULL);
++}
++
++/* File list handling - PStoreEntry is the struct and
++ * and PStoreEntry is the type that contains all info
++ * about a pstore entry.  */
++typedef struct PStoreEntry {
++        struct dirent dirent;
++        bool is_binary;
++        bool handled;
++        char *content;
++        size_t content_size;
++} PStoreEntry;
++
++typedef struct PStoreList {
++        PStoreEntry *entries;
++        size_t n_entries;
++        size_t n_entries_allocated;
++} PStoreList;
++
++static void pstore_entries_reset(PStoreList *list) {
++        for (size_t i = 0; i < list->n_entries; i++)
++                free(list->entries[i].content);
++        free(list->entries);
++        list->n_entries = 0;
++}
++
++static int compare_pstore_entries(const void *_a, const void *_b) {
++        PStoreEntry *a = (PStoreEntry *)_a, *b = (PStoreEntry *)_b;
++        return strcmp(a->dirent.d_name, b->dirent.d_name);
++}
++
++static int move_file(PStoreEntry *pe, const char *subdir) {
++        _cleanup_free_ char *ifd_path = NULL;
++        _cleanup_free_ char *ofd_path = NULL;
++        int r = 0;
++        struct iovec iovec[2] = {};
++        int n_iovec = 0;
++        _cleanup_free_ void *field = NULL;
++        const char *suffix = NULL;
++        size_t field_size;
++
++        if (pe->handled)
++                return 0;
++
++        ifd_path = path_join(NULL, arg_sourcedir, pe->dirent.d_name);
++        if (!ifd_path)
++                return log_oom();
++
++        ofd_path = path_join(arg_archivedir, subdir, pe->dirent.d_name);
++        if (!ofd_path)
++                return log_oom();
++
++        /* Always log to the journal */
++        suffix = arg_storage == PSTORE_STORAGE_EXTERNAL ? strjoina(" moved to ", ofd_path) : (char *)".";
++        field = strjoina("MESSAGE=PStore ", pe->dirent.d_name, suffix);
++        iovec[n_iovec++] = IOVEC_MAKE_STRING(field);
++
++        field_size = strlen("FILE=") + pe->content_size;
++        field = malloc(field_size);
++        if (!field)
++                return log_oom();
++        memcpy(stpcpy(field, "FILE="), pe->content, pe->content_size);
++        iovec[n_iovec++] = IOVEC_MAKE(field, field_size);
++
++        r = sd_journal_sendv(iovec, n_iovec);
++        if (r < 0)
++                return log_error_errno(r, "Failed to log pstore entry: %m");
++
++        if (arg_storage == PSTORE_STORAGE_EXTERNAL) {
++                /* Move file from pstore to external storage */
++                r = mkdir_parents(ofd_path, 0755);
++                if (r < 0)
++                        return log_error_errno(r, "Failed to create directoy %s: %m", ofd_path);
++                r = copy_file_atomic(ifd_path, ofd_path, 0600, 0, COPY_REPLACE);
++                if (r < 0)
++                        return log_error_errno(r, "Failed to copy_file_atomic: %s to %s", ifd_path, ofd_path);
++        }
++
++        /* If file copied properly, remove it from pstore */
++        if (arg_unlink)
++                (void) unlink(ifd_path);
++
++        pe->handled = true;
++
++        return 0;
++}
++
++static int write_dmesg(const char *dmesg, size_t size, const char *id) {
++        _cleanup_(unlink_and_freep) char *ofd_path = NULL;
++        _cleanup_free_ char *tmp_path = NULL;
++        _cleanup_close_ int ofd = -1;
++        ssize_t wr;
++        int r;
++
++        if (isempty(dmesg) || size == 0)
++                return 0;
++
++        /* log_info("Record ID %s", id); */
++
++        ofd_path = path_join(arg_archivedir, id, "dmesg.txt");
++        if (!ofd_path)
++                return log_oom();
++
++        ofd = open_tmpfile_linkable(ofd_path, O_CLOEXEC|O_CREAT|O_TRUNC|O_WRONLY, &tmp_path);
++        if (ofd < 0)
++                return log_error_errno(ofd, "Failed to open temporary file %s: %m", ofd_path);
++        wr = write(ofd, dmesg, size);
++        if (wr < 0)
++                return log_error_errno(errno, "Failed to store dmesg to %s: %m", ofd_path);
++        if (wr != (ssize_t)size)
++                return log_error_errno(-EIO, "Failed to store dmesg to %s. %zu bytes are lost.", ofd_path, size - wr);
++        r = link_tmpfile(ofd, tmp_path, ofd_path);
++        if (r < 0)
++                return log_error_errno(r, "Failed to write temporary file %s: %m", ofd_path);
++        ofd_path = mfree(ofd_path);
++
++        return 0;
++}
++
++static void process_dmesg_files(PStoreList *list) {
++        /* Move files, reconstruct dmesg.txt */
++        PStoreEntry *pe;
++        _cleanup_free_ char *dmesg = NULL;
++        size_t dmesg_size = 0;
++        _cleanup_free_ char *dmesg_id = NULL;
++
++        /* Handle each dmesg file: files processed in reverse
++         * order so as to properly reconstruct original dmesg */
++        for (size_t n = list->n_entries; n > 0; n--) {
++                bool move_file_and_continue = false;
++                _cleanup_free_ char *pe_id = NULL;
++                char *p;
++                size_t plen;
++
++                pe = &list->entries[n-1];
++
++                if (pe->handled)
++                        continue;
++                if (!startswith(pe->dirent.d_name, "dmesg-"))
++                        continue;
++
++                if (endswith(pe->dirent.d_name, ".enc.z")) /* indicates a problem */
++                        move_file_and_continue = true;
++                p = strrchr(pe->dirent.d_name, '-');
++                if (!p)
++                        move_file_and_continue = true;
++
++                if (move_file_and_continue) {
++                        /* A dmesg file on which we do NO additional processing */
++                        (void) move_file(pe, NULL);
++                        continue;
++                }
++
++                /* See if this file is one of a related group of files
++                 * in order to reconstruct dmesg */
++
++                /* When dmesg is written into pstore, it is done so in
++                 * small chunks, whatever the exchange buffer size is
++                 * with the underlying pstore backend (ie. EFI may be
++                 * ~2KiB), which means an example pstore with approximately
++                 * 64KB of storage may have up to roughly 32 dmesg files
++                 * that could be related, depending upon the size of the
++                 * original dmesg.
++                 *
++                 * Here we look at the dmesg filename and try to discern
++                 * if files are part of a related group, meaning the same
++                 * original dmesg.
++                 *
++                 * The two known pstore backends are EFI and ERST. These
++                 * backends store data in the Common Platform Error
++                 * Record, CPER, format. The dmesg- filename contains the
++                 * CPER record id, a 64bit number (in decimal notation).
++                 * In Linux, the record id is encoded with two digits for
++                 * the dmesg part (chunk) number and 3 digits for the
++                 * count number. So allowing an additional digit to
++                 * compensate for advancing time, this code ignores the
++                 * last six digits of the filename in determining the
++                 * record id.
++                 *
++                 * For the EFI backend, the record id encodes an id in the
++                 * upper 32 bits, and a timestamp in the lower 32-bits.
++                 * So ignoring the least significant 6 digits has proven
++                 * to generally identify related dmesg entries.  */
++#define PSTORE_FILENAME_IGNORE 6
++
++                /* determine common portion of record id */
++                ++p; /* move beyond dmesg- */
++                plen = strlen(p);
++                if (plen > PSTORE_FILENAME_IGNORE) {
++                        pe_id = memdup_suffix0(p, plen - PSTORE_FILENAME_IGNORE);
++                        if (!pe_id) {
++                                log_oom();
++                                return;
++                        }
++                } else
++                        pe_id = mfree(pe_id);
++
++                /* Now move file from pstore to archive storage */
++                move_file(pe, pe_id);
++
++                /* If the current record id is NOT the same as the
++                 * previous record id, then start a new dmesg.txt file */
++                if (!pe_id || !dmesg_id || !streq(pe_id, dmesg_id)) {
++                        /* Encountered a new dmesg group, close out old one, open new one */
++                        if (dmesg) {
++                                (void) write_dmesg(dmesg, dmesg_size, dmesg_id);
++                                dmesg = mfree(dmesg);
++                                dmesg_size = 0;
++                        }
++
++                        /* now point dmesg_id to storage of pe_id */
++                        free_and_replace(dmesg_id, pe_id);
++                }
++
++                /* Reconstruction of dmesg is done as a useful courtesy, do not log errors */
++                dmesg = realloc(dmesg, dmesg_size + strlen(pe->dirent.d_name) + strlen(":\n") + pe->content_size + 1);
++                if (dmesg) {
++                        dmesg_size += sprintf(&dmesg[dmesg_size], "%s:\n", pe->dirent.d_name);
++                        if (pe->content) {
++                                memcpy(&dmesg[dmesg_size], pe->content, pe->content_size);
++                                dmesg_size += pe->content_size;
++                        }
++                }
++
++                pe_id = mfree(pe_id);
++        }
++        if (dmesg)
++                (void) write_dmesg(dmesg, dmesg_size, dmesg_id);
++}
++
++static int list_files(PStoreList *list, const char *sourcepath) {
++        _cleanup_(closedirp) DIR *dirp = NULL;
++        struct dirent *de;
++        int r = 0;
++
++        dirp = opendir(sourcepath);
++        if (!dirp)
++                return log_error_errno(errno, "Failed to opendir %s: %m", sourcepath);
++
++        FOREACH_DIRENT(de, dirp, return log_error_errno(errno, "Failed to iterate through %s: %m", sourcepath)) {
++                _cleanup_free_ char *ifd_path = NULL;
++
++                ifd_path = path_join(NULL, sourcepath, de->d_name);
++                if (!ifd_path)
++                        return log_oom();
++
++                _cleanup_free_ char *buf = NULL;
++                size_t buf_size;
++
++                /* Now read contents of pstore file */
++                r = read_full_file(ifd_path, &buf, &buf_size);
++                if (r < 0) {
++                        log_warning_errno(r, "Failed to read file %s: %m", ifd_path);
++                        continue;
++                }
++
++                if (!GREEDY_REALLOC(list->entries, list->n_entries_allocated, list->n_entries + 1))
++                        return log_oom();
++
++                list->entries[list->n_entries++] = (PStoreEntry) {
++                        .dirent = *de,
++                        .content = TAKE_PTR(buf),
++                        .content_size = buf_size,
++                        .is_binary = true,
++                        .handled = false,
++                };
++        }
++
++        return r;
++}
++
++static int run(int argc, char *argv[]) {
++        _cleanup_(pstore_entries_reset) PStoreList list = {};
++        int r;
++
++        log_open();
++
++        /* Ignore all parse errors */
++        (void) parse_config();
++
++        log_debug("Selected storage '%s'.", pstore_storage_to_string(arg_storage));
++        log_debug("Selected Unlink '%d'.", arg_unlink);
++
++        if (arg_storage == PSTORE_STORAGE_NONE)
++                /* Do nothing, intentionally, leaving pstore untouched */
++                return 0;
++
++        /* Obtain list of files in pstore */
++        r = list_files(&list, arg_sourcedir);
++        if (r < 0)
++                return r;
++
++        /* Handle each pstore file */
++        /* Sort files lexigraphically ascending, generally needed by all */
++        qsort_safe(list.entries, list.n_entries, sizeof(PStoreEntry), compare_pstore_entries);
++
++        /* Process known file types */
++        process_dmesg_files(&list);
++
++        /* Move left over files out of pstore */
++        for (size_t n = 0; n < list.n_entries; n++)
++                move_file(&list.entries[n], NULL);
++
++        return 0;
++}
++
++int main(int argc, char *argv[]) {
++        int r;
++
++        r = run(argc, argv);
++        return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
++}
+diff --git a/src/pstore/pstore.conf b/src/pstore/pstore.conf
+new file mode 100644
+index 0000000000..93a8b6707c
+--- /dev/null
++++ b/src/pstore/pstore.conf
+@@ -0,0 +1,16 @@
++#  This file is part of systemd.
++#
++#  systemd is free software; you can redistribute it and/or modify it
++#  under the terms of the GNU Lesser General Public License as published by
++#  the Free Software Foundation; either version 2.1 of the License, or
++#  (at your option) any later version.
++#
++# Entries in this file show the compile time defaults.
++# You can change settings by editing this file.
++# Defaults can be restored by simply deleting this file.
++#
++# See pstore.conf(5) for details.
++
++[PStore]
++#Storage=external
++#Unlink=yes
+diff --git a/units/meson.build b/units/meson.build
+index a74fa95195..e8e64eb30a 100644
+--- a/units/meson.build
++++ b/units/meson.build
+@@ -136,6 +136,7 @@ in_units = [
+         ['systemd-binfmt.service',               'ENABLE_BINFMT',
+          'sysinit.target.wants/'],
+         ['systemd-coredump@.service',            'ENABLE_COREDUMP'],
++        ['systemd-pstore.service',               'ENABLE_PSTORE'],
+         ['systemd-firstboot.service',            'ENABLE_FIRSTBOOT',
+          'sysinit.target.wants/'],
+         ['systemd-fsck-root.service',            ''],
+diff --git a/units/systemd-pstore.service.in b/units/systemd-pstore.service.in
+new file mode 100644
+index 0000000000..fec2b1aebf
+--- /dev/null
++++ b/units/systemd-pstore.service.in
+@@ -0,0 +1,24 @@
++#  SPDX-License-Identifier: LGPL-2.1+
++#
++#  This file is part of systemd.
++#
++#  systemd is free software; you can redistribute it and/or modify it
++#  under the terms of the GNU Lesser General Public License as published by
++#  the Free Software Foundation; either version 2.1 of the License, or
++#  (at your option) any later version.
++
++[Unit]
++Description=Platform Persistent Storage Archival
++Documentation=man:systemd-pstore(8)
++DefaultDependencies=no
++Wants=systemd-remount-fs.service
++After=systemd-remount-fs.service
++
++[Service]
++Type=oneshot
++ExecStart=@rootlibexecdir@/systemd-pstore
++RemainAfterExit=yes
++StateDirectory=systemd/pstore
++
++[Install]
++WantedBy=systemd-remount-fs.service
diff --git a/SOURCES/0877-meson-drop-redundant-line.patch b/SOURCES/0877-meson-drop-redundant-line.patch
new file mode 100644
index 0000000..ed13771
--- /dev/null
+++ b/SOURCES/0877-meson-drop-redundant-line.patch
@@ -0,0 +1,27 @@
+From c95ba53ab720dfbd7f692e0a87d7f5d4f89ea36b Mon Sep 17 00:00:00 2001
+From: Yu Watanabe <watanabe.yu+github@gmail.com>
+Date: Mon, 22 Jul 2019 10:46:53 +0900
+Subject: [PATCH] meson: drop redundant line
+
+Found by @mattiasb.
+
+(cherry picked from commit 3f708e7f6909faad307bdb60ed0f8d68e84f6584)
+
+Related: #2158832
+---
+ meson.build | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/meson.build b/meson.build
+index 972a8fb6f7..673800a1a7 100644
+--- a/meson.build
++++ b/meson.build
+@@ -2166,8 +2166,6 @@ if conf.get('ENABLE_PSTORE') == 1
+                    install_rpath : rootlibexecdir,
+                    install : true,
+                    install_dir : rootlibexecdir)
+-
+-        public_programs += exe
+ endif
+ 
+ if conf.get('ENABLE_BINFMT') == 1
diff --git a/SOURCES/0878-pstore-drop-unnecessary-initializations.patch b/SOURCES/0878-pstore-drop-unnecessary-initializations.patch
new file mode 100644
index 0000000..6bc6613
--- /dev/null
+++ b/SOURCES/0878-pstore-drop-unnecessary-initializations.patch
@@ -0,0 +1,48 @@
+From 7e4b7cc35af0e3b3afbf32fa0fd9961cd01ad9a9 Mon Sep 17 00:00:00 2001
+From: Yu Watanabe <watanabe.yu+github@gmail.com>
+Date: Mon, 22 Jul 2019 10:52:12 +0900
+Subject: [PATCH] pstore: drop unnecessary initializations
+
+(cherry picked from commit 2e4effd129343d22bfed34e94810d3f87c8f0e85)
+
+Related: #2158832
+---
+ src/pstore/pstore.c | 15 ++++++---------
+ 1 file changed, 6 insertions(+), 9 deletions(-)
+
+diff --git a/src/pstore/pstore.c b/src/pstore/pstore.c
+index f95e016eb6..e6a342fc50 100644
+--- a/src/pstore/pstore.c
++++ b/src/pstore/pstore.c
+@@ -113,14 +113,12 @@ static int compare_pstore_entries(const void *_a, const void *_b) {
+ }
+ 
+ static int move_file(PStoreEntry *pe, const char *subdir) {
+-        _cleanup_free_ char *ifd_path = NULL;
+-        _cleanup_free_ char *ofd_path = NULL;
+-        int r = 0;
+-        struct iovec iovec[2] = {};
+-        int n_iovec = 0;
++        _cleanup_free_ char *ifd_path = NULL, *ofd_path = NULL;
+         _cleanup_free_ void *field = NULL;
+-        const char *suffix = NULL;
++        struct iovec iovec[2];
++        const char *suffix;
+         size_t field_size;
++        int n_iovec = 0, r;
+ 
+         if (pe->handled)
+                 return 0;
+@@ -202,10 +200,9 @@ static int write_dmesg(const char *dmesg, size_t size, const char *id) {
+ 
+ static void process_dmesg_files(PStoreList *list) {
+         /* Move files, reconstruct dmesg.txt */
+-        PStoreEntry *pe;
+-        _cleanup_free_ char *dmesg = NULL;
++        _cleanup_free_ char *dmesg = NULL, *dmesg_id = NULL;
+         size_t dmesg_size = 0;
+-        _cleanup_free_ char *dmesg_id = NULL;
++        PStoreEntry *pe;
+ 
+         /* Handle each dmesg file: files processed in reverse
+          * order so as to properly reconstruct original dmesg */
diff --git a/SOURCES/0879-pstopre-fix-return-value-of-list_files.patch b/SOURCES/0879-pstopre-fix-return-value-of-list_files.patch
new file mode 100644
index 0000000..72e8698
--- /dev/null
+++ b/SOURCES/0879-pstopre-fix-return-value-of-list_files.patch
@@ -0,0 +1,46 @@
+From a0485b96118d3d2ac439f510e404ffb3db03e23f Mon Sep 17 00:00:00 2001
+From: Yu Watanabe <watanabe.yu+github@gmail.com>
+Date: Mon, 22 Jul 2019 10:55:10 +0900
+Subject: [PATCH] pstopre: fix return value of list_files()
+
+Previously, the return value of the last read_full_file() is returned.
+This makes the error in read_full_file() is always ignored.
+
+(cherry picked from commit 337874a45fff46a80e4974c681a5e651f3a0fac9)
+
+Related: #2158832
+---
+ src/pstore/pstore.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/src/pstore/pstore.c b/src/pstore/pstore.c
+index e6a342fc50..2fbef48543 100644
+--- a/src/pstore/pstore.c
++++ b/src/pstore/pstore.c
+@@ -311,7 +311,7 @@ static void process_dmesg_files(PStoreList *list) {
+ static int list_files(PStoreList *list, const char *sourcepath) {
+         _cleanup_(closedirp) DIR *dirp = NULL;
+         struct dirent *de;
+-        int r = 0;
++        int r;
+ 
+         dirp = opendir(sourcepath);
+         if (!dirp)
+@@ -330,7 +330,7 @@ static int list_files(PStoreList *list, const char *sourcepath) {
+                 /* Now read contents of pstore file */
+                 r = read_full_file(ifd_path, &buf, &buf_size);
+                 if (r < 0) {
+-                        log_warning_errno(r, "Failed to read file %s: %m", ifd_path);
++                        log_warning_errno(r, "Failed to read file %s, skipping: %m", ifd_path);
+                         continue;
+                 }
+ 
+@@ -346,7 +346,7 @@ static int list_files(PStoreList *list, const char *sourcepath) {
+                 };
+         }
+ 
+-        return r;
++        return 0;
+ }
+ 
+ static int run(int argc, char *argv[]) {
diff --git a/SOURCES/0880-pstore-remove-temporary-file-on-failure.patch b/SOURCES/0880-pstore-remove-temporary-file-on-failure.patch
new file mode 100644
index 0000000..33bf5a0
--- /dev/null
+++ b/SOURCES/0880-pstore-remove-temporary-file-on-failure.patch
@@ -0,0 +1,36 @@
+From 58000dc7dd93ff6e8357de64154b0849d3c17c5d Mon Sep 17 00:00:00 2001
+From: Yu Watanabe <watanabe.yu+github@gmail.com>
+Date: Mon, 22 Jul 2019 11:01:43 +0900
+Subject: [PATCH] pstore: remove temporary file on failure
+
+(cherry picked from commit 03c5f6cc02648eeff3179b2b762d46b9e1889bb1)
+
+Related: #2158832
+---
+ src/pstore/pstore.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/src/pstore/pstore.c b/src/pstore/pstore.c
+index 2fbef48543..ce8080ceed 100644
+--- a/src/pstore/pstore.c
++++ b/src/pstore/pstore.c
+@@ -167,8 +167,8 @@ static int move_file(PStoreEntry *pe, const char *subdir) {
+ }
+ 
+ static int write_dmesg(const char *dmesg, size_t size, const char *id) {
+-        _cleanup_(unlink_and_freep) char *ofd_path = NULL;
+-        _cleanup_free_ char *tmp_path = NULL;
++        _cleanup_(unlink_and_freep) char *tmp_path = NULL;
++        _cleanup_free_ char *ofd_path = NULL;
+         _cleanup_close_ int ofd = -1;
+         ssize_t wr;
+         int r;
+@@ -193,7 +193,7 @@ static int write_dmesg(const char *dmesg, size_t size, const char *id) {
+         r = link_tmpfile(ofd, tmp_path, ofd_path);
+         if (r < 0)
+                 return log_error_errno(r, "Failed to write temporary file %s: %m", ofd_path);
+-        ofd_path = mfree(ofd_path);
++        tmp_path = mfree(tmp_path);
+ 
+         return 0;
+ }
diff --git a/SOURCES/0881-pstore-do-not-add-FILE-journal-entry-if-content_size.patch b/SOURCES/0881-pstore-do-not-add-FILE-journal-entry-if-content_size.patch
new file mode 100644
index 0000000..400dae5
--- /dev/null
+++ b/SOURCES/0881-pstore-do-not-add-FILE-journal-entry-if-content_size.patch
@@ -0,0 +1,57 @@
+From 5006e4bd9aecea40ca3d907adc692c4c8001a6c1 Mon Sep 17 00:00:00 2001
+From: Yu Watanabe <watanabe.yu+github@gmail.com>
+Date: Mon, 22 Jul 2019 11:08:06 +0900
+Subject: [PATCH] pstore: do not add FILE= journal entry if content_size == 0
+
+(cherry picked from commit 6bf18debddbe1b231f783617e054cc194bb36d1e)
+
+Related: #2158832
+---
+ src/pstore/pstore.c | 25 ++++++++++++++-----------
+ 1 file changed, 14 insertions(+), 11 deletions(-)
+
+diff --git a/src/pstore/pstore.c b/src/pstore/pstore.c
+index ce8080ceed..eb251d61c8 100644
+--- a/src/pstore/pstore.c
++++ b/src/pstore/pstore.c
+@@ -114,10 +114,8 @@ static int compare_pstore_entries(const void *_a, const void *_b) {
+ 
+ static int move_file(PStoreEntry *pe, const char *subdir) {
+         _cleanup_free_ char *ifd_path = NULL, *ofd_path = NULL;
+-        _cleanup_free_ void *field = NULL;
++        const char *suffix, *message;
+         struct iovec iovec[2];
+-        const char *suffix;
+-        size_t field_size;
+         int n_iovec = 0, r;
+ 
+         if (pe->handled)
+@@ -133,15 +131,20 @@ static int move_file(PStoreEntry *pe, const char *subdir) {
+ 
+         /* Always log to the journal */
+         suffix = arg_storage == PSTORE_STORAGE_EXTERNAL ? strjoina(" moved to ", ofd_path) : (char *)".";
+-        field = strjoina("MESSAGE=PStore ", pe->dirent.d_name, suffix);
+-        iovec[n_iovec++] = IOVEC_MAKE_STRING(field);
++        message = strjoina("MESSAGE=PStore ", pe->dirent.d_name, suffix);
++        iovec[n_iovec++] = IOVEC_MAKE_STRING(message);
+ 
+-        field_size = strlen("FILE=") + pe->content_size;
+-        field = malloc(field_size);
+-        if (!field)
+-                return log_oom();
+-        memcpy(stpcpy(field, "FILE="), pe->content, pe->content_size);
+-        iovec[n_iovec++] = IOVEC_MAKE(field, field_size);
++        if (pe->content_size > 0) {
++                _cleanup_free_ void *field = NULL;
++                size_t field_size;
++
++                field_size = strlen("FILE=") + pe->content_size;
++                field = malloc(field_size);
++                if (!field)
++                        return log_oom();
++                memcpy(stpcpy(field, "FILE="), pe->content, pe->content_size);
++                iovec[n_iovec++] = IOVEC_MAKE(field, field_size);
++        }
+ 
+         r = sd_journal_sendv(iovec, n_iovec);
+         if (r < 0)
diff --git a/SOURCES/0882-pstore-run-only-when-sys-fs-pstore-is-not-empty.patch b/SOURCES/0882-pstore-run-only-when-sys-fs-pstore-is-not-empty.patch
new file mode 100644
index 0000000..ea535a5
--- /dev/null
+++ b/SOURCES/0882-pstore-run-only-when-sys-fs-pstore-is-not-empty.patch
@@ -0,0 +1,24 @@
+From a7247899f156761934bcb4b380861b3d3ec5449f Mon Sep 17 00:00:00 2001
+From: Yu Watanabe <watanabe.yu+github@gmail.com>
+Date: Mon, 22 Jul 2019 14:09:12 +0900
+Subject: [PATCH] pstore: run only when /sys/fs/pstore is not empty
+
+(cherry picked from commit 6d4f213b1f6afb2901f0d97cec0e28e20809b713)
+
+Related: #2158832
+---
+ units/systemd-pstore.service.in | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/units/systemd-pstore.service.in b/units/systemd-pstore.service.in
+index fec2b1aebf..dde21bc33e 100644
+--- a/units/systemd-pstore.service.in
++++ b/units/systemd-pstore.service.in
+@@ -10,6 +10,7 @@
+ [Unit]
+ Description=Platform Persistent Storage Archival
+ Documentation=man:systemd-pstore(8)
++ConditionDirectoryNotEmpty=/sys/fs/pstore
+ DefaultDependencies=no
+ Wants=systemd-remount-fs.service
+ After=systemd-remount-fs.service
diff --git a/SOURCES/0883-pstore-fix-use-after-free.patch b/SOURCES/0883-pstore-fix-use-after-free.patch
new file mode 100644
index 0000000..3546fb3
--- /dev/null
+++ b/SOURCES/0883-pstore-fix-use-after-free.patch
@@ -0,0 +1,34 @@
+From 7f5bfbd5485e1cb779d7568cabb5783651fd9da3 Mon Sep 17 00:00:00 2001
+From: Michael Olbrich <m.olbrich@pengutronix.de>
+Date: Fri, 6 Sep 2019 15:04:01 +0200
+Subject: [PATCH] pstore: fix use after free
+
+The memory is still needed in the sd_journal_sendv() after the 'if' block.
+
+(cherry picked from commit 1e19f5ac0d680a63eccae7ef1fc6ce225dca0bbf)
+
+Related: #2158832
+---
+ src/pstore/pstore.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/pstore/pstore.c b/src/pstore/pstore.c
+index eb251d61c8..cafb1804c6 100644
+--- a/src/pstore/pstore.c
++++ b/src/pstore/pstore.c
+@@ -114,6 +114,7 @@ static int compare_pstore_entries(const void *_a, const void *_b) {
+ 
+ static int move_file(PStoreEntry *pe, const char *subdir) {
+         _cleanup_free_ char *ifd_path = NULL, *ofd_path = NULL;
++        _cleanup_free_ void *field = NULL;
+         const char *suffix, *message;
+         struct iovec iovec[2];
+         int n_iovec = 0, r;
+@@ -135,7 +136,6 @@ static int move_file(PStoreEntry *pe, const char *subdir) {
+         iovec[n_iovec++] = IOVEC_MAKE_STRING(message);
+ 
+         if (pe->content_size > 0) {
+-                _cleanup_free_ void *field = NULL;
+                 size_t field_size;
+ 
+                 field_size = strlen("FILE=") + pe->content_size;
diff --git a/SOURCES/0884-pstore-refuse-to-run-if-arguments-are-specified.patch b/SOURCES/0884-pstore-refuse-to-run-if-arguments-are-specified.patch
new file mode 100644
index 0000000..de27c4c
--- /dev/null
+++ b/SOURCES/0884-pstore-refuse-to-run-if-arguments-are-specified.patch
@@ -0,0 +1,29 @@
+From a35a90322f8587f650aeb72bfbe1ebcc93e503aa Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
+Date: Mon, 22 Jul 2019 10:43:19 +0200
+Subject: [PATCH] pstore: refuse to run if arguments are specified
+
+(This is why the --help chech passed.)
+
+(cherry picked from commit 22d6bea8820612e6a1483d8b6cfd820f1417ae6b)
+
+Related: #2158832
+---
+ src/pstore/pstore.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/src/pstore/pstore.c b/src/pstore/pstore.c
+index cafb1804c6..b0b21dedd4 100644
+--- a/src/pstore/pstore.c
++++ b/src/pstore/pstore.c
+@@ -358,6 +358,10 @@ static int run(int argc, char *argv[]) {
+ 
+         log_open();
+ 
++        if (argc > 1)
++                return log_error_errno(-EINVAL,
++                                       "This program takes no arguments.");
++
+         /* Ignore all parse errors */
+         (void) parse_config();
+ 
diff --git a/SOURCES/0885-pstore-allow-specifying-src-and-dst-dirs-are-argumen.patch b/SOURCES/0885-pstore-allow-specifying-src-and-dst-dirs-are-argumen.patch
new file mode 100644
index 0000000..00779b3
--- /dev/null
+++ b/SOURCES/0885-pstore-allow-specifying-src-and-dst-dirs-are-argumen.patch
@@ -0,0 +1,44 @@
+From 76fe0974f62f0a2beb2d3d8e224e80a57c0ebd09 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
+Date: Fri, 4 Oct 2019 16:14:47 +0200
+Subject: [PATCH] pstore: allow specifying src and dst dirs are arguments
+
+This makes it much easier to debug the program as a normal user, since we
+don't need to set up fake input under /sys/fs/pstore/.
+
+Also, let's make the debug output a bit nicer.
+
+(cherry picked from commit e05a72d7587ff916a983588f8393af624d330dd0)
+
+Related: #2158832
+---
+ src/pstore/pstore.c | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+diff --git a/src/pstore/pstore.c b/src/pstore/pstore.c
+index b0b21dedd4..7353e83a81 100644
+--- a/src/pstore/pstore.c
++++ b/src/pstore/pstore.c
+@@ -358,15 +358,18 @@ static int run(int argc, char *argv[]) {
+ 
+         log_open();
+ 
+-        if (argc > 1)
++        if (argc == 3) {
++                arg_sourcedir = argv[1];
++                arg_archivedir = argv[2];
++        } else if (argc > 1)
+                 return log_error_errno(-EINVAL,
+-                                       "This program takes no arguments.");
++                                       "This program takes zero or two arguments.");
+ 
+         /* Ignore all parse errors */
+         (void) parse_config();
+ 
+-        log_debug("Selected storage '%s'.", pstore_storage_to_string(arg_storage));
+-        log_debug("Selected Unlink '%d'.", arg_unlink);
++        log_debug("Selected storage: %s.", pstore_storage_to_string(arg_storage));
++        log_debug("Selected unlink: %s.", yes_no(arg_unlink));
+ 
+         if (arg_storage == PSTORE_STORAGE_NONE)
+                 /* Do nothing, intentionally, leaving pstore untouched */
diff --git a/SOURCES/0886-pstore-rework-memory-handling-for-dmesg.patch b/SOURCES/0886-pstore-rework-memory-handling-for-dmesg.patch
new file mode 100644
index 0000000..8c0adda
--- /dev/null
+++ b/SOURCES/0886-pstore-rework-memory-handling-for-dmesg.patch
@@ -0,0 +1,133 @@
+From a2ba34a79de3748f51d57541c54dbe22e1d03a9e Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
+Date: Fri, 4 Oct 2019 16:17:27 +0200
+Subject: [PATCH] pstore: rework memory handling for dmesg
+
+Semmle Security Reports report:
+> The problem occurs on the way realloc is being used. When a size
+> bigger than the chunk that wants to be reallocated is passed, realloc
+> try to malloc a  bigger size, however in the case that malloc fails
+> (for example, by forcing a big allocation)  realloc will return NULL.
+>
+> According to the man page:
+> "The realloc() function returns a pointer to the newly allocated
+> memory, which is suitably aligned for any built-in type and may be
+> different from ptr,  or  NULL  if  the  request fails.   If size was
+> equal to 0, either NULL or a pointer suitable to be passed to free()
+> is returned.  If realloc() fails, the original block is left
+> untouched; it is  not  freed or moved."
+>
+> The problem occurs when the memory ptr passed to the first argument of
+> realloc is the same as the one used for the result, for example in
+> this case:
+>
+> dmesg = realloc(dmesg, dmesg_size + strlen(pe->dirent.d_name) +
+> strlen(":\n") + pe->content_size + 1);
+>
+> https://lgtm.com/projects/g/systemd/systemd/snapshot/f8bcb81955f9e93a4787627e28f43fffb2a84836/files/src/pstore/pstore.c?sort=name&dir=A
+> SC&mode=heatmap#L300
+>
+> If the malloc inside that realloc fails, then the original memory
+> chunk will never be free but since realloc will return NULL, the
+> pointer to that memory chunk will be lost and a memory leak will
+> occur.
+>
+> In case you are curious, this is the query we used to find this problem:
+> https://lgtm.com/query/8650323308193591473/
+
+Let's use a more standard pattern: allocate memory using greedy_realloc, and
+instead of freeing it when we wrote out a chunk, let's just move the cursor
+back to the beginning and reuse the memory we allocated previously.
+
+If we fail to allocate the memory for dmesg contents, don't write the dmesg
+entry, but let's still process the files to move them out of pstore.
+
+(cherry picked from commit 8198c3e42b0614b6bd1db6f38813b842c8577304)
+
+Related: #2158832
+---
+ src/pstore/pstore.c | 43 ++++++++++++++++++++++++++-----------------
+ 1 file changed, 26 insertions(+), 17 deletions(-)
+
+diff --git a/src/pstore/pstore.c b/src/pstore/pstore.c
+index 7353e83a81..d70e142b4d 100644
+--- a/src/pstore/pstore.c
++++ b/src/pstore/pstore.c
+@@ -176,9 +176,11 @@ static int write_dmesg(const char *dmesg, size_t size, const char *id) {
+         ssize_t wr;
+         int r;
+ 
+-        if (isempty(dmesg) || size == 0)
++        if (size == 0)
+                 return 0;
+ 
++        assert(dmesg);
++
+         /* log_info("Record ID %s", id); */
+ 
+         ofd_path = path_join(arg_archivedir, id, "dmesg.txt");
+@@ -204,7 +206,8 @@ static int write_dmesg(const char *dmesg, size_t size, const char *id) {
+ static void process_dmesg_files(PStoreList *list) {
+         /* Move files, reconstruct dmesg.txt */
+         _cleanup_free_ char *dmesg = NULL, *dmesg_id = NULL;
+-        size_t dmesg_size = 0;
++        size_t dmesg_size = 0, dmesg_allocated = 0;
++        bool dmesg_bad = false;
+         PStoreEntry *pe;
+ 
+         /* Handle each dmesg file: files processed in reverse
+@@ -281,33 +284,39 @@ static void process_dmesg_files(PStoreList *list) {
+                 /* Now move file from pstore to archive storage */
+                 move_file(pe, pe_id);
+ 
++                if (dmesg_bad)
++                        continue;
++
+                 /* If the current record id is NOT the same as the
+                  * previous record id, then start a new dmesg.txt file */
+-                if (!pe_id || !dmesg_id || !streq(pe_id, dmesg_id)) {
++                if (!streq_ptr(pe_id, dmesg_id)) {
+                         /* Encountered a new dmesg group, close out old one, open new one */
+-                        if (dmesg) {
+-                                (void) write_dmesg(dmesg, dmesg_size, dmesg_id);
+-                                dmesg = mfree(dmesg);
+-                                dmesg_size = 0;
+-                        }
++                        (void) write_dmesg(dmesg, dmesg_size, dmesg_id);
++                        dmesg_size = 0;
+ 
+                         /* now point dmesg_id to storage of pe_id */
+                         free_and_replace(dmesg_id, pe_id);
+                 }
+ 
+-                /* Reconstruction of dmesg is done as a useful courtesy, do not log errors */
+-                dmesg = realloc(dmesg, dmesg_size + strlen(pe->dirent.d_name) + strlen(":\n") + pe->content_size + 1);
+-                if (dmesg) {
+-                        dmesg_size += sprintf(&dmesg[dmesg_size], "%s:\n", pe->dirent.d_name);
+-                        if (pe->content) {
+-                                memcpy(&dmesg[dmesg_size], pe->content, pe->content_size);
+-                                dmesg_size += pe->content_size;
+-                        }
++                /* Reconstruction of dmesg is done as a useful courtesy: do not fail, but don't write garbled
++                 * output either. */
++                size_t needed = strlen(pe->dirent.d_name) + strlen(":\n") + pe->content_size + 1;
++                if (!GREEDY_REALLOC(dmesg, dmesg_allocated, dmesg_size + needed)) {
++                        log_warning_errno(ENOMEM, "Failed to write dmesg file: %m");
++                        dmesg_bad = true;
++                        continue;
++                }
++
++                dmesg_size += sprintf(dmesg + dmesg_size, "%s:\n", pe->dirent.d_name);
++                if (pe->content) {
++                        memcpy(dmesg + dmesg_size, pe->content, pe->content_size);
++                        dmesg_size += pe->content_size;
+                 }
+ 
+                 pe_id = mfree(pe_id);
+         }
+-        if (dmesg)
++
++        if (!dmesg_bad)
+                 (void) write_dmesg(dmesg, dmesg_size, dmesg_id);
+ }
+ 
diff --git a/SOURCES/0887-pstore-fixes-for-dmesg.txt-reconstruction.patch b/SOURCES/0887-pstore-fixes-for-dmesg.txt-reconstruction.patch
new file mode 100644
index 0000000..cbfb074
--- /dev/null
+++ b/SOURCES/0887-pstore-fixes-for-dmesg.txt-reconstruction.patch
@@ -0,0 +1,504 @@
+From 5ac15c7dc49476e7cd7cc3a4b507282c9f78d528 Mon Sep 17 00:00:00 2001
+From: Eric DeVolder <eric.devolder@oracle.com>
+Date: Mon, 21 Nov 2022 11:27:27 -0500
+Subject: [PATCH] pstore: fixes for dmesg.txt reconstruction
+
+This patch fixes problems with the re-assembly of the dmesg
+from the records stored in pstore.
+
+The current code simply ignores the last 6 characters of the
+file name to form a base record id, which then groups any
+pstore files with this base id into the reconstructed dmesg.txt.
+This approach fails when the following oops generated the
+following in pstore:
+
+ -rw-------.  1 root root  1808 Oct 27 22:07 dmesg-efi-166692286101001
+ -rw-------.  1 root root  1341 Oct 27 22:07 dmesg-efi-166692286101002
+ -rw-------.  1 root root  1812 Oct 27 22:07 dmesg-efi-166692286102001
+ -rw-------.  1 root root  1820 Oct 27 22:07 dmesg-efi-166692286102002
+ -rw-------.  1 root root  1807 Oct 27 22:07 dmesg-efi-166692286103001
+ -rw-------.  1 root root  1791 Oct 27 22:07 dmesg-efi-166692286103002
+ -rw-------.  1 root root  1773 Oct 27 22:07 dmesg-efi-166692286104001
+ -rw-------.  1 root root  1801 Oct 27 22:07 dmesg-efi-166692286104002
+ -rw-------.  1 root root  1821 Oct 27 22:07 dmesg-efi-166692286105001
+ -rw-------.  1 root root  1809 Oct 27 22:07 dmesg-efi-166692286105002
+ -rw-------.  1 root root  1804 Oct 27 22:07 dmesg-efi-166692286106001
+ -rw-------.  1 root root  1817 Oct 27 22:07 dmesg-efi-166692286106002
+ -rw-------.  1 root root  1792 Oct 27 22:07 dmesg-efi-166692286107001
+ -rw-------.  1 root root  1810 Oct 27 22:07 dmesg-efi-166692286107002
+ -rw-------.  1 root root  1717 Oct 27 22:07 dmesg-efi-166692286108001
+ -rw-------.  1 root root  1808 Oct 27 22:07 dmesg-efi-166692286108002
+ -rw-------.  1 root root  1764 Oct 27 22:07 dmesg-efi-166692286109001
+ -rw-------.  1 root root  1765 Oct 27 22:07 dmesg-efi-166692286109002
+ -rw-------.  1 root root  1796 Oct 27 22:07 dmesg-efi-166692286110001
+ -rw-------.  1 root root  1816 Oct 27 22:07 dmesg-efi-166692286110002
+ -rw-------.  1 root root  1793 Oct 27 22:07 dmesg-efi-166692286111001
+ -rw-------.  1 root root  1751 Oct 27 22:07 dmesg-efi-166692286111002
+ -rw-------.  1 root root  1813 Oct 27 22:07 dmesg-efi-166692286112001
+ -rw-------.  1 root root  1786 Oct 27 22:07 dmesg-efi-166692286112002
+ -rw-------.  1 root root  1754 Oct 27 22:07 dmesg-efi-166692286113001
+ -rw-------.  1 root root  1752 Oct 27 22:07 dmesg-efi-166692286113002
+ -rw-------.  1 root root  1803 Oct 27 22:07 dmesg-efi-166692286114001
+ -rw-------.  1 root root  1759 Oct 27 22:07 dmesg-efi-166692286114002
+ -rw-------.  1 root root  1805 Oct 27 22:07 dmesg-efi-166692286115001
+ -rw-------.  1 root root  1787 Oct 27 22:07 dmesg-efi-166692286115002
+ -rw-------.  1 root root  1815 Oct 27 22:07 dmesg-efi-166692286116001
+ -rw-------.  1 root root  1771 Oct 27 22:07 dmesg-efi-166692286116002
+ -rw-------.  1 root root  1816 Oct 27 22:07 dmesg-efi-166692286117002
+ -rw-------.  1 root root  1388 Oct 27 22:07 dmesg-efi-166692286701003
+ -rw-------.  1 root root  1824 Oct 27 22:07 dmesg-efi-166692286702003
+ -rw-------.  1 root root  1795 Oct 27 22:07 dmesg-efi-166692286703003
+ -rw-------.  1 root root  1805 Oct 27 22:07 dmesg-efi-166692286704003
+ -rw-------.  1 root root  1813 Oct 27 22:07 dmesg-efi-166692286705003
+ -rw-------.  1 root root  1821 Oct 27 22:07 dmesg-efi-166692286706003
+ -rw-------.  1 root root  1814 Oct 27 22:07 dmesg-efi-166692286707003
+ -rw-------.  1 root root  1812 Oct 27 22:07 dmesg-efi-166692286708003
+ -rw-------.  1 root root  1769 Oct 27 22:07 dmesg-efi-166692286709003
+ -rw-------.  1 root root  1820 Oct 27 22:07 dmesg-efi-166692286710003
+ -rw-------.  1 root root  1755 Oct 27 22:07 dmesg-efi-166692286711003
+ -rw-------.  1 root root  1790 Oct 27 22:07 dmesg-efi-166692286712003
+ -rw-------.  1 root root  1756 Oct 27 22:07 dmesg-efi-166692286713003
+ -rw-------.  1 root root  1763 Oct 27 22:07 dmesg-efi-166692286714003
+ -rw-------.  1 root root  1791 Oct 27 22:07 dmesg-efi-166692286715003
+ -rw-------.  1 root root  1775 Oct 27 22:07 dmesg-efi-166692286716003
+ -rw-------.  1 root root  1820 Oct 27 22:07 dmesg-efi-166692286717003
+
+The "reconstructed" dmesg.txt that resulted from the above contained
+the following (ignoring actual contents, just providing the Part info):
+
+ Emergency#3 Part17
+ Emergency#3 Part16
+ Emergency#3 Part15
+ Emergency#3 Part14
+ Emergency#3 Part13
+ Emergency#3 Part12
+ Emergency#3 Part11
+ Emergency#3 Part10
+ Emergency#3 Part9
+ Emergency#3 Part8
+ Emergency#3 Part7
+ Emergency#3 Part6
+ Emergency#3 Part5
+ Emergency#3 Part4
+ Emergency#3 Part3
+ Emergency#3 Part2
+ Emergency#3 Part1
+ Panic#2 Part17
+ Panic#2 Part16
+ Oops#1 Part16
+ Panic#2 Part15
+ Oops#1 Part15
+ Panic#2 Part14
+ Oops#1 Part14
+ Panic#2 Part13
+ Oops#1 Part13
+ Panic#2 Part12
+ Oops#1 Part12
+ Panic#2 Part11
+ Oops#1 Part11
+ Panic#2 Part10
+ Oops#1 Part10
+ Panic#2 Part9
+ Oops#1 Part9
+ Panic#2 Part8
+ Oops#1 Part8
+ Panic#2 Part7
+ Oops#1 Part7
+ Panic#2 Part6
+ Oops#1 Part6
+ Panic#2 Part5
+ Oops#1 Part5
+ Panic#2 Part4
+ Oops#1 Part4
+ Panic#2 Part3
+ Oops#1 Part3
+ Panic#2 Part2
+ Oops#1 Part2
+ Panic#2 Part1
+ Oops#1 Part1
+
+The above is a interleaved mess of three dmesg dumps.
+
+This patch fixes the above problems, and simplifies the dmesg
+reconstruction process. The code now distinguishes between
+records on EFI vs ERST, which have differently formatted
+record identifiers. Using knowledge of the format of the
+record ids allows vastly improved reconstruction process.
+
+With this change in place, the above pstore records now
+result in the following:
+
+ # ls -alR /var/lib/systemd/pstore
+ 1666922861:
+ total 8
+ drwxr-xr-x. 4 root root   28 Nov 18 14:58 .
+ drwxr-xr-x. 7 root root  144 Nov 18 14:58 ..
+ drwxr-xr-x. 2 root root 4096 Nov 18 14:58 001
+ drwxr-xr-x. 2 root root 4096 Nov 18 14:58 002
+
+ 1666922861/001:
+ total 100
+ drwxr-xr-x. 2 root root  4096 Nov 18 14:58 .
+ drwxr-xr-x. 4 root root    28 Nov 18 14:58 ..
+ -rw-------. 1 root root  1808 Oct 27 22:07 dmesg-efi-166692286101001
+ -rw-------. 1 root root  1812 Oct 27 22:07 dmesg-efi-166692286102001
+ -rw-------. 1 root root  1807 Oct 27 22:07 dmesg-efi-166692286103001
+ -rw-------. 1 root root  1773 Oct 27 22:07 dmesg-efi-166692286104001
+ -rw-------. 1 root root  1821 Oct 27 22:07 dmesg-efi-166692286105001
+ -rw-------. 1 root root  1804 Oct 27 22:07 dmesg-efi-166692286106001
+ -rw-------. 1 root root  1792 Oct 27 22:07 dmesg-efi-166692286107001
+ -rw-------. 1 root root  1717 Oct 27 22:07 dmesg-efi-166692286108001
+ -rw-------. 1 root root  1764 Oct 27 22:07 dmesg-efi-166692286109001
+ -rw-------. 1 root root  1796 Oct 27 22:07 dmesg-efi-166692286110001
+ -rw-------. 1 root root  1793 Oct 27 22:07 dmesg-efi-166692286111001
+ -rw-------. 1 root root  1813 Oct 27 22:07 dmesg-efi-166692286112001
+ -rw-------. 1 root root  1754 Oct 27 22:07 dmesg-efi-166692286113001
+ -rw-------. 1 root root  1803 Oct 27 22:07 dmesg-efi-166692286114001
+ -rw-------. 1 root root  1805 Oct 27 22:07 dmesg-efi-166692286115001
+ -rw-------. 1 root root  1815 Oct 27 22:07 dmesg-efi-166692286116001
+ -rw-r-----. 1 root root 28677 Nov 18 14:58 dmesg.txt
+
+ 1666922861/002:
+ total 104
+ drwxr-xr-x. 2 root root  4096 Nov 18 14:58 .
+ drwxr-xr-x. 4 root root    28 Nov 18 14:58 ..
+ -rw-------. 1 root root  1341 Oct 27 22:07 dmesg-efi-166692286101002
+ -rw-------. 1 root root  1820 Oct 27 22:07 dmesg-efi-166692286102002
+ -rw-------. 1 root root  1791 Oct 27 22:07 dmesg-efi-166692286103002
+ -rw-------. 1 root root  1801 Oct 27 22:07 dmesg-efi-166692286104002
+ -rw-------. 1 root root  1809 Oct 27 22:07 dmesg-efi-166692286105002
+ -rw-------. 1 root root  1817 Oct 27 22:07 dmesg-efi-166692286106002
+ -rw-------. 1 root root  1810 Oct 27 22:07 dmesg-efi-166692286107002
+ -rw-------. 1 root root  1808 Oct 27 22:07 dmesg-efi-166692286108002
+ -rw-------. 1 root root  1765 Oct 27 22:07 dmesg-efi-166692286109002
+ -rw-------. 1 root root  1816 Oct 27 22:07 dmesg-efi-166692286110002
+ -rw-------. 1 root root  1751 Oct 27 22:07 dmesg-efi-166692286111002
+ -rw-------. 1 root root  1786 Oct 27 22:07 dmesg-efi-166692286112002
+ -rw-------. 1 root root  1752 Oct 27 22:07 dmesg-efi-166692286113002
+ -rw-------. 1 root root  1759 Oct 27 22:07 dmesg-efi-166692286114002
+ -rw-------. 1 root root  1787 Oct 27 22:07 dmesg-efi-166692286115002
+ -rw-------. 1 root root  1771 Oct 27 22:07 dmesg-efi-166692286116002
+ -rw-------. 1 root root  1816 Oct 27 22:07 dmesg-efi-166692286117002
+ -rw-r-----. 1 root root 30000 Nov 18 14:58 dmesg.txt
+
+ 1666922867:
+ total 4
+ drwxr-xr-x. 3 root root   17 Nov 18 14:58 .
+ drwxr-xr-x. 7 root root  144 Nov 18 14:58 ..
+ drwxr-xr-x. 2 root root 4096 Nov 18 14:58 003
+
+ 1666922867/003:
+ total 104
+ drwxr-xr-x. 2 root root  4096 Nov 18 14:58 .
+ drwxr-xr-x. 3 root root    17 Nov 18 14:58 ..
+ -rw-------. 1 root root  1388 Oct 27 22:07 dmesg-efi-166692286701003
+ -rw-------. 1 root root  1824 Oct 27 22:07 dmesg-efi-166692286702003
+ -rw-------. 1 root root  1795 Oct 27 22:07 dmesg-efi-166692286703003
+ -rw-------. 1 root root  1805 Oct 27 22:07 dmesg-efi-166692286704003
+ -rw-------. 1 root root  1813 Oct 27 22:07 dmesg-efi-166692286705003
+ -rw-------. 1 root root  1821 Oct 27 22:07 dmesg-efi-166692286706003
+ -rw-------. 1 root root  1814 Oct 27 22:07 dmesg-efi-166692286707003
+ -rw-------. 1 root root  1812 Oct 27 22:07 dmesg-efi-166692286708003
+ -rw-------. 1 root root  1769 Oct 27 22:07 dmesg-efi-166692286709003
+ -rw-------. 1 root root  1820 Oct 27 22:07 dmesg-efi-166692286710003
+ -rw-------. 1 root root  1755 Oct 27 22:07 dmesg-efi-166692286711003
+ -rw-------. 1 root root  1790 Oct 27 22:07 dmesg-efi-166692286712003
+ -rw-------. 1 root root  1756 Oct 27 22:07 dmesg-efi-166692286713003
+ -rw-------. 1 root root  1763 Oct 27 22:07 dmesg-efi-166692286714003
+ -rw-------. 1 root root  1791 Oct 27 22:07 dmesg-efi-166692286715003
+ -rw-------. 1 root root  1775 Oct 27 22:07 dmesg-efi-166692286716003
+ -rw-------. 1 root root  1820 Oct 27 22:07 dmesg-efi-166692286717003
+ -rw-r-----. 1 root root 30111 Nov 18 14:58 dmesg.txt
+
+Furthemore, pstore records on ERST are now able to accurately
+identify the change in timestamp sequence in order to start a
+new dmesg.txt, as needed.
+
+(cherry picked from commit 5fbaa757077bde2db8d33b1c358518c41b990339)
+
+Related: #2158832
+---
+ src/pstore/pstore.c | 216 +++++++++++++++++++-------------------------
+ 1 file changed, 92 insertions(+), 124 deletions(-)
+
+diff --git a/src/pstore/pstore.c b/src/pstore/pstore.c
+index d70e142b4d..9f61e8f7f8 100644
+--- a/src/pstore/pstore.c
++++ b/src/pstore/pstore.c
+@@ -112,8 +112,8 @@ static int compare_pstore_entries(const void *_a, const void *_b) {
+         return strcmp(a->dirent.d_name, b->dirent.d_name);
+ }
+ 
+-static int move_file(PStoreEntry *pe, const char *subdir) {
+-        _cleanup_free_ char *ifd_path = NULL, *ofd_path = NULL;
++static int move_file(PStoreEntry *pe, const char *subdir1, const char *subdir2) {
++        _cleanup_free_ char *ifd_path = NULL, *ofd_path = NULL, *ofd_path_base = NULL;
+         _cleanup_free_ void *field = NULL;
+         const char *suffix, *message;
+         struct iovec iovec[2];
+@@ -126,7 +126,11 @@ static int move_file(PStoreEntry *pe, const char *subdir) {
+         if (!ifd_path)
+                 return log_oom();
+ 
+-        ofd_path = path_join(arg_archivedir, subdir, pe->dirent.d_name);
++        ofd_path_base = path_join(arg_archivedir, subdir1, subdir2);
++        if (!ofd_path_base)
++                return log_oom();
++
++        ofd_path = path_join(NULL, ofd_path_base, pe->dirent.d_name);
+         if (!ofd_path)
+                 return log_oom();
+ 
+@@ -169,155 +173,119 @@ static int move_file(PStoreEntry *pe, const char *subdir) {
+         return 0;
+ }
+ 
+-static int write_dmesg(const char *dmesg, size_t size, const char *id) {
+-        _cleanup_(unlink_and_freep) char *tmp_path = NULL;
+-        _cleanup_free_ char *ofd_path = NULL;
++static int append_dmesg(PStoreEntry *pe, const char *subdir1, const char *subdir2) {
++        /* Append dmesg chunk to end, create if needed */
++        _cleanup_free_ char *ofd_path = NULL, *ofd_path_base = NULL;
+         _cleanup_close_ int ofd = -1;
+         ssize_t wr;
+-        int r;
+ 
+-        if (size == 0)
+-                return 0;
++        assert(pe);
+ 
+-        assert(dmesg);
++        if (pe->content_size == 0)
++                return 0;
+ 
+-        /* log_info("Record ID %s", id); */
++        ofd_path_base = path_join(arg_archivedir, subdir1, subdir2);
++        if (!ofd_path_base)
++                return log_oom();
+ 
+-        ofd_path = path_join(arg_archivedir, id, "dmesg.txt");
++        ofd_path = path_join(NULL, ofd_path_base, "dmesg.txt");
+         if (!ofd_path)
+                 return log_oom();
+ 
+-        ofd = open_tmpfile_linkable(ofd_path, O_CLOEXEC|O_CREAT|O_TRUNC|O_WRONLY, &tmp_path);
++        ofd = open(ofd_path, O_CREAT|O_NOFOLLOW|O_NOCTTY|O_CLOEXEC|O_APPEND|O_WRONLY, 0640);
+         if (ofd < 0)
+-                return log_error_errno(ofd, "Failed to open temporary file %s: %m", ofd_path);
+-        wr = write(ofd, dmesg, size);
++                return log_error_errno(ofd, "Failed to open file %s: %m", ofd_path);
++        wr = write(ofd, pe->content, pe->content_size);
+         if (wr < 0)
+                 return log_error_errno(errno, "Failed to store dmesg to %s: %m", ofd_path);
+-        if (wr != (ssize_t)size)
+-                return log_error_errno(-EIO, "Failed to store dmesg to %s. %zu bytes are lost.", ofd_path, size - wr);
+-        r = link_tmpfile(ofd, tmp_path, ofd_path);
+-        if (r < 0)
+-                return log_error_errno(r, "Failed to write temporary file %s: %m", ofd_path);
+-        tmp_path = mfree(tmp_path);
++        if ((size_t)wr != pe->content_size)
++                return log_error_errno(-EIO, "Failed to store dmesg to %s. %zu bytes are lost.", ofd_path, pe->content_size - wr);
+ 
+         return 0;
+ }
+ 
+-static void process_dmesg_files(PStoreList *list) {
++static int process_dmesg_files(PStoreList *list) {
+         /* Move files, reconstruct dmesg.txt */
+-        _cleanup_free_ char *dmesg = NULL, *dmesg_id = NULL;
+-        size_t dmesg_size = 0, dmesg_allocated = 0;
+-        bool dmesg_bad = false;
+-        PStoreEntry *pe;
++        _cleanup_free_ char *erst_subdir = NULL;
++        uint64_t last_record_id = 0;
++
++        /* When dmesg is written into pstore, it is done so in small chunks, whatever the exchange buffer
++         * size is with the underlying pstore backend (ie. EFI may be ~2KiB), which means an example
++         * pstore with approximately 64KB of storage may have up to roughly 32 dmesg files, some likely
++         * related.
++         *
++         * Here we look at the dmesg filename and try to discern if files are part of a related group,
++         * meaning the same original dmesg.
++         *
++         * The dmesg- filename contains the backend-type and the Common Platform Error Record, CPER,
++         * record id, a 64-bit number.
++         *
++         * Files are processed in reverse lexigraphical order so as to properly reconstruct original dmesg.*/
+ 
+-        /* Handle each dmesg file: files processed in reverse
+-         * order so as to properly reconstruct original dmesg */
+         for (size_t n = list->n_entries; n > 0; n--) {
+-                bool move_file_and_continue = false;
+-                _cleanup_free_ char *pe_id = NULL;
++                PStoreEntry *pe;
+                 char *p;
+-                size_t plen;
+ 
+                 pe = &list->entries[n-1];
+ 
+                 if (pe->handled)
+                         continue;
+-                if (!startswith(pe->dirent.d_name, "dmesg-"))
+-                        continue;
+-
+                 if (endswith(pe->dirent.d_name, ".enc.z")) /* indicates a problem */
+-                        move_file_and_continue = true;
+-                p = strrchr(pe->dirent.d_name, '-');
+-                if (!p)
+-                        move_file_and_continue = true;
+-
+-                if (move_file_and_continue) {
+-                        /* A dmesg file on which we do NO additional processing */
+-                        (void) move_file(pe, NULL);
+                         continue;
+-                }
+-
+-                /* See if this file is one of a related group of files
+-                 * in order to reconstruct dmesg */
+-
+-                /* When dmesg is written into pstore, it is done so in
+-                 * small chunks, whatever the exchange buffer size is
+-                 * with the underlying pstore backend (ie. EFI may be
+-                 * ~2KiB), which means an example pstore with approximately
+-                 * 64KB of storage may have up to roughly 32 dmesg files
+-                 * that could be related, depending upon the size of the
+-                 * original dmesg.
+-                 *
+-                 * Here we look at the dmesg filename and try to discern
+-                 * if files are part of a related group, meaning the same
+-                 * original dmesg.
+-                 *
+-                 * The two known pstore backends are EFI and ERST. These
+-                 * backends store data in the Common Platform Error
+-                 * Record, CPER, format. The dmesg- filename contains the
+-                 * CPER record id, a 64bit number (in decimal notation).
+-                 * In Linux, the record id is encoded with two digits for
+-                 * the dmesg part (chunk) number and 3 digits for the
+-                 * count number. So allowing an additional digit to
+-                 * compensate for advancing time, this code ignores the
+-                 * last six digits of the filename in determining the
+-                 * record id.
+-                 *
+-                 * For the EFI backend, the record id encodes an id in the
+-                 * upper 32 bits, and a timestamp in the lower 32-bits.
+-                 * So ignoring the least significant 6 digits has proven
+-                 * to generally identify related dmesg entries.  */
+-#define PSTORE_FILENAME_IGNORE 6
+-
+-                /* determine common portion of record id */
+-                ++p; /* move beyond dmesg- */
+-                plen = strlen(p);
+-                if (plen > PSTORE_FILENAME_IGNORE) {
+-                        pe_id = memdup_suffix0(p, plen - PSTORE_FILENAME_IGNORE);
+-                        if (!pe_id) {
+-                                log_oom();
+-                                return;
+-                        }
+-                } else
+-                        pe_id = mfree(pe_id);
+-
+-                /* Now move file from pstore to archive storage */
+-                move_file(pe, pe_id);
+-
+-                if (dmesg_bad)
++                if (!startswith(pe->dirent.d_name, "dmesg-"))
+                         continue;
+ 
+-                /* If the current record id is NOT the same as the
+-                 * previous record id, then start a new dmesg.txt file */
+-                if (!streq_ptr(pe_id, dmesg_id)) {
+-                        /* Encountered a new dmesg group, close out old one, open new one */
+-                        (void) write_dmesg(dmesg, dmesg_size, dmesg_id);
+-                        dmesg_size = 0;
+-
+-                        /* now point dmesg_id to storage of pe_id */
+-                        free_and_replace(dmesg_id, pe_id);
+-                }
+-
+-                /* Reconstruction of dmesg is done as a useful courtesy: do not fail, but don't write garbled
+-                 * output either. */
+-                size_t needed = strlen(pe->dirent.d_name) + strlen(":\n") + pe->content_size + 1;
+-                if (!GREEDY_REALLOC(dmesg, dmesg_allocated, dmesg_size + needed)) {
+-                        log_warning_errno(ENOMEM, "Failed to write dmesg file: %m");
+-                        dmesg_bad = true;
+-                        continue;
+-                }
+-
+-                dmesg_size += sprintf(dmesg + dmesg_size, "%s:\n", pe->dirent.d_name);
+-                if (pe->content) {
+-                        memcpy(dmesg + dmesg_size, pe->content, pe->content_size);
+-                        dmesg_size += pe->content_size;
+-                }
+-
+-                pe_id = mfree(pe_id);
++                if ((p = startswith(pe->dirent.d_name, "dmesg-efi-"))) {
++                        /* For the EFI backend, the 3 least significant digits of record id encodes a
++                         * "count" number, the next 2 least significant digits for the dmesg part
++                         * (chunk) number, and the remaining digits as the timestamp.  See
++                         * linux/drivers/firmware/efi/efi-pstore.c in efi_pstore_write(). */
++                        _cleanup_free_ char *subdir1 = NULL, *subdir2 = NULL;
++                        size_t plen = strlen(p);
++
++                        if (plen < 6)
++                                continue;
++
++                        /* Extract base record id */
++                        subdir1 = strndup(p, plen - 5);
++                        if (!subdir1)
++                                return log_oom();
++                        /* Extract "count" field */
++                        subdir2 = strndup(p + plen - 3, 3);
++                        if (!subdir2)
++                                return log_oom();
++
++                        /* Now move file from pstore to archive storage */
++                        (void) move_file(pe, subdir1, subdir2);
++
++                        /* Append to the dmesg */
++                        (void) append_dmesg(pe, subdir1, subdir2);
++                } else if ((p = startswith(pe->dirent.d_name, "dmesg-erst-"))) {
++                        /* For the ERST backend, the record is a monotonically increasing number, seeded as
++                         * a timestamp. See linux/drivers/acpi/apei/erst.c in erst_writer(). */
++                        uint64_t record_id;
++
++                        if (safe_atou64(p, &record_id) < 0)
++                                continue;
++                        if (last_record_id - 1 != record_id)
++                                /* A discontinuity in the number has been detected, this current record id
++                                 * will become the directory name for all pieces of the dmesg in this
++                                 * series. */
++                                if (free_and_strdup(&erst_subdir, p) < 0)
++                                        return log_oom();
++
++                        /* Now move file from pstore to archive storage */
++                        (void) move_file(pe, erst_subdir, NULL);
++
++                        /* Append to the dmesg */
++                        (void) append_dmesg(pe, erst_subdir, NULL);
++
++                        /* Update, but keep erst_subdir for next file */
++                        last_record_id = record_id;
++                } else
++                        log_debug("Unknown backend, ignoring \"%s\".", pe->dirent.d_name);
+         }
+-
+-        if (!dmesg_bad)
+-                (void) write_dmesg(dmesg, dmesg_size, dmesg_id);
++        return 0;
+ }
+ 
+ static int list_files(PStoreList *list, const char *sourcepath) {
+@@ -394,11 +362,11 @@ static int run(int argc, char *argv[]) {
+         qsort_safe(list.entries, list.n_entries, sizeof(PStoreEntry), compare_pstore_entries);
+ 
+         /* Process known file types */
+-        process_dmesg_files(&list);
++        (void) process_dmesg_files(&list);
+ 
+         /* Move left over files out of pstore */
+         for (size_t n = 0; n < list.n_entries; n++)
+-                move_file(&list.entries[n], NULL);
++                (void) move_file(&list.entries[n], NULL, NULL);
+ 
+         return 0;
+ }
diff --git a/SOURCES/0888-pstore-Don-t-start-systemd-pstore.service-in-contain.patch b/SOURCES/0888-pstore-Don-t-start-systemd-pstore.service-in-contain.patch
new file mode 100644
index 0000000..10bb2fc
--- /dev/null
+++ b/SOURCES/0888-pstore-Don-t-start-systemd-pstore.service-in-contain.patch
@@ -0,0 +1,27 @@
+From 653a635086cfeaf0af12da3a722b0ebe2029b927 Mon Sep 17 00:00:00 2001
+From: Balint Reczey <balint.reczey@canonical.com>
+Date: Mon, 16 Dec 2019 19:03:19 +0100
+Subject: [PATCH] pstore: Don't start systemd-pstore.service in containers
+
+Usually it is not useful and can also fail making
+boot-and-services autopkgtest fail.
+
+(cherry picked from commit 287f506c32f3f4a48ba020408f964cb0f964d752)
+
+Related: #2158832
+---
+ units/systemd-pstore.service.in | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/units/systemd-pstore.service.in b/units/systemd-pstore.service.in
+index dde21bc33e..89f34afe34 100644
+--- a/units/systemd-pstore.service.in
++++ b/units/systemd-pstore.service.in
+@@ -11,6 +11,7 @@
+ Description=Platform Persistent Storage Archival
+ Documentation=man:systemd-pstore(8)
+ ConditionDirectoryNotEmpty=/sys/fs/pstore
++ConditionVirtualization=!container
+ DefaultDependencies=no
+ Wants=systemd-remount-fs.service
+ After=systemd-remount-fs.service
diff --git a/SOURCES/0889-units-pull-in-systemd-pstore.service-from-sysinit.ta.patch b/SOURCES/0889-units-pull-in-systemd-pstore.service-from-sysinit.ta.patch
new file mode 100644
index 0000000..3682e6f
--- /dev/null
+++ b/SOURCES/0889-units-pull-in-systemd-pstore.service-from-sysinit.ta.patch
@@ -0,0 +1,36 @@
+From c7e65774a4ccc8a431f63c5a12ab776b24ee1190 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Wed, 8 Apr 2020 16:12:00 +0200
+Subject: [PATCH] units: pull in systemd-pstore.service from sysinit.target
+
+sysinit.target is the target our early boot services are generally
+pulled in from, make systemd-pstore.service not an exception of that.
+
+Effectively this doesn't mean much, either way our unit is part of the
+initial transaction.
+
+(cherry picked from commit 167241912f51fbc0d7d0869b9af34c15b5ecc4b6)
+
+Related: #2158832
+---
+ units/systemd-pstore.service.in | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/units/systemd-pstore.service.in b/units/systemd-pstore.service.in
+index 89f34afe34..37fcf878f0 100644
+--- a/units/systemd-pstore.service.in
++++ b/units/systemd-pstore.service.in
+@@ -15,6 +15,7 @@ ConditionVirtualization=!container
+ DefaultDependencies=no
+ Wants=systemd-remount-fs.service
+ After=systemd-remount-fs.service
++Before=sysinit.target
+ 
+ [Service]
+ Type=oneshot
+@@ -23,4 +24,4 @@ RemainAfterExit=yes
+ StateDirectory=systemd/pstore
+ 
+ [Install]
+-WantedBy=systemd-remount-fs.service
++WantedBy=sysinit.target
diff --git a/SOURCES/0890-units-drop-dependency-on-systemd-remount-fs.service-.patch b/SOURCES/0890-units-drop-dependency-on-systemd-remount-fs.service-.patch
new file mode 100644
index 0000000..cb60e2b
--- /dev/null
+++ b/SOURCES/0890-units-drop-dependency-on-systemd-remount-fs.service-.patch
@@ -0,0 +1,36 @@
+From bc6f273a0475a1fa7ab56bc1e498ee62c96aa660 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Wed, 8 Apr 2020 16:10:38 +0200
+Subject: [PATCH] units: drop dependency on systemd-remount-fs.service from
+ systemd-pstore.service
+
+This dependency is now generated automatically given we use
+StateDirectory=. Moreover the combination of Wants= and After= was too
+strong anway, as whether remount-fs is pulled in or not should not be up
+to systemd-pstore.service, and in fact is part of the initial
+transaction anyway.
+
+[dtardon: This only removes Wants=, not After=, because I haven't
+backported the auto-generation code the description talks about. The
+code is simple, but it's just an optimisation allowing for slightly
+shorter unit files, hence I don't think we really need it.]
+
+(cherry picked from commit 0c978faa16fa9ecf92f0bbb5c7cc709dc472d115)
+
+Related: #2158832
+---
+ units/systemd-pstore.service.in | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/units/systemd-pstore.service.in b/units/systemd-pstore.service.in
+index 37fcf878f0..9a86f3145c 100644
+--- a/units/systemd-pstore.service.in
++++ b/units/systemd-pstore.service.in
+@@ -13,7 +13,6 @@ Documentation=man:systemd-pstore(8)
+ ConditionDirectoryNotEmpty=/sys/fs/pstore
+ ConditionVirtualization=!container
+ DefaultDependencies=no
+-Wants=systemd-remount-fs.service
+ After=systemd-remount-fs.service
+ Before=sysinit.target
+ 
diff --git a/SOURCES/0891-units-make-sure-systemd-pstore-stops-at-shutdown.patch b/SOURCES/0891-units-make-sure-systemd-pstore-stops-at-shutdown.patch
new file mode 100644
index 0000000..6fdbf34
--- /dev/null
+++ b/SOURCES/0891-units-make-sure-systemd-pstore-stops-at-shutdown.patch
@@ -0,0 +1,29 @@
+From 818ddd1efd751ef50f9960920284465befe9d704 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Wed, 8 Apr 2020 16:25:03 +0200
+Subject: [PATCH] units: make sure systemd-pstore stops at shutdown
+
+This doesn't matter too much given that the service doesn't do anything
+on shutdown, but let's still stop it to make things cleaner.
+
+(cherry picked from commit b0c1a07654c80d3cbbbcc52f860d4206707c0b08)
+
+Related: #2158832
+---
+ units/systemd-pstore.service.in | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/units/systemd-pstore.service.in b/units/systemd-pstore.service.in
+index 9a86f3145c..8cbf264a99 100644
+--- a/units/systemd-pstore.service.in
++++ b/units/systemd-pstore.service.in
+@@ -14,7 +14,8 @@ ConditionDirectoryNotEmpty=/sys/fs/pstore
+ ConditionVirtualization=!container
+ DefaultDependencies=no
+ After=systemd-remount-fs.service
+-Before=sysinit.target
++Conflicts=shutdown.target
++Before=sysinit.target shutdown.target
+ 
+ [Service]
+ Type=oneshot
diff --git a/SOURCES/0892-pstore-Run-after-modules-are-loaded.patch b/SOURCES/0892-pstore-Run-after-modules-are-loaded.patch
new file mode 100644
index 0000000..491e363
--- /dev/null
+++ b/SOURCES/0892-pstore-Run-after-modules-are-loaded.patch
@@ -0,0 +1,45 @@
+From 9cc6ee46e0083bc36b53d19e14fb637f7a1542dd Mon Sep 17 00:00:00 2001
+From: Alexander Graf <graf@amazon.com>
+Date: Thu, 9 Jun 2022 16:20:43 +0200
+Subject: [PATCH] pstore: Run after modules are loaded
+
+The systemd-pstore service takes pstore files on boot and transfers them
+to disk. It only does it once on boot and only if it finds any. The typical
+location of the pstore on modern systems is the UEFI variable store.
+
+Most distributions ship with CONFIG_EFI_VARS_PSTORE=m. That means, the
+UEFI variable store is only available on boot after the respective module
+is loaded.
+
+In most situations, the pstore service gets loaded before the UEFI pstore,
+so we don't get to transfer logs. Instead, they accumulate, filling up the
+pstore over time, potentially breaking the UEFI variable store.
+
+Let's add a service dependency on any kernel module that can provide a
+pstore to ensure we only scan for pstate after we can actually see pstate.
+
+I have seen live occurences of systems breaking because we did not erase
+the pstates and ran out of UEFI nvram space.
+
+Fixes https://github.com/systemd/systemd/issues/18540
+
+(cherry picked from commit 70e74a5997ae2ce7ba72a74ac949c3b2dad1a1d6)
+
+Related: #2158832
+---
+ units/systemd-pstore.service.in | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/units/systemd-pstore.service.in b/units/systemd-pstore.service.in
+index 8cbf264a99..1983a9738f 100644
+--- a/units/systemd-pstore.service.in
++++ b/units/systemd-pstore.service.in
+@@ -16,6 +16,8 @@ DefaultDependencies=no
+ After=systemd-remount-fs.service
+ Conflicts=shutdown.target
+ Before=sysinit.target shutdown.target
++After=modprobe@efi_pstore.service modprobe@mtdpstore.service modprobe@chromeos_pstore.service modprobe@ramoops.service modprobe@pstore_zone.service modprobe@pstore_blk.service
++Wants=modprobe@efi_pstore.service modprobe@mtdpstore.service modprobe@chromeos_pstore.service modprobe@ramoops.service modprobe@pstore_zone.service modprobe@pstore_blk.service
+ 
+ [Service]
+ Type=oneshot
diff --git a/SOURCES/0893-pstore-do-not-try-to-load-all-known-pstore-modules.patch b/SOURCES/0893-pstore-do-not-try-to-load-all-known-pstore-modules.patch
new file mode 100644
index 0000000..2108fd0
--- /dev/null
+++ b/SOURCES/0893-pstore-do-not-try-to-load-all-known-pstore-modules.patch
@@ -0,0 +1,48 @@
+From 6a6f108b59e47581d93cbc6bdc604ee84f1bb791 Mon Sep 17 00:00:00 2001
+From: Nick Rosbrook <nick.rosbrook@canonical.com>
+Date: Wed, 7 Sep 2022 13:25:13 -0400
+Subject: [PATCH] pstore: do not try to load all known pstore modules
+
+Commit 70e74a5997 ("pstore: Run after modules are loaded") added After=
+and Wants= entries for all known kernel modules providing a pstore.
+
+While adding these dependencies on systems where one of the modules is
+not present, or not configured, should not have a real affect on the
+system, it can produce annoying error messages in the kernel log. E.g.
+"mtd device must be supplied (device name is empty)" when the mtdpstore
+module is not configured correctly.
+
+Since dependencies cannot be removed with drop-ins, if a distro wants to
+remove some of these modules from systemd-pstore.service, they need to
+patch units/systemd-pstore.service.in. On the other hand, if they want
+to append to the dependencies this can be done by shipping a drop-in.
+
+Since the original intent of the previous commit was to fix [1], which
+only requires the efi_pstore module, remove all other kernel module
+dependencies from systemd-pstore.service, and let distros ship drop-ins
+to add dependencies if needed.
+
+[1] https://github.com/systemd/systemd/issues/18540
+
+(cherry picked from commit 8b8bd621e1d16808678fc3afed257df1fa03a281)
+
+Related: #2158832
+---
+ units/systemd-pstore.service.in | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/units/systemd-pstore.service.in b/units/systemd-pstore.service.in
+index 1983a9738f..19ffa8d4e8 100644
+--- a/units/systemd-pstore.service.in
++++ b/units/systemd-pstore.service.in
+@@ -16,8 +16,8 @@ DefaultDependencies=no
+ After=systemd-remount-fs.service
+ Conflicts=shutdown.target
+ Before=sysinit.target shutdown.target
+-After=modprobe@efi_pstore.service modprobe@mtdpstore.service modprobe@chromeos_pstore.service modprobe@ramoops.service modprobe@pstore_zone.service modprobe@pstore_blk.service
+-Wants=modprobe@efi_pstore.service modprobe@mtdpstore.service modprobe@chromeos_pstore.service modprobe@ramoops.service modprobe@pstore_zone.service modprobe@pstore_blk.service
++After=modprobe@efi_pstore.service
++Wants=modprobe@efi_pstore.service
+ 
+ [Service]
+ Type=oneshot
diff --git a/SOURCES/0894-logind-session-make-stopping-of-idle-session-visible.patch b/SOURCES/0894-logind-session-make-stopping-of-idle-session-visible.patch
new file mode 100644
index 0000000..df27c3b
--- /dev/null
+++ b/SOURCES/0894-logind-session-make-stopping-of-idle-session-visible.patch
@@ -0,0 +1,26 @@
+From b18e19f2262e7ed95c25d53268d12427fe77102d Mon Sep 17 00:00:00 2001
+From: David Tardon <dtardon@redhat.com>
+Date: Tue, 21 Feb 2023 10:41:47 +0100
+Subject: [PATCH] logind-session: make stopping of idle session visible to
+ admins
+
+(cherry picked from commit 6269ffe7ee8a659df7336a2582054ecd9eecf4b1)
+
+Resolves: #2156780
+---
+ src/login/logind-session.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/login/logind-session.c b/src/login/logind-session.c
+index 18a07efcdb..916202a65a 100644
+--- a/src/login/logind-session.c
++++ b/src/login/logind-session.c
+@@ -673,7 +673,7 @@ static int session_dispatch_stop_on_idle(sd_event_source *source, uint64_t t, vo
+ 
+         idle = session_get_idle_hint(s, &ts);
+         if (idle) {
+-                log_debug("Session \"%s\" of user \"%s\" is idle, stopping.", s->id, s->user->name);
++                log_info("Session \"%s\" of user \"%s\" is idle, stopping.", s->id, s->user->name);
+ 
+                 return session_stop(s, /* force */ true);
+         }
diff --git a/SOURCES/0895-journald-Increase-stdout-buffer-size-sooner-when-alm.patch b/SOURCES/0895-journald-Increase-stdout-buffer-size-sooner-when-alm.patch
new file mode 100644
index 0000000..f03ea88
--- /dev/null
+++ b/SOURCES/0895-journald-Increase-stdout-buffer-size-sooner-when-alm.patch
@@ -0,0 +1,32 @@
+From a0b52398692f3e4bda18520db9e2397f7b2c80dd Mon Sep 17 00:00:00 2001
+From: Benjamin Robin <dev@benjarobin.fr>
+Date: Sun, 3 May 2020 18:37:21 +0200
+Subject: [PATCH] journald: Increase stdout buffer size sooner, when almost
+ full
+
+If the previous received buffer length is almost equal to the allocated
+buffer size, before this change the next read can only receive a couple
+of bytes (in the worst case only 1 byte), which is not efficient.
+
+(cherry picked from commit 034e9719ac1ba88a36b05da38c7aa98761d42c77)
+
+Related: #2029426
+---
+ src/journal/journald-stream.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/src/journal/journald-stream.c b/src/journal/journald-stream.c
+index 302a82d3d7..c8de984335 100644
+--- a/src/journal/journald-stream.c
++++ b/src/journal/journald-stream.c
+@@ -507,8 +507,8 @@ static int stdout_stream_process(sd_event_source *es, int fd, uint32_t revents,
+                 goto terminate;
+         }
+ 
+-        /* If the buffer is full already (discounting the extra NUL we need), add room for another 1K */
+-        if (s->length + 1 >= s->allocated) {
++        /* If the buffer is almost full, add room for another 1K */
++        if (s->length + 512 >= s->allocated) {
+                 if (!GREEDY_REALLOC(s->buffer, s->allocated, s->length + 1 + 1024)) {
+                         log_oom();
+                         goto terminate;
diff --git a/SOURCES/0896-journald-rework-end-of-line-marker-handling-to-use-a.patch b/SOURCES/0896-journald-rework-end-of-line-marker-handling-to-use-a.patch
new file mode 100644
index 0000000..a655502
--- /dev/null
+++ b/SOURCES/0896-journald-rework-end-of-line-marker-handling-to-use-a.patch
@@ -0,0 +1,77 @@
+From d8fabe7a6839eeb0d5d0504471f2d18b07545238 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Tue, 12 May 2020 18:53:35 +0200
+Subject: [PATCH] journald: rework end of line marker handling to use a field
+ table
+
+(cherry picked from commit 549b7379ba404c33fd448d2bca46a57f6529b00b)
+
+Related: #2029426
+---
+ src/journal/journald-stream.c | 29 ++++++++++++++++++++---------
+ 1 file changed, 20 insertions(+), 9 deletions(-)
+
+diff --git a/src/journal/journald-stream.c b/src/journal/journald-stream.c
+index c8de984335..58752a5a24 100644
+--- a/src/journal/journald-stream.c
++++ b/src/journal/journald-stream.c
+@@ -54,6 +54,8 @@ typedef enum LineBreak {
+         LINE_BREAK_NUL,
+         LINE_BREAK_LINE_MAX,
+         LINE_BREAK_EOF,
++        _LINE_BREAK_MAX,
++        _LINE_BREAK_INVALID = -1,
+ } LineBreak;
+ 
+ struct StdoutStream {
+@@ -233,7 +235,11 @@ fail:
+         return log_error_errno(r, "Failed to save stream data %s: %m", s->state_file);
+ }
+ 
+-static int stdout_stream_log(StdoutStream *s, const char *p, LineBreak line_break) {
++static int stdout_stream_log(
++                StdoutStream *s,
++                const char *p,
++                LineBreak line_break) {
++
+         struct iovec *iovec;
+         int priority;
+         char syslog_priority[] = "PRIORITY=\0";
+@@ -245,6 +251,9 @@ static int stdout_stream_log(StdoutStream *s, const char *p, LineBreak line_brea
+         assert(s);
+         assert(p);
+ 
++        assert(line_break >= 0);
++        assert(line_break < _LINE_BREAK_MAX);
++
+         if (s->context)
+                 (void) client_context_maybe_refresh(s->server, s->context, NULL, NULL, 0, NULL, USEC_INFINITY);
+         else if (pid_is_valid(s->ucred.pid)) {
+@@ -296,17 +305,19 @@ static int stdout_stream_log(StdoutStream *s, const char *p, LineBreak line_brea
+                         iovec[n++] = IOVEC_MAKE_STRING(syslog_identifier);
+         }
+ 
+-        if (line_break != LINE_BREAK_NEWLINE) {
+-                const char *c;
++        static const char * const line_break_field_table[_LINE_BREAK_MAX] = {
++                [LINE_BREAK_NEWLINE]    = NULL, /* Do not add field if traditional newline */
++                [LINE_BREAK_NUL]        = "_LINE_BREAK=nul",
++                [LINE_BREAK_LINE_MAX]   = "_LINE_BREAK=line-max",
++                [LINE_BREAK_EOF]        = "_LINE_BREAK=eof",
++        };
+ 
+-                /* If this log message was generated due to an uncommon line break then mention this in the log
+-                 * entry */
++        const char *c = line_break_field_table[line_break];
+ 
+-                c =     line_break == LINE_BREAK_NUL ?      "_LINE_BREAK=nul" :
+-                        line_break == LINE_BREAK_LINE_MAX ? "_LINE_BREAK=line-max" :
+-                                                            "_LINE_BREAK=eof";
++        /* If this log message was generated due to an uncommon line break then mention this in the log
++         * entry */
++        if (c)
+                 iovec[n++] = IOVEC_MAKE_STRING(c);
+-        }
+ 
+         message = strappend("MESSAGE=", p);
+         if (message)
diff --git a/SOURCES/0897-journald-use-the-fact-that-client_context_release-re.patch b/SOURCES/0897-journald-use-the-fact-that-client_context_release-re.patch
new file mode 100644
index 0000000..7d4ab74
--- /dev/null
+++ b/SOURCES/0897-journald-use-the-fact-that-client_context_release-re.patch
@@ -0,0 +1,27 @@
+From cd85a657c932725ac7c1b506dc6dd4270d1dc068 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Tue, 12 May 2020 19:15:38 +0200
+Subject: [PATCH] journald: use the fact that client_context_release() returns
+ NULL
+
+(cherry picked from commit 020b4a023c2c6dda83afb9a82a62e640569c40c1)
+
+Related: #2029426
+---
+ src/journal/journald-stream.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/src/journal/journald-stream.c b/src/journal/journald-stream.c
+index 58752a5a24..ab1a855943 100644
+--- a/src/journal/journald-stream.c
++++ b/src/journal/journald-stream.c
+@@ -570,8 +570,7 @@ static int stdout_stream_process(sd_event_source *es, int fd, uint32_t revents,
+                         goto terminate;
+ 
+                 s->ucred = *ucred;
+-                client_context_release(s->server, s->context);
+-                s->context = NULL;
++                s->context = client_context_release(s->server, s->context);
+         }
+ 
+         s->length += l;
diff --git a/SOURCES/0898-journald-rework-pid-change-handling.patch b/SOURCES/0898-journald-rework-pid-change-handling.patch
new file mode 100644
index 0000000..09fb251
--- /dev/null
+++ b/SOURCES/0898-journald-rework-pid-change-handling.patch
@@ -0,0 +1,219 @@
+From 538bd9b42dabf1145cf7ab77f32347d516b01e88 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Tue, 12 May 2020 18:56:34 +0200
+Subject: [PATCH] journald: rework pid change handling
+
+Let's introduce an explicit line ending marker for line endings due to
+pid change.
+
+Let's also make sure we don't get confused with buffer management.
+
+Fixes: #15654
+(cherry picked from commit 45ba1ea5e9264d385fa565328fe957ef1d78caa1)
+
+Resolves: #2029426
+---
+ src/journal/journald-stream.c | 99 +++++++++++++++++++++++------------
+ 1 file changed, 66 insertions(+), 33 deletions(-)
+
+diff --git a/src/journal/journald-stream.c b/src/journal/journald-stream.c
+index ab1a855943..5be5b0939c 100644
+--- a/src/journal/journald-stream.c
++++ b/src/journal/journald-stream.c
+@@ -54,6 +54,7 @@ typedef enum LineBreak {
+         LINE_BREAK_NUL,
+         LINE_BREAK_LINE_MAX,
+         LINE_BREAK_EOF,
++        LINE_BREAK_PID_CHANGE,
+         _LINE_BREAK_MAX,
+         _LINE_BREAK_INVALID = -1,
+ } LineBreak;
+@@ -310,6 +311,7 @@ static int stdout_stream_log(
+                 [LINE_BREAK_NUL]        = "_LINE_BREAK=nul",
+                 [LINE_BREAK_LINE_MAX]   = "_LINE_BREAK=line-max",
+                 [LINE_BREAK_EOF]        = "_LINE_BREAK=eof",
++                [LINE_BREAK_PID_CHANGE] = "_LINE_BREAK=pid-change",
+         };
+ 
+         const char *c = line_break_field_table[line_break];
+@@ -431,21 +433,43 @@ static int stdout_stream_line(StdoutStream *s, char *p, LineBreak line_break) {
+         assert_not_reached("Unknown stream state");
+ }
+ 
+-static int stdout_stream_scan(StdoutStream *s, bool force_flush) {
+-        char *p;
+-        size_t remaining;
++static int stdout_stream_found(
++                StdoutStream *s,
++                char *p,
++                size_t l,
++                LineBreak line_break) {
++
++        char saved;
+         int r;
+ 
+         assert(s);
++        assert(p);
++
++        /* Let's NUL terminate the specified buffer for this call, and revert back afterwards */
++        saved = p[l];
++        p[l] = 0;
++        r = stdout_stream_line(s, p, line_break);
++        p[l] = saved;
+ 
+-        p = s->buffer;
+-        remaining = s->length;
++        return r;
++}
++
++static int stdout_stream_scan(
++                StdoutStream *s,
++                char *p,
++                size_t remaining,
++                LineBreak force_flush,
++                size_t *ret_consumed) {
+ 
+-        /* XXX: This function does nothing if (s->length == 0) */
++        size_t consumed = 0;
++        int r;
++
++        assert(s);
++        assert(p);
+ 
+         for (;;) {
+                 LineBreak line_break;
+-                size_t skip;
++                size_t skip, found;
+                 char *end1, *end2;
+ 
+                 end1 = memchr(p, '\n', remaining);
+@@ -453,43 +477,40 @@ static int stdout_stream_scan(StdoutStream *s, bool force_flush) {
+ 
+                 if (end2) {
+                         /* We found a NUL terminator */
+-                        skip = end2 - p + 1;
++                        found = end2 - p;
++                        skip = found + 1;
+                         line_break = LINE_BREAK_NUL;
+                 } else if (end1) {
+                         /* We found a \n terminator */
+-                        *end1 = 0;
+-                        skip = end1 - p + 1;
++                        found = end1 - p;
++                        skip = found + 1;
+                         line_break = LINE_BREAK_NEWLINE;
+                 } else if (remaining >= s->server->line_max) {
+                         /* Force a line break after the maximum line length */
+-                        *(p + s->server->line_max) = 0;
+-                        skip = remaining;
++                        found = skip = s->server->line_max;
+                         line_break = LINE_BREAK_LINE_MAX;
+                 } else
+                         break;
+ 
+-                r = stdout_stream_line(s, p, line_break);
++                r = stdout_stream_found(s, p, found, line_break);
+                 if (r < 0)
+                         return r;
+ 
+-                remaining -= skip;
+                 p += skip;
++                consumed += skip;
++                remaining -= skip;
+         }
+ 
+-        if (force_flush && remaining > 0) {
+-                p[remaining] = 0;
+-                r = stdout_stream_line(s, p, LINE_BREAK_EOF);
++        if (force_flush >= 0 && remaining > 0) {
++                r = stdout_stream_found(s, p, remaining, force_flush);
+                 if (r < 0)
+                         return r;
+ 
+-                p += remaining;
+-                remaining = 0;
++                consumed += remaining;
+         }
+ 
+-        if (p > s->buffer) {
+-                memmove(s->buffer, p, remaining);
+-                s->length = remaining;
+-        }
++        if (ret_consumed)
++                *ret_consumed = consumed;
+ 
+         return 0;
+ }
+@@ -497,11 +518,12 @@ static int stdout_stream_scan(StdoutStream *s, bool force_flush) {
+ static int stdout_stream_process(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
+         uint8_t buf[CMSG_SPACE(sizeof(struct ucred))];
+         StdoutStream *s = userdata;
++        size_t limit, consumed;
+         struct ucred *ucred = NULL;
+         struct cmsghdr *cmsg;
+         struct iovec iovec;
+-        size_t limit;
+         ssize_t l;
++        char *p;
+         int r;
+ 
+         struct msghdr msghdr = {
+@@ -529,7 +551,7 @@ static int stdout_stream_process(sd_event_source *es, int fd, uint32_t revents,
+         /* Try to make use of the allocated buffer in full, but never read more than the configured line size. Also,
+          * always leave room for a terminating NUL we might need to add. */
+         limit = MIN(s->allocated - 1, s->server->line_max);
+-
++        assert(s->length <= limit);
+         iovec = IOVEC_MAKE(s->buffer + s->length, limit - s->length);
+ 
+         l = recvmsg(s->fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
+@@ -543,7 +565,7 @@ static int stdout_stream_process(sd_event_source *es, int fd, uint32_t revents,
+         cmsg_close_all(&msghdr);
+ 
+         if (l == 0) {
+-                stdout_stream_scan(s, true);
++                (void) stdout_stream_scan(s, s->buffer, s->length, /* force_flush = */ LINE_BREAK_EOF, NULL);
+                 goto terminate;
+         }
+ 
+@@ -562,22 +584,33 @@ static int stdout_stream_process(sd_event_source *es, int fd, uint32_t revents,
+          * in the meantime.
+          */
+         if (ucred && ucred->pid != s->ucred.pid) {
+-                /* force out any previously half-written lines from a
+-                 * different process, before we switch to the new ucred
+-                 * structure for everything we just added */
+-                r = stdout_stream_scan(s, true);
++                /* Force out any previously half-written lines from a different process, before we switch to
++                 * the new ucred structure for everything we just added */
++                r = stdout_stream_scan(s, s->buffer, s->length, /* force_flush = */ LINE_BREAK_PID_CHANGE, NULL);
+                 if (r < 0)
+                         goto terminate;
+ 
+-                s->ucred = *ucred;
+                 s->context = client_context_release(s->server, s->context);
++
++                p = s->buffer + s->length;
++        } else {
++                p = s->buffer;
++                l += s->length;
+         }
+ 
+-        s->length += l;
+-        r = stdout_stream_scan(s, false);
++        /* Always copy in the new credentials */
++        if (ucred)
++                s->ucred = *ucred;
++
++        r = stdout_stream_scan(s, p, l, _LINE_BREAK_INVALID, &consumed);
+         if (r < 0)
+                 goto terminate;
+ 
++        /* Move what wasn't consumed to the front of the buffer */
++        assert(consumed <= (size_t) l);
++        s->length = l - consumed;
++        memmove(s->buffer, p + consumed, s->length);
++
+         return 1;
+ 
+ terminate:
diff --git a/SOURCES/0899-test-Add-a-test-case-for-15654.patch b/SOURCES/0899-test-Add-a-test-case-for-15654.patch
new file mode 100644
index 0000000..24d7ee7
--- /dev/null
+++ b/SOURCES/0899-test-Add-a-test-case-for-15654.patch
@@ -0,0 +1,34 @@
+From e019afeefb396ea42d03f4c3f9713e262aff6450 Mon Sep 17 00:00:00 2001
+From: Benjamin Robin <dev@benjarobin.fr>
+Date: Wed, 6 May 2020 23:28:02 +0200
+Subject: [PATCH] test: Add a test case for #15654
+
+(cherry picked from commit c11d8fd1dab3bc3f0abbc861ba5eb34518cec1da)
+
+Related: #2029426
+---
+ test/TEST-04-JOURNAL/test-journal.sh | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+diff --git a/test/TEST-04-JOURNAL/test-journal.sh b/test/TEST-04-JOURNAL/test-journal.sh
+index a3db1a7472..bdf137cd69 100755
+--- a/test/TEST-04-JOURNAL/test-journal.sh
++++ b/test/TEST-04-JOURNAL/test-journal.sh
+@@ -76,6 +76,17 @@ journalctl -b -o export -t "$ID" --output-fields=_PID | grep '^_PID=' >/output
+ grep -q "^_PID=$PID" /output
+ grep -vq "^_PID=$PID" /output
+ 
++# https://github.com/systemd/systemd/issues/15654
++ID=$(journalctl --new-id128 | sed -n 2p)
++printf "This will\nusually fail\nand be truncated\n">/expected
++systemd-cat -t "$ID" /bin/sh -c 'env echo -n "This will";echo;env echo -n "usually fail";echo;env echo -n "and be truncated";echo;'
++journalctl --sync
++journalctl -b -o cat -t "$ID" >/output
++cmp /expected /output
++
++# Add new tests before here, the journald restarts below
++# may make tests flappy.
++
+ # Don't lose streams on restart
+ systemctl start forever-print-hola
+ sleep 3
diff --git a/SOURCES/0900-test-Stricter-test-case-for-15654-Add-more-checks.patch b/SOURCES/0900-test-Stricter-test-case-for-15654-Add-more-checks.patch
new file mode 100644
index 0000000..8ebaec2
--- /dev/null
+++ b/SOURCES/0900-test-Stricter-test-case-for-15654-Add-more-checks.patch
@@ -0,0 +1,32 @@
+From afcfb65ce7514bf32e59e0b9d212ae18d023a4b5 Mon Sep 17 00:00:00 2001
+From: Benjamin Robin <dev@benjarobin.fr>
+Date: Sat, 9 May 2020 12:01:07 +0200
+Subject: [PATCH] test: Stricter test case for #15654 (Add more checks)
+
+Check:
+ - There is only 3 messages logged with type stdout
+ - Check all messages logged does not have new line: LINE_BREAK=eof
+ - Check that the 3 messages are logged from a different PID
+ - Check the 3 MESSAGE= content
+(cherry picked from commit d38b3b74dbde2d65b23e5963354c3db96acd3420)
+
+Related: #2029426
+---
+ test/TEST-04-JOURNAL/test-journal.sh | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/test/TEST-04-JOURNAL/test-journal.sh b/test/TEST-04-JOURNAL/test-journal.sh
+index bdf137cd69..641259ce24 100755
+--- a/test/TEST-04-JOURNAL/test-journal.sh
++++ b/test/TEST-04-JOURNAL/test-journal.sh
+@@ -83,6 +83,10 @@ systemd-cat -t "$ID" /bin/sh -c 'env echo -n "This will";echo;env echo -n "usual
+ journalctl --sync
+ journalctl -b -o cat -t "$ID" >/output
+ cmp /expected /output
++[[ $(journalctl -b -o export -t "$ID" --output-fields=_TRANSPORT | grep -Pc "^_TRANSPORT=stdout$") -eq 3 ]]
++[[ $(journalctl -b -o export -t "$ID" --output-fields=_LINE_BREAK | grep -Pc "^_LINE_BREAK=pid-change$") -eq 3 ]]
++[[ $(journalctl -b -o export -t "$ID" --output-fields=_PID | sort -u | grep -c "^_PID=.*$") -eq 3 ]]
++[[ $(journalctl -b -o export -t "$ID" --output-fields=MESSAGE | grep -Pc "^MESSAGE=(This will|usually fail|and be truncated)$") -eq 3 ]]
+ 
+ # Add new tests before here, the journald restarts below
+ # may make tests flappy.
diff --git a/SOURCES/0901-man-document-the-new-_LINE_BREAK-type.patch b/SOURCES/0901-man-document-the-new-_LINE_BREAK-type.patch
new file mode 100644
index 0000000..75c0e85
--- /dev/null
+++ b/SOURCES/0901-man-document-the-new-_LINE_BREAK-type.patch
@@ -0,0 +1,42 @@
+From 2f55aeadef3dcdf65c61f24a41178148c3544ac3 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Wed, 13 May 2020 00:09:43 +0200
+Subject: [PATCH] man: document the new _LINE_BREAK= type
+
+(cherry picked from commit a3d9aee14fa2f7df429dc401582877176206b7fd)
+
+Related: #2029426
+---
+ man/systemd.journal-fields.xml | 19 ++++++++++---------
+ 1 file changed, 10 insertions(+), 9 deletions(-)
+
+diff --git a/man/systemd.journal-fields.xml b/man/systemd.journal-fields.xml
+index 0c95c4cd95..ad2b94dbd5 100644
+--- a/man/systemd.journal-fields.xml
++++ b/man/systemd.journal-fields.xml
+@@ -326,15 +326,16 @@
+       <varlistentry>
+         <term><varname>_LINE_BREAK=</varname></term>
+         <listitem>
+-          <para>Only applies to <literal>_TRANSPORT=stdout</literal> records: indicates that the log message in the
+-          standard output/error stream was not terminated with a normal newline character (<literal>\n</literal>,
+-          i.e. ASCII 10). Specifically, when set this field is one of <option>nul</option> (in case the line was
+-          terminated by a NUL byte), <option>line-max</option> (in case the maximum log line length was reached, as
+-          configured with <varname>LineMax=</varname> in
+-          <citerefentry><refentrytitle>journald.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>) or
+-          <option>eof</option> (if this was the last log record of a stream and the stream ended without a final
+-          newline character). Note that this record is not generated when a normal newline character was used for
+-          marking the log line end.</para>
++          <para>Only applies to <literal>_TRANSPORT=stdout</literal> records: indicates that the log message
++          in the standard output/error stream was not terminated with a normal newline character
++          (<literal>\n</literal>, i.e. ASCII 10). Specifically, when set this field is one of
++          <option>nul</option> (in case the line was terminated by a NUL byte), <option>line-max</option> (in
++          case the maximum log line length was reached, as configured with <varname>LineMax=</varname> in
++          <citerefentry><refentrytitle>journald.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>),
++          <option>eof</option> (if this was the last log record of a stream and the stream ended without a
++          final newline character), or <option>pid-change</option> (if the process which generated the log
++          output changed in the middle of a line). Note that this record is not generated when a normal
++          newline character was used for marking the log line end.</para>
+         </listitem>
+       </varlistentry>
+     </variablelist>
diff --git a/SPECS/systemd.spec b/SPECS/systemd.spec
index 48f77b6..5f644f6 100644
--- a/SPECS/systemd.spec
+++ b/SPECS/systemd.spec
@@ -13,7 +13,7 @@
 Name:           systemd
 Url:            http://www.freedesktop.org/wiki/Software/systemd
 Version:        239
-Release:        72%{?dist}
+Release:        73%{?dist}
 # For a breakdown of the licensing, see README
 License:        LGPLv2+ and MIT and GPLv2+
 Summary:        System and Service Manager
@@ -922,6 +922,35 @@ Patch0869: 0869-systemctl-reintroduce-the-original-halt_main.patch
 Patch0870: 0870-systemctl-preserve-old-behavior-unless-requested.patch
 Patch0871: 0871-pam_systemd-suppress-LOG_DEBUG-log-messages-if-debug.patch
 Patch0872: 0872-udev-net_id-introduce-naming-scheme-for-RHEL-8.8.patch
+Patch0873: 0873-journald-add-API-to-move-logging-from-var-to-run-aga.patch
+Patch0874: 0874-journalctl-add-new-relinquish-and-smart-relinquish-o.patch
+Patch0875: 0875-units-automatically-revert-to-run-logging-on-shutdow.patch
+Patch0876: 0876-pstore-Tool-to-archive-contents-of-pstore.patch
+Patch0877: 0877-meson-drop-redundant-line.patch
+Patch0878: 0878-pstore-drop-unnecessary-initializations.patch
+Patch0879: 0879-pstopre-fix-return-value-of-list_files.patch
+Patch0880: 0880-pstore-remove-temporary-file-on-failure.patch
+Patch0881: 0881-pstore-do-not-add-FILE-journal-entry-if-content_size.patch
+Patch0882: 0882-pstore-run-only-when-sys-fs-pstore-is-not-empty.patch
+Patch0883: 0883-pstore-fix-use-after-free.patch
+Patch0884: 0884-pstore-refuse-to-run-if-arguments-are-specified.patch
+Patch0885: 0885-pstore-allow-specifying-src-and-dst-dirs-are-argumen.patch
+Patch0886: 0886-pstore-rework-memory-handling-for-dmesg.patch
+Patch0887: 0887-pstore-fixes-for-dmesg.txt-reconstruction.patch
+Patch0888: 0888-pstore-Don-t-start-systemd-pstore.service-in-contain.patch
+Patch0889: 0889-units-pull-in-systemd-pstore.service-from-sysinit.ta.patch
+Patch0890: 0890-units-drop-dependency-on-systemd-remount-fs.service-.patch
+Patch0891: 0891-units-make-sure-systemd-pstore-stops-at-shutdown.patch
+Patch0892: 0892-pstore-Run-after-modules-are-loaded.patch
+Patch0893: 0893-pstore-do-not-try-to-load-all-known-pstore-modules.patch
+Patch0894: 0894-logind-session-make-stopping-of-idle-session-visible.patch
+Patch0895: 0895-journald-Increase-stdout-buffer-size-sooner-when-alm.patch
+Patch0896: 0896-journald-rework-end-of-line-marker-handling-to-use-a.patch
+Patch0897: 0897-journald-use-the-fact-that-client_context_release-re.patch
+Patch0898: 0898-journald-rework-pid-change-handling.patch
+Patch0899: 0899-test-Add-a-test-case-for-15654.patch
+Patch0900: 0900-test-Stricter-test-case-for-15654-Add-more-checks.patch
+Patch0901: 0901-man-document-the-new-_LINE_BREAK-type.patch
 
 %ifarch %{ix86} x86_64 aarch64
 %global have_gnu_efi 1
@@ -1339,7 +1368,8 @@ python3 %{SOURCE2} %buildroot <<EOF
 EOF
 
 %check
-%meson_test
+# Add --num-processes 1 as workaround for issues on ppc64le - AttributeError: 'NoneType' object has no attribute '_add_reader' - https://github.com/python/cpython/issues/82200
+%meson_test --num-processes 1
 
 #############################################################################################
 
@@ -1551,6 +1581,37 @@ fi
 %files tests -f .file-list-tests
 
 %changelog
+* Mon Feb 27 2023 systemd maintenance team <systemd-maint@redhat.com> - 239-73
+- journald: add API to move logging from /var to /run again (#1873540)
+- journalctl: add new --relinquish and --smart-relinquish options (#1873540)
+- units: automatically revert to /run logging on shutdown if necessary (#1873540)
+- pstore: Tool to archive contents of pstore (#2158832)
+- meson: drop redundant line (#2158832)
+- pstore: drop unnecessary initializations (#2158832)
+- pstopre: fix return value of list_files() (#2158832)
+- pstore: remove temporary file on failure (#2158832)
+- pstore: do not add FILE= journal entry if content_size == 0 (#2158832)
+- pstore: run only when /sys/fs/pstore is not empty (#2158832)
+- pstore: fix use after free (#2158832)
+- pstore: refuse to run if arguments are specified (#2158832)
+- pstore: allow specifying src and dst dirs are arguments (#2158832)
+- pstore: rework memory handling for dmesg (#2158832)
+- pstore: fixes for dmesg.txt reconstruction (#2158832)
+- pstore: Don't start systemd-pstore.service in containers (#2158832)
+- units: pull in systemd-pstore.service from sysinit.target (#2158832)
+- units: drop dependency on systemd-remount-fs.service from systemd-pstore.service (#2158832)
+- units: make sure systemd-pstore stops at shutdown (#2158832)
+- pstore: Run after modules are loaded (#2158832)
+- pstore: do not try to load all known pstore modules (#2158832)
+- logind-session: make stopping of idle session visible to admins (#2156780)
+- journald: Increase stdout buffer size sooner, when almost full (#2029426)
+- journald: rework end of line marker handling to use a field table (#2029426)
+- journald: use the fact that client_context_release() returns NULL (#2029426)
+- journald: rework pid change handling (#2029426)
+- test: Add a test case for #15654 (#2029426)
+- test: Stricter test case for #15654 (Add more checks) (#2029426)
+- man: document the new _LINE_BREAK= type (#2029426)
+
 * Fri Feb 17 2023 systemd maintenance team <systemd-maint@redhat.com> - 239-72
 - test: import logind test from debian/ubuntu test suite (#1866955)
 - test: introduce inst_recursive() helper function (#1866955)