diff --git a/SOURCES/0499-Revert-udev-net_id-add-support-for-phys_port_name-at.patch b/SOURCES/0499-Revert-udev-net_id-add-support-for-phys_port_name-at.patch
deleted file mode 100644
index 92b8938..0000000
--- a/SOURCES/0499-Revert-udev-net_id-add-support-for-phys_port_name-at.patch
+++ /dev/null
@@ -1,95 +0,0 @@
-From 6cbd97527f6d33a140072131785547e898ee4c7a Mon Sep 17 00:00:00 2001
-From: Lukas Nykryn <lnykryn@redhat.com>
-Date: Tue, 15 Aug 2017 12:30:03 +0200
-Subject: [PATCH] Revert "udev: net_id: add support for phys_port_name
- attribute (#4506)"
-
-This reverts commit 192545bc67fed763ac54761ca067b9c2f93ecdd1.
-
-This caused change of the names for sfc driver.
-
-Resolves: #1477285
----
- src/udev/udev-builtin-net_id.c | 24 ++++++------------------
- 1 file changed, 6 insertions(+), 18 deletions(-)
-
-diff --git a/src/udev/udev-builtin-net_id.c b/src/udev/udev-builtin-net_id.c
-index 7c154355d..19e1f2631 100644
---- a/src/udev/udev-builtin-net_id.c
-+++ b/src/udev/udev-builtin-net_id.c
-@@ -38,7 +38,7 @@
-  *   o<index>[d<dev_port>]                 -- on-board device index number
-  *   s<slot>[f<function>][d<dev_port>]     -- hotplug slot index number
-  *   x<MAC>                                -- MAC address
-- *   [P<domain>]p<bus>s<slot>[f<function>][n<phys_port_name>|d<dev_id>/<dev_port>]
-+ *   [P<domain>]p<bus>s<slot>[f<function>][d<dev_id>/<dev_port>]
-  *                                         -- PCI geographical location
-  *   [P<domain>]p<bus>s<slot>[f<function>][u<port>][..][c<config>][i<interface>]
-  *                                         -- USB port number chain
-@@ -134,7 +134,7 @@ static int dev_pci_onboard(struct udev_device *dev, struct netnames *names) {
-         unsigned dev_port = 0;
-         size_t l;
-         char *s;
--        const char *attr, *port_name;
-+        const char *attr;
-         int idx;
- 
-         /* ACPI _DSM  -- device specific method for naming a PCI or PCI Express device */
-@@ -161,15 +161,10 @@ static int dev_pci_onboard(struct udev_device *dev, struct netnames *names) {
-         if (attr)
-                 dev_port = strtol(attr, NULL, 10);
- 
--        /* kernel provided front panel port name for multiple port PCI device */
--        port_name = udev_device_get_sysattr_value(dev, "phys_port_name");
--
-         s = names->pci_onboard;
-         l = sizeof(names->pci_onboard);
-         l = strpcpyf(&s, l, "o%d", idx);
--        if (port_name)
--                l = strpcpyf(&s, l, "n%s", port_name);
--        else if (dev_port > 0)
-+        if (dev_port > 0)
-                 l = strpcpyf(&s, l, "d%d", dev_port);
-         if (l == 0)
-                 names->pci_onboard[0] = '\0';
-@@ -204,7 +199,7 @@ static int dev_pci_slot(struct udev_device *dev, struct netnames *names) {
-         unsigned domain, bus, slot, func, dev_id = 0;
-         size_t l;
-         char *s;
--        const char *attr, *port_name;
-+        const char *attr;
-         struct udev_device *pci = NULL;
-         char slots[256], str[256];
-         _cleanup_closedir_ DIR *dir = NULL;
-@@ -225,9 +220,6 @@ static int dev_pci_slot(struct udev_device *dev, struct netnames *names) {
-                 }
-         }
- 
--        /* kernel provided front panel port name for multiple port PCI device */
--        port_name = udev_device_get_sysattr_value(dev, "phys_port_name");
--
-         /* compose a name based on the raw kernel's PCI bus, slot numbers */
-         s = names->pci_path;
-         l = sizeof(names->pci_path);
-@@ -236,9 +228,7 @@ static int dev_pci_slot(struct udev_device *dev, struct netnames *names) {
-         l = strpcpyf(&s, l, "p%us%u", bus, slot);
-         if (func > 0 || is_pci_multifunction(names->pcidev))
-                 l = strpcpyf(&s, l, "f%d", func);
--        if (port_name)
--                l = strpcpyf(&s, l, "n%s", port_name);
--        else if (dev_id > 0)
-+        if (dev_id > 0)
-                 l = strpcpyf(&s, l, "d%d", dev_id);
-         if (l == 0)
-                 names->pci_path[0] = '\0';
-@@ -288,9 +278,7 @@ static int dev_pci_slot(struct udev_device *dev, struct netnames *names) {
-                 l = strpcpyf(&s, l, "s%d", hotplug_slot);
-                 if (func > 0 || is_pci_multifunction(names->pcidev))
-                         l = strpcpyf(&s, l, "f%d", func);
--                if (port_name)
--                        l = strpcpyf(&s, l, "n%s", port_name);
--                else if (dev_id > 0)
-+                if (dev_id > 0)
-                         l = strpcpyf(&s, l, "d%d", dev_id);
-                 if (l == 0)
-                         names->pci_slot[0] = '\0';
diff --git a/SOURCES/0499-tests-use-XFS-as-root-filesystem-for-system-tests.patch b/SOURCES/0499-tests-use-XFS-as-root-filesystem-for-system-tests.patch
new file mode 100644
index 0000000..7dff683
--- /dev/null
+++ b/SOURCES/0499-tests-use-XFS-as-root-filesystem-for-system-tests.patch
@@ -0,0 +1,50 @@
+From e82e71d82496b7dd3268db62a89f215b4b38508f Mon Sep 17 00:00:00 2001
+From: Michal Sekletar <msekleta@redhat.com>
+Date: Mon, 24 Jul 2017 18:47:36 +0200
+Subject: [PATCH] tests: use XFS as root filesystem for system tests
+
+On RHEL-7 we don't have mount.ext3 in initramfs.
+
+RHEL-only
+
+Resolves: #1475870
+---
+ test/TEST-02-CRYPTSETUP/test.sh | 4 ++--
+ test/test-functions             | 2 +-
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/test/TEST-02-CRYPTSETUP/test.sh b/test/TEST-02-CRYPTSETUP/test.sh
+index 4be2365e2..6e5c53d8b 100755
+--- a/test/TEST-02-CRYPTSETUP/test.sh
++++ b/test/TEST-02-CRYPTSETUP/test.sh
+@@ -38,7 +38,7 @@ test_setup() {
+     echo -n test >$TESTDIR/keyfile
+     cryptsetup -q luksFormat ${LOOPDEV}p2 $TESTDIR/keyfile
+     cryptsetup luksOpen ${LOOPDEV}p2 varcrypt <$TESTDIR/keyfile
+-    mkfs.ext3 -L var /dev/mapper/varcrypt
++    mkfs.xfs -L var /dev/mapper/varcrypt
+     mkdir -p $TESTDIR/root
+     mount ${LOOPDEV}p1 $TESTDIR/root
+     mkdir -p $TESTDIR/root/var
+@@ -74,7 +74,7 @@ EOF
+         cat $initdir/etc/crypttab | ddebug
+ 
+         cat >>$initdir/etc/fstab <<EOF
+-/dev/mapper/varcrypt    /var    ext3    defaults 0 1
++/dev/mapper/varcrypt    /var    xfs    defaults 0 1
+ EOF
+     )
+     setup_nspawn_root
+diff --git a/test/test-functions b/test/test-functions
+index 901ff4860..f8950e31e 100644
+--- a/test/test-functions
++++ b/test/test-functions
+@@ -150,7 +150,7 @@ create_empty_image() {
+ ,
+ EOF
+ 
+-    mkfs.ext3 -L systemd "${LOOPDEV}p1"
++    mkfs.xfs -L systemd "${LOOPDEV}p1"
+ }
+ 
+ check_result_nspawn() {
diff --git a/SOURCES/0500-sysctl-fix-uninitialized-variable.patch b/SOURCES/0500-sysctl-fix-uninitialized-variable.patch
deleted file mode 100644
index 11226b8..0000000
--- a/SOURCES/0500-sysctl-fix-uninitialized-variable.patch
+++ /dev/null
@@ -1,27 +0,0 @@
-From 6fd8e5c41ffd14038accd866ccd81d9a35cb3291 Mon Sep 17 00:00:00 2001
-From: Michal Sekletar <msekleta@redhat.com>
-Date: Fri, 25 Aug 2017 13:13:50 +0200
-Subject: [PATCH] sysctl: fix uninitialized variable
-
-RHEL-only
-
-Reported-by: HATAYAMA Daisuke <d.hatayama@jp.fujitsu.com>
-
-Resolves: #1485121
----
- src/sysctl/sysctl.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/src/sysctl/sysctl.c b/src/sysctl/sysctl.c
-index bb2bea7cd..7fb016cee 100644
---- a/src/sysctl/sysctl.c
-+++ b/src/sysctl/sysctl.c
-@@ -91,7 +91,7 @@ static int apply_sysctl(const char *property, const char *value) {
- }
- 
- static int apply_all(OrderedHashmap *sysctl_options) {
--        int r;
-+        int r = 0;
-         char *property, *value;
-         Iterator i;
- 
diff --git a/SOURCES/0500-tests-use-fdisk-instead-of-sfdisk.patch b/SOURCES/0500-tests-use-fdisk-instead-of-sfdisk.patch
new file mode 100644
index 0000000..d15f912
--- /dev/null
+++ b/SOURCES/0500-tests-use-fdisk-instead-of-sfdisk.patch
@@ -0,0 +1,60 @@
+From 5655999840f9c3d8b55a40c1751df400b425178a Mon Sep 17 00:00:00 2001
+From: Michal Sekletar <msekleta@redhat.com>
+Date: Mon, 24 Jul 2017 13:25:19 +0200
+Subject: [PATCH] tests: use fdisk instead of sfdisk
+
+In RHEL7 we have an older version of sfdisk that exits with an error
+when executed with sfdisk script that is used in upstream to create
+partitions on root disk.
+
+Let's use equivalent fdisk commands to achieve the (more less) same
+result.
+
+Also default size of disk image is bumped to 400M. Previous 300M doesn't
+work, probably due to some fdisk bug. Size of second partiotion (/var in
+TEST-02-CRYPTSETUP) is bumped to 50M to accommodate space requirements
+of xfs filesystem.
+
+RHEL-only
+
+Resolves: #1475870
+---
+ test/test-functions | 21 ++++++++++++++++-----
+ 1 file changed, 16 insertions(+), 5 deletions(-)
+
+diff --git a/test/test-functions b/test/test-functions
+index f8950e31e..cf5612370 100644
+--- a/test/test-functions
++++ b/test/test-functions
+@@ -141,15 +141,26 @@ install_missing_libraries() {
+ create_empty_image() {
+     rm -f "$TESTDIR/rootdisk.img"
+     # Create the blank file to use as a root filesystem
+-    dd if=/dev/null of="$TESTDIR/rootdisk.img" bs=1M seek=300
++    dd if=/dev/null of="$TESTDIR/rootdisk.img" bs=1M seek=400
+     LOOPDEV=$(losetup --show -P -f $TESTDIR/rootdisk.img)
+     [ -b "$LOOPDEV" ] || return 1
+     echo "LOOPDEV=$LOOPDEV" >> $STATEFILE
+-    sfdisk "$LOOPDEV" <<EOF
+-,290M
+-,
++    fdisk "$LOOPDEV" <<EOF
++o
++n
++p
++1
++
+++290M
++n
++p
++2
++
+++50M
++w
++q
+ EOF
+-
++    partprobe "$LOOPDEV"
+     mkfs.xfs -L systemd "${LOOPDEV}p1"
+ }
+ 
diff --git a/SOURCES/0501-Revert-udev-net_id-add-support-for-phys_port_name-at.patch b/SOURCES/0501-Revert-udev-net_id-add-support-for-phys_port_name-at.patch
new file mode 100644
index 0000000..4b0472f
--- /dev/null
+++ b/SOURCES/0501-Revert-udev-net_id-add-support-for-phys_port_name-at.patch
@@ -0,0 +1,95 @@
+From 8ad860fa8e344c71fb3bb00a15b25d41e3c61b35 Mon Sep 17 00:00:00 2001
+From: Lukas Nykryn <lnykryn@redhat.com>
+Date: Tue, 15 Aug 2017 12:30:03 +0200
+Subject: [PATCH] Revert "udev: net_id: add support for phys_port_name
+ attribute (#4506)"
+
+This reverts commit 192545bc67fed763ac54761ca067b9c2f93ecdd1.
+
+This caused change of the names for sfc driver.
+
+Resolves: #1477285
+---
+ src/udev/udev-builtin-net_id.c | 24 ++++++------------------
+ 1 file changed, 6 insertions(+), 18 deletions(-)
+
+diff --git a/src/udev/udev-builtin-net_id.c b/src/udev/udev-builtin-net_id.c
+index 7c154355d..19e1f2631 100644
+--- a/src/udev/udev-builtin-net_id.c
++++ b/src/udev/udev-builtin-net_id.c
+@@ -38,7 +38,7 @@
+  *   o<index>[d<dev_port>]                 -- on-board device index number
+  *   s<slot>[f<function>][d<dev_port>]     -- hotplug slot index number
+  *   x<MAC>                                -- MAC address
+- *   [P<domain>]p<bus>s<slot>[f<function>][n<phys_port_name>|d<dev_id>/<dev_port>]
++ *   [P<domain>]p<bus>s<slot>[f<function>][d<dev_id>/<dev_port>]
+  *                                         -- PCI geographical location
+  *   [P<domain>]p<bus>s<slot>[f<function>][u<port>][..][c<config>][i<interface>]
+  *                                         -- USB port number chain
+@@ -134,7 +134,7 @@ static int dev_pci_onboard(struct udev_device *dev, struct netnames *names) {
+         unsigned dev_port = 0;
+         size_t l;
+         char *s;
+-        const char *attr, *port_name;
++        const char *attr;
+         int idx;
+ 
+         /* ACPI _DSM  -- device specific method for naming a PCI or PCI Express device */
+@@ -161,15 +161,10 @@ static int dev_pci_onboard(struct udev_device *dev, struct netnames *names) {
+         if (attr)
+                 dev_port = strtol(attr, NULL, 10);
+ 
+-        /* kernel provided front panel port name for multiple port PCI device */
+-        port_name = udev_device_get_sysattr_value(dev, "phys_port_name");
+-
+         s = names->pci_onboard;
+         l = sizeof(names->pci_onboard);
+         l = strpcpyf(&s, l, "o%d", idx);
+-        if (port_name)
+-                l = strpcpyf(&s, l, "n%s", port_name);
+-        else if (dev_port > 0)
++        if (dev_port > 0)
+                 l = strpcpyf(&s, l, "d%d", dev_port);
+         if (l == 0)
+                 names->pci_onboard[0] = '\0';
+@@ -204,7 +199,7 @@ static int dev_pci_slot(struct udev_device *dev, struct netnames *names) {
+         unsigned domain, bus, slot, func, dev_id = 0;
+         size_t l;
+         char *s;
+-        const char *attr, *port_name;
++        const char *attr;
+         struct udev_device *pci = NULL;
+         char slots[256], str[256];
+         _cleanup_closedir_ DIR *dir = NULL;
+@@ -225,9 +220,6 @@ static int dev_pci_slot(struct udev_device *dev, struct netnames *names) {
+                 }
+         }
+ 
+-        /* kernel provided front panel port name for multiple port PCI device */
+-        port_name = udev_device_get_sysattr_value(dev, "phys_port_name");
+-
+         /* compose a name based on the raw kernel's PCI bus, slot numbers */
+         s = names->pci_path;
+         l = sizeof(names->pci_path);
+@@ -236,9 +228,7 @@ static int dev_pci_slot(struct udev_device *dev, struct netnames *names) {
+         l = strpcpyf(&s, l, "p%us%u", bus, slot);
+         if (func > 0 || is_pci_multifunction(names->pcidev))
+                 l = strpcpyf(&s, l, "f%d", func);
+-        if (port_name)
+-                l = strpcpyf(&s, l, "n%s", port_name);
+-        else if (dev_id > 0)
++        if (dev_id > 0)
+                 l = strpcpyf(&s, l, "d%d", dev_id);
+         if (l == 0)
+                 names->pci_path[0] = '\0';
+@@ -288,9 +278,7 @@ static int dev_pci_slot(struct udev_device *dev, struct netnames *names) {
+                 l = strpcpyf(&s, l, "s%d", hotplug_slot);
+                 if (func > 0 || is_pci_multifunction(names->pcidev))
+                         l = strpcpyf(&s, l, "f%d", func);
+-                if (port_name)
+-                        l = strpcpyf(&s, l, "n%s", port_name);
+-                else if (dev_id > 0)
++                if (dev_id > 0)
+                         l = strpcpyf(&s, l, "d%d", dev_id);
+                 if (l == 0)
+                         names->pci_slot[0] = '\0';
diff --git a/SOURCES/0501-udev-ignore-SIGCHLD-from-unexpected-processes-130653.patch b/SOURCES/0501-udev-ignore-SIGCHLD-from-unexpected-processes-130653.patch
deleted file mode 100644
index b497247..0000000
--- a/SOURCES/0501-udev-ignore-SIGCHLD-from-unexpected-processes-130653.patch
+++ /dev/null
@@ -1,30 +0,0 @@
-From 8b998d862e401c252c4323974698691e67846412 Mon Sep 17 00:00:00 2001
-From: Jan Synacek <jsynacek@redhat.com>
-Date: Tue, 15 Aug 2017 13:29:51 +0200
-Subject: [PATCH] udev: ignore SIGCHLD from unexpected processes (#1306539)
-
-RHEL-only
-
-Author: grzegorz.halat@motorolasolutions.com
-Resolves: #1306539
----
- src/udev/udev-event.c | 6 +++++-
- 1 file changed, 5 insertions(+), 1 deletion(-)
-
-diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c
-index bc115f112..0ba079201 100644
---- a/src/udev/udev-event.c
-+++ b/src/udev/udev-event.c
-@@ -610,7 +610,11 @@ static int spawn_wait(struct udev_event *event,
-                                 event->sigterm = true;
-                                 break;
-                         case SIGCHLD:
--                                if (waitpid(pid, &status, WNOHANG) < 0)
-+                                if (pid != (pid_t) fdsi.ssi_pid) {
-+                                        log_debug("expected SIGCHLD from '%s' ["PID_FMT"] received from unknown process ["PID_FMT"]. Ignoring", cmd, pid, fdsi.ssi_pid);
-+                                        continue;
-+                                }
-+                                if (waitpid(pid, &status, WNOHANG) <= 0)
-                                         break;
-                                 if (WIFEXITED(status)) {
-                                         log_debug("'%s' ["PID_FMT"] exit with return code %i", cmd, pid, WEXITSTATUS(status));
diff --git a/SOURCES/0502-core-unset-sysfs-path-after-transition-to-dead-state.patch b/SOURCES/0502-core-unset-sysfs-path-after-transition-to-dead-state.patch
new file mode 100644
index 0000000..9991b10
--- /dev/null
+++ b/SOURCES/0502-core-unset-sysfs-path-after-transition-to-dead-state.patch
@@ -0,0 +1,49 @@
+From d5ab3fdc9bf9353478e7c0987b3830f14bbdefae Mon Sep 17 00:00:00 2001
+From: Michal Sekletar <msekleta@redhat.com>
+Date: Thu, 22 Jun 2017 14:26:39 +0200
+Subject: [PATCH] core: unset sysfs path after transition to dead state
+
+Device is gone and most likely it will get garbage collected. However in
+cases when it doesn't get gc'ed (because it is referenced by some
+other unit, e.g. mount from fstab) we need to unset sysfs. This is
+because when device appears next time, possibly, with different sysfs
+path we need to update the sysfs path. Current code could end up caching
+stale sysfs path forever.
+
+In reality this is not a problem for normal disks (unless you swap them
+during system runtime). However this issue causes failures to mount
+filesystems on LVM where sysfs path depends on activation
+order (i.e. logical volumes from volume group that is activated first
+get assigned lower dm-X numbers and corresponding syspaths).
+
+Fixes #6126
+
+(cherry picked from commit 0e139cac0318de09e6f4c1a4fc61388f7e541ebd)
+
+Resolves: #1408916
+---
+ src/core/device.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/src/core/device.c b/src/core/device.c
+index befbae83f..63a04bdd3 100644
+--- a/src/core/device.c
++++ b/src/core/device.c
+@@ -474,12 +474,16 @@ static void device_update_found_one(Device *d, bool add, DeviceFound found, bool
+                  * now referenced by the kernel, then we assume the
+                  * kernel knows it now, and udev might soon too. */
+                 device_set_state(d, DEVICE_TENTATIVE);
+-        else
++        else {
+                 /* If nobody sees the device, or if the device was
+                  * previously seen by udev and now is only referenced
+                  * from the kernel, then we consider the device is
+                  * gone, the kernel just hasn't noticed it yet. */
++
+                 device_set_state(d, DEVICE_DEAD);
++                device_unset_sysfs(d);
++        }
++
+ }
+ 
+ static int device_update_found_by_sysfs(Manager *m, const char *sysfs, bool add, DeviceFound found, bool now) {
diff --git a/SOURCES/0502-manager-when-reexecuting-try-to-connect-to-bus-only-.patch b/SOURCES/0502-manager-when-reexecuting-try-to-connect-to-bus-only-.patch
deleted file mode 100644
index d66b01e..0000000
--- a/SOURCES/0502-manager-when-reexecuting-try-to-connect-to-bus-only-.patch
+++ /dev/null
@@ -1,48 +0,0 @@
-From 156f59bc8c84fd0015b8170f6c4af9eadd1b5cfa Mon Sep 17 00:00:00 2001
-From: Michal Sekletar <msekletar@users.noreply.github.com>
-Date: Fri, 8 Sep 2017 15:41:44 +0200
-Subject: [PATCH] manager: when reexecuting try to connect to bus only when
- dbus.service is around (#6773)
-
-Trying to connect otherwise is pointless, because if socket isn't around
-we won't connect. However, when dbus.socket is present we attempt to
-connect. That attempt can't succeed because we are then supposed
-to activate dbus.service as a response to connection from
-us. This results in deadlock.
-
-Fixes #6303
-
-(cherry picked from commit 5463fa0a88f95d2002858592578f9bf4e0d2660a)
-
-Resolves: #1465737
----
- src/core/manager.c | 9 ++++++---
- 1 file changed, 6 insertions(+), 3 deletions(-)
-
-diff --git a/src/core/manager.c b/src/core/manager.c
-index 287cf6a74..041fac46b 100644
---- a/src/core/manager.c
-+++ b/src/core/manager.c
-@@ -799,16 +799,19 @@ static int manager_setup_kdbus(Manager *m) {
- 
- static int manager_connect_bus(Manager *m, bool reexecuting) {
-         bool try_bus_connect;
-+        Unit *u = NULL;
- 
-         assert(m);
- 
-         if (m->test_run)
-                 return 0;
- 
-+        u = manager_get_unit(m, SPECIAL_DBUS_SERVICE);
-+
-         try_bus_connect =
--                m->kdbus_fd >= 0 ||
--                reexecuting ||
--                (m->running_as == SYSTEMD_USER && getenv("DBUS_SESSION_BUS_ADDRESS"));
-+                (u && UNIT_IS_ACTIVE_OR_RELOADING(unit_active_state(u))) &&
-+                (reexecuting ||
-+                (m->running_as == SYSTEMD_USER && getenv("DBUS_SESSION_BUS_ADDRESS")));
- 
-         /* Try to connect to the busses, if possible. */
-         return bus_init(m, try_bus_connect);
diff --git a/SOURCES/0503-sysctl-fix-uninitialized-variable.patch b/SOURCES/0503-sysctl-fix-uninitialized-variable.patch
new file mode 100644
index 0000000..821541c
--- /dev/null
+++ b/SOURCES/0503-sysctl-fix-uninitialized-variable.patch
@@ -0,0 +1,27 @@
+From 75d982344e59e1dd916c214c5ccb6339c5c94254 Mon Sep 17 00:00:00 2001
+From: Michal Sekletar <msekleta@redhat.com>
+Date: Fri, 25 Aug 2017 13:13:50 +0200
+Subject: [PATCH] sysctl: fix uninitialized variable
+
+RHEL-only
+
+Reported-by: HATAYAMA Daisuke <d.hatayama@jp.fujitsu.com>
+
+Resolves: #1485121
+---
+ src/sysctl/sysctl.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/sysctl/sysctl.c b/src/sysctl/sysctl.c
+index bb2bea7cd..7fb016cee 100644
+--- a/src/sysctl/sysctl.c
++++ b/src/sysctl/sysctl.c
+@@ -91,7 +91,7 @@ static int apply_sysctl(const char *property, const char *value) {
+ }
+ 
+ static int apply_all(OrderedHashmap *sysctl_options) {
+-        int r;
++        int r = 0;
+         char *property, *value;
+         Iterator i;
+ 
diff --git a/SOURCES/0503-unmount-Pass-in-mount-options-when-remounting-read-o.patch b/SOURCES/0503-unmount-Pass-in-mount-options-when-remounting-read-o.patch
deleted file mode 100644
index fe9a804..0000000
--- a/SOURCES/0503-unmount-Pass-in-mount-options-when-remounting-read-o.patch
+++ /dev/null
@@ -1,104 +0,0 @@
-From 02a5d91ec022be1188875e0f169277cef3b11ad6 Mon Sep 17 00:00:00 2001
-From: Jan Janssen <medhefgo@web.de>
-Date: Mon, 26 Oct 2015 15:13:28 +0100
-Subject: [PATCH] unmount: Pass in mount options when remounting read-only
-
-man 2 mount says that the mountflags and data parameteres should
-match the original values except for the desired changes. We only
-bother with the mount options since the only flags we can change
-are MS_RDONLY, MS_SYNCHRONOUS and MS_MANDLOCK; which shouldn't
-matter too much.
-
-Fixes: #351
-
-(cherry picked from commit 471b48ed2ff6539e7071ff4694c03483c5835639)
-
-Related: #1312002
----
- src/core/umount.c | 26 ++++++++++++++++++++------
- 1 file changed, 20 insertions(+), 6 deletions(-)
-
-diff --git a/src/core/umount.c b/src/core/umount.c
-index dd7df194d..bfd8aa5f8 100644
---- a/src/core/umount.c
-+++ b/src/core/umount.c
-@@ -28,6 +28,7 @@
- #include <linux/loop.h>
- #include <linux/dm-ioctl.h>
- 
-+#include "fstab-util.h"
- #include "list.h"
- #include "mount-setup.h"
- #include "umount.h"
-@@ -39,6 +40,7 @@
- 
- typedef struct MountPoint {
-         char *path;
-+        char *options;
-         dev_t devnum;
-         LIST_FIELDS(struct MountPoint, mount_point);
- } MountPoint;
-@@ -71,7 +73,7 @@ static int mount_points_list_get(MountPoint **head) {
-                 return -errno;
- 
-         for (i = 1;; i++) {
--                _cleanup_free_ char *path = NULL;
-+                _cleanup_free_ char *path = NULL, *options = NULL;
-                 char *p = NULL;
-                 MountPoint *m;
-                 int k;
-@@ -82,15 +84,15 @@ static int mount_points_list_get(MountPoint **head) {
-                            "%*s "       /* (3) major:minor */
-                            "%*s "       /* (4) root */
-                            "%ms "       /* (5) mount point */
--                           "%*s"        /* (6) mount options */
-+                           "%*s"        /* (6) mount flags */
-                            "%*[^-]"     /* (7) optional fields */
-                            "- "         /* (8) separator */
-                            "%*s "       /* (9) file system type */
-                            "%*s"        /* (10) mount source */
--                           "%*s"        /* (11) mount options 2 */
-+                           "%ms"        /* (11) mount options */
-                            "%*[^\n]",   /* some rubbish at the end */
--                           &path);
--                if (k != 1) {
-+                           &path, &options);
-+                if (k != 2) {
-                         if (k == EOF)
-                                 break;
- 
-@@ -125,6 +127,9 @@ static int mount_points_list_get(MountPoint **head) {
-                 }
- 
-                 m->path = p;
-+                m->options = options;
-+                options = NULL;
-+
-                 LIST_PREPEND(mount_point, *head, m);
-         }
- 
-@@ -368,6 +373,14 @@ static int mount_points_list_umount(MountPoint **head, bool *changed, bool log_e
-                    benefits, but might confuse the host, as we remount
-                    the superblock here, not the bind mound. */
-                 if (detect_container(NULL) <= 0)  {
-+                        _cleanup_free_ char *options = NULL;
-+                        /* MS_REMOUNT requires that the data parameter
-+                         * should be the same from the original mount
-+                         * except for the desired changes. Since we want
-+                         * to remount read-only, we should filter out
-+                         * rw (and ro too, because it confuses the kernel) */
-+                        (void) fstab_filter_options(m->options, "rw\0ro\0", NULL, NULL, &options);
-+
-                         /* We always try to remount directories
-                          * read-only first, before we go on and umount
-                          * them.
-@@ -384,7 +397,8 @@ static int mount_points_list_umount(MountPoint **head, bool *changed, bool log_e
-                          * alias read-only we hence should be
-                          * relatively safe regarding keeping the fs we
-                          * can otherwise not see dirty. */
--                        mount(NULL, m->path, NULL, MS_REMOUNT|MS_RDONLY, NULL);
-+                        log_info("Remounting '%s' read-only with options '%s'.", m->path, options);
-+                        (void) mount(NULL, m->path, NULL, MS_REMOUNT|MS_RDONLY, options);
-                 }
- 
-                 /* Skip / and /usr since we cannot unmount that
diff --git a/SOURCES/0504-shutdown-don-t-remount-ro-network-filesystems.-6588.patch b/SOURCES/0504-shutdown-don-t-remount-ro-network-filesystems.-6588.patch
deleted file mode 100644
index 0581aa2..0000000
--- a/SOURCES/0504-shutdown-don-t-remount-ro-network-filesystems.-6588.patch
+++ /dev/null
@@ -1,76 +0,0 @@
-From c6bb93f0b564d6c0eea9e35197b66521693b2078 Mon Sep 17 00:00:00 2001
-From: NeilBrown <neil@brown.name>
-Date: Thu, 31 Aug 2017 02:48:25 +1000
-Subject: [PATCH] shutdown: don't remount,ro network filesystems. (#6588)
-
-systemd-shutdown is run after the network is stopped,
-so remounting a network filesystem read-only can hang.
-A simple umount is the most useful thing that can
-be done for a network filesystem once the network is down.
-
-(cherry picked from commit 9cbc4547702aac28466c497f720038b9e2dc510c)
-
-Resolves: #1312002
----
- src/core/umount.c | 17 ++++++++++++-----
- 1 file changed, 12 insertions(+), 5 deletions(-)
-
-diff --git a/src/core/umount.c b/src/core/umount.c
-index bfd8aa5f8..6e8ccc794 100644
---- a/src/core/umount.c
-+++ b/src/core/umount.c
-@@ -41,6 +41,7 @@
- typedef struct MountPoint {
-         char *path;
-         char *options;
-+        char *type;
-         dev_t devnum;
-         LIST_FIELDS(struct MountPoint, mount_point);
- } MountPoint;
-@@ -73,7 +74,7 @@ static int mount_points_list_get(MountPoint **head) {
-                 return -errno;
- 
-         for (i = 1;; i++) {
--                _cleanup_free_ char *path = NULL, *options = NULL;
-+                _cleanup_free_ char *path = NULL, *options = NULL, *type = NULL;
-                 char *p = NULL;
-                 MountPoint *m;
-                 int k;
-@@ -87,11 +88,11 @@ static int mount_points_list_get(MountPoint **head) {
-                            "%*s"        /* (6) mount flags */
-                            "%*[^-]"     /* (7) optional fields */
-                            "- "         /* (8) separator */
--                           "%*s "       /* (9) file system type */
-+                           "%ms "       /* (9) file system type */
-                            "%*s"        /* (10) mount source */
-                            "%ms"        /* (11) mount options */
-                            "%*[^\n]",   /* some rubbish at the end */
--                           &path, &options);
-+                           &path, &type, &options);
-                 if (k != 2) {
-                         if (k == EOF)
-                                 break;
-@@ -129,6 +130,8 @@ static int mount_points_list_get(MountPoint **head) {
-                 m->path = p;
-                 m->options = options;
-                 options = NULL;
-+                m->type = type;
-+                type = NULL;
- 
-                 LIST_PREPEND(mount_point, *head, m);
-         }
-@@ -371,8 +374,12 @@ static int mount_points_list_umount(MountPoint **head, bool *changed, bool log_e
-                 /* If we are in a container, don't attempt to
-                    read-only mount anything as that brings no real
-                    benefits, but might confuse the host, as we remount
--                   the superblock here, not the bind mound. */
--                if (detect_container(NULL) <= 0)  {
-+                   the superblock here, not the bind mount.
-+                   If the filesystem is a network fs, also skip the
-+                   remount.  It brings no value (we cannot leave
-+                   a "dirty fs") and could hang if the network is down.  */
-+                if (detect_container(NULL) <= 0 &&
-+                    !fstype_is_network(m->type)) {
-                         _cleanup_free_ char *options = NULL;
-                         /* MS_REMOUNT requires that the data parameter
-                          * should be the same from the original mount
diff --git a/SOURCES/0504-udev-ignore-SIGCHLD-from-unexpected-processes-130653.patch b/SOURCES/0504-udev-ignore-SIGCHLD-from-unexpected-processes-130653.patch
new file mode 100644
index 0000000..9c73445
--- /dev/null
+++ b/SOURCES/0504-udev-ignore-SIGCHLD-from-unexpected-processes-130653.patch
@@ -0,0 +1,30 @@
+From 461c10112d74ab223226554f2bb73aabaef43c9a Mon Sep 17 00:00:00 2001
+From: Jan Synacek <jsynacek@redhat.com>
+Date: Tue, 15 Aug 2017 13:29:51 +0200
+Subject: [PATCH] udev: ignore SIGCHLD from unexpected processes (#1306539)
+
+RHEL-only
+
+Author: grzegorz.halat@motorolasolutions.com
+Resolves: #1306539
+---
+ src/udev/udev-event.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c
+index bc115f112..0ba079201 100644
+--- a/src/udev/udev-event.c
++++ b/src/udev/udev-event.c
+@@ -610,7 +610,11 @@ static int spawn_wait(struct udev_event *event,
+                                 event->sigterm = true;
+                                 break;
+                         case SIGCHLD:
+-                                if (waitpid(pid, &status, WNOHANG) < 0)
++                                if (pid != (pid_t) fdsi.ssi_pid) {
++                                        log_debug("expected SIGCHLD from '%s' ["PID_FMT"] received from unknown process ["PID_FMT"]. Ignoring", cmd, pid, fdsi.ssi_pid);
++                                        continue;
++                                }
++                                if (waitpid(pid, &status, WNOHANG) <= 0)
+                                         break;
+                                 if (WIFEXITED(status)) {
+                                         log_debug("'%s' ["PID_FMT"] exit with return code %i", cmd, pid, WEXITSTATUS(status));
diff --git a/SOURCES/0505-compile-with-Werror.patch b/SOURCES/0505-compile-with-Werror.patch
new file mode 100644
index 0000000..2ba63a3
--- /dev/null
+++ b/SOURCES/0505-compile-with-Werror.patch
@@ -0,0 +1,83 @@
+From 382877acc6c029e59e359a076d203ca03b4b9e9e Mon Sep 17 00:00:00 2001
+From: Jan Synacek <jsynacek@redhat.com>
+Date: Wed, 3 May 2017 14:34:36 +0200
+Subject: [PATCH] compile with -Werror
+
+The maybe-uninitialized flag has to be disabled, because gcc on RHEL7
+reports tons of obvious false-positive warnings when variables are
+wrapped with _cleanup_.
+
+Also, LTO is better to be disabled. According to gcc folks, it makes
+debugging really hard and is not really recommended on RHEL7. Plus it
+makes the compilation fail with
+
+In function '__ppoll_alias',
+    inlined from 'bus_poll' at src/libsystemd/sd-bus/sd-bus.c:2822:11:
+/usr/include/bits/poll2.h:71:9: warning: call to '__ppoll_chk_warn' declared with attribute warning: ppoll called with fds buffer too small file nfds entries
+  return __ppoll_chk (__fds, __nfds, __timeout, __ss, __bos (__fds));
+
+That is also a gcc bug, already fixed in the gcc upstream
+(https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61886).
+
+Resolves: #1447937
+---
+ configure.ac               | 12 ++----------
+ src/core/main.c            |  1 -
+ src/login/logind-session.c |  2 +-
+ 3 files changed, 3 insertions(+), 12 deletions(-)
+
+diff --git a/configure.ac b/configure.ac
+index 2734368dc..def9fe5ce 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -187,7 +187,8 @@ CC_CHECK_FLAGS_APPEND([with_cflags], [CFLAGS], [\
+         -Wno-unused-parameter \
+         -Wno-missing-field-initializers \
+         -Wno-unused-result \
+-        -Werror=overflow \
++        -Werror \
++        -Wno-error=maybe-uninitialized \
+         -Wdate-time \
+         -Wnested-externs \
+         -ffast-math \
+@@ -208,15 +209,6 @@ AS_CASE([$CC], [*clang*],
+                -Wno-gnu-variable-sized-type-not-at-end \
+         ])])
+ 
+-AC_ARG_ENABLE([lto], AS_HELP_STRING([--disable-lto], [Disable Link time optimization]))
+-AS_IF([test "x$enable_lto" != "xno"], [
+-AS_CASE([$CFLAGS], [*-O[[12345\ ]]*], [
+-         CC_CHECK_FLAGS_APPEND([with_cflags], [CFLAGS], [-flto -ffat-lto-objects])
+-         CC_CHECK_FLAGS_APPEND([with_ldflags], [LDFLAGS],[-Wl,-fuse-ld=gold])
+-         ],
+-[AC_MSG_RESULT([skipping -flto, optimization not enabled])])
+-])
+-
+ AC_SUBST([OUR_CFLAGS], "$with_cflags $sanitizer_cflags")
+ 
+ AS_CASE([$CFLAGS], [*-O[[12345sz\ ]]*],
+diff --git a/src/core/main.c b/src/core/main.c
+index 50c9714f7..37e3ea0ce 100644
+--- a/src/core/main.c
++++ b/src/core/main.c
+@@ -1205,7 +1205,6 @@ static int status_welcome(void) {
+ 
+ static int write_container_id(void) {
+         const char *c;
+-        int r;
+ 
+         c = getenv("container");
+         if (isempty(c))
+diff --git a/src/login/logind-session.c b/src/login/logind-session.c
+index 4575a029f..daf875a7d 100644
+--- a/src/login/logind-session.c
++++ b/src/login/logind-session.c
+@@ -183,7 +183,7 @@ int session_save(Session *s) {
+                 "STATE=%s\n"
+                 "REMOTE=%i\n"
+                 "STOPPING=%i\n",
+-                (unsigned long) s->user->uid,
++                s->user->uid,
+                 s->user->name,
+                 session_is_active(s),
+                 session_state_to_string(session_get_state(s)),
diff --git a/SOURCES/0505-shutdown-fix-incorrect-fscanf-result-check-6806.patch b/SOURCES/0505-shutdown-fix-incorrect-fscanf-result-check-6806.patch
deleted file mode 100644
index eea0ee6..0000000
--- a/SOURCES/0505-shutdown-fix-incorrect-fscanf-result-check-6806.patch
+++ /dev/null
@@ -1,29 +0,0 @@
-From b0630cdbb8f16850f6a62447328df77130059efc Mon Sep 17 00:00:00 2001
-From: Lennart Poettering <lennart@poettering.net>
-Date: Wed, 13 Sep 2017 10:08:37 +0200
-Subject: [PATCH] shutdown: fix incorrect fscanf() result check (#6806)
-
-A correction for 090e3c9796ef6468d4f396610804d62f6ffd797f.
-
-Fixes: #6796
-
-(cherry-picked from: 3d4ec01269244c2d35a781abf748ea9ba57666e2)
-
-Related: #1312002
----
- src/core/umount.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/src/core/umount.c b/src/core/umount.c
-index 6e8ccc794..3eec0d459 100644
---- a/src/core/umount.c
-+++ b/src/core/umount.c
-@@ -93,7 +93,7 @@ static int mount_points_list_get(MountPoint **head) {
-                            "%ms"        /* (11) mount options */
-                            "%*[^\n]",   /* some rubbish at the end */
-                            &path, &type, &options);
--                if (k != 2) {
-+                if (k != 3) {
-                         if (k == EOF)
-                                 break;
- 
diff --git a/SOURCES/0506-manager-fix-connecting-to-bus-when-dbus-is-actually-.patch b/SOURCES/0506-manager-fix-connecting-to-bus-when-dbus-is-actually-.patch
deleted file mode 100644
index b69a75d..0000000
--- a/SOURCES/0506-manager-fix-connecting-to-bus-when-dbus-is-actually-.patch
+++ /dev/null
@@ -1,34 +0,0 @@
-From f4cfab4baa2365ca1484b7e43a9da434aa102153 Mon Sep 17 00:00:00 2001
-From: Michal Sekletar <msekletar@users.noreply.github.com>
-Date: Wed, 1 Nov 2017 02:25:48 -0700
-Subject: [PATCH] manager: fix connecting to bus when dbus is actually around
- (#7205)
-
-manager_connect_bus() is called *before* manager_coldplug(). As a last
-thing in service_coldplug() we set service state to
-s->deserialized_state, and thus before we do that all services are
-inactive and try_connect always evaluates to false. To fix that we must
-look at deserialized state instead of current unit state.
-
-Fixes #7146
-
-(cherry picked from commit 41dfa61d35c51a584437481d20541d5c3ccfa93d)
-
-Related: #1465737
----
- src/core/manager.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/src/core/manager.c b/src/core/manager.c
-index 041fac46b..47b09e1e9 100644
---- a/src/core/manager.c
-+++ b/src/core/manager.c
-@@ -809,7 +809,7 @@ static int manager_connect_bus(Manager *m, bool reexecuting) {
-         u = manager_get_unit(m, SPECIAL_DBUS_SERVICE);
- 
-         try_bus_connect =
--                (u && UNIT_IS_ACTIVE_OR_RELOADING(unit_active_state(u))) &&
-+                (u && SERVICE(u)->deserialized_state == SERVICE_RUNNING) &&
-                 (reexecuting ||
-                 (m->running_as == SYSTEMD_USER && getenv("DBUS_SESSION_BUS_ADDRESS")));
- 
diff --git a/SOURCES/0506-myhostname-don-t-return-any-ipv6-entries-when-ipv6-i.patch b/SOURCES/0506-myhostname-don-t-return-any-ipv6-entries-when-ipv6-i.patch
new file mode 100644
index 0000000..683a3cc
--- /dev/null
+++ b/SOURCES/0506-myhostname-don-t-return-any-ipv6-entries-when-ipv6-i.patch
@@ -0,0 +1,42 @@
+From 624fcda36dd376707e3af088b592fe3764b99acf Mon Sep 17 00:00:00 2001
+From: Jan Synacek <jsynacek@redhat.com>
+Date: Tue, 2 May 2017 14:34:17 +0200
+Subject: [PATCH] myhostname: don't return any ipv6 entries when ipv6 is
+ disabled
+
+This commit amends the rhel-only 6e5117b83af5998359916f276a9b32f755c0e6f4.
+
+Resolves: #1444824
+---
+ src/nss-myhostname/nss-myhostname.c | 10 ++++------
+ 1 file changed, 4 insertions(+), 6 deletions(-)
+
+diff --git a/src/nss-myhostname/nss-myhostname.c b/src/nss-myhostname/nss-myhostname.c
+index e197cc752..144c83171 100644
+--- a/src/nss-myhostname/nss-myhostname.c
++++ b/src/nss-myhostname/nss-myhostname.c
+@@ -351,6 +351,8 @@ enum nss_status _nss_myhostname_gethostbyname3_r(
+                 *h_errnop = NO_DATA;
+                 return NSS_STATUS_UNAVAIL;
+         }
++        if (af == AF_INET6 && !socket_ipv6_is_supported())
++                return NSS_STATUS_UNAVAIL;
+ 
+         if (is_localhost(name)) {
+                 canonical = "localhost";
+@@ -381,13 +383,9 @@ enum nss_status _nss_myhostname_gethostbyname3_r(
+                         return NSS_STATUS_NOTFOUND;
+                 }
+ 
+-                if (af == AF_INET6 && !socket_ipv6_is_supported()) {
++                n_addresses = local_addresses(NULL, 0, af, &addresses);
++                if (n_addresses < 0)
+                         n_addresses = 0;
+-                } else {
+-                        n_addresses = local_addresses(NULL, 0, af, &addresses);
+-                        if (n_addresses < 0)
+-                                n_addresses = 0;
+-                }
+ 
+                 canonical = hn;
+                 additional = n_addresses <= 0 && af == AF_INET6 ? "localhost" : NULL;
diff --git a/SOURCES/0507-automount-ack-automount-requests-even-when-already-m.patch b/SOURCES/0507-automount-ack-automount-requests-even-when-already-m.patch
deleted file mode 100644
index 2ed105b..0000000
--- a/SOURCES/0507-automount-ack-automount-requests-even-when-already-m.patch
+++ /dev/null
@@ -1,82 +0,0 @@
-From 164bd929f1c85026f21ed493d11d3b4d1b94421d Mon Sep 17 00:00:00 2001
-From: Jan Synacek <jsynacek@redhat.com>
-Date: Wed, 17 Jan 2018 09:13:24 +0100
-Subject: [PATCH] automount: ack automount requests even when already mounted
-
-If a process accesses an autofs filesystem while systemd is in the
-middle of starting the mount unit on top of it, it is possible for the
-autofs_ptype_missing_direct request from the kernel to be received after
-the mount unit has been fully started:
-
-  systemd forks and execs mount             ...
-            ...                     access autofs, blocks
-  mount exits                               ...
-  systemd receives SIGCHLD                  ...
-            ...                     kernel sends request
-  systemd receives request                  ...
-
-systemd needs to respond to this request, otherwise the kernel will
-continue to block access to the mount point.
-
-(cherry picked from commit e7d54bf58789545a9eb0b3964233defa0b007318)
-
-Resolves: #1535135
----
- src/core/automount.c | 28 ++++++++++++++++------------
- 1 file changed, 16 insertions(+), 12 deletions(-)
-
-diff --git a/src/core/automount.c b/src/core/automount.c
-index 4e066613d..9e05963e9 100644
---- a/src/core/automount.c
-+++ b/src/core/automount.c
-@@ -692,7 +692,7 @@ static int automount_start_expire(Automount *a) {
-                         automount_dispatch_expire, a);
- }
- 
--static void automount_enter_runnning(Automount *a) {
-+static void automount_enter_running(Automount *a) {
-         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-         struct stat st;
-         int r;
-@@ -718,18 +718,22 @@ static void automount_enter_runnning(Automount *a) {
-                 goto fail;
-         }
- 
--        if (!S_ISDIR(st.st_mode) || st.st_dev != a->dev_id)
-+        /* The mount unit may have been explicitly started before we got the
-+         * autofs request. Ack it to unblock anything waiting on the mount point. */
-+        if (!S_ISDIR(st.st_mode) || st.st_dev != a->dev_id) {
-                 log_unit_info(UNIT(a)->id,
-                               "%s's automount point already active?", UNIT(a)->id);
--        else {
--                r = manager_add_job(UNIT(a)->manager, JOB_START, UNIT_TRIGGER(UNIT(a)),
--                                    JOB_REPLACE, true, &error, NULL);
--                if (r < 0) {
--                        log_unit_warning(UNIT(a)->id,
--                                         "%s failed to queue mount startup job: %s",
--                                         UNIT(a)->id, bus_error_message(&error, r));
--                        goto fail;
--                }
-+                automount_send_ready(a, a->tokens, 0);
-+                return;
-+        }
-+
-+        r = manager_add_job(UNIT(a)->manager, JOB_START, UNIT_TRIGGER(UNIT(a)),
-+                        JOB_REPLACE, true, &error, NULL);
-+        if (r < 0) {
-+                log_unit_warning(UNIT(a)->id,
-+                                "%s failed to queue mount startup job: %s",
-+                                UNIT(a)->id, bus_error_message(&error, r));
-+                goto fail;
-         }
- 
-         r = automount_start_expire(a);
-@@ -953,7 +957,7 @@ static int automount_dispatch_io(sd_event_source *s, int fd, uint32_t events, vo
-                         goto fail;
-                 }
- 
--                automount_enter_runnning(a);
-+                automount_enter_running(a);
-                 break;
- 
-         case autofs_ptype_expire_direct:
diff --git a/SOURCES/0507-core-execute-fix-fork-fail-handling-in-exec_spawn.patch b/SOURCES/0507-core-execute-fix-fork-fail-handling-in-exec_spawn.patch
new file mode 100644
index 0000000..2574d5d
--- /dev/null
+++ b/SOURCES/0507-core-execute-fix-fork-fail-handling-in-exec_spawn.patch
@@ -0,0 +1,30 @@
+From 03118775f6a9bf505a65dd0b86a6d2de2e3493a3 Mon Sep 17 00:00:00 2001
+From: lc85446 <lc85446@alibaba-inc.com>
+Date: Thu, 26 Nov 2015 11:46:40 +0800
+Subject: [PATCH] core:execute: fix fork() fail handling in exec_spawn()
+
+If pid < 0 after fork(), 0 is always returned because r =
+exec_context_load_environment() has exited successfully.
+
+This will make the caller of exec_spawn() not able to handle
+the fork() error case and make systemd abort assert() possibly.
+
+Cherry-picked from: 74129a127676e4f0edac0db4296c103e76ec6694
+Resolves: #1437114
+---
+ src/core/execute.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/core/execute.c b/src/core/execute.c
+index 4265b9c34..e68276973 100644
+--- a/src/core/execute.c
++++ b/src/core/execute.c
+@@ -1977,7 +1977,7 @@ int exec_spawn(ExecCommand *command,
+                         NULL);
+         pid = fork();
+         if (pid < 0)
+-                return log_unit_error_errno(params->unit_id, r, "Failed to fork: %m");
++                return log_unit_error_errno(params->unit_id, errno, "Failed to fork: %m");
+ 
+         if (pid == 0) {
+                 int exit_status;
diff --git a/SOURCES/0508-fix-compilation-after-commit-382877acc6c029e59e359a0.patch b/SOURCES/0508-fix-compilation-after-commit-382877acc6c029e59e359a0.patch
new file mode 100644
index 0000000..1f546b2
--- /dev/null
+++ b/SOURCES/0508-fix-compilation-after-commit-382877acc6c029e59e359a0.patch
@@ -0,0 +1,26 @@
+From 4d5e724a78803ed18033f04e7ffec6c8ea3bc922 Mon Sep 17 00:00:00 2001
+From: Jan Synacek <jsynacek@redhat.com>
+Date: Thu, 7 Sep 2017 14:37:06 +0200
+Subject: [PATCH] fix compilation after commit
+ 382877acc6c029e59e359a076d203ca03b4b9e9e
+
+It turns out that explicit #warning macros work as explicit errors with -Werror.
+
+Related: #1447937
+---
+ configure.ac | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/configure.ac b/configure.ac
+index def9fe5ce..ee147e28e 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -188,7 +188,7 @@ CC_CHECK_FLAGS_APPEND([with_cflags], [CFLAGS], [\
+         -Wno-missing-field-initializers \
+         -Wno-unused-result \
+         -Werror \
+-        -Wno-error=maybe-uninitialized \
++        -Wno-error=maybe-uninitialized -Wno-error=cpp \
+         -Wdate-time \
+         -Wnested-externs \
+         -ffast-math \
diff --git a/SOURCES/0508-shared-cgroup-utils-_CGROUP_CONTROLLER_MASK_ALL-does.patch b/SOURCES/0508-shared-cgroup-utils-_CGROUP_CONTROLLER_MASK_ALL-does.patch
deleted file mode 100644
index efa1b99..0000000
--- a/SOURCES/0508-shared-cgroup-utils-_CGROUP_CONTROLLER_MASK_ALL-does.patch
+++ /dev/null
@@ -1,28 +0,0 @@
-From 839a1935c5433fe973008f231aeb247df0344eca Mon Sep 17 00:00:00 2001
-From: Lukas Nykryn <lnykryn@redhat.com>
-Date: Tue, 9 Jan 2018 12:59:19 +0100
-Subject: [PATCH] shared/cgroup-utils: _CGROUP_CONTROLLER_MASK_ALL does not
- cover CGROUP_PIDS
-
-7d44d0d43465892d4753ff50592588f49d56cf95 added a CGROUP_PIDS but
-did not bump _CGROUP_CONTROLLER_MASK_ALL.
-
-RHEL-only
-Resolves: #1532586
----
- src/shared/cgroup-util.h | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/src/shared/cgroup-util.h b/src/shared/cgroup-util.h
-index 31bd8d311..e76cd334d 100644
---- a/src/shared/cgroup-util.h
-+++ b/src/shared/cgroup-util.h
-@@ -36,7 +36,7 @@ typedef enum CGroupControllerMask {
-         CGROUP_MEMORY = 8,
-         CGROUP_DEVICE = 16,
-         CGROUP_PIDS = 32,
--        _CGROUP_CONTROLLER_MASK_ALL = 31
-+        _CGROUP_CONTROLLER_MASK_ALL = 63
- } CGroupControllerMask;
- 
- /*
diff --git a/SOURCES/0509-Redefine-32bit-time_t-format-to-signed.patch b/SOURCES/0509-Redefine-32bit-time_t-format-to-signed.patch
new file mode 100644
index 0000000..23e502c
--- /dev/null
+++ b/SOURCES/0509-Redefine-32bit-time_t-format-to-signed.patch
@@ -0,0 +1,37 @@
+From 10a1adc237ada061f557a7ae422456aa7d8c2c05 Mon Sep 17 00:00:00 2001
+From: Jan Synacek <jsynacek@redhat.com>
+Date: Thu, 7 Sep 2017 14:41:09 +0200
+Subject: [PATCH] Redefine 32bit time_t format to signed
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+It seems that it is signed both on i386 and arm.
+
+Avoids a stupid gcc warning on arm:
+
+src/udev/udevadm-monitor.c: In function ‘print_device’:
+src/udev/udevadm-monitor.c:44:16: warning: format ‘%u’ expects argument of type ‘unsigned int’, but argument 3 has type ‘__time_t {aka long int}’ [-Wformat=]
+         printf("%-6s[%"PRI_TIME".%06ld] %-8s %s (%s)\n",
+                ^
+
+(cherry picked from commit 6307c39b94344b901c1d6e0df7ee58644a8809bf)
+
+Related: #1447937
+---
+ src/shared/util.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/shared/util.h b/src/shared/util.h
+index f1b6c348f..80ad18c0a 100644
+--- a/src/shared/util.h
++++ b/src/shared/util.h
+@@ -72,7 +72,7 @@
+ #if SIZEOF_TIME_T == 8
+ #  define PRI_TIME PRIi64
+ #elif SIZEOF_TIME_T == 4
+-#  define PRI_TIME PRIu32
++#  define PRI_TIME "li"
+ #else
+ #  error Unknown time_t size
+ #endif
diff --git a/SOURCES/0509-core-execute-fix-fork-fail-handling-in-exec_spawn.patch b/SOURCES/0509-core-execute-fix-fork-fail-handling-in-exec_spawn.patch
deleted file mode 100644
index 55607c8..0000000
--- a/SOURCES/0509-core-execute-fix-fork-fail-handling-in-exec_spawn.patch
+++ /dev/null
@@ -1,30 +0,0 @@
-From 7ebf4a0faffecb3a0c8abe8bea47502044038d66 Mon Sep 17 00:00:00 2001
-From: lc85446 <lc85446@alibaba-inc.com>
-Date: Thu, 26 Nov 2015 11:46:40 +0800
-Subject: [PATCH] core:execute: fix fork() fail handling in exec_spawn()
-
-If pid < 0 after fork(), 0 is always returned because r =
-exec_context_load_environment() has exited successfully.
-
-This will make the caller of exec_spawn() not able to handle
-the fork() error case and make systemd abort assert() possibly.
-
-Cherry-picked from: 74129a127676e4f0edac0db4296c103e76ec6694
-Resolves: #1437114
----
- src/core/execute.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/src/core/execute.c b/src/core/execute.c
-index 4265b9c34..e68276973 100644
---- a/src/core/execute.c
-+++ b/src/core/execute.c
-@@ -1977,7 +1977,7 @@ int exec_spawn(ExecCommand *command,
-                         NULL);
-         pid = fork();
-         if (pid < 0)
--                return log_unit_error_errno(params->unit_id, r, "Failed to fork: %m");
-+                return log_unit_error_errno(params->unit_id, errno, "Failed to fork: %m");
- 
-         if (pid == 0) {
-                 int exit_status;
diff --git a/SOURCES/0510-journal-remove-error-check-that-never-happens.patch b/SOURCES/0510-journal-remove-error-check-that-never-happens.patch
deleted file mode 100644
index fb5110a..0000000
--- a/SOURCES/0510-journal-remove-error-check-that-never-happens.patch
+++ /dev/null
@@ -1,53 +0,0 @@
-From cc8cc45e4b7799ac1dad7701de2df3db4fbb790c Mon Sep 17 00:00:00 2001
-From: Thomas Hindoe Paaboel Andersen <phomes@gmail.com>
-Date: Fri, 14 Aug 2015 23:40:27 +0200
-Subject: [PATCH] journal: remove error check that never happens
-
-remove_directory will always return 0 so this can never happen.
-Besides that, d->path and d are freed so we would end up with
-a null pointer dereference anyway.
-
-(cherry picked from commit b2b46f91dbb71676cb981907c68521e4b1e80af1)
-
-Related: #1465759
----
- src/journal/sd-journal.c | 12 +++---------
- 1 file changed, 3 insertions(+), 9 deletions(-)
-
-diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c
-index 72f312b67..3749f9e89 100644
---- a/src/journal/sd-journal.c
-+++ b/src/journal/sd-journal.c
-@@ -1487,7 +1487,7 @@ static int add_root_directory(sd_journal *j, const char *p) {
-         return 0;
- }
- 
--static int remove_directory(sd_journal *j, Directory *d) {
-+static void remove_directory(sd_journal *j, Directory *d) {
-         assert(j);
- 
-         if (d->wd > 0) {
-@@ -1506,8 +1506,6 @@ static int remove_directory(sd_journal *j, Directory *d) {
- 
-         free(d->path);
-         free(d);
--
--        return 0;
- }
- 
- static int add_search_paths(sd_journal *j) {
-@@ -2145,12 +2143,8 @@ static void process_inotify_event(sd_journal *j, struct inotify_event *e) {
- 
-                         /* Event for a subdirectory */
- 
--                        if (e->mask & (IN_DELETE_SELF|IN_MOVE_SELF|IN_UNMOUNT)) {
--                                r = remove_directory(j, d);
--                                if (r < 0)
--                                        log_debug_errno(r, "Failed to remove directory %s: %m", d->path);
--                        }
--
-+                        if (e->mask & (IN_DELETE_SELF|IN_MOVE_SELF|IN_UNMOUNT))
-+                                remove_directory(j, d);
- 
-                 } else if (d->is_root && (e->mask & IN_ISDIR) && e->len > 0 && sd_id128_from_string(e->name, &id) >= 0) {
- 
diff --git a/SOURCES/0510-sd-bus-bus-kernel.c-fix-format-errors-on-ppc64le.patch b/SOURCES/0510-sd-bus-bus-kernel.c-fix-format-errors-on-ppc64le.patch
new file mode 100644
index 0000000..360bd21
--- /dev/null
+++ b/SOURCES/0510-sd-bus-bus-kernel.c-fix-format-errors-on-ppc64le.patch
@@ -0,0 +1,43 @@
+From b5b6f19445904feff90d6b2f9651ba51ef405144 Mon Sep 17 00:00:00 2001
+From: Jan Synacek <jsynacek@redhat.com>
+Date: Thu, 7 Sep 2017 14:43:07 +0200
+Subject: [PATCH] sd-bus/bus-kernel.c: fix format errors on ppc64le
+
+RHEL-only
+
+Related: #1447937
+---
+ src/libsystemd/sd-bus/bus-kernel.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/src/libsystemd/sd-bus/bus-kernel.c b/src/libsystemd/sd-bus/bus-kernel.c
+index e90ee449d..d1c90858e 100644
+--- a/src/libsystemd/sd-bus/bus-kernel.c
++++ b/src/libsystemd/sd-bus/bus-kernel.c
+@@ -763,7 +763,7 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) {
+                         break;
+ 
+                 default:
+-                        log_debug("Got unknown field from kernel %llu", d->type);
++                        log_debug("Got unknown field from kernel %llu", (unsigned long long) d->type);
+                 }
+         }
+ 
+@@ -1244,7 +1244,7 @@ static int translate_id_change(
+         assert(k);
+         assert(d);
+ 
+-        sprintf(owner, ":1.%llu", d->id_change.id);
++        sprintf(owner, ":1.%llu", (unsigned long long) d->id_change.id);
+ 
+         return push_name_owner_changed(
+                         bus, owner,
+@@ -1317,7 +1317,7 @@ static int bus_kernel_translate_message(sd_bus *bus, struct kdbus_msg *k) {
+                                 return -EBADMSG;
+                         found = d;
+                 } else
+-                        log_debug("Got unknown field from kernel %llu", d->type);
++                        log_debug("Got unknown field from kernel %llu", (unsigned long long) d->type);
+         }
+ 
+         if (!found) {
diff --git a/SOURCES/0511-sd-journal-various-clean-ups-and-modernizations.patch b/SOURCES/0511-sd-journal-various-clean-ups-and-modernizations.patch
deleted file mode 100644
index caed1b5..0000000
--- a/SOURCES/0511-sd-journal-various-clean-ups-and-modernizations.patch
+++ /dev/null
@@ -1,503 +0,0 @@
-From ee0e6e54479f8ad1991e531bb1e931b696d67aaf Mon Sep 17 00:00:00 2001
-From: Lennart Poettering <lennart@poettering.net>
-Date: Mon, 2 Nov 2015 23:14:30 +0100
-Subject: [PATCH] sd-journal: various clean-ups and modernizations
-
-- Always print a debug log message about files and directories we cannot
-  open right when it happens instead of the caller, thus reducing the
-  number of places where we need to generate the debug message.
-
-- Always push the errors we encounter immediately into the error set,
-  when we run into them, instead of in the caller. Thus, we never forget
-  to push them in.
-
-- Use stack instead of heap memory where we can.
-
-- Make remove_file() void, since it cannot fail anyway and always
-  returned 0.
-
-- Make local machine check of journal directories explicit in a
-  function, to make things more readable.
-
-- Port to all directory listing loops FOREACH_DIRENT_ALL()
-
-- sd-daemon is library code, hence never log at higher log levels than
-  LOG_DEBUG.
-
-(cherry picked from commit d617408ecbe69db69aefddfcb10a6c054ea46ba0)
-
-Related: #1465759
----
- src/journal/sd-journal.c | 242 ++++++++++++++++++++++-------------------------
- 1 file changed, 111 insertions(+), 131 deletions(-)
-
-diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c
-index 3749f9e89..9895d9608 100644
---- a/src/journal/sd-journal.c
-+++ b/src/journal/sd-journal.c
-@@ -1171,6 +1171,8 @@ static bool file_has_type_prefix(const char *prefix, const char *filename) {
- }
- 
- static bool file_type_wanted(int flags, const char *filename) {
-+        assert(filename);
-+
-         if (!endswith(filename, ".journal") && !endswith(filename, ".journal~"))
-                 return false;
- 
-@@ -1195,7 +1197,7 @@ static bool file_type_wanted(int flags, const char *filename) {
- 
- static int add_any_file(sd_journal *j, const char *path) {
-         JournalFile *f = NULL;
--        int r;
-+        int r, k;
- 
-         assert(j);
-         assert(path);
-@@ -1204,20 +1206,23 @@ static int add_any_file(sd_journal *j, const char *path) {
-                 return 0;
- 
-         if (ordered_hashmap_size(j->files) >= JOURNAL_FILES_MAX) {
--                log_warning("Too many open journal files, not adding %s.", path);
--                return set_put_error(j, -ETOOMANYREFS);
-+                log_debug("Too many open journal files, not adding %s.", path);
-+                r = -ETOOMANYREFS;
-+                goto fail;
-         }
- 
-         r = journal_file_open(path, O_RDONLY, 0, false, false, NULL, j->mmap, NULL, &f);
--        if (r < 0)
--                return r;
-+        if (r < 0) {
-+                log_debug_errno(r, "Failed to open journal file %s: %m", path);
-+                goto fail;
-+        }
- 
-         /* journal_file_dump(f); */
- 
-         r = ordered_hashmap_put(j->files, f->path, f);
-         if (r < 0) {
-                 journal_file_close(f);
--                return r;
-+                goto fail;
-         }
- 
-         log_debug("File %s added.", f->path);
-@@ -1227,10 +1232,17 @@ static int add_any_file(sd_journal *j, const char *path) {
-         j->current_invalidate_counter ++;
- 
-         return 0;
-+
-+fail:
-+        k = set_put_error(j, r);
-+        if (k < 0)
-+                return k;
-+
-+        return r;
- }
- 
- static int add_file(sd_journal *j, const char *prefix, const char *filename) {
--        char *path = NULL;
-+        const char *path;
- 
-         assert(j);
-         assert(prefix);
-@@ -1250,24 +1262,20 @@ static int add_file(sd_journal *j, const char *prefix, const char *filename) {
-         return add_any_file(j, path);
- }
- 
--static int remove_file(sd_journal *j, const char *prefix, const char *filename) {
--        _cleanup_free_ char *path;
-+static void remove_file(sd_journal *j, const char *prefix, const char *filename) {
-+        const char *path;
-         JournalFile *f;
- 
-         assert(j);
-         assert(prefix);
-         assert(filename);
- 
--        path = strjoin(prefix, "/", filename, NULL);
--        if (!path)
--                return -ENOMEM;
--
-+        path = strjoina(prefix, "/", filename);
-         f = ordered_hashmap_get(j->files, path);
-         if (!f)
--                return 0;
-+                return;
- 
-         remove_file_real(j, f);
--        return 0;
- }
- 
- static void remove_file_real(sd_journal *j, JournalFile *f) {
-@@ -1296,12 +1304,27 @@ static void remove_file_real(sd_journal *j, JournalFile *f) {
-         j->current_invalidate_counter ++;
- }
- 
-+static int dirname_is_machine_id(const char *fn) {
-+        sd_id128_t id, machine;
-+        int r;
-+
-+        r = sd_id128_get_machine(&machine);
-+        if (r < 0)
-+                return r;
-+
-+        r = sd_id128_from_string(fn, &id);
-+        if (r < 0)
-+                return r;
-+
-+        return sd_id128_equal(id, machine);
-+}
-+
- static int add_directory(sd_journal *j, const char *prefix, const char *dirname) {
-         _cleanup_free_ char *path = NULL;
--        int r;
-         _cleanup_closedir_ DIR *d = NULL;
--        sd_id128_t id, mid;
-+        struct dirent *de = NULL;
-         Directory *m;
-+        int r, k;
- 
-         assert(j);
-         assert(prefix);
-@@ -1310,35 +1333,36 @@ static int add_directory(sd_journal *j, const char *prefix, const char *dirname)
-         log_debug("Considering %s/%s.", prefix, dirname);
- 
-         if ((j->flags & SD_JOURNAL_LOCAL_ONLY) &&
--            (sd_id128_from_string(dirname, &id) < 0 ||
--             sd_id128_get_machine(&mid) < 0 ||
--             !(sd_id128_equal(id, mid) || path_startswith(prefix, "/run"))))
-+            !(dirname_is_machine_id(dirname) > 0 || path_startswith(prefix, "/run")))
-             return 0;
- 
-         path = strjoin(prefix, "/", dirname, NULL);
--        if (!path)
--                return -ENOMEM;
-+        if (!path) {
-+                r = -ENOMEM;
-+                goto fail;
-+        }
- 
-         d = opendir(path);
-         if (!d) {
--                log_debug_errno(errno, "Failed to open %s: %m", path);
--                if (errno == ENOENT)
--                        return 0;
--                return -errno;
-+                r = log_debug_errno(errno, "Failed to open directory %s: %m", path);
-+                goto fail;
-         }
- 
-         m = hashmap_get(j->directories_by_path, path);
-         if (!m) {
-                 m = new0(Directory, 1);
--                if (!m)
--                        return -ENOMEM;
-+                if (!m) {
-+                        r = -ENOMEM;
-+                        goto fail;
-+                }
- 
-                 m->is_root = false;
-                 m->path = path;
- 
-                 if (hashmap_put(j->directories_by_path, m->path, m) < 0) {
-                         free(m);
--                        return -ENOMEM;
-+                        r = -ENOMEM;
-+                        goto fail;
-                 }
- 
-                 path = NULL; /* avoid freeing in cleanup */
-@@ -1360,41 +1384,30 @@ static int add_directory(sd_journal *j, const char *prefix, const char *dirname)
-                         inotify_rm_watch(j->inotify_fd, m->wd);
-         }
- 
--        for (;;) {
--                struct dirent *de;
--
--                errno = 0;
--                de = readdir(d);
--                if (!de && errno != 0) {
--                        r = -errno;
--                        log_debug_errno(errno, "Failed to read directory %s: %m", m->path);
--                        return r;
--                }
--                if (!de)
--                        break;
-+        FOREACH_DIRENT_ALL(de, d, return log_debug_errno(errno, "Failed to read directory %s: %m", m->path)) {
- 
-                 if (dirent_is_file_with_suffix(de, ".journal") ||
--                    dirent_is_file_with_suffix(de, ".journal~")) {
--                        r = add_file(j, m->path, de->d_name);
--                        if (r < 0) {
--                                log_debug_errno(r, "Failed to add file %s/%s: %m",
--                                                m->path, de->d_name);
--                                r = set_put_error(j, r);
--                                if (r < 0)
--                                        return r;
--                        }
--                }
-+                    dirent_is_file_with_suffix(de, ".journal~"))
-+                        (void) add_file(j, m->path, de->d_name);
-         }
- 
-         check_network(j, dirfd(d));
- 
-         return 0;
-+
-+fail:
-+        k = set_put_error(j, r);
-+        if (k < 0)
-+                return k;
-+
-+        return r;
- }
- 
--static int add_root_directory(sd_journal *j, const char *p) {
-+static int add_root_directory(sd_journal *j, const char *p, bool missing_ok) {
-         _cleanup_closedir_ DIR *d = NULL;
-+        struct dirent *de;
-         Directory *m;
--        int r;
-+        int r, k;
- 
-         assert(j);
-         assert(p);
-@@ -1407,26 +1420,35 @@ static int add_root_directory(sd_journal *j, const char *p) {
-                 p = strjoina(j->prefix, p);
- 
-         d = opendir(p);
--        if (!d)
--                return -errno;
-+        if (!d) {
-+                if (errno == ENOENT && missing_ok)
-+                        return 0;
-+
-+                r = log_debug_errno(errno, "Failed to open root directory %s: %m", p);
-+                goto fail;
-+        }
- 
-         m = hashmap_get(j->directories_by_path, p);
-         if (!m) {
-                 m = new0(Directory, 1);
--                if (!m)
--                        return -ENOMEM;
-+                if (!m) {
-+                        r = -ENOMEM;
-+                        goto fail;
-+                }
- 
-                 m->is_root = true;
-                 m->path = strdup(p);
-                 if (!m->path) {
-                         free(m);
--                        return -ENOMEM;
-+                        r = -ENOMEM;
-+                        goto fail;
-                 }
- 
-                 if (hashmap_put(j->directories_by_path, m->path, m) < 0) {
-                         free(m->path);
-                         free(m);
--                        return -ENOMEM;
-+                        r = -ENOMEM;
-+                        goto fail;
-                 }
- 
-                 j->current_invalidate_counter ++;
-@@ -1449,42 +1471,27 @@ static int add_root_directory(sd_journal *j, const char *p) {
-         if (j->no_new_files)
-                 return 0;
- 
--        for (;;) {
--                struct dirent *de;
-+        FOREACH_DIRENT_ALL(de, d, return log_debug_errno(errno, "Failed to read directory %s: %m", m->path)) {
-                 sd_id128_t id;
- 
--                errno = 0;
--                de = readdir(d);
--                if (!de && errno != 0) {
--                        r = -errno;
--                        log_debug_errno(errno, "Failed to read directory %s: %m", m->path);
--                        return r;
--                }
--                if (!de)
--                        break;
--
-                 if (dirent_is_file_with_suffix(de, ".journal") ||
--                    dirent_is_file_with_suffix(de, ".journal~")) {
--                        r = add_file(j, m->path, de->d_name);
--                        if (r < 0) {
--                                log_debug_errno(r, "Failed to add file %s/%s: %m",
--                                                m->path, de->d_name);
--                                r = set_put_error(j, r);
--                                if (r < 0)
--                                        return r;
--                        }
--                } else if ((de->d_type == DT_DIR || de->d_type == DT_LNK || de->d_type == DT_UNKNOWN) &&
--                           sd_id128_from_string(de->d_name, &id) >= 0) {
--
--                        r = add_directory(j, m->path, de->d_name);
--                        if (r < 0)
--                                log_debug_errno(r, "Failed to add directory %s/%s: %m", m->path, de->d_name);
--                }
-+                    dirent_is_file_with_suffix(de, ".journal~"))
-+                        (void) add_file(j, m->path, de->d_name);
-+                else if (IN_SET(de->d_type, DT_DIR, DT_LNK, DT_UNKNOWN) &&
-+                         sd_id128_from_string(de->d_name, &id) >= 0)
-+                        (void) add_directory(j, m->path, de->d_name);
-         }
- 
-         check_network(j, dirfd(d));
- 
-         return 0;
-+
-+fail:
-+        k = set_put_error(j, r);
-+        if (k < 0)
-+                return k;
-+
-+        return r;
- }
- 
- static void remove_directory(sd_journal *j, Directory *d) {
-@@ -1509,8 +1516,8 @@ static void remove_directory(sd_journal *j, Directory *d) {
- }
- 
- static int add_search_paths(sd_journal *j) {
--        int r;
--        const char search_paths[] =
-+
-+        static const char search_paths[] =
-                 "/run/log/journal\0"
-                 "/var/log/journal\0";
-         const char *p;
-@@ -1520,14 +1527,8 @@ static int add_search_paths(sd_journal *j) {
-         /* We ignore most errors here, since the idea is to only open
-          * what's actually accessible, and ignore the rest. */
- 
--        NULSTR_FOREACH(p, search_paths) {
--                r = add_root_directory(j, p);
--                if (r < 0 && r != -ENOENT) {
--                        r = set_put_error(j, r);
--                        if (r < 0)
--                                return r;
--                }
--        }
-+        NULSTR_FOREACH(p, search_paths)
-+                (void) add_root_directory(j, p, true);
- 
-         return 0;
- }
-@@ -1551,17 +1552,14 @@ static int add_current_paths(sd_journal *j) {
-                 if (!dir)
-                         return -ENOMEM;
- 
--                r = add_root_directory(j, dir);
--                if (r < 0) {
--                        set_put_error(j, r);
-+                r = add_root_directory(j, dir, true);
-+                if (r < 0)
-                         return r;
--                }
-         }
- 
-         return 0;
- }
- 
--
- static int allocate_inotify(sd_journal *j) {
-         assert(j);
- 
-@@ -1689,11 +1687,9 @@ _public_ int sd_journal_open_directory(sd_journal **ret, const char *path, int f
-         if (!j)
-                 return -ENOMEM;
- 
--        r = add_root_directory(j, path);
--        if (r < 0) {
--                set_put_error(j, r);
-+        r = add_root_directory(j, path, false);
-+        if (r < 0)
-                 goto fail;
--        }
- 
-         *ret = j;
-         return 0;
-@@ -1718,10 +1714,8 @@ _public_ int sd_journal_open_files(sd_journal **ret, const char **paths, int fla
- 
-         STRV_FOREACH(path, paths) {
-                 r = add_any_file(j, *path);
--                if (r < 0) {
--                        log_error_errno(r, "Failed to open %s: %m", *path);
-+                if (r < 0)
-                         goto fail;
--                }
-         }
- 
-         j->no_new_files = true;
-@@ -2061,7 +2055,7 @@ _public_ int sd_journal_get_fd(sd_journal *j) {
-         if (j->no_new_files)
-                 r = add_current_paths(j);
-         else if (j->path)
--                r = add_root_directory(j, j->path);
-+                r = add_root_directory(j, j->path, true);
-         else
-                 r = add_search_paths(j);
-         if (r < 0)
-@@ -2108,7 +2102,6 @@ _public_ int sd_journal_get_timeout(sd_journal *j, uint64_t *timeout_usec) {
- 
- static void process_inotify_event(sd_journal *j, struct inotify_event *e) {
-         Directory *d;
--        int r;
- 
-         assert(j);
-         assert(e);
-@@ -2124,20 +2117,10 @@ static void process_inotify_event(sd_journal *j, struct inotify_event *e) {
- 
-                         /* Event for a journal file */
- 
--                        if (e->mask & (IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB)) {
--                                r = add_file(j, d->path, e->name);
--                                if (r < 0) {
--                                        log_debug_errno(r, "Failed to add file %s/%s: %m",
--                                                        d->path, e->name);
--                                        set_put_error(j, r);
--                                }
--
--                        } else if (e->mask & (IN_DELETE|IN_MOVED_FROM|IN_UNMOUNT)) {
--
--                                r = remove_file(j, d->path, e->name);
--                                if (r < 0)
--                                        log_debug_errno(r, "Failed to remove file %s/%s: %m", d->path, e->name);
--                        }
-+                        if (e->mask & (IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB))
-+                                (void) add_file(j, d->path, e->name);
-+                        else if (e->mask & (IN_DELETE|IN_MOVED_FROM|IN_UNMOUNT))
-+                                remove_file(j, d->path, e->name);
- 
-                 } else if (!d->is_root && e->len == 0) {
- 
-@@ -2150,11 +2133,8 @@ static void process_inotify_event(sd_journal *j, struct inotify_event *e) {
- 
-                         /* Event for root directory */
- 
--                        if (e->mask & (IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB)) {
--                                r = add_directory(j, d->path, e->name);
--                                if (r < 0)
--                                        log_debug_errno(r, "Failed to add directory %s/%s: %m", d->path, e->name);
--                        }
-+                        if (e->mask & (IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB))
-+                                (void) add_directory(j, d->path, e->name);
-                 }
- 
-                 return;
-@@ -2163,7 +2143,7 @@ static void process_inotify_event(sd_journal *j, struct inotify_event *e) {
-         if (e->mask & IN_IGNORED)
-                 return;
- 
--        log_warning("Unknown inotify event.");
-+        log_debug("Unknown inotify event.");
- }
- 
- static int determine_change(sd_journal *j) {
diff --git a/SOURCES/0511-tmpfiles-with-e-don-t-attempt-to-set-permissions-whe.patch b/SOURCES/0511-tmpfiles-with-e-don-t-attempt-to-set-permissions-whe.patch
new file mode 100644
index 0000000..be7b3bb
--- /dev/null
+++ b/SOURCES/0511-tmpfiles-with-e-don-t-attempt-to-set-permissions-whe.patch
@@ -0,0 +1,65 @@
+From 797dafce1bb9c3bb16da043f654391dc29075a1a Mon Sep 17 00:00:00 2001
+From: Michal Sekletar <msekleta@redhat.com>
+Date: Mon, 28 Aug 2017 17:33:24 +0200
+Subject: [PATCH] tmpfiles: with "e" don't attempt to set permissions when file
+ doesn't exist
+
+tmpfiles.d option "e" when run through systemd-tmpfiles --create should
+apply configured permissions (uid,gid) only to already existing
+files. When file doesn't exist we bail out with error. Instead we should
+silently ignore non-existing files.
+
+$ useradd test
+$ cat /etc/tmpfiles.d/foobar.conf
+e /tmp/test - test test 1d
+$ ls -l /tmp/test
+ls: cannot access '/tmp/test': No such file or directory
+
+Before:
+$ systemd-tmpfiles --create /etc/tmpfiles.d/foobar.conf
+Adjusting owner and mode for /tmp/test failed: No such file or directory
+$ echo $?
+1
+
+After:
+$ systemd-tmpfiles --create /etc/tmpfiles.d/foobar.conf
+$ echo $?
+0
+
+(cherry picked from commit 3caf791a1702c97b99d2647c9d465af404f2913d)
+
+Conflicts:
+	src/tmpfiles/tmpfiles.c
+
+Resolves: #1445732
+---
+ src/tmpfiles/tmpfiles.c | 16 ++++++++++++++--
+ 1 file changed, 14 insertions(+), 2 deletions(-)
+
+diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
+index df7676b57..ed35b8cf0 100644
+--- a/src/tmpfiles/tmpfiles.c
++++ b/src/tmpfiles/tmpfiles.c
+@@ -585,8 +585,20 @@ static int path_set_perms(Item *i, const char *path) {
+          * O_PATH. */
+ 
+         fd = open(path, O_RDONLY|O_NOFOLLOW|O_CLOEXEC|O_PATH|O_NOATIME);
+-        if (fd < 0)
+-                return log_error_errno(errno, "Adjusting owner and mode for %s failed: %m", path);
++        if (fd < 0) {
++                int level = LOG_ERR, r = -errno;
++
++                /* Option "e" operates only on existing objects. Do not
++                 * print errors about non-existent files or directories */
++                if (i->type == EMPTY_DIRECTORY && errno == ENOENT) {
++                        level = LOG_DEBUG;
++                        r = 0;
++                }
++
++                log_full_errno(level, errno, "Adjusting owner and mode for %s failed: %m", path);
++
++                return r;
++        }
+ 
+         if (fstatat(fd, "", &st, AT_EMPTY_PATH) < 0)
+                 return log_error_errno(errno, "Failed to fstat() file %s: %m", path);
diff --git a/SOURCES/0512-journalctl-continue-operation-even-if-we-run-into-an.patch b/SOURCES/0512-journalctl-continue-operation-even-if-we-run-into-an.patch
deleted file mode 100644
index 5560ea6..0000000
--- a/SOURCES/0512-journalctl-continue-operation-even-if-we-run-into-an.patch
+++ /dev/null
@@ -1,35 +0,0 @@
-From f5a2a7b3630d0ba9a25f8a81cdeaf5336b745e3e Mon Sep 17 00:00:00 2001
-From: Lennart Poettering <lennart@poettering.net>
-Date: Mon, 2 Nov 2015 23:13:01 +0100
-Subject: [PATCH] journalctl: continue operation, even if we run into an
- invalid file
-
-(cherry picked from commit 4f52b822b05c373f40fea1a41ae3ade5d5ff558e)
-
-Related: #1465759
----
- src/journal/journalctl.c | 7 ++-----
- 1 file changed, 2 insertions(+), 5 deletions(-)
-
-diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
-index c771cff8b..8c8379732 100644
---- a/src/journal/journalctl.c
-+++ b/src/journal/journalctl.c
-@@ -1804,15 +1804,12 @@ static int access_check(sd_journal *j) {
-         SET_FOREACH(code, j->errors, it) {
-                 int err;
- 
--                err = -PTR_TO_INT(code);
--                assert(err > 0);
-+                err = abs(PTR_TO_INT(code));
- 
-                 if (err == EACCES)
-                         continue;
- 
--                log_warning_errno(err, "Error was encountered while opening journal files: %m");
--                if (r == 0)
--                        r = -err;
-+                log_warning_errno(err, "An error was encountered while opening journal files, ignoring: %m");
-         }
- 
-         return r;
diff --git a/SOURCES/0512-units-introduce-getty-pre.target-6667.patch b/SOURCES/0512-units-introduce-getty-pre.target-6667.patch
new file mode 100644
index 0000000..3d298ba
--- /dev/null
+++ b/SOURCES/0512-units-introduce-getty-pre.target-6667.patch
@@ -0,0 +1,112 @@
+From d538b6082216f4867b4a50c8009abe2462aafbf4 Mon Sep 17 00:00:00 2001
+From: Michal Sekletar <msekletar@users.noreply.github.com>
+Date: Thu, 31 Aug 2017 11:20:14 +0200
+Subject: [PATCH] units: introduce getty-pre.target (#6667)
+
+This new target is a passive unit, hence it is supposed to be pulled in
+to the transaction by the service that wants to block login on the
+console (e.g. text version of initial-setup). Now both getty and
+serial-getty are ordered after this target.
+
+https://lists.freedesktop.org/archives/systemd-devel/2015-July/033754.html
+
+(cherry picked from commit 175902541852fb9207f6e532d8da48c9a102340c)
+
+Conflicts:
+	units/meson.build
+
+Resolves: #1173080
+---
+ Makefile.am                    |  1 +
+ man/systemd.special.xml        | 12 ++++++++++++
+ units/getty-pre.target         | 11 +++++++++++
+ units/getty@.service.m4        |  2 +-
+ units/serial-getty@.service.m4 |  2 +-
+ 5 files changed, 26 insertions(+), 2 deletions(-)
+ create mode 100644 units/getty-pre.target
+
+diff --git a/Makefile.am b/Makefile.am
+index e9ceac98a..7c58fd050 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -462,6 +462,7 @@ dist_systemunit_DATA = \
+ 	units/sysinit.target \
+ 	units/basic.target \
+ 	units/getty.target \
++	units/getty-pre.target \
+ 	units/halt.target \
+ 	units/kexec.target \
+ 	units/local-fs.target \
+diff --git a/man/systemd.special.xml b/man/systemd.special.xml
+index 553197d66..eb464f9f8 100644
+--- a/man/systemd.special.xml
++++ b/man/systemd.special.xml
+@@ -61,6 +61,7 @@
+     <filename>exit.target</filename>,
+     <filename>final.target</filename>,
+     <filename>getty.target</filename>,
++    <filename>getty-pre.target</filename>,
+     <filename>graphical.target</filename>,
+     <filename>halt.target</filename>,
+     <filename>hibernate.target</filename>,
+@@ -216,6 +217,17 @@
+           </para>
+         </listitem>
+       </varlistentry>
++      <varlistentry>
++        <term><filename>getty-pre.target</filename></term>
++        <listitem>
++          <para>A special passive target unit. Users of this target
++          are expected to pull it in the boot transaction via
++          a dependency (e.g. <varname>Wants=</varname>). Order your
++          unit before this unit if you want to make use of the console
++          just before <filename>getty</filename> is started.
++          </para>
++        </listitem>
++      </varlistentry>
+       <varlistentry>
+         <term><filename>graphical.target</filename></term>
+         <listitem>
+diff --git a/units/getty-pre.target b/units/getty-pre.target
+new file mode 100644
+index 000000000..f6c78b6c2
+--- /dev/null
++++ b/units/getty-pre.target
+@@ -0,0 +1,11 @@
++#  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=Login Prompts (Pre)
++Documentation=man:systemd.special(7) man:systemd-getty-generator(8)
++Documentation=http://0pointer.de/blog/projects/serial-console.html
+diff --git a/units/getty@.service.m4 b/units/getty@.service.m4
+index 46164ab9d..ad4bf2103 100644
+--- a/units/getty@.service.m4
++++ b/units/getty@.service.m4
+@@ -9,7 +9,7 @@
+ Description=Getty on %I
+ Documentation=man:agetty(8) man:systemd-getty-generator(8)
+ Documentation=http://0pointer.de/blog/projects/serial-console.html
+-After=systemd-user-sessions.service plymouth-quit-wait.service
++After=systemd-user-sessions.service plymouth-quit-wait.service getty-pre.target
+ m4_ifdef(`HAVE_SYSV_COMPAT',
+ After=rc-local.service
+ )m4_dnl
+diff --git a/units/serial-getty@.service.m4 b/units/serial-getty@.service.m4
+index 4522d0d2b..6802333f7 100644
+--- a/units/serial-getty@.service.m4
++++ b/units/serial-getty@.service.m4
+@@ -10,7 +10,7 @@ Description=Serial Getty on %I
+ Documentation=man:agetty(8) man:systemd-getty-generator(8)
+ Documentation=http://0pointer.de/blog/projects/serial-console.html
+ BindsTo=dev-%i.device
+-After=dev-%i.device systemd-user-sessions.service plymouth-quit-wait.service
++After=dev-%i.device systemd-user-sessions.service plymouth-quit-wait.service getty-pre.target
+ m4_ifdef(`HAVE_SYSV_COMPAT',
+ After=rc-local.service
+ )m4_dnl
diff --git a/SOURCES/0513-journalctl-when-we-fail-to-open-a-journal-file-print.patch b/SOURCES/0513-journalctl-when-we-fail-to-open-a-journal-file-print.patch
deleted file mode 100644
index 5833c08..0000000
--- a/SOURCES/0513-journalctl-when-we-fail-to-open-a-journal-file-print.patch
+++ /dev/null
@@ -1,204 +0,0 @@
-From 8a5944217f444929ba6a4124a4ee7fbd2c5a3fc3 Mon Sep 17 00:00:00 2001
-From: Lennart Poettering <lennart@poettering.net>
-Date: Mon, 2 Nov 2015 23:37:05 +0100
-Subject: [PATCH] journalctl: when we fail to open a journal file, print why
-
-When we enumerate journal files and encounter an invalid one, remember
-which this, and show it to the user.
-
-Note the possibly slightly surprising logic here: we store only one path
-per error code. This means we show all error kinds but not every actual
-error we encounter. This has the benefit of not requiring us to keep a
-potentially unbounded list of errors with their sources around, but can
-still provide a pretty complete overview on the errors we encountered.
-
-Fixes #1669.
-
-(cherry picked from commit 5768d2594940668506bb4cafa078f654cc20dc5a)
-
-Resolves: #1465759
----
- src/journal/journal-internal.h |  2 +-
- src/journal/journalctl.c       | 27 ++++++++++++++++++-----
- src/journal/sd-journal.c       | 49 ++++++++++++++++++++++++++++++++++--------
- 3 files changed, 63 insertions(+), 15 deletions(-)
-
-diff --git a/src/journal/journal-internal.h b/src/journal/journal-internal.h
-index 115d7776d..eb23ac28a 100644
---- a/src/journal/journal-internal.h
-+++ b/src/journal/journal-internal.h
-@@ -123,7 +123,7 @@ struct sd_journal {
-         Hashmap *directories_by_path;
-         Hashmap *directories_by_wd;
- 
--        Set *errors;
-+        Hashmap *errors;
- };
- 
- char *journal_make_match_string(sd_journal *j);
-diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
-index 8c8379732..0be70764e 100644
---- a/src/journal/journalctl.c
-+++ b/src/journal/journalctl.c
-@@ -1783,33 +1783,50 @@ static int access_check_var_log_journal(sd_journal *j) {
- static int access_check(sd_journal *j) {
-         Iterator it;
-         void *code;
-+        char *path;
-         int r = 0;
- 
-         assert(j);
- 
--        if (set_isempty(j->errors)) {
-+        if (hashmap_isempty(j->errors)) {
-                 if (ordered_hashmap_isempty(j->files))
-                         log_notice("No journal files were found.");
- 
-                 return 0;
-         }
- 
--        if (set_contains(j->errors, INT_TO_PTR(-EACCES))) {
-+        if (hashmap_contains(j->errors, INT_TO_PTR(-EACCES))) {
-                 (void) access_check_var_log_journal(j);
- 
-                 if (ordered_hashmap_isempty(j->files))
-                         r = log_error_errno(EACCES, "No journal files were opened due to insufficient permissions.");
-         }
- 
--        SET_FOREACH(code, j->errors, it) {
-+        HASHMAP_FOREACH_KEY(path, code, j->errors, it) {
-                 int err;
- 
-                 err = abs(PTR_TO_INT(code));
- 
--                if (err == EACCES)
-+                switch (err) {
-+                case EACCES:
-                         continue;
- 
--                log_warning_errno(err, "An error was encountered while opening journal files, ignoring: %m");
-+                case ENODATA:
-+                        log_warning_errno(err, "Journal file %s is truncated, ignoring file.", path);
-+                        break;
-+
-+                case EPROTONOSUPPORT:
-+                        log_warning_errno(err, "Journal file %s uses an unsupported feature, ignoring file.", path);
-+                        break;
-+
-+                case EBADMSG:
-+                        log_warning_errno(err, "Journal file %s corrupted, ignoring file.", path);
-+                        break;
-+
-+                default:
-+                        log_warning_errno(err, "An error was encountered while opening journal file %s, ignoring file.", path);
-+                        break;
-+                }
-         }
- 
-         return r;
-diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c
-index 9895d9608..14b65cfed 100644
---- a/src/journal/sd-journal.c
-+++ b/src/journal/sd-journal.c
-@@ -62,19 +62,46 @@ static bool journal_pid_changed(sd_journal *j) {
-         return j->original_pid != getpid();
- }
- 
--/* We return an error here only if we didn't manage to
--   memorize the real error. */
--static int set_put_error(sd_journal *j, int r) {
-+static int journal_put_error(sd_journal *j, int r, const char *path) {
-+        char *copy;
-         int k;
- 
-+        /* Memorize an error we encountered, and store which
-+         * file/directory it was generated from. Note that we store
-+         * only *one* path per error code, as the error code is the
-+         * key into the hashmap, and the path is the value. This means
-+         * we keep track only of all error kinds, but not of all error
-+         * locations. This has the benefit that the hashmap cannot
-+         * grow beyond bounds.
-+         *
-+         * We return an error here only if we didn't manage to
-+         * memorize the real error. */
-+
-         if (r >= 0)
-                 return r;
- 
--        k = set_ensure_allocated(&j->errors, NULL);
-+        k = hashmap_ensure_allocated(&j->errors, NULL);
-         if (k < 0)
-                 return k;
- 
--        return set_put(j->errors, INT_TO_PTR(r));
-+        if (path) {
-+                copy = strdup(path);
-+                if (!copy)
-+                        return -ENOMEM;
-+        } else
-+                copy = NULL;
-+
-+        k = hashmap_put(j->errors, INT_TO_PTR(r), copy);
-+        if (k < 0) {
-+                free(copy);
-+
-+                if (k == -EEXIST)
-+                        return 0;
-+
-+                return k;
-+        }
-+
-+        return 0;
- }
- 
- static void detach_location(sd_journal *j) {
-@@ -1234,7 +1261,7 @@ static int add_any_file(sd_journal *j, const char *path) {
-         return 0;
- 
- fail:
--        k = set_put_error(j, r);
-+        k = journal_put_error(j, r, path);
-         if (k < 0)
-                 return k;
- 
-@@ -1396,7 +1423,7 @@ static int add_directory(sd_journal *j, const char *prefix, const char *dirname)
-         return 0;
- 
- fail:
--        k = set_put_error(j, r);
-+        k = journal_put_error(j, r, path ?: dirname);
-         if (k < 0)
-                 return k;
- 
-@@ -1487,7 +1514,7 @@ static int add_root_directory(sd_journal *j, const char *p, bool missing_ok) {
-         return 0;
- 
- fail:
--        k = set_put_error(j, r);
-+        k = journal_put_error(j, r, p);
-         if (k < 0)
-                 return k;
- 
-@@ -1732,6 +1759,7 @@ fail:
- _public_ void sd_journal_close(sd_journal *j) {
-         Directory *d;
-         JournalFile *f;
-+        char *p;
- 
-         if (!j)
-                 return;
-@@ -1759,10 +1787,13 @@ _public_ void sd_journal_close(sd_journal *j) {
-                 mmap_cache_unref(j->mmap);
-         }
- 
-+        while ((p = hashmap_steal_first(j->errors)))
-+                free(p);
-+        hashmap_free(j->errors);
-+
-         free(j->path);
-         free(j->prefix);
-         free(j->unique_field);
--        set_free(j->errors);
-         free(j);
- }
- 
diff --git a/SOURCES/0513-units-order-container-and-console-getty-units-after-.patch b/SOURCES/0513-units-order-container-and-console-getty-units-after-.patch
new file mode 100644
index 0000000..2f1eba6
--- /dev/null
+++ b/SOURCES/0513-units-order-container-and-console-getty-units-after-.patch
@@ -0,0 +1,40 @@
+From b10c083e9b9de46b54873780f73dce57fa1b6d4f Mon Sep 17 00:00:00 2001
+From: Michal Sekletar <msekleta@redhat.com>
+Date: Tue, 5 Sep 2017 14:53:25 +0200
+Subject: [PATCH] units: order container and console getty units after
+ getty-pre.target
+
+(cherry picked from commit 45e27532971ac84e835a2879df510a581f933fcd)
+
+Related: #1173080
+---
+ units/console-getty.service.m4.in    | 2 +-
+ units/container-getty@.service.m4.in | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/units/console-getty.service.m4.in b/units/console-getty.service.m4.in
+index 413d94094..61ecf8951 100644
+--- a/units/console-getty.service.m4.in
++++ b/units/console-getty.service.m4.in
+@@ -11,7 +11,7 @@ Documentation=man:agetty(8)
+ After=systemd-user-sessions.service plymouth-quit-wait.service
+ ConditionPathExists=/dev/console
+ m4_ifdef(`HAVE_SYSV_COMPAT',
+-After=rc-local.service
++After=rc-local.service getty-pre.target
+ )m4_dnl
+ Before=getty.target
+ 
+diff --git a/units/container-getty@.service.m4.in b/units/container-getty@.service.m4.in
+index e126f3a48..4395ef5ce 100644
+--- a/units/container-getty@.service.m4.in
++++ b/units/container-getty@.service.m4.in
+@@ -10,7 +10,7 @@ Description=Container Getty on /dev/pts/%I
+ Documentation=man:agetty(8) man:machinectl(1)
+ After=systemd-user-sessions.service plymouth-quit-wait.service
+ m4_ifdef(`HAVE_SYSV_COMPAT',
+-After=rc-local.service
++After=rc-local.service getty-pre.target
+ )m4_dnl
+ Before=getty.target
+ IgnoreOnIsolate=yes
diff --git a/SOURCES/0514-log-never-log-into-foreign-fd-2-in-PID-1-or-its-pre-.patch b/SOURCES/0514-log-never-log-into-foreign-fd-2-in-PID-1-or-its-pre-.patch
new file mode 100644
index 0000000..917239d
--- /dev/null
+++ b/SOURCES/0514-log-never-log-into-foreign-fd-2-in-PID-1-or-its-pre-.patch
@@ -0,0 +1,76 @@
+From 5a7f49bb38bc1d7965d497e775b7cc8053b0c465 Mon Sep 17 00:00:00 2001
+From: Jan Synacek <jsynacek@redhat.com>
+Date: Fri, 18 Aug 2017 10:17:22 +0200
+Subject: [PATCH] log: never log into foreign fd #2 in PID 1 or its
+ pre-execve() children
+
+(cherry picked from commit 48a601fe5de8aa0d89ba6dadde168769fa7ce992)
+Resolves: #1420505
+---
+ src/core/main.c  | 11 +++++++++--
+ src/shared/log.c |  7 ++++++-
+ src/shared/log.h |  1 +
+ 3 files changed, 16 insertions(+), 3 deletions(-)
+
+diff --git a/src/core/main.c b/src/core/main.c
+index 37e3ea0ce..66393ed6a 100644
+--- a/src/core/main.c
++++ b/src/core/main.c
+@@ -1310,10 +1310,17 @@ int main(int argc, char *argv[]) {
+         log_show_color(isatty(STDERR_FILENO) > 0);
+         log_set_upgrade_syslog_to_journal(true);
+ 
+-        /* Disable the umask logic */
+-        if (getpid() == 1)
++        if (getpid() == 1) {
++                /* Disable the umask logic */
+                 umask(0);
+ 
++                /* Always reopen /dev/console when running as PID 1 or one of its pre-execve() children. This is
++                 * important so that we never end up logging to any foreign stderr, for example if we have to log in a
++                 * child process right before execve()'ing the actual binary, at a point in time where socket
++                 * activation stderr/stdout area already set up. */
++                log_set_always_reopen_console(true);
++        }
++
+         if (getpid() == 1 && detect_container(NULL) <= 0) {
+ 
+                 /* Running outside of a container as PID 1 */
+diff --git a/src/shared/log.c b/src/shared/log.c
+index 646a1d638..349142030 100644
+--- a/src/shared/log.c
++++ b/src/shared/log.c
+@@ -52,6 +52,7 @@ static bool show_color = false;
+ static bool show_location = false;
+ 
+ static bool upgrade_syslog_to_journal = false;
++static bool always_reopen_console = false;
+ 
+ /* Akin to glibc's __abort_msg; which is private and we hence cannot
+  * use here. */
+@@ -75,7 +76,7 @@ static int log_open_console(void) {
+         if (console_fd >= 0)
+                 return 0;
+ 
+-        if (getpid() == 1) {
++        if (always_reopen_console) {
+                 console_fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
+                 if (console_fd < 0)
+                         return console_fd;
+@@ -1061,3 +1062,7 @@ void log_received_signal(int level, const struct signalfd_siginfo *si) {
+ void log_set_upgrade_syslog_to_journal(bool b) {
+         upgrade_syslog_to_journal = b;
+ }
++
++void log_set_always_reopen_console(bool b) {
++        always_reopen_console = b;
++}
+diff --git a/src/shared/log.h b/src/shared/log.h
+index 2889e1e77..3c9448f1a 100644
+--- a/src/shared/log.h
++++ b/src/shared/log.h
+@@ -210,3 +210,4 @@ LogTarget log_target_from_string(const char *s) _pure_;
+ void log_received_signal(int level, const struct signalfd_siginfo *si);
+ 
+ void log_set_upgrade_syslog_to_journal(bool b);
++void log_set_always_reopen_console(bool b);
diff --git a/SOURCES/0514-sd-journal-properly-handle-inotify-queue-overflow.patch b/SOURCES/0514-sd-journal-properly-handle-inotify-queue-overflow.patch
deleted file mode 100644
index 702ed0c..0000000
--- a/SOURCES/0514-sd-journal-properly-handle-inotify-queue-overflow.patch
+++ /dev/null
@@ -1,442 +0,0 @@
-From afb8109dd1968e6353dbdda13e6216e12f2dec03 Mon Sep 17 00:00:00 2001
-From: Lennart Poettering <lennart@poettering.net>
-Date: Mon, 12 Feb 2018 16:14:58 +0100
-Subject: [PATCH] sd-journal: properly handle inotify queue overflow
-
-This adds proper handling of IN_Q_OVERFLOW: when the inotify queue runs
-over we'll reiterate all directories we are looking at. At the same time
-we'll mark all files and directories we encounter that way with a
-generation counter we first increased. All files and directories not
-marked like this are then unloaded.
-
-With this logic we do the best when the inotify queue overflows: we
-synchronize our in-memory state again with what's on disk.  This
-contains some refactoring of the directory logic, to share more code
-between uuid directories and "root" directories and generally make
-things a bit more readable by splitting things up into smaller bits.
-
-See: #7998 #8032
-
-(cherry-picked from commit 858749f7312bd0adb5433075a92e1c35a2fb56ac)
-
-Resolves: #1540538
----
- src/journal/journal-file.h     |   2 +
- src/journal/journal-internal.h |   2 +
- src/journal/sd-journal.c       | 237 ++++++++++++++++++++++++++++++++---------
- src/shared/path-util.c         |  14 +++
- src/shared/path-util.h         |   2 +
- 5 files changed, 206 insertions(+), 51 deletions(-)
-
-diff --git a/src/journal/journal-file.h b/src/journal/journal-file.h
-index c74ad5fc5..dd8ef52d2 100644
---- a/src/journal/journal-file.h
-+++ b/src/journal/journal-file.h
-@@ -121,6 +121,8 @@ typedef struct JournalFile {
- 
-         void *fsprg_seed;
-         size_t fsprg_seed_size;
-+
-+        unsigned last_seen_generation;
- #endif
- } JournalFile;
- 
-diff --git a/src/journal/journal-internal.h b/src/journal/journal-internal.h
-index eb23ac28a..999e9d8cb 100644
---- a/src/journal/journal-internal.h
-+++ b/src/journal/journal-internal.h
-@@ -81,6 +81,7 @@ struct Directory {
-         char *path;
-         int wd;
-         bool is_root;
-+        unsigned last_seen_generation;
- };
- 
- struct sd_journal {
-@@ -102,6 +103,7 @@ struct sd_journal {
-         int inotify_fd;
-         unsigned current_invalidate_counter, last_invalidate_counter;
-         usec_t last_process_usec;
-+        unsigned generation;
- 
-         char *unique_field;
-         JournalFile *unique_file;
-diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c
-index 14b65cfed..9186f5188 100644
---- a/src/journal/sd-journal.c
-+++ b/src/journal/sd-journal.c
-@@ -1229,8 +1229,16 @@ static int add_any_file(sd_journal *j, const char *path) {
-         assert(j);
-         assert(path);
- 
--        if (ordered_hashmap_get(j->files, path))
--                return 0;
-+        if (path) {
-+                f = ordered_hashmap_get(j->files, path);
-+                if (f) {
-+                        /* Mark this file as seen in this generation. This is used to GC old files in
-+                         * process_q_overflow() to detect journal files that are still and discern them from those who
-+                         * are gone. */
-+                        f->last_seen_generation = j->generation;
-+                        return 0;
-+                }
-+        }
- 
-         if (ordered_hashmap_size(j->files) >= JOURNAL_FILES_MAX) {
-                 log_debug("Too many open journal files, not adding %s.", path);
-@@ -1252,6 +1260,8 @@ static int add_any_file(sd_journal *j, const char *path) {
-                 goto fail;
-         }
- 
-+        f->last_seen_generation = j->generation;
-+
-         log_debug("File %s added.", f->path);
- 
-         check_network(j, f->fd);
-@@ -1346,10 +1356,96 @@ static int dirname_is_machine_id(const char *fn) {
-         return sd_id128_equal(id, machine);
- }
- 
-+static bool dirent_is_journal_file(const struct dirent *de) {
-+        assert(de);
-+
-+        if (!IN_SET(de->d_type, DT_REG, DT_LNK, DT_UNKNOWN))
-+                return false;
-+
-+        return endswith(de->d_name, ".journal") ||
-+                endswith(de->d_name, ".journal~");
-+}
-+
-+static bool dirent_is_id128_subdir(const struct dirent *de) {
-+        assert(de);
-+
-+        if (!IN_SET(de->d_type, DT_DIR, DT_LNK, DT_UNKNOWN))
-+                return false;
-+
-+        return id128_is_valid(de->d_name);
-+}
-+
-+static int directory_open(sd_journal *j, const char *path, DIR **ret) {
-+        DIR *d;
-+
-+        assert(j);
-+        assert(path);
-+        assert(ret);
-+
-+        d = opendir(path);
-+        if (!d)
-+                return -errno;
-+
-+        *ret = d;
-+        return 0;
-+}
-+
-+static int add_directory(sd_journal *j, const char *prefix, const char *dirname);
-+
-+static void directory_enumerate(sd_journal *j, Directory *m, DIR *d) {
-+        struct dirent *de;
-+
-+        assert(j);
-+        assert(m);
-+        assert(d);
-+
-+        FOREACH_DIRENT_ALL(de, d, goto fail) {
-+                if (dirent_is_journal_file(de))
-+                        (void) add_file(j, m->path, de->d_name);
-+
-+                if (m->is_root && dirent_is_id128_subdir(de))
-+                        (void) add_directory(j, m->path, de->d_name);
-+        }
-+
-+        return;
-+
-+fail:
-+        log_debug_errno(errno, "Failed to enumerate directory %s, ignoring: %m", m->path);
-+}
-+
-+static void directory_watch(sd_journal *j, Directory *m, int fd, uint32_t mask) {
-+        int r;
-+
-+        assert(j);
-+        assert(m);
-+        assert(fd >= 0);
-+
-+        /* Watch this directory if that's enabled and if it not being watched yet. */
-+
-+        if (m->wd > 0) /* Already have a watch? */
-+                return;
-+        if (j->inotify_fd < 0) /* Not watching at all? */
-+                return;
-+
-+        m->wd = inotify_add_watch_fd(j->inotify_fd, fd, mask);
-+        if (m->wd < 0) {
-+                log_debug_errno(errno, "Failed to watch journal directory '%s', ignoring: %m", m->path);
-+                return;
-+        }
-+
-+        r = hashmap_put(j->directories_by_wd, INT_TO_PTR(m->wd), m);
-+        if (r == -EEXIST)
-+                log_debug_errno(r, "Directory '%s' already being watched under a different path, ignoring: %m", m->path);
-+        if (r < 0) {
-+                log_debug_errno(r, "Failed to add watch for journal directory '%s' to hashmap, ignoring: %m", m->path);
-+                (void) inotify_rm_watch(j->inotify_fd, m->wd);
-+                m->wd = -1;
-+        }
-+}
-+
- static int add_directory(sd_journal *j, const char *prefix, const char *dirname) {
-         _cleanup_free_ char *path = NULL;
-         _cleanup_closedir_ DIR *d = NULL;
--        struct dirent *de = NULL;
-         Directory *m;
-         int r, k;
- 
-@@ -1357,7 +1453,7 @@ static int add_directory(sd_journal *j, const char *prefix, const char *dirname)
-         assert(prefix);
-         assert(dirname);
- 
--        log_debug("Considering %s/%s.", prefix, dirname);
-+        log_debug("Considering '%s/%s'.", prefix, dirname);
- 
-         if ((j->flags & SD_JOURNAL_LOCAL_ONLY) &&
-             !(dirname_is_machine_id(dirname) > 0 || path_startswith(prefix, "/run")))
-@@ -1369,9 +1465,9 @@ static int add_directory(sd_journal *j, const char *prefix, const char *dirname)
-                 goto fail;
-         }
- 
--        d = opendir(path);
--        if (!d) {
--                r = log_debug_errno(errno, "Failed to open directory %s: %m", path);
-+        r = directory_open(j, path, &d);
-+        if (r < 0) {
-+                r = log_debug_errno(errno, "Failed to open directory '%s': %m", path);
-                 goto fail;
-         }
- 
-@@ -1398,25 +1494,17 @@ static int add_directory(sd_journal *j, const char *prefix, const char *dirname)
-                 log_debug("Directory %s added.", m->path);
- 
-         } else if (m->is_root)
--                return 0;
--
--        if (m->wd <= 0 && j->inotify_fd >= 0) {
--
--                m->wd = inotify_add_watch(j->inotify_fd, m->path,
--                                          IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB|IN_DELETE|
--                                          IN_DELETE_SELF|IN_MOVE_SELF|IN_UNMOUNT|IN_MOVED_FROM|
--                                          IN_ONLYDIR);
-+                return 0; /* Don't 'downgrade' from root directory */
- 
--                if (m->wd > 0 && hashmap_put(j->directories_by_wd, INT_TO_PTR(m->wd), m) < 0)
--                        inotify_rm_watch(j->inotify_fd, m->wd);
--        }
-+        m->last_seen_generation = j->generation;
- 
--        FOREACH_DIRENT_ALL(de, d, return log_debug_errno(errno, "Failed to read directory %s: %m", m->path)) {
-+        directory_watch(j, m, dirfd(d),
-+                        IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB|IN_DELETE|
-+                        IN_DELETE_SELF|IN_MOVE_SELF|IN_UNMOUNT|IN_MOVED_FROM|
-+                        IN_ONLYDIR);
- 
--                if (dirent_is_file_with_suffix(de, ".journal") ||
--                    dirent_is_file_with_suffix(de, ".journal~"))
--                        (void) add_file(j, m->path, de->d_name);
--        }
-+        if (!j->no_new_files)
-+                directory_enumerate(j, m, d);
- 
-         check_network(j, dirfd(d));
- 
-@@ -1432,13 +1520,14 @@ fail:
- 
- static int add_root_directory(sd_journal *j, const char *p, bool missing_ok) {
-         _cleanup_closedir_ DIR *d = NULL;
--        struct dirent *de;
-         Directory *m;
-         int r, k;
- 
-         assert(j);
-         assert(p);
- 
-+        log_debug("Considering root directory '%s'.", p);
-+
-         if ((j->flags & SD_JOURNAL_RUNTIME_ONLY) &&
-             !path_startswith(p, "/run"))
-                 return -EINVAL;
-@@ -1446,12 +1535,11 @@ static int add_root_directory(sd_journal *j, const char *p, bool missing_ok) {
-         if (j->prefix)
-                 p = strjoina(j->prefix, p);
- 
--        d = opendir(p);
--        if (!d) {
--                if (errno == ENOENT && missing_ok)
--                        return 0;
--
--                r = log_debug_errno(errno, "Failed to open root directory %s: %m", p);
-+        r = directory_open(j, p, &d);
-+        if (r == -ENOENT && missing_ok)
-+                return 0;
-+        if (r < 0) {
-+                log_debug_errno(r, "Failed to open root directory %s: %m", p);
-                 goto fail;
-         }
- 
-@@ -1495,19 +1583,12 @@ static int add_root_directory(sd_journal *j, const char *p, bool missing_ok) {
-                         inotify_rm_watch(j->inotify_fd, m->wd);
-         }
- 
--        if (j->no_new_files)
--                return 0;
--
--        FOREACH_DIRENT_ALL(de, d, return log_debug_errno(errno, "Failed to read directory %s: %m", m->path)) {
--                sd_id128_t id;
-+        directory_watch(j, m, dirfd(d),
-+                        IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB|IN_DELETE|
-+                        IN_ONLYDIR);
- 
--                if (dirent_is_file_with_suffix(de, ".journal") ||
--                    dirent_is_file_with_suffix(de, ".journal~"))
--                        (void) add_file(j, m->path, de->d_name);
--                else if (IN_SET(de->d_type, DT_DIR, DT_LNK, DT_UNKNOWN) &&
--                         sd_id128_from_string(de->d_name, &id) >= 0)
--                        (void) add_directory(j, m->path, de->d_name);
--        }
-+        if (!j->no_new_files)
-+                directory_enumerate(j, m, d);
- 
-         check_network(j, dirfd(d));
- 
-@@ -2068,6 +2149,18 @@ _public_ void sd_journal_restart_data(sd_journal *j) {
-         j->current_field = 0;
- }
- 
-+static int reiterate_all_paths(sd_journal *j) {
-+        assert(j);
-+
-+        if (j->no_new_files)
-+                return add_current_paths(j);
-+
-+        if (j->path)
-+                return add_root_directory(j, j->path, true);
-+
-+        return add_search_paths(j);
-+}
-+
- _public_ int sd_journal_get_fd(sd_journal *j) {
-         int r;
- 
-@@ -2081,15 +2174,11 @@ _public_ int sd_journal_get_fd(sd_journal *j) {
-         if (r < 0)
-                 return r;
- 
--        /* Iterate through all dirs again, to add them to the
--         * inotify */
--        if (j->no_new_files)
--                r = add_current_paths(j);
--        else if (j->path)
--                r = add_root_directory(j, j->path, true);
--        else
--                r = add_search_paths(j);
--        if (r < 0)
-+         log_debug("Reiterating files to get inotify watches established.");
-+
-+        /* Iterate through all dirs again, to add them to the inotify */
-+        r = reiterate_all_paths(j);
-+         if (r < 0)
-                 return r;
- 
-         return j->inotify_fd;
-@@ -2131,12 +2220,58 @@ _public_ int sd_journal_get_timeout(sd_journal *j, uint64_t *timeout_usec) {
-         return 1;
- }
- 
-+static void process_q_overflow(sd_journal *j) {
-+        JournalFile *f;
-+        Directory *m;
-+        Iterator i;
-+
-+        assert(j);
-+
-+        /* When the inotify queue overruns we need to enumerate and re-validate all journal files to bring our list
-+         * back in sync with what's on disk. For this we pick a new generation counter value. It'll be assigned to all
-+         * journal files we encounter. All journal files and all directories that don't carry it after reenumeration
-+         * are subject for unloading. */
-+
-+        log_debug("Inotify queue overrun, reiterating everything.");
-+
-+        j->generation++;
-+        (void) reiterate_all_paths(j);
-+
-+        ORDERED_HASHMAP_FOREACH(f, j->files, i) {
-+
-+                if (f->last_seen_generation == j->generation)
-+                        continue;
-+
-+                log_debug("File '%s' hasn't been seen in this enumeration, removing.", f->path);
-+                remove_file_real(j, f);
-+        }
-+
-+        HASHMAP_FOREACH(m, j->directories_by_path, i) {
-+
-+                if (m->last_seen_generation == j->generation)
-+                        continue;
-+
-+                if (m->is_root) /* Never GC root directories */
-+                        continue;
-+
-+                log_debug("Directory '%s' hasn't been seen in this enumeration, removing.", f->path);
-+                remove_directory(j, m);
-+        }
-+
-+        log_debug("Reiteration complete.");
-+}
-+
- static void process_inotify_event(sd_journal *j, struct inotify_event *e) {
-         Directory *d;
- 
-         assert(j);
-         assert(e);
- 
-+        if (e->mask & IN_Q_OVERFLOW) {
-+                process_q_overflow(j);
-+                return;
-+        }
-+
-         /* Is this a subdirectory we watch? */
-         d = hashmap_get(j->directories_by_wd, INT_TO_PTR(e->wd));
-         if (d) {
-diff --git a/src/shared/path-util.c b/src/shared/path-util.c
-index 1181ffb9d..4d6e5e772 100644
---- a/src/shared/path-util.c
-+++ b/src/shared/path-util.c
-@@ -738,3 +738,17 @@ char *prefix_root(const char *root, const char *path) {
-         strcpy(p, path);
-         return n;
- }
-+
-+int inotify_add_watch_fd(int fd, int what, uint32_t mask) {
-+        char path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1];
-+        int r;
-+
-+        /* This is like inotify_add_watch(), except that the file to watch is not referenced by a path, but by an fd */
-+        xsprintf(path, "/proc/self/fd/%i", what);
-+
-+        r = inotify_add_watch(fd, path, mask);
-+        if (r < 0)
-+                return -errno;
-+
-+        return r;
-+}
-diff --git a/src/shared/path-util.h b/src/shared/path-util.h
-index 71bb740e9..e14702da8 100644
---- a/src/shared/path-util.h
-+++ b/src/shared/path-util.h
-@@ -65,6 +65,8 @@ int fsck_exists(const char *fstype);
- 
- char *prefix_root(const char *root, const char *path);
- 
-+int inotify_add_watch_fd(int fd, int what, uint32_t mask);
-+
- /* Similar to prefix_root(), but returns an alloca() buffer, or
-  * possibly a const pointer into the path parameter */
- #define prefix_roota(root, path)                                        \
diff --git a/SOURCES/0515-nspawn-new-option-to-start-as-PID2.patch b/SOURCES/0515-nspawn-new-option-to-start-as-PID2.patch
new file mode 100644
index 0000000..6164a39
--- /dev/null
+++ b/SOURCES/0515-nspawn-new-option-to-start-as-PID2.patch
@@ -0,0 +1,491 @@
+From 41e91ccdf9fa3097d7b90718cc83e743f4dc8d6b Mon Sep 17 00:00:00 2001
+From: Jan Rybar <jrybar@redhat.com>
+Date: Thu, 17 Aug 2017 18:01:42 +0200
+Subject: [PATCH] nspawn: new option to start as PID2
+
+Cherry-picked from: 7732f92
+Resolves: #1417387
+---
+ Makefile.am                   |   2 +
+ man/systemd-nspawn.xml        |  65 ++++++++++++--
+ src/nspawn/nspawn-stub-pid1.c | 196 ++++++++++++++++++++++++++++++++++++++++++
+ src/nspawn/nspawn-stub-pid1.h |  22 +++++
+ src/nspawn/nspawn.c           |  56 ++++++++++--
+ 5 files changed, 328 insertions(+), 13 deletions(-)
+ create mode 100644 src/nspawn/nspawn-stub-pid1.c
+ create mode 100644 src/nspawn/nspawn-stub-pid1.h
+
+diff --git a/Makefile.am b/Makefile.am
+index 7c58fd050..0e2f8d561 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -2658,6 +2658,8 @@ systemd_cgtop_LDADD = \
+ # ------------------------------------------------------------------------------
+ systemd_nspawn_SOURCES = \
+ 	src/nspawn/nspawn.c \
++	src/nspawn/nspawn-stub-pid1.c \
++	src/nspawn/nspawn-stub-pid1.h \
+ 	src/core/mount-setup.c \
+ 	src/core/mount-setup.h \
+ 	src/core/loopback-setup.c \
+diff --git a/man/systemd-nspawn.xml b/man/systemd-nspawn.xml
+index cbd44d4ab..d0eddaacc 100644
+--- a/man/systemd-nspawn.xml
++++ b/man/systemd-nspawn.xml
+@@ -241,16 +241,69 @@
+         <option>--ephemeral</option>.</para></listitem>
+       </varlistentry>
+ 
++      <varlistentry>
++      <term><option>-a</option></term>
++        <term><option>--as-pid2</option></term>
++
++        <listitem><para>Invoke the shell or specified program as process ID (PID) 2 instead of PID 1 (init). By
++        default, if neither this option nor <option>--boot</option> is used, the selected binary is run as process with
++        PID 1, a mode only suitable for programs that are aware of the special semantics that the process with PID 1
++        has on UNIX. For example, it needs to reap all processes reparented to it, and should implement
++        <command>sysvinit</command> compatible signal handling (specifically: it needs to reboot on SIGINT, reexecute
++        on SIGTERM, reload configuration on SIGHUP, and so on). With <option>--as-pid2</option> a minimal stub init
++        process is run as PID 1 and the selected binary is executed as PID 2 (and hence does not need to implement any
++        special semantics). The stub init process will reap processes as necessary and react appropriately to
++        signals. It is recommended to use this mode to invoke arbitrary commands in containers, unless they have been
++        modified to run correctly as PID 1. Or in other words: this switch should be used for pretty much all commands,
++        except when the command refers to an init or shell implementation, as these are generally capable of running
++        correctly as PID 1). This option may not be combined with <option>--boot</option> or
++        <option>--share-system</option>.</para>
++        </listitem>
++      </varlistentry>
++
+       <varlistentry>
+         <term><option>-b</option></term>
+         <term><option>--boot</option></term>
+ 
+-        <listitem><para>Automatically search for an init binary and
+-        invoke it instead of a shell or a user supplied program. If
+-        this option is used, arguments specified on the command line
+-        are used as arguments for the init binary. This option may not
+-        be combined with <option>--share-system</option>.
+-        </para></listitem>
++        <listitem><para>Automatically search for an init binary and invoke it as PID 1, instead of a shell or a user
++        supplied program. If this option is used, arguments specified on the command line are used as arguments for the
++        init binary. This option may not be combined with <option>--as-pid2</option> or
++        <option>--share-system</option>.</para>
++
++        <para>The following table explains the different modes of invocation and relationship to
++        <option>--as-pid2</option> (see above):</para>
++
++        <table>
++          <title>Invocation Mode</title>
++          <tgroup cols='2' align='left' colsep='1' rowsep='1'>
++            <colspec colname="switch" />
++            <colspec colname="explanation" />
++            <thead>
++              <row>
++                <entry>Switch</entry>
++                <entry>Explanation</entry>
++              </row>
++            </thead>
++            <tbody>
++              <row>
++                <entry>Neither <option>--as-pid2</option> nor <option>--boot</option> specified</entry>
++                <entry>The passed parameters are interpreted as command line, which is executed as PID 1 in the container.</entry>
++              </row>
++
++              <row>
++                <entry><option>--as-pid2</option> specified</entry>
++                <entry>The passed parameters are interpreted as command line, which are executed as PID 2 in the container. A stub init process is run as PID 1.</entry>
++              </row>
++
++              <row>
++                <entry><option>--boot</option> specified</entry>
++                <entry>An init binary as automatically searched and run as PID 1 in the container. The passed parameters are used as invocation parameters for this process.</entry>
++              </row>
++
++            </tbody>
++          </tgroup>
++        </table>
++        </listitem>
+       </varlistentry>
+ 
+       <varlistentry>
+diff --git a/src/nspawn/nspawn-stub-pid1.c b/src/nspawn/nspawn-stub-pid1.c
+new file mode 100644
+index 000000000..11c11560c
+--- /dev/null
++++ b/src/nspawn/nspawn-stub-pid1.c
+@@ -0,0 +1,196 @@
++/***
++  This file is part of systemd.
++
++  Copyright 2016 Lennart Poettering
++
++  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.
++
++  systemd is distributed in the hope that it will be useful, but
++  WITHOUT ANY WARRANTY; without even the implied warranty of
++  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++  Lesser General Public License for more details.
++
++  You should have received a copy of the GNU Lesser General Public License
++  along with systemd; If not, see <http://www.gnu.org/licenses/>.
++***/
++
++#include <sys/reboot.h>
++#include <sys/unistd.h>
++#include <sys/wait.h>
++#include <sys/prctl.h>
++
++#include "log.h"
++#include "nspawn-stub-pid1.h"
++#include "util.h"
++#include "time-util.h"
++#include "def.h"
++
++static int reset_environ(const char *new_environment, size_t length) {
++        unsigned long start, end;
++
++        start = (unsigned long) new_environment;
++        end = start + length;
++
++        if (prctl(PR_SET_MM, PR_SET_MM_ENV_START, start, 0, 0) < 0)
++                return -errno;
++
++        if (prctl(PR_SET_MM, PR_SET_MM_ENV_END, end, 0, 0) < 0)
++                return -errno;
++
++        return 0;
++}
++
++int stub_pid1(sd_id128_t uuid) {
++        enum {
++                STATE_RUNNING,
++                STATE_REBOOT,
++                STATE_POWEROFF,
++        } state = STATE_RUNNING;
++
++        sigset_t fullmask, oldmask, waitmask;
++        usec_t quit_usec = USEC_INFINITY;
++        pid_t pid;
++        int r;
++
++        /* The new environment we set up, on the stack. */
++        char new_environment[] =
++                "container=systemd-nspawn\0"
++                "container_uuid=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
++
++        /* Implements a stub PID 1, that reaps all processes and processes a couple of standard signals. This is useful
++         * for allowing arbitrary processes run in a container, and still have all zombies reaped. */
++
++        assert_se(sigfillset(&fullmask) >= 0);
++        assert_se(sigprocmask(SIG_BLOCK, &fullmask, &oldmask) >= 0);
++
++        pid = fork();
++        if (pid < 0)
++                return log_error_errno(errno, "Failed to fork child pid: %m");
++
++        if (pid == 0) {
++                /* Return in the child */
++                assert_se(sigprocmask(SIG_SETMASK, &oldmask, NULL) >= 0);
++                setsid();
++                return 0;
++        }
++
++        reset_all_signal_handlers();
++
++        log_close();
++        close_all_fds(NULL, 0);
++        log_open();
++
++        /* Flush out /proc/self/environ, so that we don't leak the environment from the host into the container. Also,
++         * set $container= and $container_uuid= so that clients in the container that query it from /proc/1/environ
++         * find them set. */
++        sd_id128_to_string(uuid, new_environment + sizeof(new_environment) - SD_ID128_STRING_MAX);
++        reset_environ(new_environment, sizeof(new_environment));
++
++        rename_process("STUBINIT");
++
++        assert_se(sigemptyset(&waitmask) >= 0);
++
++        sigset_add_many(&waitmask,
++                        SIGCHLD,          /* posix: process died */
++                        SIGINT,           /* sysv: ctrl-alt-del */
++                        SIGRTMIN+3,       /* systemd: halt */
++                        SIGRTMIN+4,       /* systemd: poweroff */
++                        SIGRTMIN+5,       /* systemd: reboot */
++                        SIGRTMIN+6,       /* systemd: kexec */
++                        SIGRTMIN+13,      /* systemd: halt */
++                        SIGRTMIN+14,      /* systemd: poweroff */
++                        SIGRTMIN+15,      /* systemd: reboot */
++                        SIGRTMIN+16,      /* systemd: kexec */
++                        -1);
++
++        /* Note that we ignore SIGTERM (sysv's reexec), SIGHUP (reload), and all other signals here, since we don't
++         * support reexec/reloading in this stub process. */
++
++        for (;;) {
++                siginfo_t si;
++                usec_t current_usec;
++
++                si.si_pid = 0;
++                r = waitid(P_ALL, 0, &si, WEXITED|WNOHANG);
++                if (r < 0) {
++                        r = log_error_errno(errno, "Failed to reap children: %m");
++                        goto finish;
++                }
++
++                current_usec = now(CLOCK_MONOTONIC);
++
++                if (si.si_pid == pid || current_usec >= quit_usec) {
++
++                        /* The child we started ourselves died or we reached a timeout. */
++
++                        if (state == STATE_REBOOT) { /* dispatch a queued reboot */
++                                (void) reboot(RB_AUTOBOOT);
++                                r = log_error_errno(errno, "Failed to reboot: %m");
++                                goto finish;
++
++                        } else if (state == STATE_POWEROFF)
++                                (void) reboot(RB_POWER_OFF); /* if this fails, fall back to normal exit. */
++
++                        if (si.si_pid == pid && si.si_code == CLD_EXITED)
++                                r = si.si_status; /* pass on exit code */
++                        else
++                                r = 255; /* signal, coredump, timeout, … */
++
++                        goto finish;
++                }
++                if (si.si_pid != 0)
++                        /* We reaped something. Retry until there's nothing more to reap. */
++                        continue;
++
++                if (quit_usec == USEC_INFINITY)
++                        r = sigwaitinfo(&waitmask, &si);
++                else {
++                        struct timespec ts;
++                        r = sigtimedwait(&waitmask, &si, timespec_store(&ts, quit_usec - current_usec));
++                }
++                if (r < 0) {
++                        if (errno == EINTR) /* strace -p attach can result in EINTR, let's handle this nicely. */
++                                continue;
++                        if (errno == EAGAIN) /* timeout reached */
++                                continue;
++
++                        r = log_error_errno(errno, "Failed to wait for signal: %m");
++                        goto finish;
++                }
++
++                if (si.si_signo == SIGCHLD)
++                        continue; /* Let's reap this */
++
++                if (state != STATE_RUNNING)
++                        continue;
++
++                /* Would love to use a switch() statement here, but SIGRTMIN is actually a function call, not a
++                 * constant… */
++
++                if (si.si_signo == SIGRTMIN+3 ||
++                    si.si_signo == SIGRTMIN+4 ||
++                    si.si_signo == SIGRTMIN+13 ||
++                    si.si_signo == SIGRTMIN+14)
++
++                        state = STATE_POWEROFF;
++
++                else if (si.si_signo == SIGINT ||
++                         si.si_signo == SIGRTMIN+5 ||
++                         si.si_signo == SIGRTMIN+6 ||
++                         si.si_signo == SIGRTMIN+15 ||
++                         si.si_signo == SIGRTMIN+16)
++
++                        state = STATE_REBOOT;
++                else
++                        assert_not_reached("Got unexpected signal");
++
++                /* (void) kill_and_sigcont(pid, SIGTERM); */
++                quit_usec = now(CLOCK_MONOTONIC) + DEFAULT_TIMEOUT_USEC;
++        }
++
++finish:
++        _exit(r < 0 ? EXIT_FAILURE : r);
++}
+diff --git a/src/nspawn/nspawn-stub-pid1.h b/src/nspawn/nspawn-stub-pid1.h
+new file mode 100644
+index 000000000..be0f1af4c
+--- /dev/null
++++ b/src/nspawn/nspawn-stub-pid1.h
+@@ -0,0 +1,22 @@
++#pragma once
++
++/***
++  This file is part of systemd.
++
++  Copyright 2016 Lennart Poettering
++
++  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.
++
++  systemd is distributed in the hope that it will be useful, but
++  WITHOUT ANY WARRANTY; without even the implied warranty of
++  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++  Lesser General Public License for more details.
++
++  You should have received a copy of the GNU Lesser General Public License
++  along with systemd; If not, see <http://www.gnu.org/licenses/>.
++***/
++
++int stub_pid1(sd_id128_t uuid);
+diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
+index d0003d379..ea365b3f9 100644
+--- a/src/nspawn/nspawn.c
++++ b/src/nspawn/nspawn.c
+@@ -99,6 +99,7 @@
+ #include "in-addr-util.h"
+ #include "fw-util.h"
+ #include "local-addresses.h"
++#include "nspawn-stub-pid1.h"
+ 
+ #ifdef HAVE_SECCOMP
+ #include "seccomp-util.h"
+@@ -129,6 +130,14 @@ typedef enum Volatile {
+         VOLATILE_STATE,
+ } Volatile;
+ 
++typedef enum StartMode {
++        START_PID1, /* Run parameters as command line as process 1 */
++        START_PID2, /* Use stub init process as PID 1, run parameters as command line as process 2 */
++        START_BOOT, /* Search for init system, pass arguments as parameters */
++        _START_MODE_MAX,
++        _START_MODE_INVALID = -1
++} StartMode;
++
+ static char *arg_directory = NULL;
+ static char *arg_template = NULL;
+ static char *arg_user = NULL;
+@@ -139,7 +148,7 @@ static const char *arg_selinux_apifs_context = NULL;
+ static const char *arg_slice = NULL;
+ static bool arg_private_network = false;
+ static bool arg_read_only = false;
+-static bool arg_boot = false;
++static StartMode arg_start_mode = START_PID1;
+ static bool arg_ephemeral = false;
+ static LinkJournal arg_link_journal = LINK_AUTO;
+ static bool arg_link_journal_try = false;
+@@ -200,6 +209,7 @@ static void help(void) {
+                "  -x --ephemeral            Run container with snapshot of root directory, and\n"
+                "                            remove it after exit\n"
+                "  -i --image=PATH           File system device or disk image for the container\n"
++               "  -a --as-pid2              Maintain a stub init as PID1, invoke binary as PID2\n"
+                "  -b --boot                 Boot up full system (i.e. invoke init)\n"
+                "  -u --user=USER            Run the command under specified user or uid\n"
+                "  -M --machine=NAME         Set the machine name for the container\n"
+@@ -304,6 +314,7 @@ static int parse_argv(int argc, char *argv[]) {
+                 { "ephemeral",             no_argument,       NULL, 'x'                   },
+                 { "user",                  required_argument, NULL, 'u'                   },
+                 { "private-network",       no_argument,       NULL, ARG_PRIVATE_NETWORK   },
++                { "as-pid2",               no_argument,       NULL, 'a'                   },
+                 { "boot",                  no_argument,       NULL, 'b'                   },
+                 { "uuid",                  required_argument, NULL, ARG_UUID              },
+                 { "read-only",             no_argument,       NULL, ARG_READ_ONLY         },
+@@ -340,7 +351,7 @@ static int parse_argv(int argc, char *argv[]) {
+         assert(argc >= 0);
+         assert(argv);
+ 
+-        while ((c = getopt_long(argc, argv, "+hD:u:bL:M:jS:Z:qi:xp:n", options, NULL)) >= 0)
++        while ((c = getopt_long(argc, argv, "+hD:u:abL:M:jS:Z:qi:xp:n", options, NULL)) >= 0)
+ 
+                 switch (c) {
+ 
+@@ -421,7 +432,21 @@ static int parse_argv(int argc, char *argv[]) {
+                         break;
+ 
+                 case 'b':
+-                        arg_boot = true;
++                        if (arg_start_mode == START_PID2) {
++                                log_error("--boot and --as-pid2 may not be combined.");
++                                return -EINVAL;
++                        }
++
++                        arg_start_mode = START_BOOT;
++                        break;
++
++                case 'a':
++                        if (arg_start_mode == START_BOOT) {
++                                log_error("--boot and --as-pid2 may not be combined.");
++                                return -EINVAL;
++                        }
++
++                        arg_start_mode = START_PID2;
+                         break;
+ 
+                 case ARG_UUID:
+@@ -741,7 +766,7 @@ static int parse_argv(int argc, char *argv[]) {
+         if (arg_share_system)
+                 arg_register = false;
+ 
+-        if (arg_boot && arg_share_system) {
++        if (arg_start_mode != START_PID1 && arg_share_system) {
+                 log_error("--boot and --share-system may not be combined.");
+                 return -EINVAL;
+         }
+@@ -3586,6 +3611,10 @@ int main(int argc, char *argv[]) {
+         log_parse_environment();
+         log_open();
+ 
++        /* Make sure rename_process() in the stub init process can work */
++        saved_argv = argv;
++        saved_argc = argc;
++
+         r = parse_argv(argc, argv);
+         if (r <= 0)
+                 goto finish;
+@@ -3694,7 +3723,7 @@ int main(int argc, char *argv[]) {
+                         }
+                 }
+ 
+-                if (arg_boot) {
++                if (arg_start_mode == START_BOOT) {
+                         if (path_is_os_tree(arg_directory) <= 0) {
+                                 log_error("Directory %s doesn't look like an OS root directory (os-release file is missing). Refusing.", arg_directory);
+                                 r = -EINVAL;
+@@ -4109,7 +4138,19 @@ int main(int argc, char *argv[]) {
+                         if (!barrier_place_and_sync(&barrier))
+                                 _exit(EXIT_FAILURE);
+ 
+-                        if (arg_boot) {
++                        if (arg_start_mode == START_PID2) {
++                                r = stub_pid1(arg_uuid);
++                                if (r < 0)
++                                {
++                                        log_error_errno(r, "Failed to start as PID2: %m");
++                                        _exit(EXIT_FAILURE);
++                                }
++                        }
++
++                        log_close();
++                        (void) fdset_close_others(fds);
++
++                        if (arg_start_mode == START_BOOT) {
+                                 char **a;
+                                 size_t l;
+ 
+@@ -4135,6 +4176,7 @@ int main(int argc, char *argv[]) {
+                                 execle("/bin/sh", "-sh", NULL, env_use);
+                         }
+ 
++                        log_open();
+                         log_error_errno(errno, "execv() failed: %m");
+                         _exit(EXIT_FAILURE);
+                 }
+@@ -4210,7 +4252,7 @@ int main(int argc, char *argv[]) {
+                                         goto finish;
+                                 }
+ 
+-                                if (arg_boot) {
++                                if (arg_start_mode == START_BOOT) {
+                                         /* Try to kill the init system on SIGINT or SIGTERM */
+                                         sd_event_add_signal(event, NULL, SIGINT, on_orderly_shutdown, UINT32_TO_PTR(pid));
+                                         sd_event_add_signal(event, NULL, SIGTERM, on_orderly_shutdown, UINT32_TO_PTR(pid));
diff --git a/SOURCES/0515-sd-journal-make-sure-it-s-safe-to-call-sd_journal_pr.patch b/SOURCES/0515-sd-journal-make-sure-it-s-safe-to-call-sd_journal_pr.patch
deleted file mode 100644
index c7ecc87..0000000
--- a/SOURCES/0515-sd-journal-make-sure-it-s-safe-to-call-sd_journal_pr.patch
+++ /dev/null
@@ -1,36 +0,0 @@
-From 3822b85386edacc9aaf07231b057fa847cdbde08 Mon Sep 17 00:00:00 2001
-From: Lennart Poettering <lennart@poettering.net>
-Date: Fri, 9 Feb 2018 22:38:46 +0100
-Subject: [PATCH] sd-journal: make sure it's safe to call sd_journal_process()
- before the first sd_journal_wait()
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-In that case we have no inotify fd yet, and there's nothing to process
-hence. Let's make the call a NOP.
-
-(Previously, without this change we'd end up trying to read off inotify
-fd -1, which is quite a problem... 😢)
-
-(cherry picked from commit 10c4d6405f74258ea4fac5db4888c1bf49ad5399)
-
-Related: #1540538
----
- src/journal/sd-journal.c | 3 +++
- 1 file changed, 3 insertions(+)
-
-diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c
-index 9186f5188..e1cde6e1c 100644
---- a/src/journal/sd-journal.c
-+++ b/src/journal/sd-journal.c
-@@ -2329,6 +2329,9 @@ _public_ int sd_journal_process(sd_journal *j) {
-         assert_return(j, -EINVAL);
-         assert_return(!journal_pid_changed(j), -ECHILD);
- 
-+        if (j->inotify_fd < 0) /* We have no inotify fd yet? Then there's noting to process. */
-+                return 0;
-+
-         j->last_process_usec = now(CLOCK_MONOTONIC);
-         j->last_invalidate_counter = j->current_invalidate_counter;
- 
diff --git a/SOURCES/0516-journal-implicitly-flush-to-var-on-recovery-4028.patch b/SOURCES/0516-journal-implicitly-flush-to-var-on-recovery-4028.patch
new file mode 100644
index 0000000..6094a08
--- /dev/null
+++ b/SOURCES/0516-journal-implicitly-flush-to-var-on-recovery-4028.patch
@@ -0,0 +1,77 @@
+From 80f0fa4a77bfceab3bae7cf67f44b8f899b22427 Mon Sep 17 00:00:00 2001
+From: Vito Caputo <vcaputo@gnugeneration.com>
+Date: Tue, 18 Jul 2017 18:00:37 +0200
+Subject: [PATCH] journal: implicitly flush to var on recovery (#4028)
+
+When the system journal becomes re-opened post-flush with the runtime
+journal open, it implies we've recovered from something like an ENOSPC
+situation where the system journal rotate had failed, leaving the system
+journal closed, causing the runtime journal to be opened post-flush.
+
+For the duration of the unavailable system journal, we log to the
+runtime journal.  But when the system journal gets opened (space made
+available, for example), we need to close the runtime journal before new
+journal writes will go to the system journal.  Calling
+server_flush_to_var() after opening the system journal with a runtime
+journal present, post-flush, achieves this while preserving the runtime
+journal's contents in the system journal.
+
+The combination of the present flushed flag file and the runtime journal
+being open is a state where we should be logging to the system journal,
+so it's appropriate to resume doing so once we've successfully opened
+the system journal.
+
+(cherry picked from commit 929eeb5498e8ae87e05ae683c6d3014d4b59056d)
+
+Related: #1364092
+---
+ src/journal/journald-server.c | 15 +++++++++++++--
+ 1 file changed, 13 insertions(+), 2 deletions(-)
+
+diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c
+index 2b7ecd09a..3e9412d57 100644
+--- a/src/journal/journald-server.c
++++ b/src/journal/journald-server.c
+@@ -923,6 +923,7 @@ static int system_journal_open(Server *s, bool flush_requested) {
+         char *fn;
+         sd_id128_t machine;
+         char ids[33];
++        bool flushed = false;
+ 
+         r = sd_id128_get_machine(&machine);
+         if (r < 0)
+@@ -933,7 +934,7 @@ static int system_journal_open(Server *s, bool flush_requested) {
+         if (!s->system_journal &&
+             (s->storage == STORAGE_PERSISTENT || s->storage == STORAGE_AUTO) &&
+             (flush_requested
+-             || access("/run/systemd/journal/flushed", F_OK) >= 0)) {
++             || (flushed = (access("/run/systemd/journal/flushed", F_OK) >= 0)))) {
+ 
+                 /* If in auto mode: first try to create the machine
+                  * path, but not the prefix.
+@@ -958,6 +959,16 @@ static int system_journal_open(Server *s, bool flush_requested) {
+ 
+                         r = 0;
+                 }
++
++                /* If the runtime journal is open, and we're post-flush, we're
++                 * recovering from a failed system journal rotate (ENOSPC)
++                 * for which the runtime journal was reopened.
++                 *
++                 * Perform an implicit flush to var, leaving the runtime
++                 * journal closed, now that the system journal is back.
++                 */
++                if (s->runtime_journal && flushed)
++                        (void) server_flush_to_var(s);
+         }
+ 
+         if (!s->runtime_journal &&
+@@ -1230,7 +1241,7 @@ static int dispatch_sigusr1(sd_event_source *es, const struct signalfd_siginfo *
+ 
+         log_info("Received request to flush runtime journal from PID %"PRIu32, si->ssi_pid);
+ 
+-        server_flush_to_var(s);
++        (void) server_flush_to_var(s);
+         server_sync(s);
+         server_vacuum(s);
+ 
diff --git a/SOURCES/0516-sd-journal-when-picking-up-a-new-file-compare-inode-.patch b/SOURCES/0516-sd-journal-when-picking-up-a-new-file-compare-inode-.patch
deleted file mode 100644
index 82bb1bf..0000000
--- a/SOURCES/0516-sd-journal-when-picking-up-a-new-file-compare-inode-.patch
+++ /dev/null
@@ -1,77 +0,0 @@
-From 6fc12b327982851378333d24fc902c3540dadc0e Mon Sep 17 00:00:00 2001
-From: Michal Sekletar <msekleta@redhat.com>
-Date: Tue, 20 Feb 2018 14:16:15 +0100
-Subject: [PATCH] sd-journal: when picking up a new file, compare inode/device
- info with previous open file by same name
-
-Let's make sure we aren't confused if a journal file is replaced by a
-different one (for example due to rotation) if we are in a q overflow:
-let's compare the inode/device information, and if it changed replace
-any open file object as needed.
-
-Fixes: #8198
-
-(cherry-picked from commit 32cb1983ad6f7084ff86e259ff079742a8139719)
-
-[msekleta: this is very slimmed down version of the above commit because
-a lot of code from is not applicable to RHEL-7 version]
-
-Related: #1540538
----
- src/journal/sd-journal.c | 35 +++++++++++++++++++++++++++++------
- 1 file changed, 29 insertions(+), 6 deletions(-)
-
-diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c
-index e1cde6e1c..004fe646d 100644
---- a/src/journal/sd-journal.c
-+++ b/src/journal/sd-journal.c
-@@ -1224,20 +1224,43 @@ static bool file_type_wanted(int flags, const char *filename) {
- 
- static int add_any_file(sd_journal *j, const char *path) {
-         JournalFile *f = NULL;
-+        struct stat st;
-         int r, k;
- 
-         assert(j);
-         assert(path);
- 
--        if (path) {
--                f = ordered_hashmap_get(j->files, path);
--                if (f) {
--                        /* Mark this file as seen in this generation. This is used to GC old files in
--                         * process_q_overflow() to detect journal files that are still and discern them from those who
--                         * are gone. */
-+        if (stat(path, &st) < 0) {
-+                r = log_debug_errno(errno, "Failed to stat file '%s': %m", path);
-+                return -errno;
-+        }
-+        if (S_ISDIR(st.st_mode)) {
-+                log_debug("Uh, file '%s' is a directory? Refusing.", path);
-+                return -EISDIR;
-+        }
-+        if (!S_ISREG(st.st_mode)) {
-+                log_debug("Uh, file '%s' is not a regular file? Refusing.", path);
-+                return -EBADFD;
-+        }
-+
-+        f = ordered_hashmap_get(j->files, path);
-+        if (f) {
-+
-+                if (f->last_stat.st_dev == st.st_dev &&
-+                    f->last_stat.st_ino == st.st_ino) {
-+
-+                        /* We already track this file, under the same path and with the same device/inode numbers, it's hence
-+                         * really the same. Mark this file as seen in this generation. This is used to GC old files in
-+                         * process_q_overflow() to detect journal files that are still and discern them from those who are
-+                         * gone. */
-                         f->last_seen_generation = j->generation;
-                         return 0;
-                 }
-+
-+                /* So we tracked a file under this name, but it has a different inode/device. In that case, it got
-+                 * replaced (probably due to rotation?), let's drop it hence from our list. */
-+                remove_file_real(j, f);
-+                f = NULL;
-         }
- 
-         if (ordered_hashmap_size(j->files) >= JOURNAL_FILES_MAX) {
diff --git a/SOURCES/0517-journal-add-use-flushed_flag_is_set-helper-4041.patch b/SOURCES/0517-journal-add-use-flushed_flag_is_set-helper-4041.patch
new file mode 100644
index 0000000..85b7a59
--- /dev/null
+++ b/SOURCES/0517-journal-add-use-flushed_flag_is_set-helper-4041.patch
@@ -0,0 +1,38 @@
+From 0adc312bbf5ea8ea654a5a4740f78f37eda2e9d3 Mon Sep 17 00:00:00 2001
+From: Vito Caputo <vcaputo@gnugeneration.com>
+Date: Thu, 17 Aug 2017 09:45:38 +0200
+Subject: [PATCH] journal: add/use flushed_flag_is_set() helper (#4041)
+
+Minor cleanup suggested by Lennart.
+
+(cherry-picked from commit 6431c7e216ceb9f3cfe073c94a47ac413b892e55)
+
+Related: #1364092
+---
+ src/journal/journald-server.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c
+index 3e9412d57..96ffda4ec 100644
+--- a/src/journal/journald-server.c
++++ b/src/journal/journald-server.c
+@@ -917,6 +917,9 @@ finish:
+         dispatch_message_real(s, iovec, n, m, ucred, tv, label, label_len, unit_id, priority, object_pid);
+ }
+ 
++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) {
+         int r;
+@@ -933,8 +936,7 @@ static int system_journal_open(Server *s, bool flush_requested) {
+ 
+         if (!s->system_journal &&
+             (s->storage == STORAGE_PERSISTENT || s->storage == STORAGE_AUTO) &&
+-            (flush_requested
+-             || (flushed = (access("/run/systemd/journal/flushed", F_OK) >= 0)))) {
++            (flush_requested || (flushed = flushed_flag_is_set()))) {
+ 
+                 /* If in auto mode: first try to create the machine
+                  * path, but not the prefix.
diff --git a/SOURCES/0517-journalctl-Periodically-call-sd_journal_process-in-j.patch b/SOURCES/0517-journalctl-Periodically-call-sd_journal_process-in-j.patch
deleted file mode 100644
index 8bced24..0000000
--- a/SOURCES/0517-journalctl-Periodically-call-sd_journal_process-in-j.patch
+++ /dev/null
@@ -1,59 +0,0 @@
-From 6241ea7b14a47a820e5d692a44056fa7181242cf Mon Sep 17 00:00:00 2001
-From: Peter Portante <peter.a.portante@gmail.com>
-Date: Sun, 28 Jan 2018 16:48:04 -0500
-Subject: [PATCH] journalctl: Periodically call sd_journal_process in
- journalctl
-
-If `journalctl` take a long time to process messages, and during that
-time journal file rotation occurs, a `journalctl` client will keep
-those rotated files open until it calls `sd_journal_process()`, which
-typically happens as a result of calling `sd_journal_wait()` below in
-the "following" case.  By periodically calling `sd_journal_process()`
-during the processing loop we shrink the window of time a client
-instance has open file descriptors for rotated (deleted) journal
-files.
-
-(Lennart: slightly reworked version, that dropped some of the commenting
-which was solved otherwise)
-
-(cherry picked from commit ec316d199a13d8db3f6550d60e369893de2fb417)
-
-Related: #1540538
----
- src/journal/journalctl.c | 16 ++++++++++++++++
- 1 file changed, 16 insertions(+)
-
-diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
-index 0be70764e..1e6d0761c 100644
---- a/src/journal/journalctl.c
-+++ b/src/journal/journalctl.c
-@@ -67,6 +67,8 @@
- 
- #define DEFAULT_FSS_INTERVAL_USEC (15*USEC_PER_MINUTE)
- 
-+#define PROCESS_INOTIFY_INTERVAL 1024   /* Every 1,024 messages processed */
-+
- enum {
-         /* Special values for arg_lines */
-         ARG_LINES_DEFAULT = -2,
-@@ -2294,6 +2296,20 @@ int main(int argc, char *argv[]) {
-                                 goto finish;
- 
-                         n_shown++;
-+
-+                        /* If journalctl take a long time to process messages, and during that time journal file
-+                         * rotation occurs, a journalctl client will keep those rotated files open until it calls
-+                         * sd_journal_process(), which typically happens as a result of calling sd_journal_wait() below
-+                         * in the "following" case.  By periodically calling sd_journal_process() during the processing
-+                         * loop we shrink the window of time a client instance has open file descriptors for rotated
-+                         * (deleted) journal files. */
-+                        if ((n_shown % PROCESS_INOTIFY_INTERVAL) == 0) {
-+                                r = sd_journal_process(j);
-+                                if (r < 0) {
-+                                        log_error_errno(r, "Failed to process inotify events: %m");
-+                                        goto finish;
-+                                }
-+                        }
-                 }
- 
-                 if (!arg_follow) {
diff --git a/SOURCES/0518-journald-don-t-flush-to-var-log-journal-before-we-ge.patch b/SOURCES/0518-journald-don-t-flush-to-var-log-journal-before-we-ge.patch
new file mode 100644
index 0000000..d355027
--- /dev/null
+++ b/SOURCES/0518-journald-don-t-flush-to-var-log-journal-before-we-ge.patch
@@ -0,0 +1,142 @@
+From 6032a92b8fb27a7c65a1853e62a142fd9a062b73 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Thu, 17 Aug 2017 10:21:23 +0200
+Subject: [PATCH] journald: don't flush to /var/log/journal before we get asked
+ to
+
+This changes journald to not write to /var/log/journal until it received
+SIGUSR1 for the first time, thus having been requested to flush the runtime
+journal to disk.
+
+This makes the journal work nicer with systems which have the root file system
+writable early, but still need to rearrange /var before journald should start
+writing and creating files to it, for example because ACLs need to be applied
+first, or because /var is to be mounted from another file system, NFS or tmpfs
+(as is the case for systemd.volatile=state).
+
+Before this change we required setupts with /var split out to mount the root
+disk read-only early on, and ship an /etc/fstab that remounted it writable only
+after having placed /var at the right place. But even that was racy for various
+preparations as journald might end up accessing the file system before it was
+entirely set up, as soon as it was writable.
+
+With this change we make scheduling when to start writing to /var/log/journal
+explicit. This means persistent mode now requires
+systemd-journal-flush.service in the mix to work, as otherwise journald would
+never write to the directory.
+
+See: #1397
+
+(cherry-picked from commit f78273c8dacf678cc8fd7387f678e6344a99405c)
+
+Resolves: #1364092
+---
+ src/journal/journald-server.c | 21 +++++++++++----------
+ src/journal/journald-server.h |  2 +-
+ src/journal/journald.c        |  2 +-
+ 3 files changed, 13 insertions(+), 12 deletions(-)
+
+diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c
+index 96ffda4ec..07426b41e 100644
+--- a/src/journal/journald-server.c
++++ b/src/journal/journald-server.c
+@@ -918,7 +918,7 @@ finish:
+ }
+ 
+ static bool flushed_flag_is_set(void) {
+-        return (access("/run/systemd/journal/flushed", F_OK) >= 0);
++        return access("/run/systemd/journal/flushed", F_OK) >= 0;
+ }
+ 
+ static int system_journal_open(Server *s, bool flush_requested) {
+@@ -926,7 +926,6 @@ static int system_journal_open(Server *s, bool flush_requested) {
+         char *fn;
+         sd_id128_t machine;
+         char ids[33];
+-        bool flushed = false;
+ 
+         r = sd_id128_get_machine(&machine);
+         if (r < 0)
+@@ -935,8 +934,8 @@ static int system_journal_open(Server *s, bool flush_requested) {
+         sd_id128_to_string(machine, ids);
+ 
+         if (!s->system_journal &&
+-            (s->storage == STORAGE_PERSISTENT || s->storage == STORAGE_AUTO) &&
+-            (flush_requested || (flushed = flushed_flag_is_set()))) {
++            IN_SET(s->storage, STORAGE_PERSISTENT, STORAGE_AUTO) &&
++            (flush_requested || flushed_flag_is_set())) {
+ 
+                 /* If in auto mode: first try to create the machine
+                  * path, but not the prefix.
+@@ -969,8 +968,8 @@ static int system_journal_open(Server *s, bool flush_requested) {
+                  * Perform an implicit flush to var, leaving the runtime
+                  * journal closed, now that the system journal is back.
+                  */
+-                if (s->runtime_journal && flushed)
+-                        (void) server_flush_to_var(s);
++                if (!flush_requested)
++                        (void) server_flush_to_var(s, true);
+         }
+ 
+         if (!s->runtime_journal &&
+@@ -1021,7 +1020,7 @@ static int system_journal_open(Server *s, bool flush_requested) {
+         return r;
+ }
+ 
+-int server_flush_to_var(Server *s) {
++int server_flush_to_var(Server *s, bool require_flag_file) {
+         sd_id128_t machine;
+         sd_journal *j = NULL;
+         char ts[FORMAT_TIMESPAN_MAX];
+@@ -1031,13 +1030,15 @@ int server_flush_to_var(Server *s) {
+ 
+         assert(s);
+ 
+-        if (s->storage != STORAGE_AUTO &&
+-            s->storage != STORAGE_PERSISTENT)
++        if (!IN_SET(s->storage, STORAGE_AUTO, STORAGE_PERSISTENT))
+                 return 0;
+ 
+         if (!s->runtime_journal)
+                 return 0;
+ 
++        if (require_flag_file && !flushed_flag_is_set())
++                return 0;
++
+         system_journal_open(s, true);
+ 
+         if (!s->system_journal)
+@@ -1243,7 +1244,7 @@ static int dispatch_sigusr1(sd_event_source *es, const struct signalfd_siginfo *
+ 
+         log_info("Received request to flush runtime journal from PID %"PRIu32, si->ssi_pid);
+ 
+-        (void) server_flush_to_var(s);
++        (void) server_flush_to_var(s, false);
+         server_sync(s);
+         server_vacuum(s);
+ 
+diff --git a/src/journal/journald-server.h b/src/journal/journald-server.h
+index b1263a758..7a456c2d5 100644
+--- a/src/journal/journald-server.h
++++ b/src/journal/journald-server.h
+@@ -173,6 +173,6 @@ void server_sync(Server *s);
+ void server_vacuum(Server *s);
+ void server_rotate(Server *s);
+ int server_schedule_sync(Server *s, int priority);
+-int server_flush_to_var(Server *s);
++int server_flush_to_var(Server *s, bool require_flag_file);
+ void server_maybe_append_tags(Server *s);
+ int server_process_datagram(sd_event_source *es, int fd, uint32_t revents, void *userdata);
+diff --git a/src/journal/journald.c b/src/journal/journald.c
+index 80f4634f6..15bbcbe3d 100644
+--- a/src/journal/journald.c
++++ b/src/journal/journald.c
+@@ -58,7 +58,7 @@ int main(int argc, char *argv[]) {
+                 goto finish;
+ 
+         server_vacuum(&server);
+-        server_flush_to_var(&server);
++        server_flush_to_var(&server, true);
+         server_flush_dev_kmsg(&server);
+ 
+         log_debug("systemd-journald running as pid "PID_FMT, getpid());
diff --git a/SOURCES/0519-path-util-make-use-of-mnt_id-field-exported-in-proc-.patch b/SOURCES/0519-path-util-make-use-of-mnt_id-field-exported-in-proc-.patch
new file mode 100644
index 0000000..82925c7
--- /dev/null
+++ b/SOURCES/0519-path-util-make-use-of-mnt_id-field-exported-in-proc-.patch
@@ -0,0 +1,560 @@
+From f63b66b6347a8d8e5e6930a939d1997bfd8e2e7c Mon Sep 17 00:00:00 2001
+From: Jan Synacek <jsynacek@redhat.com>
+Date: Fri, 28 Jul 2017 15:31:50 +0200
+Subject: [PATCH] path-util: make use of "mnt_id" field exported in
+ /proc/self/fdinfo/<fd>
+
+This commit is not a backport of a specific commit. It includes parts of
+several upstream commits (3f72b427b44f39a1aec6806dad6f6b57103ae9ed,
+5d409034017e9f9f8c4392157d95511fc2e05d87 and others).
+
+The main goal was to bring path_is_mount_point() up to date, which meant
+introducing fd_fdinfo_mnt_id() and fd_is_mount_point(). These were
+needed mainly because we need to determine mount points based on
+/proc/self/fdinfo/<fd> in containers. Also, there are more places in the
+code where checks for mount points are performed, which would benefit from
+this fix as well. Additionally, corresponding tests has been added.
+
+Resolves: #1472439
+---
+ src/core/automount.c                        |   2 +-
+ src/core/machine-id-setup.c                 |   2 +-
+ src/core/mount-setup.c                      |   2 +-
+ src/efi-boot-generator/efi-boot-generator.c |   2 +-
+ src/gpt-auto-generator/gpt-auto-generator.c |   2 +-
+ src/login/logind-user.c                     |   2 +-
+ src/nspawn/nspawn.c                         |  10 +-
+ src/shared/cgroup-util.c                    |   2 +-
+ src/shared/condition.c                      |   2 +-
+ src/shared/path-util.c                      | 209 ++++++++++++++++++++++------
+ src/shared/path-util.h                      |   3 +-
+ src/test/test-path-util.c                   |  66 ++++++++-
+ 12 files changed, 242 insertions(+), 62 deletions(-)
+
+diff --git a/src/core/automount.c b/src/core/automount.c
+index 4e066613d..eedd9b824 100644
+--- a/src/core/automount.c
++++ b/src/core/automount.c
+@@ -749,7 +749,7 @@ static int automount_start(Unit *u) {
+         assert(a);
+         assert(a->state == AUTOMOUNT_DEAD || a->state == AUTOMOUNT_FAILED);
+ 
+-        if (path_is_mount_point(a->where, false)) {
++        if (path_is_mount_point(a->where, 0)) {
+                 log_unit_error(u->id,
+                                "Path %s is already a mount point, refusing start for %s",
+                                a->where, u->id);
+diff --git a/src/core/machine-id-setup.c b/src/core/machine-id-setup.c
+index d00a53246..1121d373f 100644
+--- a/src/core/machine-id-setup.c
++++ b/src/core/machine-id-setup.c
+@@ -203,7 +203,7 @@ int machine_id_commit(const char *root) {
+                 etc_machine_id = path_kill_slashes(x);
+         }
+ 
+-        r = path_is_mount_point(etc_machine_id, false);
++        r = path_is_mount_point(etc_machine_id, 0);
+         if (r < 0)
+                 return log_error_errno(r, "Failed to determine whether %s is a mount point: %m", etc_machine_id);
+         if (r == 0) {
+diff --git a/src/core/mount-setup.c b/src/core/mount-setup.c
+index 521545e5c..2b8fbab1a 100644
+--- a/src/core/mount-setup.c
++++ b/src/core/mount-setup.c
+@@ -160,7 +160,7 @@ static int mount_one(const MountPoint *p, bool relabel) {
+         if (relabel)
+                 label_fix(p->where, true, true);
+ 
+-        r = path_is_mount_point(p->where, true);
++        r = path_is_mount_point(p->where, AT_SYMLINK_FOLLOW);
+         if (r < 0)
+                 return r;
+ 
+diff --git a/src/efi-boot-generator/efi-boot-generator.c b/src/efi-boot-generator/efi-boot-generator.c
+index b3ff3a8b7..5492b1994 100644
+--- a/src/efi-boot-generator/efi-boot-generator.c
++++ b/src/efi-boot-generator/efi-boot-generator.c
+@@ -69,7 +69,7 @@ int main(int argc, char *argv[]) {
+                 return EXIT_SUCCESS;
+         }
+ 
+-        if (path_is_mount_point("/boot", true) <= 0 &&
++        if (path_is_mount_point("/boot", AT_SYMLINK_FOLLOW) <= 0 &&
+             dir_is_empty("/boot") <= 0) {
+                 log_debug("/boot already populated, exiting.");
+                 return EXIT_SUCCESS;
+diff --git a/src/gpt-auto-generator/gpt-auto-generator.c b/src/gpt-auto-generator/gpt-auto-generator.c
+index 00a2141a5..d7b047118 100644
+--- a/src/gpt-auto-generator/gpt-auto-generator.c
++++ b/src/gpt-auto-generator/gpt-auto-generator.c
+@@ -299,7 +299,7 @@ static int probe_and_add_mount(
+         assert(where);
+         assert(description);
+ 
+-        if (path_is_mount_point(where, true) <= 0 &&
++        if (path_is_mount_point(where, AT_SYMLINK_FOLLOW) <= 0 &&
+             dir_is_empty(where) <= 0) {
+                 log_debug("%s already populated, ignoring.", where);
+                 return 0;
+diff --git a/src/login/logind-user.c b/src/login/logind-user.c
+index 4298704ce..912c50ebd 100644
+--- a/src/login/logind-user.c
++++ b/src/login/logind-user.c
+@@ -320,7 +320,7 @@ static int user_mkdir_runtime_path(User *u) {
+         } else
+                 p = u->runtime_path;
+ 
+-        if (path_is_mount_point(p, false) <= 0) {
++        if (path_is_mount_point(p, 0) <= 0) {
+                 _cleanup_free_ char *t = NULL;
+ 
+                 (void) mkdir(p, 0700);
+diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
+index ea365b3f9..a90a3a5d7 100644
+--- a/src/nspawn/nspawn.c
++++ b/src/nspawn/nspawn.c
+@@ -863,7 +863,7 @@ static int mount_all(const char *dest) {
+                 if (!where)
+                         return log_oom();
+ 
+-                t = path_is_mount_point(where, true);
++                t = path_is_mount_point(where, AT_SYMLINK_FOLLOW);
+                 if (t < 0) {
+                         log_error_errno(t, "Failed to detect whether %s is a mount point: %m", where);
+ 
+@@ -989,7 +989,7 @@ static int mount_cgroup_hierarchy(const char *dest, const char *controller, cons
+ 
+         to = strjoina(dest, "/sys/fs/cgroup/", hierarchy);
+ 
+-        r = path_is_mount_point(to, false);
++        r = path_is_mount_point(to, 0);
+         if (r < 0)
+                 return log_error_errno(r, "Failed to determine if %s is mounted already: %m", to);
+         if (r > 0)
+@@ -1787,7 +1787,7 @@ static int setup_journal(const char *directory) {
+         if (!p || !q)
+                 return log_oom();
+ 
+-        if (path_is_mount_point(p, false) > 0) {
++        if (path_is_mount_point(p, 0) > 0) {
+                 if (arg_link_journal != LINK_AUTO) {
+                         log_error("%s: already a mount point, refusing to use for journal", p);
+                         return -EEXIST;
+@@ -1796,7 +1796,7 @@ static int setup_journal(const char *directory) {
+                 return 0;
+         }
+ 
+-        if (path_is_mount_point(q, false) > 0) {
++        if (path_is_mount_point(q, 0) > 0) {
+                 if (arg_link_journal != LINK_AUTO) {
+                         log_error("%s: already a mount point, refusing to use for journal", q);
+                         return -EEXIST;
+@@ -3665,7 +3665,7 @@ int main(int argc, char *argv[]) {
+                          * the specified is not a mount point we
+                          * create the new snapshot in the parent
+                          * directory, just next to it. */
+-                        r = path_is_mount_point(arg_directory, false);
++                        r = path_is_mount_point(arg_directory, 0);
+                         if (r < 0) {
+                                 log_error_errno(r, "Failed to determine whether directory %s is mount point: %m", arg_directory);
+                                 goto finish;
+diff --git a/src/shared/cgroup-util.c b/src/shared/cgroup-util.c
+index c5d9e4bb5..cf085cb5f 100644
+--- a/src/shared/cgroup-util.c
++++ b/src/shared/cgroup-util.c
+@@ -488,7 +488,7 @@ int cg_get_path(const char *controller, const char *path, const char *suffix, ch
+         if (_unlikely_(!good)) {
+                 int r;
+ 
+-                r = path_is_mount_point("/sys/fs/cgroup", false);
++                r = path_is_mount_point("/sys/fs/cgroup", 0);
+                 if (r <= 0)
+                         return r < 0 ? r : -ENOENT;
+ 
+diff --git a/src/shared/condition.c b/src/shared/condition.c
+index 796cc520d..0d2cd2bc3 100644
+--- a/src/shared/condition.c
++++ b/src/shared/condition.c
+@@ -350,7 +350,7 @@ static int condition_test_path_is_mount_point(Condition *c) {
+         assert(c->parameter);
+         assert(c->type == CONDITION_PATH_IS_MOUNT_POINT);
+ 
+-        return path_is_mount_point(c->parameter, true) > 0;
++        return path_is_mount_point(c->parameter, AT_SYMLINK_FOLLOW) > 0;
+ }
+ 
+ static int condition_test_path_is_read_write(Condition *c) {
+diff --git a/src/shared/path-util.c b/src/shared/path-util.c
+index 1181ffb9d..0f252ec26 100644
+--- a/src/shared/path-util.c
++++ b/src/shared/path-util.c
+@@ -36,6 +36,7 @@
+ #include "strv.h"
+ #include "path-util.h"
+ #include "missing.h"
++#include "fileio.h"
+ 
+ bool path_is_absolute(const char *p) {
+         return p[0] == '/';
+@@ -473,87 +474,203 @@ char* path_join(const char *root, const char *path, const char *rest) {
+                                NULL);
+ }
+ 
+-int path_is_mount_point(const char *t, bool allow_symlink) {
++static int fd_fdinfo_mnt_id(int fd, const char *filename, int flags, int *mnt_id) {
++        char path[strlen("/proc/self/fdinfo/") + DECIMAL_STR_MAX(int)];
++        _cleanup_free_ char *fdinfo = NULL;
++        _cleanup_close_ int subfd = -1;
++        char *p;
++        int r;
++
++        if ((flags & AT_EMPTY_PATH) && isempty(filename))
++                xsprintf(path, "/proc/self/fdinfo/%i", fd);
++        else {
++                subfd = openat(fd, filename, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_PATH);
++                if (subfd < 0)
++                        return -errno;
++
++                xsprintf(path, "/proc/self/fdinfo/%i", subfd);
++        }
++
++        r = read_full_file(path, &fdinfo, NULL);
++        if (r == -ENOENT) /* The fdinfo directory is a relatively new addition */
++                return -EOPNOTSUPP;
++        if (r < 0)
++                return -errno;
++
++        p = startswith(fdinfo, "mnt_id:");
++        if (!p) {
++                p = strstr(fdinfo, "\nmnt_id:");
++                if (!p) /* The mnt_id field is a relatively new addition */
++                        return -EOPNOTSUPP;
++
++                p += 8;
++        }
+ 
+-        union file_handle_union h = FILE_HANDLE_INIT;
++        p += strspn(p, WHITESPACE);
++        p[strcspn(p, WHITESPACE)] = 0;
++
++        return safe_atoi(p, mnt_id);
++}
++
++int fd_is_mount_point(int fd, const char *filename, int flags) {
++        union file_handle_union h = FILE_HANDLE_INIT, h_parent = FILE_HANDLE_INIT;
+         int mount_id = -1, mount_id_parent = -1;
+-        _cleanup_free_ char *parent = NULL;
++        bool nosupp = false, check_st_dev = true;
+         struct stat a, b;
+         int r;
+-        bool nosupp = false;
+ 
+-        /* We are not actually interested in the file handles, but
+-         * name_to_handle_at() also passes us the mount ID, hence use
+-         * it but throw the handle away */
++        assert(fd >= 0);
++        assert(filename);
+ 
+-        if (path_equal(t, "/"))
+-                return 1;
+-
+-        r = name_to_handle_at(AT_FDCWD, t, &h.handle, &mount_id, allow_symlink ? AT_SYMLINK_FOLLOW : 0);
++        /* First we will try the name_to_handle_at() syscall, which
++         * tells us the mount id and an opaque file "handle". It is
++         * not supported everywhere though (kernel compile-time
++         * option, not all file systems are hooked up). If it works
++         * the mount id is usually good enough to tell us whether
++         * something is a mount point.
++         *
++         * If that didn't work we will try to read the mount id from
++         * /proc/self/fdinfo/<fd>. This is almost as good as
++         * name_to_handle_at(), however, does not return the
++         * opaque file handle. The opaque file handle is pretty useful
++         * to detect the root directory, which we should always
++         * consider a mount point. Hence we use this only as
++         * fallback. Exporting the mnt_id in fdinfo is a pretty recent
++         * kernel addition.
++         *
++         * As last fallback we do traditional fstat() based st_dev
++         * comparisons. This is how things were traditionally done,
++         * but unionfs breaks breaks this since it exposes file
++         * systems with a variety of st_dev reported. Also, btrfs
++         * subvolumes have different st_dev, even though they aren't
++         * real mounts of their own. */
++
++        r = name_to_handle_at(fd, filename, &h.handle, &mount_id, flags);
+         if (r < 0) {
+                 if (errno == ENOSYS)
+                         /* This kernel does not support name_to_handle_at()
+-                         * fall back to the traditional stat() logic. */
+-                        goto fallback;
++                         * fall back to simpler logic. */
++                        goto fallback_fdinfo;
+                 else if (errno == EOPNOTSUPP)
+                         /* This kernel or file system does not support
+-                         * name_to_handle_at(), hence fallback to the
++                         * name_to_handle_at(), hence let's see if the
++                         * upper fs supports it (in which case it is a
++                         * mount point), otherwise fallback to the
+                          * traditional stat() logic */
+                         nosupp = true;
+-                else if (errno == ENOENT)
+-                        return 0;
+                 else
+                         return -errno;
+         }
+ 
+-        r = path_get_parent(t, &parent);
+-        if (r < 0)
+-                return r;
+-
+-        h.handle.handle_bytes = MAX_HANDLE_SZ;
+-        r = name_to_handle_at(AT_FDCWD, parent, &h.handle, &mount_id_parent, AT_SYMLINK_FOLLOW);
+-        if (r < 0)
+-                if (errno == EOPNOTSUPP)
++        r = name_to_handle_at(fd, "", &h_parent.handle, &mount_id_parent, AT_EMPTY_PATH);
++        if (r < 0) {
++                if (errno == EOPNOTSUPP) {
+                         if (nosupp)
+                                 /* Neither parent nor child do name_to_handle_at()?
+                                    We have no choice but to fall back. */
+-                                goto fallback;
++                                goto fallback_fdinfo;
+                         else
+-                                /* The parent can't do name_to_handle_at() but
+-                                 * the directory we are interested in can?
+-                                 * Or the other way around?
++                                /* The parent can't do name_to_handle_at() but the
++                                 * directory we are interested in can?
+                                  * If so, it must be a mount point. */
+                                 return 1;
+-                else
++                } else
+                         return -errno;
+-        else
+-                return mount_id != mount_id_parent;
++        }
+ 
+-fallback:
+-        if (allow_symlink)
+-                r = stat(t, &a);
+-        else
+-                r = lstat(t, &a);
++        /* The parent can do name_to_handle_at() but the
++         * directory we are interested in can't? If so, it
++         * must be a mount point. */
++        if (nosupp)
++                return 1;
+ 
+-        if (r < 0) {
+-                if (errno == ENOENT)
+-                        return 0;
++        /* If the file handle for the directory we are
++         * interested in and its parent are identical, we
++         * assume this is the root directory, which is a mount
++         * point. */
+ 
+-                return -errno;
+-        }
++        if (h.handle.handle_bytes == h_parent.handle.handle_bytes &&
++            h.handle.handle_type == h_parent.handle.handle_type &&
++            memcmp(h.handle.f_handle, h_parent.handle.f_handle, h.handle.handle_bytes) == 0)
++                return 1;
+ 
+-        free(parent);
+-        parent = NULL;
++        return mount_id != mount_id_parent;
+ 
+-        r = path_get_parent(t, &parent);
++fallback_fdinfo:
++        r = fd_fdinfo_mnt_id(fd, filename, flags, &mount_id);
++        if (r == -EOPNOTSUPP)
++                goto fallback_fstat;
+         if (r < 0)
+                 return r;
+ 
+-        r = stat(parent, &b);
++        r = fd_fdinfo_mnt_id(fd, "", AT_EMPTY_PATH, &mount_id_parent);
+         if (r < 0)
++                return r;
++
++        if (mount_id != mount_id_parent)
++                return 1;
++
++        /* Hmm, so, the mount ids are the same. This leaves one
++         * special case though for the root file system. For that,
++         * let's see if the parent directory has the same inode as we
++         * are interested in. Hence, let's also do fstat() checks now,
++         * too, but avoid the st_dev comparisons, since they aren't
++         * that useful on unionfs mounts. */
++        check_st_dev = false;
++
++fallback_fstat:
++        /* yay for fstatat() taking a different set of flags than the other
++         * _at() above */
++        if (flags & AT_SYMLINK_FOLLOW)
++                flags &= ~AT_SYMLINK_FOLLOW;
++        else
++                flags |= AT_SYMLINK_NOFOLLOW;
++        if (fstatat(fd, filename, &a, flags) < 0)
++                return -errno;
++
++        if (fstatat(fd, "", &b, AT_EMPTY_PATH) < 0)
++                return -errno;
++
++        /* A directory with same device and inode as its parent? Must
++         * be the root directory */
++        if (a.st_dev == b.st_dev &&
++            a.st_ino == b.st_ino)
++                return 1;
++
++        return check_st_dev && (a.st_dev != b.st_dev);
++}
++
++/* flags can be AT_SYMLINK_FOLLOW or 0 */
++int path_is_mount_point(const char *t, int flags) {
++        _cleanup_close_ int fd = -1;
++        _cleanup_free_ char *canonical = NULL, *parent = NULL;
++
++        assert(t);
++
++        if (path_equal(t, "/"))
++                return 1;
++
++        /* we need to resolve symlinks manually, we can't just rely on
++         * fd_is_mount_point() to do that for us; if we have a structure like
++         * /bin -> /usr/bin/ and /usr is a mount point, then the parent that we
++         * look at needs to be /usr, not /. */
++        if (flags & AT_SYMLINK_FOLLOW) {
++                canonical = canonicalize_file_name(t);
++                if (!canonical)
++                        return -errno;
++
++                t = canonical;
++        }
++
++        parent = dirname_malloc(t);
++        if (!parent)
++                return -ENOMEM;
++
++        fd = openat(AT_FDCWD, parent, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_PATH);
++        if (fd < 0)
+                 return -errno;
+ 
+-        return a.st_dev != b.st_dev;
++        return fd_is_mount_point(fd, basename(t), flags);
+ }
+ 
+ int path_is_read_only_fs(const char *path) {
+diff --git a/src/shared/path-util.h b/src/shared/path-util.h
+index 71bb740e9..e16484087 100644
+--- a/src/shared/path-util.h
++++ b/src/shared/path-util.h
+@@ -53,7 +53,8 @@ char** path_strv_make_absolute_cwd(char **l);
+ char** path_strv_resolve(char **l, const char *prefix);
+ char** path_strv_resolve_uniq(char **l, const char *prefix);
+ 
+-int path_is_mount_point(const char *path, bool allow_symlink);
++int fd_is_mount_point(int fd, const char *filename, int flags);
++int path_is_mount_point(const char *path, int flags);
+ int path_is_read_only_fs(const char *path);
+ int path_is_os_tree(const char *path);
+ 
+diff --git a/src/test/test-path-util.c b/src/test/test-path-util.c
+index 6396fcb39..8870f178a 100644
+--- a/src/test/test-path-util.c
++++ b/src/test/test-path-util.c
+@@ -21,6 +21,7 @@
+ 
+ #include <stdio.h>
+ #include <unistd.h>
++#include <sys/mount.h>
+ 
+ #include "path-util.h"
+ #include "util.h"
+@@ -85,8 +86,8 @@ static void test_path(void) {
+         test_parent("/aa///file...", "/aa///");
+         test_parent("file.../", NULL);
+ 
+-        assert_se(path_is_mount_point("/", true));
+-        assert_se(path_is_mount_point("/", false));
++        assert_se(path_is_mount_point("/", AT_SYMLINK_FOLLOW));
++        assert_se(path_is_mount_point("/", 0));
+ 
+         {
+                 char p1[] = "aaa/bbb////ccc";
+@@ -99,6 +100,66 @@ static void test_path(void) {
+         }
+ }
+ 
++static void test_path_is_mount_point(void) {
++        int fd, rt, rf, rlt, rlf;
++        char tmp_dir[] = "/tmp/test-path-is-mount-point-XXXXXX";
++        _cleanup_free_ char *file1 = NULL, *file2 = NULL, *link1 = NULL, *link2 = NULL;
++
++        assert_se(path_is_mount_point("/", AT_SYMLINK_FOLLOW) > 0);
++        assert_se(path_is_mount_point("/", 0) > 0);
++
++        assert_se(path_is_mount_point("/proc", AT_SYMLINK_FOLLOW) > 0);
++        assert_se(path_is_mount_point("/proc", 0) > 0);
++
++        assert_se(path_is_mount_point("/proc/1", AT_SYMLINK_FOLLOW) == 0);
++        assert_se(path_is_mount_point("/proc/1", 0) == 0);
++
++        assert_se(path_is_mount_point("/sys", AT_SYMLINK_FOLLOW) > 0);
++        assert_se(path_is_mount_point("/sys", 0) > 0);
++
++        /* file mountpoints */
++        assert_se(mkdtemp(tmp_dir) != NULL);
++        file1 = path_join(NULL, tmp_dir, "file1");
++        assert_se(file1);
++        file2 = path_join(NULL, tmp_dir, "file2");
++        assert_se(file2);
++        fd = open(file1, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, 0664);
++        assert_se(fd > 0);
++        close(fd);
++        fd = open(file2, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, 0664);
++        assert_se(fd > 0);
++        close(fd);
++        link1 = path_join(NULL, tmp_dir, "link1");
++        assert_se(link1);
++        assert_se(symlink("file1", link1) == 0);
++        link2 = path_join(NULL, tmp_dir, "link2");
++        assert_se(link1);
++        assert_se(symlink("file2", link2) == 0);
++
++        assert_se(path_is_mount_point(file1, AT_SYMLINK_FOLLOW) == 0);
++        assert_se(path_is_mount_point(file1, 0) == 0);
++        assert_se(path_is_mount_point(link1, AT_SYMLINK_FOLLOW) == 0);
++        assert_se(path_is_mount_point(link1, 0) == 0);
++
++        /* this test will only work as root */
++        if (mount(file1, file2, NULL, MS_BIND, NULL) >= 0) {
++                rf = path_is_mount_point(file2, 0);
++                rt = path_is_mount_point(file2, AT_SYMLINK_FOLLOW);
++                rlf = path_is_mount_point(link2, 0);
++                rlt = path_is_mount_point(link2, AT_SYMLINK_FOLLOW);
++
++                assert_se(umount(file2) == 0);
++
++                assert_se(rf == 1);
++                assert_se(rt == 1);
++                assert_se(rlf == 0);
++                assert_se(rlt == 1);
++        } else
++                printf("Skipping bind mount file test: %m\n");
++
++        assert_se(rm_rf(tmp_dir, false, true, false) == 0);
++}
++
+ static void test_find_binary(const char *self, bool local) {
+         char *p;
+ 
+@@ -288,6 +349,7 @@ int main(int argc, char **argv) {
+         test_make_relative();
+         test_strv_resolve();
+         test_path_startswith();
++        test_path_is_mount_point();
+ 
+         return 0;
+ }
diff --git a/SOURCES/0520-Revert-Revert-journald-allow-restarting-journald-wit.patch b/SOURCES/0520-Revert-Revert-journald-allow-restarting-journald-wit.patch
new file mode 100644
index 0000000..3b12cdb
--- /dev/null
+++ b/SOURCES/0520-Revert-Revert-journald-allow-restarting-journald-wit.patch
@@ -0,0 +1,546 @@
+From e0a3cd2cb02c465c13dcc4e2c092c9e14883ad59 Mon Sep 17 00:00:00 2001
+From: Lukas Nykryn <lnykryn@redhat.com>
+Date: Wed, 3 Feb 2016 10:37:48 +0100
+Subject: [PATCH] Revert "Revert "journald: allow restarting journald without
+ losing stream connections""
+
+This reverts commit 91cb89c1b79ef3c475d91319edb0c052cb9f2724.
+
+Resolves: #1359939
+---
+ src/journal/journald-server.c |  26 ++-
+ src/journal/journald-stream.c | 371 ++++++++++++++++++++++++++++++++++++------
+ src/journal/journald-stream.h |   3 +-
+ 3 files changed, 340 insertions(+), 60 deletions(-)
+
+diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c
+index 07426b41e..c1358e1e9 100644
+--- a/src/journal/journald-server.c
++++ b/src/journal/journald-server.c
+@@ -1477,6 +1477,7 @@ static int server_open_hostname(Server *s) {
+ }
+ 
+ int server_init(Server *s) {
++        _cleanup_fdset_free_ FDSet *fds = NULL;
+         int n, r, fd;
+ 
+         assert(s);
+@@ -1573,26 +1574,33 @@ int server_init(Server *s) {
+                         s->audit_fd = fd;
+ 
+                 } else {
+-                        log_warning("Unknown socket passed as file descriptor %d, ignoring.", fd);
+ 
+-                        /* Let's close the fd, better be safe than
+-                           sorry. The fd might reference some resource
+-                           that we really want to release if we don't
+-                           make use of it. */
++                        if (!fds) {
++                                fds = fdset_new();
++                                if (!fds)
++                                        return log_oom();
++                        }
+ 
+-                        safe_close(fd);
++                        r = fdset_put(fds, fd);
++                        if (r < 0)
++                                return log_oom();
+                 }
+         }
+ 
+-        r = server_open_syslog_socket(s);
++        r = server_open_stdout_socket(s, fds);
+         if (r < 0)
+                 return r;
+ 
+-        r = server_open_native_socket(s);
++        if (fdset_size(fds) > 0) {
++                log_warning("%u unknown file descriptors passed, closing.", fdset_size(fds));
++                fds = fdset_free(fds);
++        }
++
++        r = server_open_syslog_socket(s);
+         if (r < 0)
+                 return r;
+ 
+-        r = server_open_stdout_socket(s);
++        r = server_open_native_socket(s);
+         if (r < 0)
+                 return r;
+ 
+diff --git a/src/journal/journald-stream.c b/src/journal/journald-stream.c
+index b8607144b..15c9110c0 100644
+--- a/src/journal/journald-stream.c
++++ b/src/journal/journald-stream.c
+@@ -28,8 +28,11 @@
+ #endif
+ 
+ #include "sd-event.h"
++#include "sd-daemon.h"
+ #include "socket-util.h"
+ #include "selinux-util.h"
++#include "mkdir.h"
++#include "fileio.h"
+ #include "journald-server.h"
+ #include "journald-stream.h"
+ #include "journald-syslog.h"
+@@ -66,14 +69,148 @@ struct StdoutStream {
+         bool forward_to_kmsg:1;
+         bool forward_to_console:1;
+ 
++        bool fdstore:1;
++
+         char buffer[LINE_MAX+1];
+         size_t length;
+ 
+         sd_event_source *event_source;
+ 
++        char *state_file;
++
+         LIST_FIELDS(StdoutStream, stdout_stream);
+ };
+ 
++void stdout_stream_free(StdoutStream *s) {
++        if (!s)
++                return;
++
++        if (s->server) {
++                assert(s->server->n_stdout_streams > 0);
++                s->server->n_stdout_streams --;
++                LIST_REMOVE(stdout_stream, s->server->stdout_streams, s);
++        }
++
++        if (s->event_source) {
++                sd_event_source_set_enabled(s->event_source, SD_EVENT_OFF);
++                s->event_source = sd_event_source_unref(s->event_source);
++        }
++
++        safe_close(s->fd);
++        free(s->label);
++        free(s->identifier);
++        free(s->unit_id);
++        free(s->state_file);
++
++        free(s);
++}
++
++DEFINE_TRIVIAL_CLEANUP_FUNC(StdoutStream*, stdout_stream_free);
++
++static void stdout_stream_destroy(StdoutStream *s) {
++        if (!s)
++                return;
++
++        if (s->state_file)
++                unlink(s->state_file);
++
++        stdout_stream_free(s);
++}
++
++static int stdout_stream_save(StdoutStream *s) {
++        _cleanup_free_ char *temp_path = NULL;
++        _cleanup_fclose_ FILE *f = NULL;
++        int r;
++
++        assert(s);
++
++        if (s->state != STDOUT_STREAM_RUNNING)
++                return 0;
++
++        if (!s->state_file) {
++                struct stat st;
++
++                r = fstat(s->fd, &st);
++                if (r < 0)
++                        return log_warning_errno(errno, "Failed to stat connected stream: %m");
++
++                /* We use device and inode numbers as identifier for the stream */
++                if (asprintf(&s->state_file, "/run/systemd/journal/streams/%lu:%lu", (unsigned long) st.st_dev, (unsigned long) st.st_ino) < 0)
++                        return log_oom();
++        }
++
++        mkdir_p("/run/systemd/journal/streams", 0755);
++
++        r = fopen_temporary(s->state_file, &f, &temp_path);
++        if (r < 0)
++                goto finish;
++
++        fprintf(f,
++                "# This is private data. Do not parse\n"
++                "PRIORITY=%i\n"
++                "LEVEL_PREFIX=%i\n"
++                "FORWARD_TO_SYSLOG=%i\n"
++                "FORWARD_TO_KMSG=%i\n"
++                "FORWARD_TO_CONSOLE=%i\n",
++                s->priority,
++                s->level_prefix,
++                s->forward_to_syslog,
++                s->forward_to_kmsg,
++                s->forward_to_console);
++
++        if (!isempty(s->identifier)) {
++                _cleanup_free_ char *escaped;
++
++                escaped = cescape(s->identifier);
++                if (!escaped) {
++                        r = -ENOMEM;
++                        goto finish;
++                }
++
++                fprintf(f, "IDENTIFIER=%s\n", escaped);
++        }
++
++        if (!isempty(s->unit_id)) {
++                _cleanup_free_ char *escaped;
++
++                escaped = cescape(s->unit_id);
++                if (!escaped) {
++                        r = -ENOMEM;
++                        goto finish;
++                }
++
++                fprintf(f, "UNIT=%s\n", escaped);
++        }
++
++        r = fflush_and_check(f);
++        if (r < 0)
++                goto finish;
++
++        if (rename(temp_path, s->state_file) < 0) {
++                r = -errno;
++                goto finish;
++        }
++
++        free(temp_path);
++        temp_path = NULL;
++
++        /* Store the connection fd in PID 1, so that we get it passed
++         * in again on next start */
++        if (!s->fdstore) {
++                sd_pid_notify_with_fds(0, false, "FDSTORE=1", &s->fd, 1);
++                s->fdstore = true;
++        }
++
++finish:
++        if (temp_path)
++                unlink(temp_path);
++
++        if (r < 0)
++                log_error_errno(r, "Failed to save stream data %s: %m", s->state_file);
++
++        return r;
++}
++
+ static int stdout_stream_log(StdoutStream *s, const char *p) {
+         struct iovec iovec[N_IOVEC_META_FIELDS + 5];
+         int priority;
+@@ -219,6 +356,9 @@ static int stdout_stream_line(StdoutStream *s, char *p) {
+ 
+                 s->forward_to_console = !!r;
+                 s->state = STDOUT_STREAM_RUNNING;
++
++                /* Try to save the stream, so that journald can be restarted and we can recover */
++                (void) stdout_stream_save(s);
+                 return 0;
+ 
+         case STDOUT_STREAM_RUNNING:
+@@ -313,36 +453,62 @@ static int stdout_stream_process(sd_event_source *es, int fd, uint32_t revents,
+         return 1;
+ 
+ terminate:
+-        stdout_stream_free(s);
++        stdout_stream_destroy(s);
+         return 0;
+ }
+ 
+-void stdout_stream_free(StdoutStream *s) {
++static int stdout_stream_install(Server *s, int fd, StdoutStream **ret) {
++        _cleanup_(stdout_stream_freep) StdoutStream *stream = NULL;
++        int r;
++
+         assert(s);
++        assert(fd >= 0);
+ 
+-        if (s->server) {
+-                assert(s->server->n_stdout_streams > 0);
+-                s->server->n_stdout_streams --;
+-                LIST_REMOVE(stdout_stream, s->server->stdout_streams, s);
+-        }
++        stream = new0(StdoutStream, 1);
++        if (!stream)
++                return log_oom();
+ 
+-        if (s->event_source) {
+-                sd_event_source_set_enabled(s->event_source, SD_EVENT_OFF);
+-                s->event_source = sd_event_source_unref(s->event_source);
++        stream->fd = -1;
++        stream->priority = LOG_INFO;
++
++        r = getpeercred(fd, &stream->ucred);
++        if (r < 0)
++                return log_error_errno(r, "Failed to determine peer credentials: %m");
++
++        if (mac_selinux_use()) {
++                r = getpeersec(fd, &stream->label);
++                if (r < 0 && r != -EOPNOTSUPP)
++                        (void) log_warning_errno(r, "Failed to determine peer security context: %m");
+         }
+ 
+-        safe_close(s->fd);
++        (void) shutdown(fd, SHUT_WR);
+ 
+-        free(s->label);
+-        free(s->identifier);
+-        free(s->unit_id);
+-        free(s);
++        r = sd_event_add_io(s->event, &stream->event_source, fd, EPOLLIN, stdout_stream_process, stream);
++        if (r < 0)
++                return log_error_errno(r, "Failed to add stream to event loop: %m");
++
++        r = sd_event_source_set_priority(stream->event_source, SD_EVENT_PRIORITY_NORMAL+5);
++        if (r < 0)
++                return log_error_errno(r, "Failed to adjust stdout event source priority: %m");
++
++        stream->fd = fd;
++
++        stream->server = s;
++        LIST_PREPEND(stdout_stream, s->stdout_streams, stream);
++        s->n_stdout_streams ++;
++
++        if (ret)
++                *ret = stream;
++
++        stream = NULL;
++
++        return 0;
+ }
+ 
+ static int stdout_stream_new(sd_event_source *es, int listen_fd, uint32_t revents, void *userdata) {
++        _cleanup_close_ int fd = -1;
+         Server *s = userdata;
+-        StdoutStream *stream;
+-        int fd, r;
++        int r;
+ 
+         assert(s);
+ 
+@@ -362,61 +528,163 @@ static int stdout_stream_new(sd_event_source *es, int listen_fd, uint32_t revent
+ 
+         if (s->n_stdout_streams >= STDOUT_STREAMS_MAX) {
+                 log_warning("Too many stdout streams, refusing connection.");
+-                safe_close(fd);
+                 return 0;
+         }
+ 
+-        stream = new0(StdoutStream, 1);
+-        if (!stream) {
+-                safe_close(fd);
+-                return log_oom();
++        r = stdout_stream_install(s, fd, NULL);
++        if (r < 0)
++                return r;
++
++        fd = -1;
++        return 0;
++}
++
++static int stdout_stream_load(StdoutStream *stream, const char *fname) {
++        _cleanup_free_ char
++                *priority = NULL,
++                *level_prefix = NULL,
++                *forward_to_syslog = NULL,
++                *forward_to_kmsg = NULL,
++                *forward_to_console = NULL;
++        int r;
++
++        assert(stream);
++        assert(fname);
++
++        if (!stream->state_file) {
++                stream->state_file = strappend("/run/systemd/journal/streams/", fname);
++                if (!stream->state_file)
++                        return log_oom();
+         }
+ 
+-        stream->fd = fd;
++        r = parse_env_file(stream->state_file, NEWLINE,
++                           "PRIORITY", &priority,
++                           "LEVEL_PREFIX", &level_prefix,
++                           "FORWARD_TO_SYSLOG", &forward_to_syslog,
++                           "FORWARD_TO_KMSG", &forward_to_kmsg,
++                           "FORWARD_TO_CONSOLE", &forward_to_console,
++                           "IDENTIFIER", &stream->identifier,
++                           "UNIT", &stream->unit_id,
++                           NULL);
++        if (r < 0)
++                return log_error_errno(r, "Failed to read: %s", stream->state_file);
+ 
+-        r = getpeercred(fd, &stream->ucred);
+-        if (r < 0) {
+-                log_error_errno(errno, "Failed to determine peer credentials: %m");
+-                goto fail;
++        if (priority) {
++                int p;
++
++                p = log_level_from_string(priority);
++                if (p >= 0)
++                        stream->priority = p;
+         }
+ 
+-#ifdef HAVE_SELINUX
+-        if (mac_selinux_use()) {
+-                r = getpeersec(fd, &stream->label);
+-                if (r < 0 && r != -EOPNOTSUPP)
+-                        (void) log_warning_errno(r, "Failed to determine peer security context: %m");
++        if (level_prefix) {
++                r = parse_boolean(level_prefix);
++                if (r >= 0)
++                        stream->level_prefix = r;
+         }
+-#endif
+ 
+-        if (shutdown(fd, SHUT_WR) < 0) {
+-                log_error_errno(errno, "Failed to shutdown writing side of socket: %m");
+-                goto fail;
++        if (forward_to_syslog) {
++                r = parse_boolean(forward_to_syslog);
++                if (r >= 0)
++                        stream->forward_to_syslog = r;
+         }
+ 
+-        r = sd_event_add_io(s->event, &stream->event_source, fd, EPOLLIN, stdout_stream_process, stream);
+-        if (r < 0) {
+-                log_error_errno(r, "Failed to add stream to event loop: %m");
+-                goto fail;
++        if (forward_to_kmsg) {
++                r = parse_boolean(forward_to_kmsg);
++                if (r >= 0)
++                        stream->forward_to_kmsg = r;
+         }
+ 
+-        r = sd_event_source_set_priority(stream->event_source, SD_EVENT_PRIORITY_NORMAL+5);
+-        if (r < 0) {
+-                log_error_errno(r, "Failed to adjust stdout event source priority: %m");
+-                goto fail;
++        if (forward_to_console) {
++                r = parse_boolean(forward_to_console);
++                if (r >= 0)
++                        stream->forward_to_console = r;
+         }
+ 
+-        stream->server = s;
+-        LIST_PREPEND(stdout_stream, s->stdout_streams, stream);
+-        s->n_stdout_streams ++;
++        return 0;
++}
++
++static int stdout_stream_restore(Server *s, const char *fname, int fd) {
++        StdoutStream *stream;
++        int r;
++
++        assert(s);
++        assert(fname);
++        assert(fd >= 0);
++
++        if (s->n_stdout_streams >= STDOUT_STREAMS_MAX) {
++                log_warning("Too many stdout streams, refusing restoring of stream.");
++                return -ENOBUFS;
++        }
++
++        r = stdout_stream_install(s, fd, &stream);
++        if (r < 0)
++                return r;
++
++        stream->state = STDOUT_STREAM_RUNNING;
++        stream->fdstore = true;
++
++        /* Ignore all parsing errors */
++        (void) stdout_stream_load(stream, fname);
+ 
+         return 0;
++}
++
++static int server_restore_streams(Server *s, FDSet *fds) {
++        _cleanup_closedir_ DIR *d = NULL;
++        struct dirent *de;
++        int r;
++
++        d = opendir("/run/systemd/journal/streams");
++        if (!d) {
++                if (errno == ENOENT)
++                        return 0;
++
++                return log_warning_errno(errno, "Failed to enumerate /run/systemd/journal/streams: %m");
++        }
++
++        FOREACH_DIRENT(de, d, goto fail) {
++                unsigned long st_dev, st_ino;
++                bool found = false;
++                Iterator i;
++                int fd;
++
++                if (sscanf(de->d_name, "%lu:%lu", &st_dev, &st_ino) != 2)
++                        continue;
++
++                FDSET_FOREACH(fd, fds, i) {
++                        struct stat st;
++
++                        if (fstat(fd, &st) < 0)
++                                return log_error_errno(errno, "Failed to stat %s: %m", de->d_name);
++
++                        if (S_ISSOCK(st.st_mode) && st.st_dev == st_dev && st.st_ino == st_ino) {
++                                found = true;
++                                break;
++                        }
++                }
++
++                if (!found) {
++                        /* No file descriptor? Then let's delete the state file */
++                        log_debug("Cannot restore stream file %s", de->d_name);
++                        unlinkat(dirfd(d), de->d_name, 0);
++                        continue;
++                }
++
++                fdset_remove(fds, fd);
++
++                r = stdout_stream_restore(s, de->d_name, fd);
++                if (r < 0)
++                        safe_close(fd);
++        }
+ 
+-fail:
+-        stdout_stream_free(stream);
+         return 0;
++
++fail:
++        return log_error_errno(errno, "Failed to read streams directory: %m");
+ }
+ 
+-int server_open_stdout_socket(Server *s) {
++int server_open_stdout_socket(Server *s, FDSet *fds) {
+         int r;
+ 
+         assert(s);
+@@ -452,5 +720,8 @@ int server_open_stdout_socket(Server *s) {
+         if (r < 0)
+                 return log_error_errno(r, "Failed to adjust priority of stdout server event source: %m");
+ 
++        /* Try to restore streams, but don't bother if this fails */
++        (void) server_restore_streams(s, fds);
++
+         return 0;
+ }
+diff --git a/src/journal/journald-stream.h b/src/journal/journald-stream.h
+index 8cad01296..94bf955d7 100644
+--- a/src/journal/journald-stream.h
++++ b/src/journal/journald-stream.h
+@@ -21,8 +21,9 @@
+   along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ ***/
+ 
++#include "fdset.h"
+ #include "journald-server.h"
+ 
+-int server_open_stdout_socket(Server *s);
++int server_open_stdout_socket(Server *s, FDSet *fds);
+ 
+ void stdout_stream_free(StdoutStream *s);
diff --git a/SOURCES/0521-journald-make-sure-we-retain-all-stream-fds-across-r.patch b/SOURCES/0521-journald-make-sure-we-retain-all-stream-fds-across-r.patch
new file mode 100644
index 0000000..e3e9898
--- /dev/null
+++ b/SOURCES/0521-journald-make-sure-we-retain-all-stream-fds-across-r.patch
@@ -0,0 +1,34 @@
+From ad2d5449dc86ac37460ac9c16e0d5d088befbd0b Mon Sep 17 00:00:00 2001
+From: Michal Sekletar <msekletar@users.noreply.github.com>
+Date: Mon, 17 Jul 2017 10:04:37 +0200
+Subject: [PATCH] journald: make sure we retain all stream fds across restarts
+ (#6348)
+
+Currently we set 4096 as maximum for number of stream connections that
+we accept. However maximum number of file descriptors that systemd is
+willing to accept from us is just 1024. This means we can't retain all
+stream connections that we accepted. Hence bump the limit of fds in a
+unit file so that systemd holds open all stream fds while we are
+restarted.
+
+New limit is set to 4224 (4096 + 128).
+
+(cherry picked from commit 3c978aca69e0e43d4dd453437ec9c498ea788795)
+
+Related: #1359939
+---
+ units/systemd-journald.service.in | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/units/systemd-journald.service.in b/units/systemd-journald.service.in
+index c85c34932..0d1ea61fe 100644
+--- a/units/systemd-journald.service.in
++++ b/units/systemd-journald.service.in
+@@ -20,6 +20,7 @@ ExecStart=@rootlibexecdir@/systemd-journald
+ Restart=always
+ RestartSec=0
+ StandardOutput=null
++FileDescriptorStoreMax=4224
+ CapabilityBoundingSet=CAP_SYS_ADMIN CAP_DAC_OVERRIDE CAP_SYS_PTRACE CAP_SYSLOG CAP_AUDIT_CONTROL CAP_AUDIT_READ CAP_CHOWN CAP_DAC_READ_SEARCH CAP_FOWNER CAP_SETUID CAP_SETGID CAP_MAC_OVERRIDE
+ WatchdogSec=3min
+ 
diff --git a/SOURCES/0522-Allow-systemd-tmpfiles-to-set-the-file-directory-att.patch b/SOURCES/0522-Allow-systemd-tmpfiles-to-set-the-file-directory-att.patch
new file mode 100644
index 0000000..1c9c72d
--- /dev/null
+++ b/SOURCES/0522-Allow-systemd-tmpfiles-to-set-the-file-directory-att.patch
@@ -0,0 +1,218 @@
+From 037b80886a6c3acad294aee139d28d1f574d82cc Mon Sep 17 00:00:00 2001
+From: Goffredo Baroncelli <kreijack@inwind.it>
+Date: Mon, 16 Mar 2015 20:33:50 +0100
+Subject: [PATCH] Allow systemd-tmpfiles to set the file/directory attributes
+
+Allow systemd-tmpfiles to set the file/directory attributes, like
+chattr(1) does. Two more commands are added: 'H' and 'h' to set the
+attributes, recursively and not.
+
+(cherry picked from commit 22c3a6cadbc99ad623501db9a928f52f6f84c0c3)
+
+Related: #1299714
+---
+ src/tmpfiles/tmpfiles.c | 150 ++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 150 insertions(+)
+
+diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
+index ed35b8cf0..c8c56c722 100644
+--- a/src/tmpfiles/tmpfiles.c
++++ b/src/tmpfiles/tmpfiles.c
+@@ -40,6 +40,7 @@
+ #include <sys/types.h>
+ #include <sys/param.h>
+ #include <sys/xattr.h>
++#include <linux/fs.h>
+ 
+ #include "log.h"
+ #include "util.h"
+@@ -91,6 +92,8 @@ typedef enum ItemType {
+         RELABEL_PATH = 'z',
+         RECURSIVE_RELABEL_PATH = 'Z',
+         ADJUST_MODE = 'm', /* legacy, 'z' is identical to this */
++        SET_ATTRIB = 'h',
++        RECURSIVE_SET_ATTRIB = 'H',
+ } ItemType;
+ 
+ typedef struct Item {
+@@ -109,12 +112,15 @@ typedef struct Item {
+         usec_t age;
+ 
+         dev_t major_minor;
++        unsigned long attrib_value;
++        unsigned long attrib_mask;
+ 
+         bool uid_set:1;
+         bool gid_set:1;
+         bool mode_set:1;
+         bool age_set:1;
+         bool mask_perms:1;
++        bool attrib_set:1;
+ 
+         bool keep_first_level:1;
+ 
+@@ -817,6 +823,127 @@ static int path_set_acls(Item *item, const char *path) {
+         return r;
+ }
+ 
++#define ALL_ATTRIBS          \
++        FS_NOATIME_FL      | \
++        FS_SYNC_FL         | \
++        FS_DIRSYNC_FL      | \
++        FS_APPEND_FL       | \
++        FS_COMPR_FL        | \
++        FS_NODUMP_FL       | \
++        FS_EXTENT_FL       | \
++        FS_IMMUTABLE_FL    | \
++        FS_JOURNAL_DATA_FL | \
++        FS_SECRM_FL        | \
++        FS_UNRM_FL         | \
++        FS_NOTAIL_FL       | \
++        FS_TOPDIR_FL       | \
++        FS_NOCOW_FL
++
++static int get_attrib_from_arg(Item *item) {
++        static const unsigned attributes[] = {
++                [(uint8_t)'A'] = FS_NOATIME_FL,      /* do not update atime */
++                [(uint8_t)'S'] = FS_SYNC_FL,         /* Synchronous updates */
++                [(uint8_t)'D'] = FS_DIRSYNC_FL,      /* dirsync behaviour (directories only) */
++                [(uint8_t)'a'] = FS_APPEND_FL,       /* writes to file may only append */
++                [(uint8_t)'c'] = FS_COMPR_FL,        /* Compress file */
++                [(uint8_t)'d'] = FS_NODUMP_FL,       /* do not dump file */
++                [(uint8_t)'e'] = FS_EXTENT_FL,       /* Top of directory hierarchies*/
++                [(uint8_t)'i'] = FS_IMMUTABLE_FL,    /* Immutable file */
++                [(uint8_t)'j'] = FS_JOURNAL_DATA_FL, /* Reserved for ext3 */
++                [(uint8_t)'s'] = FS_SECRM_FL,        /* Secure deletion */
++                [(uint8_t)'u'] = FS_UNRM_FL,         /* Undelete */
++                [(uint8_t)'t'] = FS_NOTAIL_FL,       /* file tail should not be merged */
++                [(uint8_t)'T'] = FS_TOPDIR_FL,       /* Top of directory hierarchies*/
++                [(uint8_t)'C'] = FS_NOCOW_FL,        /* Do not cow file */
++        };
++        char *p = item->argument;
++        enum {
++                MODE_ADD,
++                MODE_DEL,
++                MODE_SET
++        } mode = MODE_ADD;
++        unsigned long value = 0, mask = 0;
++
++        if (!p) {
++                log_error("\"%s\": setting ATTR need an argument", item->path);
++                return -EINVAL;
++        }
++
++        if (*p == '+') {
++                mode = MODE_ADD;
++                p++;
++        } else if (*p == '-') {
++                mode = MODE_DEL;
++                p++;
++        } else  if (*p == '=') {
++                mode = MODE_SET;
++                p++;
++        }
++
++        if (!*p && mode != MODE_SET) {
++                log_error("\"%s\": setting ATTR: argument is empty", item->path);
++                return -EINVAL;
++        }
++        for (; *p ; p++) {
++                if ((uint8_t)*p > ELEMENTSOF(attributes) || attributes[(uint8_t)*p] == 0) {
++                        log_error("\"%s\": setting ATTR: unknown attr '%c'", item->path, *p);
++                        return -EINVAL;
++                }
++                if (mode == MODE_ADD || mode == MODE_SET)
++                        value |= attributes[(uint8_t)*p];
++                else
++                        value &= ~attributes[(uint8_t)*p];
++                mask |= attributes[(uint8_t)*p];
++        }
++
++        if (mode == MODE_SET)
++                mask |= ALL_ATTRIBS;
++
++        assert(mask);
++
++        item->attrib_mask = mask;
++        item->attrib_value = value;
++        item->attrib_set = true;
++
++        return 0;
++
++}
++
++static int path_set_attrib(Item *item, const char *path) {
++        _cleanup_close_ int fd = -1;
++        int r;
++        unsigned f;
++        struct stat st;
++
++        /* do nothing */
++        if (item->attrib_mask == 0 || !item->attrib_set)
++                return 0;
++        /*
++         * It is OK to ignore an lstat() error, because the error
++         * will be catch by the open() below anyway
++         */
++        if (lstat(path, &st) == 0 &&
++            !S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode)) {
++                return 0;
++        }
++
++        fd = open(path, O_RDONLY|O_NONBLOCK|O_CLOEXEC);
++
++        if (fd < 0)
++                return log_error_errno(errno, "Cannot open \"%s\": %m", path);
++
++        f = item->attrib_value & item->attrib_mask;
++        if (!S_ISDIR(st.st_mode))
++                f &= ~FS_DIRSYNC_FL;
++        r = change_attr_fd(fd, f, item->attrib_mask);
++        if (r < 0)
++                return log_error_errno(errno,
++                        "Cannot set attrib for \"%s\", value=0x%08lx, mask=0x%08lx: %m",
++                        path, item->attrib_value, item->attrib_mask);
++
++        return 0;
++}
++
+ static int write_one_file(Item *i, const char *path) {
+         _cleanup_close_ int fd = -1;
+         int flags, r = 0;
+@@ -1266,6 +1393,18 @@ static int create_item(Item *i) {
+                 if (r < 0)
+                         return r;
+                 break;
++
++        case SET_ATTRIB:
++                r = glob_item(i, path_set_attrib, false);
++                if (r < 0)
++                        return r;
++                break;
++
++        case RECURSIVE_SET_ATTRIB:
++                r = glob_item(i, path_set_attrib, true);
++                if (r < 0)
++                        return r;
++                break;
+         }
+ 
+         return 0;
+@@ -1712,6 +1851,17 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
+                         return r;
+                 break;
+ 
++        case SET_ATTRIB:
++        case RECURSIVE_SET_ATTRIB:
++                if (!i.argument) {
++                        log_error("[%s:%u] Set attrib requires argument.", fname, line);
++                        return -EBADMSG;
++                }
++                r = get_attrib_from_arg(&i);
++                if (r < 0)
++                        return r;
++                break;
++
+         default:
+                 log_error("[%s:%u] Unknown command type '%c'.", fname, line, (char) i.type);
+                 return -EBADMSG;
diff --git a/SOURCES/0523-tmpfiles-rework-file-attribute-code.patch b/SOURCES/0523-tmpfiles-rework-file-attribute-code.patch
new file mode 100644
index 0000000..50dee6c
--- /dev/null
+++ b/SOURCES/0523-tmpfiles-rework-file-attribute-code.patch
@@ -0,0 +1,326 @@
+From 3a68810cd6ac23f7107491ab6e1fbd565ed52bf0 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Wed, 8 Apr 2015 22:35:52 +0200
+Subject: [PATCH] tmpfiles: rework file attribute code
+
+- Stick to one type for the flags field: unsigned. This appears to be
+  what the kernel uses, and there's no point in using something else.
+
+- compress the flags array by avoiding sparse entries
+
+- extend some error messages to not use abbreviated words
+
+- avoid TTOCTTOU issues by invoking fstat() after open() when applying
+  file flags
+
+- add explanation why we need to check the file type with fstat().
+
+- don't needlessly abbreviate "attribute" as "attrib", in particually as
+  "chattr" abbreviates it as "attr" rather than "attrib".
+
+(cherry picked from commit 88ec4dfa289cd97496dbb9670365a3d4be13d41c)
+
+Conflicts:
+	src/tmpfiles/tmpfiles.c
+
+Related: #1299714
+---
+ src/tmpfiles/tmpfiles.c | 207 ++++++++++++++++++++++++++----------------------
+ 1 file changed, 114 insertions(+), 93 deletions(-)
+
+diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
+index c8c56c722..800e620bc 100644
+--- a/src/tmpfiles/tmpfiles.c
++++ b/src/tmpfiles/tmpfiles.c
+@@ -92,8 +92,8 @@ typedef enum ItemType {
+         RELABEL_PATH = 'z',
+         RECURSIVE_RELABEL_PATH = 'Z',
+         ADJUST_MODE = 'm', /* legacy, 'z' is identical to this */
+-        SET_ATTRIB = 'h',
+-        RECURSIVE_SET_ATTRIB = 'H',
++        SET_ATTRIBUTE = 'h',
++        RECURSIVE_SET_ATTRIBUTE = 'H',
+ } ItemType;
+ 
+ typedef struct Item {
+@@ -112,15 +112,15 @@ typedef struct Item {
+         usec_t age;
+ 
+         dev_t major_minor;
+-        unsigned long attrib_value;
+-        unsigned long attrib_mask;
++        unsigned attribute_value;
++        unsigned attribute_mask;
+ 
+         bool uid_set:1;
+         bool gid_set:1;
+         bool mode_set:1;
+         bool age_set:1;
+         bool mask_perms:1;
+-        bool attrib_set:1;
++        bool attribute_set:1;
+ 
+         bool keep_first_level:1;
+ 
+@@ -823,123 +823,144 @@ static int path_set_acls(Item *item, const char *path) {
+         return r;
+ }
+ 
+-#define ALL_ATTRIBS          \
+-        FS_NOATIME_FL      | \
+-        FS_SYNC_FL         | \
+-        FS_DIRSYNC_FL      | \
+-        FS_APPEND_FL       | \
+-        FS_COMPR_FL        | \
+-        FS_NODUMP_FL       | \
+-        FS_EXTENT_FL       | \
+-        FS_IMMUTABLE_FL    | \
+-        FS_JOURNAL_DATA_FL | \
+-        FS_SECRM_FL        | \
+-        FS_UNRM_FL         | \
+-        FS_NOTAIL_FL       | \
+-        FS_TOPDIR_FL       | \
+-        FS_NOCOW_FL
+-
+-static int get_attrib_from_arg(Item *item) {
+-        static const unsigned attributes[] = {
+-                [(uint8_t)'A'] = FS_NOATIME_FL,      /* do not update atime */
+-                [(uint8_t)'S'] = FS_SYNC_FL,         /* Synchronous updates */
+-                [(uint8_t)'D'] = FS_DIRSYNC_FL,      /* dirsync behaviour (directories only) */
+-                [(uint8_t)'a'] = FS_APPEND_FL,       /* writes to file may only append */
+-                [(uint8_t)'c'] = FS_COMPR_FL,        /* Compress file */
+-                [(uint8_t)'d'] = FS_NODUMP_FL,       /* do not dump file */
+-                [(uint8_t)'e'] = FS_EXTENT_FL,       /* Top of directory hierarchies*/
+-                [(uint8_t)'i'] = FS_IMMUTABLE_FL,    /* Immutable file */
+-                [(uint8_t)'j'] = FS_JOURNAL_DATA_FL, /* Reserved for ext3 */
+-                [(uint8_t)'s'] = FS_SECRM_FL,        /* Secure deletion */
+-                [(uint8_t)'u'] = FS_UNRM_FL,         /* Undelete */
+-                [(uint8_t)'t'] = FS_NOTAIL_FL,       /* file tail should not be merged */
+-                [(uint8_t)'T'] = FS_TOPDIR_FL,       /* Top of directory hierarchies*/
+-                [(uint8_t)'C'] = FS_NOCOW_FL,        /* Do not cow file */
++#define ATTRIBUTES_ALL                          \
++        (FS_NOATIME_FL      |                   \
++         FS_SYNC_FL         |                   \
++         FS_DIRSYNC_FL      |                   \
++         FS_APPEND_FL       |                   \
++         FS_COMPR_FL        |                   \
++         FS_NODUMP_FL       |                   \
++         FS_EXTENT_FL       |                   \
++         FS_IMMUTABLE_FL    |                   \
++         FS_JOURNAL_DATA_FL |                   \
++         FS_SECRM_FL        |                   \
++         FS_UNRM_FL         |                   \
++         FS_NOTAIL_FL       |                   \
++         FS_TOPDIR_FL       |                   \
++         FS_NOCOW_FL)
++
++static int get_attribute_from_arg(Item *item) {
++
++        static const struct {
++                char character;
++                unsigned value;
++        } attributes[] = {
++                { 'A', FS_NOATIME_FL },      /* do not update atime */
++                { 'S', FS_SYNC_FL },         /* Synchronous updates */
++                { 'D', FS_DIRSYNC_FL },      /* dirsync behaviour (directories only) */
++                { 'a', FS_APPEND_FL },       /* writes to file may only append */
++                { 'c', FS_COMPR_FL },        /* Compress file */
++                { 'd', FS_NODUMP_FL },       /* do not dump file */
++                { 'e', FS_EXTENT_FL },       /* Top of directory hierarchies*/
++                { 'i', FS_IMMUTABLE_FL },    /* Immutable file */
++                { 'j', FS_JOURNAL_DATA_FL }, /* Reserved for ext3 */
++                { 's', FS_SECRM_FL },        /* Secure deletion */
++                { 'u', FS_UNRM_FL },         /* Undelete */
++                { 't', FS_NOTAIL_FL },       /* file tail should not be merged */
++                { 'T', FS_TOPDIR_FL },       /* Top of directory hierarchies*/
++                { 'C', FS_NOCOW_FL },        /* Do not cow file */
+         };
+-        char *p = item->argument;
++
+         enum {
+                 MODE_ADD,
+                 MODE_DEL,
+                 MODE_SET
+         } mode = MODE_ADD;
+-        unsigned long value = 0, mask = 0;
+ 
+-        if (!p) {
+-                log_error("\"%s\": setting ATTR need an argument", item->path);
+-                return -EINVAL;
+-        }
++        unsigned value = 0, mask = 0;
++        const char *p;
+ 
+-        if (*p == '+') {
+-                mode = MODE_ADD;
+-                p++;
+-        } else if (*p == '-') {
+-                mode = MODE_DEL;
+-                p++;
+-        } else  if (*p == '=') {
+-                mode = MODE_SET;
+-                p++;
++        assert(item);
++
++        p = item->argument;
++        if (p) {
++                if (*p == '+') {
++                        mode = MODE_ADD;
++                        p++;
++                } else if (*p == '-') {
++                        mode = MODE_DEL;
++                        p++;
++                } else  if (*p == '=') {
++                        mode = MODE_SET;
++                        p++;
++                }
+         }
+ 
+-        if (!*p && mode != MODE_SET) {
+-                log_error("\"%s\": setting ATTR: argument is empty", item->path);
++        if (isempty(p) && mode != MODE_SET) {
++                log_error("Setting file attribute on '%s' needs an attribute specification.", item->path);
+                 return -EINVAL;
+         }
+-        for (; *p ; p++) {
+-                if ((uint8_t)*p > ELEMENTSOF(attributes) || attributes[(uint8_t)*p] == 0) {
+-                        log_error("\"%s\": setting ATTR: unknown attr '%c'", item->path, *p);
++
++        for (; p && *p ; p++) {
++                unsigned i, v;
++
++                for (i = 0; i < ELEMENTSOF(attributes); i++)
++                        if (*p == attributes[i].character)
++                                break;
++
++                if (i >= ELEMENTSOF(attributes)) {
++                        log_error("Unknown file attribute '%c' on '%s'.", *p, item->path);
+                         return -EINVAL;
+                 }
++
++                v = attributes[i].value;
++
+                 if (mode == MODE_ADD || mode == MODE_SET)
+-                        value |= attributes[(uint8_t)*p];
++                        value |= v;
+                 else
+-                        value &= ~attributes[(uint8_t)*p];
+-                mask |= attributes[(uint8_t)*p];
++                        value &= ~v;
++
++                mask |= v;
+         }
+ 
+         if (mode == MODE_SET)
+-                mask |= ALL_ATTRIBS;
++                mask |= ATTRIBUTES_ALL;
+ 
+-        assert(mask);
++        assert(mask != 0);
+ 
+-        item->attrib_mask = mask;
+-        item->attrib_value = value;
+-        item->attrib_set = true;
++        item->attribute_mask = mask;
++        item->attribute_value = value;
++        item->attribute_set = true;
+ 
+         return 0;
+-
+ }
+ 
+-static int path_set_attrib(Item *item, const char *path) {
++static int path_set_attribute(Item *item, const char *path) {
+         _cleanup_close_ int fd = -1;
+-        int r;
+-        unsigned f;
+         struct stat st;
++        unsigned f;
++        int r;
+ 
+-        /* do nothing */
+-        if (item->attrib_mask == 0 || !item->attrib_set)
+-                return 0;
+-        /*
+-         * It is OK to ignore an lstat() error, because the error
+-         * will be catch by the open() below anyway
+-         */
+-        if (lstat(path, &st) == 0 &&
+-            !S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode)) {
++        if (!item->attribute_set || item->attribute_mask == 0)
+                 return 0;
+-        }
+ 
+         fd = open(path, O_RDONLY|O_NONBLOCK|O_CLOEXEC);
+ 
+         if (fd < 0)
+-                return log_error_errno(errno, "Cannot open \"%s\": %m", path);
++                return log_error_errno(errno, "Cannot open '%s': %m", path);
+ 
+-        f = item->attrib_value & item->attrib_mask;
++        if (fstat(fd, &st) < 0)
++                return log_error_errno(errno, "Cannot stat '%s': %m", path);
++
++        /* Issuing the file attribute ioctls on device nodes is not
++         * safe, as that will be delivered to the drivers, not the
++         * file system containing the device node. */
++        if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode)) {
++                log_error("Setting file flags is only supported on regular files and directories, cannot set on '%s'.", path);
++                return -EINVAL;
++        }
++
++        f = item->attribute_value & item->attribute_mask;
++
++        /* Mask away directory-specific flags */
+         if (!S_ISDIR(st.st_mode))
+                 f &= ~FS_DIRSYNC_FL;
+-        r = change_attr_fd(fd, f, item->attrib_mask);
++
++        r = chattr_fd(fd, f, item->attribute_mask);
+         if (r < 0)
+-                return log_error_errno(errno,
+-                        "Cannot set attrib for \"%s\", value=0x%08lx, mask=0x%08lx: %m",
+-                        path, item->attrib_value, item->attrib_mask);
++                return log_error_errno(r,
++                        "Cannot set file attribute for '%s', value=0x%08x, mask=0x%08x: %m",
++                        path, item->attribute_value, item->attribute_mask);
+ 
+         return 0;
+ }
+@@ -1394,14 +1415,14 @@ static int create_item(Item *i) {
+                         return r;
+                 break;
+ 
+-        case SET_ATTRIB:
+-                r = glob_item(i, path_set_attrib, false);
++        case SET_ATTRIBUTE:
++                r = glob_item(i, path_set_attribute, false);
+                 if (r < 0)
+                         return r;
+                 break;
+ 
+-        case RECURSIVE_SET_ATTRIB:
+-                r = glob_item(i, path_set_attrib, true);
++        case RECURSIVE_SET_ATTRIBUTE:
++                r = glob_item(i, path_set_attribute, true);
+                 if (r < 0)
+                         return r;
+                 break;
+@@ -1851,13 +1872,13 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
+                         return r;
+                 break;
+ 
+-        case SET_ATTRIB:
+-        case RECURSIVE_SET_ATTRIB:
++        case SET_ATTRIBUTE:
++        case RECURSIVE_SET_ATTRIBUTE:
+                 if (!i.argument) {
+-                        log_error("[%s:%u] Set attrib requires argument.", fname, line);
++                        log_error("[%s:%u] Set file attribute requires argument.", fname, line);
+                         return -EBADMSG;
+                 }
+-                r = get_attrib_from_arg(&i);
++                r = get_attribute_from_arg(&i);
+                 if (r < 0)
+                         return r;
+                 break;
diff --git a/SOURCES/0524-tmpfiles-warn-if-we-get-an-argument-on-lines-that-do.patch b/SOURCES/0524-tmpfiles-warn-if-we-get-an-argument-on-lines-that-do.patch
new file mode 100644
index 0000000..bbd9364
--- /dev/null
+++ b/SOURCES/0524-tmpfiles-warn-if-we-get-an-argument-on-lines-that-do.patch
@@ -0,0 +1,40 @@
+From 95ee3c8f1ef9408543c962af5f21e01ccef544e1 Mon Sep 17 00:00:00 2001
+From: Michal Sekletar <msekleta@redhat.com>
+Date: Thu, 7 Sep 2017 15:46:24 +0200
+Subject: [PATCH] tmpfiles: warn if we get an argument on lines that don't take
+ any
+
+(cherry picked from commit c82500c6fb37a25bc3c4b1e0be11a90a395619d9)
+
+Related: #1299714
+---
+ src/tmpfiles/tmpfiles.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
+index 800e620bc..70e0cc2fa 100644
+--- a/src/tmpfiles/tmpfiles.c
++++ b/src/tmpfiles/tmpfiles.c
+@@ -1788,8 +1788,6 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
+ 
+         switch (i.type) {
+ 
+-        case CREATE_FILE:
+-        case TRUNCATE_FILE:
+         case CREATE_DIRECTORY:
+         case CREATE_SUBVOLUME:
+         case EMPTY_DIRECTORY:
+@@ -1802,6 +1800,13 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
+         case ADJUST_MODE:
+         case RELABEL_PATH:
+         case RECURSIVE_RELABEL_PATH:
++                if (i.argument)
++                        log_warning("[%s:%u] %c lines don't take argument field, ignoring.", fname, line, i.type);
++
++                break;
++
++        case CREATE_FILE:
++        case TRUNCATE_FILE:
+                 break;
+ 
+         case CREATE_SYMLINK:
diff --git a/SOURCES/0525-tmpfiles-substitute-specifiers-in-arguments-for-writ.patch b/SOURCES/0525-tmpfiles-substitute-specifiers-in-arguments-for-writ.patch
new file mode 100644
index 0000000..a4ba787
--- /dev/null
+++ b/SOURCES/0525-tmpfiles-substitute-specifiers-in-arguments-for-writ.patch
@@ -0,0 +1,207 @@
+From d23386f61d810dab77e9d9d9130adbd826ea823f Mon Sep 17 00:00:00 2001
+From: Michal Sekletar <msekleta@redhat.com>
+Date: Thu, 7 Sep 2017 15:49:08 +0200
+Subject: [PATCH] tmpfiles: substitute % specifiers in arguments for writing
+ files and xattrs
+
+(cherry-picked from commit bd550f78eb261c757cbff85acdb55563c56521f2)
+
+Related: #1299714
+---
+ src/tmpfiles/tmpfiles.c | 79 ++++++++++++++++++++++++++-----------------------
+ 1 file changed, 42 insertions(+), 37 deletions(-)
+
+diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
+index 70e0cc2fa..ddb274fce 100644
+--- a/src/tmpfiles/tmpfiles.c
++++ b/src/tmpfiles/tmpfiles.c
+@@ -151,6 +151,14 @@ static const char conf_file_dirs[] = CONF_DIRS_NULSTR("tmpfiles");
+ static Hashmap *items = NULL, *globs = NULL;
+ static Set *unix_sockets = NULL;
+ 
++static const Specifier specifier_table[] = {
++        { 'm', specifier_machine_id, NULL },
++        { 'b', specifier_boot_id, NULL },
++        { 'H', specifier_host_name, NULL },
++        { 'v', specifier_kernel_release, NULL },
++        {}
++};
++
+ static bool needs_glob(ItemType t) {
+         return IN_SET(t,
+                       WRITE_FILE,
+@@ -657,8 +665,7 @@ static int path_set_perms(Item *i, const char *path) {
+         return label_fix(path, false, false);
+ }
+ 
+-static int get_xattrs_from_arg(Item *i) {
+-        char *xattr;
++static int parse_xattrs_from_arg(Item *i) {
+         const char *p;
+         int r;
+ 
+@@ -667,35 +674,37 @@ static int get_xattrs_from_arg(Item *i) {
+ 
+         p = i->argument;
+ 
+-        while ((r = unquote_first_word(&p, &xattr, false)) > 0) {
+-                _cleanup_free_ char *tmp = NULL, *name = NULL,
+-                        *value = NULL, *value2 = NULL, *_xattr = xattr;
++        for (;;) {
++                _cleanup_free_ char *name = NULL, *value = NULL, *xattr = NULL, *xattr_replaced = NULL;
++
++                r = unquote_first_word(&p, &xattr, false);
++                if (r < 0)
++                        log_warning_errno(r, "Failed to parse extended attribute '%s', ignoring: %m", p);
++                if (r <= 0)
++                        break;
++
++                r = specifier_printf(xattr, specifier_table, NULL, &xattr_replaced);
++                if (r < 0)
++                        return log_error_errno(r, "Failed to replace specifiers in extended attribute '%s': %m", xattr);
+ 
+-                r = split_pair(xattr, "=", &name, &value);
++                r = split_pair(xattr_replaced, "=", &name, &value);
+                 if (r < 0) {
+                         log_warning("Illegal xattr found: \"%s\" - ignoring.", xattr);
+                         continue;
+                 }
+ 
+-                if (strempty(name) || strempty(value)) {
+-                        log_warning("Malformed xattr found: \"%s\" - ignoring.", xattr);
++                if (isempty(name) || isempty(value)) {
++                        log_warning("Malformed extended attribute found, ignoring: %s", xattr);
+                         continue;
+                 }
+ 
+-                tmp = unquote(value, "\"");
+-                if (!tmp)
+-                        return log_oom();
+-
+-                value2 = cunescape(tmp);
+-                if (!value2)
++                if (strv_push_pair(&i->xattrs, name, value) < 0)
+                         return log_oom();
+ 
+-                if (strv_push_pair(&i->xattrs, name, value2) < 0)
+-                        return log_oom();
+-                name = value2 = NULL;
++                name = value = NULL;
+         }
+ 
+-        return r;
++        return 0;
+ }
+ 
+ static int path_set_xattrs(Item *i, const char *path) {
+@@ -708,17 +717,16 @@ static int path_set_xattrs(Item *i, const char *path) {
+                 int n;
+ 
+                 n = strlen(*value);
+-                log_debug("\"%s\": setting xattr \"%s=%s\"", path, *name, *value);
++                log_debug("Setting extended attribute '%s=%s' on %s.", *name, *value, path);
+                 if (lsetxattr(path, *name, *value, n, 0) < 0) {
+-                        log_error("Setting extended attribute %s=%s on %s failed: %m",
+-                                  *name, *value, path);
++                        log_error("Setting extended attribute %s=%s on %s failed: %m", *name, *value, path);
+                         return -errno;
+                 }
+         }
+         return 0;
+ }
+ 
+-static int get_acls_from_arg(Item *item) {
++static int parse_acls_from_arg(Item *item) {
+ #ifdef HAVE_ACL
+         int r;
+ 
+@@ -726,6 +734,7 @@ static int get_acls_from_arg(Item *item) {
+ 
+         /* If force (= modify) is set, we will not modify the acl
+          * afterwards, so the mask can be added now if necessary. */
++
+         r = parse_acl(item->argument, &item->acl_access, &item->acl_default, !item->force);
+         if (r < 0)
+                 log_warning_errno(r, "Failed to parse ACL \"%s\": %m. Ignoring",
+@@ -839,7 +848,7 @@ static int path_set_acls(Item *item, const char *path) {
+          FS_TOPDIR_FL       |                   \
+          FS_NOCOW_FL)
+ 
+-static int get_attribute_from_arg(Item *item) {
++static int parse_attribute_from_arg(Item *item) {
+ 
+         static const struct {
+                 char character;
+@@ -993,7 +1002,7 @@ static int write_one_file(Item *i, const char *path) {
+         }
+ 
+         if (i->argument) {
+-                _cleanup_free_ char *unescaped;
++                _cleanup_free_ char *unescaped = NULL, *replaced = NULL;
+ 
+                 log_debug("%s to \"%s\".",
+                           i->type == CREATE_FILE ? "Appending" : "Writing", path);
+@@ -1002,7 +1011,11 @@ static int write_one_file(Item *i, const char *path) {
+                 if (!unescaped)
+                         return log_oom();
+ 
+-                r = loop_write(fd, unescaped, strlen(unescaped), false);
++                r = specifier_printf(unescaped, specifier_table, NULL, &replaced);
++                if (r < 0)
++                        return log_error_errno(r, "Failed to replace specifiers in parameter to write '%s': %m", unescaped);
++
++                r = loop_write(fd, replaced, strlen(replaced), false);
+                 if (r < 0)
+                         return log_error_errno(r, "Failed to write file \"%s\": %m", path);
+         } else
+@@ -1712,14 +1725,6 @@ static bool should_include_path(const char *path) {
+ 
+ static int parse_line(const char *fname, unsigned line, const char *buffer) {
+ 
+-        static const Specifier specifier_table[] = {
+-                { 'm', specifier_machine_id, NULL },
+-                { 'b', specifier_boot_id, NULL },
+-                { 'H', specifier_host_name, NULL },
+-                { 'v', specifier_kernel_release, NULL },
+-                {}
+-        };
+-
+         _cleanup_free_ char *action = NULL, *mode = NULL, *user = NULL, *group = NULL, *age = NULL, *path = NULL;
+         _cleanup_(item_free_contents) Item i = {};
+         ItemArray *existing;
+@@ -1801,7 +1806,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
+         case RELABEL_PATH:
+         case RECURSIVE_RELABEL_PATH:
+                 if (i.argument)
+-                        log_warning("[%s:%u] %c lines don't take argument field, ignoring.", fname, line, i.type);
++                        log_warning("[%s:%u] %c lines don't take argument fields, ignoring.", fname, line, i.type);
+ 
+                 break;
+ 
+@@ -1861,7 +1866,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
+                         log_error("[%s:%u] Set extended attribute requires argument.", fname, line);
+                         return -EBADMSG;
+                 }
+-                r = get_xattrs_from_arg(&i);
++                r = parse_xattrs_from_arg(&i);
+                 if (r < 0)
+                         return r;
+                 break;
+@@ -1872,7 +1877,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
+                         log_error("[%s:%u] Set ACLs requires argument.", fname, line);
+                         return -EBADMSG;
+                 }
+-                r = get_acls_from_arg(&i);
++                r = parse_acls_from_arg(&i);
+                 if (r < 0)
+                         return r;
+                 break;
+@@ -1883,7 +1888,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
+                         log_error("[%s:%u] Set file attribute requires argument.", fname, line);
+                         return -EBADMSG;
+                 }
+-                r = get_attribute_from_arg(&i);
++                r = parse_attribute_from_arg(&i);
+                 if (r < 0)
+                         return r;
+                 break;
diff --git a/SOURCES/0526-btrfs-util-introduce-btrfs_is_filesystem-and-make-us.patch b/SOURCES/0526-btrfs-util-introduce-btrfs_is_filesystem-and-make-us.patch
new file mode 100644
index 0000000..1b4ed93
--- /dev/null
+++ b/SOURCES/0526-btrfs-util-introduce-btrfs_is_filesystem-and-make-us.patch
@@ -0,0 +1,105 @@
+From 81f0a57bed6e03eeaa24443d16555c7f5d20ee1a Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Wed, 22 Apr 2015 13:08:19 +0200
+Subject: [PATCH] btrfs-util: introduce btrfs_is_filesystem() and make use of
+ it where appropriate
+
+Let's unify the code that checks whether an fd is on btrfs a bit.
+
+(Also, rename btrfs_is_snapshot() to btrfs_is_subvol(), since that's
+usually how this is referred to in our code)
+
+(cherry picked from commit 21222ea5cdec65fa30a75bd5a78475459075b946)
+
+Related: #1299714
+---
+ src/shared/btrfs-util.c    | 23 ++++++++++++++++-------
+ src/shared/btrfs-util.h    |  3 ++-
+ src/shared/machine-image.c |  9 ++++-----
+ 3 files changed, 22 insertions(+), 13 deletions(-)
+
+diff --git a/src/shared/btrfs-util.c b/src/shared/btrfs-util.c
+index b34ac8b15..52a214349 100644
+--- a/src/shared/btrfs-util.c
++++ b/src/shared/btrfs-util.c
+@@ -83,10 +83,22 @@ static int extract_subvolume_name(const char *path, const char **subvolume) {
+         return 0;
+ }
+ 
+-int btrfs_is_snapshot(int fd) {
+-        struct stat st;
++int btrfs_is_filesystem(int fd) {
+         struct statfs sfs;
+ 
++        assert(fd >= 0);
++
++        if (fstatfs(fd, &sfs) < 0)
++                return -errno;
++
++        return F_TYPE_EQUAL(sfs.f_type, BTRFS_SUPER_MAGIC);
++}
++
++int btrfs_is_subvol(int fd) {
++        struct stat st;
++
++        assert(fd >= 0);
++
+         /* On btrfs subvolumes always have the inode 256 */
+ 
+         if (fstat(fd, &st) < 0)
+@@ -95,10 +107,7 @@ int btrfs_is_snapshot(int fd) {
+         if (!S_ISDIR(st.st_mode) || st.st_ino != 256)
+                 return 0;
+ 
+-        if (fstatfs(fd, &sfs) < 0)
+-                return -errno;
+-
+-        return F_TYPE_EQUAL(sfs.f_type, BTRFS_SUPER_MAGIC);
++        return btrfs_is_filesystem(fd);
+ }
+ 
+ int btrfs_subvol_snapshot(const char *old_path, const char *new_path, bool read_only, bool fallback_copy) {
+@@ -115,7 +124,7 @@ int btrfs_subvol_snapshot(const char *old_path, const char *new_path, bool read_
+         if (old_fd < 0)
+                 return -errno;
+ 
+-        r = btrfs_is_snapshot(old_fd);
++        r = btrfs_is_subvol(old_fd);
+         if (r < 0)
+                 return r;
+         if (r == 0) {
+diff --git a/src/shared/btrfs-util.h b/src/shared/btrfs-util.h
+index 1b9c142e5..1315def87 100644
+--- a/src/shared/btrfs-util.h
++++ b/src/shared/btrfs-util.h
+@@ -43,7 +43,8 @@ typedef struct BtrfsQuotaInfo {
+         uint64_t exclusive_max;
+ } BtrfsQuotaInfo;
+ 
+-int btrfs_is_snapshot(int fd);
++int btrfs_is_filesystem(int fd);
++int btrfs_is_subvol(int fd);
+ 
+ int btrfs_subvol_make(const char *path);
+ int btrfs_subvol_make_label(const char *path);
+diff --git a/src/shared/machine-image.c b/src/shared/machine-image.c
+index c02ee814c..256622928 100644
+--- a/src/shared/machine-image.c
++++ b/src/shared/machine-image.c
+@@ -136,12 +136,11 @@ static int image_make(
+ 
+                 /* btrfs subvolumes have inode 256 */
+                 if (st.st_ino == 256) {
+-                        struct statfs sfs;
+ 
+-                        if (fstatfs(fd, &sfs) < 0)
+-                                return -errno;
+-
+-                        if (F_TYPE_EQUAL(sfs.f_type, BTRFS_SUPER_MAGIC)) {
++                        r = btrfs_is_filesystem(fd);
++                        if (r < 0)
++                                return r;
++                        if (r) {
+                                 BtrfsSubvolInfo info;
+                                 BtrfsQuotaInfo quota;
+ 
diff --git a/SOURCES/0527-journal-don-t-force-FS_NOCOW_FL-on-new-journal-files.patch b/SOURCES/0527-journal-don-t-force-FS_NOCOW_FL-on-new-journal-files.patch
new file mode 100644
index 0000000..ce36900
--- /dev/null
+++ b/SOURCES/0527-journal-don-t-force-FS_NOCOW_FL-on-new-journal-files.patch
@@ -0,0 +1,86 @@
+From 245ad27530ae9e99242ebfa1631bd7fc8f66a59c Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Wed, 22 Apr 2015 13:20:49 +0200
+Subject: [PATCH] journal: don't force FS_NOCOW_FL on new journal files, but
+ warn if it is missing
+
+This way users have the freedom to set or unset the FS_NOCOW_FL flag on
+their journal files by setting it on the journal directory. Since our
+default tmpfiles configuration now sets this flag on the directory the
+flag is set by default on new files, however people can opt-out of this
+by masking the tmpfiles file for it.
+
+(cherry picked from commit fc68c92973e5437ee0489c1bc80d80f0a7b6ca0b)
+
+Conflicts:
+	src/journal/journal-file.c
+
+Resolves: #1299714
+---
+ src/journal/journal-file.c | 46 ++++++++++++++++++++++++++++++++++++----------
+ 1 file changed, 36 insertions(+), 10 deletions(-)
+
+diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c
+index 8034b771d..0fd59ec07 100644
+--- a/src/journal/journal-file.c
++++ b/src/journal/journal-file.c
+@@ -2543,6 +2543,41 @@ void journal_file_print_header(JournalFile *f) {
+                 printf("Disk usage: %s\n", format_bytes(bytes, sizeof(bytes), (off_t) st.st_blocks * 512ULL));
+ }
+ 
++static int journal_file_warn_btrfs(JournalFile *f) {
++        unsigned attrs;
++        int r;
++
++        assert(f);
++
++        /* Before we write anything, check if the COW logic is turned
++         * off on btrfs. Given our write pattern that is quite
++         * unfriendly to COW file systems this should greatly improve
++         * performance on COW file systems, such as btrfs, at the
++         * expense of data integrity features (which shouldn't be too
++         * bad, given that we do our own checksumming). */
++
++        r = btrfs_is_filesystem(f->fd);
++        if (r < 0)
++                return log_warning_errno(r, "Failed to determine if journal is on btrfs: %m");
++        if (!r)
++                return 0;
++
++        r = read_attr_fd(f->fd, &attrs);
++        if (r < 0)
++                return log_warning_errno(r, "Failed to read file attributes: %m");
++
++        if (attrs & FS_NOCOW_FL) {
++                log_debug("Detected btrfs file system with copy-on-write disabled, all is good.");
++                return 0;
++        }
++
++        log_notice("Creating journal file %s on a btrfs file system, and copy-on-write is enabled. "
++                   "This is likely to slow down journal access substantially, please consider turning "
++                   "off the copy-on-write file attribute on the journal directory, using chattr +C.", f->path);
++
++        return 1;
++}
++
+ int journal_file_open(
+                 const char *fname,
+                 int flags,
+@@ -2623,16 +2658,7 @@ int journal_file_open(
+ 
+         if (f->last_stat.st_size == 0 && f->writable) {
+ 
+-                /* Before we write anything, turn off COW logic. Given
+-                 * our write pattern that is quite unfriendly to COW
+-                 * file systems this should greatly improve
+-                 * performance on COW file systems, such as btrfs, at
+-                 * the expense of data integrity features (which
+-                 * shouldn't be too bad, given that we do our own
+-                 * checksumming). */
+-                r = chattr_fd(f->fd, true, FS_NOCOW_FL);
+-                if (r < 0 && r != -ENOTTY)
+-                        log_warning_errno(r, "Failed to set file attributes: %m");
++                (void) journal_file_warn_btrfs(f);
+ 
+                 /* Let's attach the creation time to the journal file,
+                  * so that the vacuuming code knows the age of this
diff --git a/SOURCES/0528-tmpfiles-Add-C-attrib-to-the-journal-files-directori.patch b/SOURCES/0528-tmpfiles-Add-C-attrib-to-the-journal-files-directori.patch
new file mode 100644
index 0000000..0aeb0b1
--- /dev/null
+++ b/SOURCES/0528-tmpfiles-Add-C-attrib-to-the-journal-files-directori.patch
@@ -0,0 +1,64 @@
+From 3740b7a6d246a5860c8f1d96504bbf00692447e0 Mon Sep 17 00:00:00 2001
+From: Goffredo Baroncelli <kreijack@inwind.it>
+Date: Sun, 12 Apr 2015 20:30:28 +0200
+Subject: [PATCH] tmpfiles: Add +C attrib to the journal files directories
+
+Add the +C file attribute (NOCOW) to the journal directories, so that
+the flag is inherited automatically for new journal files created in
+them. The journal write pattern is problematic on btrfs file systems as
+it results in badly fragmented files when copy-on-write (COW) is used:
+the performances decreases substantially over time.
+
+To avoid this issue, this tmpfile.d snippet sets the NOCOW attribute to
+the journal files directories, so newly created journal files inherit
+the NCOOW attribute that disables copy-on-write.
+
+Be aware that the NOCOW file attribute also disables btrfs checksumming
+for these files, and thus prevents btrfs from rebuilding corrupted files
+on a RAID filesystem.
+
+In a single disk filesystems (or filesystems without redundancy) it is
+safe to use the NOCOW flags without drawbacks, since the journal files
+contain their own checksumming.
+
+(cherry picked from commit 3a92e4ba470611ceec6693640b05eb248d62e32d)
+
+Related: #1299714
+---
+ tmpfiles.d/journal-nocow.conf | 27 +++++++++++++++++++++++++++
+ 1 file changed, 27 insertions(+)
+ create mode 100644 tmpfiles.d/journal-nocow.conf
+
+diff --git a/tmpfiles.d/journal-nocow.conf b/tmpfiles.d/journal-nocow.conf
+new file mode 100644
+index 000000000..e7938c891
+--- /dev/null
++++ b/tmpfiles.d/journal-nocow.conf
+@@ -0,0 +1,27 @@
++#  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.
++
++# See tmpfiles.d(5) for details
++
++# Set the NOCOW attribute for directories of journal files. This flag
++# is inheredited by their new files and sub-directories. Matters only
++# for btrfs filesystems.
++#
++# WARNING: Enabling the NOCOW attribute improves journal performance
++#     substantially, but also disables the btrfs checksum logic. In
++#     btrfs RAID filesystems the checksums are needed for rebuilding
++#     corrupted files. Without checksums such rebuilds are not
++#     possible.
++#
++# In a single-disk filesystem (or a filesystem without redundancy)
++# enabling the NOCOW attribute for journal files is safe, because
++# they have their own checksums and a rebuilding wouldn't be possible
++# in any case.
++
++h /var/log/journal - - - - +C
++h /var/log/journal/%m - - - - +C
++h /var/log/journal/remote - - - - +C
diff --git a/SOURCES/0529-Revert-path-util-make-use-of-mnt_id-field-exported-i.patch b/SOURCES/0529-Revert-path-util-make-use-of-mnt_id-field-exported-i.patch
new file mode 100644
index 0000000..c4e2bc0
--- /dev/null
+++ b/SOURCES/0529-Revert-path-util-make-use-of-mnt_id-field-exported-i.patch
@@ -0,0 +1,553 @@
+From f3d485e1034cdea60cab3c257e340dd9b3e48fc1 Mon Sep 17 00:00:00 2001
+From: Lukas Nykryn <lnykryn@redhat.com>
+Date: Mon, 18 Sep 2017 10:13:05 +0200
+Subject: [PATCH] Revert "path-util: make use of "mnt_id" field exported in
+ /proc/self/fdinfo/<fd>"
+
+This reverts commit f63b66b6347a8d8e5e6930a939d1997bfd8e2e7c.
+This implementation was not working becuase of misbehaving
+canonicalize_file_name.
+
+Related: #1472439
+---
+ src/core/automount.c                        |   2 +-
+ src/core/machine-id-setup.c                 |   2 +-
+ src/core/mount-setup.c                      |   2 +-
+ src/efi-boot-generator/efi-boot-generator.c |   2 +-
+ src/gpt-auto-generator/gpt-auto-generator.c |   2 +-
+ src/login/logind-user.c                     |   2 +-
+ src/nspawn/nspawn.c                         |  10 +-
+ src/shared/cgroup-util.c                    |   2 +-
+ src/shared/condition.c                      |   2 +-
+ src/shared/path-util.c                      | 209 ++++++----------------------
+ src/shared/path-util.h                      |   3 +-
+ src/test/test-path-util.c                   |  66 +--------
+ 12 files changed, 62 insertions(+), 242 deletions(-)
+
+diff --git a/src/core/automount.c b/src/core/automount.c
+index eedd9b824..4e066613d 100644
+--- a/src/core/automount.c
++++ b/src/core/automount.c
+@@ -749,7 +749,7 @@ static int automount_start(Unit *u) {
+         assert(a);
+         assert(a->state == AUTOMOUNT_DEAD || a->state == AUTOMOUNT_FAILED);
+ 
+-        if (path_is_mount_point(a->where, 0)) {
++        if (path_is_mount_point(a->where, false)) {
+                 log_unit_error(u->id,
+                                "Path %s is already a mount point, refusing start for %s",
+                                a->where, u->id);
+diff --git a/src/core/machine-id-setup.c b/src/core/machine-id-setup.c
+index 1121d373f..d00a53246 100644
+--- a/src/core/machine-id-setup.c
++++ b/src/core/machine-id-setup.c
+@@ -203,7 +203,7 @@ int machine_id_commit(const char *root) {
+                 etc_machine_id = path_kill_slashes(x);
+         }
+ 
+-        r = path_is_mount_point(etc_machine_id, 0);
++        r = path_is_mount_point(etc_machine_id, false);
+         if (r < 0)
+                 return log_error_errno(r, "Failed to determine whether %s is a mount point: %m", etc_machine_id);
+         if (r == 0) {
+diff --git a/src/core/mount-setup.c b/src/core/mount-setup.c
+index 2b8fbab1a..521545e5c 100644
+--- a/src/core/mount-setup.c
++++ b/src/core/mount-setup.c
+@@ -160,7 +160,7 @@ static int mount_one(const MountPoint *p, bool relabel) {
+         if (relabel)
+                 label_fix(p->where, true, true);
+ 
+-        r = path_is_mount_point(p->where, AT_SYMLINK_FOLLOW);
++        r = path_is_mount_point(p->where, true);
+         if (r < 0)
+                 return r;
+ 
+diff --git a/src/efi-boot-generator/efi-boot-generator.c b/src/efi-boot-generator/efi-boot-generator.c
+index 5492b1994..b3ff3a8b7 100644
+--- a/src/efi-boot-generator/efi-boot-generator.c
++++ b/src/efi-boot-generator/efi-boot-generator.c
+@@ -69,7 +69,7 @@ int main(int argc, char *argv[]) {
+                 return EXIT_SUCCESS;
+         }
+ 
+-        if (path_is_mount_point("/boot", AT_SYMLINK_FOLLOW) <= 0 &&
++        if (path_is_mount_point("/boot", true) <= 0 &&
+             dir_is_empty("/boot") <= 0) {
+                 log_debug("/boot already populated, exiting.");
+                 return EXIT_SUCCESS;
+diff --git a/src/gpt-auto-generator/gpt-auto-generator.c b/src/gpt-auto-generator/gpt-auto-generator.c
+index d7b047118..00a2141a5 100644
+--- a/src/gpt-auto-generator/gpt-auto-generator.c
++++ b/src/gpt-auto-generator/gpt-auto-generator.c
+@@ -299,7 +299,7 @@ static int probe_and_add_mount(
+         assert(where);
+         assert(description);
+ 
+-        if (path_is_mount_point(where, AT_SYMLINK_FOLLOW) <= 0 &&
++        if (path_is_mount_point(where, true) <= 0 &&
+             dir_is_empty(where) <= 0) {
+                 log_debug("%s already populated, ignoring.", where);
+                 return 0;
+diff --git a/src/login/logind-user.c b/src/login/logind-user.c
+index 912c50ebd..4298704ce 100644
+--- a/src/login/logind-user.c
++++ b/src/login/logind-user.c
+@@ -320,7 +320,7 @@ static int user_mkdir_runtime_path(User *u) {
+         } else
+                 p = u->runtime_path;
+ 
+-        if (path_is_mount_point(p, 0) <= 0) {
++        if (path_is_mount_point(p, false) <= 0) {
+                 _cleanup_free_ char *t = NULL;
+ 
+                 (void) mkdir(p, 0700);
+diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
+index a90a3a5d7..ea365b3f9 100644
+--- a/src/nspawn/nspawn.c
++++ b/src/nspawn/nspawn.c
+@@ -863,7 +863,7 @@ static int mount_all(const char *dest) {
+                 if (!where)
+                         return log_oom();
+ 
+-                t = path_is_mount_point(where, AT_SYMLINK_FOLLOW);
++                t = path_is_mount_point(where, true);
+                 if (t < 0) {
+                         log_error_errno(t, "Failed to detect whether %s is a mount point: %m", where);
+ 
+@@ -989,7 +989,7 @@ static int mount_cgroup_hierarchy(const char *dest, const char *controller, cons
+ 
+         to = strjoina(dest, "/sys/fs/cgroup/", hierarchy);
+ 
+-        r = path_is_mount_point(to, 0);
++        r = path_is_mount_point(to, false);
+         if (r < 0)
+                 return log_error_errno(r, "Failed to determine if %s is mounted already: %m", to);
+         if (r > 0)
+@@ -1787,7 +1787,7 @@ static int setup_journal(const char *directory) {
+         if (!p || !q)
+                 return log_oom();
+ 
+-        if (path_is_mount_point(p, 0) > 0) {
++        if (path_is_mount_point(p, false) > 0) {
+                 if (arg_link_journal != LINK_AUTO) {
+                         log_error("%s: already a mount point, refusing to use for journal", p);
+                         return -EEXIST;
+@@ -1796,7 +1796,7 @@ static int setup_journal(const char *directory) {
+                 return 0;
+         }
+ 
+-        if (path_is_mount_point(q, 0) > 0) {
++        if (path_is_mount_point(q, false) > 0) {
+                 if (arg_link_journal != LINK_AUTO) {
+                         log_error("%s: already a mount point, refusing to use for journal", q);
+                         return -EEXIST;
+@@ -3665,7 +3665,7 @@ int main(int argc, char *argv[]) {
+                          * the specified is not a mount point we
+                          * create the new snapshot in the parent
+                          * directory, just next to it. */
+-                        r = path_is_mount_point(arg_directory, 0);
++                        r = path_is_mount_point(arg_directory, false);
+                         if (r < 0) {
+                                 log_error_errno(r, "Failed to determine whether directory %s is mount point: %m", arg_directory);
+                                 goto finish;
+diff --git a/src/shared/cgroup-util.c b/src/shared/cgroup-util.c
+index cf085cb5f..c5d9e4bb5 100644
+--- a/src/shared/cgroup-util.c
++++ b/src/shared/cgroup-util.c
+@@ -488,7 +488,7 @@ int cg_get_path(const char *controller, const char *path, const char *suffix, ch
+         if (_unlikely_(!good)) {
+                 int r;
+ 
+-                r = path_is_mount_point("/sys/fs/cgroup", 0);
++                r = path_is_mount_point("/sys/fs/cgroup", false);
+                 if (r <= 0)
+                         return r < 0 ? r : -ENOENT;
+ 
+diff --git a/src/shared/condition.c b/src/shared/condition.c
+index 0d2cd2bc3..796cc520d 100644
+--- a/src/shared/condition.c
++++ b/src/shared/condition.c
+@@ -350,7 +350,7 @@ static int condition_test_path_is_mount_point(Condition *c) {
+         assert(c->parameter);
+         assert(c->type == CONDITION_PATH_IS_MOUNT_POINT);
+ 
+-        return path_is_mount_point(c->parameter, AT_SYMLINK_FOLLOW) > 0;
++        return path_is_mount_point(c->parameter, true) > 0;
+ }
+ 
+ static int condition_test_path_is_read_write(Condition *c) {
+diff --git a/src/shared/path-util.c b/src/shared/path-util.c
+index 0f252ec26..1181ffb9d 100644
+--- a/src/shared/path-util.c
++++ b/src/shared/path-util.c
+@@ -36,7 +36,6 @@
+ #include "strv.h"
+ #include "path-util.h"
+ #include "missing.h"
+-#include "fileio.h"
+ 
+ bool path_is_absolute(const char *p) {
+         return p[0] == '/';
+@@ -474,203 +473,87 @@ char* path_join(const char *root, const char *path, const char *rest) {
+                                NULL);
+ }
+ 
+-static int fd_fdinfo_mnt_id(int fd, const char *filename, int flags, int *mnt_id) {
+-        char path[strlen("/proc/self/fdinfo/") + DECIMAL_STR_MAX(int)];
+-        _cleanup_free_ char *fdinfo = NULL;
+-        _cleanup_close_ int subfd = -1;
+-        char *p;
+-        int r;
+-
+-        if ((flags & AT_EMPTY_PATH) && isempty(filename))
+-                xsprintf(path, "/proc/self/fdinfo/%i", fd);
+-        else {
+-                subfd = openat(fd, filename, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_PATH);
+-                if (subfd < 0)
+-                        return -errno;
+-
+-                xsprintf(path, "/proc/self/fdinfo/%i", subfd);
+-        }
+-
+-        r = read_full_file(path, &fdinfo, NULL);
+-        if (r == -ENOENT) /* The fdinfo directory is a relatively new addition */
+-                return -EOPNOTSUPP;
+-        if (r < 0)
+-                return -errno;
+-
+-        p = startswith(fdinfo, "mnt_id:");
+-        if (!p) {
+-                p = strstr(fdinfo, "\nmnt_id:");
+-                if (!p) /* The mnt_id field is a relatively new addition */
+-                        return -EOPNOTSUPP;
+-
+-                p += 8;
+-        }
++int path_is_mount_point(const char *t, bool allow_symlink) {
+ 
+-        p += strspn(p, WHITESPACE);
+-        p[strcspn(p, WHITESPACE)] = 0;
+-
+-        return safe_atoi(p, mnt_id);
+-}
+-
+-int fd_is_mount_point(int fd, const char *filename, int flags) {
+-        union file_handle_union h = FILE_HANDLE_INIT, h_parent = FILE_HANDLE_INIT;
++        union file_handle_union h = FILE_HANDLE_INIT;
+         int mount_id = -1, mount_id_parent = -1;
+-        bool nosupp = false, check_st_dev = true;
++        _cleanup_free_ char *parent = NULL;
+         struct stat a, b;
+         int r;
++        bool nosupp = false;
+ 
+-        assert(fd >= 0);
+-        assert(filename);
++        /* We are not actually interested in the file handles, but
++         * name_to_handle_at() also passes us the mount ID, hence use
++         * it but throw the handle away */
+ 
+-        /* First we will try the name_to_handle_at() syscall, which
+-         * tells us the mount id and an opaque file "handle". It is
+-         * not supported everywhere though (kernel compile-time
+-         * option, not all file systems are hooked up). If it works
+-         * the mount id is usually good enough to tell us whether
+-         * something is a mount point.
+-         *
+-         * If that didn't work we will try to read the mount id from
+-         * /proc/self/fdinfo/<fd>. This is almost as good as
+-         * name_to_handle_at(), however, does not return the
+-         * opaque file handle. The opaque file handle is pretty useful
+-         * to detect the root directory, which we should always
+-         * consider a mount point. Hence we use this only as
+-         * fallback. Exporting the mnt_id in fdinfo is a pretty recent
+-         * kernel addition.
+-         *
+-         * As last fallback we do traditional fstat() based st_dev
+-         * comparisons. This is how things were traditionally done,
+-         * but unionfs breaks breaks this since it exposes file
+-         * systems with a variety of st_dev reported. Also, btrfs
+-         * subvolumes have different st_dev, even though they aren't
+-         * real mounts of their own. */
+-
+-        r = name_to_handle_at(fd, filename, &h.handle, &mount_id, flags);
++        if (path_equal(t, "/"))
++                return 1;
++
++        r = name_to_handle_at(AT_FDCWD, t, &h.handle, &mount_id, allow_symlink ? AT_SYMLINK_FOLLOW : 0);
+         if (r < 0) {
+                 if (errno == ENOSYS)
+                         /* This kernel does not support name_to_handle_at()
+-                         * fall back to simpler logic. */
+-                        goto fallback_fdinfo;
++                         * fall back to the traditional stat() logic. */
++                        goto fallback;
+                 else if (errno == EOPNOTSUPP)
+                         /* This kernel or file system does not support
+-                         * name_to_handle_at(), hence let's see if the
+-                         * upper fs supports it (in which case it is a
+-                         * mount point), otherwise fallback to the
++                         * name_to_handle_at(), hence fallback to the
+                          * traditional stat() logic */
+                         nosupp = true;
++                else if (errno == ENOENT)
++                        return 0;
+                 else
+                         return -errno;
+         }
+ 
+-        r = name_to_handle_at(fd, "", &h_parent.handle, &mount_id_parent, AT_EMPTY_PATH);
+-        if (r < 0) {
+-                if (errno == EOPNOTSUPP) {
++        r = path_get_parent(t, &parent);
++        if (r < 0)
++                return r;
++
++        h.handle.handle_bytes = MAX_HANDLE_SZ;
++        r = name_to_handle_at(AT_FDCWD, parent, &h.handle, &mount_id_parent, AT_SYMLINK_FOLLOW);
++        if (r < 0)
++                if (errno == EOPNOTSUPP)
+                         if (nosupp)
+                                 /* Neither parent nor child do name_to_handle_at()?
+                                    We have no choice but to fall back. */
+-                                goto fallback_fdinfo;
++                                goto fallback;
+                         else
+-                                /* The parent can't do name_to_handle_at() but the
+-                                 * directory we are interested in can?
++                                /* The parent can't do name_to_handle_at() but
++                                 * the directory we are interested in can?
++                                 * Or the other way around?
+                                  * If so, it must be a mount point. */
+                                 return 1;
+-                } else
++                else
+                         return -errno;
+-        }
++        else
++                return mount_id != mount_id_parent;
+ 
+-        /* The parent can do name_to_handle_at() but the
+-         * directory we are interested in can't? If so, it
+-         * must be a mount point. */
+-        if (nosupp)
+-                return 1;
++fallback:
++        if (allow_symlink)
++                r = stat(t, &a);
++        else
++                r = lstat(t, &a);
+ 
+-        /* If the file handle for the directory we are
+-         * interested in and its parent are identical, we
+-         * assume this is the root directory, which is a mount
+-         * point. */
++        if (r < 0) {
++                if (errno == ENOENT)
++                        return 0;
+ 
+-        if (h.handle.handle_bytes == h_parent.handle.handle_bytes &&
+-            h.handle.handle_type == h_parent.handle.handle_type &&
+-            memcmp(h.handle.f_handle, h_parent.handle.f_handle, h.handle.handle_bytes) == 0)
+-                return 1;
++                return -errno;
++        }
+ 
+-        return mount_id != mount_id_parent;
++        free(parent);
++        parent = NULL;
+ 
+-fallback_fdinfo:
+-        r = fd_fdinfo_mnt_id(fd, filename, flags, &mount_id);
+-        if (r == -EOPNOTSUPP)
+-                goto fallback_fstat;
++        r = path_get_parent(t, &parent);
+         if (r < 0)
+                 return r;
+ 
+-        r = fd_fdinfo_mnt_id(fd, "", AT_EMPTY_PATH, &mount_id_parent);
++        r = stat(parent, &b);
+         if (r < 0)
+-                return r;
+-
+-        if (mount_id != mount_id_parent)
+-                return 1;
+-
+-        /* Hmm, so, the mount ids are the same. This leaves one
+-         * special case though for the root file system. For that,
+-         * let's see if the parent directory has the same inode as we
+-         * are interested in. Hence, let's also do fstat() checks now,
+-         * too, but avoid the st_dev comparisons, since they aren't
+-         * that useful on unionfs mounts. */
+-        check_st_dev = false;
+-
+-fallback_fstat:
+-        /* yay for fstatat() taking a different set of flags than the other
+-         * _at() above */
+-        if (flags & AT_SYMLINK_FOLLOW)
+-                flags &= ~AT_SYMLINK_FOLLOW;
+-        else
+-                flags |= AT_SYMLINK_NOFOLLOW;
+-        if (fstatat(fd, filename, &a, flags) < 0)
+-                return -errno;
+-
+-        if (fstatat(fd, "", &b, AT_EMPTY_PATH) < 0)
+-                return -errno;
+-
+-        /* A directory with same device and inode as its parent? Must
+-         * be the root directory */
+-        if (a.st_dev == b.st_dev &&
+-            a.st_ino == b.st_ino)
+-                return 1;
+-
+-        return check_st_dev && (a.st_dev != b.st_dev);
+-}
+-
+-/* flags can be AT_SYMLINK_FOLLOW or 0 */
+-int path_is_mount_point(const char *t, int flags) {
+-        _cleanup_close_ int fd = -1;
+-        _cleanup_free_ char *canonical = NULL, *parent = NULL;
+-
+-        assert(t);
+-
+-        if (path_equal(t, "/"))
+-                return 1;
+-
+-        /* we need to resolve symlinks manually, we can't just rely on
+-         * fd_is_mount_point() to do that for us; if we have a structure like
+-         * /bin -> /usr/bin/ and /usr is a mount point, then the parent that we
+-         * look at needs to be /usr, not /. */
+-        if (flags & AT_SYMLINK_FOLLOW) {
+-                canonical = canonicalize_file_name(t);
+-                if (!canonical)
+-                        return -errno;
+-
+-                t = canonical;
+-        }
+-
+-        parent = dirname_malloc(t);
+-        if (!parent)
+-                return -ENOMEM;
+-
+-        fd = openat(AT_FDCWD, parent, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_PATH);
+-        if (fd < 0)
+                 return -errno;
+ 
+-        return fd_is_mount_point(fd, basename(t), flags);
++        return a.st_dev != b.st_dev;
+ }
+ 
+ int path_is_read_only_fs(const char *path) {
+diff --git a/src/shared/path-util.h b/src/shared/path-util.h
+index e16484087..71bb740e9 100644
+--- a/src/shared/path-util.h
++++ b/src/shared/path-util.h
+@@ -53,8 +53,7 @@ char** path_strv_make_absolute_cwd(char **l);
+ char** path_strv_resolve(char **l, const char *prefix);
+ char** path_strv_resolve_uniq(char **l, const char *prefix);
+ 
+-int fd_is_mount_point(int fd, const char *filename, int flags);
+-int path_is_mount_point(const char *path, int flags);
++int path_is_mount_point(const char *path, bool allow_symlink);
+ int path_is_read_only_fs(const char *path);
+ int path_is_os_tree(const char *path);
+ 
+diff --git a/src/test/test-path-util.c b/src/test/test-path-util.c
+index 8870f178a..6396fcb39 100644
+--- a/src/test/test-path-util.c
++++ b/src/test/test-path-util.c
+@@ -21,7 +21,6 @@
+ 
+ #include <stdio.h>
+ #include <unistd.h>
+-#include <sys/mount.h>
+ 
+ #include "path-util.h"
+ #include "util.h"
+@@ -86,8 +85,8 @@ static void test_path(void) {
+         test_parent("/aa///file...", "/aa///");
+         test_parent("file.../", NULL);
+ 
+-        assert_se(path_is_mount_point("/", AT_SYMLINK_FOLLOW));
+-        assert_se(path_is_mount_point("/", 0));
++        assert_se(path_is_mount_point("/", true));
++        assert_se(path_is_mount_point("/", false));
+ 
+         {
+                 char p1[] = "aaa/bbb////ccc";
+@@ -100,66 +99,6 @@ static void test_path(void) {
+         }
+ }
+ 
+-static void test_path_is_mount_point(void) {
+-        int fd, rt, rf, rlt, rlf;
+-        char tmp_dir[] = "/tmp/test-path-is-mount-point-XXXXXX";
+-        _cleanup_free_ char *file1 = NULL, *file2 = NULL, *link1 = NULL, *link2 = NULL;
+-
+-        assert_se(path_is_mount_point("/", AT_SYMLINK_FOLLOW) > 0);
+-        assert_se(path_is_mount_point("/", 0) > 0);
+-
+-        assert_se(path_is_mount_point("/proc", AT_SYMLINK_FOLLOW) > 0);
+-        assert_se(path_is_mount_point("/proc", 0) > 0);
+-
+-        assert_se(path_is_mount_point("/proc/1", AT_SYMLINK_FOLLOW) == 0);
+-        assert_se(path_is_mount_point("/proc/1", 0) == 0);
+-
+-        assert_se(path_is_mount_point("/sys", AT_SYMLINK_FOLLOW) > 0);
+-        assert_se(path_is_mount_point("/sys", 0) > 0);
+-
+-        /* file mountpoints */
+-        assert_se(mkdtemp(tmp_dir) != NULL);
+-        file1 = path_join(NULL, tmp_dir, "file1");
+-        assert_se(file1);
+-        file2 = path_join(NULL, tmp_dir, "file2");
+-        assert_se(file2);
+-        fd = open(file1, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, 0664);
+-        assert_se(fd > 0);
+-        close(fd);
+-        fd = open(file2, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, 0664);
+-        assert_se(fd > 0);
+-        close(fd);
+-        link1 = path_join(NULL, tmp_dir, "link1");
+-        assert_se(link1);
+-        assert_se(symlink("file1", link1) == 0);
+-        link2 = path_join(NULL, tmp_dir, "link2");
+-        assert_se(link1);
+-        assert_se(symlink("file2", link2) == 0);
+-
+-        assert_se(path_is_mount_point(file1, AT_SYMLINK_FOLLOW) == 0);
+-        assert_se(path_is_mount_point(file1, 0) == 0);
+-        assert_se(path_is_mount_point(link1, AT_SYMLINK_FOLLOW) == 0);
+-        assert_se(path_is_mount_point(link1, 0) == 0);
+-
+-        /* this test will only work as root */
+-        if (mount(file1, file2, NULL, MS_BIND, NULL) >= 0) {
+-                rf = path_is_mount_point(file2, 0);
+-                rt = path_is_mount_point(file2, AT_SYMLINK_FOLLOW);
+-                rlf = path_is_mount_point(link2, 0);
+-                rlt = path_is_mount_point(link2, AT_SYMLINK_FOLLOW);
+-
+-                assert_se(umount(file2) == 0);
+-
+-                assert_se(rf == 1);
+-                assert_se(rt == 1);
+-                assert_se(rlf == 0);
+-                assert_se(rlt == 1);
+-        } else
+-                printf("Skipping bind mount file test: %m\n");
+-
+-        assert_se(rm_rf(tmp_dir, false, true, false) == 0);
+-}
+-
+ static void test_find_binary(const char *self, bool local) {
+         char *p;
+ 
+@@ -349,7 +288,6 @@ int main(int argc, char **argv) {
+         test_make_relative();
+         test_strv_resolve();
+         test_path_startswith();
+-        test_path_is_mount_point();
+ 
+         return 0;
+ }
diff --git a/SOURCES/0530-device-make-sure-to-remove-all-device-units-sharing-.patch b/SOURCES/0530-device-make-sure-to-remove-all-device-units-sharing-.patch
new file mode 100644
index 0000000..fddfd6b
--- /dev/null
+++ b/SOURCES/0530-device-make-sure-to-remove-all-device-units-sharing-.patch
@@ -0,0 +1,43 @@
+From 562bccced876d3bc0e9521ef31f6cc1e5cff9798 Mon Sep 17 00:00:00 2001
+From: Franck Bui <fbui@suse.com>
+Date: Wed, 30 Aug 2017 17:16:16 +0200
+Subject: [PATCH] device: make sure to remove all device units sharing the same
+ sysfs path (#6679)
+
+When a device is unplugged all device units sharing the same sysfs path
+pointing to that device are supposed to be removed.
+
+However it didn't work since while iterating the device unit list containing
+all the relevant units, each unit was removed during each iteration of
+LIST_FOREACH. However LIST_FOREACH doesn't support this use case and
+LIST_FOREACH_SAFE must be use instead.
+
+(cherry picked from commit cc0df6cc35339976c367977dc292278a1939db0c)
+
+Related: #1408916
+---
+ src/core/device.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/src/core/device.c b/src/core/device.c
+index 63a04bdd3..2afa19f2b 100644
+--- a/src/core/device.c
++++ b/src/core/device.c
+@@ -487,7 +487,7 @@ static void device_update_found_one(Device *d, bool add, DeviceFound found, bool
+ }
+ 
+ static int device_update_found_by_sysfs(Manager *m, const char *sysfs, bool add, DeviceFound found, bool now) {
+-        Device *d, *l;
++        Device *d, *l, *n;
+ 
+         assert(m);
+         assert(sysfs);
+@@ -496,7 +496,7 @@ static int device_update_found_by_sysfs(Manager *m, const char *sysfs, bool add,
+                 return 0;
+ 
+         l = hashmap_get(m->devices_by_sysfs, sysfs);
+-        LIST_FOREACH(same_sysfs, d, l)
++        LIST_FOREACH_SAFE(same_sysfs, d, n, l)
+                 device_update_found_one(d, add, found, now);
+ 
+         return 0;
diff --git a/SOURCES/0531-manager-when-reexecuting-try-to-connect-to-bus-only-.patch b/SOURCES/0531-manager-when-reexecuting-try-to-connect-to-bus-only-.patch
new file mode 100644
index 0000000..bd82b93
--- /dev/null
+++ b/SOURCES/0531-manager-when-reexecuting-try-to-connect-to-bus-only-.patch
@@ -0,0 +1,48 @@
+From 8410dde8d9593c1d96593b17d610d7daf955dab3 Mon Sep 17 00:00:00 2001
+From: Michal Sekletar <msekletar@users.noreply.github.com>
+Date: Fri, 8 Sep 2017 15:41:44 +0200
+Subject: [PATCH] manager: when reexecuting try to connect to bus only when
+ dbus.service is around (#6773)
+
+Trying to connect otherwise is pointless, because if socket isn't around
+we won't connect. However, when dbus.socket is present we attempt to
+connect. That attempt can't succeed because we are then supposed
+to activate dbus.service as a response to connection from
+us. This results in deadlock.
+
+Fixes #6303
+
+(cherry picked from commit 5463fa0a88f95d2002858592578f9bf4e0d2660a)
+
+Resolves: #1465737
+---
+ src/core/manager.c | 9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+diff --git a/src/core/manager.c b/src/core/manager.c
+index 287cf6a74..041fac46b 100644
+--- a/src/core/manager.c
++++ b/src/core/manager.c
+@@ -799,16 +799,19 @@ static int manager_setup_kdbus(Manager *m) {
+ 
+ static int manager_connect_bus(Manager *m, bool reexecuting) {
+         bool try_bus_connect;
++        Unit *u = NULL;
+ 
+         assert(m);
+ 
+         if (m->test_run)
+                 return 0;
+ 
++        u = manager_get_unit(m, SPECIAL_DBUS_SERVICE);
++
+         try_bus_connect =
+-                m->kdbus_fd >= 0 ||
+-                reexecuting ||
+-                (m->running_as == SYSTEMD_USER && getenv("DBUS_SESSION_BUS_ADDRESS"));
++                (u && UNIT_IS_ACTIVE_OR_RELOADING(unit_active_state(u))) &&
++                (reexecuting ||
++                (m->running_as == SYSTEMD_USER && getenv("DBUS_SESSION_BUS_ADDRESS")));
+ 
+         /* Try to connect to the busses, if possible. */
+         return bus_init(m, try_bus_connect);
diff --git a/SOURCES/0532-doc-document-service-exit-codes.patch b/SOURCES/0532-doc-document-service-exit-codes.patch
new file mode 100644
index 0000000..7fcdd5c
--- /dev/null
+++ b/SOURCES/0532-doc-document-service-exit-codes.patch
@@ -0,0 +1,337 @@
+From a2176ebec2b1ff05b599362af2f8426e1c4fd3ef Mon Sep 17 00:00:00 2001
+From: Jan Synacek <jsynacek@redhat.com>
+Date: Thu, 26 Jan 2017 13:45:46 +0100
+Subject: [PATCH] doc: document service exit codes
+
+(Heavily reworked by Lennart while rebasing)
+
+Fixes: #3545
+Replaces: #5159
+(cherry picked from commit 91a8f867b6fcdb9b2c4074b571e992e6c7869428)
+
+Resolves: #1178929
+---
+ man/systemd.exec.xml | 310 +++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 310 insertions(+)
+
+diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml
+index 1b14ced78..508146f06 100644
+--- a/man/systemd.exec.xml
++++ b/man/systemd.exec.xml
+@@ -1360,6 +1360,316 @@
+     cf. <citerefentry project='man-pages'><refentrytitle>pam_env</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
+   </refsect1>
+ 
++  <refsect1>
++    <title>Process exit codes</title>
++
++    <para>When invoking a unit process the service manager possibly fails to apply the execution parameters configured
++    with the settings above. In that case the already created service process will exit with a non-zero exit code
++    before the configured command line is executed. (Or in other words, the child process possibly exits with these
++    error codes, after having been created by the <citerefentry
++    project='man-pages'><refentrytitle>fork</refentrytitle><manvolnum>2</manvolnum></citerefentry> system call, but
++    before the matching <citerefentry
++    project='man-pages'><refentrytitle>execve</refentrytitle><manvolnum>2</manvolnum></citerefentry> system call is
++    called.) Specifically, exit codes defined by the C library, by the LSB specification and by the systemd service
++    manager itself are used.</para>
++
++    <para>The following basic service exit codes are defined by the C library.</para>
++
++    <table>
++      <title>Basic C library exit codes</title>
++      <tgroup cols='3'>
++        <thead>
++          <row>
++            <entry>Exit Code</entry>
++            <entry>Symbolic Name</entry>
++            <entry>Description</entry>
++          </row>
++        </thead>
++        <tbody>
++          <row>
++            <entry>0</entry>
++            <entry><constant>EXIT_SUCCESS</constant></entry>
++            <entry>Generic success code.</entry>
++          </row>
++          <row>
++            <entry>1</entry>
++            <entry><constant>EXIT_FAILURE</constant></entry>
++            <entry>Generic failure or unspecified error.</entry>
++          </row>
++        </tbody>
++      </tgroup>
++    </table>
++
++    <para>The following service exit codes are defined by the <ulink
++    url="https://refspecs.linuxbase.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/iniscrptact.html">LSB specification
++    </ulink>.
++    </para>
++
++    <table>
++      <title>LSB service exit codes</title>
++      <tgroup cols='3'>
++        <thead>
++          <row>
++            <entry>Exit Code</entry>
++            <entry>Symbolic Name</entry>
++            <entry>Description</entry>
++          </row>
++        </thead>
++        <tbody>
++          <row>
++            <entry>2</entry>
++            <entry><constant>EXIT_INVALIDARGUMENT</constant></entry>
++            <entry>Invalid or excess arguments.</entry>
++          </row>
++          <row>
++            <entry>3</entry>
++            <entry><constant>EXIT_NOTIMPLEMENTED</constant></entry>
++            <entry>Unimplemented feature.</entry>
++          </row>
++          <row>
++            <entry>4</entry>
++            <entry><constant>EXIT_NOPERMISSION</constant></entry>
++            <entry>The user has insufficient privileges.</entry>
++          </row>
++          <row>
++            <entry>5</entry>
++            <entry><constant>EXIT_NOTINSTALLED</constant></entry>
++            <entry>The program is not installed.</entry>
++          </row>
++          <row>
++            <entry>6</entry>
++            <entry><constant>EXIT_NOTCONFIGURED</constant></entry>
++            <entry>The program is not configured.</entry>
++          </row>
++          <row>
++            <entry>7</entry>
++            <entry><constant>EXIT_NOTRUNNING</constant></entry>
++            <entry>The program is not running.</entry>
++          </row>
++        </tbody>
++      </tgroup>
++    </table>
++
++    <para>
++      The LSB specification suggests that error codes 200 and above are reserved for implementations. Some of them are
++      used by the service manager to indicate problems during process invocation:
++    </para>
++    <table>
++      <title>systemd-specific exit codes</title>
++      <tgroup cols='3'>
++        <thead>
++          <row>
++            <entry>Exit Code</entry>
++            <entry>Symbolic Name</entry>
++            <entry>Description</entry>
++          </row>
++        </thead>
++        <tbody>
++          <row>
++            <entry>200</entry>
++            <entry><constant>EXIT_CHDIR</constant></entry>
++            <entry>Changing to the requested working directory failed. See <varname>WorkingDirectory=</varname> above.</entry>
++          </row>
++          <row>
++            <entry>201</entry>
++            <entry><constant>EXIT_NICE</constant></entry>
++            <entry>Failed to set up process scheduling priority (nice level). See <varname>Nice=</varname> above.</entry>
++          </row>
++          <row>
++            <entry>202</entry>
++            <entry><constant>EXIT_FDS</constant></entry>
++            <entry>Failed to close unwanted file descriptors, or to adjust passed file descriptors.</entry>
++          </row>
++          <row>
++            <entry>203</entry>
++            <entry><constant>EXIT_EXEC</constant></entry>
++            <entry>The actual process execution failed (specifically, the <citerefentry project='man-pages'><refentrytitle>execve</refentrytitle><manvolnum>2</manvolnum></citerefentry> system call). Most likely this is caused by a missing or non-accessible executable file.</entry>
++          </row>
++          <row>
++            <entry>204</entry>
++            <entry><constant>EXIT_MEMORY</constant></entry>
++            <entry>Failed to perform an action due to memory shortage.</entry>
++          </row>
++          <row>
++            <entry>205</entry>
++            <entry><constant>EXIT_LIMITS</constant></entry>
++            <entry>Failed to adjust resoure limits. See <varname>LimitCPU=</varname> and related settings above.</entry>
++          </row>
++          <row>
++            <entry>206</entry>
++            <entry><constant>EXIT_OOM_ADJUST</constant></entry>
++            <entry>Failed to adjust the OOM setting. See <varname>OOMScoreAdjust=</varname> above.</entry>
++          </row>
++          <row>
++            <entry>207</entry>
++            <entry><constant>EXIT_SIGNAL_MASK</constant></entry>
++            <entry>Failed to set process signal mask.</entry>
++          </row>
++          <row>
++            <entry>208</entry>
++            <entry><constant>EXIT_STDIN</constant></entry>
++            <entry>Failed to set up standard input. See <varname>StandardInput=</varname> above.</entry>
++          </row>
++          <row>
++            <entry>209</entry>
++            <entry><constant>EXIT_STDOUT</constant></entry>
++            <entry>Failed to set up standard output. See <varname>StandardOutput=</varname> above.</entry>
++          </row>
++          <row>
++            <entry>210</entry>
++            <entry><constant>EXIT_CHROOT</constant></entry>
++            <entry>Failed to change root directory (<citerefentry project='man-pages'><refentrytitle>chroot</refentrytitle><manvolnum>2</manvolnum></citerefentry>). See <varname>RootDirectory=</varname>/<varname>RootImage=</varname> above.</entry>
++          </row>
++          <row>
++            <entry>211</entry>
++            <entry><constant>EXIT_IOPRIO</constant></entry>
++            <entry>Failed to set up IO scheduling priority. See <varname>IOSchedulingClass=</varname>/<varname>IOSchedulingPriority=</varname> above.</entry>
++          </row>
++          <row>
++            <entry>212</entry>
++            <entry><constant>EXIT_TIMERSLACK</constant></entry>
++            <entry>Failed to set up timer slack. See <varname>TimerSlackNSec=</varname> above.</entry>
++          </row>
++          <row>
++            <entry>213</entry>
++            <entry><constant>EXIT_SECUREBITS</constant></entry>
++            <entry>Failed to set process secure bits. See <varname>SecureBits=</varname> above.</entry>
++          </row>
++          <row>
++            <entry>214</entry>
++            <entry><constant>EXIT_SETSCHEDULER</constant></entry>
++            <entry>Failed to set up CPU scheduling. See <varname>CPUSchedulingPolicy=</varname>/<varname>CPUSchedulingPriority=</varname> above.</entry>
++          </row>
++          <row>
++            <entry>215</entry>
++            <entry><constant>EXIT_CPUAFFINITY</constant></entry>
++            <entry>Failed to set up CPU affinity. See <varname>CPUAffinity=</varname> above.</entry>
++          </row>
++          <row>
++            <entry>216</entry>
++            <entry><constant>EXIT_GROUP</constant></entry>
++            <entry>Failed to determine or change group credentials. See <varname>Group=</varname>/<varname>SupplementaryGroups=</varname> above.</entry>
++          </row>
++          <row>
++            <entry>217</entry>
++            <entry><constant>EXIT_USER</constant></entry>
++            <entry>Failed to determine or change user credentials, or to set up user namespacing. See <varname>User=</varname>/<varname>PrivateUsers=</varname> above.</entry>
++          </row>
++          <row>
++            <entry>218</entry>
++            <entry><constant>EXIT_CAPABILITIES</constant></entry>
++            <entry>Failed to drop capabilities, or apply ambient capabilities. See <varname>CapabilityBoundingSet=</varname>/<varname>AmbientCapabilities=</varname> above.</entry>
++          </row>
++          <row>
++            <entry>219</entry>
++            <entry><constant>EXIT_CGROUP</constant></entry>
++            <entry>Setting up the service control group failed.</entry>
++          </row>
++          <row>
++            <entry>220</entry>
++            <entry><constant>EXIT_SETSID</constant></entry>
++            <entry>Failed to create new process session.</entry>
++          </row>
++          <row>
++            <entry>221</entry>
++            <entry><constant>EXIT_CONFIRM</constant></entry>
++            <entry>Execution has been cancelled by the user. See the <varname>systemd.confirm_spawn=</varname> kernel command line setting on <citerefentry><refentrytitle>kernel-command-line</refentrytitle><manvolnum>7</manvolnum></citerefentry> for details.</entry>
++          </row>
++          <row>
++            <entry>222</entry>
++            <entry><constant>EXIT_STDERR</constant></entry>
++            <entry>Failed to set up standard error output. See <varname>StandardError=</varname> above.</entry>
++          </row>
++          <row>
++            <entry>224</entry>
++            <entry><constant>EXIT_PAM</constant></entry>
++            <entry>Failed to set up PAM session. See <varname>PAMName=</varname> above.</entry>
++          </row>
++          <row>
++            <entry>225</entry>
++            <entry><constant>EXIT_NETWORK</constant></entry>
++            <entry>Failed to set up network namespacing. See <varname>PrivateNetwork=</varname> above.</entry>
++          </row>
++          <row>
++            <entry>226</entry>
++            <entry><constant>EXIT_NAMESPACE</constant></entry>
++            <entry>Failed to set up mount namespacing. See <varname>ReadOnlyPaths=</varname> and related settings above.</entry>
++          </row>
++          <row>
++            <entry>227</entry>
++            <entry><constant>EXIT_NO_NEW_PRIVILEGES</constant></entry>
++            <entry>Failed to disable new priviliges. See <varname>NoNewPrivileges=yes</varname> above.</entry>
++          </row>
++          <row>
++            <entry>228</entry>
++            <entry><constant>EXIT_SECCOMP</constant></entry>
++            <entry>Failed to apply system call filters. See <varname>SystemCallFilter=</varname> and related settings above.</entry>
++          </row>
++          <row>
++            <entry>229</entry>
++            <entry><constant>EXIT_SELINUX_CONTEXT</constant></entry>
++            <entry>Determining or changing SELinux context failed. See <varname>SELinuxContext=</varname> above.</entry>
++          </row>
++          <row>
++            <entry>230</entry>
++            <entry><constant>EXIT_PERSONALITY</constant></entry>
++            <entry>Failed to set up a execution domain (personality). See <varname>Personality=</varname> above.</entry>
++          </row>
++          <row>
++            <entry>231</entry>
++            <entry><constant>EXIT_APPARMOR_PROFILE</constant></entry>
++            <entry>Failed to prepare changing AppArmor profile. See <varname>AppArmorProfile=</varname> above.</entry>
++          </row>
++          <row>
++            <entry>232</entry>
++            <entry><constant>EXIT_ADDRESS_FAMILIES</constant></entry>
++            <entry>Failed to restrict address families. See <varname>RestrictAddressFamilies=</varname> above.</entry>
++          </row>
++          <row>
++            <entry>233</entry>
++            <entry><constant>EXIT_RUNTIME_DIRECTORY</constant></entry>
++            <entry>Setting up runtime directory failed. See <varname>RuntimeDirectory=</varname> and related settings above.</entry>
++          </row>
++          <row>
++            <entry>235</entry>
++            <entry><constant>EXIT_CHOWN</constant></entry>
++            <entry>Failed to adjust socket ownership. Used for socket units only.</entry>
++          </row>
++          <row>
++            <entry>236</entry>
++            <entry><constant>EXIT_SMACK_PROCESS_LABEL</constant></entry>
++            <entry>Failed to set SMACK label. See <varname>SmackProcessLabel=</varname> above.</entry>
++          </row>
++          <row>
++            <entry>237</entry>
++            <entry><constant>EXIT_KEYRING</constant></entry>
++            <entry>Failed to set up kernel keyring.</entry>
++          </row>
++          <row>
++            <entry>238</entry>
++            <entry><constant>EXIT_STATE_DIRECTORY</constant></entry>
++            <entry>Failed to set up a the unit's state directory. See <varname>StateDirectory=</varname> above.</entry>
++          </row>
++          <row>
++            <entry>239</entry>
++            <entry><constant>EXIT_CACHE_DIRECTORY</constant></entry>
++            <entry>Failed to set up a the unit's cache directory. See <varname>CacheDirectory=</varname> above.</entry>
++          </row>
++          <row>
++            <entry>240</entry>
++            <entry><constant>EXIT_LOGS_DIRECTORY</constant></entry>
++            <entry>Failed to set up a the unit's logging directory. See <varname>LogsDirectory=</varname> above.</entry>
++          </row>
++          <row>
++            <entry>241</entry>
++            <entry><constant>EXIT_CONFIGURATION_DIRECTORY</constant></entry>
++            <entry>Failed to set up a the unit's configuration directory. See <varname>ConfigurationDirectory=</varname> above.</entry>
++          </row>
++        </tbody>
++      </tgroup>
++    </table>
++  </refsect1>
++
+   <refsect1>
+       <title>See Also</title>
+       <para>
diff --git a/SOURCES/0533-units-order-cryptsetup-pre.target-before-cryptsetup..patch b/SOURCES/0533-units-order-cryptsetup-pre.target-before-cryptsetup..patch
new file mode 100644
index 0000000..ba9d7a6
--- /dev/null
+++ b/SOURCES/0533-units-order-cryptsetup-pre.target-before-cryptsetup..patch
@@ -0,0 +1,25 @@
+From acf59b657e23e3b5b0f038823fe57dcfb4f914a4 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
+Date: Tue, 5 Sep 2017 09:14:51 +0200
+Subject: [PATCH] units: order cryptsetup-pre.target before cryptsetup.target
+
+Normally this happens automatically, but if it happened that both targets were
+pulled in, even though there were no cryptsetup units, they could be started
+in reverse order, which would be somewhat confusing. Add an explicit ordering
+to avoid this potential issue.
+
+Cherry-picked from: 947d21171bdd8375db6482bc7d758d74b27f7dd4
+Resolves: #1384014
+---
+ units/cryptsetup-pre.target | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/units/cryptsetup-pre.target b/units/cryptsetup-pre.target
+index 65353419f..42e35dd4e 100644
+--- a/units/cryptsetup-pre.target
++++ b/units/cryptsetup-pre.target
+@@ -9,3 +9,4 @@
+ Description=Encrypted Volumes (Pre)
+ Documentation=man:systemd.special(7)
+ RefuseManualStart=yes
++Before=cryptsetup.target
diff --git a/SOURCES/0534-man-add-an-explicit-description-of-_netdev-to-system.patch b/SOURCES/0534-man-add-an-explicit-description-of-_netdev-to-system.patch
new file mode 100644
index 0000000..0709d77
--- /dev/null
+++ b/SOURCES/0534-man-add-an-explicit-description-of-_netdev-to-system.patch
@@ -0,0 +1,41 @@
+From eb628c9f0ec9dcaec41dadc7ff594c8420b78a71 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
+Date: Tue, 5 Sep 2017 11:20:14 +0200
+Subject: [PATCH] man: add an explicit description of _netdev to
+ systemd.mount(5)
+
+It was mentioned in passing, but having it in the list of options is also
+nice.
+
+Cherry-picked from: 0f00528db4e941503ec8cb5052367b17a8b566ba
+Resolves: #1384014
+---
+ man/systemd.mount.xml | 15 +++++++++++++++
+ 1 file changed, 15 insertions(+)
+
+diff --git a/man/systemd.mount.xml b/man/systemd.mount.xml
+index 04ed1e1cf..dfa437b5d 100644
+--- a/man/systemd.mount.xml
++++ b/man/systemd.mount.xml
+@@ -202,6 +202,21 @@
+         setting in a unit file.</para>
+         </listitem>
+       </varlistentry>
++      <varlistentry>
++        <term><option>_netdev</option></term>
++
++        <listitem><para>Normally the file system type is used to determine if a
++        mount is a "network mount", i.e. if it should only be started after the
++        network is available. Using this option overrides this detection and
++        specifies that the mount requires network.</para>
++
++        <para>Network mount units are ordered between <filename>remote-fs-pre.target</filename>
++        and <filename>remote-fs.target</filename>, instead of
++        <filename>local-fs-pre.target</filename> and <filename>local-fs.target</filename>.
++        They also pull in <filename>network-online.target</filename> and are ordered after
++        it and <filename>network.target</filename>.</para>
++        </listitem>
++      </varlistentry>
+ 
+       <varlistentry>
+         <term><option>noauto</option></term>
diff --git a/SOURCES/0535-units-add-remote-cryptsetup.target-and-remote-crypts.patch b/SOURCES/0535-units-add-remote-cryptsetup.target-and-remote-crypts.patch
new file mode 100644
index 0000000..3c3e8b8
--- /dev/null
+++ b/SOURCES/0535-units-add-remote-cryptsetup.target-and-remote-crypts.patch
@@ -0,0 +1,140 @@
+From ea1a15b35b70573ab61ca0b8123205c6885c69e4 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
+Date: Tue, 5 Sep 2017 10:15:13 +0200
+Subject: [PATCH] units: add remote-cryptsetup.target and
+ remote-cryptsetup-pre.target
+
+The pair is similar to remote-fs.target and remote-fs-pre.target. Any
+cryptsetup devices which require network shall be ordered after
+remote-cryptsetup-pre.target and before remote-cryptsetup.target.
+
+Cherry-picked from: 889128b8b27abb13e1691a72e4ce0562c564e257
+Resolves: #1384014
+---
+ Makefile.am                        |  4 +++-
+ man/systemd.special.xml            | 23 +++++++++++++++++++++++
+ units/cryptsetup-pre.target        |  2 +-
+ units/cryptsetup.target            |  2 +-
+ units/remote-cryptsetup-pre.target | 15 +++++++++++++++
+ units/remote-cryptsetup.target     | 10 ++++++++++
+ 6 files changed, 53 insertions(+), 3 deletions(-)
+ create mode 100644 units/remote-cryptsetup-pre.target
+ create mode 100644 units/remote-cryptsetup.target
+
+diff --git a/Makefile.am b/Makefile.am
+index 0e2f8d561..a1ebf5cb0 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -4861,7 +4861,9 @@ systemgenerator_PROGRAMS += \
+ 
+ dist_systemunit_DATA += \
+ 	units/cryptsetup.target \
+-	units/cryptsetup-pre.target
++	units/cryptsetup-pre.target \
++	units/remote-cryptsetup.target \
++	units/remote-cryptsetup-pre.target
+ 
+ systemd_cryptsetup_SOURCES = \
+ 	src/cryptsetup/cryptsetup.c
+diff --git a/man/systemd.special.xml b/man/systemd.special.xml
+index eb464f9f8..5529d3bf7 100644
+--- a/man/systemd.special.xml
++++ b/man/systemd.special.xml
+@@ -81,6 +81,8 @@
+     <filename>poweroff.target</filename>,
+     <filename>printer.target</filename>,
+     <filename>reboot.target</filename>,
++    <filename>remote-cryptsetup-pre.target</filename>,
++    <filename>remote-cryptsetup.target</filename>,
+     <filename>remote-fs.target</filename>,
+     <filename>remote-fs-pre.target</filename>,
+     <filename>rescue.target</filename>,
+@@ -404,6 +406,27 @@
+           this target unit, for compatibility with SysV.</para>
+         </listitem>
+       </varlistentry>
++      <varlistentry>
++        <term><filename>remote-cryptsetup-pre.target</filename></term>
++        <listitem>
++          <para>This target unit is automatically ordered before all cryptsetup devices
++          marked with the <option>_netdev</option>. It can be used to execute additional
++          units before such devices are set up.</para>
++
++          <para>It is ordered after <filename>network.target</filename> and
++          <filename>network-online.target</filename>, and also pulls the latter in as a
++          <varname>Wants=</varname> dependency.</para>
++        </listitem>
++      </varlistentry>
++      <varlistentry>
++        <term><filename>remote-cryptsetup.target</filename></term>
++        <listitem>
++          <para>Similar to <filename>cryptsetup.target</filename>, but for encrypted
++          devices which are accessed over the network. It is used for
++          <citerefentry><refentrytitle>crypttab</refentrytitle><manvolnum>8</manvolnum></citerefentry>
++          entries marked with <option>_netdev</option>.</para>
++        </listitem>
++      </varlistentry>
+       <varlistentry>
+         <term><filename>remote-fs.target</filename></term>
+         <listitem>
+diff --git a/units/cryptsetup-pre.target b/units/cryptsetup-pre.target
+index 42e35dd4e..6cb28a61a 100644
+--- a/units/cryptsetup-pre.target
++++ b/units/cryptsetup-pre.target
+@@ -6,7 +6,7 @@
+ #  (at your option) any later version.
+ 
+ [Unit]
+-Description=Encrypted Volumes (Pre)
++Description=Local Encrypted Volumes (Pre)
+ Documentation=man:systemd.special(7)
+ RefuseManualStart=yes
+ Before=cryptsetup.target
+diff --git a/units/cryptsetup.target b/units/cryptsetup.target
+index 25d3e33f6..10b17fd38 100644
+--- a/units/cryptsetup.target
++++ b/units/cryptsetup.target
+@@ -6,5 +6,5 @@
+ #  (at your option) any later version.
+ 
+ [Unit]
+-Description=Encrypted Volumes
++Description=Local Encrypted Volumes
+ Documentation=man:systemd.special(7)
+diff --git a/units/remote-cryptsetup-pre.target b/units/remote-cryptsetup-pre.target
+new file mode 100644
+index 000000000..a375e6188
+--- /dev/null
++++ b/units/remote-cryptsetup-pre.target
+@@ -0,0 +1,15 @@
++#  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=Remote Encrypted Volumes (Pre)
++Documentation=man:systemd.special(7)
++RefuseManualStart=yes
++Before=remote-cryptsetup.target
++
++After=network.target network-online.target
++Wants=network-online.target
+diff --git a/units/remote-cryptsetup.target b/units/remote-cryptsetup.target
+new file mode 100644
+index 000000000..60943bd1c
+--- /dev/null
++++ b/units/remote-cryptsetup.target
+@@ -0,0 +1,10 @@
++#  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=Remote Encrypted Volumes
++Documentation=man:systemd.special(7)
diff --git a/SOURCES/0536-cryptsetup-generator-use-remote-cryptsetup.target-wh.patch b/SOURCES/0536-cryptsetup-generator-use-remote-cryptsetup.target-wh.patch
new file mode 100644
index 0000000..2b8fccc
--- /dev/null
+++ b/SOURCES/0536-cryptsetup-generator-use-remote-cryptsetup.target-wh.patch
@@ -0,0 +1,125 @@
+From d09c35c48005669c4c4663e3ba8a6f979432cead Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
+Date: Tue, 5 Sep 2017 11:30:33 +0200
+Subject: [PATCH] cryptsetup-generator: use remote-cryptsetup.target when
+ _netdev is present
+
+This allows such devices to depend on the network. Their startup will
+be delayed similarly to network mount units.
+
+Fixes #4642.
+
+Cherry-picked from: b001ad61e91b6499897f0c977045c7608c233bfa
+Resolves: #1384014
+---
+ man/crypttab.xml                      | 13 +++++++++++++
+ src/cryptsetup/cryptsetup-generator.c | 36 +++++++++++++++++++++++------------
+ 2 files changed, 37 insertions(+), 12 deletions(-)
+
+diff --git a/man/crypttab.xml b/man/crypttab.xml
+index 3e249ad23..7085a1623 100644
+--- a/man/crypttab.xml
++++ b/man/crypttab.xml
+@@ -189,6 +189,19 @@
+         <option>size=</option>.</para></listitem>
+       </varlistentry>
+ 
++      <varlistentry>
++        <term><option>_netdev</option></term>
++
++        <listitem><para>Marks this cryptsetup device as requiring network. It will be
++        started after the network is available, similarly to
++        <citerefentry><refentrytitle>systemd.mount</refentrytitle><manvolnum>5</manvolnum></citerefentry>
++        units marked with <option>_netdev</option>. The service unit to set up this device
++        will be ordered between <filename>remote-cryptsetup-pre.target</filename> and
++        <filename>remote-cryptsetup.target</filename>, instead of
++        <filename>cryptsetup-pre.target</filename> and
++        <filename>cryptsetup.target</filename>.</para></listitem>
++      </varlistentry>
++
+       <varlistentry>
+         <term><option>noauto</option></term>
+ 
+diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c
+index d191def5f..49dc8f14b 100644
+--- a/src/cryptsetup/cryptsetup-generator.c
++++ b/src/cryptsetup/cryptsetup-generator.c
+@@ -60,7 +60,7 @@ static int create_disk(
+         _cleanup_free_ char *p = NULL, *n = NULL, *d = NULL, *u = NULL, *to = NULL, *e = NULL,
+                 *filtered = NULL;
+         _cleanup_fclose_ FILE *f = NULL;
+-        bool noauto, nofail, tmp, swap;
++        bool noauto, nofail, tmp, swap, netdev;
+         char *from;
+         int r;
+ 
+@@ -71,6 +71,7 @@ static int create_disk(
+         nofail = fstab_test_yes_no_option(options, "nofail\0" "fail\0");
+         tmp = fstab_test_option(options, "tmp\0");
+         swap = fstab_test_option(options, "swap\0");
++        netdev = fstab_test_option(options, "_netdev\0");
+ 
+         if (tmp && swap) {
+                 log_error("Device '%s' cannot be both 'tmp' and 'swap'. Ignoring.", name);
+@@ -101,22 +102,24 @@ static int create_disk(
+         if (!f)
+                 return log_error_errno(errno, "Failed to create unit file %s: %m", p);
+ 
+-        fputs(
++        fprintf(f,
+                 "# Automatically generated by systemd-cryptsetup-generator\n\n"
+                 "[Unit]\n"
+-                "Description=Cryptography Setup for %I\n"
++                "Description=Cryptography Setup for %%I\n"
+                 "Documentation=man:crypttab(5) man:systemd-cryptsetup-generator(8) man:systemd-cryptsetup@.service(8)\n"
+                 "SourcePath=/etc/crypttab\n"
+                 "DefaultDependencies=no\n"
+                 "Conflicts=umount.target\n"
+-                "BindsTo=dev-mapper-%i.device\n"
++                "BindsTo=dev-mapper-%%i.device\n"
+                 "IgnoreOnIsolate=true\n"
+-                "After=systemd-readahead-collect.service systemd-readahead-replay.service cryptsetup-pre.target\n",
+-                f);
++                "After=systemd-readahead-collect.service systemd-readahead-replay.service\n"
++                "After=%s\n",
++                netdev ? "remote-cryptsetup-pre.target" : "cryptsetup-pre.target");
+ 
+         if (!nofail)
+                 fprintf(f,
+-                        "Before=cryptsetup.target\n");
++                        "Before=%s\n",
++                        netdev ? "remote-cryptsetup.target" : "cryptsetup.target");
+ 
+         if (password) {
+                 if (STR_IN_SET(password, "/dev/urandom", "/dev/random", "/dev/hw_random"))
+@@ -196,16 +199,25 @@ static int create_disk(
+                         return log_error_errno(errno, "Failed to create symlink %s: %m", to);
+ 
+                 free(to);
+-                if (!nofail)
+-                        to = strjoin(arg_dest, "/cryptsetup.target.requires/", n, NULL);
+-                else
+-                        to = strjoin(arg_dest, "/cryptsetup.target.wants/", n, NULL);
++                if (!netdev) {
++                        if (!nofail)
++                                to = strjoin(arg_dest, "/cryptsetup.target.requires/", n, NULL);
++                        else
++                                to = strjoin(arg_dest, "/cryptsetup.target.wants/", n, NULL);
++                } else {
++                        if (!nofail)
++                                to = strjoin(arg_dest, "/remote-cryptsetup.target.requires/", n, NULL);
++                        else
++                                to = strjoin(arg_dest, "/remote-cryptsetup.target.wants/", n, NULL);
++                }
+                 if (!to)
+                         return log_oom();
+ 
+                 mkdir_parents_label(to, 0755);
+-                if (symlink(from, to) < 0)
++                if (symlink(from, to) < 0) {
++                        free(to);
+                         return log_error_errno(errno, "Failed to create symlink %s: %m", to);
++                }
+         }
+ 
+         free(to);
diff --git a/SOURCES/0537-Support-rdma-as-a-ListenNetlink-argument-6626.patch b/SOURCES/0537-Support-rdma-as-a-ListenNetlink-argument-6626.patch
new file mode 100644
index 0000000..ebae836
--- /dev/null
+++ b/SOURCES/0537-Support-rdma-as-a-ListenNetlink-argument-6626.patch
@@ -0,0 +1,28 @@
+From db66a909c0e4ca5d05a0dfa84734c1760ae41e3b Mon Sep 17 00:00:00 2001
+From: Jan Synacek <jsynacek@redhat.com>
+Date: Mon, 25 Sep 2017 10:44:19 +0200
+Subject: [PATCH] Support 'rdma' as a ListenNetlink= argument (#6626)
+
+NETLINK_RDMA has been in the kernel since v3.0.
+
+(cherry-picked from commit 5570d7f9561294271591881cf9a249d574069c30)
+
+Resolves: #1494610
+---
+ src/shared/socket-util.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/src/shared/socket-util.c b/src/shared/socket-util.c
+index 79d1582d4..baab6353e 100644
+--- a/src/shared/socket-util.c
++++ b/src/shared/socket-util.c
+@@ -725,7 +725,8 @@ static const char* const netlink_family_table[] = {
+         [NETLINK_KOBJECT_UEVENT] = "kobject-uevent",
+         [NETLINK_GENERIC] = "generic",
+         [NETLINK_SCSITRANSPORT] = "scsitransport",
+-        [NETLINK_ECRYPTFS] = "ecryptfs"
++        [NETLINK_ECRYPTFS] = "ecryptfs",
++        [NETLINK_RDMA] = "rdma",
+ };
+ 
+ DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(netlink_family, int, INT_MAX);
diff --git a/SOURCES/0538-core-namespace-Protect-usr-instead-of-home-with-Prot.patch b/SOURCES/0538-core-namespace-Protect-usr-instead-of-home-with-Prot.patch
new file mode 100644
index 0000000..de5b807
--- /dev/null
+++ b/SOURCES/0538-core-namespace-Protect-usr-instead-of-home-with-Prot.patch
@@ -0,0 +1,29 @@
+From 38d653dbd39cd1e3370e49c5cc7b031a93532e10 Mon Sep 17 00:00:00 2001
+From: Jason Pleau <jason@jpleau.ca>
+Date: Sun, 31 May 2015 12:51:17 -0400
+Subject: [PATCH] core/namespace: Protect /usr instead of /home with
+ ProtectSystem=yes
+
+A small typo in ee818b8 caused /home to be put in read-only instead of
+/usr when ProtectSystem was enabled (ie: not set to "no").
+
+(cherry picked from commit d38e01dc96c5cae1986561c4f3bc7f760560bf2a)
+
+Resolves: #1493047
+---
+ src/core/namespace.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/core/namespace.c b/src/core/namespace.c
+index 574746273..217dd36cb 100644
+--- a/src/core/namespace.c
++++ b/src/core/namespace.c
+@@ -521,7 +521,7 @@ int setup_namespace(
+                 if (protect_system != PROTECT_SYSTEM_NO) {
+                         const char *usr_dir, *boot_dir, *etc_dir;
+ 
+-                        usr_dir = prefix_roota(root_directory, "/home");
++                        usr_dir = prefix_roota(root_directory, "/usr");
+                         boot_dir = prefix_roota(root_directory, "/boot");
+                         boot_dir = strjoina("-", boot_dir);
+                         etc_dir = prefix_roota(root_directory, "/etc");
diff --git a/SOURCES/0539-udev-Use-parent-bus-id-for-virtio-disk-builtin-path-.patch b/SOURCES/0539-udev-Use-parent-bus-id-for-virtio-disk-builtin-path-.patch
new file mode 100644
index 0000000..3edfc86
--- /dev/null
+++ b/SOURCES/0539-udev-Use-parent-bus-id-for-virtio-disk-builtin-path-.patch
@@ -0,0 +1,68 @@
+From 104d13b765fac0308dbd01a1f3a0221504bd0412 Mon Sep 17 00:00:00 2001
+From: Viktor Mihajlovski <mihajlov@linux.vnet.ibm.com>
+Date: Wed, 1 Mar 2017 21:30:17 +0100
+Subject: [PATCH] udev: Use parent bus id for virtio disk builtin path-id
+ (#5500)
+
+The builtin path id for virtio block devices has been changed
+to use the bus id without a prefix "virtio-pci" to be
+compatible with all virtio transport types.
+
+In order to not break existing setups, the by-path symlinks for
+virtio block devices on the PCI bus are reintroduced by udev rules.
+The virtio-pci symlinks are considered to be deprecated and
+should be replaced by the native PCI symlinks.
+
+Example output for a virtio disk in PCI slot 7:
+ $ ls  /dev/disk/by-path
+ pci-0000:00:07.0
+ pci-0000:00:07.0-part1
+ virtio-pci-0000:00:07.0
+ virtio-pci-0000:00:07.0-part1
+
+See also
+[1] https://lists.freedesktop.org/archives/systemd-devel/2017-February/038326.html
+[2] https://lists.freedesktop.org/archives/systemd-devel/2017-March/038397.html
+
+This reverts f073b1b but keeps the same symlinks for compatibility.
+
+(cherry picked from commit fb92fbb1b171ef94207a1ebc111ef0e414d49b4c)
+
+Resolves: #1496697
+---
+ rules/60-persistent-storage.rules | 4 ++++
+ src/udev/udev-builtin-path_id.c   | 5 +----
+ 2 files changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/rules/60-persistent-storage.rules b/rules/60-persistent-storage.rules
+index 06e3329cc..10642a1fd 100644
+--- a/rules/60-persistent-storage.rules
++++ b/rules/60-persistent-storage.rules
+@@ -71,6 +71,10 @@ ENV{DEVTYPE}=="partition", ENV{ID_SAS_PATH}=="?*", SYMLINK+="disk/by-path/$env{I
+ # skip unpartitioned removable media devices from drivers which do not send "change" events
+ ENV{DEVTYPE}=="disk", KERNEL!="sd*|sr*", ATTR{removable}=="1", GOTO="persistent_storage_end"
+ 
++# legacy virtio-pci by-path links (deprecated)
++KERNEL=="vd*[!0-9]", ENV{ID_PATH}=="pci-*", SYMLINK+="disk/by-path/virtio-$env{ID_PATH}"
++KERNEL=="vd*[0-9]", ENV{ID_PATH}=="pci-*", SYMLINK+="disk/by-path/virtio-$env{ID_PATH}-part%n"
++
+ # probe filesystem metadata of optical drives which have a media inserted
+ KERNEL=="sr*", ENV{DISK_EJECT_REQUEST}!="?*", ENV{ID_CDROM_MEDIA_TRACK_COUNT_DATA}=="?*", ENV{ID_CDROM_MEDIA_SESSION_LAST_OFFSET}=="?*", \
+   IMPORT{builtin}="blkid --offset=$env{ID_CDROM_MEDIA_SESSION_LAST_OFFSET}"
+diff --git a/src/udev/udev-builtin-path_id.c b/src/udev/udev-builtin-path_id.c
+index 19447201b..d113ff21b 100644
+--- a/src/udev/udev-builtin-path_id.c
++++ b/src/udev/udev-builtin-path_id.c
+@@ -688,11 +688,8 @@ restart:
+                         parent = skip_subsystem(parent, "xen");
+                         supported_parent = true;
+                 } else if (streq(subsys, "virtio")) {
+-                        while (parent && streq_ptr("virtio", udev_device_get_subsystem(parent)))
+-                                parent = udev_device_get_parent(parent);
+-                        path_prepend(&path, "virtio-pci-%s", udev_device_get_sysname(parent));
++                        parent = skip_subsystem(parent, "virtio");
+                         supported_transport = true;
+-                        supported_parent = true;
+                 } else if (streq(subsys, "scm")) {
+                         path_prepend(&path, "scm-%s", udev_device_get_sysname(parent));
+                         parent = skip_subsystem(parent, "scm");
diff --git a/SOURCES/0540-socket-util-socket_address_parse-should-not-log-erro.patch b/SOURCES/0540-socket-util-socket_address_parse-should-not-log-erro.patch
new file mode 100644
index 0000000..95d622a
--- /dev/null
+++ b/SOURCES/0540-socket-util-socket_address_parse-should-not-log-erro.patch
@@ -0,0 +1,105 @@
+From b2dfc6d1b697da2e649b04ad0b8c3aef7a7d4d88 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Fri, 15 May 2015 20:15:59 +0200
+Subject: [PATCH] socket-util: socket_address_parse() should not log errors on
+ its own
+
+Given that socket_address_parse() is mostly a "library" call it
+shouldn't log on its own, but leave that to its caller.
+
+This patch removes logging from the call in case IPv6 is not available
+but and IPv6 address shall be parsed. Instead a new call
+socket_address_parse_and_warn() is introduced which first invokes
+socket_address_parse() and then logs if necessary.
+
+This should fix "make check" on ipv6-less kernels:
+
+http://lists.freedesktop.org/archives/systemd-devel/2015-April/031385.html
+(cherry picked from commit 7693146dee53a2b0f524e977188347166bf454ca)
+
+Related: #1497639
+---
+ src/core/load-fragment.c |  2 +-
+ src/shared/socket-util.c | 29 +++++++++++++++++++----------
+ src/shared/socket-util.h |  1 +
+ 3 files changed, 21 insertions(+), 11 deletions(-)
+
+diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
+index 58e44b89b..0c0fa0f50 100644
+--- a/src/core/load-fragment.c
++++ b/src/core/load-fragment.c
+@@ -365,7 +365,7 @@ int config_parse_socket_listen(const char *unit,
+                         log_syntax(unit, LOG_ERR, filename, line, -r,
+                                    "Failed to resolve unit specifiers on %s, ignoring: %s", rvalue, strerror(-r));
+ 
+-                r = socket_address_parse(&p->address, k ? k : rvalue);
++                r = socket_address_parse_and_warn(&p->address, k ? k : rvalue);
+                 if (r < 0) {
+                         if (r != -EAFNOSUPPORT)
+                                 log_syntax(unit, LOG_ERR, filename, line, -r,
+diff --git a/src/shared/socket-util.c b/src/shared/socket-util.c
+index baab6353e..b14e36817 100644
+--- a/src/shared/socket-util.c
++++ b/src/shared/socket-util.c
+@@ -55,11 +55,6 @@ int socket_address_parse(SocketAddress *a, const char *s) {
+         if (*s == '[') {
+                 /* IPv6 in [x:.....:z]:p notation */
+ 
+-                if (!socket_ipv6_is_supported()) {
+-                        log_warning("Binding to IPv6 address not available since kernel does not support IPv6.");
+-                        return -EAFNOSUPPORT;
+-                }
+-
+                 e = strchr(s+1, ']');
+                 if (!e)
+                         return -EINVAL;
+@@ -144,11 +139,6 @@ int socket_address_parse(SocketAddress *a, const char *s) {
+                                 if (idx == 0)
+                                         return -EINVAL;
+ 
+-                                if (!socket_ipv6_is_supported()) {
+-                                        log_warning("Binding to interface is not available since kernel does not support IPv6.");
+-                                        return -EAFNOSUPPORT;
+-                                }
+-
+                                 a->sockaddr.in6.sin6_family = AF_INET6;
+                                 a->sockaddr.in6.sin6_port = htons((uint16_t) u);
+                                 a->sockaddr.in6.sin6_scope_id = idx;
+@@ -182,6 +172,25 @@ int socket_address_parse(SocketAddress *a, const char *s) {
+         return 0;
+ }
+ 
++int socket_address_parse_and_warn(SocketAddress *a, const char *s) {
++        SocketAddress b;
++        int r;
++
++        /* Similar to socket_address_parse() but warns for IPv6 sockets when we don't support them. */
++
++        r = socket_address_parse(&b, s);
++        if (r < 0)
++                return r;
++
++        if (!socket_ipv6_is_supported() && b.sockaddr.sa.sa_family == AF_INET6) {
++                log_warning("Binding to IPv6 address not available since kernel does not support IPv6.");
++                return -EAFNOSUPPORT;
++        }
++
++        *a = b;
++        return 0;
++}
++
+ int socket_address_parse_netlink(SocketAddress *a, const char *s) {
+         int family;
+         unsigned group = 0;
+diff --git a/src/shared/socket-util.h b/src/shared/socket-util.h
+index 6bfb677fb..9200ce882 100644
+--- a/src/shared/socket-util.h
++++ b/src/shared/socket-util.h
+@@ -67,6 +67,7 @@ typedef enum SocketAddressBindIPv6Only {
+ #define socket_address_family(a) ((a)->sockaddr.sa.sa_family)
+ 
+ int socket_address_parse(SocketAddress *a, const char *s);
++int socket_address_parse_and_warn(SocketAddress *a, const char *s);
+ int socket_address_parse_netlink(SocketAddress *a, const char *s);
+ int socket_address_print(const SocketAddress *a, char **p);
+ int socket_address_verify(const SocketAddress *a) _pure_;
diff --git a/SOURCES/0541-test-fix-failing-test-socket-util-when-running-with-.patch b/SOURCES/0541-test-fix-failing-test-socket-util-when-running-with-.patch
new file mode 100644
index 0000000..fa938bd
--- /dev/null
+++ b/SOURCES/0541-test-fix-failing-test-socket-util-when-running-with-.patch
@@ -0,0 +1,69 @@
+From 4fbaa65aff7eda3b3965e9c482b08532f3491800 Mon Sep 17 00:00:00 2001
+From: Marcin Bachry <hegel666@gmail.com>
+Date: Wed, 11 Nov 2015 15:45:26 +0100
+Subject: [PATCH] test: fix failing test-socket-util when running with
+ ipv6.disable=1 kernel param
+
+The ability to use inet_pton(AF_INET6, ...) doesn't depend on kernel
+ipv6 support (inet_pton is a pure libc function), so make ipv6 address
+parsing tests unconditional.
+
+(cherry picked from commit 4ebc62ec87162aaa11e077f8693316ecf2d5c58d)
+
+Resolves: #1497639
+---
+ src/test/test-socket-util.c | 41 +++++++++++++++++++----------------------
+ 1 file changed, 19 insertions(+), 22 deletions(-)
+
+diff --git a/src/test/test-socket-util.c b/src/test/test-socket-util.c
+index 6fb4a4094..85f222993 100644
+--- a/src/test/test-socket-util.c
++++ b/src/test/test-socket-util.c
+@@ -38,28 +38,25 @@ static void test_socket_address_parse(void) {
+ 
+         assert_se(socket_address_parse(&a, "65535") >= 0);
+ 
+-        if (socket_ipv6_is_supported()) {
+-                assert_se(socket_address_parse(&a, "[::1]") < 0);
+-                assert_se(socket_address_parse(&a, "[::1]8888") < 0);
+-                assert_se(socket_address_parse(&a, "::1") < 0);
+-                assert_se(socket_address_parse(&a, "[::1]:0") < 0);
+-                assert_se(socket_address_parse(&a, "[::1]:65536") < 0);
+-                assert_se(socket_address_parse(&a, "[a:b:1]:8888") < 0);
+-
+-                assert_se(socket_address_parse(&a, "8888") >= 0);
+-                assert_se(a.sockaddr.sa.sa_family == AF_INET6);
+-
+-                assert_se(socket_address_parse(&a, "[2001:0db8:0000:85a3:0000:0000:ac1f:8001]:8888") >= 0);
+-                assert_se(a.sockaddr.sa.sa_family == AF_INET6);
+-
+-                assert_se(socket_address_parse(&a, "[::1]:8888") >= 0);
+-                assert_se(a.sockaddr.sa.sa_family == AF_INET6);
+-        } else {
+-                assert_se(socket_address_parse(&a, "[::1]:8888") < 0);
+-
+-                assert_se(socket_address_parse(&a, "8888") >= 0);
+-                assert_se(a.sockaddr.sa.sa_family == AF_INET);
+-        }
++        /* The checks below will pass even if ipv6 is disabled in
++         * kernel. The underlying glibc's inet_pton() is just a string
++         * parser and doesn't make any syscalls. */
++
++        assert_se(socket_address_parse(&a, "[::1]") < 0);
++        assert_se(socket_address_parse(&a, "[::1]8888") < 0);
++        assert_se(socket_address_parse(&a, "::1") < 0);
++        assert_se(socket_address_parse(&a, "[::1]:0") < 0);
++        assert_se(socket_address_parse(&a, "[::1]:65536") < 0);
++        assert_se(socket_address_parse(&a, "[a:b:1]:8888") < 0);
++
++        assert_se(socket_address_parse(&a, "8888") >= 0);
++        assert_se(a.sockaddr.sa.sa_family == (socket_ipv6_is_supported() ? AF_INET6 : AF_INET));
++
++        assert_se(socket_address_parse(&a, "[2001:0db8:0000:85a3:0000:0000:ac1f:8001]:8888") >= 0);
++        assert_se(a.sockaddr.sa.sa_family == AF_INET6);
++
++        assert_se(socket_address_parse(&a, "[::1]:8888") >= 0);
++        assert_se(a.sockaddr.sa.sa_family == AF_INET6);
+ 
+         assert_se(socket_address_parse(&a, "192.168.1.254:8888") >= 0);
+         assert_se(a.sockaddr.sa.sa_family == AF_INET);
diff --git a/SOURCES/0542-scsi_id-add-missing-options-to-getopt_long-6501.patch b/SOURCES/0542-scsi_id-add-missing-options-to-getopt_long-6501.patch
new file mode 100644
index 0000000..2f1e33b
--- /dev/null
+++ b/SOURCES/0542-scsi_id-add-missing-options-to-getopt_long-6501.patch
@@ -0,0 +1,25 @@
+From c7eef2f4f985dd427b120fd00a36fd3d7f9a001a Mon Sep 17 00:00:00 2001
+From: Jan Synacek <jan.synacek@gmail.com>
+Date: Wed, 2 Aug 2017 10:12:33 +0200
+Subject: [PATCH] scsi_id: add missing options to getopt_long() (#6501)
+
+(cherry picked from commit ebc6f34a0b2359ac0da41037a1122d3abe02caee)
+
+Resolves: #1476910
+---
+ src/udev/scsi_id/scsi_id.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/udev/scsi_id/scsi_id.c b/src/udev/scsi_id/scsi_id.c
+index a1b8e75fa..eae7e2955 100644
+--- a/src/udev/scsi_id/scsi_id.c
++++ b/src/udev/scsi_id/scsi_id.c
+@@ -333,7 +333,7 @@ static int set_options(struct udev *udev,
+          * file) we have to reset this back to 1.
+          */
+         optind = 1;
+-        while ((option = getopt_long(argc, argv, "d:f:gp:uvVxh", options, NULL)) >= 0)
++        while ((option = getopt_long(argc, argv, "d:f:gp:uvVxhbs:", options, NULL)) >= 0)
+                 switch (option) {
+                 case 'b':
+                         all_good = false;
diff --git a/SOURCES/0543-unmount-Pass-in-mount-options-when-remounting-read-o.patch b/SOURCES/0543-unmount-Pass-in-mount-options-when-remounting-read-o.patch
new file mode 100644
index 0000000..addea4f
--- /dev/null
+++ b/SOURCES/0543-unmount-Pass-in-mount-options-when-remounting-read-o.patch
@@ -0,0 +1,104 @@
+From 06456e9d3235921c13e0e2f86a68e41a930aae0c Mon Sep 17 00:00:00 2001
+From: Jan Janssen <medhefgo@web.de>
+Date: Mon, 26 Oct 2015 15:13:28 +0100
+Subject: [PATCH] unmount: Pass in mount options when remounting read-only
+
+man 2 mount says that the mountflags and data parameteres should
+match the original values except for the desired changes. We only
+bother with the mount options since the only flags we can change
+are MS_RDONLY, MS_SYNCHRONOUS and MS_MANDLOCK; which shouldn't
+matter too much.
+
+Fixes: #351
+
+(cherry picked from commit 471b48ed2ff6539e7071ff4694c03483c5835639)
+
+Related: #1312002
+---
+ src/core/umount.c | 26 ++++++++++++++++++++------
+ 1 file changed, 20 insertions(+), 6 deletions(-)
+
+diff --git a/src/core/umount.c b/src/core/umount.c
+index dd7df194d..bfd8aa5f8 100644
+--- a/src/core/umount.c
++++ b/src/core/umount.c
+@@ -28,6 +28,7 @@
+ #include <linux/loop.h>
+ #include <linux/dm-ioctl.h>
+ 
++#include "fstab-util.h"
+ #include "list.h"
+ #include "mount-setup.h"
+ #include "umount.h"
+@@ -39,6 +40,7 @@
+ 
+ typedef struct MountPoint {
+         char *path;
++        char *options;
+         dev_t devnum;
+         LIST_FIELDS(struct MountPoint, mount_point);
+ } MountPoint;
+@@ -71,7 +73,7 @@ static int mount_points_list_get(MountPoint **head) {
+                 return -errno;
+ 
+         for (i = 1;; i++) {
+-                _cleanup_free_ char *path = NULL;
++                _cleanup_free_ char *path = NULL, *options = NULL;
+                 char *p = NULL;
+                 MountPoint *m;
+                 int k;
+@@ -82,15 +84,15 @@ static int mount_points_list_get(MountPoint **head) {
+                            "%*s "       /* (3) major:minor */
+                            "%*s "       /* (4) root */
+                            "%ms "       /* (5) mount point */
+-                           "%*s"        /* (6) mount options */
++                           "%*s"        /* (6) mount flags */
+                            "%*[^-]"     /* (7) optional fields */
+                            "- "         /* (8) separator */
+                            "%*s "       /* (9) file system type */
+                            "%*s"        /* (10) mount source */
+-                           "%*s"        /* (11) mount options 2 */
++                           "%ms"        /* (11) mount options */
+                            "%*[^\n]",   /* some rubbish at the end */
+-                           &path);
+-                if (k != 1) {
++                           &path, &options);
++                if (k != 2) {
+                         if (k == EOF)
+                                 break;
+ 
+@@ -125,6 +127,9 @@ static int mount_points_list_get(MountPoint **head) {
+                 }
+ 
+                 m->path = p;
++                m->options = options;
++                options = NULL;
++
+                 LIST_PREPEND(mount_point, *head, m);
+         }
+ 
+@@ -368,6 +373,14 @@ static int mount_points_list_umount(MountPoint **head, bool *changed, bool log_e
+                    benefits, but might confuse the host, as we remount
+                    the superblock here, not the bind mound. */
+                 if (detect_container(NULL) <= 0)  {
++                        _cleanup_free_ char *options = NULL;
++                        /* MS_REMOUNT requires that the data parameter
++                         * should be the same from the original mount
++                         * except for the desired changes. Since we want
++                         * to remount read-only, we should filter out
++                         * rw (and ro too, because it confuses the kernel) */
++                        (void) fstab_filter_options(m->options, "rw\0ro\0", NULL, NULL, &options);
++
+                         /* We always try to remount directories
+                          * read-only first, before we go on and umount
+                          * them.
+@@ -384,7 +397,8 @@ static int mount_points_list_umount(MountPoint **head, bool *changed, bool log_e
+                          * alias read-only we hence should be
+                          * relatively safe regarding keeping the fs we
+                          * can otherwise not see dirty. */
+-                        mount(NULL, m->path, NULL, MS_REMOUNT|MS_RDONLY, NULL);
++                        log_info("Remounting '%s' read-only with options '%s'.", m->path, options);
++                        (void) mount(NULL, m->path, NULL, MS_REMOUNT|MS_RDONLY, options);
+                 }
+ 
+                 /* Skip / and /usr since we cannot unmount that
diff --git a/SOURCES/0544-shutdown-don-t-remount-ro-network-filesystems.-6588.patch b/SOURCES/0544-shutdown-don-t-remount-ro-network-filesystems.-6588.patch
new file mode 100644
index 0000000..bc4ca5e
--- /dev/null
+++ b/SOURCES/0544-shutdown-don-t-remount-ro-network-filesystems.-6588.patch
@@ -0,0 +1,76 @@
+From f70113f32c25b8d1c7d87eb812556c91b4b9b5c6 Mon Sep 17 00:00:00 2001
+From: NeilBrown <neil@brown.name>
+Date: Thu, 31 Aug 2017 02:48:25 +1000
+Subject: [PATCH] shutdown: don't remount,ro network filesystems. (#6588)
+
+systemd-shutdown is run after the network is stopped,
+so remounting a network filesystem read-only can hang.
+A simple umount is the most useful thing that can
+be done for a network filesystem once the network is down.
+
+(cherry picked from commit 9cbc4547702aac28466c497f720038b9e2dc510c)
+
+Resolves: #1312002
+---
+ src/core/umount.c | 17 ++++++++++++-----
+ 1 file changed, 12 insertions(+), 5 deletions(-)
+
+diff --git a/src/core/umount.c b/src/core/umount.c
+index bfd8aa5f8..6e8ccc794 100644
+--- a/src/core/umount.c
++++ b/src/core/umount.c
+@@ -41,6 +41,7 @@
+ typedef struct MountPoint {
+         char *path;
+         char *options;
++        char *type;
+         dev_t devnum;
+         LIST_FIELDS(struct MountPoint, mount_point);
+ } MountPoint;
+@@ -73,7 +74,7 @@ static int mount_points_list_get(MountPoint **head) {
+                 return -errno;
+ 
+         for (i = 1;; i++) {
+-                _cleanup_free_ char *path = NULL, *options = NULL;
++                _cleanup_free_ char *path = NULL, *options = NULL, *type = NULL;
+                 char *p = NULL;
+                 MountPoint *m;
+                 int k;
+@@ -87,11 +88,11 @@ static int mount_points_list_get(MountPoint **head) {
+                            "%*s"        /* (6) mount flags */
+                            "%*[^-]"     /* (7) optional fields */
+                            "- "         /* (8) separator */
+-                           "%*s "       /* (9) file system type */
++                           "%ms "       /* (9) file system type */
+                            "%*s"        /* (10) mount source */
+                            "%ms"        /* (11) mount options */
+                            "%*[^\n]",   /* some rubbish at the end */
+-                           &path, &options);
++                           &path, &type, &options);
+                 if (k != 2) {
+                         if (k == EOF)
+                                 break;
+@@ -129,6 +130,8 @@ static int mount_points_list_get(MountPoint **head) {
+                 m->path = p;
+                 m->options = options;
+                 options = NULL;
++                m->type = type;
++                type = NULL;
+ 
+                 LIST_PREPEND(mount_point, *head, m);
+         }
+@@ -371,8 +374,12 @@ static int mount_points_list_umount(MountPoint **head, bool *changed, bool log_e
+                 /* If we are in a container, don't attempt to
+                    read-only mount anything as that brings no real
+                    benefits, but might confuse the host, as we remount
+-                   the superblock here, not the bind mound. */
+-                if (detect_container(NULL) <= 0)  {
++                   the superblock here, not the bind mount.
++                   If the filesystem is a network fs, also skip the
++                   remount.  It brings no value (we cannot leave
++                   a "dirty fs") and could hang if the network is down.  */
++                if (detect_container(NULL) <= 0 &&
++                    !fstype_is_network(m->type)) {
+                         _cleanup_free_ char *options = NULL;
+                         /* MS_REMOUNT requires that the data parameter
+                          * should be the same from the original mount
diff --git a/SOURCES/0545-shutdown-fix-incorrect-fscanf-result-check-6806.patch b/SOURCES/0545-shutdown-fix-incorrect-fscanf-result-check-6806.patch
new file mode 100644
index 0000000..0b18ab2
--- /dev/null
+++ b/SOURCES/0545-shutdown-fix-incorrect-fscanf-result-check-6806.patch
@@ -0,0 +1,29 @@
+From 4ee75042124dbc675fa68d2dadfdcf866d772de8 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Wed, 13 Sep 2017 10:08:37 +0200
+Subject: [PATCH] shutdown: fix incorrect fscanf() result check (#6806)
+
+A correction for 090e3c9796ef6468d4f396610804d62f6ffd797f.
+
+Fixes: #6796
+
+(cherry-picked from: 3d4ec01269244c2d35a781abf748ea9ba57666e2)
+
+Related: #1312002
+---
+ src/core/umount.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/core/umount.c b/src/core/umount.c
+index 6e8ccc794..3eec0d459 100644
+--- a/src/core/umount.c
++++ b/src/core/umount.c
+@@ -93,7 +93,7 @@ static int mount_points_list_get(MountPoint **head) {
+                            "%ms"        /* (11) mount options */
+                            "%*[^\n]",   /* some rubbish at the end */
+                            &path, &type, &options);
+-                if (k != 2) {
++                if (k != 3) {
+                         if (k == EOF)
+                                 break;
+ 
diff --git a/SOURCES/0546-path-util-make-use-of-mnt_id-field-exported-in-proc-.patch b/SOURCES/0546-path-util-make-use-of-mnt_id-field-exported-in-proc-.patch
new file mode 100644
index 0000000..7e4c532
--- /dev/null
+++ b/SOURCES/0546-path-util-make-use-of-mnt_id-field-exported-in-proc-.patch
@@ -0,0 +1,407 @@
+From e5ac7ba7a16445f3ad23d9931979c20214eae913 Mon Sep 17 00:00:00 2001
+From: Jan Synacek <jsynacek@redhat.com>
+Date: Thu, 14 Sep 2017 16:27:08 +0200
+Subject: [PATCH] path-util: make use of "mnt_id" field exported in
+ /proc/self/fdinfo/<fd>
+
+This commit is not a backport of a specific commit. It includes parts of
+several upstream commits (3f72b427b44f39a1aec6806dad6f6b57103ae9ed,
+5d409034017e9f9f8c4392157d95511fc2e05d87 and others).
+
+The main goal was to bring path_is_mount_point() up to date, which meant
+introducing fd_fdinfo_mnt_id() and fd_is_mount_point(). These were
+needed mainly because we need to determine mount points based on
+/proc/self/fdinfo/<fd> in containers. Also, there are more places in the
+code where checks for mount points are performed, which would benefit from
+this fix as well. Additionally, corresponding tests has been added.
+
+Resolves: #1472439
+---
+ src/nspawn/nspawn.c       |   2 +-
+ src/shared/path-util.c    | 219 ++++++++++++++++++++++++++++++++++++----------
+ src/shared/path-util.h    |   1 +
+ src/test/test-path-util.c |  62 +++++++++++++
+ 4 files changed, 235 insertions(+), 49 deletions(-)
+
+diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
+index ea365b3f9..ee2e1832f 100644
+--- a/src/nspawn/nspawn.c
++++ b/src/nspawn/nspawn.c
+@@ -990,7 +990,7 @@ static int mount_cgroup_hierarchy(const char *dest, const char *controller, cons
+         to = strjoina(dest, "/sys/fs/cgroup/", hierarchy);
+ 
+         r = path_is_mount_point(to, false);
+-        if (r < 0)
++        if (r < 0 && r != -ENOENT)
+                 return log_error_errno(r, "Failed to determine if %s is mounted already: %m", to);
+         if (r > 0)
+                 return 0;
+diff --git a/src/shared/path-util.c b/src/shared/path-util.c
+index 1181ffb9d..5d4de9ec4 100644
+--- a/src/shared/path-util.c
++++ b/src/shared/path-util.c
+@@ -36,6 +36,7 @@
+ #include "strv.h"
+ #include "path-util.h"
+ #include "missing.h"
++#include "fileio.h"
+ 
+ bool path_is_absolute(const char *p) {
+         return p[0] == '/';
+@@ -473,87 +474,209 @@ char* path_join(const char *root, const char *path, const char *rest) {
+                                NULL);
+ }
+ 
+-int path_is_mount_point(const char *t, bool allow_symlink) {
++static int fd_fdinfo_mnt_id(int fd, const char *filename, int flags, int *mnt_id) {
++        char path[strlen("/proc/self/fdinfo/") + DECIMAL_STR_MAX(int)];
++        _cleanup_free_ char *fdinfo = NULL;
++        _cleanup_close_ int subfd = -1;
++        char *p;
++        int r;
++
++        if ((flags & AT_EMPTY_PATH) && isempty(filename))
++                xsprintf(path, "/proc/self/fdinfo/%i", fd);
++        else {
++                subfd = openat(fd, filename, O_CLOEXEC|O_PATH);
++                if (subfd < 0)
++                        return -errno;
+ 
+-        union file_handle_union h = FILE_HANDLE_INIT;
++                xsprintf(path, "/proc/self/fdinfo/%i", subfd);
++        }
++
++        r = read_full_file(path, &fdinfo, NULL);
++        if (r == -ENOENT) /* The fdinfo directory is a relatively new addition */
++                return -EOPNOTSUPP;
++        if (r < 0)
++                return -errno;
++
++        p = startswith(fdinfo, "mnt_id:");
++        if (!p) {
++                p = strstr(fdinfo, "\nmnt_id:");
++                if (!p) /* The mnt_id field is a relatively new addition */
++                        return -EOPNOTSUPP;
++
++                p += 8;
++        }
++
++        p += strspn(p, WHITESPACE);
++        p[strcspn(p, WHITESPACE)] = 0;
++
++        return safe_atoi(p, mnt_id);
++}
++
++int fd_is_mount_point(int fd, const char *filename, int flags) {
++        union file_handle_union h = FILE_HANDLE_INIT, h_parent = FILE_HANDLE_INIT;
+         int mount_id = -1, mount_id_parent = -1;
+-        _cleanup_free_ char *parent = NULL;
++        bool nosupp = false, check_st_dev = true;
+         struct stat a, b;
+         int r;
+-        bool nosupp = false;
+ 
+-        /* We are not actually interested in the file handles, but
+-         * name_to_handle_at() also passes us the mount ID, hence use
+-         * it but throw the handle away */
++        assert(fd >= 0);
++        assert(filename);
+ 
+-        if (path_equal(t, "/"))
+-                return 1;
+-
+-        r = name_to_handle_at(AT_FDCWD, t, &h.handle, &mount_id, allow_symlink ? AT_SYMLINK_FOLLOW : 0);
++        /* First we will try the name_to_handle_at() syscall, which
++         * tells us the mount id and an opaque file "handle". It is
++         * not supported everywhere though (kernel compile-time
++         * option, not all file systems are hooked up). If it works
++         * the mount id is usually good enough to tell us whether
++         * something is a mount point.
++         *
++         * If that didn't work we will try to read the mount id from
++         * /proc/self/fdinfo/<fd>. This is almost as good as
++         * name_to_handle_at(), however, does not return the
++         * opaque file handle. The opaque file handle is pretty useful
++         * to detect the root directory, which we should always
++         * consider a mount point. Hence we use this only as
++         * fallback. Exporting the mnt_id in fdinfo is a pretty recent
++         * kernel addition.
++         *
++         * As last fallback we do traditional fstat() based st_dev
++         * comparisons. This is how things were traditionally done,
++         * but unionfs breaks this since it exposes file
++         * systems with a variety of st_dev reported. Also, btrfs
++         * subvolumes have different st_dev, even though they aren't
++         * real mounts of their own. */
++
++        r = name_to_handle_at(fd, filename, &h.handle, &mount_id, flags);
+         if (r < 0) {
+-                if (errno == ENOSYS)
+-                        /* This kernel does not support name_to_handle_at()
+-                         * fall back to the traditional stat() logic. */
+-                        goto fallback;
++                if (IN_SET(errno, ENOSYS, EACCES, EPERM))
++                        /* This kernel does not support name_to_handle_at() at all, or the syscall was blocked (maybe
++                         * through seccomp, because we are running inside of a container?): fall back to simpler
++                         * logic. */
++                        goto fallback_fdinfo;
+                 else if (errno == EOPNOTSUPP)
+                         /* This kernel or file system does not support
+-                         * name_to_handle_at(), hence fallback to the
++                         * name_to_handle_at(), hence let's see if the
++                         * upper fs supports it (in which case it is a
++                         * mount point), otherwise fallback to the
+                          * traditional stat() logic */
+                         nosupp = true;
+-                else if (errno == ENOENT)
+-                        return 0;
+                 else
+                         return -errno;
+         }
+ 
+-        r = path_get_parent(t, &parent);
+-        if (r < 0)
+-                return r;
+-
+-        h.handle.handle_bytes = MAX_HANDLE_SZ;
+-        r = name_to_handle_at(AT_FDCWD, parent, &h.handle, &mount_id_parent, AT_SYMLINK_FOLLOW);
+-        if (r < 0)
+-                if (errno == EOPNOTSUPP)
++        r = name_to_handle_at(fd, "", &h_parent.handle, &mount_id_parent, AT_EMPTY_PATH);
++        if (r < 0) {
++                if (errno == EOPNOTSUPP) {
+                         if (nosupp)
+                                 /* Neither parent nor child do name_to_handle_at()?
+                                    We have no choice but to fall back. */
+-                                goto fallback;
++                                goto fallback_fdinfo;
+                         else
+-                                /* The parent can't do name_to_handle_at() but
+-                                 * the directory we are interested in can?
+-                                 * Or the other way around?
++                                /* The parent can't do name_to_handle_at() but the
++                                 * directory we are interested in can?
+                                  * If so, it must be a mount point. */
+                                 return 1;
+-                else
++                } else
+                         return -errno;
+-        else
+-                return mount_id != mount_id_parent;
++        }
+ 
+-fallback:
+-        if (allow_symlink)
+-                r = stat(t, &a);
+-        else
+-                r = lstat(t, &a);
++        /* The parent can do name_to_handle_at() but the
++         * directory we are interested in can't? If so, it
++         * must be a mount point. */
++        if (nosupp)
++                return 1;
+ 
+-        if (r < 0) {
+-                if (errno == ENOENT)
+-                        return 0;
++        /* If the file handle for the directory we are
++         * interested in and its parent are identical, we
++         * assume this is the root directory, which is a mount
++         * point. */
+ 
+-                return -errno;
+-        }
++        if (h.handle.handle_bytes == h_parent.handle.handle_bytes &&
++            h.handle.handle_type == h_parent.handle.handle_type &&
++            memcmp(h.handle.f_handle, h_parent.handle.f_handle, h.handle.handle_bytes) == 0)
++                return 1;
+ 
+-        free(parent);
+-        parent = NULL;
++        return mount_id != mount_id_parent;
+ 
+-        r = path_get_parent(t, &parent);
++fallback_fdinfo:
++        r = fd_fdinfo_mnt_id(fd, filename, flags, &mount_id);
++        if (IN_SET(r, -EOPNOTSUPP, -EACCES, -EPERM))
++                goto fallback_fstat;
+         if (r < 0)
+                 return r;
+ 
+-        r = stat(parent, &b);
++        r = fd_fdinfo_mnt_id(fd, "", AT_EMPTY_PATH, &mount_id_parent);
+         if (r < 0)
++                return r;
++
++        if (mount_id != mount_id_parent)
++                return 1;
++
++        /* Hmm, so, the mount ids are the same. This leaves one
++         * special case though for the root file system. For that,
++         * let's see if the parent directory has the same inode as we
++         * are interested in. Hence, let's also do fstat() checks now,
++         * too, but avoid the st_dev comparisons, since they aren't
++         * that useful on unionfs mounts. */
++        check_st_dev = false;
++
++fallback_fstat:
++        /* yay for fstatat() taking a different set of flags than the other
++         * _at() above */
++        if (flags & AT_SYMLINK_FOLLOW)
++                flags &= ~AT_SYMLINK_FOLLOW;
++        else
++                flags |= AT_SYMLINK_NOFOLLOW;
++        if (fstatat(fd, filename, &a, flags) < 0)
++                return -errno;
++
++        if (fstatat(fd, "", &b, AT_EMPTY_PATH) < 0)
++                return -errno;
++
++        /* A directory with same device and inode as its parent? Must
++         * be the root directory */
++        if (a.st_dev == b.st_dev &&
++            a.st_ino == b.st_ino)
++                return 1;
++
++        return check_st_dev && (a.st_dev != b.st_dev);
++}
++
++
++
++int path_is_mount_point(const char *t, bool allow_symlink) {
++        _cleanup_free_ char *canonical = NULL, *parent = NULL;
++        _cleanup_close_ int fd = -1;
++        int flags = allow_symlink ? AT_SYMLINK_FOLLOW : 0;
++
++        assert(t);
++
++        if (path_equal(t, "/"))
++                return 1;
++
++        /* we need to resolve symlinks manually, we can't just rely on
++         * fd_is_mount_point() to do that for us; if we have a structure like
++         * /bin -> /usr/bin/ and /usr is a mount point, then the parent that we
++         * look at needs to be /usr, not /. */
++        if (flags & AT_SYMLINK_FOLLOW) {
++                canonical = canonicalize_file_name(t);
++                if (!canonical) {
++                        if (errno == ENOENT)
++                                return 0;
++                        else
++                                return -errno;
++                }
++                t = canonical;
++        }
++
++        parent = dirname_malloc(t);
++        if (!parent)
++                return -ENOMEM;
++
++        fd = openat(AT_FDCWD, parent, O_DIRECTORY|O_CLOEXEC|O_PATH);
++        if (fd < 0)
+                 return -errno;
+ 
+-        return a.st_dev != b.st_dev;
++        return fd_is_mount_point(fd, basename(t), flags);
+ }
+ 
+ int path_is_read_only_fs(const char *path) {
+diff --git a/src/shared/path-util.h b/src/shared/path-util.h
+index 71bb740e9..34c016229 100644
+--- a/src/shared/path-util.h
++++ b/src/shared/path-util.h
+@@ -53,6 +53,7 @@ char** path_strv_make_absolute_cwd(char **l);
+ char** path_strv_resolve(char **l, const char *prefix);
+ char** path_strv_resolve_uniq(char **l, const char *prefix);
+ 
++int fd_is_mount_point(int fd, const char *filename, int flags);
+ int path_is_mount_point(const char *path, bool allow_symlink);
+ int path_is_read_only_fs(const char *path);
+ int path_is_os_tree(const char *path);
+diff --git a/src/test/test-path-util.c b/src/test/test-path-util.c
+index 6396fcb39..a4fec07e7 100644
+--- a/src/test/test-path-util.c
++++ b/src/test/test-path-util.c
+@@ -21,6 +21,7 @@
+ 
+ #include <stdio.h>
+ #include <unistd.h>
++#include <sys/mount.h>
+ 
+ #include "path-util.h"
+ #include "util.h"
+@@ -99,6 +100,66 @@ static void test_path(void) {
+         }
+ }
+ 
++static void test_path_is_mount_point(void) {
++        int fd, rt, rf, rlt, rlf;
++        char tmp_dir[] = "/tmp/test-path-is-mount-point-XXXXXX";
++        _cleanup_free_ char *file1 = NULL, *file2 = NULL, *link1 = NULL, *link2 = NULL;
++
++        assert_se(path_is_mount_point("/", true) > 0);
++        assert_se(path_is_mount_point("/", false) > 0);
++
++        assert_se(path_is_mount_point("/proc", true) > 0);
++        assert_se(path_is_mount_point("/proc", false) > 0);
++
++        assert_se(path_is_mount_point("/proc/1", true) == 0);
++        assert_se(path_is_mount_point("/proc/1", false) == 0);
++
++        assert_se(path_is_mount_point("/sys", true) > 0);
++        assert_se(path_is_mount_point("/sys", false) > 0);
++
++        /* file mountpoints */
++        assert_se(mkdtemp(tmp_dir) != NULL);
++        file1 = path_join(NULL, tmp_dir, "file1");
++        assert_se(file1);
++        file2 = path_join(NULL, tmp_dir, "file2");
++        assert_se(file2);
++        fd = open(file1, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, 0664);
++        assert_se(fd > 0);
++        close(fd);
++        fd = open(file2, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, 0664);
++        assert_se(fd > 0);
++        close(fd);
++        link1 = path_join(NULL, tmp_dir, "link1");
++        assert_se(link1);
++        assert_se(symlink("file1", link1) == 0);
++        link2 = path_join(NULL, tmp_dir, "link2");
++        assert_se(link1);
++        assert_se(symlink("file2", link2) == 0);
++
++        assert_se(path_is_mount_point(file1, true) == 0);
++        assert_se(path_is_mount_point(file1, false) == 0);
++        assert_se(path_is_mount_point(link1, true) == 0);
++        assert_se(path_is_mount_point(link1, false) == 0);
++
++        /* this test will only work as root */
++        if (mount(file1, file2, NULL, MS_BIND, NULL) >= 0) {
++                rf = path_is_mount_point(file2, false);
++                rt = path_is_mount_point(file2, true);
++                rlf = path_is_mount_point(link2, false);
++                rlt = path_is_mount_point(link2, true);
++
++                assert_se(umount(file2) == 0);
++
++                assert_se(rf == 1);
++                assert_se(rt == 1);
++                assert_se(rlf == 0);
++                assert_se(rlt == 1);
++        } else
++                printf("Skipping bind mount file test: %m\n");
++
++        assert_se(rm_rf(tmp_dir, false, true, false) == 0);
++}
++
+ static void test_find_binary(const char *self, bool local) {
+         char *p;
+ 
+@@ -288,6 +349,7 @@ int main(int argc, char **argv) {
+         test_make_relative();
+         test_strv_resolve();
+         test_path_startswith();
++        test_path_is_mount_point();
+ 
+         return 0;
+ }
diff --git a/SOURCES/0547-support-ranges-when-parsing-CPUAffinity.patch b/SOURCES/0547-support-ranges-when-parsing-CPUAffinity.patch
new file mode 100644
index 0000000..971fe38
--- /dev/null
+++ b/SOURCES/0547-support-ranges-when-parsing-CPUAffinity.patch
@@ -0,0 +1,621 @@
+From 6e00430563108b98230abd7407ac54fde61ae93c Mon Sep 17 00:00:00 2001
+From: Jan Synacek <jsynacek@redhat.com>
+Date: Tue, 26 Sep 2017 12:34:19 +0200
+Subject: [PATCH] support ranges when parsing CPUAffinity
+
+The functionality was implemented in https://github.com/systemd/systemd/pull/1699/.
+However, it is not backportable without considerable code changes.
+
+Implement parse_range() and parse_cpu_set_and_warn() from the upstream master
+branch and use them in appropriate places. Also introduce relevant tests.
+
+Resolves: #1493976
+---
+ src/core/load-fragment.c |  49 +++-----
+ src/core/main.c          |  48 ++------
+ src/shared/util.c        |  91 +++++++++++++++
+ src/shared/util.h        |   9 ++
+ src/test/test-util.c     | 296 +++++++++++++++++++++++++++++++++++++++++++++++
+ 5 files changed, 417 insertions(+), 76 deletions(-)
+
+diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
+index 0c0fa0f50..a10e1903a 100644
+--- a/src/core/load-fragment.c
++++ b/src/core/load-fragment.c
+@@ -884,50 +884,29 @@ int config_parse_exec_cpu_affinity(const char *unit,
+                                    void *userdata) {
+ 
+         ExecContext *c = data;
+-        const char *word, *state;
+-        size_t l;
++        _cleanup_cpu_free_ cpu_set_t *cpuset = NULL;
++        int ncpus;
+ 
+         assert(filename);
+         assert(lvalue);
+         assert(rvalue);
+         assert(data);
+ 
+-        if (isempty(rvalue)) {
+-                /* An empty assignment resets the CPU list */
+-                if (c->cpuset)
+-                        CPU_FREE(c->cpuset);
+-                c->cpuset = NULL;
+-                return 0;
+-        }
+-
+-        FOREACH_WORD_QUOTED(word, l, rvalue, state) {
+-                _cleanup_free_ char *t = NULL;
+-                int r;
+-                unsigned cpu;
+-
+-                t = strndup(word, l);
+-                if (!t)
+-                        return log_oom();
+-
+-                r = safe_atou(t, &cpu);
++        ncpus = parse_cpu_set_and_warn(rvalue, &cpuset, unit, filename, line, lvalue);
++        if (ncpus < 0)
++                return ncpus;
+ 
+-                if (!c->cpuset) {
+-                        c->cpuset = cpu_set_malloc(&c->cpuset_ncpus);
+-                        if (!c->cpuset)
+-                                return log_oom();
+-                }
++        if (c->cpuset)
++                CPU_FREE(c->cpuset);
+ 
+-                if (r < 0 || cpu >= c->cpuset_ncpus) {
+-                        log_syntax(unit, LOG_ERR, filename, line, ERANGE,
+-                                   "Failed to parse CPU affinity '%s', ignoring: %s", t, rvalue);
+-                        return 0;
+-                }
+-
+-                CPU_SET_S(cpu, CPU_ALLOC_SIZE(c->cpuset_ncpus), c->cpuset);
++        if (ncpus == 0)
++                /* An empty assignment resets the CPU list */
++                c->cpuset = NULL;
++        else {
++                c->cpuset = cpuset;
++                cpuset = NULL;
+         }
+-        if (!isempty(state))
+-                log_syntax(unit, LOG_WARNING, filename, line, EINVAL,
+-                           "Trailing garbage, ignoring.");
++        c->cpuset_ncpus = ncpus;
+ 
+         return 0;
+ }
+diff --git a/src/core/main.c b/src/core/main.c
+index 66393ed6a..5554ef468 100644
+--- a/src/core/main.c
++++ b/src/core/main.c
+@@ -438,49 +438,15 @@ static int config_parse_cpu_affinity2(
+                 void *data,
+                 void *userdata) {
+ 
+-        const char *word, *state;
+-        size_t l;
+-        cpu_set_t *c = NULL;
+-        unsigned ncpus = 0;
+-
+-        assert(filename);
+-        assert(lvalue);
+-        assert(rvalue);
++        _cleanup_cpu_free_ cpu_set_t *c = NULL;
++        int ncpus;
+ 
+-        FOREACH_WORD_QUOTED(word, l, rvalue, state) {
+-                char *t;
+-                int r;
+-                unsigned cpu;
+-
+-                if (!(t = strndup(word, l)))
+-                        return log_oom();
+-
+-                r = safe_atou(t, &cpu);
+-                free(t);
+-
+-                if (!c)
+-                        if (!(c = cpu_set_malloc(&ncpus)))
+-                                return log_oom();
++        ncpus = parse_cpu_set_and_warn(rvalue, &c, unit, filename, line, lvalue);
++        if (ncpus < 0)
++                return ncpus;
+ 
+-                if (r < 0 || cpu >= ncpus) {
+-                        log_syntax(unit, LOG_ERR, filename, line, -r,
+-                                   "Failed to parse CPU affinity '%s'", rvalue);
+-                        CPU_FREE(c);
+-                        return -EBADMSG;
+-                }
+-
+-                CPU_SET_S(cpu, CPU_ALLOC_SIZE(ncpus), c);
+-        }
+-        if (!isempty(state))
+-                log_syntax(unit, LOG_ERR, filename, line, EINVAL,
+-                           "Trailing garbage, ignoring.");
+-
+-        if (c) {
+-                if (sched_setaffinity(0, CPU_ALLOC_SIZE(ncpus), c) < 0)
+-                        log_unit_warning(unit, "Failed to set CPU affinity: %m");
+-
+-                CPU_FREE(c);
+-        }
++        if (sched_setaffinity(0, CPU_ALLOC_SIZE(ncpus), c) < 0)
++                log_warning_errno(errno, "Failed to set CPU affinity: %m");
+ 
+         return 0;
+ }
+diff --git a/src/shared/util.c b/src/shared/util.c
+index bbb457759..39359fcc8 100644
+--- a/src/shared/util.c
++++ b/src/shared/util.c
+@@ -2727,6 +2727,43 @@ int parse_size(const char *t, off_t base, off_t *size) {
+         return 0;
+ }
+ 
++int parse_range(const char *t, unsigned *lower, unsigned *upper) {
++        _cleanup_free_ char *word = NULL;
++        unsigned l, u;
++        int r;
++
++        assert(lower);
++        assert(upper);
++
++        /* Extract the lower bound. */
++        r = extract_first_word(&t, &word, "-", EXTRACT_DONT_COALESCE_SEPARATORS);
++        if (r < 0)
++                return r;
++        if (r == 0)
++                return -EINVAL;
++
++        r = safe_atou(word, &l);
++        if (r < 0)
++                return r;
++
++        /* Check for the upper bound and extract it if needed */
++        if (!t)
++                /* Single number with no dashes. */
++                u = l;
++        else if (!*t)
++                /* Trailing dash is an error. */
++                return -EINVAL;
++        else {
++                r = safe_atou(t, &u);
++                if (r < 0)
++                        return r;
++        }
++
++        *lower = l;
++        *upper = u;
++        return 0;
++}
++
+ int make_stdio(int fd) {
+         int r, s, t;
+ 
+@@ -3460,6 +3497,60 @@ cpu_set_t* cpu_set_malloc(unsigned *ncpus) {
+         }
+ }
+ 
++int parse_cpu_set_and_warn(
++                const char *rvalue,
++                cpu_set_t **cpu_set,
++                const char *unit,
++                const char *filename,
++                unsigned line,
++                const char *lvalue) {
++
++        const char *whole_rvalue = rvalue;
++        _cleanup_cpu_free_ cpu_set_t *c = NULL;
++        unsigned ncpus = 0;
++
++        assert(lvalue);
++        assert(rvalue);
++
++        for (;;) {
++                _cleanup_free_ char *word = NULL;
++                unsigned cpu, cpu_lower, cpu_upper;
++                int r;
++
++                r = extract_first_word(&rvalue, &word, WHITESPACE ",", EXTRACT_QUOTES);
++                if (r < 0)
++                        return log_syntax(unit, LOG_ERR, filename, line, r, "Invalid value for %s: %s", lvalue, whole_rvalue);
++                if (r == 0)
++                        break;
++
++                if (!c) {
++                        c = cpu_set_malloc(&ncpus);
++                        if (!c)
++                                return log_oom();
++                }
++
++                r = parse_range(word, &cpu_lower, &cpu_upper);
++                if (r < 0)
++                        return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse CPU affinity '%s'", word);
++                if (cpu_lower >= ncpus || cpu_upper >= ncpus)
++                        return log_syntax(unit, LOG_ERR, filename, line, EINVAL, "CPU out of range '%s' ncpus is %u", word, ncpus);
++
++                if (cpu_lower > cpu_upper)
++                        log_syntax(unit, LOG_WARNING, filename, line, 0, "Range '%s' is invalid, %u > %u", word, cpu_lower, cpu_upper);
++                else
++                        for (cpu = cpu_lower; cpu <= cpu_upper; cpu++)
++                                CPU_SET_S(cpu, CPU_ALLOC_SIZE(ncpus), c);
++        }
++
++        /* On success, sets *cpu_set and returns ncpus for the system. */
++        if (c) {
++                *cpu_set = c;
++                c = NULL;
++        }
++
++        return (int) ncpus;
++}
++
+ int status_vprintf(const char *status, bool ellipse, bool ephemeral, const char *format, va_list ap) {
+         static const char status_indent[] = "         "; /* "[" STATUS "] " */
+         _cleanup_free_ char *s = NULL;
+diff --git a/src/shared/util.h b/src/shared/util.h
+index 80ad18c0a..526a6fe84 100644
+--- a/src/shared/util.h
++++ b/src/shared/util.h
+@@ -136,6 +136,11 @@ bool streq_ptr(const char *a, const char *b) _pure_;
+ 
+ #define malloc0(n) (calloc((n), 1))
+ 
++static inline void *mfree(void *memory) {
++        free(memory);
++        return NULL;
++}
++
+ static inline const char* yes_no(bool b) {
+         return b ? "yes" : "no";
+ }
+@@ -195,6 +200,7 @@ void safe_close_pair(int p[]);
+ void close_many(const int fds[], unsigned n_fd);
+ 
+ int parse_size(const char *t, off_t base, off_t *size);
++int parse_range(const char *t, unsigned *lower, unsigned *upper);
+ 
+ int parse_boolean(const char *v) _pure_;
+ int parse_pid(const char *s, pid_t* ret_pid);
+@@ -474,6 +480,7 @@ int rm_rf_dangerous(const char *path, bool only_dirs, bool delete_root, bool hon
+ int pipe_eof(int fd);
+ 
+ cpu_set_t* cpu_set_malloc(unsigned *ncpus);
++int parse_cpu_set_and_warn(const char *rvalue, cpu_set_t **cpu_set, const char *unit, const char *filename, unsigned line, const char *lvalue);
+ 
+ int status_vprintf(const char *status, bool ellipse, bool ephemeral, const char *format, va_list ap) _printf_(4,0);
+ int status_printf(const char *status, bool ellipse, bool ephemeral, const char *format, ...) _printf_(4,5);
+@@ -692,6 +699,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(FILE*, fclose);
+ DEFINE_TRIVIAL_CLEANUP_FUNC(FILE*, pclose);
+ DEFINE_TRIVIAL_CLEANUP_FUNC(DIR*, closedir);
+ DEFINE_TRIVIAL_CLEANUP_FUNC(FILE*, endmntent);
++DEFINE_TRIVIAL_CLEANUP_FUNC(cpu_set_t*, CPU_FREE);
+ 
+ #define _cleanup_free_ _cleanup_(freep)
+ #define _cleanup_close_ _cleanup_(closep)
+@@ -702,6 +710,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(FILE*, endmntent);
+ #define _cleanup_closedir_ _cleanup_(closedirp)
+ #define _cleanup_endmntent_ _cleanup_(endmntentp)
+ #define _cleanup_close_pair_ _cleanup_(close_pairp)
++#define _cleanup_cpu_free_ _cleanup_(CPU_FREEp)
+ 
+ _malloc_  _alloc_(1, 2) static inline void *malloc_multiply(size_t a, size_t b) {
+         if (_unlikely_(b != 0 && a > ((size_t) -1) / b))
+diff --git a/src/test/test-util.c b/src/test/test-util.c
+index 971f97d7c..fcf5416c0 100644
+--- a/src/test/test-util.c
++++ b/src/test/test-util.c
+@@ -689,6 +689,300 @@ static void test_parse_size(void) {
+         assert_se(parse_size("-10B 20K", 1024, &bytes) == -ERANGE);
+ }
+ 
++static void test_parse_range(void) {
++        unsigned lower, upper;
++
++        /* Successful cases */
++        assert_se(parse_range("111", &lower, &upper) == 0);
++        assert_se(lower == 111);
++        assert_se(upper == 111);
++
++        assert_se(parse_range("111-123", &lower, &upper) == 0);
++        assert_se(lower == 111);
++        assert_se(upper == 123);
++
++        assert_se(parse_range("123-111", &lower, &upper) == 0);
++        assert_se(lower == 123);
++        assert_se(upper == 111);
++
++        assert_se(parse_range("123-123", &lower, &upper) == 0);
++        assert_se(lower == 123);
++        assert_se(upper == 123);
++
++        assert_se(parse_range("0", &lower, &upper) == 0);
++        assert_se(lower == 0);
++        assert_se(upper == 0);
++
++        assert_se(parse_range("0-15", &lower, &upper) == 0);
++        assert_se(lower == 0);
++        assert_se(upper == 15);
++
++        assert_se(parse_range("15-0", &lower, &upper) == 0);
++        assert_se(lower == 15);
++        assert_se(upper == 0);
++
++        assert_se(parse_range("128-65535", &lower, &upper) == 0);
++        assert_se(lower == 128);
++        assert_se(upper == 65535);
++
++        assert_se(parse_range("1024-4294967295", &lower, &upper) == 0);
++        assert_se(lower == 1024);
++        assert_se(upper == 4294967295);
++
++        /* Leading whitespace is acceptable */
++        assert_se(parse_range(" 111", &lower, &upper) == 0);
++        assert_se(lower == 111);
++        assert_se(upper == 111);
++
++        assert_se(parse_range(" 111-123", &lower, &upper) == 0);
++        assert_se(lower == 111);
++        assert_se(upper == 123);
++
++        assert_se(parse_range("111- 123", &lower, &upper) == 0);
++        assert_se(lower == 111);
++        assert_se(upper == 123);
++
++        assert_se(parse_range("\t111-\t123", &lower, &upper) == 0);
++        assert_se(lower == 111);
++        assert_se(upper == 123);
++
++        assert_se(parse_range(" \t 111- \t 123", &lower, &upper) == 0);
++        assert_se(lower == 111);
++        assert_se(upper == 123);
++
++        /* Error cases, make sure they fail as expected */
++        lower = upper = 9999;
++        assert_se(parse_range("111garbage", &lower, &upper) == -EINVAL);
++        assert_se(lower == 9999);
++        assert_se(upper == 9999);
++
++        assert_se(parse_range("garbage111", &lower, &upper) == -EINVAL);
++        assert_se(lower == 9999);
++        assert_se(upper == 9999);
++
++        assert_se(parse_range("garbage", &lower, &upper) == -EINVAL);
++        assert_se(lower == 9999);
++        assert_se(upper == 9999);
++
++        assert_se(parse_range("111-123garbage", &lower, &upper) == -EINVAL);
++        assert_se(lower == 9999);
++        assert_se(upper == 9999);
++
++        assert_se(parse_range("111garbage-123", &lower, &upper) == -EINVAL);
++        assert_se(lower == 9999);
++        assert_se(upper == 9999);
++
++        /* Empty string */
++        lower = upper = 9999;
++        assert_se(parse_range("", &lower, &upper) == -EINVAL);
++        assert_se(lower == 9999);
++        assert_se(upper == 9999);
++
++        /* 111--123 will pass -123 to safe_atou which returns -ERANGE for negative */
++        assert_se(parse_range("111--123", &lower, &upper) == -ERANGE);
++        assert_se(lower == 9999);
++        assert_se(upper == 9999);
++
++        assert_se(parse_range("-111-123", &lower, &upper) == -EINVAL);
++        assert_se(lower == 9999);
++        assert_se(upper == 9999);
++
++        assert_se(parse_range("111-123-", &lower, &upper) == -EINVAL);
++        assert_se(lower == 9999);
++        assert_se(upper == 9999);
++
++        assert_se(parse_range("111.4-123", &lower, &upper) == -EINVAL);
++        assert_se(lower == 9999);
++        assert_se(upper == 9999);
++
++        assert_se(parse_range("111-123.4", &lower, &upper) == -EINVAL);
++        assert_se(lower == 9999);
++        assert_se(upper == 9999);
++
++        assert_se(parse_range("111,4-123", &lower, &upper) == -EINVAL);
++        assert_se(lower == 9999);
++        assert_se(upper == 9999);
++
++        assert_se(parse_range("111-123,4", &lower, &upper) == -EINVAL);
++        assert_se(lower == 9999);
++        assert_se(upper == 9999);
++
++        /* Error on trailing dash */
++        assert_se(parse_range("111-", &lower, &upper) == -EINVAL);
++        assert_se(lower == 9999);
++        assert_se(upper == 9999);
++
++        assert_se(parse_range("111-123-", &lower, &upper) == -EINVAL);
++        assert_se(lower == 9999);
++        assert_se(upper == 9999);
++
++        assert_se(parse_range("111--", &lower, &upper) == -EINVAL);
++        assert_se(lower == 9999);
++        assert_se(upper == 9999);
++
++        assert_se(parse_range("111- ", &lower, &upper) == -EINVAL);
++        assert_se(lower == 9999);
++        assert_se(upper == 9999);
++
++        /* Whitespace is not a separator */
++        assert_se(parse_range("111 123", &lower, &upper) == -EINVAL);
++        assert_se(lower == 9999);
++        assert_se(upper == 9999);
++
++        assert_se(parse_range("111\t123", &lower, &upper) == -EINVAL);
++        assert_se(lower == 9999);
++        assert_se(upper == 9999);
++
++        assert_se(parse_range("111 \t 123", &lower, &upper) == -EINVAL);
++        assert_se(lower == 9999);
++        assert_se(upper == 9999);
++
++        /* Trailing whitespace is invalid (from safe_atou) */
++        assert_se(parse_range("111 ", &lower, &upper) == -EINVAL);
++        assert_se(lower == 9999);
++        assert_se(upper == 9999);
++
++        assert_se(parse_range("111-123 ", &lower, &upper) == -EINVAL);
++        assert_se(lower == 9999);
++        assert_se(upper == 9999);
++
++        assert_se(parse_range("111 -123", &lower, &upper) == -EINVAL);
++        assert_se(lower == 9999);
++        assert_se(upper == 9999);
++
++        assert_se(parse_range("111 -123 ", &lower, &upper) == -EINVAL);
++        assert_se(lower == 9999);
++        assert_se(upper == 9999);
++
++        assert_se(parse_range("111\t-123\t", &lower, &upper) == -EINVAL);
++        assert_se(lower == 9999);
++        assert_se(upper == 9999);
++
++        assert_se(parse_range("111 \t -123 \t ", &lower, &upper) == -EINVAL);
++        assert_se(lower == 9999);
++        assert_se(upper == 9999);
++
++        /* Out of the "unsigned" range, this is 1<<64 */
++        assert_se(parse_range("0-18446744073709551616", &lower, &upper) == -ERANGE);
++        assert_se(lower == 9999);
++        assert_se(upper == 9999);
++}
++
++static void test_parse_cpu_set(void) {
++        cpu_set_t *c = NULL;
++        int ncpus;
++        int cpu;
++
++        /* Simple range (from CPUAffinity example) */
++        ncpus = parse_cpu_set_and_warn("1 2", &c, NULL, "fake", 1, "CPUAffinity");
++        assert_se(ncpus >= 1024);
++        assert_se(CPU_ISSET_S(1, CPU_ALLOC_SIZE(ncpus), c));
++        assert_se(CPU_ISSET_S(2, CPU_ALLOC_SIZE(ncpus), c));
++        assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 2);
++        c = mfree(c);
++
++        /* A more interesting range */
++        ncpus = parse_cpu_set_and_warn("0 1 2 3 8 9 10 11", &c, NULL, "fake", 1, "CPUAffinity");
++        assert_se(ncpus >= 1024);
++        assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8);
++        for (cpu = 0; cpu < 4; cpu++)
++                assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
++        for (cpu = 8; cpu < 12; cpu++)
++                assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
++        c = mfree(c);
++
++        /* Quoted strings */
++        ncpus = parse_cpu_set_and_warn("8 '9' 10 \"11\"", &c, NULL, "fake", 1, "CPUAffinity");
++        assert_se(ncpus >= 1024);
++        assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 4);
++        for (cpu = 8; cpu < 12; cpu++)
++                assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
++        c = mfree(c);
++
++        /* Use commas as separators */
++        ncpus = parse_cpu_set_and_warn("0,1,2,3 8,9,10,11", &c, NULL, "fake", 1, "CPUAffinity");
++        assert_se(ncpus >= 1024);
++        assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8);
++        for (cpu = 0; cpu < 4; cpu++)
++                assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
++        for (cpu = 8; cpu < 12; cpu++)
++                assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
++        c = mfree(c);
++
++        /* Commas with spaces (and trailing comma, space) */
++        ncpus = parse_cpu_set_and_warn("0, 1, 2, 3, 4, 5, 6, 7, ", &c, NULL, "fake", 1, "CPUAffinity");
++        assert_se(ncpus >= 1024);
++        assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8);
++        for (cpu = 0; cpu < 8; cpu++)
++                assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
++        c = mfree(c);
++
++        /* Ranges */
++        ncpus = parse_cpu_set_and_warn("0-3,8-11", &c, NULL, "fake", 1, "CPUAffinity");
++        assert_se(ncpus >= 1024);
++        assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8);
++        for (cpu = 0; cpu < 4; cpu++)
++                assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
++        for (cpu = 8; cpu < 12; cpu++)
++                assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
++        c = mfree(c);
++
++        /* Ranges with trailing comma, space */
++        ncpus = parse_cpu_set_and_warn("0-3  8-11, ", &c, NULL, "fake", 1, "CPUAffinity");
++        assert_se(ncpus >= 1024);
++        assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8);
++        for (cpu = 0; cpu < 4; cpu++)
++                assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
++        for (cpu = 8; cpu < 12; cpu++)
++                assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
++        c = mfree(c);
++
++        /* Negative range (returns empty cpu_set) */
++        ncpus = parse_cpu_set_and_warn("3-0", &c, NULL, "fake", 1, "CPUAffinity");
++        assert_se(ncpus >= 1024);
++        assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 0);
++        c = mfree(c);
++
++        /* Overlapping ranges */
++        ncpus = parse_cpu_set_and_warn("0-7 4-11", &c, NULL, "fake", 1, "CPUAffinity");
++        assert_se(ncpus >= 1024);
++        assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 12);
++        for (cpu = 0; cpu < 12; cpu++)
++                assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
++        c = mfree(c);
++
++        /* Mix ranges and individual CPUs */
++        ncpus = parse_cpu_set_and_warn("0,1 4-11", &c, NULL, "fake", 1, "CPUAffinity");
++        assert_se(ncpus >= 1024);
++        assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 10);
++        assert_se(CPU_ISSET_S(0, CPU_ALLOC_SIZE(ncpus), c));
++        assert_se(CPU_ISSET_S(1, CPU_ALLOC_SIZE(ncpus), c));
++        for (cpu = 4; cpu < 12; cpu++)
++                assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
++        c = mfree(c);
++
++        /* Garbage */
++        ncpus = parse_cpu_set_and_warn("0 1 2 3 garbage", &c, NULL, "fake", 1, "CPUAffinity");
++        assert_se(ncpus < 0);
++        assert_se(!c);
++
++        /* Range with garbage */
++        ncpus = parse_cpu_set_and_warn("0-3 8-garbage", &c, NULL, "fake", 1, "CPUAffinity");
++        assert_se(ncpus < 0);
++        assert_se(!c);
++
++        /* Empty string */
++        c = NULL;
++        ncpus = parse_cpu_set_and_warn("", &c, NULL, "fake", 1, "CPUAffinity");
++        assert_se(ncpus == 0);  /* empty string returns 0 */
++        assert_se(!c);
++
++        /* Runaway quoted string */
++        ncpus = parse_cpu_set_and_warn("0 1 2 3 \"4 5 6 7 ", &c, NULL, "fake", 1, "CPUAffinity");
++        assert_se(ncpus < 0);
++        assert_se(!c);
++}
++
+ static void test_config_parse_iec_off(void) {
+         off_t offset = 0;
+         assert_se(config_parse_iec_off(NULL, "/this/file", 11, "Section", 22, "Size", 0, "4M", &offset, NULL) == 0);
+@@ -1605,6 +1899,8 @@ int main(int argc, char *argv[]) {
+         test_get_process_comm();
+         test_protect_errno();
+         test_parse_size();
++        test_parse_range();
++        test_parse_cpu_set();
+         test_config_parse_iec_off();
+         test_strextend();
+         test_strrep();
diff --git a/SOURCES/0548-man-Update-man-page-documentation-for-CPUAffinity.patch b/SOURCES/0548-man-Update-man-page-documentation-for-CPUAffinity.patch
new file mode 100644
index 0000000..3eebde9
--- /dev/null
+++ b/SOURCES/0548-man-Update-man-page-documentation-for-CPUAffinity.patch
@@ -0,0 +1,51 @@
+From 99afbf6e7fac9f33f0f96c0397c413ba360607a2 Mon Sep 17 00:00:00 2001
+From: Filipe Brandenburger <filbranden@google.com>
+Date: Tue, 13 Oct 2015 00:12:39 -0700
+Subject: [PATCH] man: Update man page documentation for CPUAffinity
+
+Document support for commas as a separator and possibility of specifying
+ranges of CPU indices.
+
+Tested by regenerating the manpages locally and reading them on man.
+
+(cherry picked from commit 71b1c27a406271b71f64487ae70b58f44a4a37f0)
+Resolves: #1493976
+---
+ man/systemd-system.conf.xml | 6 ++++--
+ man/systemd.exec.xml        | 6 ++++--
+ 2 files changed, 8 insertions(+), 4 deletions(-)
+
+diff --git a/man/systemd-system.conf.xml b/man/systemd-system.conf.xml
+index 53e8ff665..1861bb03f 100644
+--- a/man/systemd-system.conf.xml
++++ b/man/systemd-system.conf.xml
+@@ -117,8 +117,10 @@
+         <term><varname>CPUAffinity=</varname></term>
+ 
+         <listitem><para>Configures the initial CPU affinity for the
+-        init process. Takes a space-separated list of CPU
+-        indices.</para></listitem>
++        init process. Takes a list of CPU indices or ranges separated
++        by either whitespace or commas. CPU ranges are specified by
++        the lower and upper CPU indices separated by a
++        dash.</para></listitem>
+       </varlistentry>
+ 
+       <varlistentry>
+diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml
+index 508146f06..d7503b8e8 100644
+--- a/man/systemd.exec.xml
++++ b/man/systemd.exec.xml
+@@ -211,8 +211,10 @@
+         <term><varname>CPUAffinity=</varname></term>
+ 
+         <listitem><para>Controls the CPU affinity of the executed
+-        processes. Takes a space-separated list of CPU indices. This
+-        option may be specified more than once in which case the
++        processes. Takes a list of CPU indices or ranges separated by
++        either whitespace or commas. CPU ranges are specified by the
++        lower and upper CPU indices separated by a dash.
++        This option may be specified more than once in which case the
+         specified CPU affinity masks are merged. If the empty string
+         is assigned, the mask is reset, all assignments prior to this
+         will have no effect. See
diff --git a/SOURCES/0549-test-path-util-force-rm_rf.patch b/SOURCES/0549-test-path-util-force-rm_rf.patch
new file mode 100644
index 0000000..eb867e1
--- /dev/null
+++ b/SOURCES/0549-test-path-util-force-rm_rf.patch
@@ -0,0 +1,28 @@
+From 6e3239eed032eaf0c9a6308664a9034e64c98d30 Mon Sep 17 00:00:00 2001
+From: Lukas Nykryn <lnykryn@redhat.com>
+Date: Fri, 13 Oct 2017 13:29:14 +0200
+Subject: [PATCH] test-path-util: force rm_rf
+
+On rhel we don't have tmpfs in /tmp, so simple rm_rf will
+refuse to remove the test directory.
+
+RHEL-only
+
+Related: #1472439
+---
+ src/test/test-path-util.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/test/test-path-util.c b/src/test/test-path-util.c
+index a4fec07e7..aee1f4e03 100644
+--- a/src/test/test-path-util.c
++++ b/src/test/test-path-util.c
+@@ -157,7 +157,7 @@ static void test_path_is_mount_point(void) {
+         } else
+                 printf("Skipping bind mount file test: %m\n");
+ 
+-        assert_se(rm_rf(tmp_dir, false, true, false) == 0);
++        assert_se(rm_rf_dangerous(tmp_dir, false, true, false) == 0);
+ }
+ 
+ static void test_find_binary(const char *self, bool local) {
diff --git a/SOURCES/0550-Export-NVMe-WWID-udev-attribute-5348.patch b/SOURCES/0550-Export-NVMe-WWID-udev-attribute-5348.patch
new file mode 100644
index 0000000..e4e4964
--- /dev/null
+++ b/SOURCES/0550-Export-NVMe-WWID-udev-attribute-5348.patch
@@ -0,0 +1,28 @@
+From c9c86577937088e36bcfb67e701aebe51d2cc893 Mon Sep 17 00:00:00 2001
+From: Keith Busch <keith.busch@intel.com>
+Date: Fri, 17 Feb 2017 00:46:06 -0700
+Subject: [PATCH] Export NVMe WWID udev attribute (#5348)
+
+We need this for multipath support without relying on NVMe to SCSI
+translations.
+
+Signed-off-by: Keith Busch <keith.busch@intel.com>
+
+Cherry-picked from: 5c1be4f73082d09011661516c39fb53626d8bdc7
+Resolves: #1503253
+---
+ rules/60-persistent-storage.rules | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/rules/60-persistent-storage.rules b/rules/60-persistent-storage.rules
+index 10642a1fd..ba619633b 100644
+--- a/rules/60-persistent-storage.rules
++++ b/rules/60-persistent-storage.rules
+@@ -27,6 +27,7 @@ KERNEL=="nvme*[0-9]n*[0-9]", ATTR{wwid}=="?*", SYMLINK+="disk/by-id/nvme-$attr{w
+ KERNEL=="nvme*[0-9]n*[0-9]p*[0-9]", ENV{DEVTYPE}=="partition", ATTRS{wwid}=="?*", SYMLINK+="disk/by-id/nvme-$attr{wwid}-part%n"
+ 
+ KERNEL=="nvme*[0-9]n*[0-9]", ENV{DEVTYPE}=="disk", ATTRS{serial}=="?*", ENV{ID_SERIAL_SHORT}="$attr{serial}"
++KERNEL=="nvme*[0-9]n*[0-9]", ENV{DEVTYPE}=="disk", ATTRS{wwid}=="?*", ENV{ID_WWN}="$attr{wwid}"
+ KERNEL=="nvme*[0-9]n*[0-9]", ENV{DEVTYPE}=="disk", ATTRS{model}=="?*", ENV{ID_SERIAL_SHORT}=="?*", ENV{ID_SERIAL}="$attr{model}_$env{ID_SERIAL_SHORT}", SYMLINK+="disk/by-id/nvme-$env{ID_SERIAL}", OPTIONS="string_escape=replace"
+ 
+ KERNEL=="nvme*[0-9]n*[0-9]p*[0-9]", ENV{DEVTYPE}=="partition", ATTRS{serial}=="?*", ENV{ID_SERIAL_SHORT}="$attr{serial}"
diff --git a/SOURCES/0551-mount-make-sure-we-unmount-tmpfs-mounts-before-we-de.patch b/SOURCES/0551-mount-make-sure-we-unmount-tmpfs-mounts-before-we-de.patch
new file mode 100644
index 0000000..6115327
--- /dev/null
+++ b/SOURCES/0551-mount-make-sure-we-unmount-tmpfs-mounts-before-we-de.patch
@@ -0,0 +1,122 @@
+From e7e3e1d230c15079a3d1480c47076ffd89f1de63 Mon Sep 17 00:00:00 2001
+From: Michal Sekletar <msekletar@users.noreply.github.com>
+Date: Mon, 16 Oct 2017 16:15:05 +0200
+Subject: [PATCH] mount: make sure we unmount tmpfs mounts before we deactivate
+ swaps (#7076)
+
+In the past we introduced this property just for tmp.mount. However on
+todays systems usually there are many more tmpfs mounts. Most notably
+mounts backing XDG_RUNTIME_DIR for each user.
+
+Let's generalize what we already have for tmp.mount and implement the
+ordering After=swap.target for all tmpfs based mounts.
+
+(cherry picked from commit fab35afabf01a5dea651187a1ccb5ae7cd778f9d)
+
+Conflicts:
+	src/core/mount.h
+
+Resolves: #1437518
+---
+ src/core/dbus-mount.c | 10 +---------
+ src/core/mount.c      | 24 ++++++++++++++++++++++++
+ src/core/mount.h      |  1 +
+ units/tmp.mount       |  1 -
+ 4 files changed, 26 insertions(+), 10 deletions(-)
+
+diff --git a/src/core/dbus-mount.c b/src/core/dbus-mount.c
+index 53fe4edc3..04beba631 100644
+--- a/src/core/dbus-mount.c
++++ b/src/core/dbus-mount.c
+@@ -90,20 +90,12 @@ static int property_get_type(
+                 sd_bus_error *error) {
+ 
+         Mount *m = userdata;
+-        const char *d;
+ 
+         assert(bus);
+         assert(reply);
+         assert(m);
+ 
+-        if (m->from_proc_self_mountinfo && m->parameters_proc_self_mountinfo.fstype)
+-                d = m->parameters_proc_self_mountinfo.fstype;
+-        else if (m->from_fragment && m->parameters_fragment.fstype)
+-                d = m->parameters_fragment.fstype;
+-        else
+-                d = "";
+-
+-        return sd_bus_message_append(reply, "s", d);
++        return sd_bus_message_append(reply, "s", mount_get_fstype(m));
+ }
+ 
+ static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, mount_result, MountResult);
+diff --git a/src/core/mount.c b/src/core/mount.c
+index 7ca7f5a25..a6d93b869 100644
+--- a/src/core/mount.c
++++ b/src/core/mount.c
+@@ -119,6 +119,21 @@ static bool needs_quota(const MountParameters *p) {
+                                  "usrquota\0" "grpquota\0" "quota\0" "usrjquota\0" "grpjquota\0");
+ }
+ 
++const char *mount_get_fstype(const Mount *m) {
++        const char *type = NULL;
++
++        assert(m);
++
++        if (m->from_proc_self_mountinfo && m->parameters_proc_self_mountinfo.fstype)
++                type = m->parameters_proc_self_mountinfo.fstype;
++        else if (m->from_fragment && m->parameters_fragment.fstype)
++                type = m->parameters_fragment.fstype;
++        else
++                type = "";
++
++        return type;
++}
++
+ static void mount_init(Unit *u) {
+         Mount *m = MOUNT(u);
+ 
+@@ -236,6 +251,7 @@ _pure_ static MountParameters* get_mount_parameters(Mount *m) {
+ 
+ static int mount_add_mount_links(Mount *m) {
+         _cleanup_free_ char *parent = NULL;
++        const char *fstype;
+         MountParameters *pm;
+         Unit *other;
+         Iterator i;
+@@ -292,6 +308,14 @@ static int mount_add_mount_links(Mount *m) {
+                 }
+         }
+ 
++        /* If this is a tmpfs mount then we have to unmount it before we try to deactivate swaps */
++        fstype = mount_get_fstype(m);
++        if (streq(fstype, "tmpfs")) {
++                r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, SPECIAL_SWAP_TARGET, NULL, true);
++                if (r < 0)
++                        return r;
++        }
++
+         return 0;
+ }
+ 
+diff --git a/src/core/mount.h b/src/core/mount.h
+index d6987e6fa..353222000 100644
+--- a/src/core/mount.h
++++ b/src/core/mount.h
+@@ -130,3 +130,4 @@ const char* mount_result_to_string(MountResult i) _const_;
+ MountResult mount_result_from_string(const char *s) _pure_;
+ 
+ void warn_if_dir_nonempty(const char *unit, const char* where);
++const char *mount_get_fstype(const Mount *m);
+diff --git a/units/tmp.mount b/units/tmp.mount
+index 8c53a8705..af0cf4a55 100644
+--- a/units/tmp.mount
++++ b/units/tmp.mount
+@@ -13,7 +13,6 @@ ConditionPathIsSymbolicLink=!/tmp
+ DefaultDependencies=no
+ Conflicts=umount.target
+ Before=local-fs.target umount.target
+-After=swap.target
+ 
+ [Mount]
+ What=tmpfs
diff --git a/SOURCES/0552-journald-never-accept-fds-from-file-systems-with-man.patch b/SOURCES/0552-journald-never-accept-fds-from-file-systems-with-man.patch
new file mode 100644
index 0000000..6203c9e
--- /dev/null
+++ b/SOURCES/0552-journald-never-accept-fds-from-file-systems-with-man.patch
@@ -0,0 +1,67 @@
+From 6d9aff83ef5d50a65fad4f4218073bd4aa3e6902 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Tue, 10 Nov 2015 20:08:04 +0100
+Subject: [PATCH] journald: never accept fds from file systems with mandatory
+ locking enabled
+
+This is pretty much a work-around for a security vulnerability in
+kernels that allow unprivileged user namespaces.
+
+Fixes #1822.
+
+Cherry-picked from: 1e603a482f57edb1fb863dbf23b868cf5854e004
+Resolves: #1501017
+---
+ src/journal/journald-native.c | 30 ++++++++++++++++++++++++++++++
+ 1 file changed, 30 insertions(+)
+
+diff --git a/src/journal/journald-native.c b/src/journal/journald-native.c
+index 2c9cf6e7a..fdb1a38dd 100644
+--- a/src/journal/journald-native.c
++++ b/src/journal/journald-native.c
+@@ -23,6 +23,7 @@
+ #include <stddef.h>
+ #include <sys/epoll.h>
+ #include <sys/mman.h>
++#include <sys/statvfs.h>
+ 
+ #include "socket-util.h"
+ #include "path-util.h"
+@@ -391,8 +392,37 @@ void server_process_native_file(
+                 assert_se(munmap(p, ps) >= 0);
+         } else {
+                 _cleanup_free_ void *p = NULL;
++                struct statvfs vfs;
+                 ssize_t n;
+ 
++                if (fstatvfs(fd, &vfs) < 0) {
++                        log_error_errno(errno, "Failed to stat file system of passed file, ignoring: %m");
++                        return;
++                }
++
++                /* Refuse operating on file systems that have
++                 * mandatory locking enabled, see:
++                 *
++                 * https://github.com/systemd/systemd/issues/1822
++                 */
++                if (vfs.f_flag & ST_MANDLOCK) {
++                        log_error("Received file descriptor from file system with mandatory locking enable, refusing.");
++                        return;
++                }
++
++                /* Make the fd non-blocking. On regular files this has
++                 * the effect of bypassing mandatory locking. Of
++                 * course, this should normally not be necessary given
++                 * the check above, but let's better be safe than
++                 * sorry, after all NFS is pretty confusing regarding
++                 * file system flags, and we better don't trust it,
++                 * and so is SMB. */
++                r = fd_nonblock(fd, true);
++                if (r < 0) {
++                        log_error_errno(r, "Failed to make fd non-blocking, ignoring: %m");
++                        return;
++                }
++
+                 /* The file is not sealed, we can't map the file here, since
+                  * clients might then truncate it and trigger a SIGBUS for
+                  * us. So let's stupidly read it */
diff --git a/SOURCES/0553-udev-builtin-keyboard-move-fetching-the-device-node-.patch b/SOURCES/0553-udev-builtin-keyboard-move-fetching-the-device-node-.patch
new file mode 100644
index 0000000..cf020a9
--- /dev/null
+++ b/SOURCES/0553-udev-builtin-keyboard-move-fetching-the-device-node-.patch
@@ -0,0 +1,52 @@
+From 7d6891da40f2f5cfbc5bf02b6a58dc49c1577373 Mon Sep 17 00:00:00 2001
+From: Peter Hutterer <peter.hutterer@who-t.net>
+Date: Fri, 20 Mar 2015 12:48:24 +1000
+Subject: [PATCH] udev: builtin-keyboard: move fetching the device node up
+
+No point parsing the properties if we can't get the devnode to apply them
+later. Plus, this makes future additions easier to slot in.
+
+(cherry picked from commit 753bd5c7ede5e74c21221fcf59de3ce320d6722d)
+
+Resolves: #1500119
+---
+ src/udev/udev-builtin-keyboard.c | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+diff --git a/src/udev/udev-builtin-keyboard.c b/src/udev/udev-builtin-keyboard.c
+index d8ee4cbb6..bde7bf07f 100644
+--- a/src/udev/udev-builtin-keyboard.c
++++ b/src/udev/udev-builtin-keyboard.c
+@@ -75,6 +75,13 @@ static int builtin_keyboard(struct udev_device *dev, int argc, char *argv[], boo
+         unsigned map_count = 0;
+         unsigned release[1024];
+         unsigned release_count = 0;
++        const char *node;
++
++        node = udev_device_get_devnode(dev);
++        if (!node) {
++                log_error("Error, no device node for '%s'", udev_device_get_syspath(dev));
++                return EXIT_FAILURE;
++        }
+ 
+         udev_list_entry_foreach(entry, udev_device_get_properties_list_entry(dev)) {
+                 const char *key;
+@@ -128,17 +135,10 @@ static int builtin_keyboard(struct udev_device *dev, int argc, char *argv[], boo
+         }
+ 
+         if (map_count > 0 || release_count > 0) {
+-                const char *node;
+                 int fd;
+                 unsigned i;
+ 
+-                node = udev_device_get_devnode(dev);
+-                if (!node) {
+-                        log_error("Error, no device node for '%s'", udev_device_get_syspath(dev));
+-                        return EXIT_FAILURE;
+-                }
+-
+-                fd = open(udev_device_get_devnode(dev), O_RDWR|O_CLOEXEC|O_NONBLOCK|O_NOCTTY);
++                fd = open(node, O_RDWR|O_CLOEXEC|O_NONBLOCK|O_NOCTTY);
+                 if (fd < 0) {
+                         log_error_errno(errno, "Error, opening device '%s': %m", node);
+                         return EXIT_FAILURE;
diff --git a/SOURCES/0554-udev-builtin-keyboard-immediately-EVIOCSKEYCODE-when.patch b/SOURCES/0554-udev-builtin-keyboard-immediately-EVIOCSKEYCODE-when.patch
new file mode 100644
index 0000000..129e378
--- /dev/null
+++ b/SOURCES/0554-udev-builtin-keyboard-immediately-EVIOCSKEYCODE-when.patch
@@ -0,0 +1,90 @@
+From 4f9b03c28555799f8672b905323bf6d1f95eb13f Mon Sep 17 00:00:00 2001
+From: Peter Hutterer <peter.hutterer@who-t.net>
+Date: Fri, 20 Mar 2015 12:52:46 +1000
+Subject: [PATCH] udev: builtin-keyboard: immediately EVIOCSKEYCODE when we
+ have a pair
+
+Rather than building a map and looping through the map, immediately call the
+ioctl when we have a successfully parsed property.
+
+This has a side-effect: before the maximum number of ioctls was limited to the
+size of the map (1024), now it is unlimited.
+
+(cherry picked from commit cfba2656e3b4a9c5e03db4ec0a8f76c3762d35a8)
+
+Resolves: #1500119
+---
+ src/udev/udev-builtin-keyboard.c | 45 ++++++++++++++++------------------------
+ 1 file changed, 18 insertions(+), 27 deletions(-)
+
+diff --git a/src/udev/udev-builtin-keyboard.c b/src/udev/udev-builtin-keyboard.c
+index bde7bf07f..515edd45c 100644
+--- a/src/udev/udev-builtin-keyboard.c
++++ b/src/udev/udev-builtin-keyboard.c
+@@ -71,10 +71,10 @@ static int builtin_keyboard(struct udev_device *dev, int argc, char *argv[], boo
+         struct {
+                 unsigned scan;
+                 unsigned key;
+-        } map[1024];
+-        unsigned map_count = 0;
++        } map;
+         unsigned release[1024];
+         unsigned release_count = 0;
++        _cleanup_close_ int fd = -1;
+         const char *node;
+ 
+         node = udev_device_get_devnode(dev);
+@@ -128,37 +128,28 @@ static int builtin_keyboard(struct udev_device *dev, int argc, char *argv[], boo
+                         }
+                 }
+ 
+-                map[map_count].scan = scancode;
+-                map[map_count].key = keycode_num;
+-                if (map_count < ELEMENTSOF(map)-1)
+-                        map_count++;
+-        }
+-
+-        if (map_count > 0 || release_count > 0) {
+-                int fd;
+-                unsigned i;
+-
+-                fd = open(node, O_RDWR|O_CLOEXEC|O_NONBLOCK|O_NOCTTY);
+-                if (fd < 0) {
+-                        log_error_errno(errno, "Error, opening device '%s': %m", node);
+-                        return EXIT_FAILURE;
++                if (fd == -1) {
++                        fd = open(node, O_RDWR|O_CLOEXEC|O_NONBLOCK|O_NOCTTY);
++                        if (fd < 0) {
++                                log_error_errno(errno, "Error, opening device '%s': %m", node);
++                                return EXIT_FAILURE;
++                        }
+                 }
+ 
+-                /* install list of map codes */
+-                for (i = 0; i < map_count; i++) {
+-                        log_debug("keyboard: mapping scan code %d (0x%x) to key code %d (0x%x)",
+-                                  map[i].scan, map[i].scan, map[i].key, map[i].key);
+-                        if (ioctl(fd, EVIOCSKEYCODE, &map[i]) < 0)
+-                                log_error_errno(errno, "Error calling EVIOCSKEYCODE on device node '%s' (scan code 0x%x, key code %d): %m", node, map[i].scan, map[i].key);
+-                }
++                map.scan = scancode;
++                map.key = keycode_num;
+ 
+-                /* install list of force-release codes */
+-                if (release_count > 0)
+-                        install_force_release(dev, release, release_count);
++                log_debug("keyboard: mapping scan code %d (0x%x) to key code %d (0x%x)",
++                          map.scan, map.scan, map.key, map.key);
+ 
+-                close(fd);
++                if (ioctl(fd, EVIOCSKEYCODE, &map) < 0)
++                        log_error_errno(errno, "Error calling EVIOCSKEYCODE on device node '%s' (scan code 0x%x, key code %d): %m", node, map.scan, map.key);
+         }
+ 
++        /* install list of force-release codes */
++        if (release_count > 0)
++                install_force_release(dev, release, release_count);
++
+         return EXIT_SUCCESS;
+ }
+ 
diff --git a/SOURCES/0555-udev-builtin-keyboard-move-actual-key-mapping-to-a-h.patch b/SOURCES/0555-udev-builtin-keyboard-move-actual-key-mapping-to-a-h.patch
new file mode 100644
index 0000000..6750c02
--- /dev/null
+++ b/SOURCES/0555-udev-builtin-keyboard-move-actual-key-mapping-to-a-h.patch
@@ -0,0 +1,114 @@
+From 3b4e03492fd157ab87ea625a8ad1eb91cef7396b Mon Sep 17 00:00:00 2001
+From: Peter Hutterer <peter.hutterer@who-t.net>
+Date: Fri, 20 Mar 2015 13:17:20 +1000
+Subject: [PATCH] udev: builtin-keyboard: move actual key mapping to a helper
+ function
+
+No changes in the mapping, but previously we opened the device only on
+successful parsing. Now we open the mapping as soon as we have a value that
+looks interesting. Since errors are supposed to be the exception, not the
+rule, this is probably fine.
+
+(cherry picked from commit c9a8e34094733018727677fee44be2c2952224c0)
+
+Resolves: #1500119
+---
+ src/udev/udev-builtin-keyboard.c | 58 +++++++++++++++++++++++-----------------
+ 1 file changed, 33 insertions(+), 25 deletions(-)
+
+diff --git a/src/udev/udev-builtin-keyboard.c b/src/udev/udev-builtin-keyboard.c
+index 515edd45c..f33401790 100644
+--- a/src/udev/udev-builtin-keyboard.c
++++ b/src/udev/udev-builtin-keyboard.c
+@@ -66,12 +66,41 @@ static int install_force_release(struct udev_device *dev, const unsigned *releas
+         return ret;
+ }
+ 
+-static int builtin_keyboard(struct udev_device *dev, int argc, char *argv[], bool test) {
+-        struct udev_list_entry *entry;
++static void map_keycode(int fd, const char *devnode, int scancode, const char *keycode)
++{
+         struct {
+                 unsigned scan;
+                 unsigned key;
+         } map;
++        char *endptr;
++        const struct key *k;
++        unsigned keycode_num;
++
++        /* translate identifier to key code */
++        k = keyboard_lookup_key(keycode, strlen(keycode));
++        if (k) {
++                keycode_num = k->id;
++        } else {
++                /* check if it's a numeric code already */
++                keycode_num = strtoul(keycode, &endptr, 0);
++                if (endptr[0] !='\0') {
++                        log_error("Error, unknown key identifier '%s'", keycode);
++                        return;
++                }
++        }
++
++        map.scan = scancode;
++        map.key = keycode_num;
++
++        log_debug("keyboard: mapping scan code %d (0x%x) to key code %d (0x%x)",
++                  map.scan, map.scan, map.key, map.key);
++
++        if (ioctl(fd, EVIOCSKEYCODE, &map) < 0)
++                log_error_errno(errno, "Error calling EVIOCSKEYCODE on device node '%s' (scan code 0x%x, key code %d): %m", devnode, map.scan, map.key);
++}
++
++static int builtin_keyboard(struct udev_device *dev, int argc, char *argv[], bool test) {
++        struct udev_list_entry *entry;
+         unsigned release[1024];
+         unsigned release_count = 0;
+         _cleanup_close_ int fd = -1;
+@@ -85,10 +114,9 @@ static int builtin_keyboard(struct udev_device *dev, int argc, char *argv[], boo
+ 
+         udev_list_entry_foreach(entry, udev_device_get_properties_list_entry(dev)) {
+                 const char *key;
+-                unsigned scancode, keycode_num;
+                 char *endptr;
++                unsigned scancode;
+                 const char *keycode;
+-                const struct key *k;
+ 
+                 key = udev_list_entry_get_name(entry);
+                 if (!startswith(key, "KEYBOARD_KEY_"))
+@@ -115,19 +143,6 @@ static int builtin_keyboard(struct udev_device *dev, int argc, char *argv[], boo
+                                 continue;
+                 }
+ 
+-                /* translate identifier to key code */
+-                k = keyboard_lookup_key(keycode, strlen(keycode));
+-                if (k) {
+-                        keycode_num = k->id;
+-                } else {
+-                        /* check if it's a numeric code already */
+-                        keycode_num = strtoul(keycode, &endptr, 0);
+-                        if (endptr[0] !='\0') {
+-                                log_error("Error, unknown key identifier '%s'", keycode);
+-                                continue;
+-                        }
+-                }
+-
+                 if (fd == -1) {
+                         fd = open(node, O_RDWR|O_CLOEXEC|O_NONBLOCK|O_NOCTTY);
+                         if (fd < 0) {
+@@ -136,14 +151,7 @@ static int builtin_keyboard(struct udev_device *dev, int argc, char *argv[], boo
+                         }
+                 }
+ 
+-                map.scan = scancode;
+-                map.key = keycode_num;
+-
+-                log_debug("keyboard: mapping scan code %d (0x%x) to key code %d (0x%x)",
+-                          map.scan, map.scan, map.key, map.key);
+-
+-                if (ioctl(fd, EVIOCSKEYCODE, &map) < 0)
+-                        log_error_errno(errno, "Error calling EVIOCSKEYCODE on device node '%s' (scan code 0x%x, key code %d): %m", node, map.scan, map.key);
++                map_keycode(fd, node, scancode, keycode);
+         }
+ 
+         /* install list of force-release codes */
diff --git a/SOURCES/0556-udev-builtin-keyboard-invert-a-condition.patch b/SOURCES/0556-udev-builtin-keyboard-invert-a-condition.patch
new file mode 100644
index 0000000..f809524
--- /dev/null
+++ b/SOURCES/0556-udev-builtin-keyboard-invert-a-condition.patch
@@ -0,0 +1,90 @@
+From a347fcea7ab1648cfa28b4fbb903ae95b879b86e Mon Sep 17 00:00:00 2001
+From: Peter Hutterer <peter.hutterer@who-t.net>
+Date: Fri, 20 Mar 2015 14:00:31 +1000
+Subject: [PATCH] udev: builtin-keyboard: invert a condition
+
+No functional changes, just to make the next patch easier to review
+
+(cherry picked from commit 8a0fd83cf03547653a195582ba004d2ff69dfbd0)
+
+Resolves: #1500119
+---
+ src/udev/udev-builtin-keyboard.c | 56 ++++++++++++++++++++--------------------
+ 1 file changed, 28 insertions(+), 28 deletions(-)
+
+diff --git a/src/udev/udev-builtin-keyboard.c b/src/udev/udev-builtin-keyboard.c
+index f33401790..86f4018ef 100644
+--- a/src/udev/udev-builtin-keyboard.c
++++ b/src/udev/udev-builtin-keyboard.c
+@@ -115,43 +115,43 @@ static int builtin_keyboard(struct udev_device *dev, int argc, char *argv[], boo
+         udev_list_entry_foreach(entry, udev_device_get_properties_list_entry(dev)) {
+                 const char *key;
+                 char *endptr;
+-                unsigned scancode;
+-                const char *keycode;
+ 
+                 key = udev_list_entry_get_name(entry);
+-                if (!startswith(key, "KEYBOARD_KEY_"))
+-                        continue;
+-
+-                /* KEYBOARD_KEY_<hex scan code>=<key identifier string> */
+-                scancode = strtoul(key + 13, &endptr, 16);
+-                if (endptr[0] != '\0') {
+-                        log_error("Error, unable to parse scan code from '%s'", key);
+-                        continue;
+-                }
++                if (startswith(key, "KEYBOARD_KEY_")) {
++                        const char *keycode;
++                        unsigned scancode;
++
++                        /* KEYBOARD_KEY_<hex scan code>=<key identifier string> */
++                        scancode = strtoul(key + 13, &endptr, 16);
++                        if (endptr[0] != '\0') {
++                                log_error("Error, unable to parse scan code from '%s'", key);
++                                continue;
++                        }
+ 
+-                keycode = udev_list_entry_get_value(entry);
++                        keycode = udev_list_entry_get_value(entry);
+ 
+-                /* a leading '!' needs a force-release entry */
+-                if (keycode[0] == '!') {
+-                        keycode++;
++                        /* a leading '!' needs a force-release entry */
++                        if (keycode[0] == '!') {
++                                keycode++;
+ 
+-                        release[release_count] = scancode;
+-                        if (release_count <  ELEMENTSOF(release)-1)
+-                                release_count++;
++                                release[release_count] = scancode;
++                                if (release_count <  ELEMENTSOF(release)-1)
++                                        release_count++;
+ 
+-                        if (keycode[0] == '\0')
+-                                continue;
+-                }
++                                if (keycode[0] == '\0')
++                                        continue;
++                        }
+ 
+-                if (fd == -1) {
+-                        fd = open(node, O_RDWR|O_CLOEXEC|O_NONBLOCK|O_NOCTTY);
+-                        if (fd < 0) {
+-                                log_error_errno(errno, "Error, opening device '%s': %m", node);
+-                                return EXIT_FAILURE;
++                        if (fd == -1) {
++                                fd = open(node, O_RDWR|O_CLOEXEC|O_NONBLOCK|O_NOCTTY);
++                                if (fd < 0) {
++                                        log_error_errno(errno, "Error, opening device '%s': %m", node);
++                                        return EXIT_FAILURE;
++                                }
+                         }
+-                }
+ 
+-                map_keycode(fd, node, scancode, keycode);
++                        map_keycode(fd, node, scancode, keycode);
++                }
+         }
+ 
+         /* install list of force-release codes */
diff --git a/SOURCES/0557-udev-builtin-keyboard-add-support-for-EVDEV_ABS_.patch b/SOURCES/0557-udev-builtin-keyboard-add-support-for-EVDEV_ABS_.patch
new file mode 100644
index 0000000..9736e98
--- /dev/null
+++ b/SOURCES/0557-udev-builtin-keyboard-add-support-for-EVDEV_ABS_.patch
@@ -0,0 +1,240 @@
+From e6682abae36dcfe8a093686a3bd67b3568157c35 Mon Sep 17 00:00:00 2001
+From: Peter Hutterer <peter.hutterer@who-t.net>
+Date: Thu, 19 Mar 2015 14:19:58 +1000
+Subject: [PATCH] udev: builtin-keyboard: add support for EVDEV_ABS_*
+
+Parse properties in the form
+EVDEV_ABS_00="<min>:<max>:<res>:<fuzz>:<flat>"
+
+and apply them to the kernel device. Future processes that open that device
+will see the updated EV_ABS range.
+
+This is particularly useful for touchpads that don't provide a resolution in
+the kernel driver but can be fixed up through hwdb entries (e.g. bcm5974).
+
+All values in the property are optional, e.g. a string of "::45" is valid to
+set the resolution to 45.
+
+The order intentionally orders resolution before fuzz and flat despite it
+being the last element in the absinfo struct. The use-case for setting
+fuzz/flat is almost non-existent, resolution is probably the most common case
+we'll need.
+
+To avoid multiple hwdb invocations for the same device, replace the
+hwdb "keyboard:" prefix with "evdev:" and drop the separate 60-keyboard.rules
+file. The new 60-evdev.rules is called for all event nodes
+anyway, we don't need a separate rules file and second callout to the hwdb
+builtin.
+
+(cherry picked from commit 51c0c2869845a058268d54c3111d55d0dd485704)
+
+Changes to the upstream commit:
+- 60-keyboard.rules is left in place, the 60-keyboard.hwdb is left
+  unmodified. This avoids any potential breakage from user-installed hwdb
+  files that are triggered by that rule.
+
+Conflicts:
+	hwdb/60-keyboard.hwdb
+	rules/60-keyboard.rules
+
+Resolves: #1500119
+---
+ Makefile.am                      |  2 +
+ hwdb/60-evdev.hwdb               | 37 +++++++++++++++++
+ rules/60-evdev.rules             | 14 +++++++
+ src/udev/udev-builtin-keyboard.c | 86 ++++++++++++++++++++++++++++++++++++++--
+ 4 files changed, 135 insertions(+), 4 deletions(-)
+ create mode 100644 hwdb/60-evdev.hwdb
+ create mode 100644 rules/60-evdev.rules
+
+diff --git a/Makefile.am b/Makefile.am
+index a1ebf5cb0..13c93f485 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -3499,6 +3499,7 @@ dist_udevrules_DATA += \
+ 	rules/42-usb-hid-pm.rules \
+ 	rules/50-udev-default.rules \
+ 	rules/60-drm.rules \
++	rules/60-evdev.rules \
+ 	rules/60-keyboard.rules \
+ 	rules/60-persistent-storage-tape.rules \
+ 	rules/60-persistent-serial.rules \
+@@ -3702,6 +3703,7 @@ dist_udevhwdb_DATA = \
+ 	hwdb/20-acpi-vendor.hwdb \
+ 	hwdb/20-OUI.hwdb \
+ 	hwdb/20-net-ifname.hwdb \
++	hwdb/60-evdev.hwdb \
+ 	hwdb/60-keyboard.hwdb \
+ 	hwdb/70-mouse.hwdb \
+ 	hwdb/70-touchpad.hwdb
+diff --git a/hwdb/60-evdev.hwdb b/hwdb/60-evdev.hwdb
+new file mode 100644
+index 000000000..ad2d09e72
+--- /dev/null
++++ b/hwdb/60-evdev.hwdb
+@@ -0,0 +1,37 @@
++# This file is part of systemd.
++#
++# The lookup keys are composed in:
++#   60-evdev.rules
++#
++# Note: The format of the "evdev:" prefix match key is a
++# contract between the rules file and the hardware data, it might
++# change in later revisions to support more or better matches, it
++# is not necessarily expected to be a stable ABI.
++#
++# Match string formats:
++# evdev:<modalias>
++# evdev:name:<device name>:dmi:<dmi string>
++#
++# To add local entries, create a new file
++#   /etc/udev/hwdb.d/61-evdev-local.hwdb
++# and add your rules there. To load the new rules execute (as root):
++#   udevadm hwdb --update
++#   udevadm trigger /dev/input/eventXX
++# where /dev/input/eventXX is the device in question. If in
++# doubt, simply use /dev/input/event* to reload all input rules.
++#
++# If your changes are generally applicable, open a bug report on
++#   http://bugs.freedesktop.org/enter_bug.cgi?product=systemd
++# and include your new rules, a description of the device, and the
++# output of
++#   udevadm info /dev/input/eventXX
++# (or /dev/input/event*).
++#
++# Allowed properties are:
++#    EVDEV_ABS_<axis>=<min>:<max>:<res>:<fuzz>:<flat>
++#
++# where <axis> is the hexadecimal EV_ABS code as listed in linux/input.h
++# and min, max, res, fuzz, flat are the decimal values to the respective
++# fields of the struct input_absinfo as listed in linux/input.h.
++# If a field is missing the field will be left as-is. Not all fields need to
++# be present. e.g. ::45 sets the resolution to 45 units/mm.
+diff --git a/rules/60-evdev.rules b/rules/60-evdev.rules
+new file mode 100644
+index 000000000..67308ad23
+--- /dev/null
++++ b/rules/60-evdev.rules
+@@ -0,0 +1,14 @@
++# do not edit this file, it will be overwritten on update
++
++ACTION=="remove", GOTO="evdev_end"
++KERNEL!="event*", GOTO="evdev_end"
++
++# skip later rules when we find something for this input device
++IMPORT{builtin}="hwdb --subsystem=input --lookup-prefix=evdev:", \
++  RUN{builtin}+="keyboard", GOTO="evdev_end"
++
++# device matching the input device name and the machine's DMI data
++KERNELS=="input*", IMPORT{builtin}="hwdb 'evdev:name:$attr{name}:$attr{[dmi/id]modalias}'", \
++  RUN{builtin}+="keyboard", GOTO="evdev_end"
++
++LABEL="evdev_end"
+diff --git a/src/udev/udev-builtin-keyboard.c b/src/udev/udev-builtin-keyboard.c
+index 86f4018ef..eaa21abf6 100644
+--- a/src/udev/udev-builtin-keyboard.c
++++ b/src/udev/udev-builtin-keyboard.c
+@@ -99,6 +99,69 @@ static void map_keycode(int fd, const char *devnode, int scancode, const char *k
+                 log_error_errno(errno, "Error calling EVIOCSKEYCODE on device node '%s' (scan code 0x%x, key code %d): %m", devnode, map.scan, map.key);
+ }
+ 
++static inline char* parse_token(const char *current, int32_t *val_out) {
++        char *next;
++        int32_t val;
++
++        if (!current)
++                return NULL;
++
++        val = strtol(current, &next, 0);
++        if (*next && *next != ':')
++                return NULL;
++
++        if (next != current)
++                *val_out = val;
++
++        if (*next)
++                next++;
++
++        return next;
++}
++
++static void override_abs(int fd, const char *devnode,
++                         unsigned evcode, const char *value) {
++        struct input_absinfo absinfo;
++        int rc;
++        char *next;
++
++        rc = ioctl(fd, EVIOCGABS(evcode), &absinfo);
++        if (rc < 0) {
++                log_error_errno(errno, "Error, unable to EVIOCGABS device '%s'",
++                                devnode);
++                return;
++        }
++
++        next = parse_token(value, &absinfo.minimum);
++        next = parse_token(next, &absinfo.maximum);
++        next = parse_token(next, &absinfo.resolution);
++        next = parse_token(next, &absinfo.fuzz);
++        next = parse_token(next, &absinfo.flat);
++        if (!next) {
++                log_error("Error, unable to parse EV_ABS override '%s' for '%s'\n",
++                          value, devnode);
++                return;
++        }
++
++        log_debug("keyboard: override %x with %d/%d/%d/%d/%d", evcode,
++                  absinfo.minimum, absinfo.maximum, absinfo.resolution,
++                  absinfo.fuzz, absinfo.flat);
++        rc = ioctl(fd, EVIOCSABS(evcode), &absinfo);
++        if (rc < 0)
++                log_error_errno(errno, "Error, unable to update device '%s'",
++                                devnode);
++}
++
++static int open_device(const char *devnode) {
++        int fd;
++
++        fd = open(devnode, O_RDWR|O_CLOEXEC|O_NONBLOCK|O_NOCTTY);
++        if (fd < 0)
++                log_error_errno(errno, "Error, opening device '%s': %m", devnode);
++
++        return fd < 0 ? -errno : fd;
++}
++
+ static int builtin_keyboard(struct udev_device *dev, int argc, char *argv[], bool test) {
+         struct udev_list_entry *entry;
+         unsigned release[1024];
+@@ -143,14 +206,29 @@ static int builtin_keyboard(struct udev_device *dev, int argc, char *argv[], boo
+                         }
+ 
+                         if (fd == -1) {
+-                                fd = open(node, O_RDWR|O_CLOEXEC|O_NONBLOCK|O_NOCTTY);
+-                                if (fd < 0) {
+-                                        log_error_errno(errno, "Error, opening device '%s': %m", node);
++                                fd = open_device(node);
++                                if (fd < 0)
+                                         return EXIT_FAILURE;
+-                                }
+                         }
+ 
+                         map_keycode(fd, node, scancode, keycode);
++                } else if (startswith(key, "EVDEV_ABS_")) {
++                        unsigned evcode;
++
++                        /* EVDEV_ABS_<EV_ABS code>=<min>:<max>:<res>:<fuzz>:<flat> */
++                        evcode = strtoul(key + 10, &endptr, 16);
++                        if (endptr[0] != '\0') {
++                                log_error("Error, unable to parse EV_ABS code from '%s'", key);
++                                continue;
++                        }
++
++                        if (fd == -1) {
++                                fd = open_device(node);
++                                if (fd < 0)
++                                        return EXIT_FAILURE;
++                        }
++
++                        override_abs(fd, node, evcode, udev_list_entry_get_value(entry));
+                 }
+         }
+ 
diff --git a/SOURCES/0558-hwdb-sync-60-evdev.hwdb-from-systemd-v235.patch b/SOURCES/0558-hwdb-sync-60-evdev.hwdb-from-systemd-v235.patch
new file mode 100644
index 0000000..5bb7108
--- /dev/null
+++ b/SOURCES/0558-hwdb-sync-60-evdev.hwdb-from-systemd-v235.patch
@@ -0,0 +1,436 @@
+From 525d254a21daa1ddd6634a465596299121fd0470 Mon Sep 17 00:00:00 2001
+From: Peter Hutterer <peter.hutterer@who-t.net>
+Date: Tue, 10 Oct 2017 10:08:16 +1000
+Subject: [PATCH] hwdb: sync 60-evdev.hwdb from systemd v235
+
+Resolves: rhbz#1500119
+---
+ hwdb/60-evdev.hwdb | 407 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 400 insertions(+), 7 deletions(-)
+
+diff --git a/hwdb/60-evdev.hwdb b/hwdb/60-evdev.hwdb
+index ad2d09e72..f688ef269 100644
+--- a/hwdb/60-evdev.hwdb
++++ b/hwdb/60-evdev.hwdb
+@@ -15,17 +15,17 @@
+ # To add local entries, create a new file
+ #   /etc/udev/hwdb.d/61-evdev-local.hwdb
+ # and add your rules there. To load the new rules execute (as root):
+-#   udevadm hwdb --update
++#   systemd-hwdb update
+ #   udevadm trigger /dev/input/eventXX
+ # where /dev/input/eventXX is the device in question. If in
+ # doubt, simply use /dev/input/event* to reload all input rules.
+ #
+-# If your changes are generally applicable, open a bug report on
+-#   http://bugs.freedesktop.org/enter_bug.cgi?product=systemd
+-# and include your new rules, a description of the device, and the
+-# output of
+-#   udevadm info /dev/input/eventXX
+-# (or /dev/input/event*).
++# If your changes are generally applicable, preferably send them as a pull
++# request to
++#   https://github.com/systemd/systemd
++# or create a bug report on https://github.com/systemd/systemd/issues and
++# include your new rules, a description of the device, and the output of
++#   udevadm info /dev/input/eventXX.
+ #
+ # Allowed properties are:
+ #    EVDEV_ABS_<axis>=<min>:<max>:<res>:<fuzz>:<flat>
+@@ -35,3 +35,396 @@
+ # fields of the struct input_absinfo as listed in linux/input.h.
+ # If a field is missing the field will be left as-is. Not all fields need to
+ # be present. e.g. ::45 sets the resolution to 45 units/mm.
++
++#
++# Sort by brand, model
++
++#########################################
++# Apple
++#########################################
++
++#  Macbook2,1 (late 2006), single-button touchpad
++evdev:input:b0003v05ACp021B*
++# Macbook4,1
++evdev:input:b0003v05ACp0229*
++ EVDEV_ABS_00=256:1471:12
++ EVDEV_ABS_01=256:831:12
++
++# Macbook5,1 (unibody), aka wellspring3
++evdev:input:b0003v05ACp0236*
++evdev:input:b0003v05ACp0237*
++evdev:input:b0003v05ACp0238*
++ EVDEV_ABS_00=::92
++ EVDEV_ABS_01=::90
++ EVDEV_ABS_35=::92
++ EVDEV_ABS_36=::90
++
++# Macbook8 (unibody, March 2011)
++evdev:input:b0003v05ACp0245*
++evdev:input:b0003v05ACp0246*
++evdev:input:b0003v05ACp0247*
++ EVDEV_ABS_00=::92
++ EVDEV_ABS_01=::91
++ EVDEV_ABS_35=::92
++ EVDEV_ABS_36=::91
++
++# Macbook8,2 (unibody)
++evdev:input:b0003v05ACp0252*
++evdev:input:b0003v05ACp0253*
++evdev:input:b0003v05ACp0254*
++ EVDEV_ABS_00=::94
++ EVDEV_ABS_01=::92
++ EVDEV_ABS_35=::94
++ EVDEV_ABS_36=::92
++
++# MacbookPro10,1 (unibody, June 2012)
++evdev:input:b0003v05ACp0262*
++evdev:input:b0003v05ACp0263*
++evdev:input:b0003v05ACp0264*
++# MacbookPro10,2 (unibody, October 2012)
++evdev:input:b0003v05ACp0259*
++evdev:input:b0003v05ACp025A*
++evdev:input:b0003v05ACp025B*
++ EVDEV_ABS_00=::94
++ EVDEV_ABS_01=::92
++ EVDEV_ABS_35=::94
++ EVDEV_ABS_36=::92
++
++#########################################
++# ASUS
++#########################################
++
++# Asus VivoBook E402SA
++evdev:name:Elan Touchpad:dmi:*svnASUSTeKCOMPUTERINC.:pnE402SA*
++ EVDEV_ABS_00=::29
++ EVDEV_ABS_01=::29
++ EVDEV_ABS_35=::29
++ EVDEV_ABS_36=::29
++
++# Asus K52JT
++evdev:name:ETPS/2 Elantech Touchpad:dmi:bvn*:bvr*:bd*:svnASUSTeKComputerInc.:pnK52JT:*
++ EVDEV_ABS_00=::18
++ EVDEV_ABS_01=::16
++ EVDEV_ABS_35=::18
++ EVDEV_ABS_36=::16
++
++# Asus X550CC and S550CB
++evdev:name:ETPS/2 Elantech Touchpad:dmi:*:svnASUSTeKCOMPUTERINC.:pn?550C?:*
++ EVDEV_ABS_00=::31
++ EVDEV_ABS_01=::30
++ EVDEV_ABS_35=::31
++ EVDEV_ABS_36=::30
++
++# Asus UX301L
++evdev:name:Elan Touchpad:dmi:*:svnASUSTeKCOMPUTERINC.:pnUX301LAA:*
++ EVDEV_ABS_00=::30
++ EVDEV_ABS_01=::29
++ EVDEV_ABS_35=::30
++ EVDEV_ABS_36=::29
++
++# Asus UX305
++evdev:name:Elan Touchpad:dmi:*:svnASUSTeKCOMPUTERINC.:pnUX305UA:*
++ EVDEV_ABS_00=0:3097:32
++ EVDEV_ABS_01=0:2119:33
++ EVDEV_ABS_35=0:3097:32
++ EVDEV_ABS_36=0:2119:33
++
++#########################################
++# Dell
++#########################################
++
++# Dell Vostro 1510
++evdev:name:AlpsPS/2 ALPS GlidePoint*:dmi:bvn*:bvr*:bd*:svnDellInc.:pnVostro1510*
++ EVDEV_ABS_00=::14
++ EVDEV_ABS_01=::18
++
++# Dell Inspiron N5040
++evdev:name:AlpsPS/2 ALPS DualPoint TouchPad:dmi:bvn*:bvr*:bd*:svnDellInc.:pnInspironN5040*
++ EVDEV_ABS_00=25:2000:22
++ EVDEV_ABS_01=0:1351:28
++ EVDEV_ABS_35=25:2000:22
++ EVDEV_ABS_36=0:1351:28
++
++# Dell Latitude E6220
++evdev:name:AlpsPS/2 ALPS DualPoint TouchPad:dmi:bvn*:bvr*:bd*:svnDellInc.:pnLatitudeE6220*
++ EVDEV_ABS_00=76:1815:22
++ EVDEV_ABS_01=131:1330:30
++ EVDEV_ABS_35=76:1815:22
++ EVDEV_ABS_36=131:1330:30
++
++# Dell Latitude E6320
++evdev:name:AlpsPS/2 ALPS DualPoint TouchPad:dmi:bvn*:bvr*:bd*:svnDellInc.:pnLatitudeE6320*
++ EVDEV_ABS_00=79:1841:22
++ EVDEV_ABS_01=140:1325:29
++ EVDEV_ABS_35=79:1841:22
++ EVDEV_ABS_36=140:1325:29
++
++# Dell Latitude E7470
++evdev:name:AlpsPS/2 ALPS DualPoint TouchPad:dmi:bvn*:bvr*:bd*:svnDellInc.:pnLatitudeE7470*
++ EVDEV_ABS_00=39:5856:59
++ EVDEV_ABS_01=10:1532:29
++ EVDEV_ABS_35=39:5856:59
++ EVDEV_ABS_36=10:1532:29
++
++# Dell Precision 5510
++evdev:name:SynPS/2 Synaptics TouchPad:dmi:bvn*:bvr*:bd*:svnDellInc.:pnPrecision5510*
++ EVDEV_ABS_00=::42
++ EVDEV_ABS_01=::43
++ EVDEV_ABS_35=::42
++ EVDEV_ABS_36=::43
++
++# Dell Precision M4700
++evdev:name:AlpsPS/2 ALPS DualPoint TouchPad:dmi:*svnDellInc.:pnPrecisionM4700*
++ EVDEV_ABS_00=0:1960:24
++ EVDEV_ABS_01=113:1436:30
++ EVDEV_ABS_35=0:1960:24
++ EVDEV_ABS_36=113:1436:30
++
++# Dell XPS15 9550
++evdev:name:SynPS/2 Synaptics TouchPad:dmi:bvn*:bvr*:bd*:svnDellInc.:pnXPS159550*
++ EVDEV_ABS_00=::41
++ EVDEV_ABS_01=::43
++ EVDEV_ABS_35=::41
++ EVDEV_ABS_36=::43
++
++# Dell XPS M1530
++evdev:name:AlpsPS/2 ALPS GlidePoint:dmi:bvn*:bvr*:bd*:svnDellInc.:pnXPSM1530*
++ EVDEV_ABS_00=85:947:15
++ EVDEV_ABS_01=154:726:18
++
++#####
++# Sun
++#####
++
++# Fujitsu Component - USB Touch Panel
++evdev:input:b0003v0430p0530*
++ EVDEV_ABS_00=0:4096:16
++ EVDEV_ABS_01=0:4096:16
++
++#########################################
++# Google
++#########################################
++
++# Chromebook Pixel (2015) - Samus
++evdev:name:Atmel maXTouch Touch*:dmi:bvn*:bvr*:bd*:svnGOOGLE:pnSamus*
++ EVDEV_ABS_00=::10
++ EVDEV_ABS_01=::10
++ EVDEV_ABS_35=::10
++ EVDEV_ABS_36=::10
++
++#########################################
++# HP
++#########################################
++
++# HP Pavilion dm4
++evdev:name:SynPS/2 Synaptics TouchPad*:dmi:*svnHewlett-Packard:pnHPPaviliondm4*
++ EVDEV_ABS_00=1360:5563:47
++ EVDEV_ABS_01=1269:4618:61
++ EVDEV_ABS_35=1360:5563:47
++ EVDEV_ABS_36=1269:4618:61
++
++# HP Pavilion dv7
++evdev:name:SynPS/2 Synaptics TouchPad*:dmi:*svnHewlett-Packard:pnHPPaviliondv7*
++ EVDEV_ABS_00=1068:5805:44
++ EVDEV_ABS_01=1197:4890:57
++ EVDEV_ABS_35=1068:5805:44
++ EVDEV_ABS_36=1197:4890:57
++
++# HP Spectre
++evdev:name:SynPS/2 Synaptics TouchPad:dmi:i*svnHP:pnHPSpectreNotebook*
++ EVDEV_ABS_00=1205:5691:47
++ EVDEV_ABS_01=1083:4808:65
++ EVDEV_ABS_35=1205:5691:47
++ EVDEV_ABS_36=1083:4808:65
++
++#########################################
++# Lenovo
++#########################################
++
++# Lenovo B590
++evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pvrLenovoB590*
++ EVDEV_ABS_00=1243:5759:48
++ EVDEV_ABS_01=1130:4832:65
++ EVDEV_ABS_35=1243:5759:48
++ EVDEV_ABS_36=1130:4832:65
++
++# Lenovo E530
++evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO:pn*ThinkPadEdgeE530*
++ EVDEV_ABS_00=1241:5703:49
++ EVDEV_ABS_01=1105:4820:68
++ EVDEV_ABS_35=1241:5703:49
++ EVDEV_ABS_36=1105:4820:68
++
++# Lenovo L430
++evdev:name:ETPS/2 Elantech Touchpad:dmi:*svnLENOVO*:pvrThinkPadL430*
++ EVDEV_ABS_00=19:2197:29
++ EVDEV_ABS_01=12:1151:25
++ EVDEV_ABS_35=19:2197:29
++ EVDEV_ABS_36=12:1151:25
++
++# Lenovo P50
++evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pn*ThinkPad*P50*
++ EVDEV_ABS_00=::44
++ EVDEV_ABS_01=::67
++ EVDEV_ABS_35=::44
++ EVDEV_ABS_36=::67
++
++# Lenovo *40 series
++evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pvrThinkPad??40:*
++evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pvrThinkPad??40?:*
++ EVDEV_ABS_00=::41
++ EVDEV_ABS_01=::37
++ EVDEV_ABS_35=::41
++ EVDEV_ABS_36=::37
++
++# Lenovo ThinkPad T430
++evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pvrThinkPadT430*
++ EVDEV_ABS_00=1250:5631:58
++ EVDEV_ABS_01=1309:4826:78
++ EVDEV_ABS_35=1250:5631:58
++ EVDEV_ABS_36=1309:4826:78
++
++# Lenovo Thinkpad Carbon X1 4th gen. and X1 Yoga 1st gen.
++evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pvrThinkPadX1Carbon4th*
++ EVDEV_ABS_00=1262:5679:44
++ EVDEV_ABS_01=1101:4824:65
++ EVDEV_ABS_35=1262:5679:44
++ EVDEV_ABS_36=1101:4824:65
++
++# Lenovo Thinkpad Carbon X1 5th gen.
++evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pvrThinkPadX1Carbon5th*
++ EVDEV_ABS_00=::44
++ EVDEV_ABS_01=::65
++ EVDEV_ABS_35=::44
++ EVDEV_ABS_36=::65
++
++# Lenovo Thinkpad Carbon X1 5th gen. (rmi4)
++evdev:name:Synaptics TM3289-002:dmi:*svnLENOVO*:pvrThinkPadX1Carbon5th*
++ EVDEV_ABS_00=::19
++ EVDEV_ABS_01=::19
++ EVDEV_ABS_35=::19
++ EVDEV_ABS_36=::19
++
++# Lenovo T460
++evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pn*ThinkPad*T460*
++ EVDEV_ABS_00=1266:5677:44
++ EVDEV_ABS_01=1093:4832:65
++ EVDEV_ABS_35=1266:5677:44
++ EVDEV_ABS_36=1093:4832:65
++
++# Lenovo T510
++evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pn*ThinkPad*T510*
++ EVDEV_ABS_00=778:6239:72
++ EVDEV_ABS_01=841:5330:100
++ EVDEV_ABS_35=778:6239:72
++ EVDEV_ABS_36=841:5330:100
++
++# Lenovo V360
++evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO:*pvrLenovoV360*
++ EVDEV_ABS_00=1243:5927:60
++ EVDEV_ABS_01=902:5330:108
++
++# Lenovo W530
++evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO:*pvrThinkPadW530*
++ EVDEV_ABS_00=1250:5631:59
++ EVDEV_ABS_01=1205:4834:81
++ EVDEV_ABS_35=1250:5631:59
++ EVDEV_ABS_36=1205:4834:81
++
++# Lenovo X220 series
++evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO:*pvrThinkPadX220*
++ EVDEV_ABS_00=1316:5627:58
++ EVDEV_ABS_01=1355:4826:81
++ EVDEV_ABS_35=1316:5627:58
++ EVDEV_ABS_36=1355:4826:81
++
++# Lenovo X230 series
++evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pn*ThinkPad*X230*
++ EVDEV_ABS_01=::100
++ EVDEV_ABS_36=::100
++
++# Lenovo Y700-14ISK
++evdev:name:AlpsPS/2 ALPS GlidePoint:dmi:*svnLENOVO:*pvrLenovoideapadY700-14ISK*
++ EVDEV_ABS_00=::27
++ EVDEV_ABS_01=::29
++ EVDEV_ABS_35=::27
++ EVDEV_ABS_36=::29
++
++# Lenovo Ideapad 500S-13ISK
++evdev:name:AlpsPS/2 ALPS GlidePoint:dmi:*svnLENOVO:*pvrLenovoideapad500S-13ISK*
++ EVDEV_ABS_00=125:3955:37
++ EVDEV_ABS_01=104:1959:27
++ EVDEV_ABS_35=125:3954:37
++ EVDEV_ABS_36=104:1959:27
++
++# Lenovo Yoga 500-14ISK
++evdev:name:AlpsPS/2 ALPS GlidePoint:dmi:*svnLENOVO:*pvrLenovoYoga500-14ISK*
++ EVDEV_ABS_00=124:3955:36
++ EVDEV_ABS_01=103:1959:26
++ EVDEV_ABS_35=124:3955:36
++ EVDEV_ABS_36=103:1959:26
++
++# Lenovo Flex 3 15-inch
++evdev:name:AlpsPS/2 ALPS GlidePoint*:dmi:bvn*:bvr*:bd*:svnLENOVO*:pvrFlex3-15*
++ EVDEV_ABS_00=::38
++ EVDEV_ABS_01=::28
++ EVDEV_ABS_35=::38
++ EVDEV_ABS_36=::28
++
++#########################################
++# Samsung
++#########################################
++
++# Samsung 305V4
++evdev:name:ETPS/2 Elantech Touchpad:dmi:*svnSAMSUNGELECTRONICSCO.,LTD.:pn305V4A/305V5A*
++ EVDEV_ABS_00=0:2480:28
++ EVDEV_ABS_01=0:1116:24
++ EVDEV_ABS_35=0:2480:28
++ EVDEV_ABS_36=0:1116:24
++
++# Samsung 880Z5E
++evdev:name:ETPS/2 Elantech Touchpad:dmi:*svnSAMSUNGELECTRONICSCO.,LTD.:pn870Z5E/880Z5E/680Z5E*
++ EVDEV_ABS_00=::30
++ EVDEV_ABS_01=::29
++ EVDEV_ABS_35=::30
++ EVDEV_ABS_36=::29
++
++#########################################
++# System76
++#########################################
++
++# GalagoPro 2 (galp2)
++evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnSystem76:pnGalagoPro:pvrgalp2:*
++ EVDEV_ABS_00=1238:5747:50
++ EVDEV_ABS_01=901:4900:83
++ EVDEV_ABS_35=1238:5747:50
++ EVDEV_ABS_36=901:4900:83
++
++#########################################
++# Toshiba
++#########################################
++
++# Toshiba Tecra M11
++evdev:name:AlpsPS/2 ALPS DualPoint TouchPad:dmi:*svnTOSHIBA:pnTECRAM11*
++ EVDEV_ABS_00=90:962:11
++ EVDEV_ABS_01=51:681:14
++
++#########################################
++# Razer
++#########################################
++
++# Razer Blade Stealth (2016)
++evdev:name:Synaptics TM2438-005:dmi:*svnRazer:pnBladeStealth*
++ EVDEV_ABS_00=0:4064:29
++ EVDEV_ABS_01=0:2405:37
++ EVDEV_ABS_35=0:4064:29
++ EVDEV_ABS_36=0:2405:37
++
++#########################################
++# Waltop
++#########################################
++
++# WALTOP International Corp. Slim Tablet
++evdev:input:b0003v172Fp0031*
++ EVDEV_ABS_00=0:10000:400
++ EVDEV_ABS_01=0:6250:400
diff --git a/SOURCES/0559-journal-ensure-open-journals-from-find_journal-3973.patch b/SOURCES/0559-journal-ensure-open-journals-from-find_journal-3973.patch
new file mode 100644
index 0000000..8f6023f
--- /dev/null
+++ b/SOURCES/0559-journal-ensure-open-journals-from-find_journal-3973.patch
@@ -0,0 +1,266 @@
+From b36c31ddc2f3427ea2a1f700db08d8e104e4110a Mon Sep 17 00:00:00 2001
+From: Jan Synacek <jsynacek@redhat.com>
+Date: Thu, 5 Oct 2017 11:26:21 +0200
+Subject: [PATCH] journal: ensure open journals from find_journal() (#3973)
+
+If journals get into a closed state like when rotate fails due to
+ENOSPC, when space is made available it currently goes unnoticed leaving
+the journals in a closed state indefinitely.
+
+By calling system_journal_open() on entry to find_journal() we ensure
+the journal has been opened/created if possible.
+
+Also moved system_journal_open() up to after open_journal(), before
+find_journal().
+
+Fixes https://github.com/systemd/systemd/issues/3968
+
+(cherry picked from commit 105bdb46b4ac7eb658a2f27727216591d0bfe267)
+
+Resolves: #1493846
+---
+ src/journal/journald-server.c | 217 ++++++++++++++++++++++--------------------
+ 1 file changed, 114 insertions(+), 103 deletions(-)
+
+diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c
+index c1358e1e9..96e7d6156 100644
+--- a/src/journal/journald-server.c
++++ b/src/journal/journald-server.c
+@@ -239,6 +239,109 @@ finish:
+ #endif
+ }
+ 
++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) {
++        int r;
++        char *fn;
++        sd_id128_t machine;
++        char ids[33];
++
++        r = sd_id128_get_machine(&machine);
++        if (r < 0)
++                return log_error_errno(r, "Failed to get machine id: %m");
++
++        sd_id128_to_string(machine, ids);
++
++        if (!s->system_journal &&
++            IN_SET(s->storage, STORAGE_PERSISTENT, STORAGE_AUTO) &&
++            (flush_requested || flushed_flag_is_set())) {
++
++                /* If in auto mode: first try to create the machine
++                 * path, but not the prefix.
++                 *
++                 * If in persistent mode: create /var/log/journal and
++                 * the machine path */
++
++                if (s->storage == STORAGE_PERSISTENT)
++                        (void) mkdir_p("/var/log/journal/", 0755);
++
++                fn = strjoina("/var/log/journal/", ids);
++                (void) mkdir(fn, 0755);
++
++                fn = strjoina(fn, "/system.journal");
++                r = journal_file_open_reliably(fn, O_RDWR|O_CREAT, 0640, s->compress, s->seal, &s->system_metrics, s->mmap, NULL, &s->system_journal);
++
++                if (r >= 0)
++                        server_fix_perms(s, s->system_journal, 0);
++                else if (r < 0) {
++                        if (r != -ENOENT && r != -EROFS)
++                                log_warning_errno(r, "Failed to open system journal: %m");
++
++                        r = 0;
++                }
++
++                /* If the runtime journal is open, and we're post-flush, we're
++                 * recovering from a failed system journal rotate (ENOSPC)
++                 * for which the runtime journal was reopened.
++                 *
++                 * Perform an implicit flush to var, leaving the runtime
++                 * journal closed, now that the system journal is back.
++                 */
++                if (!flush_requested)
++                        (void) server_flush_to_var(s, true);
++        }
++
++        if (!s->runtime_journal &&
++            (s->storage != STORAGE_NONE)) {
++
++                fn = strjoin("/run/log/journal/", ids, "/system.journal", NULL);
++                if (!fn)
++                        return -ENOMEM;
++
++                if (s->system_journal) {
++
++                        /* Try to open the runtime journal, but only
++                         * if it already exists, so that we can flush
++                         * it into the system journal */
++
++                        r = journal_file_open(fn, O_RDWR, 0640, s->compress, false, &s->runtime_metrics, s->mmap, NULL, &s->runtime_journal);
++                        free(fn);
++
++                        if (r < 0) {
++                                if (r != -ENOENT)
++                                        log_warning_errno(r, "Failed to open runtime journal: %m");
++
++                                r = 0;
++                        }
++
++                } else {
++
++                        /* OK, we really need the runtime journal, so create
++                         * it if necessary. */
++
++                        (void) mkdir("/run/log", 0755);
++                        (void) mkdir("/run/log/journal", 0755);
++                        (void) mkdir_parents(fn, 0750);
++
++                        r = journal_file_open_reliably(fn, O_RDWR|O_CREAT, 0640, s->compress, false, &s->runtime_metrics, s->mmap, NULL, &s->runtime_journal);
++                        free(fn);
++
++                        if (r < 0)
++                                return log_error_errno(r, "Failed to open runtime journal: %m");
++                }
++
++                if (s->runtime_journal)
++                        server_fix_perms(s, s->runtime_journal, 0);
++        }
++
++        available_space(s, true);
++
++        return r;
++}
++
+ static JournalFile* find_journal(Server *s, uid_t uid) {
+         _cleanup_free_ char *p = NULL;
+         int r;
+@@ -247,6 +350,17 @@ static JournalFile* find_journal(Server *s, uid_t uid) {
+ 
+         assert(s);
+ 
++        /* A rotate that fails to create the new journal (ENOSPC) leaves the
++         * rotated journal as NULL.  Unless we revisit opening, even after
++         * space is made available we'll continue to return NULL indefinitely.
++         *
++         * system_journal_open() is a noop if the journals are already open, so
++         * we can just call it here to recover from failed rotates (or anything
++         * else that's left the journals as NULL).
++         *
++         * Fixes https://github.com/systemd/systemd/issues/3968 */
++        (void) system_journal_open(s, 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
+          * to guarantee proper order as soon as we flush /run to
+@@ -917,109 +1031,6 @@ finish:
+         dispatch_message_real(s, iovec, n, m, ucred, tv, label, label_len, unit_id, priority, object_pid);
+ }
+ 
+-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) {
+-        int r;
+-        char *fn;
+-        sd_id128_t machine;
+-        char ids[33];
+-
+-        r = sd_id128_get_machine(&machine);
+-        if (r < 0)
+-                return log_error_errno(r, "Failed to get machine id: %m");
+-
+-        sd_id128_to_string(machine, ids);
+-
+-        if (!s->system_journal &&
+-            IN_SET(s->storage, STORAGE_PERSISTENT, STORAGE_AUTO) &&
+-            (flush_requested || flushed_flag_is_set())) {
+-
+-                /* If in auto mode: first try to create the machine
+-                 * path, but not the prefix.
+-                 *
+-                 * If in persistent mode: create /var/log/journal and
+-                 * the machine path */
+-
+-                if (s->storage == STORAGE_PERSISTENT)
+-                        (void) mkdir_p("/var/log/journal/", 0755);
+-
+-                fn = strjoina("/var/log/journal/", ids);
+-                (void) mkdir(fn, 0755);
+-
+-                fn = strjoina(fn, "/system.journal");
+-                r = journal_file_open_reliably(fn, O_RDWR|O_CREAT, 0640, s->compress, s->seal, &s->system_metrics, s->mmap, NULL, &s->system_journal);
+-
+-                if (r >= 0)
+-                        server_fix_perms(s, s->system_journal, 0);
+-                else if (r < 0) {
+-                        if (r != -ENOENT && r != -EROFS)
+-                                log_warning_errno(r, "Failed to open system journal: %m");
+-
+-                        r = 0;
+-                }
+-
+-                /* If the runtime journal is open, and we're post-flush, we're
+-                 * recovering from a failed system journal rotate (ENOSPC)
+-                 * for which the runtime journal was reopened.
+-                 *
+-                 * Perform an implicit flush to var, leaving the runtime
+-                 * journal closed, now that the system journal is back.
+-                 */
+-                if (!flush_requested)
+-                        (void) server_flush_to_var(s, true);
+-        }
+-
+-        if (!s->runtime_journal &&
+-            (s->storage != STORAGE_NONE)) {
+-
+-                fn = strjoin("/run/log/journal/", ids, "/system.journal", NULL);
+-                if (!fn)
+-                        return -ENOMEM;
+-
+-                if (s->system_journal) {
+-
+-                        /* Try to open the runtime journal, but only
+-                         * if it already exists, so that we can flush
+-                         * it into the system journal */
+-
+-                        r = journal_file_open(fn, O_RDWR, 0640, s->compress, false, &s->runtime_metrics, s->mmap, NULL, &s->runtime_journal);
+-                        free(fn);
+-
+-                        if (r < 0) {
+-                                if (r != -ENOENT)
+-                                        log_warning_errno(r, "Failed to open runtime journal: %m");
+-
+-                                r = 0;
+-                        }
+-
+-                } else {
+-
+-                        /* OK, we really need the runtime journal, so create
+-                         * it if necessary. */
+-
+-                        (void) mkdir("/run/log", 0755);
+-                        (void) mkdir("/run/log/journal", 0755);
+-                        (void) mkdir_parents(fn, 0750);
+-
+-                        r = journal_file_open_reliably(fn, O_RDWR|O_CREAT, 0640, s->compress, false, &s->runtime_metrics, s->mmap, NULL, &s->runtime_journal);
+-                        free(fn);
+-
+-                        if (r < 0)
+-                                return log_error_errno(r, "Failed to open runtime journal: %m");
+-                }
+-
+-                if (s->runtime_journal)
+-                        server_fix_perms(s, s->runtime_journal, 0);
+-        }
+-
+-        available_space(s, true);
+-
+-        return r;
+-}
+-
+ int server_flush_to_var(Server *s, bool require_flag_file) {
+         sd_id128_t machine;
+         sd_journal *j = NULL;
diff --git a/SOURCES/0560-journal-only-check-available-space-when-journal-is-o.patch b/SOURCES/0560-journal-only-check-available-space-when-journal-is-o.patch
new file mode 100644
index 0000000..3fce2ef
--- /dev/null
+++ b/SOURCES/0560-journal-only-check-available-space-when-journal-is-o.patch
@@ -0,0 +1,69 @@
+From 3511688b336ee36f200d2ade5e3bdc01de9c503e Mon Sep 17 00:00:00 2001
+From: Jan Synacek <jsynacek@redhat.com>
+Date: Mon, 9 Oct 2017 12:47:21 +0200
+Subject: [PATCH] journal: only check available space when journal is open
+
+RHEL-only
+
+Related: #1493846
+---
+ src/journal/journald-server.c | 17 ++++++++++-------
+ 1 file changed, 10 insertions(+), 7 deletions(-)
+
+diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c
+index 96e7d6156..f6f8c30eb 100644
+--- a/src/journal/journald-server.c
++++ b/src/journal/journald-server.c
+@@ -253,12 +253,12 @@ static int system_journal_open(Server *s, bool flush_requested) {
+         if (r < 0)
+                 return log_error_errno(r, "Failed to get machine id: %m");
+ 
+-        sd_id128_to_string(machine, ids);
+-
+         if (!s->system_journal &&
+             IN_SET(s->storage, STORAGE_PERSISTENT, STORAGE_AUTO) &&
+             (flush_requested || flushed_flag_is_set())) {
+ 
++                sd_id128_to_string(machine, ids);
++
+                 /* If in auto mode: first try to create the machine
+                  * path, but not the prefix.
+                  *
+@@ -274,9 +274,10 @@ static int system_journal_open(Server *s, bool flush_requested) {
+                 fn = strjoina(fn, "/system.journal");
+                 r = journal_file_open_reliably(fn, O_RDWR|O_CREAT, 0640, s->compress, s->seal, &s->system_metrics, s->mmap, NULL, &s->system_journal);
+ 
+-                if (r >= 0)
++                if (r >= 0) {
+                         server_fix_perms(s, s->system_journal, 0);
+-                else if (r < 0) {
++                        available_space(s, true);
++                } else if (r < 0) {
+                         if (r != -ENOENT && r != -EROFS)
+                                 log_warning_errno(r, "Failed to open system journal: %m");
+ 
+@@ -297,6 +298,8 @@ static int system_journal_open(Server *s, bool flush_requested) {
+         if (!s->runtime_journal &&
+             (s->storage != STORAGE_NONE)) {
+ 
++                sd_id128_to_string(machine, ids);
++
+                 fn = strjoin("/run/log/journal/", ids, "/system.journal", NULL);
+                 if (!fn)
+                         return -ENOMEM;
+@@ -333,12 +336,12 @@ static int system_journal_open(Server *s, bool flush_requested) {
+                                 return log_error_errno(r, "Failed to open runtime journal: %m");
+                 }
+ 
+-                if (s->runtime_journal)
++                if (s->runtime_journal) {
+                         server_fix_perms(s, s->runtime_journal, 0);
++                        available_space(s, true);
++                }
+         }
+ 
+-        available_space(s, true);
+-
+         return r;
+ }
+ 
diff --git a/SOURCES/0561-automount-if-an-automount-unit-is-masked-don-t-react.patch b/SOURCES/0561-automount-if-an-automount-unit-is-masked-don-t-react.patch
new file mode 100644
index 0000000..afaf168
--- /dev/null
+++ b/SOURCES/0561-automount-if-an-automount-unit-is-masked-don-t-react.patch
@@ -0,0 +1,158 @@
+From 85eeadc898d2c0f8b7524982c84b88b01a5dcb89 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Wed, 1 Mar 2017 04:03:48 +0100
+Subject: [PATCH] automount: if an automount unit is masked, don't react to
+ activation anymore (#5445)
+
+Otherwise we'll hit an assert sooner or later.
+
+This requires us to initialize ->where even if we come back in "masked"
+mode, as otherwise we don't know how to operate on the automount and
+detach it.
+
+Fixes: #5441
+(cherry picked from commit e350ca3f1ecb6672b74cd25d09ef23c7b309aa5a)
+
+Resolves: #1498318
+---
+ src/core/automount.c | 74 +++++++++++++++++++++++++++++++++++-----------------
+ 1 file changed, 50 insertions(+), 24 deletions(-)
+
+diff --git a/src/core/automount.c b/src/core/automount.c
+index 4e066613d..20a5de8ca 100644
+--- a/src/core/automount.c
++++ b/src/core/automount.c
+@@ -106,18 +106,18 @@ static void unmount_autofs(Automount *a) {
+         if (a->pipe_fd < 0)
+                 return;
+ 
+-        automount_send_ready(a, a->tokens, -EHOSTDOWN);
+-        automount_send_ready(a, a->expire_tokens, -EHOSTDOWN);
+-
+         a->pipe_event_source = sd_event_source_unref(a->pipe_event_source);
+         a->pipe_fd = safe_close(a->pipe_fd);
+ 
+-        /* If we reload/reexecute things we keep the mount point
+-         * around */
+-        if (a->where &&
+-            (UNIT(a)->manager->exit_code != MANAGER_RELOAD &&
+-             UNIT(a)->manager->exit_code != MANAGER_REEXECUTE))
+-                repeat_unmount(a->where);
++        /* If we reload/reexecute things we keep the mount point around */
++        if (!IN_SET(UNIT(a)->manager->exit_code, MANAGER_RELOAD, MANAGER_REEXECUTE)) {
++
++                automount_send_ready(a, a->tokens, -EHOSTDOWN);
++                automount_send_ready(a, a->expire_tokens, -EHOSTDOWN);
++
++                if (a->where)
++                        repeat_unmount(a->where);
++        }
+ }
+ 
+ static void automount_done(Unit *u) {
+@@ -193,6 +193,20 @@ static int automount_verify(Automount *a) {
+         return 0;
+ }
+ 
++static int automount_set_where(Automount *a) {
++        assert(a);
++
++        if (a->where)
++                return 0;
++
++        a->where = unit_name_to_path(UNIT(a)->id);
++        if (!a->where)
++                return -ENOMEM;
++
++        path_kill_slashes(a->where);
++        return 1;
++}
++
+ static int automount_load(Unit *u) {
+         Automount *a = AUTOMOUNT(u);
+         int r;
+@@ -208,13 +222,9 @@ static int automount_load(Unit *u) {
+         if (u->load_state == UNIT_LOADED) {
+                 Unit *x;
+ 
+-                if (!a->where) {
+-                        a->where = unit_name_to_path(u->id);
+-                        if (!a->where)
+-                                return -ENOMEM;
+-                }
+-
+-                path_kill_slashes(a->where);
++                r = automount_set_where(a);
++                if (r < 0)
++                        return r;
+ 
+                 r = unit_load_related_unit(u, ".mount", &x);
+                 if (r < 0)
+@@ -259,6 +269,8 @@ static void automount_set_state(Automount *a, AutomountState state) {
+         unit_notify(UNIT(a), state_translation_table[old_state], state_translation_table[state], true);
+ }
+ 
++static int automount_start_expire(Automount *a);
++
+ static int automount_coldplug(Unit *u, Hashmap *deferred_work) {
+         Automount *a = AUTOMOUNT(u);
+         int r;
+@@ -266,20 +278,30 @@ static int automount_coldplug(Unit *u, Hashmap *deferred_work) {
+         assert(a);
+         assert(a->state == AUTOMOUNT_DEAD);
+ 
+-        if (a->deserialized_state != a->state) {
++        if (a->deserialized_state == a->state)
++                return 0;
++
++        if (IN_SET(a->deserialized_state, AUTOMOUNT_WAITING, AUTOMOUNT_RUNNING)) {
++
++                r = automount_set_where(a);
++                if (r < 0)
++                        return r;
+ 
+                 r = open_dev_autofs(u->manager);
+                 if (r < 0)
+                         return r;
+ 
+-                if (a->deserialized_state == AUTOMOUNT_WAITING ||
+-                    a->deserialized_state == AUTOMOUNT_RUNNING) {
++                assert(a->pipe_fd >= 0);
+ 
+-                        assert(a->pipe_fd >= 0);
++                r = sd_event_add_io(u->manager->event, &a->pipe_event_source, a->pipe_fd, EPOLLIN, automount_dispatch_io, u);
++                if (r < 0)
++                        return r;
+ 
+-                        r = sd_event_add_io(u->manager->event, &a->pipe_event_source, a->pipe_fd, EPOLLIN, automount_dispatch_io, u);
++                (void) sd_event_source_set_description(a->pipe_event_source, "automount-io");
++                if (a->deserialized_state == AUTOMOUNT_RUNNING) {
++                        r = automount_start_expire(a);
+                         if (r < 0)
+-                                return r;
++                                log_unit_warning_errno(UNIT(a)->id, r, "Failed to start expiration timer, ignoring: %m");
+                 }
+ 
+                 automount_set_state(a, a->deserialized_state);
+@@ -636,8 +658,6 @@ static void *expire_thread(void *p) {
+         return NULL;
+ }
+ 
+-static int automount_start_expire(Automount *a);
+-
+ static int automount_dispatch_expire(sd_event_source *source, usec_t usec, void *userdata) {
+         Automount *a = AUTOMOUNT(userdata);
+         _cleanup_(expire_data_freep) struct expire_data *data = NULL;
+@@ -699,6 +719,12 @@ static void automount_enter_runnning(Automount *a) {
+ 
+         assert(a);
+ 
++        /* If the user masked our unit in the meantime, fail */
++        if (UNIT(a)->load_state != UNIT_LOADED) {
++                log_unit_error(UNIT(a)->id, "Suppressing automount event since unit is no longer loaded.");
++                goto fail;
++        }
++
+         /* We don't take mount requests anymore if we are supposed to
+          * shut down anyway */
+         if (unit_stop_pending(UNIT(a))) {
diff --git a/SOURCES/0562-units-add-Install-section-to-remote-cryptsetup.targe.patch b/SOURCES/0562-units-add-Install-section-to-remote-cryptsetup.targe.patch
new file mode 100644
index 0000000..a8693a1
--- /dev/null
+++ b/SOURCES/0562-units-add-Install-section-to-remote-cryptsetup.targe.patch
@@ -0,0 +1,44 @@
+From 923299bbe6aa2c22a2592dcbcae722f273e7a5dd Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
+Date: Thu, 12 Oct 2017 22:13:03 +0200
+Subject: [PATCH] units: add [Install] section to remote-cryptsetup.target
+
+This makes this target the same as remote-fs.target in this regard. In practice
+it probably doesn't make that much difference, because all encrypted devices
+that are part of remote-fs.target (marked with _netdev) will be used for mount
+points, so they will be pulled in anyway individually, but with this change any
+such device will be configured, even if it is not pulled by any other unit.
+
+Cherry-picked from: 8f462b074eb9830d6d5029f70c9010ce50e68357
+Resolves: #1477757
+---
+ system-preset/90-systemd.preset | 1 +
+ units/remote-cryptsetup.target  | 6 ++++++
+ 2 files changed, 7 insertions(+)
+
+diff --git a/system-preset/90-systemd.preset b/system-preset/90-systemd.preset
+index 24963f062..a011ec67a 100644
+--- a/system-preset/90-systemd.preset
++++ b/system-preset/90-systemd.preset
+@@ -9,6 +9,7 @@
+ # generally follow a default-off policy.
+ 
+ enable remote-fs.target
++enable remote-cryptsetup.target
+ enable machines.target
+ 
+ enable getty@.service
+diff --git a/units/remote-cryptsetup.target b/units/remote-cryptsetup.target
+index 60943bd1c..c306d521f 100644
+--- a/units/remote-cryptsetup.target
++++ b/units/remote-cryptsetup.target
+@@ -8,3 +8,9 @@
+ [Unit]
+ Description=Remote Encrypted Volumes
+ Documentation=man:systemd.special(7)
++After=remote-cryptsetup-pre.target
++DefaultDependencies=no
++Conflicts=shutdown.target
++
++[Install]
++WantedBy=multi-user.target
diff --git a/SOURCES/0563-units-replace-remote-cryptsetup-pre.target-with-remo.patch b/SOURCES/0563-units-replace-remote-cryptsetup-pre.target-with-remo.patch
new file mode 100644
index 0000000..6ef7b47
--- /dev/null
+++ b/SOURCES/0563-units-replace-remote-cryptsetup-pre.target-with-remo.patch
@@ -0,0 +1,152 @@
+From 0d13caa0714c32af45165310e93f62c965f45b01 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
+Date: Thu, 12 Oct 2017 22:34:54 +0200
+Subject: [PATCH] units: replace remote-cryptsetup-pre.target with
+ remote-fs-pre.target
+
+remote-cryptsetup-pre.target was designed as an active unit (that pulls in
+network-online.target), the opposite of remote-fs-pre.target (a passive unit,
+with individual provider services ordering itself before it and pulling it in,
+for example iscsi.service and nfs-client.target).
+
+To make remote-cryptsetup-pre.target really work, those services should be
+ordered before it too. But this would require updates to all those services,
+not just changes from systemd side.
+
+But the requirements for remote-fs-pre.target and remote-cryptset-pre.target
+are fairly similar (e.g. iscsi devices can certainly be used for both), so
+let's reuse remote-fs-pre.target also for remote cryptsetup units. This loses
+a bit of flexibility, but does away with the requirement for various provider
+services to know about remote-cryptsetup-pre.target.
+
+Cherry-picked from: a0dd209763f9e67054ee322a2dfd52bccf345c2e
+Resolves: #1477757
+---
+ Makefile.am                           |  3 +--
+ man/crypttab.xml                      |  2 +-
+ man/systemd.special.xml               | 20 ++++----------------
+ src/cryptsetup/cryptsetup-generator.c |  2 +-
+ units/remote-cryptsetup-pre.target    | 15 ---------------
+ units/remote-cryptsetup.target        |  2 +-
+ 6 files changed, 8 insertions(+), 36 deletions(-)
+ delete mode 100644 units/remote-cryptsetup-pre.target
+
+diff --git a/Makefile.am b/Makefile.am
+index 13c93f485..f06bc29c2 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -4864,8 +4864,7 @@ systemgenerator_PROGRAMS += \
+ dist_systemunit_DATA += \
+ 	units/cryptsetup.target \
+ 	units/cryptsetup-pre.target \
+-	units/remote-cryptsetup.target \
+-	units/remote-cryptsetup-pre.target
++	units/remote-cryptsetup.target
+ 
+ systemd_cryptsetup_SOURCES = \
+ 	src/cryptsetup/cryptsetup.c
+diff --git a/man/crypttab.xml b/man/crypttab.xml
+index 7085a1623..a9197ab40 100644
+--- a/man/crypttab.xml
++++ b/man/crypttab.xml
+@@ -196,7 +196,7 @@
+         started after the network is available, similarly to
+         <citerefentry><refentrytitle>systemd.mount</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+         units marked with <option>_netdev</option>. The service unit to set up this device
+-        will be ordered between <filename>remote-cryptsetup-pre.target</filename> and
++        will be ordered between <filename>remote-fs-pre.target</filename> and
+         <filename>remote-cryptsetup.target</filename>, instead of
+         <filename>cryptsetup-pre.target</filename> and
+         <filename>cryptsetup.target</filename>.</para></listitem>
+diff --git a/man/systemd.special.xml b/man/systemd.special.xml
+index 5529d3bf7..e04f08bd3 100644
+--- a/man/systemd.special.xml
++++ b/man/systemd.special.xml
+@@ -81,7 +81,6 @@
+     <filename>poweroff.target</filename>,
+     <filename>printer.target</filename>,
+     <filename>reboot.target</filename>,
+-    <filename>remote-cryptsetup-pre.target</filename>,
+     <filename>remote-cryptsetup.target</filename>,
+     <filename>remote-fs.target</filename>,
+     <filename>remote-fs-pre.target</filename>,
+@@ -406,18 +405,6 @@
+           this target unit, for compatibility with SysV.</para>
+         </listitem>
+       </varlistentry>
+-      <varlistentry>
+-        <term><filename>remote-cryptsetup-pre.target</filename></term>
+-        <listitem>
+-          <para>This target unit is automatically ordered before all cryptsetup devices
+-          marked with the <option>_netdev</option>. It can be used to execute additional
+-          units before such devices are set up.</para>
+-
+-          <para>It is ordered after <filename>network.target</filename> and
+-          <filename>network-online.target</filename>, and also pulls the latter in as a
+-          <varname>Wants=</varname> dependency.</para>
+-        </listitem>
+-      </varlistentry>
+       <varlistentry>
+         <term><filename>remote-cryptsetup.target</filename></term>
+         <listitem>
+@@ -768,9 +755,10 @@
+         <term><filename>remote-fs-pre.target</filename></term>
+         <listitem>
+           <para>This target unit is automatically ordered before all
+-          remote mount point units (see above). It can be used to run
+-          certain units before the remote mounts are established. Note
+-          that this unit is generally not part of the initial
++          mount point units (see above) and cryptsetup devices
++          marked with the <option>_netdev</option>. It can be used to run
++          certain units before remote encrypted devices and mounts are established.
++          Note that this unit is generally not part of the initial
+           transaction, unless the unit that wants to be ordered before
+           all remote mounts pulls it in via a
+           <varname>Wants=</varname> type dependency. If the unit wants
+diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c
+index 49dc8f14b..82a280d86 100644
+--- a/src/cryptsetup/cryptsetup-generator.c
++++ b/src/cryptsetup/cryptsetup-generator.c
+@@ -114,7 +114,7 @@ static int create_disk(
+                 "IgnoreOnIsolate=true\n"
+                 "After=systemd-readahead-collect.service systemd-readahead-replay.service\n"
+                 "After=%s\n",
+-                netdev ? "remote-cryptsetup-pre.target" : "cryptsetup-pre.target");
++                netdev ? "remote-fs-pre.target" : "cryptsetup-pre.target");
+ 
+         if (!nofail)
+                 fprintf(f,
+diff --git a/units/remote-cryptsetup-pre.target b/units/remote-cryptsetup-pre.target
+deleted file mode 100644
+index a375e6188..000000000
+--- a/units/remote-cryptsetup-pre.target
++++ /dev/null
+@@ -1,15 +0,0 @@
+-#  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=Remote Encrypted Volumes (Pre)
+-Documentation=man:systemd.special(7)
+-RefuseManualStart=yes
+-Before=remote-cryptsetup.target
+-
+-After=network.target network-online.target
+-Wants=network-online.target
+diff --git a/units/remote-cryptsetup.target b/units/remote-cryptsetup.target
+index c306d521f..d485b0672 100644
+--- a/units/remote-cryptsetup.target
++++ b/units/remote-cryptsetup.target
+@@ -8,7 +8,7 @@
+ [Unit]
+ Description=Remote Encrypted Volumes
+ Documentation=man:systemd.special(7)
+-After=remote-cryptsetup-pre.target
++After=remote-fs-pre.target
+ DefaultDependencies=no
+ Conflicts=shutdown.target
+ 
diff --git a/SOURCES/0564-man-add-a-note-about-_netdev-usage.patch b/SOURCES/0564-man-add-a-note-about-_netdev-usage.patch
new file mode 100644
index 0000000..c72084c
--- /dev/null
+++ b/SOURCES/0564-man-add-a-note-about-_netdev-usage.patch
@@ -0,0 +1,41 @@
+From 3608a654d9d9c4f9d75454e5fe190ef938e9a4f4 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
+Date: Thu, 12 Oct 2017 22:43:58 +0200
+Subject: [PATCH] man: add a note about _netdev usage
+
+Cherry-picked from: 288c26165e0ff71857394f360f42432bc808556f
+Resolves: #1477757
+---
+ man/crypttab.xml | 12 +++++++++++-
+ 1 file changed, 11 insertions(+), 1 deletion(-)
+
+diff --git a/man/crypttab.xml b/man/crypttab.xml
+index a9197ab40..e4ecab3dc 100644
+--- a/man/crypttab.xml
++++ b/man/crypttab.xml
+@@ -199,7 +199,16 @@
+         will be ordered between <filename>remote-fs-pre.target</filename> and
+         <filename>remote-cryptsetup.target</filename>, instead of
+         <filename>cryptsetup-pre.target</filename> and
+-        <filename>cryptsetup.target</filename>.</para></listitem>
++        <filename>cryptsetup.target</filename>.</para>
++
++        <para>Hint: if this device is used for a mount point that is specified in
++        <citerefentry project='man-pages'><refentrytitle>fstab</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
++        the <option>_netdev</option> option should also be used for the mount
++        point. Otherwise, a dependency loop might be created where the mount point
++        will be pulled in by <filename>local-fs.target</filename>, while the
++        service to configure the network is usually only started <emphasis>after</emphasis>
++        the local file system has been mounted.</para>
++        </listitem>
+       </varlistentry>
+ 
+       <varlistentry>
+@@ -396,6 +405,7 @@ hidden     /mnt/tc_hidden  /dev/null    tcrypt-hidden,tcrypt-keyfile=/etc/keyfil
+       <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+       <citerefentry><refentrytitle>systemd-cryptsetup@.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+       <citerefentry><refentrytitle>systemd-cryptsetup-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
++      <citerefentry project='man-pages'><refentrytitle>fstab</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+       <citerefentry project='die-net'><refentrytitle>cryptsetup</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+       <citerefentry project='man-pages'><refentrytitle>mkswap</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+       <citerefentry project='man-pages'><refentrytitle>mke2fs</refentrytitle><manvolnum>8</manvolnum></citerefentry>
diff --git a/SOURCES/0565-units-make-remote-cryptsetup.target-also-after-crypt.patch b/SOURCES/0565-units-make-remote-cryptsetup.target-also-after-crypt.patch
new file mode 100644
index 0000000..5fb3090
--- /dev/null
+++ b/SOURCES/0565-units-make-remote-cryptsetup.target-also-after-crypt.patch
@@ -0,0 +1,28 @@
+From d3b747ccbd34fd11298429787e67429af9c06dbb Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
+Date: Wed, 18 Oct 2017 15:14:46 +0200
+Subject: [PATCH] units: make remote-cryptsetup.target also after
+ cryptsetup-pre.target
+
+This way people can order units before cryptsetup-pre.target and
+have them run before any cryptsetup-related stuff.
+
+Cherry-picked from: a0e030f53bad355be1084a0475eb30aae20e3e43
+Resolves: #1477757
+---
+ units/remote-cryptsetup.target | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/units/remote-cryptsetup.target b/units/remote-cryptsetup.target
+index d485b0672..ac4e1b71d 100644
+--- a/units/remote-cryptsetup.target
++++ b/units/remote-cryptsetup.target
+@@ -8,7 +8,7 @@
+ [Unit]
+ Description=Remote Encrypted Volumes
+ Documentation=man:systemd.special(7)
+-After=remote-fs-pre.target
++After=remote-fs-pre.target cryptsetup-pre.target
+ DefaultDependencies=no
+ Conflicts=shutdown.target
+ 
diff --git a/SOURCES/0566-cryptsetup-generator-use-after-free.patch b/SOURCES/0566-cryptsetup-generator-use-after-free.patch
new file mode 100644
index 0000000..9cdfb0c
--- /dev/null
+++ b/SOURCES/0566-cryptsetup-generator-use-after-free.patch
@@ -0,0 +1,28 @@
+From ae554d506040559c2dbf972ecf4a33be4fb6d869 Mon Sep 17 00:00:00 2001
+From: Lukas Nykryn <lnykryn@redhat.com>
+Date: Tue, 31 Oct 2017 12:59:02 +0100
+Subject: [PATCH] cryptsetup-generator: use after free
+
+rhel-only
+
+Related: #1477757
+---
+ src/cryptsetup/cryptsetup-generator.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c
+index 82a280d86..c387e2104 100644
+--- a/src/cryptsetup/cryptsetup-generator.c
++++ b/src/cryptsetup/cryptsetup-generator.c
+@@ -214,10 +214,8 @@ static int create_disk(
+                         return log_oom();
+ 
+                 mkdir_parents_label(to, 0755);
+-                if (symlink(from, to) < 0) {
+-                        free(to);
++                if (symlink(from, to) < 0)
+                         return log_error_errno(errno, "Failed to create symlink %s: %m", to);
+-                }
+         }
+ 
+         free(to);
diff --git a/SOURCES/0567-manager-fix-connecting-to-bus-when-dbus-is-actually-.patch b/SOURCES/0567-manager-fix-connecting-to-bus-when-dbus-is-actually-.patch
new file mode 100644
index 0000000..d6ee4d4
--- /dev/null
+++ b/SOURCES/0567-manager-fix-connecting-to-bus-when-dbus-is-actually-.patch
@@ -0,0 +1,34 @@
+From d46ca2a3ed881bc9324ebd9da0a66af1133d43a7 Mon Sep 17 00:00:00 2001
+From: Michal Sekletar <msekletar@users.noreply.github.com>
+Date: Wed, 1 Nov 2017 02:25:48 -0700
+Subject: [PATCH] manager: fix connecting to bus when dbus is actually around
+ (#7205)
+
+manager_connect_bus() is called *before* manager_coldplug(). As a last
+thing in service_coldplug() we set service state to
+s->deserialized_state, and thus before we do that all services are
+inactive and try_connect always evaluates to false. To fix that we must
+look at deserialized state instead of current unit state.
+
+Fixes #7146
+
+(cherry picked from commit 41dfa61d35c51a584437481d20541d5c3ccfa93d)
+
+Related: #1465737
+---
+ src/core/manager.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/core/manager.c b/src/core/manager.c
+index 041fac46b..47b09e1e9 100644
+--- a/src/core/manager.c
++++ b/src/core/manager.c
+@@ -809,7 +809,7 @@ static int manager_connect_bus(Manager *m, bool reexecuting) {
+         u = manager_get_unit(m, SPECIAL_DBUS_SERVICE);
+ 
+         try_bus_connect =
+-                (u && UNIT_IS_ACTIVE_OR_RELOADING(unit_active_state(u))) &&
++                (u && SERVICE(u)->deserialized_state == SERVICE_RUNNING) &&
+                 (reexecuting ||
+                 (m->running_as == SYSTEMD_USER && getenv("DBUS_SESSION_BUS_ADDRESS")));
+ 
diff --git a/SOURCES/0568-journal-remote-make-url-option-support-arbitrary-url.patch b/SOURCES/0568-journal-remote-make-url-option-support-arbitrary-url.patch
new file mode 100644
index 0000000..59537ff
--- /dev/null
+++ b/SOURCES/0568-journal-remote-make-url-option-support-arbitrary-url.patch
@@ -0,0 +1,40 @@
+From 70c096e5ae7bb7b415c82ee6cc177ac2d557feff Mon Sep 17 00:00:00 2001
+From: Yu Watanabe <watanabe.yu+github@gmail.com>
+Date: Sun, 24 Jan 2016 15:45:47 +0900
+Subject: [PATCH] journal-remote: make --url option support arbitrary url
+
+Currently, --url option supports the only form like http(s)://some.host:19531.
+This commit adds support to call systemd-journal-remote as follwos:
+systemd-journal-remote --url='http://some.host:19531'
+systemd-journal-remote --url='http://some.host:19531/'
+systemd-journal-remote --url='http://some.host:19531/entries'
+systemd-journal-remote --url='http://some.host:19531/entries?boot&follow'
+The first three example result the same and retrieve all entries.
+The last example retrieves only current boot entries and wait new events.
+
+Cherry-picked from: b68f6b0a794f9e6cb6457a0ac55041c4e7b1a5cb
+Resolves: #1505385
+---
+ src/journal-remote/journal-remote.c | 9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+diff --git a/src/journal-remote/journal-remote.c b/src/journal-remote/journal-remote.c
+index 4fac55cc9..a455fb6bd 100644
+--- a/src/journal-remote/journal-remote.c
++++ b/src/journal-remote/journal-remote.c
+@@ -894,7 +894,14 @@ static int remoteserver_init(RemoteServer *s,
+         if (arg_url) {
+                 const char *url, *hostname;
+ 
+-                url = strjoina(arg_url, "/entries");
++                if (!strstr(arg_url, "/entries")) {
++                        if (endswith(arg_url, "/"))
++                                url = strjoina(arg_url, "entries");
++                        else
++                                url = strjoina(arg_url, "/entries");
++                }
++                else
++                        url = strdupa(arg_url);
+ 
+                 if (arg_getter) {
+                         log_info("Spawning getter %s...", url);
diff --git a/SOURCES/0569-journald-make-maximum-size-of-stream-log-lines-confi.patch b/SOURCES/0569-journald-make-maximum-size-of-stream-log-lines-confi.patch
new file mode 100644
index 0000000..a238169
--- /dev/null
+++ b/SOURCES/0569-journald-make-maximum-size-of-stream-log-lines-confi.patch
@@ -0,0 +1,525 @@
+From 32244f8d21a3e06f6519c47234289da696f6b151 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Sun, 8 Oct 2017 09:05:59 +0200
+Subject: [PATCH] journald: make maximum size of stream log lines configurable
+ and bump it to 48K (#6838)
+
+This adds a new setting LineMax= to journald.conf, and sets it by
+default to 48K. When we convert stream-based stdout/stderr logging into
+record-based log entries, read up to the specified amount of bytes
+before forcing a line-break.
+
+This also makes three related changes:
+
+- When a NUL byte is read we'll not recognize this as alternative line
+  break, instead of silently dropping everything after it. (see #4863)
+
+- The reason for a line-break is now encoded in the log record, if it
+  wasn't a plain newline. Specifically, we distuingish "nul",
+  "line-max" and "eof", for line breaks due to NUL byte, due to the
+  maximum line length as configured with LineMax= or due to end of
+  stream. This data is stored in the new implicit _LINE_BREAK= field.
+  It's not synthesized for plain \n line breaks.
+
+- A randomized 128bit ID is assigned to each log stream.
+
+With these three changes in place it's (mostly) possible to reconstruct
+the original byte streams from log data, as (most) of the context of
+the conversion from the byte stream to log records is saved now. (So,
+the only bits we still drop are empty lines. Which might be something to
+look into in a future change, and which is outside of the scope of this
+work)
+
+Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=86465
+See: #4863
+Replaces: #4875
+
+(cherry picked from commit ec20fe5ffb8a00469bab209fff6c069bb93c6db2)
+
+Resolves: #1442262
+
+[msekleta: I had to manually rewrite upstream commit, because git
+did very poor job merging old and new code and identified a lot of merge
+conflicts in a code that was totally unrelated.]
+---
+ man/journald.conf.xml            |  18 ++++++
+ man/systemd.journal-fields.xml   |  22 ++++++++
+ src/journal/journald-gperf.gperf |   1 +
+ src/journal/journald-server.c    |  68 +++++++++++++++++++++++
+ src/journal/journald-server.h    |   3 +
+ src/journal/journald-stream.c    | 116 ++++++++++++++++++++++++++++++++-------
+ src/journal/journald.conf        |   1 +
+ 7 files changed, 209 insertions(+), 20 deletions(-)
+
+diff --git a/man/journald.conf.xml b/man/journald.conf.xml
+index 46a498b67..e2d6a1225 100644
+--- a/man/journald.conf.xml
++++ b/man/journald.conf.xml
+@@ -354,6 +354,24 @@
+         <filename>/dev/console</filename>.</para></listitem>
+       </varlistentry>
+ 
++      <varlistentry>
++        <term><varname>LineMax=</varname></term>
++
++        <listitem><para>The maximum line length to permit when converting stream logs into record logs. When a systemd
++        unit's standard output/error are connected to the journal via a stream socket, the data read is split into
++        individual log records at newline (<literal>\n</literal>, ASCII 10) and NUL characters. If no such delimiter is
++        read for the specified number of bytes a hard log record boundary is artifically inserted, breaking up overly
++        long lines into multiple log records. Selecting overly large values increases the possible memory usage of the
++        Journal daemon for each stream client, as in the worst case the journal daemon needs to buffer the specified
++        number of bytes in memory before it can flush a new log record to disk. Also note that permitting overly large
++        line maximum line lengths affects compatibility with traditional log protocols as log records might not fit
++        anymore into a single <constant>AF_UNIX</constant> or <constant>AF_INET</constant> datagram. Takes a size in
++        bytes. If the value is suffixed with K, M, G or T, the specified size is parsed as Kilobytes, Megabytes,
++        Gigabytes, or Terabytes (with the base 1024), respectively. Defaults to 48K, which is relatively large but
++        still small enough so that log records likely fit into network datagrams along with extra room for
++        metadata. Note that values below 79 are not accepted and will be bumped to 79.</para></listitem>
++      </varlistentry>
++
+     </variablelist>
+ 
+   </refsect1>
+diff --git a/man/systemd.journal-fields.xml b/man/systemd.journal-fields.xml
+index 7d6c5c715..a53f8def2 100644
+--- a/man/systemd.journal-fields.xml
++++ b/man/systemd.journal-fields.xml
+@@ -311,6 +311,28 @@
+           </variablelist>
+         </listitem>
+       </varlistentry>
++      <varlistentry>
++        <term><varname>_STREAM_ID=</varname></term>
++        <listitem>
++          <para>Only applies to <literal>_TRANSPORT=stream</literal> records: specifies a randomized 128bit ID assigned
++          to the stream connection when it was first created. This ID is useful to reconstruct individual log streams
++          from the log records: all log records carrying the same stream ID originate from the same stream.</para>
++        </listitem>
++      </varlistentry>
++      <varlistentry>
++        <term><varname>_LINE_BREAK=</varname></term>
++        <listitem>
++          <para>Only applies to <literal>_TRANSPORT=stream</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>
++        </listitem>
++      </varlistentry>
+     </variablelist>
+   </refsect1>
+ 
+diff --git a/src/journal/journald-gperf.gperf b/src/journal/journald-gperf.gperf
+index 74554c1c3..73327c10e 100644
+--- a/src/journal/journald-gperf.gperf
++++ b/src/journal/journald-gperf.gperf
+@@ -40,3 +40,4 @@ Journal.MaxLevelKMsg,       config_parse_log_level,  0, offsetof(Server, max_lev
+ Journal.MaxLevelConsole,    config_parse_log_level,  0, offsetof(Server, max_level_console)
+ Journal.MaxLevelWall,       config_parse_log_level,  0, offsetof(Server, max_level_wall)
+ Journal.SplitMode,          config_parse_split_mode, 0, offsetof(Server, split_mode)
++Journal.LineMax,            config_parse_line_max,   0, offsetof(Server, line_max)
+\ No newline at end of file
+diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c
+index f6f8c30eb..daeecd519 100644
+--- a/src/journal/journald-server.c
++++ b/src/journal/journald-server.c
+@@ -67,6 +67,10 @@
+ 
+ #define RECHECK_AVAILABLE_SPACE_USEC (30*USEC_PER_SEC)
+ 
++/* Pick a good default that is likely to fit into AF_UNIX and AF_INET SOCK_DGRAM datagrams, and even leaves some room
+++ * for a bit of additional metadata. */
++#define DEFAULT_LINE_MAX (48*1024)
++
+ static const char* const storage_table[_STORAGE_MAX] = {
+         [STORAGE_AUTO] = "auto",
+         [STORAGE_VOLATILE] = "volatile",
+@@ -83,9 +87,71 @@ static const char* const split_mode_table[_SPLIT_MAX] = {
+         [SPLIT_NONE] = "none",
+ };
+ 
++
+ DEFINE_STRING_TABLE_LOOKUP(split_mode, SplitMode);
+ DEFINE_CONFIG_PARSE_ENUM(config_parse_split_mode, split_mode, SplitMode, "Failed to parse split mode setting");
+ 
++int config_parse_line_max(
++                const char* unit,
++                const char *filename,
++                unsigned line,
++                const char *section,
++                unsigned section_line,
++                const char *lvalue,
++                int ltype,
++                const char *rvalue,
++                void *data,
++                void *userdata) {
++
++        size_t *sz = data;
++        int r;
++
++        assert(filename);
++        assert(lvalue);
++        assert(rvalue);
++        assert(data);
++
++        if (isempty(rvalue))
++                /* Empty assignment means default */
++                *sz = DEFAULT_LINE_MAX;
++        else {
++                uint64_t v;
++                off_t u;
++
++                r = parse_size(rvalue, 1024, &u);
++                if (r < 0) {
++                        log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse LineMax= value, ignoring: %s", rvalue);
++                        return 0;
++                }
++
++                /* Backport note */
++                /* Upstream ditched use of off_t however our parse_size implementation still takes off_t*
++                 * as an argument. Since we compile with -Werror, we have two choices, either disable sign-compare
++                 * warning or do this casting so we don't have to change rest of the code. I think it is
++                 * better to do cast here instead of rewriting the code so it deals with off_t instead of
++                 * uint64_t. Doing conversion off_t -> uint64_t is something that we should think about. */
++                v = (uint64_t) u;
++
++                if (v < 79) {
++                        /* Why specify 79 here as minimum line length? Simply, because the most common traditional
++                         * terminal size is 80ch, and it might make sense to break one character before the natural
++                         * line break would occur on that. */
++                        log_syntax(unit, LOG_WARNING, filename, line, 0, "LineMax= too small, clamping to 79: %s", rvalue);
++                        *sz = 79;
++                } else if (v > (uint64_t) (SSIZE_MAX-1)) {
++                        /* So, why specify SSIZE_MAX-1 here? Because that's one below the largest size value read()
++                         * can return, and we need one extra byte for the trailing NUL byte. Of course IRL such large
++                         * memory allocations will fail anyway, hence this limit is mostly theoretical anyway, as we'll
++                         * fail much earlier anyway. */
++                        log_syntax(unit, LOG_WARNING, filename, line, 0, "LineMax= too large, clamping to %" PRIu64 ": %s", (uint64_t) (SSIZE_MAX-1), rvalue);
++                        *sz = SSIZE_MAX-1;
++                } else
++                        *sz = (size_t) v;
++        }
++
++        return 0;
++}
++
+ static uint64_t available_space(Server *s, bool verbose) {
+         char ids[33];
+         _cleanup_free_ char *p = NULL;
+@@ -1518,6 +1584,8 @@ int server_init(Server *s) {
+         s->max_level_console = LOG_INFO;
+         s->max_level_wall = LOG_EMERG;
+ 
++        s->line_max = DEFAULT_LINE_MAX;
++
+         memset(&s->system_metrics, 0xFF, sizeof(s->system_metrics));
+         memset(&s->runtime_metrics, 0xFF, sizeof(s->runtime_metrics));
+ 
+diff --git a/src/journal/journald-server.h b/src/journal/journald-server.h
+index 7a456c2d5..b29410778 100644
+--- a/src/journal/journald-server.h
++++ b/src/journal/journald-server.h
+@@ -143,6 +143,8 @@ typedef struct Server {
+ 
+         /* Cached cgroup root, so that we don't have to query that all the time */
+         char *cgroup_root;
++
++        size_t line_max;
+ } Server;
+ 
+ #define N_IOVEC_META_FIELDS 20
+@@ -157,6 +159,7 @@ void server_driver_message(Server *s, sd_id128_t message_id, const char *format,
+ const struct ConfigPerfItem* journald_gperf_lookup(const char *key, unsigned length);
+ 
+ int config_parse_storage(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
++int config_parse_line_max(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+ 
+ const char *storage_to_string(Storage s) _const_;
+ Storage storage_from_string(const char *s) _pure_;
+diff --git a/src/journal/journald-stream.c b/src/journal/journald-stream.c
+index 15c9110c0..4d6b7ad18 100644
+--- a/src/journal/journald-stream.c
++++ b/src/journal/journald-stream.c
+@@ -53,6 +53,16 @@ typedef enum StdoutStreamState {
+         STDOUT_STREAM_RUNNING
+ } StdoutStreamState;
+ 
++/* The different types of log record terminators: a real \n was read, a NUL character was read, the maximum line length
++ * was reached, or the end of the stream was reached */
++
++typedef enum LineBreak {
++        LINE_BREAK_NEWLINE,
++        LINE_BREAK_NUL,
++        LINE_BREAK_LINE_MAX,
++        LINE_BREAK_EOF,
++} LineBreak;
++
+ struct StdoutStream {
+         Server *server;
+         StdoutStreamState state;
+@@ -71,14 +81,17 @@ struct StdoutStream {
+ 
+         bool fdstore:1;
+ 
+-        char buffer[LINE_MAX+1];
++        char *buffer;
+         size_t length;
++        size_t allocated;
+ 
+         sd_event_source *event_source;
+ 
+         char *state_file;
+ 
+         LIST_FIELDS(StdoutStream, stdout_stream);
++
++        char id_field[sizeof("_STREAM_ID=")-1 + SD_ID128_STRING_MAX];
+ };
+ 
+ void stdout_stream_free(StdoutStream *s) {
+@@ -101,6 +114,7 @@ void stdout_stream_free(StdoutStream *s) {
+         free(s->identifier);
+         free(s->unit_id);
+         free(s->state_file);
++        free(s->buffer);
+ 
+         free(s);
+ }
+@@ -151,12 +165,14 @@ static int stdout_stream_save(StdoutStream *s) {
+                 "LEVEL_PREFIX=%i\n"
+                 "FORWARD_TO_SYSLOG=%i\n"
+                 "FORWARD_TO_KMSG=%i\n"
+-                "FORWARD_TO_CONSOLE=%i\n",
++                "FORWARD_TO_CONSOLE=%i\n"
++                "STREAM_ID=%s\n",
+                 s->priority,
+                 s->level_prefix,
+                 s->forward_to_syslog,
+                 s->forward_to_kmsg,
+-                s->forward_to_console);
++                s->forward_to_console,
++                s->id_field + strlen("_STREAM_ID="));
+ 
+         if (!isempty(s->identifier)) {
+                 _cleanup_free_ char *escaped;
+@@ -211,8 +227,8 @@ finish:
+         return r;
+ }
+ 
+-static int stdout_stream_log(StdoutStream *s, const char *p) {
+-        struct iovec iovec[N_IOVEC_META_FIELDS + 5];
++static int stdout_stream_log(StdoutStream *s, const char *p, LineBreak line_break) {
++        struct iovec iovec[N_IOVEC_META_FIELDS + 7];
+         int priority;
+         char syslog_priority[] = "PRIORITY=\0";
+         char syslog_facility[sizeof("SYSLOG_FACILITY=")-1 + DECIMAL_STR_MAX(int) + 1];
+@@ -245,6 +261,8 @@ static int stdout_stream_log(StdoutStream *s, const char *p) {
+ 
+         IOVEC_SET_STRING(iovec[n++], "_TRANSPORT=stdout");
+ 
++        IOVEC_SET_STRING(iovec[n++], s->id_field);
++
+         syslog_priority[strlen("PRIORITY=")] = '0' + LOG_PRI(priority);
+         IOVEC_SET_STRING(iovec[n++], syslog_priority);
+ 
+@@ -259,6 +277,18 @@ static int stdout_stream_log(StdoutStream *s, const char *p) {
+                         IOVEC_SET_STRING(iovec[n++], syslog_identifier);
+         }
+ 
++        if (line_break != LINE_BREAK_NEWLINE) {
++                const char *c;
++
++                /* If this log message was generated due to an uncommon line break then mention this in the log
++                 * entry */
++
++                c =     line_break == LINE_BREAK_NUL ?      "_LINE_BREAK=nul" :
++                        line_break == LINE_BREAK_LINE_MAX ? "_LINE_BREAK=line-max" :
++                                                            "_LINE_BREAK=eof";
++                IOVEC_SET_STRING(iovec[n++], c);
++        }
++
+         message = strappend("MESSAGE=", p);
+         if (message)
+                 IOVEC_SET_STRING(iovec[n++], message);
+@@ -268,12 +298,18 @@ static int stdout_stream_log(StdoutStream *s, const char *p) {
+         return 0;
+ }
+ 
+-static int stdout_stream_line(StdoutStream *s, char *p) {
++static int stdout_stream_line(StdoutStream *s, char *p, LineBreak line_break) {
+         int r;
+ 
+         assert(s);
+         assert(p);
+ 
++        /* line breaks by NUL, line max length or EOF are not permissible during the negotiation part of the protocol */
++        if (line_break != LINE_BREAK_NEWLINE && s->state != STDOUT_STREAM_RUNNING) {
++                log_warning("Control protocol line not properly terminated.");
++                return -EINVAL;
++        }
++
+         p = strstrip(p);
+ 
+         switch (s->state) {
+@@ -362,7 +398,7 @@ static int stdout_stream_line(StdoutStream *s, char *p) {
+                 return 0;
+ 
+         case STDOUT_STREAM_RUNNING:
+-                return stdout_stream_log(s, p);
++                return stdout_stream_log(s, p, line_break);
+         }
+ 
+         assert_not_reached("Unknown stream state");
+@@ -378,21 +414,32 @@ static int stdout_stream_scan(StdoutStream *s, bool force_flush) {
+         p = s->buffer;
+         remaining = s->length;
+         for (;;) {
+-                char *end;
++                LineBreak line_break;
+                 size_t skip;
+ 
+-                end = memchr(p, '\n', remaining);
+-                if (end)
+-                        skip = end - p + 1;
+-                else if (remaining >= sizeof(s->buffer) - 1) {
+-                        end = p + sizeof(s->buffer) - 1;
++                char *end1, *end2;
++
++                end1 = memchr(p, '\n', remaining);
++                end2 = memchr(p, 0, end1 ? (size_t) (end1 - p) : remaining);
++
++                if (end2) {
++                        /* We found a NUL terminator */
++                        skip = end2 - p + 1;
++                        line_break = LINE_BREAK_NUL;
++                } else if (end1) {
++                        /* We found a \n terminator */
++                        *end1 = 0;
++                        skip = end1 - p + 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;
++                        line_break = LINE_BREAK_LINE_MAX;
+                 } else
+                         break;
+ 
+-                *end = 0;
+-
+-                r = stdout_stream_line(s, p);
++                r = stdout_stream_line(s, p, line_break);
+                 if (r < 0)
+                         return r;
+ 
+@@ -402,7 +449,7 @@ static int stdout_stream_scan(StdoutStream *s, bool force_flush) {
+ 
+         if (force_flush && remaining > 0) {
+                 p[remaining] = 0;
+-                r = stdout_stream_line(s, p);
++                r = stdout_stream_line(s, p, LINE_BREAK_EOF);
+                 if (r < 0)
+                         return r;
+ 
+@@ -420,6 +467,7 @@ 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) {
+         StdoutStream *s = userdata;
++        size_t limit;
+         ssize_t l;
+         int r;
+ 
+@@ -430,9 +478,20 @@ static int stdout_stream_process(sd_event_source *es, int fd, uint32_t revents,
+                 goto terminate;
+         }
+ 
+-        l = read(s->fd, s->buffer+s->length, sizeof(s->buffer)-1-s->length);
+-        if (l < 0) {
++        /* If the buffer is full already (discounting the extra NUL we need), add room for another 1K */
++        if (s->length + 1 >= s->allocated) {
++                if (!GREEDY_REALLOC(s->buffer, s->allocated, s->length + 1 + 1024)) {
++                        log_oom();
++                        goto terminate;
++                }
++        }
++
++        /* 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);
+ 
++        l = read(s->fd, s->buffer + s->length, limit - s->length);
++        if (l < 0) {
+                 if (errno == EAGAIN)
+                         return 0;
+ 
+@@ -459,11 +518,16 @@ terminate:
+ 
+ static int stdout_stream_install(Server *s, int fd, StdoutStream **ret) {
+         _cleanup_(stdout_stream_freep) StdoutStream *stream = NULL;
++        sd_id128_t id;
+         int r;
+ 
+         assert(s);
+         assert(fd >= 0);
+ 
++        r = sd_id128_randomize(&id);
++        if (r < 0)
++                return log_error_errno(r, "Failed to generate stream ID: %m");
++
+         stream = new0(StdoutStream, 1);
+         if (!stream)
+                 return log_oom();
+@@ -471,6 +535,8 @@ static int stdout_stream_install(Server *s, int fd, StdoutStream **ret) {
+         stream->fd = -1;
+         stream->priority = LOG_INFO;
+ 
++        xsprintf(stream->id_field, "_STREAM_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(id));
++
+         r = getpeercred(fd, &stream->ucred);
+         if (r < 0)
+                 return log_error_errno(r, "Failed to determine peer credentials: %m");
+@@ -545,7 +611,8 @@ static int stdout_stream_load(StdoutStream *stream, const char *fname) {
+                 *level_prefix = NULL,
+                 *forward_to_syslog = NULL,
+                 *forward_to_kmsg = NULL,
+-                *forward_to_console = NULL;
++                *forward_to_console = NULL,
++                *stream_id = NULL;
+         int r;
+ 
+         assert(stream);
+@@ -565,6 +632,7 @@ static int stdout_stream_load(StdoutStream *stream, const char *fname) {
+                            "FORWARD_TO_CONSOLE", &forward_to_console,
+                            "IDENTIFIER", &stream->identifier,
+                            "UNIT", &stream->unit_id,
++                           "STREAM_ID", &stream_id,
+                            NULL);
+         if (r < 0)
+                 return log_error_errno(r, "Failed to read: %s", stream->state_file);
+@@ -601,6 +669,14 @@ static int stdout_stream_load(StdoutStream *stream, const char *fname) {
+                         stream->forward_to_console = r;
+         }
+ 
++        if (stream_id) {
++                sd_id128_t id;
++
++                r = sd_id128_from_string(stream_id, &id);
++                if (r >= 0)
++                        xsprintf(stream->id_field, "_STREAM_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(id));
++        }
++
+         return 0;
+ }
+ 
+diff --git a/src/journal/journald.conf b/src/journal/journald.conf
+index 3907dfb7f..5355ec2b2 100644
+--- a/src/journal/journald.conf
++++ b/src/journal/journald.conf
+@@ -37,3 +37,4 @@
+ #MaxLevelKMsg=notice
+ #MaxLevelConsole=info
+ #MaxLevelWall=emerg
++#LineMax=48K
diff --git a/SOURCES/0570-service-serialize-information-about-currently-execut.patch b/SOURCES/0570-service-serialize-information-about-currently-execut.patch
new file mode 100644
index 0000000..08e3ac1
--- /dev/null
+++ b/SOURCES/0570-service-serialize-information-about-currently-execut.patch
@@ -0,0 +1,304 @@
+From 5aafbcced90ae2a3b418d6fe26c67e820daa8bad Mon Sep 17 00:00:00 2001
+From: Michal Sekletar <msekleta@redhat.com>
+Date: Mon, 23 Jan 2017 17:12:35 +0100
+Subject: [PATCH] service: serialize information about currently executing
+ command
+
+Stored information will help us to resume execution after the
+daemon-reload.
+
+This commit implements following scheme,
+
+* On serialization:
+  - we count rank of the currently executing command
+  - we store command type, its rank and command line arguments
+
+* On deserialization:
+  - configuration is parsed and loaded
+  - we deserialize stored data, command type, rank and arguments
+  - we look at the given rank in the list and if command there has same
+    arguments then we restore execution at that point
+  - otherwise we search respective command list and we look for command
+    that has the same arguments
+  - if both methods fail we do not do not resume execution at all
+
+To better illustrate how does above scheme works, please consider
+following cases (<<< denotes position where we resume execution after reload)
+
+; Original unit file
+[Service]
+ExecStart=/bin/true <<<
+ExecStart=/bin/false
+
+; Swapped commands
+; Second command is not going to be executed
+[Service]
+ExecStart=/bin/false
+ExecStart=/bin/true <<<
+
+; Commands added before
+; Same commands are problematic and execution could be restarted at wrong place
+[Service]
+ExecStart=/bin/foo
+ExecStart=/bin/bar
+ExecStart=/bin/true <<<
+ExecStart=/bin/false
+
+; Commands added after
+; Same commands are not an issue in this case
+[Service]
+ExecStart=/bin/true <<<
+ExecStart=/bin/false
+ExecStart=/bin/foo
+ExecStart=/bin/bar
+
+; New commands interleaved with old commands
+; Some new commands will be executed while others won't
+ExecStart=/bin/foo
+ExecStart=/bin/true <<<
+ExecStart=/bin/bar
+ExecStart=/bin/false
+
+As you can see, above scheme has some drawbacks. However, in most
+cases (we assume that in most common case unit file command list is not
+changed while some other command is running for the same unit) it
+should cause that systemd does the right thing, which is restoring
+execution exactly at the point we were before daemon-reload.
+
+Fixes #518
+
+(cherry picked from commit e266c068b5597e18b2299f9c9d3ee6cf04198c41)
+
+Resolves: #1404657,#1471230
+---
+ src/core/service.c | 195 ++++++++++++++++++++++++++++++++++++++++++++++++-----
+ 1 file changed, 180 insertions(+), 15 deletions(-)
+
+diff --git a/src/core/service.c b/src/core/service.c
+index 3bd6c3338..9ad3a0eb0 100644
+--- a/src/core/service.c
++++ b/src/core/service.c
+@@ -1950,6 +1950,80 @@ _pure_ static bool service_can_reload(Unit *u) {
+         return !!s->exec_command[SERVICE_EXEC_RELOAD];
+ }
+ 
++static unsigned service_exec_command_index(Unit *u, ServiceExecCommand id, ExecCommand *current) {
++        Service *s = SERVICE(u);
++        unsigned idx = 0;
++        ExecCommand *first, *c;
++
++        assert(s);
++
++        first = s->exec_command[id];
++
++        /* Figure out where we are in the list by walking back to the beginning */
++        for (c = current; c != first; c = c->command_prev)
++                idx++;
++
++        return idx;
++}
++
++static int service_serialize_exec_command(Unit *u, FILE *f, ExecCommand *command) {
++        Service *s = SERVICE(u);
++        ServiceExecCommand id;
++        unsigned idx;
++        const char *type;
++        char **arg;
++        _cleanup_strv_free_ char **escaped_args = NULL;
++        _cleanup_free_ char *args = NULL, *p = NULL;
++        size_t allocated = 0, length = 0;
++
++        assert(s);
++        assert(f);
++
++        if (!command)
++                return 0;
++
++        if (command == s->control_command) {
++                type = "control";
++                id = s->control_command_id;
++        } else {
++                type = "main";
++                id = SERVICE_EXEC_START;
++        }
++
++        idx = service_exec_command_index(u, id, command);
++
++        STRV_FOREACH(arg, command->argv) {
++                size_t n;
++                _cleanup_free_ char *e = NULL;
++
++                e = xescape(*arg, WHITESPACE);
++                if (!e)
++                        return -ENOMEM;
++
++                n = strlen(e);
++                if (!GREEDY_REALLOC(args, allocated, length + 1 + n + 1))
++                        return -ENOMEM;
++
++                if (length > 0)
++                        args[length++] = ' ';
++
++                memcpy(args + length, e, n);
++                length += n;
++        }
++
++        if (!GREEDY_REALLOC(args, allocated, length + 1))
++                return -ENOMEM;
++        args[length++] = 0;
++
++        p = xescape(command->path, WHITESPACE);
++        if (!p)
++                return -ENOMEM;
++
++        fprintf(f, "%s-command=%s %u %s %s\n", type, service_exec_command_to_string(id), idx, p, args);
++
++        return 0;
++}
++
+ static int service_serialize(Unit *u, FILE *f, FDSet *fds) {
+         Service *s = SERVICE(u);
+         ServiceFDStore *fs;
+@@ -1974,12 +2048,8 @@ static int service_serialize(Unit *u, FILE *f, FDSet *fds) {
+         if (s->status_text)
+                 unit_serialize_item(u, f, "status-text", s->status_text);
+ 
+-        /* FIXME: There's a minor uncleanliness here: if there are
+-         * multiple commands attached here, we will start from the
+-         * first one again */
+-        if (s->control_command_id >= 0)
+-                unit_serialize_item(u, f, "control-command",
+-                                    service_exec_command_to_string(s->control_command_id));
++        service_serialize_exec_command(u, f, s->control_command);
++        service_serialize_exec_command(u, f, s->main_command);
+ 
+         if (s->socket_fd >= 0) {
+                 int copy;
+@@ -2035,6 +2105,106 @@ static int service_serialize(Unit *u, FILE *f, FDSet *fds) {
+         return 0;
+ }
+ 
++static int service_deserialize_exec_command(Unit *u, const char *key, const char *value) {
++        Service *s = SERVICE(u);
++        int r;
++        unsigned idx = 0, i;
++        bool control, found = false;
++        ServiceExecCommand id = _SERVICE_EXEC_COMMAND_INVALID;
++        ExecCommand *command = NULL;
++        _cleanup_free_ char *args = NULL, *path = NULL;
++        _cleanup_strv_free_ char **argv = NULL;
++
++        enum ExecCommandState {
++                STATE_EXEC_COMMAND_TYPE,
++                STATE_EXEC_COMMAND_INDEX,
++                STATE_EXEC_COMMAND_PATH,
++                STATE_EXEC_COMMAND_ARGS,
++                _STATE_EXEC_COMMAND_MAX,
++                _STATE_EXEC_COMMAND_INVALID = -1,
++        } state;
++
++        assert(s);
++        assert(key);
++        assert(value);
++
++        control = streq(key, "control-command");
++
++        state = STATE_EXEC_COMMAND_TYPE;
++
++        for (;;) {
++                _cleanup_free_ char *arg = NULL;
++
++                r = extract_first_word(&value, &arg, NULL, EXTRACT_CUNESCAPE);
++                if (r == 0)
++                        break;
++                else if (r < 0)
++                        return r;
++
++                switch (state) {
++                case STATE_EXEC_COMMAND_TYPE:
++                        id = service_exec_command_from_string(arg);
++                        if (id < 0)
++                                return -EINVAL;
++
++                        state = STATE_EXEC_COMMAND_INDEX;
++                        break;
++                case STATE_EXEC_COMMAND_INDEX:
++                        r = safe_atou(arg, &idx);
++                        if (r < 0)
++                                return -EINVAL;
++
++                        state = STATE_EXEC_COMMAND_PATH;
++                        break;
++                case STATE_EXEC_COMMAND_PATH:
++                        path = arg;
++                        arg = NULL;
++                        state = STATE_EXEC_COMMAND_ARGS;
++
++                        if (!path_is_absolute(path))
++                                return -EINVAL;
++                        break;
++                case STATE_EXEC_COMMAND_ARGS:
++                        r = strv_extend(&argv, arg);
++                        if (r < 0)
++                                return -ENOMEM;
++                        break;
++                default:
++                        assert_not_reached("Unknown error at deserialization of exec command");
++                        break;
++                }
++        }
++
++        if (state != STATE_EXEC_COMMAND_ARGS)
++                return -EINVAL;
++
++        /* Let's check whether exec command on given offset matches data that we just deserialized */
++        for (command = s->exec_command[id], i = 0; command; command = command->command_next, i++) {
++                if (i != idx)
++                        continue;
++
++                found = strv_equal(argv, command->argv) && streq(command->path, path);
++                break;
++        }
++
++        if (!found) {
++                /* Command at the index we serialized is different, let's look for command that exactly
++                 * matches but is on different index. If there is no such command we will not resume execution. */
++                for (command = s->exec_command[id]; command; command = command->command_next)
++                        if (strv_equal(command->argv, argv) && streq(command->path, path))
++                                break;
++        }
++
++        if (command && control)
++                s->control_command = command;
++        else if (command)
++                s->main_command = command;
++        else
++                log_unit_warning(u->id, "Current command vanished from the unit file, execution of the command list won't be resumed.");
++
++        return 0;
++}
++
+ static int service_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
+         Service *s = SERVICE(u);
+         int r;
+@@ -2105,16 +2275,11 @@ static int service_deserialize_item(Unit *u, const char *key, const char *value,
+                         s->status_text = t;
+                 }
+ 
+-        } else if (streq(key, "control-command")) {
+-                ServiceExecCommand id;
++        } else if (STR_IN_SET(key, "main-command", "control-command")) {
++                r = service_deserialize_exec_command(u, key, value);
++                if (r < 0)
++                        log_unit_debug_errno(u->id, r, "Failed to parse serialized command \"%s\": %m", value);
+ 
+-                id = service_exec_command_from_string(value);
+-                if (id < 0)
+-                        log_unit_debug(u->id, "Failed to parse exec-command value %s", value);
+-                else {
+-                        s->control_command_id = id;
+-                        s->control_command = s->exec_command[id];
+-                }
+         } else if (streq(key, "socket-fd")) {
+                 int fd;
+ 
diff --git a/SOURCES/0571-tests-add-new-test-for-issue-518.patch b/SOURCES/0571-tests-add-new-test-for-issue-518.patch
new file mode 100644
index 0000000..252fc6b
--- /dev/null
+++ b/SOURCES/0571-tests-add-new-test-for-issue-518.patch
@@ -0,0 +1,226 @@
+From 675af6905b424f2a927e4737a53f9b844e0cd9cc Mon Sep 17 00:00:00 2001
+From: Michal Sekletar <msekleta@redhat.com>
+Date: Wed, 15 Feb 2017 12:40:52 +0100
+Subject: [PATCH] tests: add new test for issue #518
+
+(cherry picked from commit 123d672e85d0c52ff7cf81997d4910990da409c1)
+
+Related: #1404657, #1471230
+---
+ Makefile.am                       |   3 +-
+ test/test-exec-deserialization.py | 192 ++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 194 insertions(+), 1 deletion(-)
+ create mode 100755 test/test-exec-deserialization.py
+
+diff --git a/Makefile.am b/Makefile.am
+index f06bc29c2..c4a96e1fd 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -5711,7 +5711,8 @@ EXTRA_DIST += \
+ 	src/network/networkd-network-gperf.gperf \
+ 	src/network/networkd-netdev-gperf.gperf \
+ 	units/systemd-networkd.service.in \
+-	units/systemd-networkd-wait-online.service.in
++	units/systemd-networkd-wait-online.service.in \
++	test/test-exec-deserialization.py
+ 
+ CLEANFILES += \
+ 	src/network/networkd-network-gperf.c \
+diff --git a/test/test-exec-deserialization.py b/test/test-exec-deserialization.py
+new file mode 100755
+index 000000000..b974b1c13
+--- /dev/null
++++ b/test/test-exec-deserialization.py
+@@ -0,0 +1,192 @@
++#!/usr/bin/python3
++
++#
++#  Copyright 2017 Michal Sekletar <msekleta@redhat.com>
++#
++#  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.
++#
++#  systemd is distributed in the hope that it will be useful, but
++#  WITHOUT ANY WARRANTY; without even the implied warranty of
++#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++#  Lesser General Public License for more details.
++#
++#  You should have received a copy of the GNU Lesser General Public License
++#  along with systemd; If not, see <http://www.gnu.org/licenses/>.
++
++# ATTENTION: This uses the *installed* systemd, not the one from the built
++# source tree.
++
++import unittest
++import time
++import os
++import tempfile
++import subprocess
++
++from enum import Enum
++
++class UnitFileChange(Enum):
++    NO_CHANGE = 0
++    LINES_SWAPPED = 1
++    COMMAND_ADDED_BEFORE = 2
++    COMMAND_ADDED_AFTER = 3
++    COMMAND_INTERLEAVED = 4
++    REMOVAL = 5
++
++class ExecutionResumeTest(unittest.TestCase):
++    def setUp(self):
++        self.unit = 'test-issue-518.service'
++        self.unitfile_path = '/run/systemd/system/{0}'.format(self.unit)
++        self.output_file = tempfile.mktemp()
++        self.unit_files = {}
++
++        unit_file_content = '''
++        [Service]
++        Type=oneshot
++        ExecStart=/bin/sleep 2
++        ExecStart=/bin/bash -c "echo foo >> {0}"
++        '''.format(self.output_file)
++        self.unit_files[UnitFileChange.NO_CHANGE] = unit_file_content
++
++        unit_file_content = '''
++        [Service]
++        Type=oneshot
++        ExecStart=/bin/bash -c "echo foo >> {0}"
++        ExecStart=/bin/sleep 2
++        '''.format(self.output_file)
++        self.unit_files[UnitFileChange.LINES_SWAPPED] = unit_file_content
++
++        unit_file_content = '''
++        [Service]
++        Type=oneshot
++        ExecStart=/bin/bash -c "echo bar >> {0}"
++        ExecStart=/bin/sleep 2
++        ExecStart=/bin/bash -c "echo foo >> {0}"
++        '''.format(self.output_file)
++        self.unit_files[UnitFileChange.COMMAND_ADDED_BEFORE] = unit_file_content
++
++        unit_file_content = '''
++        [Service]
++        Type=oneshot
++        ExecStart=/bin/sleep 2
++        ExecStart=/bin/bash -c "echo foo >> {0}"
++        ExecStart=/bin/bash -c "echo bar >> {0}"
++        '''.format(self.output_file)
++        self.unit_files[UnitFileChange.COMMAND_ADDED_AFTER] = unit_file_content
++
++        unit_file_content = '''
++        [Service]
++        Type=oneshot
++        ExecStart=/bin/bash -c "echo baz >> {0}"
++        ExecStart=/bin/sleep 2
++        ExecStart=/bin/bash -c "echo foo >> {0}"
++        ExecStart=/bin/bash -c "echo bar >> {0}"
++        '''.format(self.output_file)
++        self.unit_files[UnitFileChange.COMMAND_INTERLEAVED] = unit_file_content
++
++        unit_file_content = '''
++        [Service]
++        Type=oneshot
++        ExecStart=/bin/bash -c "echo bar >> {0}"
++        ExecStart=/bin/bash -c "echo baz >> {0}"
++        '''.format(self.output_file)
++        self.unit_files[UnitFileChange.REMOVAL] = unit_file_content
++
++    def reload(self):
++        subprocess.check_call(['systemctl', 'daemon-reload'])
++
++    def write_unit_file(self, unit_file_change):
++        if not isinstance(unit_file_change, UnitFileChange):
++            raise ValueError('Unknown unit file change')
++
++        content = self.unit_files[unit_file_change]
++
++        with open(self.unitfile_path, 'w') as f:
++            f.write(content)
++
++        self.reload()
++
++    def check_output(self, expected_output):
++        try:
++            with open(self.output_file, 'r') as log:
++                output = log.read()
++        except IOError:
++            self.fail()
++
++        self.assertEqual(output, expected_output)
++
++    def setup_unit(self):
++        self.write_unit_file(UnitFileChange.NO_CHANGE)
++        subprocess.check_call(['systemctl', '--job-mode=replace', '--no-block', 'start', self.unit])
++
++    def test_no_change(self):
++        expected_output = 'foo\n'
++
++        self.setup_unit()
++        self.reload()
++        time.sleep(4)
++
++        self.check_output(expected_output)
++
++    def test_swapped(self):
++        expected_output = ''
++
++        self.setup_unit()
++        self.write_unit_file(UnitFileChange.LINES_SWAPPED)
++        self.reload()
++        time.sleep(4)
++
++        self.assertTrue(not os.path.exists(self.output_file))
++
++    def test_added_before(self):
++        expected_output = 'foo\n'
++
++        self.setup_unit()
++        self.write_unit_file(UnitFileChange.COMMAND_ADDED_BEFORE)
++        self.reload()
++        time.sleep(4)
++
++        self.check_output(expected_output)
++
++    def test_added_after(self):
++        expected_output = 'foo\nbar\n'
++
++        self.setup_unit()
++        self.write_unit_file(UnitFileChange.COMMAND_ADDED_AFTER)
++        self.reload()
++        time.sleep(4)
++
++        self.check_output(expected_output)
++
++    def test_interleaved(self):
++        expected_output = 'foo\nbar\n'
++
++        self.setup_unit()
++        self.write_unit_file(UnitFileChange.COMMAND_INTERLEAVED)
++        self.reload()
++        time.sleep(4)
++
++        self.check_output(expected_output)
++
++    def test_removal(self):
++        self.setup_unit()
++        self.write_unit_file(UnitFileChange.REMOVAL)
++        self.reload()
++        time.sleep(4)
++
++        self.assertTrue(not os.path.exists(self.output_file))
++
++    def tearDown(self):
++        for f in [self.output_file, self.unitfile_path]:
++            try:
++                os.remove(f)
++            except OSError:
++                # ignore error if log file doesn't exist
++                pass
++
++        self.reload()
++
++if __name__ == '__main__':
++    unittest.main()
diff --git a/SOURCES/0572-tests-in-RHEL-7-we-don-t-have-python3-by-default.patch b/SOURCES/0572-tests-in-RHEL-7-we-don-t-have-python3-by-default.patch
new file mode 100644
index 0000000..cfd15f3
--- /dev/null
+++ b/SOURCES/0572-tests-in-RHEL-7-we-don-t-have-python3-by-default.patch
@@ -0,0 +1,27 @@
+From 8a8fa94333650d3c34fcd42b696598cdc930a876 Mon Sep 17 00:00:00 2001
+From: Michal Sekletar <msekleta@redhat.com>
+Date: Mon, 2 Oct 2017 16:20:11 +0200
+Subject: [PATCH] tests: in RHEL-7 we don't have python3 by default
+
+Note that for running this test it is necessary to install backport of
+enum package from python-3.4 to python2.
+
+yum install -y python-enum34
+
+RHEL-only
+
+Related: #1404657, #1471230
+---
+ test/test-exec-deserialization.py | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/test/test-exec-deserialization.py b/test/test-exec-deserialization.py
+index b974b1c13..859778a7a 100755
+--- a/test/test-exec-deserialization.py
++++ b/test/test-exec-deserialization.py
+@@ -1,4 +1,4 @@
+-#!/usr/bin/python3
++#!/usr/bin/python
+ 
+ #
+ #  Copyright 2017 Michal Sekletar <msekleta@redhat.com>
diff --git a/SOURCES/0573-service-attempt-to-execute-next-main-command-only-fo.patch b/SOURCES/0573-service-attempt-to-execute-next-main-command-only-fo.patch
new file mode 100644
index 0000000..c922fe2
--- /dev/null
+++ b/SOURCES/0573-service-attempt-to-execute-next-main-command-only-fo.patch
@@ -0,0 +1,81 @@
+From 3bcdd03212c6f0a849a4fbdf3cc7cb99fb7327cb Mon Sep 17 00:00:00 2001
+From: Michal Sekletar <msekletar@users.noreply.github.com>
+Date: Fri, 25 Aug 2017 15:36:10 +0200
+Subject: [PATCH] service: attempt to execute next main command only for
+ oneshot services (#6619)
+
+This commit fixes crash described in
+https://github.com/systemd/systemd/issues/6533
+
+Multiple ExecStart lines are allowed only for oneshot services
+anyway so it doesn't make sense to call service_run_next_main() with
+services of type other than SERVICE_ONESHOT.
+
+Referring back to reproducer from the issue, previously we didn't observe
+this problem because s->main_command was reset after daemon-reload hence
+we never reached the assert statement in service_run_next_main().
+
+Fixes #6533
+
+(cherry picked from commit b58aeb70dbd1cab5908b003ef5187da1fc241839)
+
+Related: #1404657, #1471230
+---
+ src/core/service.c                |  1 +
+ test/test-exec-deserialization.py | 31 +++++++++++++++++++++++++++++++
+ 2 files changed, 32 insertions(+)
+
+diff --git a/src/core/service.c b/src/core/service.c
+index 9ad3a0eb0..ceed1cc2e 100644
+--- a/src/core/service.c
++++ b/src/core/service.c
+@@ -2612,6 +2612,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
+ 
+                 if (s->main_command &&
+                     s->main_command->command_next &&
++                    s->type == SERVICE_ONESHOT &&
+                     f == SERVICE_SUCCESS) {
+ 
+                         /* There is another command to *
+diff --git a/test/test-exec-deserialization.py b/test/test-exec-deserialization.py
+index 859778a7a..61623da99 100755
+--- a/test/test-exec-deserialization.py
++++ b/test/test-exec-deserialization.py
+@@ -178,6 +178,37 @@ class ExecutionResumeTest(unittest.TestCase):
+ 
+         self.assertTrue(not os.path.exists(self.output_file))
+ 
++    def test_issue_6533(self):
++        unit = "test-issue-6533.service"
++        unitfile_path = "/run/systemd/system/{}".format(unit)
++
++        content = '''
++        [Service]
++        ExecStart=/bin/sleep 5
++        '''
++
++        with open(unitfile_path, 'w') as f:
++            f.write(content)
++
++        self.reload()
++
++        subprocess.check_call(['systemctl', '--job-mode=replace', '--no-block', 'start', unit])
++        time.sleep(2)
++
++        content = '''
++        [Service]
++        ExecStart=/bin/sleep 5
++        ExecStart=/bin/true
++        '''
++
++        with open(unitfile_path, 'w') as f:
++            f.write(content)
++
++        self.reload()
++        time.sleep(5)
++
++        self.assertTrue(subprocess.call("journalctl -b _PID=1  | grep -q 'Freezing execution'", shell=True) != 0)
++
+     def tearDown(self):
+         for f in [self.output_file, self.unitfile_path]:
+             try:
diff --git a/SOURCES/0574-timedatectl-stop-using-xstrftime.patch b/SOURCES/0574-timedatectl-stop-using-xstrftime.patch
new file mode 100644
index 0000000..762bbc8
--- /dev/null
+++ b/SOURCES/0574-timedatectl-stop-using-xstrftime.patch
@@ -0,0 +1,155 @@
+From add02d6e5934100f023b45584d0227be90a297e8 Mon Sep 17 00:00:00 2001
+From: Jan Synacek <jsynacek@redhat.com>
+Date: Thu, 19 Oct 2017 09:53:56 +0200
+Subject: [PATCH] timedatectl: stop using xstrftime
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+When using strftime in arbitrary locales, we cannot really say how big the
+buffer should be. Let's make the buffer "large", which will work fine pretty
+much always, and just print n/a if the timestamp does not fit. strftime returns
+0 if the buffer is too small and a NUL-terminated string otherwise, so we
+can drop the size specifications in string formatting.
+
+$ export LANG=fa_IR.UTF-8
+$ date
+چهارشنبه ۱۸ اكتبر ۱۷، ساعت ۱۰:۵۴:۲۴ (+0330)
+$ timedatectl
+Assertion 'xstrftime: a[] must be big enough' failed at ../src/timedate/timedatectl.c:105, function print_status_info(). Aborting.
+
+now:
+
+$ timedatectl
+        Local time: چهارشنبه 2017-10-18 16:29:40 CEST
+    Universal time: چهارشنبه 2017-10-18 14:29:40 UTC
+          RTC time: چهارشنبه 2017-10-18 14:29:40
+…
+
+(cherry picked from commit 14ce0c25c28ba58e80084e28b4f23884199900e4)
+Resolves: #1503942
+---
+ src/shared/time-util.h     |  2 --
+ src/timedate/timedatectl.c | 49 ++++++++++++++++++++++++----------------------
+ 2 files changed, 26 insertions(+), 25 deletions(-)
+
+diff --git a/src/shared/time-util.h b/src/shared/time-util.h
+index f2789142f..32e90902a 100644
+--- a/src/shared/time-util.h
++++ b/src/shared/time-util.h
+@@ -108,5 +108,3 @@ int get_timezones(char ***l);
+ bool timezone_is_valid(const char *name);
+ 
+ clockid_t clock_boottime_or_monotonic(void);
+-
+-#define xstrftime(buf, fmt, tm) assert_se(strftime(buf, ELEMENTSOF(buf), fmt, tm) > 0)
+diff --git a/src/timedate/timedatectl.c b/src/timedate/timedatectl.c
+index 1accccb68..3e9b657bc 100644
+--- a/src/timedate/timedatectl.c
++++ b/src/timedate/timedatectl.c
+@@ -93,8 +93,8 @@ static const char *jump_str(int delta_minutes, char *s, size_t size) {
+ }
+ 
+ static void print_status_info(const StatusInfo *i) {
+-        char a[FORMAT_TIMESTAMP_MAX];
+-        char b[FORMAT_TIMESTAMP_MAX];
++        char a[LINE_MAX];
++        char b[LINE_MAX];
+         char s[32];
+         struct tm tm;
+         time_t sec;
+@@ -104,6 +104,7 @@ static void print_status_info(const StatusInfo *i) {
+         int dn = 0;
+         bool is_dstc = false, is_dstn = false;
+         int r;
++        size_t n;
+ 
+         assert(i);
+ 
+@@ -123,11 +124,11 @@ static void print_status_info(const StatusInfo *i) {
+                 fprintf(stderr, "Warning: Could not get time from timedated and not operating locally.\n\n");
+ 
+         if (have_time) {
+-                xstrftime(a, "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&sec, &tm));
+-                printf("      Local time: %.*s\n", (int) sizeof(a), a);
++                n = strftime(a, sizeof a, "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&sec, &tm));
++                printf("      Local time: %s\n", n > 0 ? a : "n/a");
+ 
+-                xstrftime(a, "%a %Y-%m-%d %H:%M:%S UTC", gmtime_r(&sec, &tm));
+-                printf("  Universal time: %.*s\n", (int) sizeof(a), a);
++                n = strftime(a, sizeof a, "%a %Y-%m-%d %H:%M:%S UTC", gmtime_r(&sec, &tm));
++                printf("  Universal time: %s\n", n > 0 ? a : "n/a");
+         } else {
+                 printf("      Local time: %s\n", "n/a");
+                 printf("  Universal time: %s\n", "n/a");
+@@ -137,24 +138,26 @@ static void print_status_info(const StatusInfo *i) {
+                 time_t rtc_sec;
+ 
+                 rtc_sec = (time_t)(i->rtc_time / USEC_PER_SEC);
+-                xstrftime(a, "%a %Y-%m-%d %H:%M:%S", gmtime_r(&rtc_sec, &tm));
+-                printf("        RTC time: %.*s\n", (int) sizeof(a), a);
++                n = strftime(a, sizeof a, "%a %Y-%m-%d %H:%M:%S", gmtime_r(&rtc_sec, &tm));
++                printf("        RTC time: %s\n", n > 0 ? a : "n/a");
+         } else
+                 printf("        RTC time: %s\n", "n/a");
+ 
+         if (have_time)
+-                xstrftime(a, "%Z, %z", localtime_r(&sec, &tm));
++                n = strftime(a, sizeof a, "%Z, %z", localtime_r(&sec, &tm));
+ 
+-        printf("       Time zone: %s (%.*s)\n"
++        printf("       Time zone: %s (%s)\n"
+                "     NTP enabled: %s\n"
+                "NTP synchronized: %s\n"
+                " RTC in local TZ: %s\n",
+-               strna(i->timezone), (int) sizeof(a), have_time ? a : "n/a",
++               strna(i->timezone), have_time && n > 0 ? a : "n/a",
+                i->ntp_capable ? yes_no(i->ntp_enabled) : "n/a",
+                yes_no(i->ntp_synced),
+                yes_no(i->rtc_local));
+ 
+         if (have_time) {
++                size_t m;
++
+                 r = time_get_dst(sec, "/etc/localtime",
+                                  &tc, &zc, &is_dstc,
+                                  &tn, &dn, &zn, &is_dstn);
+@@ -164,26 +167,26 @@ static void print_status_info(const StatusInfo *i) {
+                         printf("      DST active: %s\n", yes_no(is_dstc));
+ 
+                         t = tc - 1;
+-                        xstrftime(a, "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&t, &tm));
++                        n = strftime(a, sizeof a, "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&t, &tm));
+ 
+-                        xstrftime(b, "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&tc, &tm));
++                        m = strftime(b, sizeof b, "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&tc, &tm));
+                         printf(" Last DST change: DST %s at\n"
+-                               "                  %.*s\n"
+-                               "                  %.*s\n",
++                               "                  %s\n"
++                               "                  %s\n",
+                                is_dstc ? "began" : "ended",
+-                               (int) sizeof(a), a,
+-                               (int) sizeof(b), b);
++                               n > 0 ? a : "n/a",
++                               m > 0 ? b : "n/a");
+ 
+                         t = tn - 1;
+-                        xstrftime(a, "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&t, &tm));
+-                        xstrftime(b, "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&tn, &tm));
++                        n = strftime(a, sizeof a, "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&t, &tm));
++                        m = strftime(b, sizeof b, "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&tn, &tm));
+                         printf(" Next DST change: DST %s (the clock jumps %s) at\n"
+-                               "                  %.*s\n"
+-                               "                  %.*s\n",
++                               "                  %s\n"
++                               "                  %s\n",
+                                is_dstn ? "begins" : "ends",
+                                jump_str(dn, s, sizeof(s)),
+-                               (int) sizeof(a), a,
+-                               (int) sizeof(b), b);
++                               n > 0 ? a : "n/a",
++                               m > 0 ? b : "n/a");
+                 }
+         } else
+                 printf("      DST active: %s\n", yes_no(is_dstc));
diff --git a/SOURCES/0575-Add-support-to-read-lz4-compressed-journals.patch b/SOURCES/0575-Add-support-to-read-lz4-compressed-journals.patch
new file mode 100644
index 0000000..8f6516a
--- /dev/null
+++ b/SOURCES/0575-Add-support-to-read-lz4-compressed-journals.patch
@@ -0,0 +1,120 @@
+From bae0c1d66cba62b19d39a3a79cb76fbd5d4ef7e7 Mon Sep 17 00:00:00 2001
+From: Jan Rybar <jrybar@redhat.com>
+Date: Thu, 17 Aug 2017 14:38:11 +0200
+Subject: [PATCH] Add support to read lz4 compressed journals
+
+Functionality already in codebase, but deactivated in RHEL
+Changed calling of LZ4 functions due to deprecation of the originals.
+Fixed typecasting of max_bytes to size_t in debuglog()
+
+Resolves: rhbz#1431687
+
+changes to .spec file:
+
+@@ -552,6 +553,7 @@ BuildRequires:  libblkid-devel
+ BuildRequires:  xz-devel
+ BuildRequires:  zlib-devel
+ BuildRequires:  bzip2-devel
++BuildRequires:  lz4-devel
+ BuildRequires:  libidn-devel
+ BuildRequires:  libcurl-devel
+ BuildRequires:  kmod-devel
+@@ -742,6 +744,7 @@ CONFIGURE_OPTS=(
+     --enable-compat-libs
+     --disable-sysusers
+     --disable-ldconfig
++    --enable-lz4
+ %ifarch s390 s390x ppc %{power64} aarch64
+     --disable-lto
+ %endif
+---
+ src/journal/compress.c     | 11 ++++++++---
+ src/journal/compress.h     | 11 -----------
+ src/journal/journal-file.c |  5 ++---
+ 3 files changed, 10 insertions(+), 17 deletions(-)
+
+diff --git a/src/journal/compress.c b/src/journal/compress.c
+index 4fb09f596..3baf9e4ad 100644
+--- a/src/journal/compress.c
++++ b/src/journal/compress.c
+@@ -98,7 +98,12 @@ int compress_blob_lz4(const void *src, uint64_t src_size, void *dst, size_t *dst
+         if (src_size < 9)
+                 return -ENOBUFS;
+ 
+-        r = LZ4_compress_limitedOutput(src, dst + 8, src_size, src_size - 8 - 1);
++#if LZ4_VERSION_NUMBER >= 10700
++        r = LZ4_compress_default(src, (char*)dst + 8, src_size, src_size - 8 - 1);
++#else
++        r = LZ4_compress_limitedOutput(src, (char*)dst + 8, src_size, src_size - 8 - 1);
++#endif
++
+         if (r <= 0)
+                 return -ENOBUFS;
+ 
+@@ -458,7 +463,7 @@ int compress_stream_lz4(int fdf, int fdt, off_t max_bytes) {
+ 
+                 total_in += n;
+ 
+-                r = LZ4_compress_continue(&lz4_data, buf, out, n);
++                r = LZ4_compress_fast_continue(&lz4_data, buf, out, n, LZ4_COMPRESSBOUND(LZ4_BUFSIZE), 0);
+                 if (r == 0) {
+                         log_error("LZ4 compression failed.");
+                         return -EBADMSG;
+@@ -634,7 +639,7 @@ int decompress_stream_lz4(int fdf, int fdt, off_t max_bytes) {
+                 total_out += r;
+ 
+                 if (max_bytes != -1 && total_out > (size_t) max_bytes) {
+-                        log_debug("Decompressed stream longer than %zd bytes", max_bytes);
++                        log_debug("Decompressed stream longer than %zd bytes", (size_t) max_bytes);
+                         return -EFBIG;
+                 }
+ 
+diff --git a/src/journal/compress.h b/src/journal/compress.h
+index 136dda6d3..0f62a58d6 100644
+--- a/src/journal/compress.h
++++ b/src/journal/compress.h
+@@ -35,15 +35,9 @@ int compress_blob_lz4(const void *src, uint64_t src_size, void *dst, size_t *dst
+ 
+ static inline int compress_blob(const void *src, uint64_t src_size, void *dst, size_t *dst_size) {
+         int r;
+-#ifdef HAVE_LZ4
+-        r = compress_blob_lz4(src, src_size, dst, dst_size);
+-        if (r == 0)
+-                return OBJECT_COMPRESSED_LZ4;
+-#else
+         r = compress_blob_xz(src, src_size, dst, dst_size);
+         if (r == 0)
+                 return OBJECT_COMPRESSED_XZ;
+-#endif
+         return r;
+ }
+ 
+@@ -75,12 +69,7 @@ int compress_stream_lz4(int fdf, int fdt, off_t max_bytes);
+ int decompress_stream_xz(int fdf, int fdt, off_t max_size);
+ int decompress_stream_lz4(int fdf, int fdt, off_t max_size);
+ 
+-#ifdef HAVE_LZ4
+-#  define compress_stream compress_stream_lz4
+-#  define COMPRESSED_EXT ".lz4"
+-#else
+ #  define compress_stream compress_stream_xz
+ #  define COMPRESSED_EXT ".xz"
+-#endif
+ 
+ int decompress_stream(const char *filename, int fdf, int fdt, off_t max_bytes);
+diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c
+index 0fd59ec07..ebc8e6230 100644
+--- a/src/journal/journal-file.c
++++ b/src/journal/journal-file.c
+@@ -2615,9 +2615,8 @@ int journal_file_open(
+         f->flags = flags;
+         f->prot = prot_from_flags(flags);
+         f->writable = (flags & O_ACCMODE) != O_RDONLY;
+-#if defined(HAVE_LZ4)
+-        f->compress_lz4 = compress;
+-#elif defined(HAVE_XZ)
++
++#if defined(HAVE_XZ)
+         f->compress_xz = compress;
+ #endif
+ #ifdef HAVE_GCRYPT
diff --git a/SOURCES/0576-journald-never-block-when-sending-messages-on-NOTIFY.patch b/SOURCES/0576-journald-never-block-when-sending-messages-on-NOTIFY.patch
new file mode 100644
index 0000000..8c40d40
--- /dev/null
+++ b/SOURCES/0576-journald-never-block-when-sending-messages-on-NOTIFY.patch
@@ -0,0 +1,449 @@
+From c67c643418b1df5b5705b3a72eba1e6755830dc5 Mon Sep 17 00:00:00 2001
+From: Jan Synacek <jsynacek@redhat.com>
+Date: Tue, 21 Nov 2017 12:46:28 +0100
+Subject: [PATCH] journald: never block when sending messages on NOTIFY_SOCKET
+ socket
+
+Otherwise we might run into deadlocks, when journald blocks on the
+notify socket on PID 1, and PID 1 blocks on IPC to dbus-daemon and
+dbus-daemon blocks on logging to journald. Break this cycle by making
+sure that journald never ever blocks on PID 1.
+
+Note that this change disables support for event loop watchdog support,
+as these messages are sent in blocking style by sd-event. That should
+not be a big loss though, as people reported frequent problems with the
+watchdog hitting journald on excessively slow IO.
+
+Fixes: #1505.
+(cherry-picked from commit e22aa3d3284709234f086ebebc13a905a295b7a7)
+
+Resolves: #1511565
+---
+ src/journal/journald-server.c     | 130 +++++++++++++++++++++++++++++++++++++-
+ src/journal/journald-server.h     |  13 ++--
+ src/journal/journald-stream.c     |  68 ++++++++++++++++++--
+ src/journal/journald-stream.h     |   3 +
+ src/journal/journald.c            |   8 ---
+ units/systemd-journald.service.in |   1 -
+ 6 files changed, 201 insertions(+), 22 deletions(-)
+
+diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c
+index daeecd519..a810829b2 100644
+--- a/src/journal/journald-server.c
++++ b/src/journal/journald-server.c
+@@ -67,6 +67,8 @@
+ 
+ #define RECHECK_AVAILABLE_SPACE_USEC (30*USEC_PER_SEC)
+ 
++#define NOTIFY_SNDBUF_SIZE (8*1024*1024)
++
+ /* Pick a good default that is likely to fit into AF_UNIX and AF_INET SOCK_DGRAM datagrams, and even leaves some room
+ + * for a bit of additional metadata. */
+ #define DEFAULT_LINE_MAX (48*1024)
+@@ -1556,6 +1558,126 @@ static int server_open_hostname(Server *s) {
+         return 0;
+ }
+ 
++static int dispatch_notify_event(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
++        Server *s = userdata;
++        int r;
++
++        assert(s);
++        assert(s->notify_event_source == es);
++        assert(s->notify_fd == fd);
++
++        if (revents != EPOLLOUT) {
++                log_error("Invalid events on notify file descriptor.");
++                return -EINVAL;
++        }
++
++        /* The $NOTIFY_SOCKET is writable again, now send exactly one
++         * message on it. Either it's the initial READY=1 event or an
++         * stdout stream event. If there's nothing to write anymore,
++         * turn our event source off. The next time there's something
++         * to send it will be turned on again. */
++
++        if (!s->sent_notify_ready) {
++                static const char p[] =
++                        "READY=1\n"
++                        "STATUS=Processing requests...";
++                ssize_t l;
++
++                l = send(s->notify_fd, p, strlen(p), MSG_DONTWAIT);
++                if (l < 0) {
++                        if (errno == EAGAIN)
++                                return 0;
++
++                        return log_error_errno(errno, "Failed to send READY=1 notification message: %m");
++                }
++
++                s->sent_notify_ready = true;
++                log_debug("Sent READY=1 notification.");
++
++        } else if (s->stdout_streams_notify_queue)
++                /* Dispatch one stream notification event */
++                stdout_stream_send_notify(s->stdout_streams_notify_queue);
++
++        /* Leave us enabled if there's still more to to do. */
++        if (s->stdout_streams_notify_queue)
++                return 0;
++
++        /* There was nothing to do anymore, let's turn ourselves off. */
++        r = sd_event_source_set_enabled(es, SD_EVENT_OFF);
++        if (r < 0)
++                return log_error_errno(r, "Failed to turn off notify event source: %m");
++
++        return 0;
++}
++
++static int server_connect_notify(Server *s) {
++        union sockaddr_union sa = {
++                .un.sun_family = AF_UNIX,
++        };
++        const char *e;
++        int r;
++
++        assert(s);
++        assert(s->notify_fd < 0);
++        assert(!s->notify_event_source);
++
++        /*
++          So here's the problem: we'd like to send notification
++          messages to PID 1, but we cannot do that via sd_notify(),
++          since that's synchronous, and we might end up blocking on
++          it. Specifically: given that PID 1 might block on
++          dbus-daemon during IPC, and dbus-daemon is logging to us,
++          and might hence block on us, we might end up in a deadlock
++          if we block on sending PID 1 notification messages -- by
++          generating a full blocking circle. To avoid this, let's
++          create a non-blocking socket, and connect it to the
++          notification socket, and then wait for POLLOUT before we
++          send anything. This should efficiently avoid any deadlocks,
++          as we'll never block on PID 1, hence PID 1 can safely block
++          on dbus-daemon which can safely block on us again.
++
++          Don't think that this issue is real? It is, see:
++          https://github.com/systemd/systemd/issues/1505
++        */
++
++        e = getenv("NOTIFY_SOCKET");
++        if (!e)
++                return 0;
++
++        if ((e[0] != '@' && e[0] != '/') || e[1] == 0) {
++                log_error("NOTIFY_SOCKET set to an invalid value: %s", e);
++                return -EINVAL;
++        }
++
++        if (strlen(e) > sizeof(sa.un.sun_path)) {
++                log_error("NOTIFY_SOCKET path too long: %s", e);
++                return -EINVAL;
++        }
++
++        s->notify_fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
++        if (s->notify_fd < 0)
++                return log_error_errno(errno, "Failed to create notify socket: %m");
++
++        (void) fd_inc_sndbuf(s->notify_fd, NOTIFY_SNDBUF_SIZE);
++
++        strncpy(sa.un.sun_path, e, sizeof(sa.un.sun_path));
++        if (sa.un.sun_path[0] == '@')
++                sa.un.sun_path[0] = 0;
++
++        r = connect(s->notify_fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(e));
++        if (r < 0)
++                return log_error_errno(errno, "Failed to connect to notify socket: %m");
++
++        r = sd_event_add_io(s->event, &s->notify_event_source, s->notify_fd, EPOLLOUT, dispatch_notify_event, s);
++        if (r < 0)
++                return log_error_errno(r, "Failed to watch notification socket: %m");
++
++        /* This should fire pretty soon, which we'll use to send the
++         * READY=1 event. */
++
++        return 0;
++}
++
+ int server_init(Server *s) {
+         _cleanup_fdset_free_ FDSet *fds = NULL;
+         int n, r, fd;
+@@ -1563,7 +1685,7 @@ int server_init(Server *s) {
+         assert(s);
+ 
+         zero(*s);
+-        s->syslog_fd = s->native_fd = s->stdout_fd = s->dev_kmsg_fd = s->audit_fd = s->hostname_fd = -1;
++        s->syslog_fd = s->native_fd = s->stdout_fd = s->dev_kmsg_fd = s->audit_fd = s->hostname_fd = s->notify_fd = -1;
+         s->compress = true;
+         s->seal = true;
+ 
+@@ -1611,8 +1733,6 @@ int server_init(Server *s) {
+         if (r < 0)
+                 return log_error_errno(r, "Failed to create event loop: %m");
+ 
+-        sd_event_set_watchdog(s->event, true);
+-
+         n = sd_listen_fds(true);
+         if (n < 0)
+                 return log_error_errno(n, "Failed to read listening file descriptors from environment: %m");
+@@ -1718,6 +1838,8 @@ int server_init(Server *s) {
+         server_cache_boot_id(s);
+         server_cache_machine_id(s);
+ 
++        (void) server_connect_notify(s);
++
+         r = system_journal_open(s, false);
+         if (r < 0)
+                 return r;
+@@ -1770,6 +1892,7 @@ void server_done(Server *s) {
+         sd_event_source_unref(s->sigterm_event_source);
+         sd_event_source_unref(s->sigint_event_source);
+         sd_event_source_unref(s->hostname_event_source);
++        sd_event_source_unref(s->notify_event_source);
+         sd_event_unref(s->event);
+ 
+         safe_close(s->syslog_fd);
+@@ -1778,6 +1901,7 @@ void server_done(Server *s) {
+         safe_close(s->dev_kmsg_fd);
+         safe_close(s->audit_fd);
+         safe_close(s->hostname_fd);
++        safe_close(s->notify_fd);
+ 
+         if (s->rate_limit)
+                 journal_rate_limit_free(s->rate_limit);
+diff --git a/src/journal/journald-server.h b/src/journal/journald-server.h
+index b29410778..e59ff35e2 100644
+--- a/src/journal/journald-server.h
++++ b/src/journal/journald-server.h
+@@ -27,12 +27,15 @@
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ 
++typedef struct Server Server;
++
+ #include "sd-event.h"
+ #include "journal-file.h"
+ #include "hashmap.h"
+ #include "util.h"
+ #include "audit.h"
+ #include "journald-rate-limit.h"
++#include "journald-stream.h"
+ #include "list.h"
+ 
+ typedef enum Storage {
+@@ -52,15 +55,14 @@ typedef enum SplitMode {
+         _SPLIT_INVALID = -1
+ } SplitMode;
+ 
+-typedef struct StdoutStream StdoutStream;
+-
+-typedef struct Server {
++struct Server {
+         int syslog_fd;
+         int native_fd;
+         int stdout_fd;
+         int dev_kmsg_fd;
+         int audit_fd;
+         int hostname_fd;
++        int notify_fd;
+ 
+         sd_event *event;
+ 
+@@ -75,6 +77,7 @@ typedef struct Server {
+         sd_event_source *sigterm_event_source;
+         sd_event_source *sigint_event_source;
+         sd_event_source *hostname_event_source;
++        sd_event_source *notify_event_source;
+ 
+         JournalFile *runtime_journal;
+         JournalFile *system_journal;
+@@ -114,6 +117,7 @@ typedef struct Server {
+         usec_t oldest_file_usec;
+ 
+         LIST_HEAD(StdoutStream, stdout_streams);
++        LIST_HEAD(StdoutStream, stdout_streams_notify_queue);
+         unsigned n_stdout_streams;
+ 
+         char *tty_path;
+@@ -135,6 +139,7 @@ typedef struct Server {
+ 
+         struct udev *udev;
+ 
++        bool sent_notify_ready;
+         bool sync_scheduled;
+ 
+         char machine_id_field[sizeof("_MACHINE_ID=") + 32];
+@@ -145,7 +150,7 @@ typedef struct Server {
+         char *cgroup_root;
+ 
+         size_t line_max;
+-} Server;
++};
+ 
+ #define N_IOVEC_META_FIELDS 20
+ #define N_IOVEC_KERNEL_FIELDS 64
+diff --git a/src/journal/journald-stream.c b/src/journal/journald-stream.c
+index 4d6b7ad18..9118d1a31 100644
+--- a/src/journal/journald-stream.c
++++ b/src/journal/journald-stream.c
+@@ -80,6 +80,7 @@ struct StdoutStream {
+         bool forward_to_console:1;
+ 
+         bool fdstore:1;
++        bool in_notify_queue:1;
+ 
+         char *buffer;
+         size_t length;
+@@ -90,6 +91,7 @@ struct StdoutStream {
+         char *state_file;
+ 
+         LIST_FIELDS(StdoutStream, stdout_stream);
++        LIST_FIELDS(StdoutStream, stdout_stream_notify_queue);
+ 
+         char id_field[sizeof("_STREAM_ID=")-1 + SD_ID128_STRING_MAX];
+ };
+@@ -102,6 +104,9 @@ void stdout_stream_free(StdoutStream *s) {
+                 assert(s->server->n_stdout_streams > 0);
+                 s->server->n_stdout_streams --;
+                 LIST_REMOVE(stdout_stream, s->server->stdout_streams, s);
++
++                if (s->in_notify_queue)
++                        LIST_REMOVE(stdout_stream_notify_queue, s->server->stdout_streams_notify_queue, s);
+         }
+ 
+         if (s->event_source) {
+@@ -126,7 +131,7 @@ static void stdout_stream_destroy(StdoutStream *s) {
+                 return;
+ 
+         if (s->state_file)
+-                unlink(s->state_file);
++                (void) unlink(s->state_file);
+ 
+         stdout_stream_free(s);
+ }
+@@ -210,11 +215,15 @@ static int stdout_stream_save(StdoutStream *s) {
+         free(temp_path);
+         temp_path = NULL;
+ 
+-        /* Store the connection fd in PID 1, so that we get it passed
+-         * in again on next start */
+-        if (!s->fdstore) {
+-                sd_pid_notify_with_fds(0, false, "FDSTORE=1", &s->fd, 1);
+-                s->fdstore = true;
++        if (!s->fdstore && !s->in_notify_queue) {
++                LIST_PREPEND(stdout_stream_notify_queue, s->server->stdout_streams_notify_queue, s);
++                s->in_notify_queue = true;
++
++                if (s->server->notify_event_source) {
++                        r = sd_event_source_set_enabled(s->server->notify_event_source, SD_EVENT_ON);
++                        if (r < 0)
++                                log_warning_errno(r, "Failed to enable notify event source: %m");
++                }
+         }
+ 
+ finish:
+@@ -801,3 +810,50 @@ int server_open_stdout_socket(Server *s, FDSet *fds) {
+ 
+         return 0;
+ }
++
++void stdout_stream_send_notify(StdoutStream *s) {
++        struct iovec iovec = {
++                .iov_base = (char*) "FDSTORE=1",
++                .iov_len = strlen("FDSTORE=1"),
++        };
++        struct msghdr msghdr = {
++                .msg_iov = &iovec,
++                .msg_iovlen = 1,
++        };
++        struct cmsghdr *cmsg;
++        ssize_t l;
++
++        assert(s);
++        assert(!s->fdstore);
++        assert(s->in_notify_queue);
++        assert(s->server);
++        assert(s->server->notify_fd >= 0);
++
++        /* Store the connection fd in PID 1, so that we get it passed
++         * in again on next start */
++
++        msghdr.msg_controllen = CMSG_SPACE(sizeof(int));
++        msghdr.msg_control = alloca0(msghdr.msg_controllen);
++
++        cmsg = CMSG_FIRSTHDR(&msghdr);
++        cmsg->cmsg_level = SOL_SOCKET;
++        cmsg->cmsg_type = SCM_RIGHTS;
++        cmsg->cmsg_len = CMSG_LEN(sizeof(int));
++
++        memcpy(CMSG_DATA(cmsg), &s->fd, sizeof(int));
++
++        l = sendmsg(s->server->notify_fd, &msghdr, MSG_DONTWAIT|MSG_NOSIGNAL);
++        if (l < 0) {
++                if (errno == EAGAIN)
++                        return;
++
++                log_error_errno(errno, "Failed to send stream file descriptor to service manager: %m");
++        } else {
++                log_debug("Successfully sent stream file descriptor to service manager.");
++                s->fdstore = 1;
++        }
++
++        LIST_REMOVE(stdout_stream_notify_queue, s->server->stdout_streams_notify_queue, s);
++        s->in_notify_queue = false;
++
++}
+diff --git a/src/journal/journald-stream.h b/src/journal/journald-stream.h
+index 94bf955d7..fd8c94fb6 100644
+--- a/src/journal/journald-stream.h
++++ b/src/journal/journald-stream.h
+@@ -21,9 +21,12 @@
+   along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ ***/
+ 
++typedef struct StdoutStream StdoutStream;
++
+ #include "fdset.h"
+ #include "journald-server.h"
+ 
+ int server_open_stdout_socket(Server *s, FDSet *fds);
+ 
+ void stdout_stream_free(StdoutStream *s);
++void stdout_stream_send_notify(StdoutStream *s);
+diff --git a/src/journal/journald.c b/src/journal/journald.c
+index 15bbcbe3d..b7ba2b6ec 100644
+--- a/src/journal/journald.c
++++ b/src/journal/journald.c
+@@ -64,10 +64,6 @@ int main(int argc, char *argv[]) {
+         log_debug("systemd-journald running as pid "PID_FMT, getpid());
+         server_driver_message(&server, SD_MESSAGE_JOURNAL_START, "Journal started");
+ 
+-        sd_notify(false,
+-                  "READY=1\n"
+-                  "STATUS=Processing requests...");
+-
+         for (;;) {
+                 usec_t t = USEC_INFINITY, n;
+ 
+@@ -120,10 +116,6 @@ int main(int argc, char *argv[]) {
+         server_driver_message(&server, SD_MESSAGE_JOURNAL_STOP, "Journal stopped");
+ 
+ finish:
+-        sd_notify(false,
+-                  "STOPPING=1\n"
+-                  "STATUS=Shutting down...");
+-
+         server_done(&server);
+ 
+         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+diff --git a/units/systemd-journald.service.in b/units/systemd-journald.service.in
+index 0d1ea61fe..c94c0bfba 100644
+--- a/units/systemd-journald.service.in
++++ b/units/systemd-journald.service.in
+@@ -22,7 +22,6 @@ RestartSec=0
+ StandardOutput=null
+ FileDescriptorStoreMax=4224
+ CapabilityBoundingSet=CAP_SYS_ADMIN CAP_DAC_OVERRIDE CAP_SYS_PTRACE CAP_SYSLOG CAP_AUDIT_CONTROL CAP_AUDIT_READ CAP_CHOWN CAP_DAC_READ_SEARCH CAP_FOWNER CAP_SETUID CAP_SETGID CAP_MAC_OVERRIDE
+-WatchdogSec=3min
+ 
+ # Increase the default a bit in order to allow many simultaneous
+ # services being run since we keep one fd open per service. Also, when
diff --git a/SOURCES/0577-journal-restore-watchdog-support.patch b/SOURCES/0577-journal-restore-watchdog-support.patch
new file mode 100644
index 0000000..0fa5760
--- /dev/null
+++ b/SOURCES/0577-journal-restore-watchdog-support.patch
@@ -0,0 +1,184 @@
+From 652a44f9a9948a023fd7b26f72044fea0b13c25d Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Tue, 3 Nov 2015 12:28:19 +0100
+Subject: [PATCH] journal: restore watchdog support
+
+(cherry picked from commit 119e9655dc36f18ed74f9a256d5c693b5aeb43ab)
+
+Conflicts:
+	src/journal/journald-server.h
+	units/systemd-journald.service.in
+
+Related: #1511565
+---
+ src/journal/journald-server.c     | 62 +++++++++++++++++++++++++++++++++++----
+ src/journal/journald-server.h     | 13 ++++----
+ units/systemd-journald.service.in |  1 +
+ 3 files changed, 66 insertions(+), 10 deletions(-)
+
+diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c
+index a810829b2..6e7568b60 100644
+--- a/src/journal/journald-server.c
++++ b/src/journal/journald-server.c
+@@ -1572,10 +1572,10 @@ static int dispatch_notify_event(sd_event_source *es, int fd, uint32_t revents,
+         }
+ 
+         /* The $NOTIFY_SOCKET is writable again, now send exactly one
+-         * message on it. Either it's the initial READY=1 event or an
+-         * stdout stream event. If there's nothing to write anymore,
+-         * turn our event source off. The next time there's something
+-         * to send it will be turned on again. */
++         * message on it. Either it's the wtachdog event, the initial
++         * READY=1 event or an stdout stream event. If there's nothing
++         * to write anymore, turn our event source off. The next time
++         * there's something to send it will be turned on again. */
+ 
+         if (!s->sent_notify_ready) {
+                 static const char p[] =
+@@ -1594,12 +1594,30 @@ static int dispatch_notify_event(sd_event_source *es, int fd, uint32_t revents,
+                 s->sent_notify_ready = true;
+                 log_debug("Sent READY=1 notification.");
+ 
++        } else if (s->send_watchdog) {
++
++                static const char p[] =
++                        "WATCHDOG=1";
++
++                ssize_t l;
++
++                l = send(s->notify_fd, p, strlen(p), MSG_DONTWAIT);
++                if (l < 0) {
++                        if (errno == EAGAIN)
++                                return 0;
++
++                        return log_error_errno(errno, "Failed to send WATCHDOG=1 notification message: %m");
++                }
++
++                s->send_watchdog = false;
++                log_debug("Sent WATCHDOG=1 notification.");
++
+         } else if (s->stdout_streams_notify_queue)
+                 /* Dispatch one stream notification event */
+                 stdout_stream_send_notify(s->stdout_streams_notify_queue);
+ 
+         /* Leave us enabled if there's still more to to do. */
+-        if (s->stdout_streams_notify_queue)
++        if (s->send_watchdog || s->stdout_streams_notify_queue)
+                 return 0;
+ 
+         /* There was nothing to do anymore, let's turn ourselves off. */
+@@ -1610,6 +1628,29 @@ static int dispatch_notify_event(sd_event_source *es, int fd, uint32_t revents,
+         return 0;
+ }
+ 
++static int dispatch_watchdog(sd_event_source *es, uint64_t usec, void *userdata) {
++        Server *s = userdata;
++        int r;
++
++        assert(s);
++
++        s->send_watchdog = true;
++
++        r = sd_event_source_set_enabled(s->notify_event_source, SD_EVENT_ON);
++        if (r < 0)
++                log_warning_errno(r, "Failed to turn on notify event source: %m");
++
++        r = sd_event_source_set_time(s->watchdog_event_source, usec + s->watchdog_usec / 2);
++        if (r < 0)
++                return log_error_errno(r, "Failed to restart watchdog event source: %m");
++
++        r = sd_event_source_set_enabled(s->watchdog_event_source, SD_EVENT_ON);
++        if (r < 0)
++                return log_error_errno(r, "Failed to enable watchdog event source: %m");
++
++        return 0;
++}
++
+ static int server_connect_notify(Server *s) {
+         union sockaddr_union sa = {
+                 .un.sun_family = AF_UNIX,
+@@ -1672,6 +1713,14 @@ static int server_connect_notify(Server *s) {
+         if (r < 0)
+                 return log_error_errno(r, "Failed to watch notification socket: %m");
+ 
++        if (sd_watchdog_enabled(false, &s->watchdog_usec) > 0) {
++                s->send_watchdog = true;
++
++                r = sd_event_add_time(s->event, &s->watchdog_event_source, CLOCK_MONOTONIC, now(CLOCK_MONOTONIC) + s->watchdog_usec/2, s->watchdog_usec*3/4, dispatch_watchdog, s);
++                if (r < 0)
++                        return log_error_errno(r, "Failed to add watchdog time event: %m");
++        }
++
+         /* This should fire pretty soon, which we'll use to send the
+          * READY=1 event. */
+ 
+@@ -1689,6 +1738,8 @@ int server_init(Server *s) {
+         s->compress = true;
+         s->seal = true;
+ 
++        s->watchdog_usec = USEC_INFINITY;
++
+         s->sync_interval_usec = DEFAULT_SYNC_INTERVAL_USEC;
+         s->sync_scheduled = false;
+ 
+@@ -1893,6 +1944,7 @@ void server_done(Server *s) {
+         sd_event_source_unref(s->sigint_event_source);
+         sd_event_source_unref(s->hostname_event_source);
+         sd_event_source_unref(s->notify_event_source);
++        sd_event_source_unref(s->watchdog_event_source);
+         sd_event_unref(s->event);
+ 
+         safe_close(s->syslog_fd);
+diff --git a/src/journal/journald-server.h b/src/journal/journald-server.h
+index e59ff35e2..f046fde83 100644
+--- a/src/journal/journald-server.h
++++ b/src/journal/journald-server.h
+@@ -78,6 +78,7 @@ struct Server {
+         sd_event_source *sigint_event_source;
+         sd_event_source *hostname_event_source;
+         sd_event_source *notify_event_source;
++        sd_event_source *watchdog_event_source;
+ 
+         JournalFile *runtime_journal;
+         JournalFile *system_journal;
+@@ -133,14 +134,14 @@ struct Server {
+ 
+         MMapCache *mmap;
+ 
+-        bool dev_kmsg_readable;
++        struct udev *udev;
+ 
+         uint64_t *kernel_seqnum;
++        bool dev_kmsg_readable:1;
+ 
+-        struct udev *udev;
+-
+-        bool sent_notify_ready;
+-        bool sync_scheduled;
++        bool send_watchdog:1;
++        bool sent_notify_ready:1;
++        bool sync_scheduled:1;
+ 
+         char machine_id_field[sizeof("_MACHINE_ID=") + 32];
+         char boot_id_field[sizeof("_BOOT_ID=") + 32];
+@@ -149,6 +150,8 @@ struct Server {
+         /* Cached cgroup root, so that we don't have to query that all the time */
+         char *cgroup_root;
+ 
++        usec_t watchdog_usec;
++
+         size_t line_max;
+ };
+ 
+diff --git a/units/systemd-journald.service.in b/units/systemd-journald.service.in
+index c94c0bfba..0d1ea61fe 100644
+--- a/units/systemd-journald.service.in
++++ b/units/systemd-journald.service.in
+@@ -22,6 +22,7 @@ RestartSec=0
+ StandardOutput=null
+ FileDescriptorStoreMax=4224
+ CapabilityBoundingSet=CAP_SYS_ADMIN CAP_DAC_OVERRIDE CAP_SYS_PTRACE CAP_SYSLOG CAP_AUDIT_CONTROL CAP_AUDIT_READ CAP_CHOWN CAP_DAC_READ_SEARCH CAP_FOWNER CAP_SETUID CAP_SETGID CAP_MAC_OVERRIDE
++WatchdogSec=3min
+ 
+ # Increase the default a bit in order to allow many simultaneous
+ # services being run since we keep one fd open per service. Also, when
diff --git a/SOURCES/0578-cgroup-resource-property-setting-ignored-if-einval.patch b/SOURCES/0578-cgroup-resource-property-setting-ignored-if-einval.patch
new file mode 100644
index 0000000..38d71eb
--- /dev/null
+++ b/SOURCES/0578-cgroup-resource-property-setting-ignored-if-einval.patch
@@ -0,0 +1,729 @@
+From cbeadf0e57c0d240977d574a8b5726b441f519a9 Mon Sep 17 00:00:00 2001
+From: Jan Rybar <jrybar@redhat.com>
+Date: Fri, 22 Sep 2017 11:53:50 +0200
+Subject: [PATCH] cgroup resource property setting ignored if einval
+
+Resolves: rhbz#1302305
+Cherry-picked from: d53d94743c5e5e3a4a6, 3fdf9ad
+---
+ man/systemd.resource-control.xml |   9 +--
+ src/core/cgroup.c                |  54 +++++++++--------
+ src/core/cgroup.h                |  14 ++---
+ src/core/dbus-cgroup.c           | 125 +++++++++++++++------------------------
+ src/core/load-fragment.c         |  54 +++++++----------
+ src/core/unit.c                  |   4 +-
+ src/libsystemd/sd-bus/bus-util.c |  35 +++++++----
+ src/shared/cgroup-util.c         |  41 +++++++++++++
+ src/shared/cgroup-util.h         |  27 +++++++++
+ 9 files changed, 205 insertions(+), 158 deletions(-)
+
+diff --git a/man/systemd.resource-control.xml b/man/systemd.resource-control.xml
+index f507c6748..6ab17e8cb 100644
+--- a/man/systemd.resource-control.xml
++++ b/man/systemd.resource-control.xml
+@@ -118,10 +118,11 @@
+ 
+         <listitem>
+           <para>Assign the specified CPU time share weight to the
+-          processes executed. Those options take an integer value and
++          processes executed. These options take an integer value and
+           control the <literal>cpu.shares</literal> control group
+-          attribute, which defaults to 1024. For details about this
+-          control group attribute, see <ulink
++          attribute. The allowed range is 2 to 262144. Defaults to
++          1024. For details about this control group attribute, see
++          <ulink
+           url="https://www.kernel.org/doc/Documentation/scheduler/sched-design-CFS.txt">sched-design-CFS.txt</ulink>.
+           The available CPU time is split up among all units within
+           one slice relative to their CPU time share weight.</para>
+@@ -258,7 +259,7 @@
+         the executed processes. Takes a single weight value (between
+         10 and 1000) to set the default block IO weight. This controls
+         the <literal>blkio.weight</literal> control group attribute,
+-        which defaults to 1000. For details about this control group
++        which defaults to 500. For details about this control group
+         attribute, see <ulink
+         url="https://www.kernel.org/doc/Documentation/cgroups/blkio-controller.txt">blkio-controller.txt</ulink>.
+         The available IO bandwidth is split up among all units within
+diff --git a/src/core/cgroup.c b/src/core/cgroup.c
+index d4a8f9cbe..0779fa555 100644
+--- a/src/core/cgroup.c
++++ b/src/core/cgroup.c
+@@ -35,14 +35,16 @@ void cgroup_context_init(CGroupContext *c) {
+         /* Initialize everything to the kernel defaults, assuming the
+          * structure is preinitialized to 0 */
+ 
+-        c->cpu_shares = (unsigned long) -1;
+-        c->startup_cpu_shares = (unsigned long) -1;
++        c->cpu_shares = CGROUP_CPU_SHARES_INVALID;
++        c->startup_cpu_shares = CGROUP_CPU_SHARES_INVALID;
++        c->cpu_quota_per_sec_usec = USEC_INFINITY;
++
+         c->memory_limit = (uint64_t) -1;
+-        c->blockio_weight = (unsigned long) -1;
+-        c->startup_blockio_weight = (unsigned long) -1;
+-        c->tasks_max = (uint64_t) -1;
+ 
+-        c->cpu_quota_per_sec_usec = USEC_INFINITY;
++        c->blockio_weight = CGROUP_BLKIO_WEIGHT_INVALID;
++        c->startup_blockio_weight = CGROUP_BLKIO_WEIGHT_INVALID;
++
++        c->tasks_max = (uint64_t) -1;
+ }
+ 
+ void cgroup_context_free_device_allow(CGroupContext *c, CGroupDeviceAllow *a) {
+@@ -100,11 +102,12 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
+                 "%sCPUAccounting=%s\n"
+                 "%sBlockIOAccounting=%s\n"
+                 "%sMemoryAccounting=%s\n"
+-                "%sCPUShares=%lu\n"
+-                "%sStartupCPUShares=%lu\n"
++                "%sTasksAccounting=%s\n"
++                "%sCPUShares=%" PRIu64 "\n"
++                "%sStartupCPUShares=%" PRIu64 "\n"
+                 "%sCPUQuotaPerSecSec=%s\n"
+-                "%sBlockIOWeight=%lu\n"
+-                "%sStartupBlockIOWeight=%lu\n"
++                "%sBlockIOWeight=%" PRIu64 "\n"
++                "%sStartupBlockIOWeight=%" PRIu64 "\n"
+                 "%sMemoryLimit=%" PRIu64 "\n"
+                 "%sTasksMax=%" PRIu64 "\n"
+                 "%sDevicePolicy=%s\n"
+@@ -112,6 +115,7 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
+                 prefix, yes_no(c->cpu_accounting),
+                 prefix, yes_no(c->blockio_accounting),
+                 prefix, yes_no(c->memory_accounting),
++                prefix, yes_no(c->tasks_accounting),
+                 prefix, c->cpu_shares,
+                 prefix, c->startup_cpu_shares,
+                 prefix, format_timespan(u, sizeof(u), c->cpu_quota_per_sec_usec, 1),
+@@ -131,7 +135,7 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
+ 
+         LIST_FOREACH(device_weights, w, c->blockio_device_weights)
+                 fprintf(f,
+-                        "%sBlockIODeviceWeight=%s %lu",
++                        "%sBlockIODeviceWeight=%s %" PRIu64,
+                         prefix,
+                         w->path,
+                         w->weight);
+@@ -307,11 +311,11 @@ void cgroup_context_apply(CGroupContext *c, CGroupControllerMask mask, const cha
+          * and missing cgroups, i.e. EROFS and ENOENT. */
+ 
+         if ((mask & CGROUP_CPU) && !is_root) {
+-                char buf[MAX(DECIMAL_STR_MAX(unsigned long), DECIMAL_STR_MAX(usec_t)) + 1];
++                char buf[MAX(DECIMAL_STR_MAX(uint64_t), DECIMAL_STR_MAX(usec_t)) + 1];
+ 
+-                sprintf(buf, "%lu\n",
+-                        IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING) && c->startup_cpu_shares != (unsigned long) -1 ? c->startup_cpu_shares :
+-                        c->cpu_shares != (unsigned long) -1 ? c->cpu_shares : 1024);
++                sprintf(buf, "%" PRIu64 "\n",
++                        IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING) && c->startup_cpu_shares != CGROUP_CPU_SHARES_INVALID ? c->startup_cpu_shares :
++                        c->cpu_shares != CGROUP_CPU_SHARES_INVALID ? c->cpu_shares : CGROUP_CPU_SHARES_DEFAULT);
+                 r = cg_set_attribute("cpu", path, "cpu.shares", buf);
+                 if (r < 0)
+                         log_full_errno(IN_SET(r, -ENOENT, -EROFS) ? LOG_DEBUG : LOG_WARNING, r,
+@@ -334,15 +338,15 @@ void cgroup_context_apply(CGroupContext *c, CGroupControllerMask mask, const cha
+         }
+ 
+         if (mask & CGROUP_BLKIO) {
+-                char buf[MAX3(DECIMAL_STR_MAX(unsigned long)+1,
+-                              DECIMAL_STR_MAX(dev_t)*2+2+DECIMAL_STR_MAX(unsigned long)*1,
+-                              DECIMAL_STR_MAX(dev_t)*2+2+DECIMAL_STR_MAX(uint64_t)+1)];
++                char buf[MAX(DECIMAL_STR_MAX(uint64_t)+1,
++                             DECIMAL_STR_MAX(dev_t)*2+2+DECIMAL_STR_MAX(uint64_t)+1)];
+                 CGroupBlockIODeviceWeight *w;
+                 CGroupBlockIODeviceBandwidth *b;
+ 
+                 if (!is_root) {
+-                        sprintf(buf, "%lu\n", IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING) && c->startup_blockio_weight != (unsigned long) -1 ? c->startup_blockio_weight :
+-                                c->blockio_weight != (unsigned long) -1 ? c->blockio_weight : 1000);
++                        sprintf(buf, "%" PRIu64 "\n",
++                                IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING) && c->startup_blockio_weight != CGROUP_BLKIO_WEIGHT_INVALID ? c->startup_blockio_weight :
++                                c->blockio_weight != CGROUP_BLKIO_WEIGHT_INVALID ? c->blockio_weight : CGROUP_BLKIO_WEIGHT_DEFAULT);
+                         r = cg_set_attribute("blkio", path, "blkio.weight", buf);
+                         if (r < 0)
+                                 log_full_errno(IN_SET(r, -ENOENT, -EROFS) ? LOG_DEBUG : LOG_WARNING, r,
+@@ -356,7 +360,7 @@ void cgroup_context_apply(CGroupContext *c, CGroupControllerMask mask, const cha
+                                 if (r < 0)
+                                         continue;
+ 
+-                                sprintf(buf, "%u:%u %lu", major(dev), minor(dev), w->weight);
++                                sprintf(buf, "%u:%u %" PRIu64 "\n", major(dev), minor(dev), w->weight);
+                                 r = cg_set_attribute("blkio", path, "blkio.weight_device", buf);
+                                 if (r < 0)
+                                         log_full_errno(IN_SET(r, -ENOENT, -EROFS) ? LOG_DEBUG : LOG_WARNING, r,
+@@ -482,14 +486,14 @@ CGroupControllerMask cgroup_context_get_mask(CGroupContext *c) {
+         /* Figure out which controllers we need */
+ 
+         if (c->cpu_accounting ||
+-            c->cpu_shares != (unsigned long) -1 ||
+-            c->startup_cpu_shares != (unsigned long) -1 ||
++            c->cpu_shares != CGROUP_CPU_SHARES_INVALID ||
++            c->startup_cpu_shares != CGROUP_CPU_SHARES_INVALID ||
+             c->cpu_quota_per_sec_usec != USEC_INFINITY)
+                 mask |= CGROUP_CPUACCT | CGROUP_CPU;
+ 
+         if (c->blockio_accounting ||
+-            c->blockio_weight != (unsigned long) -1 ||
+-            c->startup_blockio_weight != (unsigned long) -1 ||
++            c->blockio_weight != CGROUP_BLKIO_WEIGHT_INVALID ||
++            c->startup_blockio_weight != CGROUP_BLKIO_WEIGHT_INVALID ||
+             c->blockio_device_weights ||
+             c->blockio_device_bandwidths)
+                 mask |= CGROUP_BLKIO;
+diff --git a/src/core/cgroup.h b/src/core/cgroup.h
+index 8af3eaa3a..870f39c52 100644
+--- a/src/core/cgroup.h
++++ b/src/core/cgroup.h
+@@ -58,7 +58,7 @@ struct CGroupDeviceAllow {
+ struct CGroupBlockIODeviceWeight {
+         LIST_FIELDS(CGroupBlockIODeviceWeight, device_weights);
+         char *path;
+-        unsigned long weight;
++        uint64_t weight;
+ };
+ 
+ struct CGroupBlockIODeviceBandwidth {
+@@ -74,12 +74,12 @@ struct CGroupContext {
+         bool memory_accounting;
+         bool tasks_accounting;
+ 
+-        unsigned long cpu_shares;
+-        unsigned long startup_cpu_shares;
++        uint64_t cpu_shares;
++        uint64_t startup_cpu_shares;
+         usec_t cpu_quota_per_sec_usec;
+ 
+-        unsigned long blockio_weight;
+-        unsigned long startup_blockio_weight;
++        uint64_t blockio_weight;
++        uint64_t startup_blockio_weight;
+         LIST_HEAD(CGroupBlockIODeviceWeight, blockio_device_weights);
+         LIST_HEAD(CGroupBlockIODeviceBandwidth, blockio_device_bandwidths);
+ 
+@@ -88,9 +88,9 @@ struct CGroupContext {
+         CGroupDevicePolicy device_policy;
+         LIST_HEAD(CGroupDeviceAllow, device_allow);
+ 
+-        bool delegate;
+-
+         uint64_t tasks_max;
++
++        bool delegate;
+ };
+ 
+ #include "unit.h"
+diff --git a/src/core/dbus-cgroup.c b/src/core/dbus-cgroup.c
+index fa76c60c1..ffeeb5aa9 100644
+--- a/src/core/dbus-cgroup.c
++++ b/src/core/dbus-cgroup.c
+@@ -133,34 +133,16 @@ static int property_get_device_allow(
+         return sd_bus_message_close_container(reply);
+ }
+ 
+-static int property_get_ulong_as_u64(
+-                sd_bus *bus,
+-                const char *path,
+-                const char *interface,
+-                const char *property,
+-                sd_bus_message *reply,
+-                void *userdata,
+-                sd_bus_error *error) {
+-
+-        unsigned long *ul = userdata;
+-
+-        assert(bus);
+-        assert(reply);
+-        assert(ul);
+-
+-        return sd_bus_message_append(reply, "t", *ul == (unsigned long) -1 ? (uint64_t) -1 : (uint64_t) *ul);
+-}
+-
+ const sd_bus_vtable bus_cgroup_vtable[] = {
+         SD_BUS_VTABLE_START(0),
+         SD_BUS_PROPERTY("Delegate", "b", bus_property_get_bool, offsetof(CGroupContext, delegate), 0),
+         SD_BUS_PROPERTY("CPUAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, cpu_accounting), 0),
+-        SD_BUS_PROPERTY("CPUShares", "t", property_get_ulong_as_u64, offsetof(CGroupContext, cpu_shares), 0),
+-        SD_BUS_PROPERTY("StartupCPUShares", "t", property_get_ulong_as_u64, offsetof(CGroupContext, startup_cpu_shares), 0),
++        SD_BUS_PROPERTY("CPUShares", "t", NULL, offsetof(CGroupContext, cpu_shares), 0),
++        SD_BUS_PROPERTY("StartupCPUShares", "t", NULL, offsetof(CGroupContext, startup_cpu_shares), 0),
+         SD_BUS_PROPERTY("CPUQuotaPerSecUSec", "t", bus_property_get_usec, offsetof(CGroupContext, cpu_quota_per_sec_usec), 0),
+         SD_BUS_PROPERTY("BlockIOAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, blockio_accounting), 0),
+-        SD_BUS_PROPERTY("BlockIOWeight", "t", property_get_ulong_as_u64, offsetof(CGroupContext, blockio_weight), 0),
+-        SD_BUS_PROPERTY("StartupBlockIOWeight", "t", property_get_ulong_as_u64, offsetof(CGroupContext, startup_blockio_weight), 0),
++        SD_BUS_PROPERTY("BlockIOWeight", "t", NULL, offsetof(CGroupContext, blockio_weight), 0),
++        SD_BUS_PROPERTY("StartupBlockIOWeight", "t", NULL, offsetof(CGroupContext, startup_blockio_weight), 0),
+         SD_BUS_PROPERTY("BlockIODeviceWeight", "a(st)", property_get_blockio_device_weight, 0, 0),
+         SD_BUS_PROPERTY("BlockIOReadBandwidth", "a(st)", property_get_blockio_device_bandwidths, 0, 0),
+         SD_BUS_PROPERTY("BlockIOWriteBandwidth", "a(st)", property_get_blockio_device_bandwidths, 0, 0),
+@@ -237,49 +219,45 @@ int bus_cgroup_set_property(
+                 return 1;
+ 
+         } else if (streq(name, "CPUShares")) {
+-                uint64_t u64;
+-                unsigned long ul;
++                uint64_t shares;
+ 
+-                r = sd_bus_message_read(message, "t", &u64);
++                r = sd_bus_message_read(message, "t", &shares);
+                 if (r < 0)
+                         return r;
+ 
+-                if (u64 == (uint64_t) -1)
+-                        ul = (unsigned long) -1;
+-                else {
+-                        ul = (unsigned long) u64;
+-                        if (ul <= 0 || (uint64_t) ul != u64)
+-                                return sd_bus_error_set_errnof(error, EINVAL, "CPUShares value out of range");
+-                }
++                if (!CGROUP_CPU_SHARES_IS_OK(shares))
++                        return sd_bus_error_set_errnof(error, EINVAL, "CPUShares value out of range");
+ 
+                 if (mode != UNIT_CHECK) {
+-                        c->cpu_shares = ul;
++                        c->cpu_shares = shares;
+                         u->cgroup_realized_mask &= ~CGROUP_CPU;
+-                        unit_write_drop_in_private_format(u, mode, name, "CPUShares=%lu", ul);
++
++                        if (shares == CGROUP_CPU_SHARES_INVALID)
++                                unit_write_drop_in_private(u, mode, name, "CPUShares=");
++                        else
++                                unit_write_drop_in_private_format(u, mode, name, "CPUShares=%" PRIu64, shares);
+                 }
+ 
+                 return 1;
+ 
+         } else if (streq(name, "StartupCPUShares")) {
+-                uint64_t u64;
+-                unsigned long ul;
++                uint64_t shares;
+ 
+-                r = sd_bus_message_read(message, "t", &u64);
++                r = sd_bus_message_read(message, "t", &shares);
+                 if (r < 0)
+                         return r;
+ 
+-                if (u64 == (uint64_t) -1)
+-                        ul = (unsigned long) -1;
+-                else {
+-                        ul = (unsigned long) u64;
+-                        if (ul <= 0 || (uint64_t) ul != u64)
+-                                return sd_bus_error_set_errnof(error, EINVAL, "StartupCPUShares value out of range");
+-                }
++                if (!CGROUP_CPU_SHARES_IS_OK(shares))
++                        return sd_bus_error_set_errnof(error, EINVAL, "StartupCPUShares value out of range");
+ 
+                 if (mode != UNIT_CHECK) {
+-                        c->startup_cpu_shares = ul;
++                        c->startup_cpu_shares = shares;
+                         u->cgroup_realized_mask &= ~CGROUP_CPU;
+-                        unit_write_drop_in_private_format(u, mode, name, "StartupCPUShares=%lu", ul);
++
++                        if (shares == CGROUP_CPU_SHARES_INVALID)
++                                unit_write_drop_in_private(u, mode, name, "StartupCPUShares=");
++                        else
++                                unit_write_drop_in_private_format(u, mode, name, "StartupCPUShares=%" PRIu64, shares);
+                 }
+ 
+                 return 1;
+@@ -318,49 +296,45 @@ int bus_cgroup_set_property(
+                 return 1;
+ 
+         } else if (streq(name, "BlockIOWeight")) {
+-                uint64_t u64;
+-                unsigned long ul;
++                uint64_t weight;
+ 
+-                r = sd_bus_message_read(message, "t", &u64);
++                r = sd_bus_message_read(message, "t", &weight);
+                 if (r < 0)
+                         return r;
+ 
+-                if (u64 == (uint64_t) -1)
+-                        ul = (unsigned long) -1;
+-                else  {
+-                        ul = (unsigned long) u64;
+-                        if (ul < 10 || ul > 1000)
+-                                return sd_bus_error_set_errnof(error, EINVAL, "BlockIOWeight value out of range");
+-                }
++                if (!CGROUP_BLKIO_WEIGHT_IS_OK(weight))
++                        return sd_bus_error_set_errnof(error, EINVAL, "BlockIOWeight value out of range");
+ 
+                 if (mode != UNIT_CHECK) {
+-                        c->blockio_weight = ul;
++                        c->blockio_weight = weight;
+                         u->cgroup_realized_mask &= ~CGROUP_BLKIO;
+-                        unit_write_drop_in_private_format(u, mode, name, "BlockIOWeight=%lu", ul);
++
++                        if (weight == CGROUP_BLKIO_WEIGHT_INVALID)
++                                unit_write_drop_in_private(u, mode, name, "BlockIOWeight=");
++                        else
++                                unit_write_drop_in_private_format(u, mode, name, "BlockIOWeight=%" PRIu64, weight);
+                 }
+ 
+                 return 1;
+ 
+         } else if (streq(name, "StartupBlockIOWeight")) {
+-                uint64_t u64;
+-                unsigned long ul;
++                uint64_t weight;
+ 
+-                r = sd_bus_message_read(message, "t", &u64);
++                r = sd_bus_message_read(message, "t", &weight);
+                 if (r < 0)
+                         return r;
+ 
+-                if (u64 == (uint64_t) -1)
+-                        ul = (unsigned long) -1;
+-                else  {
+-                        ul = (unsigned long) u64;
+-                        if (ul < 10 || ul > 1000)
+-                                return sd_bus_error_set_errnof(error, EINVAL, "StartupBlockIOWeight value out of range");
+-                }
++                if (CGROUP_BLKIO_WEIGHT_IS_OK(weight))
++                        return sd_bus_error_set_errnof(error, EINVAL, "StartupBlockIOWeight value out of range");
+ 
+                 if (mode != UNIT_CHECK) {
+-                        c->startup_blockio_weight = ul;
++                        c->startup_blockio_weight = weight;
+                         u->cgroup_realized_mask &= ~CGROUP_BLKIO;
+-                        unit_write_drop_in_private_format(u, mode, name, "StartupBlockIOWeight=%lu", ul);
++
++                        if (weight == CGROUP_BLKIO_WEIGHT_INVALID)
++                                unit_write_drop_in_private(u, mode, name, "StartupBlockIOWeight=");
++                        else
++                                unit_write_drop_in_private_format(u, mode, name, "StartupBlockIOWeight=%" PRIu64, weight);
+                 }
+ 
+                 return 1;
+@@ -455,17 +429,16 @@ int bus_cgroup_set_property(
+ 
+         } else if (streq(name, "BlockIODeviceWeight")) {
+                 const char *path;
+-                uint64_t u64;
++                uint64_t weight;
+                 unsigned n = 0;
+ 
+                 r = sd_bus_message_enter_container(message, 'a', "(st)");
+                 if (r < 0)
+                         return r;
+ 
+-                while ((r = sd_bus_message_read(message, "(st)", &path, &u64)) > 0) {
+-                        unsigned long ul = u64;
++                while ((r = sd_bus_message_read(message, "(st)", &path, &weight)) > 0) {
+ 
+-                        if (ul < 10 || ul > 1000)
++                        if (!CGROUP_BLKIO_WEIGHT_IS_OK(weight) || weight == CGROUP_BLKIO_WEIGHT_INVALID)
+                                 return sd_bus_error_set_errnof(error, EINVAL, "BlockIODeviceWeight out of range");
+ 
+                         if (mode != UNIT_CHECK) {
+@@ -491,7 +464,7 @@ int bus_cgroup_set_property(
+                                         LIST_PREPEND(device_weights,c->blockio_device_weights, a);
+                                 }
+ 
+-                                a->weight = ul;
++                                a->weight = weight;
+                         }
+ 
+                         n++;
+@@ -520,7 +493,7 @@ int bus_cgroup_set_property(
+ 
+                         fputs("BlockIODeviceWeight=\n", f);
+                         LIST_FOREACH(device_weights, a, c->blockio_device_weights)
+-                                fprintf(f, "BlockIODeviceWeight=%s %lu\n", a->path, a->weight);
++                                fprintf(f, "BlockIODeviceWeight=%s %" PRIu64 "\n", a->path, a->weight);
+ 
+                         fflush(f);
+                         unit_write_drop_in_private(u, mode, name, buf);
+diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
+index a10e1903a..da58bcc5c 100644
+--- a/src/core/load-fragment.c
++++ b/src/core/load-fragment.c
+@@ -2951,26 +2951,19 @@ int config_parse_cpu_shares(
+                 void *data,
+                 void *userdata) {
+ 
+-        unsigned long *shares = data, lu;
++        uint64_t *shares = data;
+         int r;
+ 
+         assert(filename);
+         assert(lvalue);
+         assert(rvalue);
+ 
+-        if (isempty(rvalue)) {
+-                *shares = (unsigned long) -1;
+-                return 0;
+-        }
+-
+-        r = safe_atolu(rvalue, &lu);
+-        if (r < 0 || lu <= 0) {
+-                log_syntax(unit, LOG_ERR, filename, line, EINVAL,
+-                           "CPU shares '%s' invalid. Ignoring.", rvalue);
++        r = cg_cpu_shares_parse(rvalue, shares);
++        if (r < 0) {
++                log_syntax(unit, LOG_ERR, filename, line, r, "CPU shares '%s' invalid. Ignoring.", rvalue);
+                 return 0;
+         }
+ 
+-        *shares = lu;
+         return 0;
+ }
+ 
+@@ -3163,26 +3156,19 @@ int config_parse_blockio_weight(
+                 void *data,
+                 void *userdata) {
+ 
+-        unsigned long *weight = data, lu;
++        uint64_t *weight = data;
+         int r;
+ 
+         assert(filename);
+         assert(lvalue);
+         assert(rvalue);
+ 
+-        if (isempty(rvalue)) {
+-                *weight = (unsigned long) -1;
+-                return 0;
+-        }
+-
+-        r = safe_atolu(rvalue, &lu);
+-        if (r < 0 || lu < 10 || lu > 1000) {
+-                log_syntax(unit, LOG_ERR, filename, line, EINVAL,
+-                           "Block IO weight '%s' invalid. Ignoring.", rvalue);
++        r = cg_blkio_weight_parse(rvalue, weight);
++        if (r < 0) {
++                log_syntax(unit, LOG_ERR, filename, line, r, "Block IO weight '%s' invalid. Ignoring.", rvalue);
+                 return 0;
+         }
+ 
+-        *weight = lu;
+         return 0;
+ }
+ 
+@@ -3201,8 +3187,8 @@ int config_parse_blockio_device_weight(
+         _cleanup_free_ char *path = NULL;
+         CGroupBlockIODeviceWeight *w;
+         CGroupContext *c = data;
+-        unsigned long lu;
+         const char *weight;
++        uint64_t u;
+         size_t n;
+         int r;
+ 
+@@ -3219,9 +3205,10 @@ int config_parse_blockio_device_weight(
+ 
+         n = strcspn(rvalue, WHITESPACE);
+         weight = rvalue + n;
+-        if (!*weight) {
+-                log_syntax(unit, LOG_ERR, filename, line, EINVAL,
+-                           "Expected block device and device weight. Ignoring.");
++        weight += strspn(weight, WHITESPACE);
++
++        if (isempty(weight)) {
++                log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Expected block device and device weight. Ignoring.");
+                 return 0;
+         }
+ 
+@@ -3230,19 +3217,18 @@ int config_parse_blockio_device_weight(
+                 return log_oom();
+ 
+         if (!path_startswith(path, "/dev")) {
+-                log_syntax(unit, LOG_ERR, filename, line, EINVAL,
+-                           "Invalid device node path '%s'. Ignoring.", path);
++                log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Invalid device node path '%s'. Ignoring.", path);
+                 return 0;
+         }
+ 
+-        weight += strspn(weight, WHITESPACE);
+-        r = safe_atolu(weight, &lu);
+-        if (r < 0 || lu < 10 || lu > 1000) {
+-                log_syntax(unit, LOG_ERR, filename, line, EINVAL,
+-                           "Block IO weight '%s' invalid. Ignoring.", rvalue);
++        r = cg_blkio_weight_parse(weight, &u);
++        if (r < 0) {
++                log_syntax(unit, LOG_ERR, filename, line, r, "Block IO weight '%s' invalid. Ignoring.", weight);
+                 return 0;
+         }
+ 
++        assert(u != CGROUP_BLKIO_WEIGHT_INVALID);
++
+         w = new0(CGroupBlockIODeviceWeight, 1);
+         if (!w)
+                 return log_oom();
+@@ -3250,7 +3236,7 @@ int config_parse_blockio_device_weight(
+         w->path = path;
+         path = NULL;
+ 
+-        w->weight = lu;
++        w->weight = u;
+ 
+         LIST_PREPEND(device_weights, c->blockio_device_weights, w);
+         return 0;
+diff --git a/src/core/unit.c b/src/core/unit.c
+index 6a2ad6ed3..8c0fde878 100644
+--- a/src/core/unit.c
++++ b/src/core/unit.c
+@@ -1178,8 +1178,8 @@ static int unit_add_startup_units(Unit *u) {
+         if (!c)
+                 return 0;
+ 
+-        if (c->startup_cpu_shares == (unsigned long) -1 &&
+-            c->startup_blockio_weight == (unsigned long) -1)
++        if (c->startup_cpu_shares == CGROUP_CPU_SHARES_INVALID &&
++            c->startup_blockio_weight == CGROUP_BLKIO_WEIGHT_INVALID)
+                 return 0;
+ 
+         r = set_put(u->manager->startup_units, u);
+diff --git a/src/libsystemd/sd-bus/bus-util.c b/src/libsystemd/sd-bus/bus-util.c
+index 263457427..cbf1eccf7 100644
+--- a/src/libsystemd/sd-bus/bus-util.c
++++ b/src/libsystemd/sd-bus/bus-util.c
+@@ -23,20 +23,23 @@
+ 
+ #include "sd-daemon.h"
+ #include "sd-event.h"
+-#include "util.h"
+-#include "strv.h"
+-#include "macro.h"
++#include "sd-bus.h"
++
++#include "bus-error.h"
++#include "bus-internal.h"
++#include "bus-label.h"
++#include "bus-message.h"
++#include "cgroup-util.h"
+ #include "def.h"
+-#include "path-util.h"
++#include "macro.h"
+ #include "missing.h"
++#include "path-util.h"
+ #include "set.h"
++#include "strv.h"
+ #include "unit-name.h"
++#include "util.h"
+ 
+-#include "sd-bus.h"
+-#include "bus-error.h"
+-#include "bus-message.h"
+ #include "bus-util.h"
+-#include "bus-internal.h"
+ 
+ static int name_owner_change_callback(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
+         sd_event *e = userdata;
+@@ -1429,10 +1432,22 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
+                 }
+ 
+                 r = sd_bus_message_append(m, "sv", "TasksMax", "t", t);
+-        } else if (STR_IN_SET(field, "CPUShares", "BlockIOWeight")) {
++
++        } else if (STR_IN_SET(field, "CPUShares", "StartupCPUShares")) {
++                uint64_t u;
++
++                r = cg_cpu_shares_parse(eq, &u);
++                if (r < 0) {
++                        log_error("Failed to parse %s value %s.", field, eq);
++                        return -EINVAL;
++                }
++
++                r = sd_bus_message_append(m, "v", "t", u);
++
++        } else if (STR_IN_SET(field, "BlockIOWeight", "StartupBlockIOWeight")) {
+                 uint64_t u;
+ 
+-                r = safe_atou64(eq, &u);
++                r = cg_blkio_weight_parse(eq, &u);
+                 if (r < 0) {
+                         log_error("Failed to parse %s value %s.", field, eq);
+                         return -EINVAL;
+diff --git a/src/shared/cgroup-util.c b/src/shared/cgroup-util.c
+index c5d9e4bb5..f67b53b4d 100644
+--- a/src/shared/cgroup-util.c
++++ b/src/shared/cgroup-util.c
+@@ -1795,3 +1795,44 @@ int cg_kernel_controllers(Set *controllers) {
+ 
+         return 0;
+ }
++
++
++int cg_cpu_shares_parse(const char *s, uint64_t *ret) {
++        uint64_t u;
++        int r;
++
++        if (isempty(s)) {
++                *ret = CGROUP_CPU_SHARES_INVALID;
++                return 0;
++        }
++
++        r = safe_atou64(s, &u);
++        if (r < 0)
++                return r;
++
++        if (u < CGROUP_CPU_SHARES_MIN || u > CGROUP_CPU_SHARES_MAX)
++                return -ERANGE;
++
++        *ret = u;
++        return 0;
++}
++
++int cg_blkio_weight_parse(const char *s, uint64_t *ret) {
++        uint64_t u;
++        int r;
++
++        if (isempty(s)) {
++                *ret = CGROUP_BLKIO_WEIGHT_INVALID;
++                return 0;
++        }
++
++        r = safe_atou64(s, &u);
++        if (r < 0)
++                return r;
++
++        if (u < CGROUP_BLKIO_WEIGHT_MIN || u > CGROUP_BLKIO_WEIGHT_MAX)
++                return -ERANGE;
++
++        *ret = u;
++        return 0;
++}
+diff --git a/src/shared/cgroup-util.h b/src/shared/cgroup-util.h
+index 31bd8d311..615c1f03e 100644
+--- a/src/shared/cgroup-util.h
++++ b/src/shared/cgroup-util.h
+@@ -39,6 +39,30 @@ typedef enum CGroupControllerMask {
+         _CGROUP_CONTROLLER_MASK_ALL = 31
+ } CGroupControllerMask;
+ 
++/* Special values for the cpu.shares attribute */
++#define CGROUP_CPU_SHARES_INVALID ((uint64_t) -1)
++#define CGROUP_CPU_SHARES_MIN UINT64_C(2)
++#define CGROUP_CPU_SHARES_MAX UINT64_C(262144)
++#define CGROUP_CPU_SHARES_DEFAULT UINT64_C(1024)
++
++static inline bool CGROUP_CPU_SHARES_IS_OK(uint64_t x) {
++        return
++            x == CGROUP_CPU_SHARES_INVALID ||
++            (x >= CGROUP_CPU_SHARES_MIN && x <= CGROUP_CPU_SHARES_MAX);
++}
++
++/* Special values for the blkio.weight attribute */
++#define CGROUP_BLKIO_WEIGHT_INVALID ((uint64_t) -1)
++#define CGROUP_BLKIO_WEIGHT_MIN UINT64_C(10)
++#define CGROUP_BLKIO_WEIGHT_MAX UINT64_C(1000)
++#define CGROUP_BLKIO_WEIGHT_DEFAULT UINT64_C(500)
++
++static inline bool CGROUP_BLKIO_WEIGHT_IS_OK(uint64_t x) {
++        return
++            x == CGROUP_BLKIO_WEIGHT_INVALID ||
++            (x >= CGROUP_BLKIO_WEIGHT_MIN && x <= CGROUP_BLKIO_WEIGHT_MAX);
++}
++
+ /*
+  * General rules:
+  *
+@@ -136,3 +160,6 @@ int cg_trim_everywhere(CGroupControllerMask supported, const char *path, bool de
+ CGroupControllerMask cg_mask_supported(void);
+ 
+ int cg_kernel_controllers(Set *controllers);
++
++int cg_cpu_shares_parse(const char *s, uint64_t *ret);
++int cg_blkio_weight_parse(const char *s, uint64_t *ret);
diff --git a/SOURCES/0579-fileio-add-new-helper-call-read_line-as-bounded-getl.patch b/SOURCES/0579-fileio-add-new-helper-call-read_line-as-bounded-getl.patch
new file mode 100644
index 0000000..a12c7ab
--- /dev/null
+++ b/SOURCES/0579-fileio-add-new-helper-call-read_line-as-bounded-getl.patch
@@ -0,0 +1,177 @@
+From d7b56e186521ce2e48e27edda121d780a3d62d27 Mon Sep 17 00:00:00 2001
+From: Jan Synacek <jsynacek@redhat.com>
+Date: Thu, 23 Nov 2017 08:53:50 +0100
+Subject: [PATCH] fileio: add new helper call read_line() as bounded getline()
+ replacement
+
+read_line() is much like getline(), and returns a line read from a
+FILE*, of arbitrary sizes. In contrast to gets() it will grow the buffer
+dynamically, and in contrast to getline() it will place a user-specified
+boundary on the line.
+
+(cherry-picked from commit 4f9a66a32dda1d9a28f9bb3fa31c2148524bc46a)
+
+Resolves: #1503106
+---
+ src/shared/fileio.c    | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++
+ src/shared/fileio.h    |  2 ++
+ src/test/test-fileio.c | 44 +++++++++++++++++++++++++++++
+ 3 files changed, 123 insertions(+)
+
+diff --git a/src/shared/fileio.c b/src/shared/fileio.c
+index ff6b1a7ed..107737573 100644
+--- a/src/shared/fileio.c
++++ b/src/shared/fileio.c
+@@ -815,3 +815,80 @@ int get_status_field(const char *filename, const char *pattern, char **field) {
+ 
+         return 0;
+ }
++
++int read_line(FILE *f, size_t limit, char **ret) {
++        _cleanup_free_ char *buffer = NULL;
++        size_t n = 0, allocated = 0, count = 0;
++        int r;
++
++        assert(f);
++
++        /* Something like a bounded version of getline().
++         *
++         * Considers EOF, \n and \0 end of line delimiters, and does not include these delimiters in the string
++         * returned.
++         *
++         * Returns the number of bytes read from the files (i.e. including delimiters — this hence usually differs from
++         * the number of characters in the returned string). When EOF is hit, 0 is returned.
++         *
++         * The input parameter limit is the maximum numbers of characters in the returned string, i.e. excluding
++         * delimiters. If the limit is hit we fail and return -ENOBUFS.
++         *
++         * If a line shall be skipped ret may be initialized as NULL. */
++
++        if (ret) {
++                if (!GREEDY_REALLOC(buffer, allocated, 1))
++                        return -ENOMEM;
++        }
++
++        flockfile(f);
++
++        for (;;) {
++                int c;
++
++                if (n >= limit) {
++                        funlockfile(f);
++                        return -ENOBUFS;
++                }
++
++                errno = 0;
++                c = fgetc_unlocked(f);
++                if (c == EOF) {
++                        /* if we read an error, and have no data to return, then propagate the error */
++                        if (ferror_unlocked(f) && n == 0) {
++                                r = errno > 0 ? -errno : -EIO;
++                                funlockfile(f);
++                                return r;
++                        }
++
++                        break;
++                }
++
++                count++;
++
++                if (IN_SET(c, '\n', 0)) /* Reached a delimiter */
++                        break;
++
++                if (ret) {
++                        if (!GREEDY_REALLOC(buffer, allocated, n + 2)) {
++                                funlockfile(f);
++                                return -ENOMEM;
++                        }
++
++                        buffer[n] = (char) c;
++                }
++
++                n++;
++        }
++
++        funlockfile(f);
++
++        if (ret) {
++                buffer[n] = 0;
++
++                *ret = buffer;
++                buffer = NULL;
++        }
++
++        return (int) count;
++}
+diff --git a/src/shared/fileio.h b/src/shared/fileio.h
+index 5ae51c1e2..f33464dce 100644
+--- a/src/shared/fileio.h
++++ b/src/shared/fileio.h
+@@ -43,3 +43,5 @@ int write_env_file(const char *fname, char **l);
+ int executable_is_script(const char *path, char **interpreter);
+ 
+ int get_status_field(const char *filename, const char *pattern, char **field);
++
++int read_line(FILE *f, size_t limit, char **ret);
+diff --git a/src/test/test-fileio.c b/src/test/test-fileio.c
+index 63e4a19b7..fc5969322 100644
+--- a/src/test/test-fileio.c
++++ b/src/test/test-fileio.c
+@@ -392,6 +392,49 @@ static void test_load_env_file_pairs(void) {
+         unlink(fn);
+ }
+ 
++static void test_read_line(void) {
++        _cleanup_fclose_ FILE *f = NULL;
++        _cleanup_free_ char *line = NULL;
++
++        char buffer[] =
++                "Some test data\n"
++                "With newlines, and a NUL byte\0"
++                "\n"
++                "an empty line\n"
++                "an ignored line\n"
++                "and a very long line that is supposed to be truncated, because it is so long\n";
++
++        f = fmemopen(buffer, sizeof(buffer), "re");
++        assert_se(f);
++
++        assert_se(read_line(f, (size_t) -1, &line) == 15 && streq(line, "Some test data"));
++        line = mfree(line);
++
++        assert_se(read_line(f, 1024, &line) == 30 && streq(line, "With newlines, and a NUL byte"));
++        line = mfree(line);
++
++        assert_se(read_line(f, 1024, &line) == 1 && streq(line, ""));
++        line = mfree(line);
++
++        assert_se(read_line(f, 1024, &line) == 14 && streq(line, "an empty line"));
++        line = mfree(line);
++
++        assert_se(read_line(f, (size_t) -1, NULL) == 16);
++
++        assert_se(read_line(f, 16, &line) == -ENOBUFS);
++        line = mfree(line);
++
++        /* read_line() stopped when it hit the limit, that means when we continue reading we'll read at the first
++         * character after the previous limit. Let's make use of tha to continue our test. */
++        assert_se(read_line(f, 1024, &line) == 61 && streq(line, "line that is supposed to be truncated, because it is so long"));
++        line = mfree(line);
++
++        assert_se(read_line(f, 1024, &line) == 1 && streq(line, ""));
++        line = mfree(line);
++
++        assert_se(read_line(f, 1024, &line) == 0 && streq(line, ""));
++}
++
+ int main(int argc, char *argv[]) {
+         log_parse_environment();
+         log_open();
+@@ -405,6 +448,7 @@ int main(int argc, char *argv[]) {
+         test_write_string_file();
+         test_write_string_file_no_create();
+         test_load_env_file_pairs();
++        test_read_line();
+ 
+         return 0;
+ }
diff --git a/SOURCES/0580-def-add-new-constant-LONG_LINE_MAX.patch b/SOURCES/0580-def-add-new-constant-LONG_LINE_MAX.patch
new file mode 100644
index 0000000..2798123
--- /dev/null
+++ b/SOURCES/0580-def-add-new-constant-LONG_LINE_MAX.patch
@@ -0,0 +1,28 @@
+From 4cd343cf1a25e603ea78acbac027589f6a53a118 Mon Sep 17 00:00:00 2001
+From: Jan Synacek <jsynacek@redhat.com>
+Date: Thu, 23 Nov 2017 09:22:21 +0100
+Subject: [PATCH] def: add new constant LONG_LINE_MAX
+
+LONG_LINE_MAX is much like LINE_MAX, but longer.
+
+As it turns out LINE_MAX at 4096 is too short for many usecases. Since
+the general concept of having a common maximum line length limit makes
+sense let's add our own, and make it larger (1MB for now).
+
+(cherry-picked from commit 189912440f6545404e84b3cd1d6ca54f1057e3e6)
+
+Resolves: #1503106
+---
+ src/shared/def.h | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/src/shared/def.h b/src/shared/def.h
+index 76daf012d..9e008a6d2 100644
+--- a/src/shared/def.h
++++ b/src/shared/def.h
+@@ -87,3 +87,5 @@
+ 
+ #define NOTIFY_FD_MAX 768
+ #define NOTIFY_BUFFER_MAX PIPE_BUF
++
++#define LONG_LINE_MAX (1U*1024U*1024U)
diff --git a/SOURCES/0581-fileio-rework-read_one_line_file-on-top-of-read_line.patch b/SOURCES/0581-fileio-rework-read_one_line_file-on-top-of-read_line.patch
new file mode 100644
index 0000000..5be44af
--- /dev/null
+++ b/SOURCES/0581-fileio-rework-read_one_line_file-on-top-of-read_line.patch
@@ -0,0 +1,55 @@
+From aab6aeb2529a1e9b51eeadf91decd06e03af5da1 Mon Sep 17 00:00:00 2001
+From: Jan Synacek <jsynacek@redhat.com>
+Date: Thu, 23 Nov 2017 09:23:34 +0100
+Subject: [PATCH] fileio: rework read_one_line_file() on top of read_line()
+
+(cherry picked from commit f4b51a2d092685c9a080e84130fec2d74c834f5c)
+
+Resolves: #1503106
+---
+ src/shared/fileio.c | 18 ++----------------
+ 1 file changed, 2 insertions(+), 16 deletions(-)
+
+diff --git a/src/shared/fileio.c b/src/shared/fileio.c
+index 107737573..be775f982 100644
+--- a/src/shared/fileio.c
++++ b/src/shared/fileio.c
+@@ -25,6 +25,7 @@
+ #include "strv.h"
+ #include "utf8.h"
+ #include "ctype.h"
++#include "def.h"
+ #include "fileio.h"
+ 
+ int write_string_stream(FILE *f, const char *line) {
+@@ -108,7 +109,6 @@ int write_string_file_atomic(const char *fn, const char *line) {
+ 
+ int read_one_line_file(const char *fn, char **line) {
+         _cleanup_fclose_ FILE *f = NULL;
+-        char t[LINE_MAX], *c;
+ 
+         assert(fn);
+         assert(line);
+@@ -117,21 +117,7 @@ int read_one_line_file(const char *fn, char **line) {
+         if (!f)
+                 return -errno;
+ 
+-        if (!fgets(t, sizeof(t), f)) {
+-
+-                if (ferror(f))
+-                        return errno ? -errno : -EIO;
+-
+-                t[0] = 0;
+-        }
+-
+-        c = strdup(t);
+-        if (!c)
+-                return -ENOMEM;
+-        truncate_nl(c);
+-
+-        *line = c;
+-        return 0;
++        return read_line(f, LONG_LINE_MAX, line);
+ }
+ 
+ int read_full_stream(FILE *f, char **contents, size_t *size) {
diff --git a/SOURCES/0582-cgroup-util-replace-one-use-of-fgets-by-read_line.patch b/SOURCES/0582-cgroup-util-replace-one-use-of-fgets-by-read_line.patch
new file mode 100644
index 0000000..fa3a207
--- /dev/null
+++ b/SOURCES/0582-cgroup-util-replace-one-use-of-fgets-by-read_line.patch
@@ -0,0 +1,33 @@
+From cde797e980fac7f8b1aa35db3f65fc591b820d62 Mon Sep 17 00:00:00 2001
+From: Jan Synacek <jsynacek@redhat.com>
+Date: Thu, 23 Nov 2017 09:27:06 +0100
+Subject: [PATCH] cgroup-util: replace one use of fgets() by read_line()
+
+(cherry picked from commit 2351e44d3ed57b7a48b9e544a59c3b797ac4d216)
+
+Resolves: #1503106
+---
+ src/shared/cgroup-util.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/src/shared/cgroup-util.c b/src/shared/cgroup-util.c
+index f67b53b4d..4585450b3 100644
+--- a/src/shared/cgroup-util.c
++++ b/src/shared/cgroup-util.c
+@@ -1747,7 +1747,6 @@ CGroupControllerMask cg_mask_supported(void) {
+ 
+ int cg_kernel_controllers(Set *controllers) {
+         _cleanup_fclose_ FILE *f = NULL;
+-        char buf[LINE_MAX];
+         int r;
+ 
+         assert(controllers);
+@@ -1760,7 +1759,7 @@ int cg_kernel_controllers(Set *controllers) {
+         }
+ 
+         /* Ignore the header line */
+-        (void) fgets(buf, sizeof(buf), f);
++        (void) read_line(f, (size_t) -1, NULL);
+ 
+         for (;;) {
+                 char *controller;
diff --git a/SOURCES/0583-conf-parse-remove-4K-line-length-limit.patch b/SOURCES/0583-conf-parse-remove-4K-line-length-limit.patch
new file mode 100644
index 0000000..14853bf
--- /dev/null
+++ b/SOURCES/0583-conf-parse-remove-4K-line-length-limit.patch
@@ -0,0 +1,124 @@
+From beef22775206d99b06c95c9a015e1b17bf3e767f Mon Sep 17 00:00:00 2001
+From: Jan Synacek <jsynacek@redhat.com>
+Date: Thu, 23 Nov 2017 10:13:52 +0100
+Subject: [PATCH] conf-parse: remove 4K line length limit
+
+Let's use read_line() to solve our long line limitation.
+
+Fixes #3302.
+(cherry picked from commit e6dde451a51dc5aaa7f4d98d39b8fe735f73d2af)
+
+Resolves: #1503106
+---
+ src/shared/conf-parser.c | 50 +++++++++++++++++++++++++++++++++++-------------
+ src/shared/utf8.h        |  1 +
+ 2 files changed, 38 insertions(+), 13 deletions(-)
+
+diff --git a/src/shared/conf-parser.c b/src/shared/conf-parser.c
+index 0b1af6c57..73e4d49ea 100644
+--- a/src/shared/conf-parser.c
++++ b/src/shared/conf-parser.c
+@@ -28,6 +28,8 @@
+ 
+ #include "conf-parser.h"
+ #include "conf-files.h"
++#include "def.h"
++#include "fileio.h"
+ #include "util.h"
+ #include "macro.h"
+ #include "strv.h"
+@@ -339,7 +341,7 @@ int config_parse(const char *unit,
+         _cleanup_free_ char *section = NULL, *continuation = NULL;
+         _cleanup_fclose_ FILE *ours = NULL;
+         unsigned line = 0, section_line = 0;
+-        bool section_ignored = false;
++        bool section_ignored = false, allow_bom = true;
+         int r;
+ 
+         assert(filename);
+@@ -359,21 +361,45 @@ int config_parse(const char *unit,
+ 
+         fd_warn_permissions(filename, fileno(f));
+ 
+-        while (!feof(f)) {
+-                char l[LINE_MAX], *p, *c = NULL, *e;
++        for (;;) {
++                _cleanup_free_ char *buf = NULL;
++                char *l, *p, *c = NULL, *e;
+                 bool escaped = false;
+ 
+-                if (!fgets(l, sizeof(l), f)) {
+-                        if (feof(f))
+-                                break;
++                r = read_line(f, LONG_LINE_MAX, &buf);
++                if (r == 0)
++                        break;
++                if (r == -ENOBUFS) {
++                        if (warn)
++                                log_error_errno(r, "%s:%u: Line too long", filename, line);
+ 
+-                        log_error_errno(errno, "Failed to read configuration file '%s': %m", filename);
+-                        return -errno;
++                        return r;
++                }
++                if (r < 0) {
++                        if (warn)
++                                log_error_errno(r, "%s:%u: Error while reading configuration file: %m", filename, line);
++
++                        return r;
+                 }
+ 
+-                truncate_nl(l);
++                l = buf;
++                if (allow_bom) {
++                        char *q;
++
++                        q = startswith(buf, UTF8_BYTE_ORDER_MARK);
++                        if (q) {
++                                l = q;
++                                allow_bom = false;
++                        }
++                }
+ 
+                 if (continuation) {
++                        if (strlen(continuation) + strlen(l) > LONG_LINE_MAX) {
++                                if (warn)
++                                        log_error("%s:%u: Continuation line too long", filename, line);
++                                return -ENOBUFS;
++                        }
++
+                         c = strappend(continuation, l);
+                         if (!c) {
+                                 if (warn)
+@@ -381,8 +407,7 @@ int config_parse(const char *unit,
+                                 return -ENOMEM;
+                         }
+ 
+-                        free(continuation);
+-                        continuation = NULL;
++                        continuation = mfree(continuation);
+                         p = c;
+                 } else
+                         p = l;
+@@ -428,8 +453,7 @@ int config_parse(const char *unit,
+ 
+                 if (r < 0) {
+                         if (warn)
+-                                log_warning_errno(r, "Failed to parse file '%s': %m",
+-                                                  filename);
++                                log_warning_errno(r, "%s:%u: Failed to parse file: %m", filename, line);
+                         return r;
+                 }
+         }
+diff --git a/src/shared/utf8.h b/src/shared/utf8.h
+index 77f663438..d31737061 100644
+--- a/src/shared/utf8.h
++++ b/src/shared/utf8.h
+@@ -26,6 +26,7 @@
+ #include "macro.h"
+ 
+ #define UTF8_REPLACEMENT_CHARACTER "\xef\xbf\xbd"
++#define UTF8_BYTE_ORDER_MARK "\xef\xbb\xbf"
+ 
+ const char *utf8_is_valid(const char *s) _pure_;
+ char *ascii_is_valid(const char *s) _pure_;
diff --git a/SOURCES/0584-test-conf-parser-add-tests-for-config-parser.patch b/SOURCES/0584-test-conf-parser-add-tests-for-config-parser.patch
new file mode 100644
index 0000000..1ee34f3
--- /dev/null
+++ b/SOURCES/0584-test-conf-parser-add-tests-for-config-parser.patch
@@ -0,0 +1,204 @@
+From 75fa3b2c5f62dd6d55860aaea979289d53b62a24 Mon Sep 17 00:00:00 2001
+From: Jan Synacek <jsynacek@redhat.com>
+Date: Thu, 23 Nov 2017 09:58:11 +0100
+Subject: [PATCH] test-conf-parser: add tests for config parser
+
+Add some basic tests for config_parse(). Add tests for the new long lines,
+including overflow.
+
+(cherry picked from commit e3f46367f577f8bd4b3a62ea0149bdcb112da573)
+(cherry picked from commit 8f313f4febb4df13279aaae86c846bbb142a5a39)
+
+Resolves: #1503106
+---
+ Makefile.am                 |   7 ++
+ src/test/test-conf-parser.c | 155 ++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 162 insertions(+)
+ create mode 100644 src/test/test-conf-parser.c
+
+diff --git a/Makefile.am b/Makefile.am
+index c4a96e1fd..8c73326fa 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -1416,6 +1416,7 @@ tests += \
+ 	test-socket-util \
+ 	test-fdset \
+ 	test-conf-files \
++	test-conf-parser \
+ 	test-capability \
+ 	test-async \
+ 	test-ratelimit \
+@@ -2041,6 +2042,12 @@ test_conf_files_SOURCES = \
+ test_conf_files_LDADD = \
+ 	libsystemd-shared.la
+ 
++test_conf_parser_SOURCES = \
++        src/test/test-conf-parser.c
++
++test_conf_parser_LDADD = \
++	libsystemd-shared.la
++
+ # ------------------------------------------------------------------------------
+ ## .PHONY so it always rebuilds it
+ .PHONY: coverage lcov-run lcov-report coverage-sync
+diff --git a/src/test/test-conf-parser.c b/src/test/test-conf-parser.c
+new file mode 100644
+index 000000000..4052d0095
+--- /dev/null
++++ b/src/test/test-conf-parser.c
+@@ -0,0 +1,155 @@
++/***
++  This file is part of systemd.
++
++  Copyright 2015 Ronny Chevalier
++
++  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.
++
++  systemd is distributed in the hope that it will be useful, but
++  WITHOUT ANY WARRANTY; without even the implied warranty of
++  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++  Lesser General Public License for more details.
++
++  You should have received a copy of the GNU Lesser General Public License
++  along with systemd; If not, see <http://www.gnu.org/licenses/>.
++***/
++
++#include "conf-parser.h"
++#include "fileio.h"
++#include "log.h"
++#include "macro.h"
++#include "strv.h"
++#include "util.h"
++
++#define x10(x) x x x x x x x x x x
++#define x100(x) x10(x10(x))
++#define x1000(x) x10(x100(x))
++
++static const char* const config_file[] = {
++        "[Section]\n"
++        "setting1=1\n",
++
++        "[Section]\n"
++        "setting1=1",        /* no terminating newline */
++
++        "\n\n\n\n[Section]\n\n\n"
++        "setting1=1",        /* some whitespace, no terminating newline */
++
++        "[Section]\n"
++        "[Section]\n"
++        "setting1=1\n"
++        "setting1=2\n"
++        "setting1=1\n",      /* repeated settings */
++
++        "[Section]\n"
++        "setting1=1\\\n"     /* normal continuation */
++        "2\\\n"
++        "3\n",
++
++        "[Section]\n"
++        "setting1=1\\\\\\\n" /* continuation with trailing escape symbols */
++        "\\\\2\n",           /* note that C requires one level of escaping, so the
++                              * parser gets "…1 BS BS BS NL BS BS 2 NL", which
++                              * it translates into "…1 BS BS SP BS BS 2" */
++
++        "\n[Section]\n\n"
++        "setting1="          /* a line above LINE_MAX length */
++        x1000("ABCD")
++        "\n",
++
++        "[Section]\n"
++        "setting1="          /* a line above LINE_MAX length, with continuation */
++        x1000("ABCD") "\\\n"
++        "foobar",
++
++        "[Section]\n"
++        "setting1="          /* a line above the allowed limit: 9 + 1050000 + 1 */
++        x1000(x1000("x") x10("abcde")) "\n",
++
++        "[Section]\n"
++        "setting1="          /* many continuation lines, together above the limit */
++        x1000(x1000("x") x10("abcde") "\\\n") "xxx",
++};
++
++static void test_config_parse(unsigned i, const char *s) {
++        char name[] = "/tmp/test-conf-parser.XXXXXX";
++        int fd, r;
++        _cleanup_fclose_ FILE *f = NULL;
++        _cleanup_free_ char *setting1 = NULL;
++
++        const ConfigTableItem items[] = {
++                { "Section", "setting1",  config_parse_string,   0, &setting1},
++                {}
++        };
++
++        log_info("== %s[%i] ==", __func__, i);
++
++        fd = mkostemp_safe(name, O_CLOEXEC);
++        assert_se(fd >= 0);
++        assert_se((size_t) write(fd, s, strlen(s)) == strlen(s));
++
++        assert_se(lseek(fd, 0, SEEK_SET) == 0);
++        assert_se(f = fdopen(fd, "r"));
++
++        /*
++        int config_parse(const char *unit,
++                         const char *filename,
++                         FILE *f,
++                         const char *sections,
++                         ConfigItemLookup lookup,
++                         const void *table,
++                         bool relaxed,
++                         bool allow_include,
++                         bool warn,
++                         void *userdata)
++        */
++
++        r = config_parse(NULL, name, f,
++                         "Section\0",
++                         config_item_table_lookup, items,
++                         false, false, true, NULL);
++
++        switch (i) {
++        case 0 ... 3:
++                assert_se(r == 0);
++                assert_se(streq(setting1, "1"));
++                break;
++
++        case 4:
++                assert_se(r == 0);
++                assert_se(streq(setting1, "1 2 3"));
++                break;
++
++        case 5:
++                assert_se(r == 0);
++                assert_se(streq(setting1, "1\\\\ \\\\2"));
++                break;
++
++        case 6:
++                assert_se(r == 0);
++                assert_se(streq(setting1, x1000("ABCD")));
++                break;
++
++        case 7:
++                assert_se(r == 0);
++                assert_se(streq(setting1, x1000("ABCD") " foobar"));
++                break;
++
++        case 8 ... 9:
++                assert_se(r == -ENOBUFS);
++                assert_se(setting1 == NULL);
++                break;
++        }
++}
++
++int main(int argc, char **argv) {
++        unsigned i;
++
++        for (i = 0; i < ELEMENTSOF(config_file); i++)
++                test_config_parse(i, config_file[i]);
++
++        return 0;
++}
diff --git a/SOURCES/0585-fileio-use-_cleanup_-for-FILE-unlocking.patch b/SOURCES/0585-fileio-use-_cleanup_-for-FILE-unlocking.patch
new file mode 100644
index 0000000..726ccaf
--- /dev/null
+++ b/SOURCES/0585-fileio-use-_cleanup_-for-FILE-unlocking.patch
@@ -0,0 +1,103 @@
+From d750826683aaad1cf33b16290c7daa8b0a669f4c Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
+Date: Sat, 23 Sep 2017 10:48:09 +0200
+Subject: [PATCH] fileio: use _cleanup_ for FILE unlocking
+
+(cherry picked from commit f858e5148e4f36335555dfaac812197ebd3ef036)
+
+Resolves: #1503106
+---
+ src/shared/fileio.c | 57 +++++++++++++++++++++++++----------------------------
+ 1 file changed, 27 insertions(+), 30 deletions(-)
+
+diff --git a/src/shared/fileio.c b/src/shared/fileio.c
+index be775f982..4880a4941 100644
+--- a/src/shared/fileio.c
++++ b/src/shared/fileio.c
+@@ -802,10 +802,13 @@ int get_status_field(const char *filename, const char *pattern, char **field) {
+         return 0;
+ }
+ 
++static inline void funlockfilep(FILE **f) {
++        funlockfile(*f);
++}
++
+ int read_line(FILE *f, size_t limit, char **ret) {
+         _cleanup_free_ char *buffer = NULL;
+         size_t n = 0, allocated = 0, count = 0;
+-        int r;
+ 
+         assert(f);
+ 
+@@ -827,48 +830,42 @@ int read_line(FILE *f, size_t limit, char **ret) {
+                         return -ENOMEM;
+         }
+ 
+-        flockfile(f);
++        {
++                _cleanup_(funlockfilep) FILE *flocked = f;
++                flockfile(f);
+ 
+-        for (;;) {
+-                int c;
++                for (;;) {
++                        int c;
+ 
+-                if (n >= limit) {
+-                        funlockfile(f);
+-                        return -ENOBUFS;
+-                }
++                        if (n >= limit)
++                                return -ENOBUFS;
++
++                        errno = 0;
++                        c = fgetc_unlocked(f);
++                        if (c == EOF) {
++                                /* if we read an error, and have no data to return, then propagate the error */
++                                if (ferror_unlocked(f) && n == 0)
++                                        return errno > 0 ? -errno : -EIO;
+ 
+-                errno = 0;
+-                c = fgetc_unlocked(f);
+-                if (c == EOF) {
+-                        /* if we read an error, and have no data to return, then propagate the error */
+-                        if (ferror_unlocked(f) && n == 0) {
+-                                r = errno > 0 ? -errno : -EIO;
+-                                funlockfile(f);
+-                                return r;
++                                break;
+                         }
+ 
+-                        break;
+-                }
++                        count++;
+ 
+-                count++;
++                        if (IN_SET(c, '\n', 0)) /* Reached a delimiter */
++                                break;
+ 
+-                if (IN_SET(c, '\n', 0)) /* Reached a delimiter */
+-                        break;
++                        if (ret) {
++                                if (!GREEDY_REALLOC(buffer, allocated, n + 2))
++                                        return -ENOMEM;
+ 
+-                if (ret) {
+-                        if (!GREEDY_REALLOC(buffer, allocated, n + 2)) {
+-                                funlockfile(f);
+-                                return -ENOMEM;
++                                buffer[n] = (char) c;
+                         }
+ 
+-                        buffer[n] = (char) c;
++                        n++;
+                 }
+-
+-                n++;
+         }
+ 
+-        funlockfile(f);
+-
+         if (ret) {
+                 buffer[n] = 0;
+ 
diff --git a/SOURCES/0586-test-fileio-also-test-read_line-with-actual-files.patch b/SOURCES/0586-test-fileio-also-test-read_line-with-actual-files.patch
new file mode 100644
index 0000000..b89c611
--- /dev/null
+++ b/SOURCES/0586-test-fileio-also-test-read_line-with-actual-files.patch
@@ -0,0 +1,105 @@
+From 4a0e2c447eeac47eaa497a2db6925590b3cec3bd Mon Sep 17 00:00:00 2001
+From: Jan Synacek <jsynacek@redhat.com>
+Date: Thu, 23 Nov 2017 11:42:05 +0100
+Subject: [PATCH] test-fileio: also test read_line() with actual files
+
+Just in case the real FILE and the one from fmemopen weren't exactly
+the same.
+
+(cherry picked from commit 2c9de13912350f5887ccccdae9e1707512208053)
+
+Resolves: #1503106
+---
+ src/test/test-fileio.c | 63 ++++++++++++++++++++++++++++++++++++++++----------
+ 1 file changed, 51 insertions(+), 12 deletions(-)
+
+diff --git a/src/test/test-fileio.c b/src/test/test-fileio.c
+index fc5969322..791bfc97b 100644
+--- a/src/test/test-fileio.c
++++ b/src/test/test-fileio.c
+@@ -392,20 +392,17 @@ static void test_load_env_file_pairs(void) {
+         unlink(fn);
+ }
+ 
+-static void test_read_line(void) {
+-        _cleanup_fclose_ FILE *f = NULL;
+-        _cleanup_free_ char *line = NULL;
+ 
+-        char buffer[] =
+-                "Some test data\n"
+-                "With newlines, and a NUL byte\0"
+-                "\n"
+-                "an empty line\n"
+-                "an ignored line\n"
+-                "and a very long line that is supposed to be truncated, because it is so long\n";
++static const char buffer[] =
++        "Some test data\n"
++        "With newlines, and a NUL byte\0"
++        "\n"
++        "an empty line\n"
++        "an ignored line\n"
++        "and a very long line that is supposed to be truncated, because it is so long\n";
+ 
+-        f = fmemopen(buffer, sizeof(buffer), "re");
+-        assert_se(f);
++static void test_read_line_one_file(FILE *f) {
++        _cleanup_free_ char *line = NULL;
+ 
+         assert_se(read_line(f, (size_t) -1, &line) == 15 && streq(line, "Some test data"));
+         line = mfree(line);
+@@ -435,6 +432,46 @@ static void test_read_line(void) {
+         assert_se(read_line(f, 1024, &line) == 0 && streq(line, ""));
+ }
+ 
++static void test_read_line(void) {
++        _cleanup_fclose_ FILE *f = NULL;
++        _cleanup_free_ char *line = NULL;
++
++        f = fmemopen((void*) buffer, sizeof(buffer), "re");
++        assert_se(f);
++
++        test_read_line_one_file(f);
++}
++
++static void test_read_line2(void) {
++        char name[] = "/tmp/test-fileio.XXXXXX";
++        int fd;
++        _cleanup_fclose_ FILE *f = NULL;
++
++        fd = mkostemp_safe(name, O_CLOEXEC);
++        assert_se(fd >= 0);
++        assert_se((size_t) write(fd, buffer, sizeof(buffer)) == sizeof(buffer));
++
++        assert_se(lseek(fd, 0, SEEK_SET) == 0);
++        assert_se(f = fdopen(fd, "r"));
++
++        test_read_line_one_file(f);
++}
++
++static void test_read_line3(void) {
++        _cleanup_fclose_ FILE *f = NULL;
++        _cleanup_free_ char *line = NULL;
++        int r;
++
++        f = fopen("/proc/cmdline", "re");
++        if (!f && IN_SET(errno, ENOENT, EPERM))
++                return;
++        assert_se(f);
++
++        r = read_line(f, LINE_MAX, &line);
++        assert_se((size_t) r == strlen(line) + 1);
++        assert_se(read_line(f, LINE_MAX, NULL) == 0);
++}
++
+ int main(int argc, char *argv[]) {
+         log_parse_environment();
+         log_open();
+@@ -449,6 +486,8 @@ int main(int argc, char *argv[]) {
+         test_write_string_file_no_create();
+         test_load_env_file_pairs();
+         test_read_line();
++        test_read_line2();
++        test_read_line3();
+ 
+         return 0;
+ }
diff --git a/SOURCES/0587-fileio-return-0-from-read_one_line_file-on-success.patch b/SOURCES/0587-fileio-return-0-from-read_one_line_file-on-success.patch
new file mode 100644
index 0000000..35fdb0b
--- /dev/null
+++ b/SOURCES/0587-fileio-return-0-from-read_one_line_file-on-success.patch
@@ -0,0 +1,36 @@
+From 29d296bbe3ce769d64f90a08ba0e091725140704 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
+Date: Sun, 24 Sep 2017 14:27:21 +0200
+Subject: [PATCH] fileio: return 0 from read_one_line_file on success
+
+Fixup for f4b51a2d09. Suggested by Evgeny Vereshchagin.
+
+(cherry picked from commit 2e33df93dee35af986683d1226f93e0f9659de5d)
+
+Resolves: #1503106
+---
+ src/shared/fileio.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/src/shared/fileio.c b/src/shared/fileio.c
+index 4880a4941..65a0753c2 100644
+--- a/src/shared/fileio.c
++++ b/src/shared/fileio.c
+@@ -109,6 +109,7 @@ int write_string_file_atomic(const char *fn, const char *line) {
+ 
+ int read_one_line_file(const char *fn, char **line) {
+         _cleanup_fclose_ FILE *f = NULL;
++        int r;
+ 
+         assert(fn);
+         assert(line);
+@@ -117,7 +118,8 @@ int read_one_line_file(const char *fn, char **line) {
+         if (!f)
+                 return -errno;
+ 
+-        return read_line(f, LONG_LINE_MAX, line);
++        r = read_line(f, LONG_LINE_MAX, line);
++        return r < 0 ? r : 0;
+ }
+ 
+ int read_full_stream(FILE *f, char **contents, size_t *size) {
diff --git a/SOURCES/0588-man-fix-description-of-force-in-halt-8-7392.patch b/SOURCES/0588-man-fix-description-of-force-in-halt-8-7392.patch
new file mode 100644
index 0000000..c6309e0
--- /dev/null
+++ b/SOURCES/0588-man-fix-description-of-force-in-halt-8-7392.patch
@@ -0,0 +1,33 @@
+From fa011f2b4e6339f6672835712cb7b281e0603207 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
+Date: Mon, 20 Nov 2017 14:27:46 +0100
+Subject: [PATCH] man: fix description of --force in halt(8) (#7392)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1449751
+(cherry picked from commit 5d9adb5b60b815b477ba9e6b19ef0fd7e1854a38)
+
+Resolves: #1515130
+---
+ man/halt.xml | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/man/halt.xml b/man/halt.xml
+index a06dbd009..d0fc25c20 100644
+--- a/man/halt.xml
++++ b/man/halt.xml
+@@ -112,8 +112,13 @@
+         <term><option>-f</option></term>
+         <term><option>--force</option></term>
+ 
+-        <listitem><para>Force immediate halt, power-off, reboot. Do
+-        not contact the init system.</para></listitem>
++        <listitem><para>Force immediate halt, power-off, or reboot. When
++        specified once, this results in an immediate but clean shutdown
++        by the system manager. When specified twice, this results in an
++        immediate shutdown without contacting the system manager. See the
++        description of <option>--force</option> in
++        <citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
++        for more details.</para></listitem>
+       </varlistentry>
+ 
+       <varlistentry>
diff --git a/SOURCES/0589-journal-return-better-error-for-empty-files.patch b/SOURCES/0589-journal-return-better-error-for-empty-files.patch
new file mode 100644
index 0000000..8210792
--- /dev/null
+++ b/SOURCES/0589-journal-return-better-error-for-empty-files.patch
@@ -0,0 +1,32 @@
+From fcef41057f40008693dd9161c973c2c6117e1433 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
+Date: Sun, 25 Oct 2015 00:09:44 -0400
+Subject: [PATCH] journal: return better error for empty files
+
+When reading stuff, we should only return EIO when an actual read error
+occured, not when we don't like the data for whatever reason.
+
+We already return ENODATA for all other kinds of file truncation, hence
+do the same for the most obvious kind, so that callers know what ENODATA
+means.
+
+(cherry picked from commit cfb571f30fd415304b2f674f1615dc861058c347)
+
+Related: #1465759
+---
+ src/journal/journal-file.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c
+index ebc8e6230..2bb3a9757 100644
+--- a/src/journal/journal-file.c
++++ b/src/journal/journal-file.c
+@@ -2693,7 +2693,7 @@ int journal_file_open(
+         }
+ 
+         if (f->last_stat.st_size < (off_t) HEADER_SIZE_MIN) {
+-                r = -EIO;
++                r = -ENODATA;
+                 goto fail;
+         }
+ 
diff --git a/SOURCES/0590-journalctl-continue-operation-even-if-we-run-into-an.patch b/SOURCES/0590-journalctl-continue-operation-even-if-we-run-into-an.patch
new file mode 100644
index 0000000..e2c0f6f
--- /dev/null
+++ b/SOURCES/0590-journalctl-continue-operation-even-if-we-run-into-an.patch
@@ -0,0 +1,35 @@
+From d5a96e0d5fccfa2f0c31df4ef5637717acd1fa9d Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Mon, 2 Nov 2015 23:13:01 +0100
+Subject: [PATCH] journalctl: continue operation, even if we run into an
+ invalid file
+
+(cherry picked from commit 4f52b822b05c373f40fea1a41ae3ade5d5ff558e)
+
+Related: #1465759
+---
+ src/journal/journalctl.c | 7 ++-----
+ 1 file changed, 2 insertions(+), 5 deletions(-)
+
+diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
+index c771cff8b..8c8379732 100644
+--- a/src/journal/journalctl.c
++++ b/src/journal/journalctl.c
+@@ -1804,15 +1804,12 @@ static int access_check(sd_journal *j) {
+         SET_FOREACH(code, j->errors, it) {
+                 int err;
+ 
+-                err = -PTR_TO_INT(code);
+-                assert(err > 0);
++                err = abs(PTR_TO_INT(code));
+ 
+                 if (err == EACCES)
+                         continue;
+ 
+-                log_warning_errno(err, "Error was encountered while opening journal files: %m");
+-                if (r == 0)
+-                        r = -err;
++                log_warning_errno(err, "An error was encountered while opening journal files, ignoring: %m");
+         }
+ 
+         return r;
diff --git a/SOURCES/0591-journal-remove-error-check-that-never-happens.patch b/SOURCES/0591-journal-remove-error-check-that-never-happens.patch
new file mode 100644
index 0000000..1e8f057
--- /dev/null
+++ b/SOURCES/0591-journal-remove-error-check-that-never-happens.patch
@@ -0,0 +1,53 @@
+From 2b7119bc5e1a62d1bb6cb6ac0e4239345b9f8691 Mon Sep 17 00:00:00 2001
+From: Thomas Hindoe Paaboel Andersen <phomes@gmail.com>
+Date: Fri, 14 Aug 2015 23:40:27 +0200
+Subject: [PATCH] journal: remove error check that never happens
+
+remove_directory will always return 0 so this can never happen.
+Besides that, d->path and d are freed so we would end up with
+a null pointer dereference anyway.
+
+(cherry picked from commit b2b46f91dbb71676cb981907c68521e4b1e80af1)
+
+Related: #1465759
+---
+ src/journal/sd-journal.c | 12 +++---------
+ 1 file changed, 3 insertions(+), 9 deletions(-)
+
+diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c
+index 72f312b67..3749f9e89 100644
+--- a/src/journal/sd-journal.c
++++ b/src/journal/sd-journal.c
+@@ -1487,7 +1487,7 @@ static int add_root_directory(sd_journal *j, const char *p) {
+         return 0;
+ }
+ 
+-static int remove_directory(sd_journal *j, Directory *d) {
++static void remove_directory(sd_journal *j, Directory *d) {
+         assert(j);
+ 
+         if (d->wd > 0) {
+@@ -1506,8 +1506,6 @@ static int remove_directory(sd_journal *j, Directory *d) {
+ 
+         free(d->path);
+         free(d);
+-
+-        return 0;
+ }
+ 
+ static int add_search_paths(sd_journal *j) {
+@@ -2145,12 +2143,8 @@ static void process_inotify_event(sd_journal *j, struct inotify_event *e) {
+ 
+                         /* Event for a subdirectory */
+ 
+-                        if (e->mask & (IN_DELETE_SELF|IN_MOVE_SELF|IN_UNMOUNT)) {
+-                                r = remove_directory(j, d);
+-                                if (r < 0)
+-                                        log_debug_errno(r, "Failed to remove directory %s: %m", d->path);
+-                        }
+-
++                        if (e->mask & (IN_DELETE_SELF|IN_MOVE_SELF|IN_UNMOUNT))
++                                remove_directory(j, d);
+ 
+                 } else if (d->is_root && (e->mask & IN_ISDIR) && e->len > 0 && sd_id128_from_string(e->name, &id) >= 0) {
+ 
diff --git a/SOURCES/0592-sd-journal-various-clean-ups-and-modernizations.patch b/SOURCES/0592-sd-journal-various-clean-ups-and-modernizations.patch
new file mode 100644
index 0000000..fb8c700
--- /dev/null
+++ b/SOURCES/0592-sd-journal-various-clean-ups-and-modernizations.patch
@@ -0,0 +1,503 @@
+From 6930375c3f0d9681f27b42f1d0406721c3f9a013 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Mon, 2 Nov 2015 23:14:30 +0100
+Subject: [PATCH] sd-journal: various clean-ups and modernizations
+
+- Always print a debug log message about files and directories we cannot
+  open right when it happens instead of the caller, thus reducing the
+  number of places where we need to generate the debug message.
+
+- Always push the errors we encounter immediately into the error set,
+  when we run into them, instead of in the caller. Thus, we never forget
+  to push them in.
+
+- Use stack instead of heap memory where we can.
+
+- Make remove_file() void, since it cannot fail anyway and always
+  returned 0.
+
+- Make local machine check of journal directories explicit in a
+  function, to make things more readable.
+
+- Port to all directory listing loops FOREACH_DIRENT_ALL()
+
+- sd-daemon is library code, hence never log at higher log levels than
+  LOG_DEBUG.
+
+(cherry picked from commit d617408ecbe69db69aefddfcb10a6c054ea46ba0)
+
+Related: #1465759
+---
+ src/journal/sd-journal.c | 242 ++++++++++++++++++++++-------------------------
+ 1 file changed, 111 insertions(+), 131 deletions(-)
+
+diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c
+index 3749f9e89..9895d9608 100644
+--- a/src/journal/sd-journal.c
++++ b/src/journal/sd-journal.c
+@@ -1171,6 +1171,8 @@ static bool file_has_type_prefix(const char *prefix, const char *filename) {
+ }
+ 
+ static bool file_type_wanted(int flags, const char *filename) {
++        assert(filename);
++
+         if (!endswith(filename, ".journal") && !endswith(filename, ".journal~"))
+                 return false;
+ 
+@@ -1195,7 +1197,7 @@ static bool file_type_wanted(int flags, const char *filename) {
+ 
+ static int add_any_file(sd_journal *j, const char *path) {
+         JournalFile *f = NULL;
+-        int r;
++        int r, k;
+ 
+         assert(j);
+         assert(path);
+@@ -1204,20 +1206,23 @@ static int add_any_file(sd_journal *j, const char *path) {
+                 return 0;
+ 
+         if (ordered_hashmap_size(j->files) >= JOURNAL_FILES_MAX) {
+-                log_warning("Too many open journal files, not adding %s.", path);
+-                return set_put_error(j, -ETOOMANYREFS);
++                log_debug("Too many open journal files, not adding %s.", path);
++                r = -ETOOMANYREFS;
++                goto fail;
+         }
+ 
+         r = journal_file_open(path, O_RDONLY, 0, false, false, NULL, j->mmap, NULL, &f);
+-        if (r < 0)
+-                return r;
++        if (r < 0) {
++                log_debug_errno(r, "Failed to open journal file %s: %m", path);
++                goto fail;
++        }
+ 
+         /* journal_file_dump(f); */
+ 
+         r = ordered_hashmap_put(j->files, f->path, f);
+         if (r < 0) {
+                 journal_file_close(f);
+-                return r;
++                goto fail;
+         }
+ 
+         log_debug("File %s added.", f->path);
+@@ -1227,10 +1232,17 @@ static int add_any_file(sd_journal *j, const char *path) {
+         j->current_invalidate_counter ++;
+ 
+         return 0;
++
++fail:
++        k = set_put_error(j, r);
++        if (k < 0)
++                return k;
++
++        return r;
+ }
+ 
+ static int add_file(sd_journal *j, const char *prefix, const char *filename) {
+-        char *path = NULL;
++        const char *path;
+ 
+         assert(j);
+         assert(prefix);
+@@ -1250,24 +1262,20 @@ static int add_file(sd_journal *j, const char *prefix, const char *filename) {
+         return add_any_file(j, path);
+ }
+ 
+-static int remove_file(sd_journal *j, const char *prefix, const char *filename) {
+-        _cleanup_free_ char *path;
++static void remove_file(sd_journal *j, const char *prefix, const char *filename) {
++        const char *path;
+         JournalFile *f;
+ 
+         assert(j);
+         assert(prefix);
+         assert(filename);
+ 
+-        path = strjoin(prefix, "/", filename, NULL);
+-        if (!path)
+-                return -ENOMEM;
+-
++        path = strjoina(prefix, "/", filename);
+         f = ordered_hashmap_get(j->files, path);
+         if (!f)
+-                return 0;
++                return;
+ 
+         remove_file_real(j, f);
+-        return 0;
+ }
+ 
+ static void remove_file_real(sd_journal *j, JournalFile *f) {
+@@ -1296,12 +1304,27 @@ static void remove_file_real(sd_journal *j, JournalFile *f) {
+         j->current_invalidate_counter ++;
+ }
+ 
++static int dirname_is_machine_id(const char *fn) {
++        sd_id128_t id, machine;
++        int r;
++
++        r = sd_id128_get_machine(&machine);
++        if (r < 0)
++                return r;
++
++        r = sd_id128_from_string(fn, &id);
++        if (r < 0)
++                return r;
++
++        return sd_id128_equal(id, machine);
++}
++
+ static int add_directory(sd_journal *j, const char *prefix, const char *dirname) {
+         _cleanup_free_ char *path = NULL;
+-        int r;
+         _cleanup_closedir_ DIR *d = NULL;
+-        sd_id128_t id, mid;
++        struct dirent *de = NULL;
+         Directory *m;
++        int r, k;
+ 
+         assert(j);
+         assert(prefix);
+@@ -1310,35 +1333,36 @@ static int add_directory(sd_journal *j, const char *prefix, const char *dirname)
+         log_debug("Considering %s/%s.", prefix, dirname);
+ 
+         if ((j->flags & SD_JOURNAL_LOCAL_ONLY) &&
+-            (sd_id128_from_string(dirname, &id) < 0 ||
+-             sd_id128_get_machine(&mid) < 0 ||
+-             !(sd_id128_equal(id, mid) || path_startswith(prefix, "/run"))))
++            !(dirname_is_machine_id(dirname) > 0 || path_startswith(prefix, "/run")))
+             return 0;
+ 
+         path = strjoin(prefix, "/", dirname, NULL);
+-        if (!path)
+-                return -ENOMEM;
++        if (!path) {
++                r = -ENOMEM;
++                goto fail;
++        }
+ 
+         d = opendir(path);
+         if (!d) {
+-                log_debug_errno(errno, "Failed to open %s: %m", path);
+-                if (errno == ENOENT)
+-                        return 0;
+-                return -errno;
++                r = log_debug_errno(errno, "Failed to open directory %s: %m", path);
++                goto fail;
+         }
+ 
+         m = hashmap_get(j->directories_by_path, path);
+         if (!m) {
+                 m = new0(Directory, 1);
+-                if (!m)
+-                        return -ENOMEM;
++                if (!m) {
++                        r = -ENOMEM;
++                        goto fail;
++                }
+ 
+                 m->is_root = false;
+                 m->path = path;
+ 
+                 if (hashmap_put(j->directories_by_path, m->path, m) < 0) {
+                         free(m);
+-                        return -ENOMEM;
++                        r = -ENOMEM;
++                        goto fail;
+                 }
+ 
+                 path = NULL; /* avoid freeing in cleanup */
+@@ -1360,41 +1384,30 @@ static int add_directory(sd_journal *j, const char *prefix, const char *dirname)
+                         inotify_rm_watch(j->inotify_fd, m->wd);
+         }
+ 
+-        for (;;) {
+-                struct dirent *de;
+-
+-                errno = 0;
+-                de = readdir(d);
+-                if (!de && errno != 0) {
+-                        r = -errno;
+-                        log_debug_errno(errno, "Failed to read directory %s: %m", m->path);
+-                        return r;
+-                }
+-                if (!de)
+-                        break;
++        FOREACH_DIRENT_ALL(de, d, return log_debug_errno(errno, "Failed to read directory %s: %m", m->path)) {
+ 
+                 if (dirent_is_file_with_suffix(de, ".journal") ||
+-                    dirent_is_file_with_suffix(de, ".journal~")) {
+-                        r = add_file(j, m->path, de->d_name);
+-                        if (r < 0) {
+-                                log_debug_errno(r, "Failed to add file %s/%s: %m",
+-                                                m->path, de->d_name);
+-                                r = set_put_error(j, r);
+-                                if (r < 0)
+-                                        return r;
+-                        }
+-                }
++                    dirent_is_file_with_suffix(de, ".journal~"))
++                        (void) add_file(j, m->path, de->d_name);
+         }
+ 
+         check_network(j, dirfd(d));
+ 
+         return 0;
++
++fail:
++        k = set_put_error(j, r);
++        if (k < 0)
++                return k;
++
++        return r;
+ }
+ 
+-static int add_root_directory(sd_journal *j, const char *p) {
++static int add_root_directory(sd_journal *j, const char *p, bool missing_ok) {
+         _cleanup_closedir_ DIR *d = NULL;
++        struct dirent *de;
+         Directory *m;
+-        int r;
++        int r, k;
+ 
+         assert(j);
+         assert(p);
+@@ -1407,26 +1420,35 @@ static int add_root_directory(sd_journal *j, const char *p) {
+                 p = strjoina(j->prefix, p);
+ 
+         d = opendir(p);
+-        if (!d)
+-                return -errno;
++        if (!d) {
++                if (errno == ENOENT && missing_ok)
++                        return 0;
++
++                r = log_debug_errno(errno, "Failed to open root directory %s: %m", p);
++                goto fail;
++        }
+ 
+         m = hashmap_get(j->directories_by_path, p);
+         if (!m) {
+                 m = new0(Directory, 1);
+-                if (!m)
+-                        return -ENOMEM;
++                if (!m) {
++                        r = -ENOMEM;
++                        goto fail;
++                }
+ 
+                 m->is_root = true;
+                 m->path = strdup(p);
+                 if (!m->path) {
+                         free(m);
+-                        return -ENOMEM;
++                        r = -ENOMEM;
++                        goto fail;
+                 }
+ 
+                 if (hashmap_put(j->directories_by_path, m->path, m) < 0) {
+                         free(m->path);
+                         free(m);
+-                        return -ENOMEM;
++                        r = -ENOMEM;
++                        goto fail;
+                 }
+ 
+                 j->current_invalidate_counter ++;
+@@ -1449,42 +1471,27 @@ static int add_root_directory(sd_journal *j, const char *p) {
+         if (j->no_new_files)
+                 return 0;
+ 
+-        for (;;) {
+-                struct dirent *de;
++        FOREACH_DIRENT_ALL(de, d, return log_debug_errno(errno, "Failed to read directory %s: %m", m->path)) {
+                 sd_id128_t id;
+ 
+-                errno = 0;
+-                de = readdir(d);
+-                if (!de && errno != 0) {
+-                        r = -errno;
+-                        log_debug_errno(errno, "Failed to read directory %s: %m", m->path);
+-                        return r;
+-                }
+-                if (!de)
+-                        break;
+-
+                 if (dirent_is_file_with_suffix(de, ".journal") ||
+-                    dirent_is_file_with_suffix(de, ".journal~")) {
+-                        r = add_file(j, m->path, de->d_name);
+-                        if (r < 0) {
+-                                log_debug_errno(r, "Failed to add file %s/%s: %m",
+-                                                m->path, de->d_name);
+-                                r = set_put_error(j, r);
+-                                if (r < 0)
+-                                        return r;
+-                        }
+-                } else if ((de->d_type == DT_DIR || de->d_type == DT_LNK || de->d_type == DT_UNKNOWN) &&
+-                           sd_id128_from_string(de->d_name, &id) >= 0) {
+-
+-                        r = add_directory(j, m->path, de->d_name);
+-                        if (r < 0)
+-                                log_debug_errno(r, "Failed to add directory %s/%s: %m", m->path, de->d_name);
+-                }
++                    dirent_is_file_with_suffix(de, ".journal~"))
++                        (void) add_file(j, m->path, de->d_name);
++                else if (IN_SET(de->d_type, DT_DIR, DT_LNK, DT_UNKNOWN) &&
++                         sd_id128_from_string(de->d_name, &id) >= 0)
++                        (void) add_directory(j, m->path, de->d_name);
+         }
+ 
+         check_network(j, dirfd(d));
+ 
+         return 0;
++
++fail:
++        k = set_put_error(j, r);
++        if (k < 0)
++                return k;
++
++        return r;
+ }
+ 
+ static void remove_directory(sd_journal *j, Directory *d) {
+@@ -1509,8 +1516,8 @@ static void remove_directory(sd_journal *j, Directory *d) {
+ }
+ 
+ static int add_search_paths(sd_journal *j) {
+-        int r;
+-        const char search_paths[] =
++
++        static const char search_paths[] =
+                 "/run/log/journal\0"
+                 "/var/log/journal\0";
+         const char *p;
+@@ -1520,14 +1527,8 @@ static int add_search_paths(sd_journal *j) {
+         /* We ignore most errors here, since the idea is to only open
+          * what's actually accessible, and ignore the rest. */
+ 
+-        NULSTR_FOREACH(p, search_paths) {
+-                r = add_root_directory(j, p);
+-                if (r < 0 && r != -ENOENT) {
+-                        r = set_put_error(j, r);
+-                        if (r < 0)
+-                                return r;
+-                }
+-        }
++        NULSTR_FOREACH(p, search_paths)
++                (void) add_root_directory(j, p, true);
+ 
+         return 0;
+ }
+@@ -1551,17 +1552,14 @@ static int add_current_paths(sd_journal *j) {
+                 if (!dir)
+                         return -ENOMEM;
+ 
+-                r = add_root_directory(j, dir);
+-                if (r < 0) {
+-                        set_put_error(j, r);
++                r = add_root_directory(j, dir, true);
++                if (r < 0)
+                         return r;
+-                }
+         }
+ 
+         return 0;
+ }
+ 
+-
+ static int allocate_inotify(sd_journal *j) {
+         assert(j);
+ 
+@@ -1689,11 +1687,9 @@ _public_ int sd_journal_open_directory(sd_journal **ret, const char *path, int f
+         if (!j)
+                 return -ENOMEM;
+ 
+-        r = add_root_directory(j, path);
+-        if (r < 0) {
+-                set_put_error(j, r);
++        r = add_root_directory(j, path, false);
++        if (r < 0)
+                 goto fail;
+-        }
+ 
+         *ret = j;
+         return 0;
+@@ -1718,10 +1714,8 @@ _public_ int sd_journal_open_files(sd_journal **ret, const char **paths, int fla
+ 
+         STRV_FOREACH(path, paths) {
+                 r = add_any_file(j, *path);
+-                if (r < 0) {
+-                        log_error_errno(r, "Failed to open %s: %m", *path);
++                if (r < 0)
+                         goto fail;
+-                }
+         }
+ 
+         j->no_new_files = true;
+@@ -2061,7 +2055,7 @@ _public_ int sd_journal_get_fd(sd_journal *j) {
+         if (j->no_new_files)
+                 r = add_current_paths(j);
+         else if (j->path)
+-                r = add_root_directory(j, j->path);
++                r = add_root_directory(j, j->path, true);
+         else
+                 r = add_search_paths(j);
+         if (r < 0)
+@@ -2108,7 +2102,6 @@ _public_ int sd_journal_get_timeout(sd_journal *j, uint64_t *timeout_usec) {
+ 
+ static void process_inotify_event(sd_journal *j, struct inotify_event *e) {
+         Directory *d;
+-        int r;
+ 
+         assert(j);
+         assert(e);
+@@ -2124,20 +2117,10 @@ static void process_inotify_event(sd_journal *j, struct inotify_event *e) {
+ 
+                         /* Event for a journal file */
+ 
+-                        if (e->mask & (IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB)) {
+-                                r = add_file(j, d->path, e->name);
+-                                if (r < 0) {
+-                                        log_debug_errno(r, "Failed to add file %s/%s: %m",
+-                                                        d->path, e->name);
+-                                        set_put_error(j, r);
+-                                }
+-
+-                        } else if (e->mask & (IN_DELETE|IN_MOVED_FROM|IN_UNMOUNT)) {
+-
+-                                r = remove_file(j, d->path, e->name);
+-                                if (r < 0)
+-                                        log_debug_errno(r, "Failed to remove file %s/%s: %m", d->path, e->name);
+-                        }
++                        if (e->mask & (IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB))
++                                (void) add_file(j, d->path, e->name);
++                        else if (e->mask & (IN_DELETE|IN_MOVED_FROM|IN_UNMOUNT))
++                                remove_file(j, d->path, e->name);
+ 
+                 } else if (!d->is_root && e->len == 0) {
+ 
+@@ -2150,11 +2133,8 @@ static void process_inotify_event(sd_journal *j, struct inotify_event *e) {
+ 
+                         /* Event for root directory */
+ 
+-                        if (e->mask & (IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB)) {
+-                                r = add_directory(j, d->path, e->name);
+-                                if (r < 0)
+-                                        log_debug_errno(r, "Failed to add directory %s/%s: %m", d->path, e->name);
+-                        }
++                        if (e->mask & (IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB))
++                                (void) add_directory(j, d->path, e->name);
+                 }
+ 
+                 return;
+@@ -2163,7 +2143,7 @@ static void process_inotify_event(sd_journal *j, struct inotify_event *e) {
+         if (e->mask & IN_IGNORED)
+                 return;
+ 
+-        log_warning("Unknown inotify event.");
++        log_debug("Unknown inotify event.");
+ }
+ 
+ static int determine_change(sd_journal *j) {
diff --git a/SOURCES/0593-journalctl-when-we-fail-to-open-a-journal-file-print.patch b/SOURCES/0593-journalctl-when-we-fail-to-open-a-journal-file-print.patch
new file mode 100644
index 0000000..9d9c0f2
--- /dev/null
+++ b/SOURCES/0593-journalctl-when-we-fail-to-open-a-journal-file-print.patch
@@ -0,0 +1,204 @@
+From 9f7b08ba18ac3d4fd51e70d78d44b60ffb65411f Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Mon, 2 Nov 2015 23:37:05 +0100
+Subject: [PATCH] journalctl: when we fail to open a journal file, print why
+
+When we enumerate journal files and encounter an invalid one, remember
+which this, and show it to the user.
+
+Note the possibly slightly surprising logic here: we store only one path
+per error code. This means we show all error kinds but not every actual
+error we encounter. This has the benefit of not requiring us to keep a
+potentially unbounded list of errors with their sources around, but can
+still provide a pretty complete overview on the errors we encountered.
+
+Fixes #1669.
+
+(cherry picked from commit 5768d2594940668506bb4cafa078f654cc20dc5a)
+
+Resolves: #1465759
+---
+ src/journal/journal-internal.h |  2 +-
+ src/journal/journalctl.c       | 27 ++++++++++++++++++-----
+ src/journal/sd-journal.c       | 49 ++++++++++++++++++++++++++++++++++--------
+ 3 files changed, 63 insertions(+), 15 deletions(-)
+
+diff --git a/src/journal/journal-internal.h b/src/journal/journal-internal.h
+index 115d7776d..eb23ac28a 100644
+--- a/src/journal/journal-internal.h
++++ b/src/journal/journal-internal.h
+@@ -123,7 +123,7 @@ struct sd_journal {
+         Hashmap *directories_by_path;
+         Hashmap *directories_by_wd;
+ 
+-        Set *errors;
++        Hashmap *errors;
+ };
+ 
+ char *journal_make_match_string(sd_journal *j);
+diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
+index 8c8379732..0be70764e 100644
+--- a/src/journal/journalctl.c
++++ b/src/journal/journalctl.c
+@@ -1783,33 +1783,50 @@ static int access_check_var_log_journal(sd_journal *j) {
+ static int access_check(sd_journal *j) {
+         Iterator it;
+         void *code;
++        char *path;
+         int r = 0;
+ 
+         assert(j);
+ 
+-        if (set_isempty(j->errors)) {
++        if (hashmap_isempty(j->errors)) {
+                 if (ordered_hashmap_isempty(j->files))
+                         log_notice("No journal files were found.");
+ 
+                 return 0;
+         }
+ 
+-        if (set_contains(j->errors, INT_TO_PTR(-EACCES))) {
++        if (hashmap_contains(j->errors, INT_TO_PTR(-EACCES))) {
+                 (void) access_check_var_log_journal(j);
+ 
+                 if (ordered_hashmap_isempty(j->files))
+                         r = log_error_errno(EACCES, "No journal files were opened due to insufficient permissions.");
+         }
+ 
+-        SET_FOREACH(code, j->errors, it) {
++        HASHMAP_FOREACH_KEY(path, code, j->errors, it) {
+                 int err;
+ 
+                 err = abs(PTR_TO_INT(code));
+ 
+-                if (err == EACCES)
++                switch (err) {
++                case EACCES:
+                         continue;
+ 
+-                log_warning_errno(err, "An error was encountered while opening journal files, ignoring: %m");
++                case ENODATA:
++                        log_warning_errno(err, "Journal file %s is truncated, ignoring file.", path);
++                        break;
++
++                case EPROTONOSUPPORT:
++                        log_warning_errno(err, "Journal file %s uses an unsupported feature, ignoring file.", path);
++                        break;
++
++                case EBADMSG:
++                        log_warning_errno(err, "Journal file %s corrupted, ignoring file.", path);
++                        break;
++
++                default:
++                        log_warning_errno(err, "An error was encountered while opening journal file %s, ignoring file.", path);
++                        break;
++                }
+         }
+ 
+         return r;
+diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c
+index 9895d9608..14b65cfed 100644
+--- a/src/journal/sd-journal.c
++++ b/src/journal/sd-journal.c
+@@ -62,19 +62,46 @@ static bool journal_pid_changed(sd_journal *j) {
+         return j->original_pid != getpid();
+ }
+ 
+-/* We return an error here only if we didn't manage to
+-   memorize the real error. */
+-static int set_put_error(sd_journal *j, int r) {
++static int journal_put_error(sd_journal *j, int r, const char *path) {
++        char *copy;
+         int k;
+ 
++        /* Memorize an error we encountered, and store which
++         * file/directory it was generated from. Note that we store
++         * only *one* path per error code, as the error code is the
++         * key into the hashmap, and the path is the value. This means
++         * we keep track only of all error kinds, but not of all error
++         * locations. This has the benefit that the hashmap cannot
++         * grow beyond bounds.
++         *
++         * We return an error here only if we didn't manage to
++         * memorize the real error. */
++
+         if (r >= 0)
+                 return r;
+ 
+-        k = set_ensure_allocated(&j->errors, NULL);
++        k = hashmap_ensure_allocated(&j->errors, NULL);
+         if (k < 0)
+                 return k;
+ 
+-        return set_put(j->errors, INT_TO_PTR(r));
++        if (path) {
++                copy = strdup(path);
++                if (!copy)
++                        return -ENOMEM;
++        } else
++                copy = NULL;
++
++        k = hashmap_put(j->errors, INT_TO_PTR(r), copy);
++        if (k < 0) {
++                free(copy);
++
++                if (k == -EEXIST)
++                        return 0;
++
++                return k;
++        }
++
++        return 0;
+ }
+ 
+ static void detach_location(sd_journal *j) {
+@@ -1234,7 +1261,7 @@ static int add_any_file(sd_journal *j, const char *path) {
+         return 0;
+ 
+ fail:
+-        k = set_put_error(j, r);
++        k = journal_put_error(j, r, path);
+         if (k < 0)
+                 return k;
+ 
+@@ -1396,7 +1423,7 @@ static int add_directory(sd_journal *j, const char *prefix, const char *dirname)
+         return 0;
+ 
+ fail:
+-        k = set_put_error(j, r);
++        k = journal_put_error(j, r, path ?: dirname);
+         if (k < 0)
+                 return k;
+ 
+@@ -1487,7 +1514,7 @@ static int add_root_directory(sd_journal *j, const char *p, bool missing_ok) {
+         return 0;
+ 
+ fail:
+-        k = set_put_error(j, r);
++        k = journal_put_error(j, r, p);
+         if (k < 0)
+                 return k;
+ 
+@@ -1732,6 +1759,7 @@ fail:
+ _public_ void sd_journal_close(sd_journal *j) {
+         Directory *d;
+         JournalFile *f;
++        char *p;
+ 
+         if (!j)
+                 return;
+@@ -1759,10 +1787,13 @@ _public_ void sd_journal_close(sd_journal *j) {
+                 mmap_cache_unref(j->mmap);
+         }
+ 
++        while ((p = hashmap_steal_first(j->errors)))
++                free(p);
++        hashmap_free(j->errors);
++
+         free(j->path);
+         free(j->prefix);
+         free(j->unique_field);
+-        set_free(j->errors);
+         free(j);
+ }
+ 
diff --git a/SOURCES/0594-journald-fix-accuracy-of-watchdog-timer-event.patch b/SOURCES/0594-journald-fix-accuracy-of-watchdog-timer-event.patch
new file mode 100644
index 0000000..e80a7e6
--- /dev/null
+++ b/SOURCES/0594-journald-fix-accuracy-of-watchdog-timer-event.patch
@@ -0,0 +1,31 @@
+From 5386dfa655da623cbd5ab1be6c9c66ad866fc17a Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Thu, 12 Nov 2015 12:33:10 +0100
+Subject: [PATCH] journald: fix accuracy of watchdog timer event
+
+Adding 3/4th of the watchdog frequency as accuracy on top of 1/2 of the
+watchdog frequency means we might end up at 5/4th of the frequency which
+means we might miss the message from time to time.
+
+Maybe fixes #1804
+
+(cherry picked from commit 4de2402b603ea2f518f451d06f09e15aeae54fab)
+
+Related: #1511565
+---
+ src/journal/journald-server.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c
+index 6e7568b60..7c69061f4 100644
+--- a/src/journal/journald-server.c
++++ b/src/journal/journald-server.c
+@@ -1716,7 +1716,7 @@ static int server_connect_notify(Server *s) {
+         if (sd_watchdog_enabled(false, &s->watchdog_usec) > 0) {
+                 s->send_watchdog = true;
+ 
+-                r = sd_event_add_time(s->event, &s->watchdog_event_source, CLOCK_MONOTONIC, now(CLOCK_MONOTONIC) + s->watchdog_usec/2, s->watchdog_usec*3/4, dispatch_watchdog, s);
++                r = sd_event_add_time(s->event, &s->watchdog_event_source, CLOCK_MONOTONIC, now(CLOCK_MONOTONIC) + s->watchdog_usec/2, s->watchdog_usec/4, dispatch_watchdog, s);
+                 if (r < 0)
+                         return log_error_errno(r, "Failed to add watchdog time event: %m");
+         }
diff --git a/SOURCES/0595-core-fix-the-reversed-sanity-check-when-setting-Star.patch b/SOURCES/0595-core-fix-the-reversed-sanity-check-when-setting-Star.patch
new file mode 100644
index 0000000..498bad3
--- /dev/null
+++ b/SOURCES/0595-core-fix-the-reversed-sanity-check-when-setting-Star.patch
@@ -0,0 +1,28 @@
+From 468004bfb6efeef42b9191ee218304f0ab492654 Mon Sep 17 00:00:00 2001
+From: Tejun Heo <htejun@fb.com>
+Date: Mon, 23 May 2016 16:48:46 -0400
+Subject: [PATCH] core: fix the reversed sanity check when setting
+ StartupBlockIOWeight over dbus
+
+bus_cgroup_set_property() was rejecting if the input value was in range.
+Reverse it.
+
+Cherry-picked from: 6fb09269769634df1096663ce90fac47585eb63a
+Resolves: #1302305
+---
+ src/core/dbus-cgroup.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/core/dbus-cgroup.c b/src/core/dbus-cgroup.c
+index ffeeb5aa9..66b1324fe 100644
+--- a/src/core/dbus-cgroup.c
++++ b/src/core/dbus-cgroup.c
+@@ -324,7 +324,7 @@ int bus_cgroup_set_property(
+                 if (r < 0)
+                         return r;
+ 
+-                if (CGROUP_BLKIO_WEIGHT_IS_OK(weight))
++                if (!CGROUP_BLKIO_WEIGHT_IS_OK(weight))
+                         return sd_bus_error_set_errnof(error, EINVAL, "StartupBlockIOWeight value out of range");
+ 
+                 if (mode != UNIT_CHECK) {
diff --git a/SOURCES/0596-shared-dropin-ignore-ENAMETOOLONG-when-checking-drop.patch b/SOURCES/0596-shared-dropin-ignore-ENAMETOOLONG-when-checking-drop.patch
new file mode 100644
index 0000000..180ee6d
--- /dev/null
+++ b/SOURCES/0596-shared-dropin-ignore-ENAMETOOLONG-when-checking-drop.patch
@@ -0,0 +1,37 @@
+From 3ce9a9b286825793548ed7a7673dd9674a4e4137 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Nykr=C3=BDn?= <lnykryn@redhat.com>
+Date: Fri, 1 Dec 2017 20:34:49 +0100
+Subject: [PATCH] shared/dropin: ignore ENAMETOOLONG when checking drop-in
+ directories (#7525)
+
+This usually happens for device units with long
+path in /sys. But users can't even create such drop-ins,
+so lets just ignore the error here.
+
+Fixes #6867
+
+Cherry-picked from: dfeec916b57b593ce07d3751aebdb0cce1d05201
+Resolves: #1489095
+---
+ src/shared/dropin.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/src/shared/dropin.c b/src/shared/dropin.c
+index d1baad619..b674d307a 100644
+--- a/src/shared/dropin.c
++++ b/src/shared/dropin.c
+@@ -129,8 +129,12 @@ static int iterate_dir(
+ 
+         d = opendir(path);
+         if (!d) {
+-                if (errno == ENOENT)
+-                        return 0;
++                /* Ignore ENOENT, after all most units won't have a drop-in dir.
++                 * Also ignore ENAMETOOLONG, users are not even able to create
++                 * the drop-in dir in such case. This mostly happens for device units with long /sys path.
++                 * */
++                if (IN_SET(errno, ENOENT, ENAMETOOLONG))
++                            return 0;
+ 
+                 log_error_errno(errno, "Failed to open directory %s: %m", path);
+                 return -errno;
diff --git a/SOURCES/0597-cryptsetup-when-unlocking-always-put-path-to-the-obj.patch b/SOURCES/0597-cryptsetup-when-unlocking-always-put-path-to-the-obj.patch
new file mode 100644
index 0000000..3d5962d
--- /dev/null
+++ b/SOURCES/0597-cryptsetup-when-unlocking-always-put-path-to-the-obj.patch
@@ -0,0 +1,52 @@
+From ec71ee722b573560c14840214adab862b09280c3 Mon Sep 17 00:00:00 2001
+From: Michal Sekletar <msekleta@redhat.com>
+Date: Tue, 12 Dec 2017 17:49:14 +0100
+Subject: [PATCH] cryptsetup: when unlocking always put path to the object into
+ Id
+
+Some ask-password agents (e.g. clevis-luks-askpass) use Id option from
+/run/systemd/ask-password/ask* file in order to obtain the password for
+the device.
+
+Id option should be in the following format,
+e.g. Id=subsystem:data. Where data part is supposed to identify object
+that ask-password query is done for. Since
+e51b9486d1b59e72c293028fed1384f4e4ef09aa this field has format
+Id=cryptsetup:/dev/block/major:minor when systemd-cryptsetup is
+unlocking encrypted block device. However, crypttab also supports
+encrypted image files in which case we usually set data part of Id to
+"vol on mountpoint". This is unexpected and actually breaks network
+based device encryption as implemented by clevis.
+
+Example:
+$ cat /etc/crypttab
+clevis-unlocked /clevis-test-disk-image none luks,_netdev
+$ systemctl start 'systemd-cryptsetup@clevis\x2dunlocked.service'
+$ grep Id /run/systemd/ask-password/ask*
+
+Before:
+$ Id=cryptsetup:clevis-unlocked on /clevis-test-disk-image-mnt
+
+After:
+$ Id=cryptsetup:/clevis-test-disk-image
+
+(cherry-picked from commit 5a9f1b05ed6dad48958097fb37811668e69447fb)
+
+Resolves: #1511043
+---
+ src/cryptsetup/cryptsetup.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c
+index 5dedb073e..c57d2b294 100644
+--- a/src/cryptsetup/cryptsetup.c
++++ b/src/cryptsetup/cryptsetup.c
+@@ -342,7 +342,7 @@ static int get_password(const char *vol, const char *src, usec_t until, bool acc
+                 escaped_name = maj_min;
+                 maj_min = NULL;
+         } else
+-                escaped_name = cescape(name);
++                escaped_name = cescape(src);
+ 
+         if (!escaped_name)
+                 return log_oom();
diff --git a/SOURCES/0598-cryptsetup-use-more-descriptive-name-for-the-variabl.patch b/SOURCES/0598-cryptsetup-use-more-descriptive-name-for-the-variabl.patch
new file mode 100644
index 0000000..77832cc
--- /dev/null
+++ b/SOURCES/0598-cryptsetup-use-more-descriptive-name-for-the-variabl.patch
@@ -0,0 +1,106 @@
+From 1e02c945fbf54f2b9179ab84794a05cffb3efd98 Mon Sep 17 00:00:00 2001
+From: Michal Sekletar <msekleta@redhat.com>
+Date: Tue, 12 Dec 2017 20:00:31 +0100
+Subject: [PATCH] cryptsetup: use more descriptive name for the variable and
+ drop redundant function
+
+Let's rename escaped_name to disk_path since this is an actual content
+that pointer refers to. It is either path to encrypted block device
+or path to encrypted image file.
+
+Also drop redundant function disk_major_minor(). src is always set, and
+it always points to either encrypted block device path (or symlink to
+such device) or to encrypted image. In case it is set to device path
+there is no need to reset it to /dev/block/major:minor symlink since
+those paths are equivalent.
+
+(cherry-picked from commit ea7e7c1e9c3b579ee94a11a192f1013ee4cb829e)
+
+Related: #1511043
+---
+ src/cryptsetup/cryptsetup.c | 41 ++++++++---------------------------------
+ 1 file changed, 8 insertions(+), 33 deletions(-)
+
+diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c
+index c57d2b294..69a015614 100644
+--- a/src/cryptsetup/cryptsetup.c
++++ b/src/cryptsetup/cryptsetup.c
+@@ -217,23 +217,6 @@ static void log_glue(int level, const char *msg, void *usrptr) {
+         log_debug("%s", msg);
+ }
+ 
+-static int disk_major_minor(const char *path, char **ret) {
+-        struct stat st;
+-
+-        assert(path);
+-
+-        if (stat(path, &st) < 0)
+-                return -errno;
+-
+-        if (!S_ISBLK(st.st_mode))
+-                return -EINVAL;
+-
+-        if (asprintf(ret, "/dev/block/%d:%d", major(st.st_rdev), minor(st.st_rdev)) < 0)
+-                return -errno;
+-
+-        return 0;
+-}
+-
+ static char* disk_description(const char *path) {
+ 
+         static const char name_fields[] =
+@@ -299,11 +282,11 @@ static int get_password(const char *vol, const char *src, usec_t until, bool acc
+         int r = 0;
+         char **p;
+         _cleanup_free_ char *text = NULL;
+-        _cleanup_free_ char *escaped_name = NULL;
++        _cleanup_free_ char *disk_path = NULL;
+         char *id;
+         const char *name = NULL;
+         _cleanup_free_ char *description = NULL, *name_buffer = NULL,
+-                *mount_point = NULL, *maj_min = NULL;
++                *mount_point = NULL;
+ 
+         assert(vol);
+         assert(src);
+@@ -312,6 +295,10 @@ static int get_password(const char *vol, const char *src, usec_t until, bool acc
+         description = disk_description(src);
+         mount_point = disk_mount_point(vol);
+ 
++        disk_path = cescape(src);
++        if (!disk_path)
++                return log_oom();
++
+         if (description && streq(vol, description)) {
+                 /* If the description string is simply the
+                  * volume name, then let's not show this
+@@ -335,19 +322,7 @@ static int get_password(const char *vol, const char *src, usec_t until, bool acc
+         if (asprintf(&text, "Please enter passphrase for disk %s!", name) < 0)
+                 return log_oom();
+ 
+-        if (src)
+-                (void) disk_major_minor(src, &maj_min);
+-
+-        if (maj_min) {
+-                escaped_name = maj_min;
+-                maj_min = NULL;
+-        } else
+-                escaped_name = cescape(src);
+-
+-        if (!escaped_name)
+-                return log_oom();
+-
+-        id = strjoina("cryptsetup:", escaped_name);
++        id = strjoina("cryptsetup:", disk_path);
+ 
+         r = ask_password_auto(text, "drive-harddisk", id, until, accept_cached, passwords);
+         if (r < 0)
+@@ -361,7 +336,7 @@ static int get_password(const char *vol, const char *src, usec_t until, bool acc
+                 if (asprintf(&text, "Please enter passphrase for disk %s! (verification)", name) < 0)
+                         return log_oom();
+ 
+-                id = strjoina("cryptsetup-verification:", escaped_name);
++                id = strjoina("cryptsetup-verification:", disk_path);
+ 
+                 r = ask_password_auto(text, "drive-harddisk", id, until, false, &passwords2);
+                 if (r < 0)
diff --git a/SOURCES/0599-cryptsetup-generator-do-not-bind-to-the-decrypted-de.patch b/SOURCES/0599-cryptsetup-generator-do-not-bind-to-the-decrypted-de.patch
new file mode 100644
index 0000000..e53a384
--- /dev/null
+++ b/SOURCES/0599-cryptsetup-generator-do-not-bind-to-the-decrypted-de.patch
@@ -0,0 +1,31 @@
+From 1fa67ac23b3fff0e04c55df8cca6a54994adf175 Mon Sep 17 00:00:00 2001
+From: Ivan Shapovalov <intelfx@intelfx.name>
+Date: Wed, 30 Aug 2017 19:49:07 +0300
+Subject: [PATCH] cryptsetup-generator: do not bind to the decrypted device
+ unit (#6538)
+
+This breaks things when the decrypted device is not immediately
+`SYSTEMD_READY=1` (e. g. when a multi-device btrfs system is placed on
+multiple cryptsetup devices).
+
+Fixes #6537.
+
+(cherry picked from commit e9ea4526a3a3b41eced29b8d742498cc36750424)
+
+Related: #1511043
+---
+ src/cryptsetup/cryptsetup-generator.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c
+index c387e2104..5f29093f5 100644
+--- a/src/cryptsetup/cryptsetup-generator.c
++++ b/src/cryptsetup/cryptsetup-generator.c
+@@ -110,7 +110,6 @@ static int create_disk(
+                 "SourcePath=/etc/crypttab\n"
+                 "DefaultDependencies=no\n"
+                 "Conflicts=umount.target\n"
+-                "BindsTo=dev-mapper-%%i.device\n"
+                 "IgnoreOnIsolate=true\n"
+                 "After=systemd-readahead-collect.service systemd-readahead-replay.service\n"
+                 "After=%s\n",
diff --git a/SOURCES/0600-shared-cgroup-utils-_CGROUP_CONTROLLER_MASK_ALL-does.patch b/SOURCES/0600-shared-cgroup-utils-_CGROUP_CONTROLLER_MASK_ALL-does.patch
new file mode 100644
index 0000000..288ad7b
--- /dev/null
+++ b/SOURCES/0600-shared-cgroup-utils-_CGROUP_CONTROLLER_MASK_ALL-does.patch
@@ -0,0 +1,28 @@
+From 864cf889ecf371df9e67f27682a8f9bc0f68e153 Mon Sep 17 00:00:00 2001
+From: Lukas Nykryn <lnykryn@redhat.com>
+Date: Tue, 9 Jan 2018 12:59:19 +0100
+Subject: [PATCH] shared/cgroup-utils: _CGROUP_CONTROLLER_MASK_ALL does not
+ cover CGROUP_PIDS
+
+7d44d0d43465892d4753ff50592588f49d56cf95 added a CGROUP_PIDS but
+did not bump _CGROUP_CONTROLLER_MASK_ALL.
+
+RHEL-only
+Resolves: #1532586
+---
+ src/shared/cgroup-util.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/shared/cgroup-util.h b/src/shared/cgroup-util.h
+index 615c1f03e..b6f28c5c2 100644
+--- a/src/shared/cgroup-util.h
++++ b/src/shared/cgroup-util.h
+@@ -36,7 +36,7 @@ typedef enum CGroupControllerMask {
+         CGROUP_MEMORY = 8,
+         CGROUP_DEVICE = 16,
+         CGROUP_PIDS = 32,
+-        _CGROUP_CONTROLLER_MASK_ALL = 31
++        _CGROUP_CONTROLLER_MASK_ALL = 63
+ } CGroupControllerMask;
+ 
+ /* Special values for the cpu.shares attribute */
diff --git a/SOURCES/0601-automount-ack-automount-requests-even-when-already-m.patch b/SOURCES/0601-automount-ack-automount-requests-even-when-already-m.patch
new file mode 100644
index 0000000..d0b9e21
--- /dev/null
+++ b/SOURCES/0601-automount-ack-automount-requests-even-when-already-m.patch
@@ -0,0 +1,82 @@
+From d9df4d0ed03f56036b04e19a8e6be2c028c4a72e Mon Sep 17 00:00:00 2001
+From: Jan Synacek <jsynacek@redhat.com>
+Date: Wed, 17 Jan 2018 09:13:24 +0100
+Subject: [PATCH] automount: ack automount requests even when already mounted
+
+If a process accesses an autofs filesystem while systemd is in the
+middle of starting the mount unit on top of it, it is possible for the
+autofs_ptype_missing_direct request from the kernel to be received after
+the mount unit has been fully started:
+
+  systemd forks and execs mount             ...
+            ...                     access autofs, blocks
+  mount exits                               ...
+  systemd receives SIGCHLD                  ...
+            ...                     kernel sends request
+  systemd receives request                  ...
+
+systemd needs to respond to this request, otherwise the kernel will
+continue to block access to the mount point.
+
+(cherry picked from commit e7d54bf58789545a9eb0b3964233defa0b007318)
+
+Resolves: #1535135
+---
+ src/core/automount.c | 28 ++++++++++++++++------------
+ 1 file changed, 16 insertions(+), 12 deletions(-)
+
+diff --git a/src/core/automount.c b/src/core/automount.c
+index 20a5de8ca..182ba5240 100644
+--- a/src/core/automount.c
++++ b/src/core/automount.c
+@@ -712,7 +712,7 @@ static int automount_start_expire(Automount *a) {
+                         automount_dispatch_expire, a);
+ }
+ 
+-static void automount_enter_runnning(Automount *a) {
++static void automount_enter_running(Automount *a) {
+         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+         struct stat st;
+         int r;
+@@ -744,18 +744,22 @@ static void automount_enter_runnning(Automount *a) {
+                 goto fail;
+         }
+ 
+-        if (!S_ISDIR(st.st_mode) || st.st_dev != a->dev_id)
++        /* The mount unit may have been explicitly started before we got the
++         * autofs request. Ack it to unblock anything waiting on the mount point. */
++        if (!S_ISDIR(st.st_mode) || st.st_dev != a->dev_id) {
+                 log_unit_info(UNIT(a)->id,
+                               "%s's automount point already active?", UNIT(a)->id);
+-        else {
+-                r = manager_add_job(UNIT(a)->manager, JOB_START, UNIT_TRIGGER(UNIT(a)),
+-                                    JOB_REPLACE, true, &error, NULL);
+-                if (r < 0) {
+-                        log_unit_warning(UNIT(a)->id,
+-                                         "%s failed to queue mount startup job: %s",
+-                                         UNIT(a)->id, bus_error_message(&error, r));
+-                        goto fail;
+-                }
++                automount_send_ready(a, a->tokens, 0);
++                return;
++        }
++
++        r = manager_add_job(UNIT(a)->manager, JOB_START, UNIT_TRIGGER(UNIT(a)),
++                        JOB_REPLACE, true, &error, NULL);
++        if (r < 0) {
++                log_unit_warning(UNIT(a)->id,
++                                "%s failed to queue mount startup job: %s",
++                                UNIT(a)->id, bus_error_message(&error, r));
++                goto fail;
+         }
+ 
+         r = automount_start_expire(a);
+@@ -979,7 +983,7 @@ static int automount_dispatch_io(sd_event_source *s, int fd, uint32_t events, vo
+                         goto fail;
+                 }
+ 
+-                automount_enter_runnning(a);
++                automount_enter_running(a);
+                 break;
+ 
+         case autofs_ptype_expire_direct:
diff --git a/SOURCES/0602-udev-net_id-add-support-for-platform-bus-ACPI-mostly.patch b/SOURCES/0602-udev-net_id-add-support-for-platform-bus-ACPI-mostly.patch
new file mode 100644
index 0000000..cbcc4d5
--- /dev/null
+++ b/SOURCES/0602-udev-net_id-add-support-for-platform-bus-ACPI-mostly.patch
@@ -0,0 +1,134 @@
+From 2a73ec2f11e5dde5754260d0ce99778f35ec92cc Mon Sep 17 00:00:00 2001
+From: Jan Synacek <jsynacek@redhat.com>
+Date: Wed, 17 Jan 2018 10:08:08 +0100
+Subject: [PATCH] udev: net_id add support for platform bus (ACPI, mostly
+ arm64) devices
+
+(cherry picked from commit c20e6de897b2378bc3f936e1e265d2d2e2450a73)
+
+Note: There is RHEL-only code in the patch. After some discussion,
+we only want to rename Hisilicon Network Subsystem (HNS) devices.
+
+Resolves: #1529633
+---
+ src/udev/udev-builtin-net_id.c | 72 ++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 72 insertions(+)
+
+diff --git a/src/udev/udev-builtin-net_id.c b/src/udev/udev-builtin-net_id.c
+index 19e1f2631..69cee5a72 100644
+--- a/src/udev/udev-builtin-net_id.c
++++ b/src/udev/udev-builtin-net_id.c
+@@ -42,6 +42,7 @@
+  *                                         -- PCI geographical location
+  *   [P<domain>]p<bus>s<slot>[f<function>][u<port>][..][c<config>][i<interface>]
+  *                                         -- USB port number chain
++ *   a<vendor><model>i<instance>           -- Platform bus ACPI instance id
+  *
+  * All multi-function PCI devices will carry the [f<function>] number in the
+  * device name, including the function 0 device.
+@@ -100,6 +101,7 @@
+ 
+ #include "udev.h"
+ #include "fileio.h"
++#include "def.h"
+ 
+ #define ONBOARD_INDEX_MAX (16*1024-1)
+ 
+@@ -110,6 +112,7 @@ enum netname_type{
+         NET_BCMA,
+         NET_VIRTIO,
+         NET_CCWGROUP,
++        NET_PLATFORM,
+ };
+ 
+ struct netnames {
+@@ -127,6 +130,7 @@ struct netnames {
+         char usb_ports[IFNAMSIZ];
+         char bcma_core[IFNAMSIZ];
+         char ccw_group[IFNAMSIZ];
++        char platform_path[IFNAMSIZ];
+ };
+ 
+ /* retrieve on-board index number and label from firmware */
+@@ -288,6 +292,64 @@ out:
+         return err;
+ }
+ 
++#define _PLATFORM_TEST "/sys/devices/platform/vvvvPPPP"
++#define _PLATFORM_PATTERN4 "/sys/devices/platform/%4s%4x:%2x/net/eth%u"
++#define _PLATFORM_PATTERN3 "/sys/devices/platform/%3s%4x:%2x/net/eth%u"
++
++static int names_platform(struct udev_device *dev, struct netnames *names, bool test) {
++        struct udev_device *parent;
++        char vendor[5];
++        unsigned model, instance, ethid;
++        const char *syspath, *pattern, *validchars;
++
++        /* check if our direct parent is a platform device with no other bus in-between */
++        parent = udev_device_get_parent(dev);
++        if (!parent)
++                return -ENOENT;
++
++        if (!streq_ptr("platform", udev_device_get_subsystem(parent)))
++                 return -ENOENT;
++
++        syspath = udev_device_get_syspath(dev);
++
++        /* syspath is too short, to have a valid ACPI instance */
++        if (strlen(syspath) < sizeof _PLATFORM_TEST)
++                return -EINVAL;
++
++        /* Vendor ID can be either PNP ID (3 chars A-Z) or ACPI ID (4 chars A-Z and numerals) */
++        if (syspath[sizeof _PLATFORM_TEST - 1] == ':') {
++                pattern = _PLATFORM_PATTERN4;
++                validchars = UPPERCASE_LETTERS DIGITS;
++        } else {
++                pattern = _PLATFORM_PATTERN3;
++                validchars = UPPERCASE_LETTERS;
++        }
++
++        /* RHEL-only! */
++        /* We only want to rename HNS cards */
++        if (!startswith(syspath, "/sys/devices/platform/HISI"))
++                return -ENOENT;
++
++        /* Platform devices are named after ACPI table match, and instance id
++         * eg. "/sys/devices/platform/HISI00C2:00");
++         * The Vendor (3 or 4 char), followed by hexdecimal model number : instance id.
++         */
++#pragma GCC diagnostic push
++#pragma GCC diagnostic ignored "-Wformat-nonliteral"
++        if (sscanf(syspath, pattern, vendor, &model, &instance, &ethid) != 4)
++                return -EINVAL;
++#pragma GCC diagnostic pop
++
++        if (!in_charset(vendor, validchars))
++                return -ENOENT;
++
++        ascii_strlower(vendor);
++
++        xsprintf(names->platform_path, "a%s%xi%u", vendor, model, instance);
++        names->type = NET_PLATFORM;
++        return 0;
++}
++
+ static int names_pci(struct udev_device *dev, struct netnames *names) {
+         struct udev_device *parent;
+         static int do_virtio = -1;
+@@ -555,6 +617,16 @@ static int builtin_net_id(struct udev_device *dev, int argc, char *argv[], bool
+                 goto out;
+         }
+ 
++        /* get ACPI path names for ARM64 platform devices */
++        err = names_platform(dev, &names, test);
++        if (err >= 0 && names.type == NET_PLATFORM) {
++                char str[IFNAMSIZ];
++
++                if (snprintf(str, sizeof(str), "%s%s", prefix, names.platform_path) < (int)sizeof(str))
++                        udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str);
++                goto out;
++        }
++
+         /* get PCI based path names, we compose only PCI based paths */
+         err = names_pci(dev, &names);
+         if (err < 0)
diff --git a/SOURCES/0603-journald-native-Fix-typo-in-MANDLOCK-message.patch b/SOURCES/0603-journald-native-Fix-typo-in-MANDLOCK-message.patch
new file mode 100644
index 0000000..1e36686
--- /dev/null
+++ b/SOURCES/0603-journald-native-Fix-typo-in-MANDLOCK-message.patch
@@ -0,0 +1,24 @@
+From fd5cce8255e14fd619654d3d639485787afdc89c Mon Sep 17 00:00:00 2001
+From: Frantisek Sumsal <frantisek@sumsal.cz>
+Date: Mon, 22 Jan 2018 11:18:53 +0100
+Subject: [PATCH] journald-native: Fix typo in MANDLOCK message
+
+Cherry-picked from: 1dc52f56f9641be12470be664d16043a7a08ff37
+Resolves: #1501017
+---
+ src/journal/journald-native.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/journal/journald-native.c b/src/journal/journald-native.c
+index fdb1a38dd..cf3349393 100644
+--- a/src/journal/journald-native.c
++++ b/src/journal/journald-native.c
+@@ -406,7 +406,7 @@ void server_process_native_file(
+                  * https://github.com/systemd/systemd/issues/1822
+                  */
+                 if (vfs.f_flag & ST_MANDLOCK) {
+-                        log_error("Received file descriptor from file system with mandatory locking enable, refusing.");
++                        log_error("Received file descriptor from file system with mandatory locking enabled, refusing.");
+                         return;
+                 }
+ 
diff --git a/SOURCES/0604-process-util-make-our-freeze-routine-do-something-us.patch b/SOURCES/0604-process-util-make-our-freeze-routine-do-something-us.patch
new file mode 100644
index 0000000..4507872
--- /dev/null
+++ b/SOURCES/0604-process-util-make-our-freeze-routine-do-something-us.patch
@@ -0,0 +1,45 @@
+From 04213418a4e8d4e7f74f5b8b03713172a658d9e4 Mon Sep 17 00:00:00 2001
+From: Michal Sekletar <msekleta@redhat.com>
+Date: Fri, 12 Jan 2018 13:05:48 +0100
+Subject: [PATCH] process-util: make our freeze() routine do something useful
+
+When we crash we freeze() our-self (or possibly we reboot the machine if
+that is configured). However, calling pause() is very unhelpful thing to
+do. We should at least continue to do what init systems being doing
+since 70's and that is reaping zombies. Otherwise zombies start to
+accumulate on the system which is a very bad thing. As that can prevent
+admin from taking manual steps to reboot the machine in somewhat
+graceful manner (e.g. manually stopping services, unmounting data
+volumes  and calling reboot -f).
+
+Fixes #7783
+
+(cherry picked from commit 8647283e453e4039029e2b21270241fa4010b3d8)
+
+Resolves: #1540941
+---
+ src/shared/util.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+diff --git a/src/shared/util.c b/src/shared/util.c
+index 39359fcc8..af0953273 100644
+--- a/src/shared/util.c
++++ b/src/shared/util.c
+@@ -4158,6 +4158,17 @@ noreturn void freeze(void) {
+ 
+         sync();
+ 
++        /* Let's not freeze right away, but keep reaping zombies. */
++        for (;;) {
++                int r;
++                siginfo_t si = {};
++
++                r = waitid(P_ALL, 0, &si, WEXITED);
++                if (r < 0 && errno != EINTR)
++                        break;
++        }
++
++        /* waitid() failed with an unexpected error, things are really borked. Freeze now! */
+         for (;;)
+                 pause();
+ }
diff --git a/SOURCES/0605-dbus-propagate-errors-from-bus_init_system-and-bus_i.patch b/SOURCES/0605-dbus-propagate-errors-from-bus_init_system-and-bus_i.patch
new file mode 100644
index 0000000..bc131c8
--- /dev/null
+++ b/SOURCES/0605-dbus-propagate-errors-from-bus_init_system-and-bus_i.patch
@@ -0,0 +1,131 @@
+From ac8fd4f713c1861e8a62fd811b2e79acbee5db31 Mon Sep 17 00:00:00 2001
+From: Michal Sekletar <msekleta@redhat.com>
+Date: Wed, 10 Jan 2018 17:22:12 +0100
+Subject: [PATCH] dbus: propagate errors from bus_init_system() and
+ bus_init_api()
+
+The aim of this change is to make sure that we properly log about all
+D-Bus connection problems. After all, we only ever attempt to get on the
+bus if dbus-daemon is around, so any failure in the process should be
+treated as an error.
+
+bus_init_system() is only called from bus_init() and in
+bus_init() we have a bool flag which governs whether we should attempt
+to connect to the system bus or not.
+Hence if we are in bus_init_system() then it is clear we got called from
+a context where connection to the bus is actually required and therefore
+shouldn't be treated as the "best effort" type of operation. Same
+applies to bus_init_api().
+
+We make use of those error codes in bus_init() and log high level
+message that informs admin about what is going on (and is easy to spot
+and makes sense to an end user).
+
+Also "retrying later" bit is actually a lie. We won't retry unless we
+are explicitly told to reconnect via SIGUSR1 or re-executed. This is
+because bus_init() is always called from the context where dbus-daemon
+is already around and hence bus_init() won't be called again from
+unit_notify().
+
+Fixes #7782
+
+(cherry picked from commit dc7118ba094415d8de3812881cc5cbe2e3cac73e)
+
+Resolves: #1541061
+---
+ src/core/dbus.c | 46 +++++++++++++++++-----------------------------
+ 1 file changed, 17 insertions(+), 29 deletions(-)
+
+diff --git a/src/core/dbus.c b/src/core/dbus.c
+index 0061211fa..d551eab01 100644
+--- a/src/core/dbus.c
++++ b/src/core/dbus.c
+@@ -811,27 +811,21 @@ static int bus_init_api(Manager *m) {
+                 else
+                         r = sd_bus_open_user(&bus);
+ 
+-                if (r < 0) {
+-                        log_debug("Failed to connect to API bus, retrying later...");
+-                        return 0;
+-                }
++                if (r < 0)
++                        return log_error_errno(r, "Failed to connect to API bus: %m");
+ 
+                 r = sd_bus_attach_event(bus, m->event, SD_EVENT_PRIORITY_NORMAL);
+-                if (r < 0) {
+-                        log_error_errno(r, "Failed to attach API bus to event loop: %m");
+-                        return 0;
+-                }
++                if (r < 0)
++                        return log_error_errno(r, "Failed to attach API bus to event loop: %m");
+ 
+                 r = bus_setup_disconnected_match(m, bus);
+                 if (r < 0)
+-                        return 0;
++                        return r;
+         }
+ 
+         r = bus_setup_api(m, bus);
+-        if (r < 0) {
+-                log_error_errno(r, "Failed to set up API bus: %m");
+-                return 0;
+-        }
++        if (r < 0)
++                return log_error_errno(r, "Failed to set up API bus: %m");
+ 
+         m->api_bus = bus;
+         bus = NULL;
+@@ -880,26 +874,20 @@ static int bus_init_system(Manager *m) {
+         }
+ 
+         r = sd_bus_open_system(&bus);
+-        if (r < 0) {
+-                log_debug("Failed to connect to system bus, retrying later...");
+-                return 0;
+-        }
++        if (r < 0)
++                return log_error_errno(r, "Failed to connect to system bus: %m");
+ 
+         r = bus_setup_disconnected_match(m, bus);
+         if (r < 0)
+-                return 0;
++                return r;
+ 
+         r = sd_bus_attach_event(bus, m->event, SD_EVENT_PRIORITY_NORMAL);
+-        if (r < 0) {
+-                log_error_errno(r, "Failed to attach system bus to event loop: %m");
+-                return 0;
+-        }
++        if (r < 0)
++                return log_error_errno(r, "Failed to attach system bus to event loop: %m");
+ 
+         r = bus_setup_system(m, bus);
+-        if (r < 0) {
+-                log_error_errno(r, "Failed to set up system bus: %m");
+-                return 0;
+-        }
++        if (r < 0)
++                return log_error_errno(r, "Failed to set up system bus: %m");
+ 
+         m->system_bus = bus;
+         bus = NULL;
+@@ -984,16 +972,16 @@ int bus_init(Manager *m, bool try_bus_connect) {
+         if (try_bus_connect) {
+                 r = bus_init_system(m);
+                 if (r < 0)
+-                        return r;
++                        return log_error_errno(r, "Failed to initialize D-Bus connection: %m");
+ 
+                 r = bus_init_api(m);
+                 if (r < 0)
+-                        return r;
++                        return log_error_errno(r, "Error occured during D-Bus APIs initialization: %m");
+         }
+ 
+         r = bus_init_private(m);
+         if (r < 0)
+-                return r;
++                return log_error_errno(r, "Failed to create private D-Bus server: %m");
+ 
+         return 0;
+ }
diff --git a/SOURCES/0606-bus-util.c-fix-TasksMax-property-assignment.patch b/SOURCES/0606-bus-util.c-fix-TasksMax-property-assignment.patch
new file mode 100644
index 0000000..2630ceb
--- /dev/null
+++ b/SOURCES/0606-bus-util.c-fix-TasksMax-property-assignment.patch
@@ -0,0 +1,44 @@
+From fc0a9c4e9701370822014298849116da2d3e41f3 Mon Sep 17 00:00:00 2001
+From: Jan Synacek <jsynacek@redhat.com>
+Date: Tue, 30 Jan 2018 12:58:42 +0100
+Subject: [PATCH] bus-util.c: fix TasksMax= property assignment
+
+Also, with the current code structure, it's not possible to also set
+the TasksMaxScale= in the same if branch, simply because how the
+sd_bus_message_append() is used. In src/systemctl/systemctl.c, the
+message container is already open in set_property().
+
+Resolves: #1537147
+---
+ src/libsystemd/sd-bus/bus-util.c | 15 ++++-----------
+ 1 file changed, 4 insertions(+), 11 deletions(-)
+
+diff --git a/src/libsystemd/sd-bus/bus-util.c b/src/libsystemd/sd-bus/bus-util.c
+index cbf1eccf7..b1bdbad2d 100644
+--- a/src/libsystemd/sd-bus/bus-util.c
++++ b/src/libsystemd/sd-bus/bus-util.c
+@@ -1418,20 +1418,13 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
+                 if (isempty(eq) || streq(eq, "infinity"))
+                         t = (uint64_t) -1;
+                 else {
+-                        r = parse_percent(eq);
+-                        if (r >= 0) {
+-                                r = sd_bus_message_append(m, "sv", "TasksMaxScale", "u", (uint32_t) (((uint64_t) UINT32_MAX * r) / 100U));
+-                                if (r < 0)
+-                                        return bus_log_create_error(r);
+-                        } else {
+-                                r = safe_atou64(eq, &t);
+-                                if (r < 0)
+-                                        return log_error_errno(r, "Failed to parse maximum tasks specification %s", assignment);
+-                        }
++                        r = safe_atou64(eq, &t);
++                        if (r < 0)
++                                return log_error_errno(r, "Failed to parse maximum tasks specification %s", assignment);
+ 
+                 }
+ 
+-                r = sd_bus_message_append(m, "sv", "TasksMax", "t", t);
++                r = sd_bus_message_append(m, "v", "t", t);
+ 
+         } else if (STR_IN_SET(field, "CPUShares", "StartupCPUShares")) {
+                 uint64_t u;
diff --git a/SOURCES/0607-sparse-avoid-clash-with-__bitwise-and-__force-from-4.patch b/SOURCES/0607-sparse-avoid-clash-with-__bitwise-and-__force-from-4.patch
new file mode 100644
index 0000000..1283fd0
--- /dev/null
+++ b/SOURCES/0607-sparse-avoid-clash-with-__bitwise-and-__force-from-4.patch
@@ -0,0 +1,89 @@
+From 59a855f7dbbd79c01ab9e8d326e986de786dda3f Mon Sep 17 00:00:00 2001
+From: Lubomir Rintel <lkundrak@v3.sk>
+Date: Wed, 11 Jan 2017 10:50:25 +0100
+Subject: [PATCH] sparse: avoid clash with __bitwise and __force from 4.10
+ linux/types.h (#5061)
+
+It also used __bitwise and __force. It seems easier to rename
+our versions since they are local to this one single header.
+
+Also, undefine them afteerwards, so that we don't pollute the
+preprocessor macro namespace.
+
+(cherry picked from commit dc66f33a16596c2886a24da12e56ec096214e124)
+
+Related: #1447937
+---
+ src/shared/sparse-endian.h | 47 ++++++++++++++++++++++++----------------------
+ 1 file changed, 25 insertions(+), 22 deletions(-)
+
+diff --git a/src/shared/sparse-endian.h b/src/shared/sparse-endian.h
+index c913fda8c..a3573b84a 100644
+--- a/src/shared/sparse-endian.h
++++ b/src/shared/sparse-endian.h
+@@ -26,19 +26,19 @@
+ #include <stdint.h>
+ 
+ #ifdef __CHECKER__
+-#define __bitwise __attribute__((bitwise))
+-#define __force __attribute__((force))
++#define __sd_bitwise __attribute__((bitwise))
++#define __sd_force __attribute__((force))
+ #else
+-#define __bitwise
+-#define __force
++#define __sd_bitwise
++#define __sd_force
+ #endif
+ 
+-typedef uint16_t __bitwise le16_t;
+-typedef uint16_t __bitwise be16_t;
+-typedef uint32_t __bitwise le32_t;
+-typedef uint32_t __bitwise be32_t;
+-typedef uint64_t __bitwise le64_t;
+-typedef uint64_t __bitwise be64_t;
++typedef uint16_t __sd_bitwise le16_t;
++typedef uint16_t __sd_bitwise be16_t;
++typedef uint32_t __sd_bitwise le32_t;
++typedef uint32_t __sd_bitwise be32_t;
++typedef uint64_t __sd_bitwise le64_t;
++typedef uint64_t __sd_bitwise be64_t;
+ 
+ #undef htobe16
+ #undef htole16
+@@ -69,20 +69,23 @@ typedef uint64_t __bitwise be64_t;
+ #define bswap_64_on_be(x) __bswap_64(x)
+ #endif
+ 
+-static inline le16_t htole16(uint16_t value) { return (le16_t __force) bswap_16_on_be(value); }
+-static inline le32_t htole32(uint32_t value) { return (le32_t __force) bswap_32_on_be(value); }
+-static inline le64_t htole64(uint64_t value) { return (le64_t __force) bswap_64_on_be(value); }
++static inline le16_t htole16(uint16_t value) { return (le16_t __sd_force) bswap_16_on_be(value); }
++static inline le32_t htole32(uint32_t value) { return (le32_t __sd_force) bswap_32_on_be(value); }
++static inline le64_t htole64(uint64_t value) { return (le64_t __sd_force) bswap_64_on_be(value); }
+ 
+-static inline be16_t htobe16(uint16_t value) { return (be16_t __force) bswap_16_on_le(value); }
+-static inline be32_t htobe32(uint32_t value) { return (be32_t __force) bswap_32_on_le(value); }
+-static inline be64_t htobe64(uint64_t value) { return (be64_t __force) bswap_64_on_le(value); }
++static inline be16_t htobe16(uint16_t value) { return (be16_t __sd_force) bswap_16_on_le(value); }
++static inline be32_t htobe32(uint32_t value) { return (be32_t __sd_force) bswap_32_on_le(value); }
++static inline be64_t htobe64(uint64_t value) { return (be64_t __sd_force) bswap_64_on_le(value); }
+ 
+-static inline uint16_t le16toh(le16_t value) { return bswap_16_on_be((uint16_t __force)value); }
+-static inline uint32_t le32toh(le32_t value) { return bswap_32_on_be((uint32_t __force)value); }
+-static inline uint64_t le64toh(le64_t value) { return bswap_64_on_be((uint64_t __force)value); }
++static inline uint16_t le16toh(le16_t value) { return bswap_16_on_be((uint16_t __sd_force)value); }
++static inline uint32_t le32toh(le32_t value) { return bswap_32_on_be((uint32_t __sd_force)value); }
++static inline uint64_t le64toh(le64_t value) { return bswap_64_on_be((uint64_t __sd_force)value); }
+ 
+-static inline uint16_t be16toh(be16_t value) { return bswap_16_on_le((uint16_t __force)value); }
+-static inline uint32_t be32toh(be32_t value) { return bswap_32_on_le((uint32_t __force)value); }
+-static inline uint64_t be64toh(be64_t value) { return bswap_64_on_le((uint64_t __force)value); }
++static inline uint16_t be16toh(be16_t value) { return bswap_16_on_le((uint16_t __sd_force)value); }
++static inline uint32_t be32toh(be32_t value) { return bswap_32_on_le((uint32_t __sd_force)value); }
++static inline uint64_t be64toh(be64_t value) { return bswap_64_on_le((uint64_t __sd_force)value); }
++
++#undef __sd_bitwise
++#undef __sd_force
+ 
+ #endif /* SPARSE_ENDIAN_H */
diff --git a/SOURCES/0608-core-Let-two-more-booleans-survive-a-daemon-reload.patch b/SOURCES/0608-core-Let-two-more-booleans-survive-a-daemon-reload.patch
new file mode 100644
index 0000000..67a3ed9
--- /dev/null
+++ b/SOURCES/0608-core-Let-two-more-booleans-survive-a-daemon-reload.patch
@@ -0,0 +1,76 @@
+From ab0cdf76c184cbe7f8376e0a2c8d7a60d10ca9b3 Mon Sep 17 00:00:00 2001
+From: Werner Fink <werner@suse.de>
+Date: Wed, 10 Jun 2015 14:36:50 +0200
+Subject: [PATCH] core: Let two more booleans survive a daemon-reload
+
+Without the boolean bus_name_good services as well as cgroup_realized
+for units a unit of Type=dbus and ExecReload sending SIGHUP to $MAINPID
+will be terminated if systemd will be daemon reloaded.
+
+https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=746151
+https://bugs.freedesktop.org/show_bug.cgi?id=78311
+https://bugzilla.opensuse.org/show_bug.cgi?id=934077
+
+Cherry-picked from: de1d4f9b5c6345f63edd46f643485eca909995bf
+Resolves: #1542391
+---
+ src/core/service.c |  9 +++++++++
+ src/core/unit.c    | 11 +++++++++++
+ 2 files changed, 20 insertions(+)
+
+diff --git a/src/core/service.c b/src/core/service.c
+index ceed1cc2e..71ec5e37c 100644
+--- a/src/core/service.c
++++ b/src/core/service.c
+@@ -2044,6 +2044,7 @@ static int service_serialize(Unit *u, FILE *f, FDSet *fds) {
+                 unit_serialize_item_format(u, f, "main-pid", PID_FMT, s->main_pid);
+ 
+         unit_serialize_item(u, f, "main-pid-known", yes_no(s->main_pid_known));
++        unit_serialize_item(u, f, "bus-name-good", yes_no(s->bus_name_good));
+ 
+         if (s->status_text)
+                 unit_serialize_item(u, f, "status-text", s->status_text);
+@@ -2264,6 +2265,14 @@ static int service_deserialize_item(Unit *u, const char *key, const char *value,
+                         log_unit_debug(u->id, "Failed to parse main-pid-known value %s", value);
+                 else
+                         s->main_pid_known = b;
++        } else if (streq(key, "bus-name-good")) {
++                int b;
++
++                b = parse_boolean(value);
++                if (b < 0)
++                        log_unit_debug(u->id, "Failed to parse bus-name-good value: %s", value);
++                else
++                        s->bus_name_good = b;
+         } else if (streq(key, "status-text")) {
+                 char *t;
+ 
+diff --git a/src/core/unit.c b/src/core/unit.c
+index 8c0fde878..41d7b63d7 100644
+--- a/src/core/unit.c
++++ b/src/core/unit.c
+@@ -2619,6 +2619,7 @@ int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs) {
+ 
+         if (u->cgroup_path)
+                 unit_serialize_item(u, f, "cgroup", u->cgroup_path);
++        unit_serialize_item(u, f, "cgroup-realized", yes_no(u->cgroup_realized));
+ 
+         if (serialize_jobs) {
+                 if (u->job) {
+@@ -2809,6 +2810,16 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) {
+                         u->cgroup_path = s;
+                         assert(hashmap_put(u->manager->cgroup_unit, s, u) == 1);
+ 
++                        continue;
++                } else if (streq(l, "cgroup-realized")) {
++                        int b;
++
++                        b = parse_boolean(v);
++                        if (b < 0)
++                                log_unit_debug(u->id, "Failed to parse cgroup-realized bool %s, ignoring.", v);
++                        else
++                                u->cgroup_realized = b;
++
+                         continue;
+                 }
+ 
diff --git a/SOURCES/0609-core-don-t-choke-if-a-unit-another-unit-triggers-van.patch b/SOURCES/0609-core-don-t-choke-if-a-unit-another-unit-triggers-van.patch
new file mode 100644
index 0000000..3a6a0a8
--- /dev/null
+++ b/SOURCES/0609-core-don-t-choke-if-a-unit-another-unit-triggers-van.patch
@@ -0,0 +1,212 @@
+From d7b2f6efd02375af4cf043ef9db6d316b65d4779 Mon Sep 17 00:00:00 2001
+From: Jan Synacek <jsynacek@redhat.com>
+Date: Fri, 16 Feb 2018 09:56:50 +0100
+Subject: [PATCH] core: don't choke if a unit another unit triggers vanishes
+ during reload
+
+Fixes: #1981
+
+(cherry picked from e903182e5b0daa941de47a9c08c824106cec7fe0)
+Resolves: #1545676
+---
+ src/core/automount.c | 25 +++++++++++++++++++++----
+ src/core/path.c      | 18 +++++++++++++++---
+ src/core/timer.c     | 30 ++++++++++++++++++++++++++----
+ 3 files changed, 62 insertions(+), 11 deletions(-)
+
+diff --git a/src/core/automount.c b/src/core/automount.c
+index 182ba5240..679fe071e 100644
+--- a/src/core/automount.c
++++ b/src/core/automount.c
+@@ -715,6 +715,7 @@ static int automount_start_expire(Automount *a) {
+ static void automount_enter_running(Automount *a) {
+         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+         struct stat st;
++        Unit *trigger;
+         int r;
+ 
+         assert(a);
+@@ -753,8 +754,13 @@ static void automount_enter_running(Automount *a) {
+                 return;
+         }
+ 
+-        r = manager_add_job(UNIT(a)->manager, JOB_START, UNIT_TRIGGER(UNIT(a)),
+-                        JOB_REPLACE, true, &error, NULL);
++        trigger = UNIT_TRIGGER(UNIT(a));
++        if (!trigger) {
++                log_unit_error(UNIT(a)->id, "Unit to trigger vanished.");
++                goto fail;
++        }
++
++        r = manager_add_job(UNIT(a)->manager, JOB_START, trigger, JOB_REPLACE, true, &error, NULL);
+         if (r < 0) {
+                 log_unit_warning(UNIT(a)->id,
+                                 "%s failed to queue mount startup job: %s",
+@@ -775,6 +781,7 @@ fail:
+ 
+ static int automount_start(Unit *u) {
+         Automount *a = AUTOMOUNT(u);
++        Unit *trigger;
+ 
+         assert(a);
+         assert(a->state == AUTOMOUNT_DEAD || a->state == AUTOMOUNT_FAILED);
+@@ -786,8 +793,11 @@ static int automount_start(Unit *u) {
+                 return -EEXIST;
+         }
+ 
+-        if (UNIT_TRIGGER(u)->load_state != UNIT_LOADED)
++        trigger = UNIT_TRIGGER(u);
++        if (!trigger || trigger->load_state != UNIT_LOADED) {
++                log_unit_error(u->id, "Refusing to start, unit to trigger not loaded.");
+                 return -ENOENT;
++        }
+ 
+         a->result = AUTOMOUNT_SUCCESS;
+         automount_enter_waiting(a);
+@@ -936,6 +946,7 @@ static int automount_dispatch_io(sd_event_source *s, int fd, uint32_t events, vo
+         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+         union autofs_v5_packet_union packet;
+         Automount *a = AUTOMOUNT(userdata);
++        Unit *trigger;
+         ssize_t l;
+         int r;
+ 
+@@ -1002,7 +1013,13 @@ static int automount_dispatch_io(sd_event_source *s, int fd, uint32_t events, vo
+                         log_unit_error_errno(UNIT(a)->id, r, "Failed to remember token: %m");
+                         goto fail;
+                 }
+-                r = manager_add_job(UNIT(a)->manager, JOB_STOP, UNIT_TRIGGER(UNIT(a)), JOB_REPLACE, true, &error, NULL);
++
++                trigger = UNIT_TRIGGER(UNIT(a));
++                if (!trigger) {
++                        log_unit_error(UNIT(a)->id, "Unit to trigger vanished.");
++                        goto fail;
++                }
++                r = manager_add_job(UNIT(a)->manager, JOB_STOP, trigger, JOB_REPLACE, true, &error, NULL);
+                 if (r < 0) {
+                         log_unit_warning(UNIT(a)->id,
+                                          "%s failed to queue umount startup job: %s",
+diff --git a/src/core/path.c b/src/core/path.c
+index 51e36fa8b..0533bb4e2 100644
+--- a/src/core/path.c
++++ b/src/core/path.c
+@@ -475,6 +475,7 @@ static void path_enter_dead(Path *p, PathResult f) {
+ 
+ static void path_enter_running(Path *p) {
+         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
++        Unit *trigger;
+         int r;
+ 
+         assert(p);
+@@ -483,8 +484,14 @@ static void path_enter_running(Path *p) {
+         if (unit_stop_pending(UNIT(p)))
+                 return;
+ 
+-        r = manager_add_job(UNIT(p)->manager, JOB_START, UNIT_TRIGGER(UNIT(p)),
+-                            JOB_REPLACE, true, &error, NULL);
++        trigger = UNIT_TRIGGER(UNIT(p));
++        if (!trigger) {
++                log_unit_error(UNIT(p)->id, "Unit to trigger vanished.");
++                path_enter_dead(p, TIMER_FAILURE_RESOURCES);
++                return;
++        }
++
++        r = manager_add_job(UNIT(p)->manager, JOB_START, trigger, JOB_REPLACE, true, &error, NULL);
+         if (r < 0)
+                 goto fail;
+ 
+@@ -566,12 +573,17 @@ static void path_mkdir(Path *p) {
+ 
+ static int path_start(Unit *u) {
+         Path *p = PATH(u);
++        Unit *trigger;
+ 
+         assert(p);
+         assert(p->state == PATH_DEAD || p->state == PATH_FAILED);
+ 
+-        if (UNIT_TRIGGER(u)->load_state != UNIT_LOADED)
++
++        trigger = UNIT_TRIGGER(u);
++        if (!trigger || trigger->load_state != UNIT_LOADED) {
++                log_unit_error(u->id, "Refusing to start, unit to trigger not loaded.");
+                 return -ENOENT;
++        }
+ 
+         path_mkdir(p);
+ 
+diff --git a/src/core/timer.c b/src/core/timer.c
+index f318dc6f4..91d8db67e 100644
+--- a/src/core/timer.c
++++ b/src/core/timer.c
+@@ -343,8 +343,18 @@ static void timer_enter_waiting(Timer *t, bool initial) {
+         usec_t ts_realtime, ts_monotonic;
+         usec_t base = 0;
+         TimerValue *v;
++        Unit *trigger;
+         int r;
+ 
++        assert(t);
++
++        trigger = UNIT_TRIGGER(UNIT(t));
++        if (!trigger) {
++                log_unit_error(UNIT(t)->id, "Unit to trigger vanished.");
++                timer_enter_dead(t, TIMER_FAILURE_RESOURCES);
++                return;
++        }
++
+         /* If we shall wake the system we use the boottime clock
+          * rather than the monotonic clock. */
+ 
+@@ -399,7 +409,7 @@ static void timer_enter_waiting(Timer *t, bool initial) {
+ 
+                         case TIMER_UNIT_ACTIVE:
+ 
+-                                base = UNIT_TRIGGER(UNIT(t))->inactive_exit_timestamp.monotonic;
++                                base = trigger->inactive_exit_timestamp.monotonic;
+ 
+                                 if (base <= 0)
+                                         base = t->last_trigger.monotonic;
+@@ -523,6 +533,7 @@ fail:
+ 
+ static void timer_enter_running(Timer *t) {
+         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
++        Unit *trigger;
+         int r;
+ 
+         assert(t);
+@@ -531,8 +542,15 @@ static void timer_enter_running(Timer *t) {
+         if (unit_stop_pending(UNIT(t)))
+                 return;
+ 
+-        r = manager_add_job(UNIT(t)->manager, JOB_START, UNIT_TRIGGER(UNIT(t)),
+-                            JOB_REPLACE, true, &error, NULL);
++
++        trigger = UNIT_TRIGGER(UNIT(t));
++        if (!trigger) {
++                log_unit_error(UNIT(t)->id, "Unit to trigger vanished.");
++                timer_enter_dead(t, TIMER_FAILURE_RESOURCES);
++                return;
++        }
++
++        r = manager_add_job(UNIT(t)->manager, JOB_START, trigger, JOB_REPLACE, true, &error, NULL);
+         if (r < 0)
+                 goto fail;
+ 
+@@ -554,12 +572,16 @@ fail:
+ static int timer_start(Unit *u) {
+         Timer *t = TIMER(u);
+         TimerValue *v;
++        Unit *trigger;
+ 
+         assert(t);
+         assert(t->state == TIMER_DEAD || t->state == TIMER_FAILED);
+ 
+-        if (UNIT_TRIGGER(u)->load_state != UNIT_LOADED)
++        trigger = UNIT_TRIGGER(u);
++        if (!trigger || trigger->load_state != UNIT_LOADED) {
++                log_unit_error(u->id, "Refusing to start, unit to trigger not loaded.");
+                 return -ENOENT;
++        }
+ 
+         t->last_trigger = DUAL_TIMESTAMP_NULL;
+ 
diff --git a/SOURCES/0610-sd-journal-properly-handle-inotify-queue-overflow.patch b/SOURCES/0610-sd-journal-properly-handle-inotify-queue-overflow.patch
new file mode 100644
index 0000000..c3f7d24
--- /dev/null
+++ b/SOURCES/0610-sd-journal-properly-handle-inotify-queue-overflow.patch
@@ -0,0 +1,442 @@
+From 7204e7f9ea3067bda7e5658a06e91b67c736f8ab Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Mon, 12 Feb 2018 16:14:58 +0100
+Subject: [PATCH] sd-journal: properly handle inotify queue overflow
+
+This adds proper handling of IN_Q_OVERFLOW: when the inotify queue runs
+over we'll reiterate all directories we are looking at. At the same time
+we'll mark all files and directories we encounter that way with a
+generation counter we first increased. All files and directories not
+marked like this are then unloaded.
+
+With this logic we do the best when the inotify queue overflows: we
+synchronize our in-memory state again with what's on disk.  This
+contains some refactoring of the directory logic, to share more code
+between uuid directories and "root" directories and generally make
+things a bit more readable by splitting things up into smaller bits.
+
+See: #7998 #8032
+
+(cherry-picked from commit 858749f7312bd0adb5433075a92e1c35a2fb56ac)
+
+Resolves: #1540538
+---
+ src/journal/journal-file.h     |   2 +
+ src/journal/journal-internal.h |   2 +
+ src/journal/sd-journal.c       | 237 ++++++++++++++++++++++++++++++++---------
+ src/shared/path-util.c         |  14 +++
+ src/shared/path-util.h         |   2 +
+ 5 files changed, 206 insertions(+), 51 deletions(-)
+
+diff --git a/src/journal/journal-file.h b/src/journal/journal-file.h
+index c74ad5fc5..dd8ef52d2 100644
+--- a/src/journal/journal-file.h
++++ b/src/journal/journal-file.h
+@@ -121,6 +121,8 @@ typedef struct JournalFile {
+ 
+         void *fsprg_seed;
+         size_t fsprg_seed_size;
++
++        unsigned last_seen_generation;
+ #endif
+ } JournalFile;
+ 
+diff --git a/src/journal/journal-internal.h b/src/journal/journal-internal.h
+index eb23ac28a..999e9d8cb 100644
+--- a/src/journal/journal-internal.h
++++ b/src/journal/journal-internal.h
+@@ -81,6 +81,7 @@ struct Directory {
+         char *path;
+         int wd;
+         bool is_root;
++        unsigned last_seen_generation;
+ };
+ 
+ struct sd_journal {
+@@ -102,6 +103,7 @@ struct sd_journal {
+         int inotify_fd;
+         unsigned current_invalidate_counter, last_invalidate_counter;
+         usec_t last_process_usec;
++        unsigned generation;
+ 
+         char *unique_field;
+         JournalFile *unique_file;
+diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c
+index 14b65cfed..9186f5188 100644
+--- a/src/journal/sd-journal.c
++++ b/src/journal/sd-journal.c
+@@ -1229,8 +1229,16 @@ static int add_any_file(sd_journal *j, const char *path) {
+         assert(j);
+         assert(path);
+ 
+-        if (ordered_hashmap_get(j->files, path))
+-                return 0;
++        if (path) {
++                f = ordered_hashmap_get(j->files, path);
++                if (f) {
++                        /* Mark this file as seen in this generation. This is used to GC old files in
++                         * process_q_overflow() to detect journal files that are still and discern them from those who
++                         * are gone. */
++                        f->last_seen_generation = j->generation;
++                        return 0;
++                }
++        }
+ 
+         if (ordered_hashmap_size(j->files) >= JOURNAL_FILES_MAX) {
+                 log_debug("Too many open journal files, not adding %s.", path);
+@@ -1252,6 +1260,8 @@ static int add_any_file(sd_journal *j, const char *path) {
+                 goto fail;
+         }
+ 
++        f->last_seen_generation = j->generation;
++
+         log_debug("File %s added.", f->path);
+ 
+         check_network(j, f->fd);
+@@ -1346,10 +1356,96 @@ static int dirname_is_machine_id(const char *fn) {
+         return sd_id128_equal(id, machine);
+ }
+ 
++static bool dirent_is_journal_file(const struct dirent *de) {
++        assert(de);
++
++        if (!IN_SET(de->d_type, DT_REG, DT_LNK, DT_UNKNOWN))
++                return false;
++
++        return endswith(de->d_name, ".journal") ||
++                endswith(de->d_name, ".journal~");
++}
++
++static bool dirent_is_id128_subdir(const struct dirent *de) {
++        assert(de);
++
++        if (!IN_SET(de->d_type, DT_DIR, DT_LNK, DT_UNKNOWN))
++                return false;
++
++        return id128_is_valid(de->d_name);
++}
++
++static int directory_open(sd_journal *j, const char *path, DIR **ret) {
++        DIR *d;
++
++        assert(j);
++        assert(path);
++        assert(ret);
++
++        d = opendir(path);
++        if (!d)
++                return -errno;
++
++        *ret = d;
++        return 0;
++}
++
++static int add_directory(sd_journal *j, const char *prefix, const char *dirname);
++
++static void directory_enumerate(sd_journal *j, Directory *m, DIR *d) {
++        struct dirent *de;
++
++        assert(j);
++        assert(m);
++        assert(d);
++
++        FOREACH_DIRENT_ALL(de, d, goto fail) {
++                if (dirent_is_journal_file(de))
++                        (void) add_file(j, m->path, de->d_name);
++
++                if (m->is_root && dirent_is_id128_subdir(de))
++                        (void) add_directory(j, m->path, de->d_name);
++        }
++
++        return;
++
++fail:
++        log_debug_errno(errno, "Failed to enumerate directory %s, ignoring: %m", m->path);
++}
++
++static void directory_watch(sd_journal *j, Directory *m, int fd, uint32_t mask) {
++        int r;
++
++        assert(j);
++        assert(m);
++        assert(fd >= 0);
++
++        /* Watch this directory if that's enabled and if it not being watched yet. */
++
++        if (m->wd > 0) /* Already have a watch? */
++                return;
++        if (j->inotify_fd < 0) /* Not watching at all? */
++                return;
++
++        m->wd = inotify_add_watch_fd(j->inotify_fd, fd, mask);
++        if (m->wd < 0) {
++                log_debug_errno(errno, "Failed to watch journal directory '%s', ignoring: %m", m->path);
++                return;
++        }
++
++        r = hashmap_put(j->directories_by_wd, INT_TO_PTR(m->wd), m);
++        if (r == -EEXIST)
++                log_debug_errno(r, "Directory '%s' already being watched under a different path, ignoring: %m", m->path);
++        if (r < 0) {
++                log_debug_errno(r, "Failed to add watch for journal directory '%s' to hashmap, ignoring: %m", m->path);
++                (void) inotify_rm_watch(j->inotify_fd, m->wd);
++                m->wd = -1;
++        }
++}
++
+ static int add_directory(sd_journal *j, const char *prefix, const char *dirname) {
+         _cleanup_free_ char *path = NULL;
+         _cleanup_closedir_ DIR *d = NULL;
+-        struct dirent *de = NULL;
+         Directory *m;
+         int r, k;
+ 
+@@ -1357,7 +1453,7 @@ static int add_directory(sd_journal *j, const char *prefix, const char *dirname)
+         assert(prefix);
+         assert(dirname);
+ 
+-        log_debug("Considering %s/%s.", prefix, dirname);
++        log_debug("Considering '%s/%s'.", prefix, dirname);
+ 
+         if ((j->flags & SD_JOURNAL_LOCAL_ONLY) &&
+             !(dirname_is_machine_id(dirname) > 0 || path_startswith(prefix, "/run")))
+@@ -1369,9 +1465,9 @@ static int add_directory(sd_journal *j, const char *prefix, const char *dirname)
+                 goto fail;
+         }
+ 
+-        d = opendir(path);
+-        if (!d) {
+-                r = log_debug_errno(errno, "Failed to open directory %s: %m", path);
++        r = directory_open(j, path, &d);
++        if (r < 0) {
++                r = log_debug_errno(errno, "Failed to open directory '%s': %m", path);
+                 goto fail;
+         }
+ 
+@@ -1398,25 +1494,17 @@ static int add_directory(sd_journal *j, const char *prefix, const char *dirname)
+                 log_debug("Directory %s added.", m->path);
+ 
+         } else if (m->is_root)
+-                return 0;
+-
+-        if (m->wd <= 0 && j->inotify_fd >= 0) {
+-
+-                m->wd = inotify_add_watch(j->inotify_fd, m->path,
+-                                          IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB|IN_DELETE|
+-                                          IN_DELETE_SELF|IN_MOVE_SELF|IN_UNMOUNT|IN_MOVED_FROM|
+-                                          IN_ONLYDIR);
++                return 0; /* Don't 'downgrade' from root directory */
+ 
+-                if (m->wd > 0 && hashmap_put(j->directories_by_wd, INT_TO_PTR(m->wd), m) < 0)
+-                        inotify_rm_watch(j->inotify_fd, m->wd);
+-        }
++        m->last_seen_generation = j->generation;
+ 
+-        FOREACH_DIRENT_ALL(de, d, return log_debug_errno(errno, "Failed to read directory %s: %m", m->path)) {
++        directory_watch(j, m, dirfd(d),
++                        IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB|IN_DELETE|
++                        IN_DELETE_SELF|IN_MOVE_SELF|IN_UNMOUNT|IN_MOVED_FROM|
++                        IN_ONLYDIR);
+ 
+-                if (dirent_is_file_with_suffix(de, ".journal") ||
+-                    dirent_is_file_with_suffix(de, ".journal~"))
+-                        (void) add_file(j, m->path, de->d_name);
+-        }
++        if (!j->no_new_files)
++                directory_enumerate(j, m, d);
+ 
+         check_network(j, dirfd(d));
+ 
+@@ -1432,13 +1520,14 @@ fail:
+ 
+ static int add_root_directory(sd_journal *j, const char *p, bool missing_ok) {
+         _cleanup_closedir_ DIR *d = NULL;
+-        struct dirent *de;
+         Directory *m;
+         int r, k;
+ 
+         assert(j);
+         assert(p);
+ 
++        log_debug("Considering root directory '%s'.", p);
++
+         if ((j->flags & SD_JOURNAL_RUNTIME_ONLY) &&
+             !path_startswith(p, "/run"))
+                 return -EINVAL;
+@@ -1446,12 +1535,11 @@ static int add_root_directory(sd_journal *j, const char *p, bool missing_ok) {
+         if (j->prefix)
+                 p = strjoina(j->prefix, p);
+ 
+-        d = opendir(p);
+-        if (!d) {
+-                if (errno == ENOENT && missing_ok)
+-                        return 0;
+-
+-                r = log_debug_errno(errno, "Failed to open root directory %s: %m", p);
++        r = directory_open(j, p, &d);
++        if (r == -ENOENT && missing_ok)
++                return 0;
++        if (r < 0) {
++                log_debug_errno(r, "Failed to open root directory %s: %m", p);
+                 goto fail;
+         }
+ 
+@@ -1495,19 +1583,12 @@ static int add_root_directory(sd_journal *j, const char *p, bool missing_ok) {
+                         inotify_rm_watch(j->inotify_fd, m->wd);
+         }
+ 
+-        if (j->no_new_files)
+-                return 0;
+-
+-        FOREACH_DIRENT_ALL(de, d, return log_debug_errno(errno, "Failed to read directory %s: %m", m->path)) {
+-                sd_id128_t id;
++        directory_watch(j, m, dirfd(d),
++                        IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB|IN_DELETE|
++                        IN_ONLYDIR);
+ 
+-                if (dirent_is_file_with_suffix(de, ".journal") ||
+-                    dirent_is_file_with_suffix(de, ".journal~"))
+-                        (void) add_file(j, m->path, de->d_name);
+-                else if (IN_SET(de->d_type, DT_DIR, DT_LNK, DT_UNKNOWN) &&
+-                         sd_id128_from_string(de->d_name, &id) >= 0)
+-                        (void) add_directory(j, m->path, de->d_name);
+-        }
++        if (!j->no_new_files)
++                directory_enumerate(j, m, d);
+ 
+         check_network(j, dirfd(d));
+ 
+@@ -2068,6 +2149,18 @@ _public_ void sd_journal_restart_data(sd_journal *j) {
+         j->current_field = 0;
+ }
+ 
++static int reiterate_all_paths(sd_journal *j) {
++        assert(j);
++
++        if (j->no_new_files)
++                return add_current_paths(j);
++
++        if (j->path)
++                return add_root_directory(j, j->path, true);
++
++        return add_search_paths(j);
++}
++
+ _public_ int sd_journal_get_fd(sd_journal *j) {
+         int r;
+ 
+@@ -2081,15 +2174,11 @@ _public_ int sd_journal_get_fd(sd_journal *j) {
+         if (r < 0)
+                 return r;
+ 
+-        /* Iterate through all dirs again, to add them to the
+-         * inotify */
+-        if (j->no_new_files)
+-                r = add_current_paths(j);
+-        else if (j->path)
+-                r = add_root_directory(j, j->path, true);
+-        else
+-                r = add_search_paths(j);
+-        if (r < 0)
++         log_debug("Reiterating files to get inotify watches established.");
++
++        /* Iterate through all dirs again, to add them to the inotify */
++        r = reiterate_all_paths(j);
++         if (r < 0)
+                 return r;
+ 
+         return j->inotify_fd;
+@@ -2131,12 +2220,58 @@ _public_ int sd_journal_get_timeout(sd_journal *j, uint64_t *timeout_usec) {
+         return 1;
+ }
+ 
++static void process_q_overflow(sd_journal *j) {
++        JournalFile *f;
++        Directory *m;
++        Iterator i;
++
++        assert(j);
++
++        /* When the inotify queue overruns we need to enumerate and re-validate all journal files to bring our list
++         * back in sync with what's on disk. For this we pick a new generation counter value. It'll be assigned to all
++         * journal files we encounter. All journal files and all directories that don't carry it after reenumeration
++         * are subject for unloading. */
++
++        log_debug("Inotify queue overrun, reiterating everything.");
++
++        j->generation++;
++        (void) reiterate_all_paths(j);
++
++        ORDERED_HASHMAP_FOREACH(f, j->files, i) {
++
++                if (f->last_seen_generation == j->generation)
++                        continue;
++
++                log_debug("File '%s' hasn't been seen in this enumeration, removing.", f->path);
++                remove_file_real(j, f);
++        }
++
++        HASHMAP_FOREACH(m, j->directories_by_path, i) {
++
++                if (m->last_seen_generation == j->generation)
++                        continue;
++
++                if (m->is_root) /* Never GC root directories */
++                        continue;
++
++                log_debug("Directory '%s' hasn't been seen in this enumeration, removing.", f->path);
++                remove_directory(j, m);
++        }
++
++        log_debug("Reiteration complete.");
++}
++
+ static void process_inotify_event(sd_journal *j, struct inotify_event *e) {
+         Directory *d;
+ 
+         assert(j);
+         assert(e);
+ 
++        if (e->mask & IN_Q_OVERFLOW) {
++                process_q_overflow(j);
++                return;
++        }
++
+         /* Is this a subdirectory we watch? */
+         d = hashmap_get(j->directories_by_wd, INT_TO_PTR(e->wd));
+         if (d) {
+diff --git a/src/shared/path-util.c b/src/shared/path-util.c
+index 5d4de9ec4..fcc591686 100644
+--- a/src/shared/path-util.c
++++ b/src/shared/path-util.c
+@@ -861,3 +861,17 @@ char *prefix_root(const char *root, const char *path) {
+         strcpy(p, path);
+         return n;
+ }
++
++int inotify_add_watch_fd(int fd, int what, uint32_t mask) {
++        char path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1];
++        int r;
++
++        /* This is like inotify_add_watch(), except that the file to watch is not referenced by a path, but by an fd */
++        xsprintf(path, "/proc/self/fd/%i", what);
++
++        r = inotify_add_watch(fd, path, mask);
++        if (r < 0)
++                return -errno;
++
++        return r;
++}
+diff --git a/src/shared/path-util.h b/src/shared/path-util.h
+index 34c016229..96490e12b 100644
+--- a/src/shared/path-util.h
++++ b/src/shared/path-util.h
+@@ -66,6 +66,8 @@ int fsck_exists(const char *fstype);
+ 
+ char *prefix_root(const char *root, const char *path);
+ 
++int inotify_add_watch_fd(int fd, int what, uint32_t mask);
++
+ /* Similar to prefix_root(), but returns an alloca() buffer, or
+  * possibly a const pointer into the path parameter */
+ #define prefix_roota(root, path)                                        \
diff --git a/SOURCES/0611-sd-journal-make-sure-it-s-safe-to-call-sd_journal_pr.patch b/SOURCES/0611-sd-journal-make-sure-it-s-safe-to-call-sd_journal_pr.patch
new file mode 100644
index 0000000..26c212a
--- /dev/null
+++ b/SOURCES/0611-sd-journal-make-sure-it-s-safe-to-call-sd_journal_pr.patch
@@ -0,0 +1,36 @@
+From efd523764efcd39340fb62875716c8c8b79f0de9 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Fri, 9 Feb 2018 22:38:46 +0100
+Subject: [PATCH] sd-journal: make sure it's safe to call sd_journal_process()
+ before the first sd_journal_wait()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+In that case we have no inotify fd yet, and there's nothing to process
+hence. Let's make the call a NOP.
+
+(Previously, without this change we'd end up trying to read off inotify
+fd -1, which is quite a problem... 😢)
+
+(cherry picked from commit 10c4d6405f74258ea4fac5db4888c1bf49ad5399)
+
+Related: #1540538
+---
+ src/journal/sd-journal.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c
+index 9186f5188..e1cde6e1c 100644
+--- a/src/journal/sd-journal.c
++++ b/src/journal/sd-journal.c
+@@ -2329,6 +2329,9 @@ _public_ int sd_journal_process(sd_journal *j) {
+         assert_return(j, -EINVAL);
+         assert_return(!journal_pid_changed(j), -ECHILD);
+ 
++        if (j->inotify_fd < 0) /* We have no inotify fd yet? Then there's noting to process. */
++                return 0;
++
+         j->last_process_usec = now(CLOCK_MONOTONIC);
+         j->last_invalidate_counter = j->current_invalidate_counter;
+ 
diff --git a/SOURCES/0612-journalctl-Periodically-call-sd_journal_process-in-j.patch b/SOURCES/0612-journalctl-Periodically-call-sd_journal_process-in-j.patch
new file mode 100644
index 0000000..026f18b
--- /dev/null
+++ b/SOURCES/0612-journalctl-Periodically-call-sd_journal_process-in-j.patch
@@ -0,0 +1,59 @@
+From 98169577b83b45a40105cf58e6cffe0272074817 Mon Sep 17 00:00:00 2001
+From: Peter Portante <peter.a.portante@gmail.com>
+Date: Sun, 28 Jan 2018 16:48:04 -0500
+Subject: [PATCH] journalctl: Periodically call sd_journal_process in
+ journalctl
+
+If `journalctl` take a long time to process messages, and during that
+time journal file rotation occurs, a `journalctl` client will keep
+those rotated files open until it calls `sd_journal_process()`, which
+typically happens as a result of calling `sd_journal_wait()` below in
+the "following" case.  By periodically calling `sd_journal_process()`
+during the processing loop we shrink the window of time a client
+instance has open file descriptors for rotated (deleted) journal
+files.
+
+(Lennart: slightly reworked version, that dropped some of the commenting
+which was solved otherwise)
+
+(cherry picked from commit ec316d199a13d8db3f6550d60e369893de2fb417)
+
+Related: #1540538
+---
+ src/journal/journalctl.c | 16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
+
+diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
+index 0be70764e..1e6d0761c 100644
+--- a/src/journal/journalctl.c
++++ b/src/journal/journalctl.c
+@@ -67,6 +67,8 @@
+ 
+ #define DEFAULT_FSS_INTERVAL_USEC (15*USEC_PER_MINUTE)
+ 
++#define PROCESS_INOTIFY_INTERVAL 1024   /* Every 1,024 messages processed */
++
+ enum {
+         /* Special values for arg_lines */
+         ARG_LINES_DEFAULT = -2,
+@@ -2294,6 +2296,20 @@ int main(int argc, char *argv[]) {
+                                 goto finish;
+ 
+                         n_shown++;
++
++                        /* If journalctl take a long time to process messages, and during that time journal file
++                         * rotation occurs, a journalctl client will keep those rotated files open until it calls
++                         * sd_journal_process(), which typically happens as a result of calling sd_journal_wait() below
++                         * in the "following" case.  By periodically calling sd_journal_process() during the processing
++                         * loop we shrink the window of time a client instance has open file descriptors for rotated
++                         * (deleted) journal files. */
++                        if ((n_shown % PROCESS_INOTIFY_INTERVAL) == 0) {
++                                r = sd_journal_process(j);
++                                if (r < 0) {
++                                        log_error_errno(r, "Failed to process inotify events: %m");
++                                        goto finish;
++                                }
++                        }
+                 }
+ 
+                 if (!arg_follow) {
diff --git a/SOURCES/0613-sd-journal-when-picking-up-a-new-file-compare-inode-.patch b/SOURCES/0613-sd-journal-when-picking-up-a-new-file-compare-inode-.patch
new file mode 100644
index 0000000..94dca30
--- /dev/null
+++ b/SOURCES/0613-sd-journal-when-picking-up-a-new-file-compare-inode-.patch
@@ -0,0 +1,77 @@
+From febbc3baae65db64692e3ae2852630c5e324ab43 Mon Sep 17 00:00:00 2001
+From: Michal Sekletar <msekleta@redhat.com>
+Date: Tue, 20 Feb 2018 14:16:15 +0100
+Subject: [PATCH] sd-journal: when picking up a new file, compare inode/device
+ info with previous open file by same name
+
+Let's make sure we aren't confused if a journal file is replaced by a
+different one (for example due to rotation) if we are in a q overflow:
+let's compare the inode/device information, and if it changed replace
+any open file object as needed.
+
+Fixes: #8198
+
+(cherry-picked from commit 32cb1983ad6f7084ff86e259ff079742a8139719)
+
+[msekleta: this is very slimmed down version of the above commit because
+a lot of code from is not applicable to RHEL-7 version]
+
+Related: #1540538
+---
+ src/journal/sd-journal.c | 35 +++++++++++++++++++++++++++++------
+ 1 file changed, 29 insertions(+), 6 deletions(-)
+
+diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c
+index e1cde6e1c..004fe646d 100644
+--- a/src/journal/sd-journal.c
++++ b/src/journal/sd-journal.c
+@@ -1224,20 +1224,43 @@ static bool file_type_wanted(int flags, const char *filename) {
+ 
+ static int add_any_file(sd_journal *j, const char *path) {
+         JournalFile *f = NULL;
++        struct stat st;
+         int r, k;
+ 
+         assert(j);
+         assert(path);
+ 
+-        if (path) {
+-                f = ordered_hashmap_get(j->files, path);
+-                if (f) {
+-                        /* Mark this file as seen in this generation. This is used to GC old files in
+-                         * process_q_overflow() to detect journal files that are still and discern them from those who
+-                         * are gone. */
++        if (stat(path, &st) < 0) {
++                r = log_debug_errno(errno, "Failed to stat file '%s': %m", path);
++                return -errno;
++        }
++        if (S_ISDIR(st.st_mode)) {
++                log_debug("Uh, file '%s' is a directory? Refusing.", path);
++                return -EISDIR;
++        }
++        if (!S_ISREG(st.st_mode)) {
++                log_debug("Uh, file '%s' is not a regular file? Refusing.", path);
++                return -EBADFD;
++        }
++
++        f = ordered_hashmap_get(j->files, path);
++        if (f) {
++
++                if (f->last_stat.st_dev == st.st_dev &&
++                    f->last_stat.st_ino == st.st_ino) {
++
++                        /* We already track this file, under the same path and with the same device/inode numbers, it's hence
++                         * really the same. Mark this file as seen in this generation. This is used to GC old files in
++                         * process_q_overflow() to detect journal files that are still and discern them from those who are
++                         * gone. */
+                         f->last_seen_generation = j->generation;
+                         return 0;
+                 }
++
++                /* So we tracked a file under this name, but it has a different inode/device. In that case, it got
++                 * replaced (probably due to rotation?), let's drop it hence from our list. */
++                remove_file_real(j, f);
++                f = NULL;
+         }
+ 
+         if (ordered_hashmap_size(j->files) >= JOURNAL_FILES_MAX) {
diff --git a/SOURCES/76-phys-port-name.rules b/SOURCES/76-phys-port-name.rules
index 92bb25a..067f73a 100644
--- a/SOURCES/76-phys-port-name.rules
+++ b/SOURCES/76-phys-port-name.rules
@@ -4,5 +4,6 @@ SUBSYSTEM!="net", GOTO="phys_port_name_end"
 
 DRIVERS=="mlxsw*", ATTR{phys_port_name}=="?*", IMPORT{program}="/usr/lib/udev/phys-port-name-gen %k"
 DRIVERS=="rocker", ATTR{phys_port_name}=="?*", IMPORT{program}="/usr/lib/udev/phys-port-name-gen %k"
+DRIVERS=="nfp*", ATTR{phys_port_name}=="?*", IMPORT{program}="/usr/lib/udev/phys-port-name-gen %k"
 
 LABEL="phys_port_name_end"
diff --git a/SPECS/systemd.spec b/SPECS/systemd.spec
index a81bb0c..6bdbb74 100644
--- a/SPECS/systemd.spec
+++ b/SPECS/systemd.spec
@@ -7,7 +7,7 @@
 Name:           systemd
 Url:            http://www.freedesktop.org/wiki/Software/systemd
 Version:        219
-Release:        42%{?dist}.10
+Release:        57%{?dist}
 # For a breakdown of the licensing, see README
 License:        LGPLv2+ and MIT and GPLv2+
 Summary:        A System and Service Manager
@@ -537,25 +537,121 @@ Patch0495: 0495-systemd-notify-Always-pass-a-valid-pid-to-sd_pid_not.patch
 Patch0496: 0496-sd_pid_notify_with_fds-fix-computing-msg_controllen.patch
 Patch0497: 0497-rules-move-cpu-hotplug-rule-to-separate-file.patch
 Patch0498: 0498-Revert-rules-move-cpu-hotplug-rule-to-separate-file.patch
-Patch0499: 0499-Revert-udev-net_id-add-support-for-phys_port_name-at.patch
-Patch0500: 0500-sysctl-fix-uninitialized-variable.patch
-Patch0501: 0501-udev-ignore-SIGCHLD-from-unexpected-processes-130653.patch
-Patch0502: 0502-manager-when-reexecuting-try-to-connect-to-bus-only-.patch
-Patch0503: 0503-unmount-Pass-in-mount-options-when-remounting-read-o.patch
-Patch0504: 0504-shutdown-don-t-remount-ro-network-filesystems.-6588.patch
-Patch0505: 0505-shutdown-fix-incorrect-fscanf-result-check-6806.patch
-Patch0506: 0506-manager-fix-connecting-to-bus-when-dbus-is-actually-.patch
-Patch0507: 0507-automount-ack-automount-requests-even-when-already-m.patch
-Patch0508: 0508-shared-cgroup-utils-_CGROUP_CONTROLLER_MASK_ALL-does.patch
-Patch0509: 0509-core-execute-fix-fork-fail-handling-in-exec_spawn.patch
-Patch0510: 0510-journal-remove-error-check-that-never-happens.patch
-Patch0511: 0511-sd-journal-various-clean-ups-and-modernizations.patch
-Patch0512: 0512-journalctl-continue-operation-even-if-we-run-into-an.patch
-Patch0513: 0513-journalctl-when-we-fail-to-open-a-journal-file-print.patch
-Patch0514: 0514-sd-journal-properly-handle-inotify-queue-overflow.patch
-Patch0515: 0515-sd-journal-make-sure-it-s-safe-to-call-sd_journal_pr.patch
-Patch0516: 0516-sd-journal-when-picking-up-a-new-file-compare-inode-.patch
-Patch0517: 0517-journalctl-Periodically-call-sd_journal_process-in-j.patch
+Patch0499: 0499-tests-use-XFS-as-root-filesystem-for-system-tests.patch
+Patch0500: 0500-tests-use-fdisk-instead-of-sfdisk.patch
+Patch0501: 0501-Revert-udev-net_id-add-support-for-phys_port_name-at.patch
+Patch0502: 0502-core-unset-sysfs-path-after-transition-to-dead-state.patch
+Patch0503: 0503-sysctl-fix-uninitialized-variable.patch
+Patch0504: 0504-udev-ignore-SIGCHLD-from-unexpected-processes-130653.patch
+Patch0505: 0505-compile-with-Werror.patch
+Patch0506: 0506-myhostname-don-t-return-any-ipv6-entries-when-ipv6-i.patch
+Patch0507: 0507-core-execute-fix-fork-fail-handling-in-exec_spawn.patch
+Patch0508: 0508-fix-compilation-after-commit-382877acc6c029e59e359a0.patch
+Patch0509: 0509-Redefine-32bit-time_t-format-to-signed.patch
+Patch0510: 0510-sd-bus-bus-kernel.c-fix-format-errors-on-ppc64le.patch
+Patch0511: 0511-tmpfiles-with-e-don-t-attempt-to-set-permissions-whe.patch
+Patch0512: 0512-units-introduce-getty-pre.target-6667.patch
+Patch0513: 0513-units-order-container-and-console-getty-units-after-.patch
+Patch0514: 0514-log-never-log-into-foreign-fd-2-in-PID-1-or-its-pre-.patch
+Patch0515: 0515-nspawn-new-option-to-start-as-PID2.patch
+Patch0516: 0516-journal-implicitly-flush-to-var-on-recovery-4028.patch
+Patch0517: 0517-journal-add-use-flushed_flag_is_set-helper-4041.patch
+Patch0518: 0518-journald-don-t-flush-to-var-log-journal-before-we-ge.patch
+Patch0519: 0519-path-util-make-use-of-mnt_id-field-exported-in-proc-.patch
+Patch0520: 0520-Revert-Revert-journald-allow-restarting-journald-wit.patch
+Patch0521: 0521-journald-make-sure-we-retain-all-stream-fds-across-r.patch
+Patch0522: 0522-Allow-systemd-tmpfiles-to-set-the-file-directory-att.patch
+Patch0523: 0523-tmpfiles-rework-file-attribute-code.patch
+Patch0524: 0524-tmpfiles-warn-if-we-get-an-argument-on-lines-that-do.patch
+Patch0525: 0525-tmpfiles-substitute-specifiers-in-arguments-for-writ.patch
+Patch0526: 0526-btrfs-util-introduce-btrfs_is_filesystem-and-make-us.patch
+Patch0527: 0527-journal-don-t-force-FS_NOCOW_FL-on-new-journal-files.patch
+Patch0528: 0528-tmpfiles-Add-C-attrib-to-the-journal-files-directori.patch
+Patch0529: 0529-Revert-path-util-make-use-of-mnt_id-field-exported-i.patch
+Patch0530: 0530-device-make-sure-to-remove-all-device-units-sharing-.patch
+Patch0531: 0531-manager-when-reexecuting-try-to-connect-to-bus-only-.patch
+Patch0532: 0532-doc-document-service-exit-codes.patch
+Patch0533: 0533-units-order-cryptsetup-pre.target-before-cryptsetup..patch
+Patch0534: 0534-man-add-an-explicit-description-of-_netdev-to-system.patch
+Patch0535: 0535-units-add-remote-cryptsetup.target-and-remote-crypts.patch
+Patch0536: 0536-cryptsetup-generator-use-remote-cryptsetup.target-wh.patch
+Patch0537: 0537-Support-rdma-as-a-ListenNetlink-argument-6626.patch
+Patch0538: 0538-core-namespace-Protect-usr-instead-of-home-with-Prot.patch
+Patch0539: 0539-udev-Use-parent-bus-id-for-virtio-disk-builtin-path-.patch
+Patch0540: 0540-socket-util-socket_address_parse-should-not-log-erro.patch
+Patch0541: 0541-test-fix-failing-test-socket-util-when-running-with-.patch
+Patch0542: 0542-scsi_id-add-missing-options-to-getopt_long-6501.patch
+Patch0543: 0543-unmount-Pass-in-mount-options-when-remounting-read-o.patch
+Patch0544: 0544-shutdown-don-t-remount-ro-network-filesystems.-6588.patch
+Patch0545: 0545-shutdown-fix-incorrect-fscanf-result-check-6806.patch
+Patch0546: 0546-path-util-make-use-of-mnt_id-field-exported-in-proc-.patch
+Patch0547: 0547-support-ranges-when-parsing-CPUAffinity.patch
+Patch0548: 0548-man-Update-man-page-documentation-for-CPUAffinity.patch
+Patch0549: 0549-test-path-util-force-rm_rf.patch
+Patch0550: 0550-Export-NVMe-WWID-udev-attribute-5348.patch
+Patch0551: 0551-mount-make-sure-we-unmount-tmpfs-mounts-before-we-de.patch
+Patch0552: 0552-journald-never-accept-fds-from-file-systems-with-man.patch
+Patch0553: 0553-udev-builtin-keyboard-move-fetching-the-device-node-.patch
+Patch0554: 0554-udev-builtin-keyboard-immediately-EVIOCSKEYCODE-when.patch
+Patch0555: 0555-udev-builtin-keyboard-move-actual-key-mapping-to-a-h.patch
+Patch0556: 0556-udev-builtin-keyboard-invert-a-condition.patch
+Patch0557: 0557-udev-builtin-keyboard-add-support-for-EVDEV_ABS_.patch
+Patch0558: 0558-hwdb-sync-60-evdev.hwdb-from-systemd-v235.patch
+Patch0559: 0559-journal-ensure-open-journals-from-find_journal-3973.patch
+Patch0560: 0560-journal-only-check-available-space-when-journal-is-o.patch
+Patch0561: 0561-automount-if-an-automount-unit-is-masked-don-t-react.patch
+Patch0562: 0562-units-add-Install-section-to-remote-cryptsetup.targe.patch
+Patch0563: 0563-units-replace-remote-cryptsetup-pre.target-with-remo.patch
+Patch0564: 0564-man-add-a-note-about-_netdev-usage.patch
+Patch0565: 0565-units-make-remote-cryptsetup.target-also-after-crypt.patch
+Patch0566: 0566-cryptsetup-generator-use-after-free.patch
+Patch0567: 0567-manager-fix-connecting-to-bus-when-dbus-is-actually-.patch
+Patch0568: 0568-journal-remote-make-url-option-support-arbitrary-url.patch
+Patch0569: 0569-journald-make-maximum-size-of-stream-log-lines-confi.patch
+Patch0570: 0570-service-serialize-information-about-currently-execut.patch
+Patch0571: 0571-tests-add-new-test-for-issue-518.patch
+Patch0572: 0572-tests-in-RHEL-7-we-don-t-have-python3-by-default.patch
+Patch0573: 0573-service-attempt-to-execute-next-main-command-only-fo.patch
+Patch0574: 0574-timedatectl-stop-using-xstrftime.patch
+Patch0575: 0575-Add-support-to-read-lz4-compressed-journals.patch
+Patch0576: 0576-journald-never-block-when-sending-messages-on-NOTIFY.patch
+Patch0577: 0577-journal-restore-watchdog-support.patch
+Patch0578: 0578-cgroup-resource-property-setting-ignored-if-einval.patch
+Patch0579: 0579-fileio-add-new-helper-call-read_line-as-bounded-getl.patch
+Patch0580: 0580-def-add-new-constant-LONG_LINE_MAX.patch
+Patch0581: 0581-fileio-rework-read_one_line_file-on-top-of-read_line.patch
+Patch0582: 0582-cgroup-util-replace-one-use-of-fgets-by-read_line.patch
+Patch0583: 0583-conf-parse-remove-4K-line-length-limit.patch
+Patch0584: 0584-test-conf-parser-add-tests-for-config-parser.patch
+Patch0585: 0585-fileio-use-_cleanup_-for-FILE-unlocking.patch
+Patch0586: 0586-test-fileio-also-test-read_line-with-actual-files.patch
+Patch0587: 0587-fileio-return-0-from-read_one_line_file-on-success.patch
+Patch0588: 0588-man-fix-description-of-force-in-halt-8-7392.patch
+Patch0589: 0589-journal-return-better-error-for-empty-files.patch
+Patch0590: 0590-journalctl-continue-operation-even-if-we-run-into-an.patch
+Patch0591: 0591-journal-remove-error-check-that-never-happens.patch
+Patch0592: 0592-sd-journal-various-clean-ups-and-modernizations.patch
+Patch0593: 0593-journalctl-when-we-fail-to-open-a-journal-file-print.patch
+Patch0594: 0594-journald-fix-accuracy-of-watchdog-timer-event.patch
+Patch0595: 0595-core-fix-the-reversed-sanity-check-when-setting-Star.patch
+Patch0596: 0596-shared-dropin-ignore-ENAMETOOLONG-when-checking-drop.patch
+Patch0597: 0597-cryptsetup-when-unlocking-always-put-path-to-the-obj.patch
+Patch0598: 0598-cryptsetup-use-more-descriptive-name-for-the-variabl.patch
+Patch0599: 0599-cryptsetup-generator-do-not-bind-to-the-decrypted-de.patch
+Patch0600: 0600-shared-cgroup-utils-_CGROUP_CONTROLLER_MASK_ALL-does.patch
+Patch0601: 0601-automount-ack-automount-requests-even-when-already-m.patch
+Patch0602: 0602-udev-net_id-add-support-for-platform-bus-ACPI-mostly.patch
+Patch0603: 0603-journald-native-Fix-typo-in-MANDLOCK-message.patch
+Patch0604: 0604-process-util-make-our-freeze-routine-do-something-us.patch
+Patch0605: 0605-dbus-propagate-errors-from-bus_init_system-and-bus_i.patch
+Patch0606: 0606-bus-util.c-fix-TasksMax-property-assignment.patch
+Patch0607: 0607-sparse-avoid-clash-with-__bitwise-and-__force-from-4.patch
+Patch0608: 0608-core-Let-two-more-booleans-survive-a-daemon-reload.patch
+Patch0609: 0609-core-don-t-choke-if-a-unit-another-unit-triggers-van.patch
+Patch0610: 0610-sd-journal-properly-handle-inotify-queue-overflow.patch
+Patch0611: 0611-sd-journal-make-sure-it-s-safe-to-call-sd_journal_pr.patch
+Patch0612: 0612-journalctl-Periodically-call-sd_journal_process-in-j.patch
+Patch0613: 0613-sd-journal-when-picking-up-a-new-file-compare-inode-.patch
 
 %global num_patches %{lua: c=0; for i,p in ipairs(patches) do c=c+1; end; print(c);}
 
@@ -574,6 +670,7 @@ BuildRequires:  libblkid-devel
 BuildRequires:  xz-devel
 BuildRequires:  zlib-devel
 BuildRequires:  bzip2-devel
+BuildRequires:  lz4-devel
 BuildRequires:  libidn-devel
 BuildRequires:  libcurl-devel
 BuildRequires:  kmod-devel
@@ -615,7 +712,7 @@ Provides:       /sbin/shutdown
 Provides:       syslog
 Provides:       systemd-units = %{version}-%{release}
 
-Conflicts:      dracut < 033-499
+Conflicts:      dracut < 033-243
 Conflicts:      initscripts < 9.49.28-1
 
 #Obsolete packages when we are migrating from rhel6
@@ -764,6 +861,7 @@ CONFIGURE_OPTS=(
     --enable-compat-libs
     --disable-sysusers
     --disable-ldconfig
+    --enable-lz4
 %ifarch s390 s390x ppc %{power64} aarch64
     --disable-lto
 %endif
@@ -869,6 +967,8 @@ mkdir -p %{buildroot}%{_localstatedir}/lib/systemd/coredump
 mkdir -p %{buildroot}%{_localstatedir}/lib/systemd/catalog
 mkdir -p %{buildroot}%{_localstatedir}/lib/systemd/backlight
 mkdir -p %{buildroot}%{_localstatedir}/lib/systemd/rfkill
+mkdir -p %{buildroot}%{_localstatedir}/lib/systemd/journal-upload
+
 touch %{buildroot}%{_localstatedir}/lib/systemd/catalog/database
 touch %{buildroot}%{_sysconfdir}/udev/hwdb.bin
 touch %{buildroot}%{_localstatedir}/lib/systemd/random-seed
@@ -1108,7 +1208,7 @@ if [ -z "$preferred" ]; then
         preferred=kdm
     fi
 fi
-if [ -n "$preferred" -a -r "/usr/lib/systemd/system/$preferred.service" ]; then
+if [ $1 -eq 1 -a -n "$preferred" -a -r "/usr/lib/systemd/system/$preferred.service" ]; then
     # This is supposed to fail when the symlink already exists
     ln -s "/usr/lib/systemd/system/$preferred.service" /etc/systemd/system/display-manager.service >/dev/null 2>&1 || :
 fi
@@ -1490,6 +1590,7 @@ fi
 %{_prefix}/lib/systemd/systemd-journal-upload
 %{_prefix}/lib/systemd/systemd-journal-remote
 %{_prefix}/lib/tmpfiles.d/systemd-remote.conf
+%dir %attr(0755,systemd-journal-upload,systemd-journal-upload) %{_localstatedir}/lib/systemd/journal-upload
 %{_mandir}/man8/systemd-journal-gatewayd.*
 %{_mandir}/man8/systemd-journal-remote.*
 %{_datadir}/systemd/gatewayd
@@ -1524,43 +1625,154 @@ fi
 %{_mandir}/man8/systemd-resolved.*
 
 %changelog
-* Wed Feb 21 2018 Lukas Nykryn <lnykryn@redhat.com> - 219-42.10
-- journal: remove error check that never happens (#1465759)
-- sd-journal: various clean-ups and modernizations (#1465759)
-- journalctl: continue operation, even if we run into an invalid file (#1465759)
-- journalctl: when we fail to open a journal file, print why (#1465759)
+* Tue Feb 20 2018 Lukas Nykryn <lnykryn@redhat.com> - 219-57
 - sd-journal: properly handle inotify queue overflow (#1540538)
 - sd-journal: make sure it's safe to call sd_journal_process() before the first sd_journal_wait() (#1540538)
-- sd-journal: when picking up a new file, compare inode/device info with previous open file by same name (#1540538)
 - journalctl: Periodically call sd_journal_process in journalctl (#1540538)
+- sd-journal: when picking up a new file, compare inode/device info with previous open file by same name (#1540538)
 
-* Mon Feb 19 2018 Lukas Nykryn <lnykryn@redhat.com> - 219-42.9
-- core:execute: fix fork() fail handling in exec_spawn() (#1437114)
+* Mon Feb 19 2018 Lukas Nykryn <lnykryn@redhat.com> - 219-56
+- core: don't choke if a unit another unit triggers vanishes during reload (#1545676)
 
-* Tue Feb 13 2018 Lukas Nykryn <lnykryn@redhat.com> - 219-42.8
-- shared/cgroup-utils: _CGROUP_CONTROLLER_MASK_ALL does not cover CGROUP_PIDS (#1532586)
+* Wed Feb 07 2018 Lukas Nykryn <lnykryn@redhat.com> - 219-55
+- sparse: avoid clash with __bitwise and __force from 4.10 linux/types.h (#5061) (#1447937)
+- core: Let two more booleans survive a daemon-reload (#1542391)
 
-* Wed Jan 17 2018 Lukas Nykryn <lnykryn@redhat.com> - 219-42.7
+* Tue Feb 06 2018 Lukas Nykryn <lnykryn@redhat.com> - 219-54
 - automount: ack automount requests even when already mounted (#1535135)
+- udev: net_id add support for platform bus (ACPI, mostly arm64) devices (#1529633)
+- journald-native: Fix typo in MANDLOCK message (#1501017)
+- process-util: make our freeze() routine do something useful (#1540941)
+- dbus: propagate errors from bus_init_system() and bus_init_api() (#1541061)
+- bus-util.c: fix TasksMax= property assignment (#1537147)
 
-* Tue Jan 09 2018 Lukas Nykryn <lnykryn@redhat.com> - 219-42.6
-- manager: fix connecting to bus when dbus is actually around (#7205) (#1465737)
+* Tue Jan 09 2018 Lukas Nykryn <lnykryn@redhat.com> - 219-53
+- shared/cgroup-utils: _CGROUP_CONTROLLER_MASK_ALL does not cover CGROUP_PIDS (#1532586)
+
+* Thu Dec 14 2017 Lukas Nykryn <lnykryn@redhat.com> - 219-52
+- cryptsetup: when unlocking always put path to the object into Id (#1511043)
+- cryptsetup: use more descriptive name for the variable and drop redundant function (#1511043)
+- cryptsetup-generator: do not bind to the decrypted device unit (#6538) (#1511043)
+- introduce naming based on phys_port_name for nfp via udev rule (#1516283)
+
+* Tue Dec 05 2017 Lukáš Nykrýn <lnykryn@redhat.com> - 219-51
+- revert substitute PACKAGE_STRING with the actual package NVR (#1453153)
+
+* Mon Dec 04 2017 Lukas Nykryn <lnykryn@redhat.com> - 219-50
+- core: fix the reversed sanity check when setting StartupBlockIOWeight over dbus (#1302305)
+- shared/dropin: ignore ENAMETOOLONG when checking drop-in directories (#7525) (#1489095)
+- enable display manager only on systemd installation (#1464893)
+- remove unnecessary dependency on dracut (#1466676)
+- substitute PACKAGE_STRING with the actual package NVR (#1453153)
+
+* Fri Nov 24 2017 Lukas Nykryn <lnykryn@redhat.com> - 219-49
+- journald: fix accuracy of watchdog timer event (#1511565)
+
+* Thu Nov 23 2017 Lukas Nykryn <lnykryn@redhat.com> - 219-48
+- journald: never block when sending messages on NOTIFY_SOCKET socket (#1511565)
+- journal: restore watchdog support (#1511565)
+- cgroup resource property setting ignored if einval (rhbz#1302305)
+- fileio: add new helper call read_line() as bounded getline() replacement (#1503106)
+- def: add new constant LONG_LINE_MAX (#1503106)
+- fileio: rework read_one_line_file() on top of read_line() (#1503106)
+- cgroup-util: replace one use of fgets() by read_line() (#1503106)
+- conf-parse: remove 4K line length limit (#1503106)
+- test-conf-parser: add tests for config parser (#1503106)
+- fileio: use _cleanup_ for FILE unlocking (#1503106)
+- test-fileio: also test read_line() with actual files (#1503106)
+- fileio: return 0 from read_one_line_file on success (#1503106)
+- man: fix description of --force in halt(8) (#7392) (#1515130)
+- journal: return better error for empty files (#1465759)
+- journalctl: continue operation, even if we run into an invalid file (#1465759)
+- journal: remove error check that never happens (#1465759)
+- sd-journal: various clean-ups and modernizations (#1465759)
+- journalctl: when we fail to open a journal file, print why (#1465759)
 
-* Thu Dec 07 2017 Lukas Nykryn <lnykryn@redhat.com> - 219-42.5
+* Thu Nov 16 2017 Lukas Nykryn <lnykryn@redhat.com> - 219-47
+- cryptsetup-generator: use after free (#1477757)
+- manager: fix connecting to bus when dbus is actually around (#7205) (#1465737)
+- journal-remote: make --url option support arbitrary url (#1505385)
+- journald: make maximum size of stream log lines configurable and bump it to 48K (#6838) (#1442262)
+- service: serialize information about currently executing command (#1404657,#1471230)
+- tests: add new test for issue #518 (#1404657,)
+- tests: in RHEL-7 we don't have python3 by default (#1404657,)
+- service: attempt to execute next main command only for oneshot services (#6619) (#1404657,)
+- timedatectl: stop using xstrftime (#1503942)
+- Add support to read lz4 compressed journals (rhbz#1431687)
+
+* Tue Oct 31 2017 Lukas Nykryn <lnykryn@redhat.com> - 219-46
+- Support 'rdma' as a ListenNetlink= argument (#6626) (#1494610)
+- core/namespace: Protect /usr instead of /home with ProtectSystem=yes (#1493047)
+- udev: Use parent bus id for virtio disk builtin path-id (#5500) (#1496697)
+- socket-util: socket_address_parse() should not log errors on its own (#1497639)
+- test: fix failing test-socket-util when running with ipv6.disable=1 kernel param (#1497639)
+- scsi_id: add missing options to getopt_long() (#6501) (#1476910)
 - unmount: Pass in mount options when remounting read-only (#1312002)
 - shutdown: don't remount,ro network filesystems. (#6588) (#1312002)
 - shutdown: fix incorrect fscanf() result check (#6806) (#1312002)
-
-* Fri Sep 29 2017 Lukas Nykryn <lnykryn@redhat.com> - 219-42.4
+- path-util: make use of "mnt_id" field exported in /proc/self/fdinfo/<fd> (#1472439)
+- support ranges when parsing CPUAffinity (#1493976)
+- man: Update man page documentation for CPUAffinity (#1493976)
+- test-path-util: force rm_rf (#1472439)
+- Export NVMe WWID udev attribute (#5348) (#1503253)
+- mount: make sure we unmount tmpfs mounts before we deactivate swaps (#7076) (#1437518)
+- journald: never accept fds from file systems with mandatory locking enabled (#1501017)
+- udev: builtin-keyboard: move fetching the device node up (#1500119)
+- udev: builtin-keyboard: immediately EVIOCSKEYCODE when we have a pair (#1500119)
+- udev: builtin-keyboard: move actual key mapping to a helper function (#1500119)
+- udev: builtin-keyboard: invert a condition (#1500119)
+- udev: builtin-keyboard: add support for EVDEV_ABS_* (#1500119)
+- hwdb: sync 60-evdev.hwdb from systemd v235 (rhbz#1500119)
+- journal: ensure open journals from find_journal() (#3973) (#1493846)
+- journal: only check available space when journal is open (#1493846)
+- automount: if an automount unit is masked, don't react to activation anymore (#5445) (#1498318)
+- units: add [Install] section to remote-cryptsetup.target (#1477757)
+- units: replace remote-cryptsetup-pre.target with remote-fs-pre.target (#1477757)
+- man: add a note about _netdev usage (#1477757)
+- units: make remote-cryptsetup.target also after cryptsetup-pre.target (#1477757)
+
+* Wed Sep 27 2017 Lukas Nykryn <lnykryn@redhat.com> - 219-45
+- journal: implicitly flush to var on recovery (#4028) (#1364092)
+- journal: add/use flushed_flag_is_set() helper (#4041) (#1364092)
+- journald: don't flush to /var/log/journal before we get asked to (#1364092)
+- path-util: make use of "mnt_id" field exported in /proc/self/fdinfo/<fd> (#1472439)
+- Revert "Revert "journald: allow restarting journald without losing stream connections"" (#1359939)
+- journald: make sure we retain all stream fds across restarts (#6348) (#1359939)
+- Allow systemd-tmpfiles to set the file/directory attributes (#1299714)
+- tmpfiles: rework file attribute code (#1299714)
+- tmpfiles: warn if we get an argument on lines that don't take any (#1299714)
+- tmpfiles: substitute % specifiers in arguments for writing files and xattrs (#1299714)
+- btrfs-util: introduce btrfs_is_filesystem() and make use of it where appropriate (#1299714)
+- journal: don't force FS_NOCOW_FL on new journal files, but warn if it is missing (#1299714)
+- tmpfiles: Add +C attrib to the journal files directories (#1299714)
+- Revert "path-util: make use of "mnt_id" field exported in /proc/self/fdinfo/<fd>" (#1472439)
+- device: make sure to remove all device units sharing the same sysfs path (#6679) (#1408916)
 - manager: when reexecuting try to connect to bus only when dbus.service is around (#6773) (#1465737)
-
-* Mon Sep 25 2017 Lukas Nykryn <lnykryn@redhat.com> - 219-42.3
-- udev: ignore SIGCHLD from unexpected processes (#1306539) (#1306539)
-
-* Thu Sep 21 2017 Lukas Nykryn <lnykryn@redhat.com> - 219-42.2
+- doc: document service exit codes (#1178929)
+- units: order cryptsetup-pre.target before cryptsetup.target (#1384014)
+- man: add an explicit description of _netdev to systemd.mount(5) (#1384014)
+- units: add remote-cryptsetup.target and remote-cryptsetup-pre.target (#1384014)
+- cryptsetup-generator: use remote-cryptsetup.target when _netdev is present (#1384014)
+
+* Tue Sep 12 2017 Lukas Nykryn <lnykryn@redhat.com> - 219-44
+- core: unset sysfs path after transition to dead state (#1408916)
 - sysctl: fix uninitialized variable (#1485121)
-
-* Tue Aug 15 2017 Lukas Nykryn <lnykryn@redhat.com> - 219-42.1
+- udev: ignore SIGCHLD from unexpected processes (#1306539) (#1306539)
+- compile with -Werror (#1447937)
+- myhostname: don't return any ipv6 entries when ipv6 is disabled (#1444824)
+- core:execute: fix fork() fail handling in exec_spawn() (#1437114)
+- fix compilation after commit 382877acc6c029e59e359a076d203ca03b4b9e9e (#1447937)
+- Redefine 32bit time_t format to signed (#1447937)
+- sd-bus/bus-kernel.c: fix format errors on ppc64le (#1447937)
+- tmpfiles: with "e" don't attempt to set permissions when file doesn't exist (#1445732)
+- units: introduce getty-pre.target (#6667) (#1173080)
+- units: order container and console getty units after getty-pre.target (#1173080)
+- log: never log into foreign fd #2 in PID 1 or its pre-execve() children (#1420505)
+- nspawn: new option to start as PID2 (#1417387)
+
+* Wed Aug 16 2017 Lukas Nykryn <lnykryn@redhat.com> - 219-43
+- tests: use XFS as root filesystem for system tests (#1475870)
+- tests: use fdisk instead of sfdisk (#1475870)
 - Revert "udev: net_id: add support for phys_port_name attribute (#4506)" (#1477285)
 - reintroduce naming based on phys_port_name for mlxsw and rocker via udev rule