diff --git a/SOURCES/0258-run-synchronously-wait-until-the-scope-unit-we-creat.patch b/SOURCES/0258-run-synchronously-wait-until-the-scope-unit-we-creat.patch
index 125a175..2634ba1 100644
--- a/SOURCES/0258-run-synchronously-wait-until-the-scope-unit-we-creat.patch
+++ b/SOURCES/0258-run-synchronously-wait-until-the-scope-unit-we-creat.patch
@@ -1,4 +1,4 @@
-From 18d515aeb3a2007fa0a762b9b9658f489d4b403d Mon Sep 17 00:00:00 2001
+From 5532bedf8ef456f02fdec62d46bc1be65cdfde30 Mon Sep 17 00:00:00 2001
 From: Lennart Poettering <lennart@poettering.net>
 Date: Tue, 28 Apr 2015 12:21:31 +0200
 Subject: [PATCH] run: synchronously wait until the scope unit we create is
@@ -11,7 +11,7 @@ short-running (such as an invocation to /bin/true).
 https://bugs.freedesktop.org/show_bug.cgi?id=86520
 
 Cherry-picked from: de158ed22db60e3a6654557fa4aa72f7248550af
-Resolves: #1283192
+Resolves: #1272368
 ---
  src/libsystemd/sd-bus/bus-util.c | 10 ++++++++++
  src/libsystemd/sd-bus/bus-util.h |  1 +
diff --git a/SOURCES/0259-device-rework-how-we-enter-tentative-state.patch b/SOURCES/0259-device-rework-how-we-enter-tentative-state.patch
index 5d3e8d6..b866e07 100644
--- a/SOURCES/0259-device-rework-how-we-enter-tentative-state.patch
+++ b/SOURCES/0259-device-rework-how-we-enter-tentative-state.patch
@@ -1,4 +1,4 @@
-From 960ea6ae7a9e2aca3594318ab893f7d5383e46b6 Mon Sep 17 00:00:00 2001
+From ff6c50a1451e0e8fdca72039a0a00ebb0a20ba6c Mon Sep 17 00:00:00 2001
 From: Lennart Poettering <lennart@poettering.net>
 Date: Fri, 24 Apr 2015 12:29:05 +0200
 Subject: [PATCH] device: rework how we enter tentative state
diff --git a/SOURCES/0260-core-Do-not-bind-a-mount-unit-to-a-device-if-it-was-.patch b/SOURCES/0260-core-Do-not-bind-a-mount-unit-to-a-device-if-it-was-.patch
index ac334ba..c1a9ea1 100644
--- a/SOURCES/0260-core-Do-not-bind-a-mount-unit-to-a-device-if-it-was-.patch
+++ b/SOURCES/0260-core-Do-not-bind-a-mount-unit-to-a-device-if-it-was-.patch
@@ -1,4 +1,4 @@
-From c81de449d57bc563be7b4d4d53d07de28adcaa9b Mon Sep 17 00:00:00 2001
+From 75b183700853e616362cf2f22831e1e9dc8a5515 Mon Sep 17 00:00:00 2001
 From: Harald Hoyer <harald@redhat.com>
 Date: Tue, 24 Nov 2015 09:41:26 +0100
 Subject: [PATCH] core: Do not bind a mount unit to a device, if it was from
diff --git a/SOURCES/0261-logind-set-RemoveIPC-no-by-default.patch b/SOURCES/0261-logind-set-RemoveIPC-no-by-default.patch
index 1094ebd..bce797f 100644
--- a/SOURCES/0261-logind-set-RemoveIPC-no-by-default.patch
+++ b/SOURCES/0261-logind-set-RemoveIPC-no-by-default.patch
@@ -1,4 +1,4 @@
-From b4d12e023a1418e850ec96616739e7be1d71c4f5 Mon Sep 17 00:00:00 2001
+From 07cda5adb4ccecc6208b9fc85f4ea3ed8dece47d Mon Sep 17 00:00:00 2001
 From: Lukas Nykryn <lnykryn@redhat.com>
 Date: Thu, 26 Nov 2015 14:14:55 +0100
 Subject: [PATCH] logind: set RemoveIPC=no by default
diff --git a/SOURCES/0262-sysv-generator-follow-symlinks-in-etc-rc.d-init.d.patch b/SOURCES/0262-sysv-generator-follow-symlinks-in-etc-rc.d-init.d.patch
index b048273..e435f0e 100644
--- a/SOURCES/0262-sysv-generator-follow-symlinks-in-etc-rc.d-init.d.patch
+++ b/SOURCES/0262-sysv-generator-follow-symlinks-in-etc-rc.d-init.d.patch
@@ -1,4 +1,4 @@
-From 25dc202140f4daa18faeae11e26e9e16e8dae84e Mon Sep 17 00:00:00 2001
+From 7374770f790080b677f504075ba9659230e11226 Mon Sep 17 00:00:00 2001
 From: Lukas Nykryn <lnykryn@redhat.com>
 Date: Fri, 11 Sep 2015 16:23:07 +0200
 Subject: [PATCH] sysv-generator: follow symlinks in /etc/rc.d/init.d
@@ -11,7 +11,7 @@ On rhel-based distributions you can use alternatives --initscript
 instread of symlink, but this is not usable for other distributions.
 
 Cherry-picked from: 7b729f8686a83b24f3d9a891cde1c
-Resolves: #1288005
+Resolves: #1285492
 ---
  src/sysv-generator/sysv-generator.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/SOURCES/0263-man-RemoveIPC-is-set-to-no-on-rhel.patch b/SOURCES/0263-man-RemoveIPC-is-set-to-no-on-rhel.patch
deleted file mode 100644
index 32b3385..0000000
--- a/SOURCES/0263-man-RemoveIPC-is-set-to-no-on-rhel.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From 931ad3c2c253b40cb2c8eef8876b962e8f2d1072 Mon Sep 17 00:00:00 2001
-From: Lukas Nykryn <lnykryn@redhat.com>
-Date: Thu, 10 Dec 2015 09:34:34 +0100
-Subject: [PATCH] man: RemoveIPC is set to no on rhel
-
-RHEL-only
-
-Related: #1284588
----
- man/logind.conf.xml | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/man/logind.conf.xml b/man/logind.conf.xml
-index d02d573..54651f0 100644
---- a/man/logind.conf.xml
-+++ b/man/logind.conf.xml
-@@ -276,7 +276,7 @@
-         memory and message queues, as well as POSIX shared memory and
-         message queues. Note that IPC objects of the root user are
-         excluded from the effect of this setting. Defaults to
--        <literal>yes</literal>.</para></listitem>
-+        <literal>no</literal>.</para></listitem>
-       </varlistentry>
- 
-     </variablelist>
diff --git a/SOURCES/0263-sysv-generator-test-always-log-to-console.patch b/SOURCES/0263-sysv-generator-test-always-log-to-console.patch
new file mode 100644
index 0000000..b6f4daf
--- /dev/null
+++ b/SOURCES/0263-sysv-generator-test-always-log-to-console.patch
@@ -0,0 +1,28 @@
+From a714212703b3fe5f2a27773602cabbc4ab53da15 Mon Sep 17 00:00:00 2001
+From: Martin Pitt <martin.pitt@ubuntu.com>
+Date: Mon, 15 Jun 2015 08:59:44 +0200
+Subject: [PATCH] sysv-generator test: always log to console
+
+Set $SYSTEMD_LOG_TARGET so that the output always goes to stdout/stderr. This
+fixes running the test as root, as that logged to the journal previously.
+
+https://github.com/systemd/systemd/issues/195
+
+Cherry-picked from: 6b7d32add4733a83f86e18bb86f914037a6688b7
+Resolves: #1279034
+---
+ test/sysv-generator-test.py | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/test/sysv-generator-test.py b/test/sysv-generator-test.py
+index e716d70..1537864 100644
+--- a/test/sysv-generator-test.py
++++ b/test/sysv-generator-test.py
+@@ -60,6 +60,7 @@ class SysvGeneratorTest(unittest.TestCase):
+         '''
+         env = os.environ.copy()
+         env['SYSTEMD_LOG_LEVEL'] = 'debug'
++        env['SYSTEMD_LOG_TARGET'] = 'console'
+         env['SYSTEMD_SYSVINIT_PATH'] = self.init_d_dir
+         env['SYSTEMD_SYSVRCND_PATH'] = self.rcnd_dir
+         env['SYSTEMD_UNIT_PATH'] = self.unit_dir
diff --git a/SOURCES/0264-makefile-disable-udev-tests.patch b/SOURCES/0264-makefile-disable-udev-tests.patch
deleted file mode 100644
index dcf9d8e..0000000
--- a/SOURCES/0264-makefile-disable-udev-tests.patch
+++ /dev/null
@@ -1,27 +0,0 @@
-From c79d960c9cf769e913c6824363c0f2f7f257762e Mon Sep 17 00:00:00 2001
-From: Lukas Nykryn <lnykryn@redhat.com>
-Date: Thu, 10 Dec 2015 11:08:19 +0100
-Subject: [PATCH] makefile: disable udev tests
-
-RHEL-only
----
- Makefile.am | 6 +++---
- 1 file changed, 3 insertions(+), 3 deletions(-)
-
-diff --git a/Makefile.am b/Makefile.am
-index 887e70a..2645f66 100644
---- a/Makefile.am
-+++ b/Makefile.am
-@@ -3785,9 +3785,9 @@ hwdb-remove-hook:
- endif
- 
- # ------------------------------------------------------------------------------
--TESTS += \
--	test/udev-test.pl \
--	$(NULL)
-+#TESTS += \
-+#	test/udev-test.pl \
-+#	$(NULL)
- 
- if HAVE_PYTHON
- TESTS += \
diff --git a/SOURCES/0264-man-RemoveIPC-is-set-to-no-on-rhel.patch b/SOURCES/0264-man-RemoveIPC-is-set-to-no-on-rhel.patch
new file mode 100644
index 0000000..2a6d56c
--- /dev/null
+++ b/SOURCES/0264-man-RemoveIPC-is-set-to-no-on-rhel.patch
@@ -0,0 +1,25 @@
+From 7602b4a03ef2b932ef3c22ce25d01a782074059f Mon Sep 17 00:00:00 2001
+From: Lukas Nykryn <lnykryn@redhat.com>
+Date: Thu, 10 Dec 2015 09:34:34 +0100
+Subject: [PATCH] man: RemoveIPC is set to no on rhel
+
+RHEL-only
+
+Related: #1284588
+---
+ man/logind.conf.xml | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/man/logind.conf.xml b/man/logind.conf.xml
+index d02d573..54651f0 100644
+--- a/man/logind.conf.xml
++++ b/man/logind.conf.xml
+@@ -276,7 +276,7 @@
+         memory and message queues, as well as POSIX shared memory and
+         message queues. Note that IPC objects of the root user are
+         excluded from the effect of this setting. Defaults to
+-        <literal>yes</literal>.</para></listitem>
++        <literal>no</literal>.</para></listitem>
+       </varlistentry>
+ 
+     </variablelist>
diff --git a/SOURCES/0265-Avoid-tmp-being-mounted-as-tmpfs-without-the-user-s-.patch b/SOURCES/0265-Avoid-tmp-being-mounted-as-tmpfs-without-the-user-s-.patch
new file mode 100644
index 0000000..7933126
--- /dev/null
+++ b/SOURCES/0265-Avoid-tmp-being-mounted-as-tmpfs-without-the-user-s-.patch
@@ -0,0 +1,28 @@
+From 14eaa63230a16a32f49db74d4b0d78247874ccdd Mon Sep 17 00:00:00 2001
+From: Didier Roche <didrocks@ubuntu.com>
+Date: Wed, 13 Jan 2016 12:49:57 +0100
+Subject: [PATCH] Avoid /tmp being mounted as tmpfs without the user's will
+
+Ensure PrivateTmp doesn't require tmpfs through tmp.mount, but rather
+adds an After relationship.
+
+rhel-only
+
+Resolves: #1298109
+---
+ src/core/unit.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/core/unit.c b/src/core/unit.c
+index ae47a28..4fb2fd3 100644
+--- a/src/core/unit.c
++++ b/src/core/unit.c
+@@ -807,7 +807,7 @@ int unit_add_exec_dependencies(Unit *u, ExecContext *c) {
+                 return 0;
+ 
+         if (c->private_tmp) {
+-                r = unit_require_mounts_for(u, "/tmp");
++                r = unit_add_dependency_by_name(u, UNIT_AFTER, "tmp.mount", NULL, true);
+                 if (r < 0)
+                         return r;
+ 
diff --git a/SOURCES/0265-sysv-generator-test-always-log-to-console.patch b/SOURCES/0265-sysv-generator-test-always-log-to-console.patch
deleted file mode 100644
index b882f6a..0000000
--- a/SOURCES/0265-sysv-generator-test-always-log-to-console.patch
+++ /dev/null
@@ -1,27 +0,0 @@
-From dff573ed5425cad26370ce5f4dc95c859d58ee72 Mon Sep 17 00:00:00 2001
-From: Martin Pitt <martin.pitt@ubuntu.com>
-Date: Mon, 15 Jun 2015 08:59:44 +0200
-Subject: [PATCH] sysv-generator test: always log to console
-
-Set $SYSTEMD_LOG_TARGET so that the output always goes to stdout/stderr. This
-fixes running the test as root, as that logged to the journal previously.
-
-https://github.com/systemd/systemd/issues/195
-
-Cherry-picked from: 6b7d32add4733a83f86e18bb86f914037a6688b7
----
- test/sysv-generator-test.py | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/test/sysv-generator-test.py b/test/sysv-generator-test.py
-index e716d70..1537864 100644
---- a/test/sysv-generator-test.py
-+++ b/test/sysv-generator-test.py
-@@ -60,6 +60,7 @@ class SysvGeneratorTest(unittest.TestCase):
-         '''
-         env = os.environ.copy()
-         env['SYSTEMD_LOG_LEVEL'] = 'debug'
-+        env['SYSTEMD_LOG_TARGET'] = 'console'
-         env['SYSTEMD_SYSVINIT_PATH'] = self.init_d_dir
-         env['SYSTEMD_SYSVRCND_PATH'] = self.rcnd_dir
-         env['SYSTEMD_UNIT_PATH'] = self.unit_dir
diff --git a/SOURCES/0266-test-sysv-generator-Check-for-network-online.target.patch b/SOURCES/0266-test-sysv-generator-Check-for-network-online.target.patch
index 678699e..db2ca26 100644
--- a/SOURCES/0266-test-sysv-generator-Check-for-network-online.target.patch
+++ b/SOURCES/0266-test-sysv-generator-Check-for-network-online.target.patch
@@ -1,8 +1,9 @@
-From dc923c37bf23c035e510c241ff228e3e2f92c1ef Mon Sep 17 00:00:00 2001
+From e955c2298241b9a2957dd8d36c48cbfe0a108d49 Mon Sep 17 00:00:00 2001
 From: Branislav Blaskovic <bblaskov@redhat.com>
 Date: Sat, 7 Nov 2015 11:32:49 +0100
 Subject: [PATCH] test sysv-generator: Check for network-online.target.
 
+Resolves: #1279034
 ---
  test/sysv-generator-test.py | 18 ++++++++++++------
  1 file changed, 12 insertions(+), 6 deletions(-)
diff --git a/SOURCES/0267-Avoid-tmp-being-mounted-as-tmpfs-without-the-user-s-.patch b/SOURCES/0267-Avoid-tmp-being-mounted-as-tmpfs-without-the-user-s-.patch
deleted file mode 100644
index 4f06b24..0000000
--- a/SOURCES/0267-Avoid-tmp-being-mounted-as-tmpfs-without-the-user-s-.patch
+++ /dev/null
@@ -1,28 +0,0 @@
-From 73d33e8e1b310c292dc92d26ca0cd7bfefa31852 Mon Sep 17 00:00:00 2001
-From: Didier Roche <didrocks@ubuntu.com>
-Date: Wed, 13 Jan 2016 12:49:57 +0100
-Subject: [PATCH] Avoid /tmp being mounted as tmpfs without the user's will
-
-Ensure PrivateTmp doesn't require tmpfs through tmp.mount, but rather
-adds an After relationship.
-
-rhel-only
-
-Resolves: #1298109
----
- src/core/unit.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/src/core/unit.c b/src/core/unit.c
-index ae47a28..4fb2fd3 100644
---- a/src/core/unit.c
-+++ b/src/core/unit.c
-@@ -807,7 +807,7 @@ int unit_add_exec_dependencies(Unit *u, ExecContext *c) {
-                 return 0;
- 
-         if (c->private_tmp) {
--                r = unit_require_mounts_for(u, "/tmp");
-+                r = unit_add_dependency_by_name(u, UNIT_AFTER, "tmp.mount", NULL, true);
-                 if (r < 0)
-                         return r;
- 
diff --git a/SOURCES/0267-makefile-disable-udev-tests.patch b/SOURCES/0267-makefile-disable-udev-tests.patch
new file mode 100644
index 0000000..4379d44
--- /dev/null
+++ b/SOURCES/0267-makefile-disable-udev-tests.patch
@@ -0,0 +1,27 @@
+From 7da662710420fdcbf2691f4a82644332d18d4605 Mon Sep 17 00:00:00 2001
+From: Lukas Nykryn <lnykryn@redhat.com>
+Date: Thu, 10 Dec 2015 11:08:19 +0100
+Subject: [PATCH] makefile: disable udev tests
+
+RHEL-only
+---
+ Makefile.am | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/Makefile.am b/Makefile.am
+index 887e70a..2645f66 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -3785,9 +3785,9 @@ hwdb-remove-hook:
+ endif
+ 
+ # ------------------------------------------------------------------------------
+-TESTS += \
+-	test/udev-test.pl \
+-	$(NULL)
++#TESTS += \
++#	test/udev-test.pl \
++#	$(NULL)
+ 
+ if HAVE_PYTHON
+ TESTS += \
diff --git a/SOURCES/0268-arm-aarch64-detect-virt-check-dmi.patch b/SOURCES/0268-arm-aarch64-detect-virt-check-dmi.patch
new file mode 100644
index 0000000..59389fd
--- /dev/null
+++ b/SOURCES/0268-arm-aarch64-detect-virt-check-dmi.patch
@@ -0,0 +1,40 @@
+From a64e8d52d4058451e8b8d291db4cc276ee31d46d Mon Sep 17 00:00:00 2001
+From: Andrew Jones <drjones@redhat.com>
+Date: Mon, 9 Nov 2015 14:22:20 +0100
+Subject: [PATCH] arm/aarch64: detect-virt: check dmi
+
+ARM/AArch64 guests now have SMBIOS tables populated (when boot
+with a late enough QEMU and a late enough AAVMF is used as the
+bootloader). Furthermore, when booting ARM/AArch64 guests with
+ACPI, the DT detection obviously no longer works, so we need
+dmi detection.
+
+Cherry-picked from: 2ef8a4c4399dcb7b6fcaecd41f27377b584e9a4b
+Resolves: #1278165
+---
+ src/shared/virt.c | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/src/shared/virt.c b/src/shared/virt.c
+index 54c4655..d3ce8dd 100644
+--- a/src/shared/virt.c
++++ b/src/shared/virt.c
+@@ -29,7 +29,7 @@
+ 
+ static int detect_vm_cpuid(const char **_id) {
+ 
+-        /* Both CPUID and DMI are x86 specific interfaces... */
++        /* CPUID is an x86 specific interface. */
+ #if defined(__i386__) || defined(__x86_64__)
+ 
+         static const char cpuid_vendor_table[] =
+@@ -139,8 +139,7 @@ static int detect_vm_devicetree(const char **_id) {
+ 
+ static int detect_vm_dmi(const char **_id) {
+ 
+-        /* Both CPUID and DMI are x86 specific interfaces... */
+-#if defined(__i386__) || defined(__x86_64__)
++#if defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__aarch64__)
+ 
+         static const char *const dmi_vendors[] = {
+                 "/sys/class/dmi/id/sys_vendor",
diff --git a/SOURCES/0268-udev-fibre-channel-fix-NPIV-support.patch b/SOURCES/0268-udev-fibre-channel-fix-NPIV-support.patch
deleted file mode 100644
index 5958e60..0000000
--- a/SOURCES/0268-udev-fibre-channel-fix-NPIV-support.patch
+++ /dev/null
@@ -1,69 +0,0 @@
-From 41bcd014886cfd2bc4415f2c78668008963934a9 Mon Sep 17 00:00:00 2001
-From: Maurizio Lombardi <mlombard@redhat.com>
-Date: Mon, 1 Feb 2016 14:44:22 +0100
-Subject: [PATCH] udev: fibre channel: fix NPIV support
-
-When using NPIV, you can create multiple virtual HBAs on top of the
-physical one, this means that the physical N_Port can have multiple
-port IDs associated to it.
-Suppose a LUN is assigned to the physical HBA and to a virtual HBA,
-in both cases the original code uses the ID of the physical HBA
-to build the by-path link and udev will end up trying to create two by-path
-links with the same name.
-
-This patch fixes the problem by using the port ID of the virtual HBA
-whenever it detects that the device belongs to a virtual HBA,
-otherwise it uses the port ID of the physical HBA.
-
-(cherry-picked from 155a760bcedd11b7f3b430350a46f10736286895)
-
-Resolves: #1266934
----
- src/udev/udev-builtin-path_id.c | 27 ++++++++++++++++++++++++---
- 1 file changed, 24 insertions(+), 3 deletions(-)
-
-diff --git a/src/udev/udev-builtin-path_id.c b/src/udev/udev-builtin-path_id.c
-index 9ca6084..695ac7f 100644
---- a/src/udev/udev-builtin-path_id.c
-+++ b/src/udev/udev-builtin-path_id.c
-@@ -92,6 +92,9 @@ static struct udev_device *skip_subsystem(struct udev_device *dev, const char *s
- static struct udev_device *handle_scsi_fibre_channel(struct udev_device *parent, char **path) {
-         struct udev *udev  = udev_device_get_udev(parent);
-         struct udev_device *targetdev;
-+        struct udev_device *rportdev;
-+        struct udev_device *hostdev;
-+        struct udev_device *vportdev;
-         struct udev_device *fcdev = NULL;
-         const char *port;
-         char *lun = NULL;
-@@ -100,9 +103,27 @@ static struct udev_device *handle_scsi_fibre_channel(struct udev_device *parent,
-         if (targetdev == NULL)
-                 return NULL;
- 
--        fcdev = udev_device_new_from_subsystem_sysname(udev, "fc_transport", udev_device_get_sysname(targetdev));
--        if (fcdev == NULL)
--                return NULL;
-+        rportdev = udev_device_get_parent(targetdev);
-+        if (rportdev == NULL)
-+                goto skip_npiv_check;
-+
-+        hostdev = udev_device_get_parent(rportdev);
-+        if (hostdev == NULL)
-+                goto skip_npiv_check;
-+
-+        vportdev = udev_device_get_parent(hostdev);
-+        if (vportdev == NULL)
-+                goto skip_npiv_check;
-+
-+        fcdev = udev_device_new_from_subsystem_sysname(udev, "fc_vports", udev_device_get_sysname(vportdev));
-+
-+skip_npiv_check:
-+        if (fcdev == NULL) {
-+                fcdev = udev_device_new_from_subsystem_sysname(udev, "fc_transport", udev_device_get_sysname(targetdev));
-+                if (fcdev == NULL)
-+                        return NULL;
-+        }
-+
-         port = udev_device_get_sysattr_value(fcdev, "port_name");
-         if (port == NULL) {
-                 parent = NULL;
diff --git a/SOURCES/0269-ata_id-unreverse-WWN-identifier.patch b/SOURCES/0269-ata_id-unreverse-WWN-identifier.patch
deleted file mode 100644
index 3f875a3..0000000
--- a/SOURCES/0269-ata_id-unreverse-WWN-identifier.patch
+++ /dev/null
@@ -1,43 +0,0 @@
-From af5732176cb192206f555a1c00dd5431a757367f Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
-Date: Wed, 22 Jul 2015 00:23:47 -0400
-Subject: [PATCH] ata_id: unreverse WWN identifier
-
-An endianness conversion was lost in 6024a6e302bad6bcf073fa84a41a6123305dc845.
-Restore it. Now ata_id and scsi_id output match.
-
-https://bugzilla.redhat.com/show_bug.cgi?id=1227503
-
-Cherry-picked from: 01f61d331bb5038f0c877ac03c54333328b6ea28
-Resolves: #1308795
----
- src/udev/ata_id/ata_id.c | 14 ++++++++++++--
- 1 file changed, 12 insertions(+), 2 deletions(-)
-
-diff --git a/src/udev/ata_id/ata_id.c b/src/udev/ata_id/ata_id.c
-index b6f28c6..4adec44 100644
---- a/src/udev/ata_id/ata_id.c
-+++ b/src/udev/ata_id/ata_id.c
-@@ -638,10 +638,20 @@ int main(int argc, char *argv[])
-                  * All other values are reserved.
-                  */
-                 word = identify.wyde[108];
--                if ((word & 0xf000) == 0x5000)
-+                if ((word & 0xf000) == 0x5000) {
-+                        uint64_t wwwn;
-+
-+                        wwwn   = identify.wyde[108];
-+                        wwwn <<= 16;
-+                        wwwn  |= identify.wyde[109];
-+                        wwwn <<= 16;
-+                        wwwn  |= identify.wyde[110];
-+                        wwwn <<= 16;
-+                        wwwn  |= identify.wyde[111];
-                         printf("ID_WWN=0x%1$" PRIx64 "\n"
-                                "ID_WWN_WITH_EXTENSION=0x%1$" PRIx64 "\n",
--                               identify.octa[108/4]);
-+                               wwwn);
-+                }
- 
-                 /* from Linux's include/linux/ata.h */
-                 if (identify.wyde[0] == 0x848a ||
diff --git a/SOURCES/0269-detect-virt-dmi-look-for-KVM.patch b/SOURCES/0269-detect-virt-dmi-look-for-KVM.patch
new file mode 100644
index 0000000..b33108a
--- /dev/null
+++ b/SOURCES/0269-detect-virt-dmi-look-for-KVM.patch
@@ -0,0 +1,40 @@
+From 795d7cadb7b49ae11e2544ce325779f8d5ec7526 Mon Sep 17 00:00:00 2001
+From: Andrew Jones <drjones@redhat.com>
+Date: Mon, 9 Nov 2015 14:29:09 +0100
+Subject: [PATCH] detect-virt: dmi: look for KVM
+
+Some guests (ARM, AArch64, x86-RHEL) have 'KVM' in the product name.
+Look for that first in order to more precisely report "kvm" when
+detecting a QEMU/KVM guest. Without this patch we report "qemu",
+even if KVM acceleration is in use on ARM/AArch64 guests.
+
+I've only tested a backported version of this and the previous
+patch on an AArch64 guest (which worked). Of course it would be
+nice to get regression testing on all guest types that depend on
+dmi done.
+
+Cherry-picked from: 3728dcde4542b7b2792d9ef0baeb742d82983b03
+Resolves: #1278165
+---
+ src/shared/virt.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/src/shared/virt.c b/src/shared/virt.c
+index d3ce8dd..55a6ca9 100644
+--- a/src/shared/virt.c
++++ b/src/shared/virt.c
+@@ -142,12 +142,14 @@ static int detect_vm_dmi(const char **_id) {
+ #if defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__aarch64__)
+ 
+         static const char *const dmi_vendors[] = {
++                "/sys/class/dmi/id/product_name", /* Test this before sys_vendor to detect KVM over QEMU */
+                 "/sys/class/dmi/id/sys_vendor",
+                 "/sys/class/dmi/id/board_vendor",
+                 "/sys/class/dmi/id/bios_vendor"
+         };
+ 
+         static const char dmi_vendor_table[] =
++                "KVM\0"                   "kvm\0"
+                 "QEMU\0"                  "qemu\0"
+                 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
+                 "VMware\0"                "vmware\0"
diff --git a/SOURCES/0270-Fixup-WWN-bytes-for-big-endian-systems.patch b/SOURCES/0270-Fixup-WWN-bytes-for-big-endian-systems.patch
deleted file mode 100644
index 932fd0e..0000000
--- a/SOURCES/0270-Fixup-WWN-bytes-for-big-endian-systems.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-From e2236a77928842bbf092956f8fa1918f2b4f7b9b Mon Sep 17 00:00:00 2001
-From: Tom Lyon <pugs@drivescale.com>
-Date: Mon, 21 Sep 2015 14:36:32 -0700
-Subject: [PATCH] Fixup WWN bytes for big-endian systems
-
-Cherry-picked from: cf22cddcfd07d10fecd7b03ef465e957054daec2
-Resolves: #1308795
----
- src/udev/ata_id/ata_id.c | 4 ++++
- 1 file changed, 4 insertions(+)
-
-diff --git a/src/udev/ata_id/ata_id.c b/src/udev/ata_id/ata_id.c
-index 4adec44..ef05fba 100644
---- a/src/udev/ata_id/ata_id.c
-+++ b/src/udev/ata_id/ata_id.c
-@@ -485,6 +485,10 @@ int main(int argc, char *argv[])
-                 disk_identify_fixup_uint16(identify.byte,  90);     /* time required for enhanced SECURITY ERASE UNIT */
-                 disk_identify_fixup_uint16(identify.byte,  91);     /* current APM values */
-                 disk_identify_fixup_uint16(identify.byte,  94);     /* current AAM value */
-+                disk_identify_fixup_uint16(identify.byte, 108);     /* wwn */
-+                disk_identify_fixup_uint16(identify.byte, 109);     /* wwn */
-+                disk_identify_fixup_uint16(identify.byte, 110);     /* wwn */
-+                disk_identify_fixup_uint16(identify.byte, 111);     /* wwn */
-                 disk_identify_fixup_uint16(identify.byte, 128);     /* device lock function */
-                 disk_identify_fixup_uint16(identify.byte, 217);     /* nominal media rotation rate */
-                 memcpy(&id, identify.byte, sizeof id);
diff --git a/SOURCES/0270-Revert-journald-turn-ForwardToSyslog-off-by-default.patch b/SOURCES/0270-Revert-journald-turn-ForwardToSyslog-off-by-default.patch
new file mode 100644
index 0000000..499e9a7
--- /dev/null
+++ b/SOURCES/0270-Revert-journald-turn-ForwardToSyslog-off-by-default.patch
@@ -0,0 +1,54 @@
+From 1b8d3a9c51d5584b6f6e394592a83b43cfbc693d Mon Sep 17 00:00:00 2001
+From: Lukas Nykryn <lnykryn@redhat.com>
+Date: Mon, 25 Jan 2016 14:03:47 +0100
+Subject: [PATCH] Revert "journald: turn ForwardToSyslog= off by default"
+
+This reverts commit 46b131574fdd7d77c15a0919ca9010cad7aa6ac7.
+
+rhel-only
+
+Resolves: #1285642
+---
+ man/journald.conf.xml         | 2 +-
+ src/journal/journald-server.c | 1 +
+ src/journal/journald.conf     | 2 +-
+ 3 files changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/man/journald.conf.xml b/man/journald.conf.xml
+index 2cbe58b..c4f71e8 100644
+--- a/man/journald.conf.xml
++++ b/man/journald.conf.xml
+@@ -302,7 +302,7 @@
+         These options take boolean arguments. If forwarding to syslog
+         is enabled but nothing reads messages from the socket,
+         forwarding to syslog has no effect. By default, only
+-        forwarding to wall is enabled. These settings may be
++        forwarding to syslog and wall is enabled. These settings may be
+         overridden at boot time with the kernel command line options
+         <literal>systemd.journald.forward_to_syslog=</literal>,
+         <literal>systemd.journald.forward_to_kmsg=</literal>,
+diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c
+index f13147f..6a35ebb 100644
+--- a/src/journal/journald-server.c
++++ b/src/journal/journald-server.c
+@@ -1470,6 +1470,7 @@ int server_init(Server *s) {
+         s->rate_limit_interval = DEFAULT_RATE_LIMIT_INTERVAL;
+         s->rate_limit_burst = DEFAULT_RATE_LIMIT_BURST;
+ 
++        s->forward_to_syslog = true;
+         s->forward_to_wall = true;
+ 
+         s->max_file_usec = DEFAULT_MAX_FILE_USEC;
+diff --git a/src/journal/journald.conf b/src/journal/journald.conf
+index 47eefe9..3907dfb 100644
+--- a/src/journal/journald.conf
++++ b/src/journal/journald.conf
+@@ -27,7 +27,7 @@
+ #RuntimeMaxFileSize=
+ #MaxRetentionSec=
+ #MaxFileSec=1month
+-#ForwardToSyslog=no
++#ForwardToSyslog=yes
+ #ForwardToKMsg=no
+ #ForwardToConsole=no
+ #ForwardToWall=yes
diff --git a/SOURCES/0271-Revert-udev-fibre-channel-fix-NPIV-support.patch b/SOURCES/0271-Revert-udev-fibre-channel-fix-NPIV-support.patch
deleted file mode 100644
index e9ab780..0000000
--- a/SOURCES/0271-Revert-udev-fibre-channel-fix-NPIV-support.patch
+++ /dev/null
@@ -1,57 +0,0 @@
-From 3b9db589b168cef9c07ad63c8cc06950844bfd5b Mon Sep 17 00:00:00 2001
-From: Michal Sekletar <msekleta@redhat.com>
-Date: Mon, 29 Feb 2016 16:33:38 +0100
-Subject: [PATCH] Revert "udev: fibre channel: fix NPIV support"
-
-This reverts commit 569d98e9caae425120bf28f6b440e6cc117abc0d.
-
-Related: #1266934
----
- src/udev/udev-builtin-path_id.c | 27 +++------------------------
- 1 file changed, 3 insertions(+), 24 deletions(-)
-
-diff --git a/src/udev/udev-builtin-path_id.c b/src/udev/udev-builtin-path_id.c
-index 695ac7f..9ca6084 100644
---- a/src/udev/udev-builtin-path_id.c
-+++ b/src/udev/udev-builtin-path_id.c
-@@ -92,9 +92,6 @@ static struct udev_device *skip_subsystem(struct udev_device *dev, const char *s
- static struct udev_device *handle_scsi_fibre_channel(struct udev_device *parent, char **path) {
-         struct udev *udev  = udev_device_get_udev(parent);
-         struct udev_device *targetdev;
--        struct udev_device *rportdev;
--        struct udev_device *hostdev;
--        struct udev_device *vportdev;
-         struct udev_device *fcdev = NULL;
-         const char *port;
-         char *lun = NULL;
-@@ -103,27 +100,9 @@ static struct udev_device *handle_scsi_fibre_channel(struct udev_device *parent,
-         if (targetdev == NULL)
-                 return NULL;
- 
--        rportdev = udev_device_get_parent(targetdev);
--        if (rportdev == NULL)
--                goto skip_npiv_check;
--
--        hostdev = udev_device_get_parent(rportdev);
--        if (hostdev == NULL)
--                goto skip_npiv_check;
--
--        vportdev = udev_device_get_parent(hostdev);
--        if (vportdev == NULL)
--                goto skip_npiv_check;
--
--        fcdev = udev_device_new_from_subsystem_sysname(udev, "fc_vports", udev_device_get_sysname(vportdev));
--
--skip_npiv_check:
--        if (fcdev == NULL) {
--                fcdev = udev_device_new_from_subsystem_sysname(udev, "fc_transport", udev_device_get_sysname(targetdev));
--                if (fcdev == NULL)
--                        return NULL;
--        }
--
-+        fcdev = udev_device_new_from_subsystem_sysname(udev, "fc_transport", udev_device_get_sysname(targetdev));
-+        if (fcdev == NULL)
-+                return NULL;
-         port = udev_device_get_sysattr_value(fcdev, "port_name");
-         if (port == NULL) {
-                 parent = NULL;
diff --git a/SOURCES/0271-terminal-util-when-resetting-terminals-don-t-wait-fo.patch b/SOURCES/0271-terminal-util-when-resetting-terminals-don-t-wait-fo.patch
new file mode 100644
index 0000000..62276b3
--- /dev/null
+++ b/SOURCES/0271-terminal-util-when-resetting-terminals-don-t-wait-fo.patch
@@ -0,0 +1,75 @@
+From 067fbebee46a376c639c9369dcaf80004047414d Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Mon, 3 Aug 2015 19:04:08 +0200
+Subject: [PATCH] terminal-util: when resetting terminals, don't wait for
+ carrier
+
+In case of non-CLOCAL lines (i.e. those with carrier detect configured)
+we shouldnt wait for a carrier if all we try to do is reset the TTY.
+Hence, whenever we open such a TTY pass O_NONBLOCK.
+
+Note that we continue to open ttys we intend to write to without
+O_ONBLOCK, we only add it in cases we invoke ioctl()s or other terminal
+operations without reading or writing to the device.
+
+Fixes #835.
+
+Cherry-picked from: 0a8b555ceb07ce916b9bd48782d1eb69a12f0f2e
+Resolves: #1266745
+---
+ src/shared/util.c | 14 +++++++++-----
+ 1 file changed, 9 insertions(+), 5 deletions(-)
+
+diff --git a/src/shared/util.c b/src/shared/util.c
+index 778c2b0..5092588 100644
+--- a/src/shared/util.c
++++ b/src/shared/util.c
+@@ -1713,7 +1713,7 @@ bool fstype_is_network(const char *fstype) {
+ int chvt(int vt) {
+         _cleanup_close_ int fd;
+ 
+-        fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC);
++        fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
+         if (fd < 0)
+                 return -errno;
+ 
+@@ -1953,7 +1953,11 @@ finish:
+ int reset_terminal(const char *name) {
+         _cleanup_close_ int fd = -1;
+ 
+-        fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
++        /* We open the terminal with O_NONBLOCK here, to ensure we
++         * don't block on carrier if this is a terminal with carrier
++         * configured. */
++
++        fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
+         if (fd < 0)
+                 return fd;
+ 
+@@ -2204,7 +2208,7 @@ int release_terminal(void) {
+         struct sigaction sa_old;
+         int r = 0;
+ 
+-        fd = open("/dev/tty", O_RDWR|O_NOCTTY|O_NDELAY|O_CLOEXEC);
++        fd = open("/dev/tty", O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
+         if (fd < 0)
+                 return -errno;
+ 
+@@ -4405,7 +4409,7 @@ int terminal_vhangup_fd(int fd) {
+ int terminal_vhangup(const char *name) {
+         _cleanup_close_ int fd;
+ 
+-        fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
++        fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
+         if (fd < 0)
+                 return fd;
+ 
+@@ -4452,7 +4456,7 @@ int vt_disallocate(const char *name) {
+                 return -EINVAL;
+ 
+         /* Try to deallocate */
+-        fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC);
++        fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
+         if (fd < 0)
+                 return fd;
+ 
diff --git a/SOURCES/0272-basic-terminal-util-introduce-SYSTEMD_COLORS-environ.patch b/SOURCES/0272-basic-terminal-util-introduce-SYSTEMD_COLORS-environ.patch
new file mode 100644
index 0000000..e4546ec
--- /dev/null
+++ b/SOURCES/0272-basic-terminal-util-introduce-SYSTEMD_COLORS-environ.patch
@@ -0,0 +1,154 @@
+From 9d67a3a2d4fd378ca04726c5eb5f31ee222c50e4 Mon Sep 17 00:00:00 2001
+From: Jan Synacek <jsynacek@redhat.com>
+Date: Tue, 19 Jan 2016 10:17:19 +0100
+Subject: [PATCH] basic/terminal-util: introduce SYSTEMD_COLORS environment
+ variable
+
+... to determine if color output should be enabled. If the variable is not set,
+fall back to using on_tty(). Also, rewrite existing code to use
+colors_enabled() where appropriate.
+
+Cherry-picked from: 40c9fe4c0862114dab390c8ed16f78cf056b9140
+Resolves: #1247963
+---
+ man/systemd.xml           |  7 +++++++
+ src/journal/journalctl.c  |  2 +-
+ src/login/loginctl.c      |  2 +-
+ src/machine/machinectl.c  |  2 +-
+ src/shared/util.c         | 13 +++++++++++++
+ src/shared/util.h         | 13 +++++++------
+ src/systemctl/systemctl.c |  2 +-
+ 7 files changed, 31 insertions(+), 10 deletions(-)
+
+diff --git a/man/systemd.xml b/man/systemd.xml
+index eb289f0..30005b1 100644
+--- a/man/systemd.xml
++++ b/man/systemd.xml
+@@ -755,6 +755,13 @@
+       </varlistentry>
+ 
+       <varlistentry>
++        <term><varname>$SYSTEMD_COLORS</varname></term>
++
++        <listitem><para>Controls whether colorized output should be generated.
++        </para></listitem>
++      </varlistentry>
++
++      <varlistentry>
+         <term><varname>$LISTEN_PID</varname></term>
+         <term><varname>$LISTEN_FDS</varname></term>
+ 
+diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
+index 8236d08..7058788 100644
+--- a/src/journal/journalctl.c
++++ b/src/journal/journalctl.c
+@@ -2140,7 +2140,7 @@ int main(int argc, char *argv[]) {
+                         flags =
+                                 arg_all * OUTPUT_SHOW_ALL |
+                                 arg_full * OUTPUT_FULL_WIDTH |
+-                                on_tty() * OUTPUT_COLOR |
++                                colors_enabled() * OUTPUT_COLOR |
+                                 arg_catalog * OUTPUT_CATALOG |
+                                 arg_utc * OUTPUT_UTC;
+ 
+diff --git a/src/login/loginctl.c b/src/login/loginctl.c
+index 6c8a59e..8e3bfbe 100644
+--- a/src/login/loginctl.c
++++ b/src/login/loginctl.c
+@@ -83,7 +83,7 @@ static OutputFlags get_output_flags(void) {
+                 arg_all * OUTPUT_SHOW_ALL |
+                 arg_full * OUTPUT_FULL_WIDTH |
+                 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
+-                on_tty() * OUTPUT_COLOR;
++                colors_enabled() * OUTPUT_COLOR;
+ }
+ 
+ static int list_sessions(int argc, char *argv[], void *userdata) {
+diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c
+index f191070..ef1214a 100644
+--- a/src/machine/machinectl.c
++++ b/src/machine/machinectl.c
+@@ -105,7 +105,7 @@ static OutputFlags get_output_flags(void) {
+                 arg_all * OUTPUT_SHOW_ALL |
+                 arg_full * OUTPUT_FULL_WIDTH |
+                 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
+-                on_tty() * OUTPUT_COLOR |
++                colors_enabled() * OUTPUT_COLOR |
+                 !arg_quiet * OUTPUT_WARN_CUTOFF;
+ }
+ 
+diff --git a/src/shared/util.c b/src/shared/util.c
+index 5092588..dc51852 100644
+--- a/src/shared/util.c
++++ b/src/shared/util.c
+@@ -8146,3 +8146,16 @@ char *shell_maybe_quote(const char *s) {
+ 
+         return r;
+ }
++
++bool colors_enabled(void) {
++        const char *colors;
++
++        colors = getenv("SYSTEMD_COLORS");
++        if (!colors) {
++                if (streq_ptr(getenv("TERM"), "dumb"))
++                        return false;
++                return on_tty();
++        }
++
++        return parse_boolean(colors) != 0;
++}
+diff --git a/src/shared/util.h b/src/shared/util.h
+index 7ecfd85..b4a4a49 100644
+--- a/src/shared/util.h
++++ b/src/shared/util.h
+@@ -485,29 +485,30 @@ unsigned lines(void);
+ void columns_lines_cache_reset(int _unused_ signum);
+ 
+ bool on_tty(void);
++bool colors_enabled(void);
+ 
+ static inline const char *ansi_highlight(void) {
+-        return on_tty() ? ANSI_HIGHLIGHT_ON : "";
++        return colors_enabled() ? ANSI_HIGHLIGHT_ON : "";
+ }
+ 
+ static inline const char *ansi_highlight_red(void) {
+-        return on_tty() ? ANSI_HIGHLIGHT_RED_ON : "";
++        return colors_enabled() ? ANSI_HIGHLIGHT_RED_ON : "";
+ }
+ 
+ static inline const char *ansi_highlight_green(void) {
+-        return on_tty() ? ANSI_HIGHLIGHT_GREEN_ON : "";
++        return colors_enabled() ? ANSI_HIGHLIGHT_GREEN_ON : "";
+ }
+ 
+ static inline const char *ansi_highlight_yellow(void) {
+-        return on_tty() ? ANSI_HIGHLIGHT_YELLOW_ON : "";
++        return colors_enabled() ? ANSI_HIGHLIGHT_YELLOW_ON : "";
+ }
+ 
+ static inline const char *ansi_highlight_blue(void) {
+-        return on_tty() ? ANSI_HIGHLIGHT_BLUE_ON : "";
++        return colors_enabled() ? ANSI_HIGHLIGHT_BLUE_ON : "";
+ }
+ 
+ static inline const char *ansi_highlight_off(void) {
+-        return on_tty() ? ANSI_HIGHLIGHT_OFF : "";
++        return colors_enabled() ? ANSI_HIGHLIGHT_OFF : "";
+ }
+ 
+ int files_same(const char *filea, const char *fileb);
+diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
+index 89d0b3b..5d3a85f 100644
+--- a/src/systemctl/systemctl.c
++++ b/src/systemctl/systemctl.c
+@@ -197,7 +197,7 @@ static OutputFlags get_output_flags(void) {
+                 arg_all * OUTPUT_SHOW_ALL |
+                 arg_full * OUTPUT_FULL_WIDTH |
+                 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
+-                on_tty() * OUTPUT_COLOR |
++                colors_enabled() * OUTPUT_COLOR |
+                 !arg_quiet * OUTPUT_WARN_CUTOFF;
+ }
+ 
diff --git a/SOURCES/0272-udev-path-id-fibre-channel-NPIV-use-fc_vport-s-port_.patch b/SOURCES/0272-udev-path-id-fibre-channel-NPIV-use-fc_vport-s-port_.patch
deleted file mode 100644
index 82e8f78..0000000
--- a/SOURCES/0272-udev-path-id-fibre-channel-NPIV-use-fc_vport-s-port_.patch
+++ /dev/null
@@ -1,125 +0,0 @@
-From 77314a3851676724fa018d76a4136fba059082d4 Mon Sep 17 00:00:00 2001
-From: Mauricio Faria de Oliveira <mauricfo@linux.vnet.ibm.com>
-Date: Tue, 23 Feb 2016 15:02:02 -0300
-Subject: [PATCH] udev: path-id: fibre channel NPIV - use fc_vport's port_name
-
-With the Fibre Channel NPIV (N_Port ID Virtualization) feature,
-a single physical N_Port (e.g., PCI address) can have multiple
-N_Port IDs (e.g., different fc_host nodes) - which can connect
-to the same target LUN (e.g., fc_remote_port's port_name and
-LUN number).
-
-Thus, in order to be unique, the device persistent path should
-include the fc_vport's port_name (only if the fc_vport is used),
-in addition to the already in use PCI address, fc_remote_port's
-port_name and LUN number.
-
-The patch merges the 2 proposals submitted upstream, addressing
-some problems with both:
-- #2500 (don't replace the fc_rport's port_name with fc_vport's)
-- #2665 (don't add a fc_host/fc_vport's port_name if not needed)
-
-Links
-- https://github.com/systemd/systemd/pull/2500/
-- https://github.com/systemd/systemd/pull/2665/
-
-Built, checked, tested on RHEL Server 7.1 with no regressions.
-
-With the patch, /dev/disk/by-path symlinks are created correctly,
-and are unique, backward-compatible with the physical port case:
-- physical port (no vport field)
-- virtual ports (w/ vport field)
-
-    # ls -l /dev/disk/by-path | grep 0001:09:00.0
-    <...> pci-0001:09:00.0-fc-0x500507680b2255fe-lun-0 -> ../../sdh
-    <...> pci-0001:09:00.0-fc-0x500507680b2255ff-lun-0 -> ../../sdi
-    <...> pci-0001:09:00.0-vport-0x5001a4aaf00a6785-fc-0x500507680b2255fe-lun-0 -> ../../sde
-    <...> pci-0001:09:00.0-vport-0x5001a4aaf00a6785-fc-0x500507680b2255ff-lun-0 -> ../../sdd
-    <...> pci-0001:09:00.0-vport-0x5001a4ad99d8c2de-fc-0x500507680b2255fe-lun-0 -> ../../sdc
-    <...> pci-0001:09:00.0-vport-0x5001a4ad99d8c2de-fc-0x500507680b2255ff-lun-0 -> ../../sdb
-
-Accordingly w/ sysfs:
-
-    # ls -ld /sys/block/sd* | grep host1
-    <...> /sys/block/sdb -> ../devices/pci0001:00/<...>/0001:09:00.0/host1/vport-1:0-0/host3/rport-3:0-1/target3:0:0/3:0:0:0/block/sdb
-    <...> /sys/block/sdc -> ../devices/pci0001:00/<...>/0001:09:00.0/host1/vport-1:0-0/host3/rport-3:0-2/target3:0:1/3:0:1:0/block/sdc
-    <...> /sys/block/sdd -> ../devices/pci0001:00/<...>/0001:09:00.0/host1/vport-1:0-2/host5/rport-5:0-1/target5:0:0/5:0:0:0/block/sdd
-    <...> /sys/block/sde -> ../devices/pci0001:00/<...>/0001:09:00.0/host1/vport-1:0-2/host5/rport-5:0-2/target5:0:1/5:0:1:0/block/sde
-    <...> /sys/block/sdh -> ../devices/pci0001:00/<...>/0001:09:00.0/host1/rport-1:0-3/target1:0:0/1:0:0:0/block/sdh
-    <...> /sys/block/sdi -> ../devices/pci0001:00/<...>/0001:09:00.0/host1/rport-1:0-4/target1:0:1/1:0:1:0/block/sdi
-
-The symlinks still include the fc_remote_port's (target) port_name:
-
-    # grep . /sys/class/fc_remote_ports/rport-{3:0-{1,2},5:0-{1,2},1:0-{3,4}}/port_name
-    /sys/class/fc_remote_ports/rport-3:0-1/port_name:0x500507680b2255ff
-    /sys/class/fc_remote_ports/rport-3:0-2/port_name:0x500507680b2255fe
-    /sys/class/fc_remote_ports/rport-5:0-1/port_name:0x500507680b2255ff
-    /sys/class/fc_remote_ports/rport-5:0-2/port_name:0x500507680b2255fe
-    /sys/class/fc_remote_ports/rport-1:0-3/port_name:0x500507680b2255fe
-    /sys/class/fc_remote_ports/rport-1:0-4/port_name:0x500507680b2255ff
-
-And now include the fc_vport's (virtual host) port_name *if* it's from a fc_vport:
-
-    # grep . /sys/class/fc_host/host1/port_name /sys/class/fc_vports/vport-1:0-{0,2}/port_name
-    /sys/class/fc_host/host1/port_name:0x10000090fa8f0ebc
-    /sys/class/fc_vports/vport-1:0-0/port_name:0x5001a4ad99d8c2de
-    /sys/class/fc_vports/vport-1:0-2/port_name:0x5001a4aaf00a6785
-
-Signed-off-by: Mauricio Faria de Oliveira <mauricfo@linux.vnet.ibm.com>
-Reported-by: Srikanth B. Aithal <bssrikanth@in.ibm.com>
-
-Cherry-picked from: 6a3d3f9e5970cf982ac37c65d0b856146b675a12
-Resolves: #1266934
----
- src/udev/udev-builtin-path_id.c | 30 ++++++++++++++++++++++++++++++
- 1 file changed, 30 insertions(+)
-
-diff --git a/src/udev/udev-builtin-path_id.c b/src/udev/udev-builtin-path_id.c
-index 9ca6084..3b72922 100644
---- a/src/udev/udev-builtin-path_id.c
-+++ b/src/udev/udev-builtin-path_id.c
-@@ -92,7 +92,11 @@ static struct udev_device *skip_subsystem(struct udev_device *dev, const char *s
- static struct udev_device *handle_scsi_fibre_channel(struct udev_device *parent, char **path) {
-         struct udev *udev  = udev_device_get_udev(parent);
-         struct udev_device *targetdev;
-+        struct udev_device *rportdev;
-+        struct udev_device *hostdev;
-+        struct udev_device *vportdev;
-         struct udev_device *fcdev = NULL;
-+        struct udev_device *fc_vportdev = NULL;
-         const char *port;
-         char *lun = NULL;
- 
-@@ -113,6 +117,32 @@ static struct udev_device *handle_scsi_fibre_channel(struct udev_device *parent,
-         path_prepend(path, "fc-%s-%s", port, lun);
-         if (lun)
-                 free(lun);
-+
-+        /* NPIV */
-+        rportdev = udev_device_get_parent(targetdev);
-+        if (rportdev == NULL)
-+                goto out;
-+
-+        hostdev = udev_device_get_parent(rportdev);
-+        if (hostdev == NULL)
-+                goto out;
-+
-+        vportdev = udev_device_get_parent(hostdev);
-+        if (vportdev == NULL)
-+                goto out;
-+
-+        fc_vportdev = udev_device_new_from_subsystem_sysname(udev, "fc_vports", udev_device_get_sysname(vportdev));
-+        if (fc_vportdev == NULL)
-+                goto out;
-+
-+        port = udev_device_get_sysattr_value(fc_vportdev, "port_name");
-+        if (port == NULL)
-+                goto out_npiv;
-+
-+        path_prepend(path, "vport-%s", port);
-+
-+out_npiv:
-+        udev_device_unref(fc_vportdev);
- out:
-         udev_device_unref(fcdev);
-         return parent;
diff --git a/SOURCES/0273-ask-password-don-t-abort-when-message-is-missing.patch b/SOURCES/0273-ask-password-don-t-abort-when-message-is-missing.patch
new file mode 100644
index 0000000..2cd79fe
--- /dev/null
+++ b/SOURCES/0273-ask-password-don-t-abort-when-message-is-missing.patch
@@ -0,0 +1,35 @@
+From 2737fab0dba5ed238b4e0e927139e46e4911e1b4 Mon Sep 17 00:00:00 2001
+From: Lukas Nykryn <lnykryn@redhat.com>
+Date: Thu, 28 Jan 2016 16:01:51 +0100
+Subject: [PATCH] ask-password: don't abort when message is missing
+
+This was fixed in upstream in
+e287086b8aa2558356af225a12d9bfea8e7d61ca
+add support for caching passwords in the kernel keyring
+
+But we don't want that in rhel.
+
+rhel-only
+
+Resolves: #1261136
+---
+ src/shared/ask-password-api.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/src/shared/ask-password-api.c b/src/shared/ask-password-api.c
+index 0a61daf..19baa6b 100644
+--- a/src/shared/ask-password-api.c
++++ b/src/shared/ask-password-api.c
+@@ -70,9 +70,11 @@ int ask_password_tty(
+                 POLL_INOTIFY
+         };
+ 
+-        assert(message);
+         assert(_passphrase);
+ 
++        if (!message)
++                message = "Password:";
++
+         if (flag_file) {
+                 notify = inotify_init1(IN_CLOEXEC|IN_NONBLOCK);
+                 if (notify < 0) {
diff --git a/SOURCES/0273-rules-set-SYSTEMD_READY-0-on-DM_UDEV_DISABLE_OTHER_R.patch b/SOURCES/0273-rules-set-SYSTEMD_READY-0-on-DM_UDEV_DISABLE_OTHER_R.patch
deleted file mode 100644
index a7ee894..0000000
--- a/SOURCES/0273-rules-set-SYSTEMD_READY-0-on-DM_UDEV_DISABLE_OTHER_R.patch
+++ /dev/null
@@ -1,35 +0,0 @@
-From 92f17bb12a37fe9deb0868ef8c4a43696319e72e Mon Sep 17 00:00:00 2001
-From: Lukas Nykryn <lnykryn@redhat.com>
-Date: Thu, 25 Feb 2016 15:15:04 +0100
-Subject: [PATCH] rules: set SYSTEMD_READY=0 on
- DM_UDEV_DISABLE_OTHER_RULES_FLAG=1 only with ADD event
-
-The "SYSTEMD_READY=0" will cause automatic unmount
-of mountpoint that is on top of such DM device
-if this is used with multipath which sets
-DM_UDEV_DISABLE_OTHER_RULES_FLAG in case
-we have a CHANGE event thatcomes after DM multipath
-device reload when one of the paths is down or up.
-
-See https://bugzilla.redhat.com/show_bug.cgi?id=1312011
-
-RHEL-only
-Cherry-picked from: 83a3642f617975d596b5001b1699c3d16773a6e5
-Resolves: #1312011
----
- rules/99-systemd.rules.in | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/rules/99-systemd.rules.in b/rules/99-systemd.rules.in
-index b66d727..a4f4bf3 100644
---- a/rules/99-systemd.rules.in
-+++ b/rules/99-systemd.rules.in
-@@ -12,7 +12,7 @@ SUBSYSTEM=="tty", KERNEL=="tty[a-zA-Z]*|hvc*|xvc*|hvsi*|ttysclp*|sclp_line*|3270
- KERNEL=="vport*", TAG+="systemd"
- 
- SUBSYSTEM=="block", KERNEL!="ram*", TAG+="systemd"
--SUBSYSTEM=="block", KERNEL!="ram*", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}=="1", ENV{SYSTEMD_READY}="0"
-+SUBSYSTEM=="block", KERNEL!="ram*", ACTION=="add", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}=="1", ENV{SYSTEMD_READY}="0"
- 
- # Ignore encrypted devices with no identified superblock on it, since
- # we are probably still calling mke2fs or mkswap on it.
diff --git a/SOURCES/0274-Revert-journald-turn-ForwardToSyslog-off-by-default.patch b/SOURCES/0274-Revert-journald-turn-ForwardToSyslog-off-by-default.patch
deleted file mode 100644
index ce7e24e..0000000
--- a/SOURCES/0274-Revert-journald-turn-ForwardToSyslog-off-by-default.patch
+++ /dev/null
@@ -1,54 +0,0 @@
-From 298dd4f0bf734002a4fc7f51e5a46216017db2f6 Mon Sep 17 00:00:00 2001
-From: Lukas Nykryn <lnykryn@redhat.com>
-Date: Mon, 25 Jan 2016 14:03:47 +0100
-Subject: [PATCH] Revert "journald: turn ForwardToSyslog= off by default"
-
-This reverts commit 46b131574fdd7d77c15a0919ca9010cad7aa6ac7.
-
-rhel-only
-
-Resolves: #1285642
----
- man/journald.conf.xml         | 2 +-
- src/journal/journald-server.c | 1 +
- src/journal/journald.conf     | 2 +-
- 3 files changed, 3 insertions(+), 2 deletions(-)
-
-diff --git a/man/journald.conf.xml b/man/journald.conf.xml
-index 2cbe58b..c4f71e8 100644
---- a/man/journald.conf.xml
-+++ b/man/journald.conf.xml
-@@ -302,7 +302,7 @@
-         These options take boolean arguments. If forwarding to syslog
-         is enabled but nothing reads messages from the socket,
-         forwarding to syslog has no effect. By default, only
--        forwarding to wall is enabled. These settings may be
-+        forwarding to syslog and wall is enabled. These settings may be
-         overridden at boot time with the kernel command line options
-         <literal>systemd.journald.forward_to_syslog=</literal>,
-         <literal>systemd.journald.forward_to_kmsg=</literal>,
-diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c
-index f13147f..6a35ebb 100644
---- a/src/journal/journald-server.c
-+++ b/src/journal/journald-server.c
-@@ -1470,6 +1470,7 @@ int server_init(Server *s) {
-         s->rate_limit_interval = DEFAULT_RATE_LIMIT_INTERVAL;
-         s->rate_limit_burst = DEFAULT_RATE_LIMIT_BURST;
- 
-+        s->forward_to_syslog = true;
-         s->forward_to_wall = true;
- 
-         s->max_file_usec = DEFAULT_MAX_FILE_USEC;
-diff --git a/src/journal/journald.conf b/src/journal/journald.conf
-index 47eefe9..3907dfb 100644
---- a/src/journal/journald.conf
-+++ b/src/journal/journald.conf
-@@ -27,7 +27,7 @@
- #RuntimeMaxFileSize=
- #MaxRetentionSec=
- #MaxFileSec=1month
--#ForwardToSyslog=no
-+#ForwardToSyslog=yes
- #ForwardToKMsg=no
- #ForwardToConsole=no
- #ForwardToWall=yes
diff --git a/SOURCES/0274-sysv-generator-do-not-join-dependencies-on-one-line-.patch b/SOURCES/0274-sysv-generator-do-not-join-dependencies-on-one-line-.patch
new file mode 100644
index 0000000..99ffbe7
--- /dev/null
+++ b/SOURCES/0274-sysv-generator-do-not-join-dependencies-on-one-line-.patch
@@ -0,0 +1,135 @@
+From 72b3ff75e786efa2c9b2fdfb50e46597434c5420 Mon Sep 17 00:00:00 2001
+From: Lukas Nykryn <lnykryn@redhat.com>
+Date: Wed, 20 Jan 2016 15:16:32 +0100
+Subject: [PATCH] sysv-generator: do not join dependencies on one line, split
+ them
+
+If there is a lot of initscripts and dependencies between them we might
+end generating After= (and similar) lines which are longer then LINE_MAX
+and thus rejected by parser in systemd.
+
+Fixes #2099
+
+Cherry-picked from: c584ffc0b75d4b9e9229bf1d8edb7d89562be3c1
+Resolves: #1288600
+---
+ src/sysv-generator/sysv-generator.c | 44 ++++++++++---------------------------
+ test/sysv-generator-test.py         | 18 +++++++++++++--
+ 2 files changed, 28 insertions(+), 34 deletions(-)
+
+diff --git a/src/sysv-generator/sysv-generator.c b/src/sysv-generator/sysv-generator.c
+index 0a8a528..d60e75a 100644
+--- a/src/sysv-generator/sysv-generator.c
++++ b/src/sysv-generator/sysv-generator.c
+@@ -134,34 +134,14 @@ static int add_alias(const char *service, const char *alias) {
+ }
+ 
+ static int generate_unit_file(SysvStub *s) {
+-        char **p;
+         _cleanup_fclose_ FILE *f = NULL;
+-        _cleanup_free_ char *unit = NULL;
+-        _cleanup_free_ char *before = NULL;
+-        _cleanup_free_ char *after = NULL;
+-        _cleanup_free_ char *wants = NULL;
+-        _cleanup_free_ char *conflicts = NULL;
++        const char *unit;
++        char **p;
+         int r;
+ 
+-        before = strv_join(s->before, " ");
+-        if (!before)
+-                return log_oom();
+-
+-        after = strv_join(s->after, " ");
+-        if (!after)
+-                return log_oom();
+-
+-        wants = strv_join(s->wants, " ");
+-        if (!wants)
+-                return log_oom();
+-
+-        conflicts = strv_join(s->conflicts, " ");
+-        if (!conflicts)
+-                return log_oom();
++        assert(s);
+ 
+-        unit = strjoin(arg_dest, "/", s->name, NULL);
+-        if (!unit)
+-                return log_oom();
++        unit = strjoina(arg_dest, "/", s->name);
+ 
+         /* We might already have a symlink with the same name from a Provides:,
+          * or from backup files like /etc/init.d/foo.bak. Real scripts always win,
+@@ -183,14 +163,14 @@ static int generate_unit_file(SysvStub *s) {
+                 "Description=%s\n",
+                 s->path, s->description);
+ 
+-        if (!isempty(before))
+-                fprintf(f, "Before=%s\n", before);
+-        if (!isempty(after))
+-                fprintf(f, "After=%s\n", after);
+-        if (!isempty(wants))
+-                fprintf(f, "Wants=%s\n", wants);
+-        if (!isempty(conflicts))
+-                fprintf(f, "Conflicts=%s\n", conflicts);
++        STRV_FOREACH(p, s->before)
++                fprintf(f, "Before=%s\n", *p);
++        STRV_FOREACH(p, s->after)
++                fprintf(f, "After=%s\n", *p);
++        STRV_FOREACH(p, s->wants)
++                fprintf(f, "Wants=%s\n", *p);
++        STRV_FOREACH(p, s->conflicts)
++                fprintf(f, "Conflicts=%s\n", *p);
+ 
+         fprintf(f,
+                 "\n[Service]\n"
+diff --git a/test/sysv-generator-test.py b/test/sysv-generator-test.py
+index 2060ad7..25a35da 100644
+--- a/test/sysv-generator-test.py
++++ b/test/sysv-generator-test.py
+@@ -23,6 +23,7 @@ import subprocess
+ import tempfile
+ import shutil
+ from glob import glob
++import collections
+ 
+ try:
+     from configparser import RawConfigParser
+@@ -32,6 +33,12 @@ except ImportError:
+ 
+ sysv_generator = os.path.join(os.environ.get('builddir', '.'), 'systemd-sysv-generator')
+ 
++class MultiDict(collections.OrderedDict):
++    def __setitem__(self, key, value):
++        if isinstance(value, list) and key in self:
++            self[key].extend(value)
++        else:
++            super(MultiDict, self).__setitem__(key, value)
+ 
+ class SysvGeneratorTest(unittest.TestCase):
+     def setUp(self):
+@@ -77,7 +84,14 @@ class SysvGeneratorTest(unittest.TestCase):
+         for service in glob(self.out_dir + '/*.service'):
+             if os.path.islink(service):
+                 continue
+-            cp = RawConfigParser()
++            try:
++                # for python3 we need here strict=False to parse multiple
++                # lines with the same key
++                cp = RawConfigParser(dict_type=MultiDict, strict=False)
++            except TypeError:
++                # RawConfigParser in python2 does not have the strict option
++                # but it allows multiple lines with the same key by default
++                cp = RawConfigParser(dict_type=MultiDict)
+             cp.optionxform = lambda o: o  # don't lower-case option names
+             with open(service) as f:
+                 cp.readfp(f)
+@@ -215,7 +229,7 @@ class SysvGeneratorTest(unittest.TestCase):
+         s = self.run_generator()[1]['foo.service']
+         self.assertEqual(set(s.options('Unit')),
+                          set(['Documentation', 'SourcePath', 'Description', 'After']))
+-        self.assertEqual(s.get('Unit', 'After'), 'nss-lookup.target rpcbind.target')
++        self.assertEqual(s.get('Unit', 'After').split(), ['nss-lookup.target', 'rpcbind.target'])
+ 
+     def test_lsb_deps(self):
+         '''LSB header dependencies to other services'''
diff --git a/SOURCES/0275-journal-fix-error-handling-when-compressing-journal-.patch b/SOURCES/0275-journal-fix-error-handling-when-compressing-journal-.patch
deleted file mode 100644
index 286998e..0000000
--- a/SOURCES/0275-journal-fix-error-handling-when-compressing-journal-.patch
+++ /dev/null
@@ -1,67 +0,0 @@
-From 4c82b9247b29f31814e7ee5f77c745db659e27ac Mon Sep 17 00:00:00 2001
-From: Lennart Poettering <lennart@poettering.net>
-Date: Sat, 24 Oct 2015 13:17:54 +0200
-Subject: [PATCH] journal: fix error handling when compressing journal objects
-
-Let's make sure we handle compression errors properly, and don't
-misunderstand an error for success.
-
-Also, let's actually compress things if lz4 is enabled.
-
-Fixes #1662.
-
-Cherry-picked from: d1afbcd22170e95c79261340071d376fe41fc3af
-Resolves: #1292447
----
- src/journal/journal-file.c | 12 +++++++-----
- src/journal/journal-file.h |  5 +++++
- 2 files changed, 12 insertions(+), 5 deletions(-)
-
-diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c
-index f500568..a8f92e2 100644
---- a/src/journal/journal-file.c
-+++ b/src/journal/journal-file.c
-@@ -1051,23 +1051,25 @@ static int journal_file_append_data(
-         o->data.hash = htole64(hash);
- 
- #if defined(HAVE_XZ) || defined(HAVE_LZ4)
--        if (f->compress_xz &&
--            size >= COMPRESSION_SIZE_THRESHOLD) {
-+        if (JOURNAL_FILE_COMPRESS(f) && size >= COMPRESSION_SIZE_THRESHOLD) {
-                 size_t rsize;
- 
-                 compression = compress_blob(data, size, o->data.payload, &rsize);
- 
--                if (compression) {
-+                if (compression >= 0) {
-                         o->object.size = htole64(offsetof(Object, data.payload) + rsize);
-                         o->object.flags |= compression;
- 
-                         log_debug("Compressed data object %"PRIu64" -> %zu using %s",
-                                   size, rsize, object_compressed_to_string(compression));
--                }
-+                } else
-+                        /* Compression didn't work, we don't really care why, let's continue without compression */
-+                        compression = 0;
-+
-         }
- #endif
- 
--        if (!compression && size > 0)
-+        if (compression == 0 && size > 0)
-                 memcpy(o->data.payload, data, size);
- 
-         r = journal_file_link_data(f, o, p, hash);
-diff --git a/src/journal/journal-file.h b/src/journal/journal-file.h
-index 403c8f7..0f29b09 100644
---- a/src/journal/journal-file.h
-+++ b/src/journal/journal-file.h
-@@ -229,3 +229,8 @@ int journal_file_get_cutoff_realtime_usec(JournalFile *f, usec_t *from, usec_t *
- int journal_file_get_cutoff_monotonic_usec(JournalFile *f, sd_id128_t boot, usec_t *from, usec_t *to);
- 
- bool journal_file_rotate_suggested(JournalFile *f, usec_t max_file_usec);
-+
-+static inline bool JOURNAL_FILE_COMPRESS(JournalFile *f) {
-+        assert(f);
-+        return f->compress_xz || f->compress_lz4;
-+}
diff --git a/SOURCES/0275-udev-fibre-channel-fix-NPIV-support.patch b/SOURCES/0275-udev-fibre-channel-fix-NPIV-support.patch
new file mode 100644
index 0000000..5258624
--- /dev/null
+++ b/SOURCES/0275-udev-fibre-channel-fix-NPIV-support.patch
@@ -0,0 +1,69 @@
+From 569d98e9caae425120bf28f6b440e6cc117abc0d Mon Sep 17 00:00:00 2001
+From: Maurizio Lombardi <mlombard@redhat.com>
+Date: Mon, 1 Feb 2016 14:44:22 +0100
+Subject: [PATCH] udev: fibre channel: fix NPIV support
+
+When using NPIV, you can create multiple virtual HBAs on top of the
+physical one, this means that the physical N_Port can have multiple
+port IDs associated to it.
+Suppose a LUN is assigned to the physical HBA and to a virtual HBA,
+in both cases the original code uses the ID of the physical HBA
+to build the by-path link and udev will end up trying to create two by-path
+links with the same name.
+
+This patch fixes the problem by using the port ID of the virtual HBA
+whenever it detects that the device belongs to a virtual HBA,
+otherwise it uses the port ID of the physical HBA.
+
+(cherry-picked from 155a760bcedd11b7f3b430350a46f10736286895)
+
+Resolves: #1266934
+---
+ src/udev/udev-builtin-path_id.c | 27 ++++++++++++++++++++++++---
+ 1 file changed, 24 insertions(+), 3 deletions(-)
+
+diff --git a/src/udev/udev-builtin-path_id.c b/src/udev/udev-builtin-path_id.c
+index 9ca6084..695ac7f 100644
+--- a/src/udev/udev-builtin-path_id.c
++++ b/src/udev/udev-builtin-path_id.c
+@@ -92,6 +92,9 @@ static struct udev_device *skip_subsystem(struct udev_device *dev, const char *s
+ static struct udev_device *handle_scsi_fibre_channel(struct udev_device *parent, char **path) {
+         struct udev *udev  = udev_device_get_udev(parent);
+         struct udev_device *targetdev;
++        struct udev_device *rportdev;
++        struct udev_device *hostdev;
++        struct udev_device *vportdev;
+         struct udev_device *fcdev = NULL;
+         const char *port;
+         char *lun = NULL;
+@@ -100,9 +103,27 @@ static struct udev_device *handle_scsi_fibre_channel(struct udev_device *parent,
+         if (targetdev == NULL)
+                 return NULL;
+ 
+-        fcdev = udev_device_new_from_subsystem_sysname(udev, "fc_transport", udev_device_get_sysname(targetdev));
+-        if (fcdev == NULL)
+-                return NULL;
++        rportdev = udev_device_get_parent(targetdev);
++        if (rportdev == NULL)
++                goto skip_npiv_check;
++
++        hostdev = udev_device_get_parent(rportdev);
++        if (hostdev == NULL)
++                goto skip_npiv_check;
++
++        vportdev = udev_device_get_parent(hostdev);
++        if (vportdev == NULL)
++                goto skip_npiv_check;
++
++        fcdev = udev_device_new_from_subsystem_sysname(udev, "fc_vports", udev_device_get_sysname(vportdev));
++
++skip_npiv_check:
++        if (fcdev == NULL) {
++                fcdev = udev_device_new_from_subsystem_sysname(udev, "fc_transport", udev_device_get_sysname(targetdev));
++                if (fcdev == NULL)
++                        return NULL;
++        }
++
+         port = udev_device_get_sysattr_value(fcdev, "port_name");
+         if (port == NULL) {
+                 parent = NULL;
diff --git a/SOURCES/0276-ata_id-unreverse-WWN-identifier.patch b/SOURCES/0276-ata_id-unreverse-WWN-identifier.patch
new file mode 100644
index 0000000..afde9b5
--- /dev/null
+++ b/SOURCES/0276-ata_id-unreverse-WWN-identifier.patch
@@ -0,0 +1,43 @@
+From d1c32b69edc7f0f62a7c3f65691c2cb9fedcb112 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
+Date: Wed, 22 Jul 2015 00:23:47 -0400
+Subject: [PATCH] ata_id: unreverse WWN identifier
+
+An endianness conversion was lost in 6024a6e302bad6bcf073fa84a41a6123305dc845.
+Restore it. Now ata_id and scsi_id output match.
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1227503
+
+Cherry-picked from: 01f61d331bb5038f0c877ac03c54333328b6ea28
+Resolves: #1273306
+---
+ src/udev/ata_id/ata_id.c | 14 ++++++++++++--
+ 1 file changed, 12 insertions(+), 2 deletions(-)
+
+diff --git a/src/udev/ata_id/ata_id.c b/src/udev/ata_id/ata_id.c
+index b6f28c6..4adec44 100644
+--- a/src/udev/ata_id/ata_id.c
++++ b/src/udev/ata_id/ata_id.c
+@@ -638,10 +638,20 @@ int main(int argc, char *argv[])
+                  * All other values are reserved.
+                  */
+                 word = identify.wyde[108];
+-                if ((word & 0xf000) == 0x5000)
++                if ((word & 0xf000) == 0x5000) {
++                        uint64_t wwwn;
++
++                        wwwn   = identify.wyde[108];
++                        wwwn <<= 16;
++                        wwwn  |= identify.wyde[109];
++                        wwwn <<= 16;
++                        wwwn  |= identify.wyde[110];
++                        wwwn <<= 16;
++                        wwwn  |= identify.wyde[111];
+                         printf("ID_WWN=0x%1$" PRIx64 "\n"
+                                "ID_WWN_WITH_EXTENSION=0x%1$" PRIx64 "\n",
+-                               identify.octa[108/4]);
++                               wwwn);
++                }
+ 
+                 /* from Linux's include/linux/ata.h */
+                 if (identify.wyde[0] == 0x848a ||
diff --git a/SOURCES/0276-journal-irrelevant-coding-style-fixes.patch b/SOURCES/0276-journal-irrelevant-coding-style-fixes.patch
deleted file mode 100644
index 2895df5..0000000
--- a/SOURCES/0276-journal-irrelevant-coding-style-fixes.patch
+++ /dev/null
@@ -1,45 +0,0 @@
-From 8368db3b100bd587c580d5ed2561390c5ed76a8c Mon Sep 17 00:00:00 2001
-From: Lennart Poettering <lennart@poettering.net>
-Date: Sat, 24 Oct 2015 15:08:15 +0200
-Subject: [PATCH] journal: irrelevant coding style fixes
-
-Cherry-picked from: 0240c603691e006165d8687d6a2c70859755b11f
-Related: #1292447
----
- src/journal/compress.c     | 9 +++++----
- src/journal/journal-file.c | 2 +-
- 2 files changed, 6 insertions(+), 5 deletions(-)
-
-diff --git a/src/journal/compress.c b/src/journal/compress.c
-index 6923753..c9a3399 100644
---- a/src/journal/compress.c
-+++ b/src/journal/compress.c
-@@ -51,10 +51,11 @@ int compress_blob_xz(const void *src, uint64_t src_size, void *dst, size_t *dst_
- #ifdef HAVE_XZ
-         static const lzma_options_lzma opt = {
-                 1u << 20u, NULL, 0, LZMA_LC_DEFAULT, LZMA_LP_DEFAULT,
--                LZMA_PB_DEFAULT, LZMA_MODE_FAST, 128, LZMA_MF_HC3, 4};
--        static const lzma_filter filters[2] = {
--                {LZMA_FILTER_LZMA2, (lzma_options_lzma*) &opt},
--                {LZMA_VLI_UNKNOWN, NULL}
-+                LZMA_PB_DEFAULT, LZMA_MODE_FAST, 128, LZMA_MF_HC3, 4
-+        };
-+        static const lzma_filter filters[] = {
-+                { LZMA_FILTER_LZMA2, (lzma_options_lzma*) &opt },
-+                { LZMA_VLI_UNKNOWN, NULL }
-         };
-         lzma_ret ret;
-         size_t out_pos = 0;
-diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c
-index a8f92e2..892fe47 100644
---- a/src/journal/journal-file.c
-+++ b/src/journal/journal-file.c
-@@ -1032,7 +1032,7 @@ static int journal_file_append_data(
-         r = journal_file_find_data_object_with_hash(f, data, size, hash, &o, &p);
-         if (r < 0)
-                 return r;
--        else if (r > 0) {
-+        if (r > 0) {
- 
-                 if (ret)
-                         *ret = o;
diff --git a/SOURCES/0277-Fixup-WWN-bytes-for-big-endian-systems.patch b/SOURCES/0277-Fixup-WWN-bytes-for-big-endian-systems.patch
new file mode 100644
index 0000000..1ed0185
--- /dev/null
+++ b/SOURCES/0277-Fixup-WWN-bytes-for-big-endian-systems.patch
@@ -0,0 +1,26 @@
+From 2a62c3c66698148f1439176bd6ca5a946b8de550 Mon Sep 17 00:00:00 2001
+From: Tom Lyon <pugs@drivescale.com>
+Date: Mon, 21 Sep 2015 14:36:32 -0700
+Subject: [PATCH] Fixup WWN bytes for big-endian systems
+
+Cherry-picked from: cf22cddcfd07d10fecd7b03ef465e957054daec2
+Resolves: #1273306
+---
+ src/udev/ata_id/ata_id.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/src/udev/ata_id/ata_id.c b/src/udev/ata_id/ata_id.c
+index 4adec44..ef05fba 100644
+--- a/src/udev/ata_id/ata_id.c
++++ b/src/udev/ata_id/ata_id.c
+@@ -485,6 +485,10 @@ int main(int argc, char *argv[])
+                 disk_identify_fixup_uint16(identify.byte,  90);     /* time required for enhanced SECURITY ERASE UNIT */
+                 disk_identify_fixup_uint16(identify.byte,  91);     /* current APM values */
+                 disk_identify_fixup_uint16(identify.byte,  94);     /* current AAM value */
++                disk_identify_fixup_uint16(identify.byte, 108);     /* wwn */
++                disk_identify_fixup_uint16(identify.byte, 109);     /* wwn */
++                disk_identify_fixup_uint16(identify.byte, 110);     /* wwn */
++                disk_identify_fixup_uint16(identify.byte, 111);     /* wwn */
+                 disk_identify_fixup_uint16(identify.byte, 128);     /* device lock function */
+                 disk_identify_fixup_uint16(identify.byte, 217);     /* nominal media rotation rate */
+                 memcpy(&id, identify.byte, sizeof id);
diff --git a/SOURCES/0277-fstab-generator-cescape-device-name-in-root-fsck-ser.patch b/SOURCES/0277-fstab-generator-cescape-device-name-in-root-fsck-ser.patch
deleted file mode 100644
index 860308b..0000000
--- a/SOURCES/0277-fstab-generator-cescape-device-name-in-root-fsck-ser.patch
+++ /dev/null
@@ -1,49 +0,0 @@
-From f29f53f95636fea60a3f757786131790477ab71a Mon Sep 17 00:00:00 2001
-From: Andrei Borzenkov <arvidjaar@gmail.com>
-Date: Wed, 3 Jun 2015 20:50:59 +0300
-Subject: [PATCH] fstab-generator: cescape device name in root-fsck service
-
-We unescape ExecStart line when parsing it, so escape device name
-before adding it to unit file.
-
-fixes #50
-
-Cherry-picked from: fa05e97
-Resolves: #1306126
----
- src/shared/generator.c | 10 ++++++++--
- 1 file changed, 8 insertions(+), 2 deletions(-)
-
-diff --git a/src/shared/generator.c b/src/shared/generator.c
-index 3af84a3..be8e24e 100644
---- a/src/shared/generator.c
-+++ b/src/shared/generator.c
-@@ -35,8 +35,13 @@
- static int write_fsck_sysroot_service(const char *dir, const char *what) {
-         const char *unit;
-         _cleanup_free_ char *device = NULL;
-+        _cleanup_free_ char *escaped;
-         _cleanup_fclose_ FILE *f = NULL;
- 
-+        escaped = cescape(what);
-+        if (!escaped)
-+                return log_oom();
-+
-         unit = strjoina(dir, "/systemd-fsck-root.service");
-         log_debug("Creating %s", unit);
- 
-@@ -61,11 +66,12 @@ static int write_fsck_sysroot_service(const char *dir, const char *what) {
-                 "[Service]\n"
-                 "Type=oneshot\n"
-                 "RemainAfterExit=yes\n"
--                "ExecStart=" SYSTEMD_FSCK_PATH " %2$s\n"
-+                "ExecStart=" SYSTEMD_FSCK_PATH " %4$s\n"
-                 "TimeoutSec=0\n",
-                 program_invocation_short_name,
-                 what,
--                device);
-+                device,
-+                escaped);
- 
-         fflush(f);
-         if (ferror(f))
diff --git a/SOURCES/0278-manager-reduce-complexity-of-unit_gc_sweep-3507.patch b/SOURCES/0278-manager-reduce-complexity-of-unit_gc_sweep-3507.patch
deleted file mode 100644
index 1ecb187..0000000
--- a/SOURCES/0278-manager-reduce-complexity-of-unit_gc_sweep-3507.patch
+++ /dev/null
@@ -1,62 +0,0 @@
-From 8994877c8c0d2cab6e5c7e8cf98df5ff580d87a8 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Nykr=C3=BDn?= <lnykryn@redhat.com>
-Date: Tue, 14 Jun 2016 14:20:56 +0200
-Subject: [PATCH] manager: reduce complexity of unit_gc_sweep (#3507)
-
-When unit is marked as UNSURE, we are trying to find if it state was
-changed over and over again. So lets not go through the UNSURE states
-again. Also when we find a GOOD unit lets propagate the GOOD state to
-all units that this unit reference.
-
-This is a problem on machines with a lot of initscripts with different
-starting priority, since those units will reference each other and the
-original algorithm might get to n! complexity.
-
-Thanks HATAYAMA Daisuke for the expand_good_state code.
-Cherry-picked from: 4892084f096c19da0e83f28f250ca187b58c22b2
-Resolves: #1344556
----
- src/core/manager.c | 16 +++++++++++++++-
- 1 file changed, 15 insertions(+), 1 deletion(-)
-
-diff --git a/src/core/manager.c b/src/core/manager.c
-index 7483a96..45ca540 100644
---- a/src/core/manager.c
-+++ b/src/core/manager.c
-@@ -765,6 +765,19 @@ enum {
-         _GC_OFFSET_MAX
- };
- 
-+static void unit_gc_mark_good(Unit *u, unsigned gc_marker)
-+{
-+        Iterator i;
-+        Unit *other;
-+
-+        u->gc_marker = gc_marker + GC_OFFSET_GOOD;
-+
-+        /* Recursively mark referenced units as GOOD as well */
-+        SET_FOREACH(other, u->dependencies[UNIT_REFERENCES], i)
-+                if (other->gc_marker == gc_marker + GC_OFFSET_UNSURE)
-+                        unit_gc_mark_good(other, gc_marker);
-+}
-+
- static void unit_gc_sweep(Unit *u, unsigned gc_marker) {
-         Iterator i;
-         Unit *other;
-@@ -774,6 +787,7 @@ static void unit_gc_sweep(Unit *u, unsigned gc_marker) {
- 
-         if (u->gc_marker == gc_marker + GC_OFFSET_GOOD ||
-             u->gc_marker == gc_marker + GC_OFFSET_BAD ||
-+            u->gc_marker == gc_marker + GC_OFFSET_UNSURE ||
-             u->gc_marker == gc_marker + GC_OFFSET_IN_PATH)
-                 return;
- 
-@@ -814,7 +828,7 @@ bad:
-         return;
- 
- good:
--        u->gc_marker = gc_marker + GC_OFFSET_GOOD;
-+        unit_gc_mark_good(u, gc_marker);
- }
- 
- static unsigned manager_dispatch_gc_queue(Manager *m) {
diff --git a/SOURCES/0278-sd-journal-introduce-has_runtime_files-and-has_persi.patch b/SOURCES/0278-sd-journal-introduce-has_runtime_files-and-has_persi.patch
new file mode 100644
index 0000000..bd281be
--- /dev/null
+++ b/SOURCES/0278-sd-journal-introduce-has_runtime_files-and-has_persi.patch
@@ -0,0 +1,276 @@
+From 5ec508cc5c13d831c93ce98d84b1d9cedb0117a7 Mon Sep 17 00:00:00 2001
+From: Jan Synacek <jsynacek@redhat.com>
+Date: Mon, 1 Feb 2016 09:23:58 +0100
+Subject: [PATCH] sd-journal: introduce has_runtime_files and
+ has_persistent_files
+
+Also introduce sd_journal_has_runtime_files() and
+sd_journal_has_persistent_files() to the public API. These functions
+can be used to easily find out if the open journal files are runtime
+and/or persistent.
+
+Cherry-picked from: 39fd5b08a73f144a20202a665bd25cad51d8a90b
+Resolves: #1082179
+---
+ Makefile-man.am                      |  7 +++
+ man/sd-journal.xml                   |  8 ++-
+ man/sd_journal_has_runtime_files.xml | 95 ++++++++++++++++++++++++++++++++++++
+ src/journal/journal-internal.h       |  2 +
+ src/journal/sd-journal.c             | 29 +++++++----
+ src/systemd/sd-journal.h             |  3 ++
+ 6 files changed, 133 insertions(+), 11 deletions(-)
+ create mode 100644 man/sd_journal_has_runtime_files.xml
+
+diff --git a/Makefile-man.am b/Makefile-man.am
+index 497be66..7ec709c 100644
+--- a/Makefile-man.am
++++ b/Makefile-man.am
+@@ -40,6 +40,7 @@ MANPAGES += \
+ 	man/sd_journal_get_fd.3 \
+ 	man/sd_journal_get_realtime_usec.3 \
+ 	man/sd_journal_get_usage.3 \
++	man/sd_journal_has_runtime_files.3 \
+ 	man/sd_journal_next.3 \
+ 	man/sd_journal_open.3 \
+ 	man/sd_journal_print.3 \
+@@ -176,6 +177,7 @@ MANPAGES_ALIAS += \
+ 	man/sd_journal_get_events.3 \
+ 	man/sd_journal_get_monotonic_usec.3 \
+ 	man/sd_journal_get_timeout.3 \
++	man/sd_journal_has_persistent_files.3 \
+ 	man/sd_journal_next_skip.3 \
+ 	man/sd_journal_open_container.3 \
+ 	man/sd_journal_open_directory.3 \
+@@ -287,6 +289,7 @@ man/sd_journal_get_data_threshold.3: man/sd_journal_get_data.3
+ man/sd_journal_get_events.3: man/sd_journal_get_fd.3
+ man/sd_journal_get_monotonic_usec.3: man/sd_journal_get_realtime_usec.3
+ man/sd_journal_get_timeout.3: man/sd_journal_get_fd.3
++man/sd_journal_has_persistent_files.3: man/sd_journal_has_runtime_files.3
+ man/sd_journal_next_skip.3: man/sd_journal_next.3
+ man/sd_journal_open_container.3: man/sd_journal_open.3
+ man/sd_journal_open_directory.3: man/sd_journal_open.3
+@@ -500,6 +503,9 @@ man/sd_journal_get_monotonic_usec.html: man/sd_journal_get_realtime_usec.html
+ man/sd_journal_get_timeout.html: man/sd_journal_get_fd.html
+ 	$(html-alias)
+ 
++man/sd_journal_has_persistent_files.html: man/sd_journal_has_runtime_files.html
++	$(html-alias)
++
+ man/sd_journal_next_skip.html: man/sd_journal_next.html
+ 	$(html-alias)
+ 
+@@ -1727,6 +1733,7 @@ EXTRA_DIST += \
+ 	man/sd_journal_get_fd.xml \
+ 	man/sd_journal_get_realtime_usec.xml \
+ 	man/sd_journal_get_usage.xml \
++	man/sd_journal_has_runtime_files.xml \
+ 	man/sd_journal_next.xml \
+ 	man/sd_journal_open.xml \
+ 	man/sd_journal_print.xml \
+diff --git a/man/sd-journal.xml b/man/sd-journal.xml
+index 9b1a522..a1185d3 100644
+--- a/man/sd-journal.xml
++++ b/man/sd-journal.xml
+@@ -81,9 +81,11 @@
+     <citerefentry><refentrytitle>sd_journal_get_cutoff_realtime_usec</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+     <citerefentry><refentrytitle>sd_journal_get_cutoff_monotonic_usec</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+     <citerefentry><refentrytitle>sd_journal_get_usage</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+-    <citerefentry><refentrytitle>sd_journal_get_catalog</refentrytitle><manvolnum>3</manvolnum></citerefentry>
++    <citerefentry><refentrytitle>sd_journal_get_catalog</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
++    <citerefentry><refentrytitle>sd_journal_get_fd</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
++    <citerefentry><refentrytitle>sd_journal_has_runtime_files</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+     and
+-    <citerefentry><refentrytitle>sd_journal_get_fd</refentrytitle><manvolnum>3</manvolnum></citerefentry>
++    <citerefentry><refentrytitle>sd_journal_has_persistent_files</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+     for more information about the functions implemented.</para>
+ 
+     <para>Command line access for submitting entries to the journal is
+@@ -116,6 +118,8 @@
+       <citerefentry><refentrytitle>sd_journal_get_fd</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+       <citerefentry><refentrytitle>sd_journal_query_unique</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+       <citerefentry><refentrytitle>sd_journal_get_catalog</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
++      <citerefentry><refentrytitle>sd_journal_has_runtime_files</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
++      <citerefentry><refentrytitle>sd_journal_has_persistent_files</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+       <citerefentry><refentrytitle>journalctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+       <citerefentry><refentrytitle>sd-id128</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+       <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+diff --git a/man/sd_journal_has_runtime_files.xml b/man/sd_journal_has_runtime_files.xml
+new file mode 100644
+index 0000000..237e649
+--- /dev/null
++++ b/man/sd_journal_has_runtime_files.xml
+@@ -0,0 +1,95 @@
++<?xml version='1.0'?> <!--*-nxml-*-->
++<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
++  "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
++
++<!--
++  This file is part of systemd.
++
++  Copyright 2016 Jan Synáček
++
++  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/>.
++-->
++
++<refentry id="sd_journal_has_runtime_files">
++
++  <refentryinfo>
++    <title>sd_journal_has_runtime_files</title>
++    <productname>systemd</productname>
++
++    <authorgroup>
++      <author>
++        <contrib>Developer</contrib>
++        <firstname>Jan</firstname>
++        <surname>Synáček</surname>
++        <email>jan.synacek@gmail.com</email>
++      </author>
++    </authorgroup>
++  </refentryinfo>
++
++  <refmeta>
++    <refentrytitle>sd_journal_has_runtime_files</refentrytitle>
++    <manvolnum>3</manvolnum>
++  </refmeta>
++
++  <refnamediv>
++    <refname>sd_journal_has_runtime_files</refname>
++    <refname>sd_journal_has_persistent_files</refname>
++    <refpurpose>Query availability of runtime or persistent journal files.</refpurpose>
++  </refnamediv>
++
++  <refsynopsisdiv>
++    <funcsynopsis>
++      <funcsynopsisinfo>#include &lt;systemd/sd-journal.h&gt;</funcsynopsisinfo>
++
++      <funcprototype>
++        <funcdef>int <function>sd_journal_has_runtime_files</function></funcdef>
++        <paramdef>sd_journal *<parameter>j</parameter></paramdef>
++      </funcprototype>
++
++      <funcprototype>
++        <funcdef>int <function>sd_journal_has_persistent_files</function></funcdef>
++        <paramdef>sd_journal *<parameter>j</parameter></paramdef>
++      </funcprototype>
++
++    </funcsynopsis>
++  </refsynopsisdiv>
++
++  <refsect1>
++    <title>Description</title>
++
++    <para><function>sd_journal_has_runtime_files()</function> returns a positive value
++    if runtime journal files (present in /run/systemd/journal/) have been found.
++    Otherwise returns 0.</para>
++
++    <para><function>sd_journal_has_persistent_files()</function> returns a positive value
++    if persistent journal files (present in /var/log/journal/) have been found.
++    Otherwise returns 0.</para>
++  </refsect1>
++
++  <refsect1>
++    <title>Return value</title>
++    <para>Both <function>sd_journal_has_runtime_files()</function>
++    and <function>sd_journal_has_persistent_files()</function> return -EINVAL
++    if their argument is NULL.
++    </para>
++  </refsect1>
++
++  <refsect1>
++    <title>See Also</title>
++    <para>
++      <citerefentry><refentrytitle>sd-journal</refentrytitle><manvolnum>3</manvolnum></citerefentry>
++    </para>
++  </refsect1>
++
++</refentry>
+diff --git a/src/journal/journal-internal.h b/src/journal/journal-internal.h
+index b51ecdb..115d777 100644
+--- a/src/journal/journal-internal.h
++++ b/src/journal/journal-internal.h
+@@ -115,6 +115,8 @@ struct sd_journal {
+                                   removed, and there were no more
+                                   files, so sd_j_enumerate_unique
+                                   will return a value equal to 0. */
++        bool has_runtime_files:1;
++        bool has_persistent_files:1;
+ 
+         size_t data_threshold;
+ 
+diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c
+index 9b9e8ac..20456c3 100644
+--- a/src/journal/sd-journal.c
++++ b/src/journal/sd-journal.c
+@@ -1230,8 +1230,7 @@ static int add_any_file(sd_journal *j, const char *path) {
+ }
+ 
+ static int add_file(sd_journal *j, const char *prefix, const char *filename) {
+-        _cleanup_free_ char *path = NULL;
+-        int r;
++        char *path = NULL;
+ 
+         assert(j);
+         assert(prefix);
+@@ -1241,14 +1240,14 @@ static int add_file(sd_journal *j, const char *prefix, const char *filename) {
+             !file_type_wanted(j->flags, filename))
+                 return 0;
+ 
+-        path = strjoin(prefix, "/", filename, NULL);
+-        if (!path)
+-                return -ENOMEM;
++        path = strjoina(prefix, "/", filename);
+ 
+-        r = add_any_file(j, path);
+-        if (r == -ENOENT)
+-                return 0;
+-        return r;
++        if (!j->has_runtime_files && path_startswith(path, "/run/log/journal"))
++                j->has_runtime_files = true;
++        else if (!j->has_persistent_files && path_startswith(path, "/var/log/journal"))
++                j->has_persistent_files = true;
++
++        return add_any_file(j, path);
+ }
+ 
+ static int remove_file(sd_journal *j, const char *prefix, const char *filename) {
+@@ -2616,3 +2615,15 @@ _public_ int sd_journal_get_data_threshold(sd_journal *j, size_t *sz) {
+         *sz = j->data_threshold;
+         return 0;
+ }
++
++_public_ int sd_journal_has_runtime_files(sd_journal *j) {
++        assert_return(j, -EINVAL);
++
++        return j->has_runtime_files;
++}
++
++_public_ int sd_journal_has_persistent_files(sd_journal *j) {
++        assert_return(j, -EINVAL);
++
++        return j->has_persistent_files;
++}
+diff --git a/src/systemd/sd-journal.h b/src/systemd/sd-journal.h
+index 00237a2..d5fd46e 100644
+--- a/src/systemd/sd-journal.h
++++ b/src/systemd/sd-journal.h
+@@ -138,6 +138,9 @@ int sd_journal_reliable_fd(sd_journal *j);
+ int sd_journal_get_catalog(sd_journal *j, char **text);
+ int sd_journal_get_catalog_for_message_id(sd_id128_t id, char **text);
+ 
++int sd_journal_has_runtime_files(sd_journal *j);
++int sd_journal_has_persistent_files(sd_journal *j);
++
+ /* the inverse condition avoids ambiguity of danling 'else' after the macro */
+ #define SD_JOURNAL_FOREACH(j)                                           \
+         if (sd_journal_seek_head(j) < 0) { }                            \
diff --git a/SOURCES/0279-core-use-an-AF_UNIX-SOCK_DGRAM-socket-for-cgroup-age.patch b/SOURCES/0279-core-use-an-AF_UNIX-SOCK_DGRAM-socket-for-cgroup-age.patch
deleted file mode 100644
index 7690756..0000000
--- a/SOURCES/0279-core-use-an-AF_UNIX-SOCK_DGRAM-socket-for-cgroup-age.patch
+++ /dev/null
@@ -1,489 +0,0 @@
-From 72696594d40d538e26f6522e064d79f70c8b2f9e Mon Sep 17 00:00:00 2001
-From: Lennart Poettering <lennart@poettering.net>
-Date: Wed, 4 May 2016 20:43:23 +0200
-Subject: [PATCH] core: use an AF_UNIX/SOCK_DGRAM socket for cgroup agent
- notification
-
-dbus-daemon currently uses a backlog of 30 on its D-bus system bus socket. On
-overloaded systems this means that only 30 connections may be queued without
-dbus-daemon processing them before further connection attempts fail. Our
-cgroups-agent binary so far used D-Bus for its messaging, and hitting this
-limit hence may result in us losing cgroup empty messages.
-
-This patch adds a seperate cgroup agent socket of type AF_UNIX/SOCK_DGRAM.
-Since sockets of these types need no connection set up, no listen() backlog
-applies. Our cgroup-agent binary will hence simply block as long as it can't
-enqueue its datagram message, so that we won't lose cgroup empty messages as
-likely anymore.
-
-This also rearranges the ordering of the processing of SIGCHLD signals, service
-notification messages (sd_notify()...) and the two types of cgroup
-notifications (inotify for the unified hierarchy support, and agent for the
-classic hierarchy support). We now always process events for these in the
-following order:
-
-  1. service notification messages  (SD_EVENT_PRIORITY_NORMAL-7)
-  2. SIGCHLD signals (SD_EVENT_PRIORITY_NORMAL-6)
-  3. cgroup inotify and cgroup agent (SD_EVENT_PRIORITY_NORMAL-5)
-
-This is because when receiving SIGCHLD we invalidate PID information, which we
-need to process the service notification messages which are bound to PIDs.
-Hence the order between the first two items. And we want to process SIGCHLD
-metadata to detect whether a service is gone, before using cgroup
-notifications, to decide when a service is gone, since the former carries more
-useful metadata.
-
-Related to this:
-https://bugs.freedesktop.org/show_bug.cgi?id=95264
-https://github.com/systemd/systemd/issues/1961
-
-Cherry-picked from: d8fdc62037b5b0a9fd603ad5efd6b49f956f86b5
-Resolves: #1305608
----
- src/cgroups-agent/cgroups-agent.c |  48 ++++++------
- src/core/cgroup.c                 |   2 +
- src/core/dbus.c                   |  56 +++++++-------
- src/core/dbus.h                   |   2 +
- src/core/manager.c                | 149 ++++++++++++++++++++++++++++++++++++--
- src/core/manager.h                |   3 +
- 6 files changed, 198 insertions(+), 62 deletions(-)
-
-diff --git a/src/cgroups-agent/cgroups-agent.c b/src/cgroups-agent/cgroups-agent.c
-index 529e843..2fe6583 100644
---- a/src/cgroups-agent/cgroups-agent.c
-+++ b/src/cgroups-agent/cgroups-agent.c
-@@ -1,5 +1,3 @@
--/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
--
- /***
-   This file is part of systemd.
- 
-@@ -20,14 +18,21 @@
- ***/
- 
- #include <stdlib.h>
-+#include <sys/socket.h>
- 
--#include "sd-bus.h"
- #include "log.h"
--#include "bus-util.h"
-+#include "socket-util.h"
- 
- int main(int argc, char *argv[]) {
--        _cleanup_bus_close_unref_ sd_bus *bus = NULL;
--        int r;
-+
-+        static const union sockaddr_union sa = {
-+                .un.sun_family = AF_UNIX,
-+                .un.sun_path = "/run/systemd/cgroups-agent",
-+        };
-+
-+        _cleanup_close_ int fd = -1;
-+        ssize_t n;
-+        size_t l;
- 
-         if (argc != 2) {
-                 log_error("Incorrect number of arguments.");
-@@ -38,27 +43,22 @@ int main(int argc, char *argv[]) {
-         log_parse_environment();
-         log_open();
- 
--        /* We send this event to the private D-Bus socket and then the
--         * system instance will forward this to the system bus. We do
--         * this to avoid an activation loop when we start dbus when we
--         * are called when the dbus service is shut down. */
--
--        r = bus_open_system_systemd(&bus);
--        if (r < 0) {
--                /* If we couldn't connect we assume this was triggered
--                 * while systemd got restarted/transitioned from
--                 * initrd to the system, so let's ignore this */
--                log_debug_errno(r, "Failed to get D-Bus connection: %m");
-+        fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
-+        if (fd < 0) {
-+                log_debug_errno(errno, "Failed to allocate socket: %m");
-+                return EXIT_FAILURE;
-+        }
-+
-+        l = strlen(argv[1]);
-+
-+        n = sendto(fd, argv[1], l, 0, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path));
-+        if (n < 0) {
-+                log_debug_errno(errno, "Failed to send cgroups agent message: %m");
-                 return EXIT_FAILURE;
-         }
- 
--        r = sd_bus_emit_signal(bus,
--                               "/org/freedesktop/systemd1/agent",
--                               "org.freedesktop.systemd1.Agent",
--                               "Released",
--                               "s", argv[1]);
--        if (r < 0) {
--                log_debug_errno(r, "Failed to send signal message on private connection: %m");
-+        if ((size_t) n != l) {
-+                log_debug("Datagram size mismatch");
-                 return EXIT_FAILURE;
-         }
- 
-diff --git a/src/core/cgroup.c b/src/core/cgroup.c
-index 10fdcc9..b7f08fb 100644
---- a/src/core/cgroup.c
-+++ b/src/core/cgroup.c
-@@ -1028,6 +1028,8 @@ int manager_notify_cgroup_empty(Manager *m, const char *cgroup) {
-         assert(m);
-         assert(cgroup);
- 
-+        log_debug("Got cgroup empty notification for: %s", cgroup);
-+
-         u = manager_get_unit_by_cgroup(m, cgroup);
-         if (u) {
-                 r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, true);
-diff --git a/src/core/dbus.c b/src/core/dbus.c
-index 85b5174..29524d4 100644
---- a/src/core/dbus.c
-+++ b/src/core/dbus.c
-@@ -72,12 +72,37 @@ int bus_send_queued_message(Manager *m) {
-         return 0;
- }
- 
-+int bus_forward_agent_released(Manager *m, const char *path) {
-+        int r;
-+
-+        assert(m);
-+        assert(path);
-+
-+        if (!m->running_as == SYSTEMD_SYSTEM)
-+                return 0;
-+
-+        if (!m->system_bus)
-+                return 0;
-+
-+        /* If we are running a system instance we forward the agent message on the system bus, so that the user
-+         * instances get notified about this, too */
-+
-+        r = sd_bus_emit_signal(m->system_bus,
-+                               "/org/freedesktop/systemd1/agent",
-+                               "org.freedesktop.systemd1.Agent",
-+                               "Released",
-+                               "s", path);
-+        if (r < 0)
-+                return log_warning_errno(r, "Failed to propagate agent release message: %m");
-+
-+        return 1;
-+}
-+
- static int signal_agent_released(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
-         Manager *m = userdata;
-         const char *cgroup;
-         int r;
- 
--        assert(bus);
-         assert(message);
-         assert(m);
- 
-@@ -88,16 +113,6 @@ static int signal_agent_released(sd_bus *bus, sd_bus_message *message, void *use
-         }
- 
-         manager_notify_cgroup_empty(m, cgroup);
--
--        if (m->running_as == SYSTEMD_SYSTEM && m->system_bus) {
--                /* If we are running as system manager, forward the
--                 * message to the system bus */
--
--                r = sd_bus_send(m->system_bus, message, NULL);
--                if (r < 0)
--                        log_warning_errno(r, "Failed to forward Released message: %m");
--        }
--
-         return 0;
- }
- 
-@@ -679,25 +694,6 @@ static int bus_on_connection(sd_event_source *s, int fd, uint32_t revents, void
-                 return 0;
-         }
- 
--        if (m->running_as == SYSTEMD_SYSTEM) {
--                /* When we run as system instance we get the Released
--                 * signal via a direct connection */
--
--                r = sd_bus_add_match(
--                                bus,
--                                NULL,
--                                "type='signal',"
--                                "interface='org.freedesktop.systemd1.Agent',"
--                                "member='Released',"
--                                "path='/org/freedesktop/systemd1/agent'",
--                                signal_agent_released, m);
--
--                if (r < 0) {
--                        log_warning_errno(r, "Failed to register Released match on new connection bus: %m");
--                        return 0;
--                }
--        }
--
-         r = bus_setup_disconnected_match(m, bus);
-         if (r < 0)
-                 return 0;
-diff --git a/src/core/dbus.h b/src/core/dbus.h
-index d04f532..c27d136 100644
---- a/src/core/dbus.h
-+++ b/src/core/dbus.h
-@@ -40,3 +40,5 @@ int bus_verify_manage_unit_async(Manager *m, sd_bus_message *call, sd_bus_error
- int bus_verify_manage_unit_async_for_kill(Manager *m, sd_bus_message *call, sd_bus_error *error);
- int bus_verify_manage_unit_files_async(Manager *m, sd_bus_message *call, sd_bus_error *error);
- int bus_verify_reload_daemon_async(Manager *m, sd_bus_message *call, sd_bus_error *error);
-+
-+int bus_forward_agent_released(Manager *m, const char *path);
-diff --git a/src/core/manager.c b/src/core/manager.c
-index 45ca540..b6d76ca 100644
---- a/src/core/manager.c
-+++ b/src/core/manager.c
-@@ -83,8 +83,10 @@
- #define JOBS_IN_PROGRESS_WAIT_USEC (5*USEC_PER_SEC)
- #define JOBS_IN_PROGRESS_PERIOD_USEC (USEC_PER_SEC / 3)
- #define JOBS_IN_PROGRESS_PERIOD_DIVISOR 3
-+#define CGROUPS_AGENT_RCVBUF_SIZE (8*1024*1024)
- 
- static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata);
-+static int manager_dispatch_cgroups_agent_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata);
- static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata);
- static int manager_dispatch_time_change_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata);
- static int manager_dispatch_idle_pipe_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata);
-@@ -456,11 +458,11 @@ static int manager_setup_signals(Manager *m) {
-         if (r < 0)
-                 return r;
- 
--        /* Process signals a bit earlier than the rest of things, but
--         * later than notify_fd processing, so that the notify
--         * processing can still figure out to which process/service a
--         * message belongs, before we reap the process. */
--        r = sd_event_source_set_priority(m->signal_event_source, -5);
-+        /* Process signals a bit earlier than the rest of things, but later than notify_fd processing, so that the
-+         * notify processing can still figure out to which process/service a message belongs, before we reap the
-+         * process. Also, process this before handling cgroup notifications, so that we always collect child exit
-+         * status information before detecting that there's no process in a cgroup. */
-+        r = sd_event_source_set_priority(m->signal_event_source, -6);
-         if (r < 0)
-                 return r;
- 
-@@ -541,7 +543,7 @@ int manager_new(SystemdRunningAs running_as, bool test_run, Manager **_m) {
- 
-         m->idle_pipe[0] = m->idle_pipe[1] = m->idle_pipe[2] = m->idle_pipe[3] = -1;
- 
--        m->pin_cgroupfs_fd = m->notify_fd = m->signal_fd = m->time_change_fd = m->dev_autofs_fd = m->private_listen_fd = m->kdbus_fd = m->utab_inotify_fd = -1;
-+        m->pin_cgroupfs_fd = m->notify_fd = m->cgroups_agent_fd = m->signal_fd = m->time_change_fd = m->dev_autofs_fd = m->private_listen_fd = m->kdbus_fd = m->utab_inotify_fd = -1;
-         m->current_job_id = 1; /* start as id #1, so that we can leave #0 around as "null-like" value */
- 
-         m->ask_password_inotify_fd = -1;
-@@ -689,8 +691,8 @@ static int manager_setup_notify(Manager *m) {
-                 if (r < 0)
-                         return log_error_errno(r, "Failed to allocate notify event source: %m");
- 
--                /* Process signals a bit earlier than SIGCHLD, so that we can
--                 * still identify to which service an exit message belongs */
-+                /* Process notification messages a bit earlier than SIGCHLD, so that we can still identify to which
-+                 * service an exit message belongs. */
-                 r = sd_event_source_set_priority(m->notify_event_source, -7);
-                 if (r < 0)
-                         return log_error_errno(r, "Failed to set priority of notify event source: %m");
-@@ -699,6 +701,77 @@ static int manager_setup_notify(Manager *m) {
-         return 0;
- }
- 
-+static int manager_setup_cgroups_agent(Manager *m) {
-+
-+        static const union sockaddr_union sa = {
-+                .un.sun_family = AF_UNIX,
-+                .un.sun_path = "/run/systemd/cgroups-agent",
-+        };
-+        int r;
-+
-+        /* This creates a listening socket we receive cgroups agent messages on. We do not use D-Bus for delivering
-+         * these messages from the cgroups agent binary to PID 1, as the cgroups agent binary is very short-living, and
-+         * each instance of it needs a new D-Bus connection. Since D-Bus connections are SOCK_STREAM/AF_UNIX, on
-+         * overloaded systems the backlog of the D-Bus socket becomes relevant, as not more than the configured number
-+         * of D-Bus connections may be queued until the kernel will start dropping further incoming connections,
-+         * possibly resulting in lost cgroups agent messages. To avoid this, we'll use a private SOCK_DGRAM/AF_UNIX
-+         * socket, where no backlog is relevant as communication may take place without an actual connect() cycle, and
-+         * we thus won't lose messages.
-+         *
-+         * Note that PID 1 will forward the agent message to system bus, so that the user systemd instance may listen
-+         * to it. The system instance hence listens on this special socket, but the user instances listen on the system
-+         * bus for these messages. */
-+
-+        if (m->test_run)
-+                return 0;
-+
-+        if (!m->running_as == SYSTEMD_SYSTEM)
-+                return 0;
-+
-+        if (m->cgroups_agent_fd < 0) {
-+                _cleanup_close_ int fd = -1;
-+
-+                /* First free all secondary fields */
-+                m->cgroups_agent_event_source = sd_event_source_unref(m->cgroups_agent_event_source);
-+
-+                fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
-+                if (fd < 0)
-+                        return log_error_errno(errno, "Failed to allocate cgroups agent socket: %m");
-+
-+                fd_inc_rcvbuf(fd, CGROUPS_AGENT_RCVBUF_SIZE);
-+
-+                (void) unlink(sa.un.sun_path);
-+
-+                /* Only allow root to connect to this socket */
-+                RUN_WITH_UMASK(0077)
-+                        r = bind(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path));
-+                if (r < 0)
-+                        return log_error_errno(errno, "bind(%s) failed: %m", sa.un.sun_path);
-+
-+                m->cgroups_agent_fd = fd;
-+                fd = -1;
-+        }
-+
-+        if (!m->cgroups_agent_event_source) {
-+                r = sd_event_add_io(m->event, &m->cgroups_agent_event_source, m->cgroups_agent_fd, EPOLLIN, manager_dispatch_cgroups_agent_fd, m);
-+                if (r < 0)
-+                        return log_error_errno(r, "Failed to allocate cgroups agent event source: %m");
-+
-+                /* Process cgroups notifications early, but after having processed service notification messages or
-+                 * SIGCHLD signals, so that a cgroup running empty is always just the last safety net of notification,
-+                 * and we collected the metadata the notification and SIGCHLD stuff offers first. Also see handling of
-+                 * cgroup inotify for the unified cgroup stuff. */
-+                r = sd_event_source_set_priority(m->cgroups_agent_event_source, SD_EVENT_PRIORITY_NORMAL-5);
-+                if (r < 0)
-+                        return log_error_errno(r, "Failed to set priority of cgroups agent event source: %m");
-+
-+                (void) sd_event_source_set_description(m->cgroups_agent_event_source, "manager-cgroups-agent");
-+        }
-+
-+        return 0;
-+}
-+
-+
- static int manager_setup_kdbus(Manager *m) {
- #ifdef ENABLE_KDBUS
-         _cleanup_free_ char *p = NULL;
-@@ -926,6 +999,7 @@ Manager* manager_free(Manager *m) {
- 
-         sd_event_source_unref(m->signal_event_source);
-         sd_event_source_unref(m->notify_event_source);
-+        sd_event_source_unref(m->cgroups_agent_event_source);
-         sd_event_source_unref(m->time_change_event_source);
-         sd_event_source_unref(m->jobs_in_progress_event_source);
-         sd_event_source_unref(m->idle_pipe_event_source);
-@@ -933,6 +1007,7 @@ Manager* manager_free(Manager *m) {
- 
-         safe_close(m->signal_fd);
-         safe_close(m->notify_fd);
-+        safe_close(m->cgroups_agent_fd);
-         safe_close(m->time_change_fd);
-         safe_close(m->kdbus_fd);
- 
-@@ -1181,6 +1256,10 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) {
-         if (q < 0 && r == 0)
-                 r = q;
- 
-+        q = manager_setup_cgroups_agent(m);
-+        if (q < 0 && r == 0)
-+                r = q;
-+
-         /* We might have deserialized the kdbus control fd, but if we
-          * didn't, then let's create the bus now. */
-         manager_setup_kdbus(m);
-@@ -1502,6 +1581,35 @@ static unsigned manager_dispatch_dbus_queue(Manager *m) {
-         return n;
- }
- 
-+static int manager_dispatch_cgroups_agent_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
-+        Manager *m = userdata;
-+        char buf[PATH_MAX+1];
-+        ssize_t n;
-+
-+        n = recv(fd, buf, sizeof(buf), 0);
-+        if (n < 0)
-+                return log_error_errno(errno, "Failed to read cgroups agent message: %m");
-+        if (n == 0) {
-+                log_error("Got zero-length cgroups agent message, ignoring.");
-+                return 0;
-+        }
-+        if ((size_t) n >= sizeof(buf)) {
-+                log_error("Got overly long cgroups agent message, ignoring.");
-+                return 0;
-+        }
-+
-+        if (memchr(buf, 0, n)) {
-+                log_error("Got cgroups agent message with embedded NUL byte, ignoring.");
-+                return 0;
-+        }
-+        buf[n] = 0;
-+
-+        manager_notify_cgroup_empty(m, buf);
-+        bus_forward_agent_released(m, buf);
-+
-+        return 0;
-+}
-+
- static void manager_invoke_notify_message(Manager *m, Unit *u, pid_t pid, char *buf, size_t n, FDSet *fds) {
-         _cleanup_strv_free_ char **tags = NULL;
- 
-@@ -2314,6 +2422,16 @@ int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool switching_root) {
-                 fprintf(f, "notify-socket=%s\n", m->notify_socket);
-         }
- 
-+        if (m->cgroups_agent_fd >= 0) {
-+                int copy;
-+
-+                copy = fdset_put_dup(fds, m->cgroups_agent_fd);
-+                if (copy < 0)
-+                        return copy;
-+
-+                fprintf(f, "cgroups-agent-fd=%i\n", copy);
-+        }
-+
-         if (m->kdbus_fd >= 0) {
-                 int copy;
- 
-@@ -2483,6 +2601,17 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
-                         free(m->notify_socket);
-                         m->notify_socket = n;
- 
-+                } else if (startswith(l, "cgroups-agent-fd=")) {
-+                        int fd;
-+
-+                        if (safe_atoi(l + 17, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))
-+                                log_debug("Failed to parse cgroups agent fd: %s", l + 10);
-+                        else {
-+                                m->cgroups_agent_event_source = sd_event_source_unref(m->cgroups_agent_event_source);
-+                                safe_close(m->cgroups_agent_fd);
-+                                m->cgroups_agent_fd = fdset_remove(fds, fd);
-+                        }
-+
-                 } else if (startswith(l, "kdbus-fd=")) {
-                         int fd;
- 
-@@ -2609,6 +2738,10 @@ int manager_reload(Manager *m) {
-         if (q < 0 && r >= 0)
-                 r = q;
- 
-+        q = manager_setup_cgroups_agent(m);
-+        if (q < 0 && r >= 0)
-+                r = q;
-+
-         /* Third, fire things up! */
-         q = manager_coldplug(m);
-         if (q < 0 && r >= 0)
-diff --git a/src/core/manager.h b/src/core/manager.h
-index d3971f1..3e855db 100644
---- a/src/core/manager.h
-+++ b/src/core/manager.h
-@@ -137,6 +137,9 @@ struct Manager {
-         int notify_fd;
-         sd_event_source *notify_event_source;
- 
-+        int cgroups_agent_fd;
-+        sd_event_source *cgroups_agent_event_source;
-+
-         int signal_fd;
-         sd_event_source *signal_event_source;
- 
diff --git a/SOURCES/0279-journalctl-improve-error-messages-when-the-specified.patch b/SOURCES/0279-journalctl-improve-error-messages-when-the-specified.patch
new file mode 100644
index 0000000..d79bc02
--- /dev/null
+++ b/SOURCES/0279-journalctl-improve-error-messages-when-the-specified.patch
@@ -0,0 +1,31 @@
+From 046d996001c0b3fe34d34683e55f62481a5af932 Mon Sep 17 00:00:00 2001
+From: Jan Synacek <jsynacek@redhat.com>
+Date: Mon, 1 Feb 2016 09:29:02 +0100
+Subject: [PATCH] journalctl: improve error messages when the specified boot is
+ not found
+
+Cherry-picked from: c34e939909710bf124e7741c3648592a30418ffd
+Resolves: #1082179
+---
+ src/journal/journalctl.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
+index 7058788..964f849 100644
+--- a/src/journal/journalctl.c
++++ b/src/journal/journalctl.c
+@@ -1090,10 +1090,11 @@ static int add_boot(sd_journal *j) {
+                 const char *reason = (r == 0) ? "No such boot ID in journal" : strerror(-r);
+ 
+                 if (sd_id128_is_null(arg_boot_id))
+-                        log_error("Failed to look up boot %+i: %s", arg_boot_offset, reason);
++                        log_error("Data from the specified boot (%+i) is not available: %s",
++                                  arg_boot_offset, reason);
+                 else
+-                        log_error("Failed to look up boot ID "SD_ID128_FORMAT_STR"%+i: %s",
+-                                  SD_ID128_FORMAT_VAL(arg_boot_id), arg_boot_offset, reason);
++                        log_error("Data from the specified boot ("SD_ID128_FORMAT_STR") is not available: %s",
++                                  SD_ID128_FORMAT_VAL(arg_boot_id), reason);
+ 
+                 return r == 0 ? -ENODATA : r;
+         }
diff --git a/SOURCES/0280-journalctl-show-friendly-info-when-using-b-on-runtim.patch b/SOURCES/0280-journalctl-show-friendly-info-when-using-b-on-runtim.patch
new file mode 100644
index 0000000..1938244
--- /dev/null
+++ b/SOURCES/0280-journalctl-show-friendly-info-when-using-b-on-runtim.patch
@@ -0,0 +1,33 @@
+From a932c70a76846aa7dbb4b783291b44bfc8cbd76c Mon Sep 17 00:00:00 2001
+From: Jan Synacek <jsynacek@redhat.com>
+Date: Mon, 1 Feb 2016 09:25:22 +0100
+Subject: [PATCH] journalctl: show friendly info when using -b on runtime
+ journal only
+
+Make it clear that specifing boot when there is actually only one has no
+effect. This cosmetic patch improves user experience a bit.
+
+Cherry-picked from: 0f1a9a830c87d8accdc3a44d0a93ad343e52a7bd
+Resolves: #1082179
+---
+ src/journal/journalctl.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
+index 964f849..836d7d2 100644
+--- a/src/journal/journalctl.c
++++ b/src/journal/journalctl.c
+@@ -1905,6 +1905,13 @@ int main(int argc, char *argv[]) {
+                 goto finish;
+         }
+ 
++        if (arg_boot_offset != 0 &&
++            sd_journal_has_runtime_files(j) > 0 &&
++            sd_journal_has_persistent_files(j) == 0) {
++                log_info("Specifying boot ID has no effect, no persistent journal was found");
++                r = 0;
++                goto finish;
++        }
+         /* add_boot() must be called first!
+          * It may need to seek the journal to find parent boot IDs. */
+         r = add_boot(j);
diff --git a/SOURCES/0280-logind-process-session-inhibitor-fds-at-higher-prior.patch b/SOURCES/0280-logind-process-session-inhibitor-fds-at-higher-prior.patch
deleted file mode 100644
index a396534..0000000
--- a/SOURCES/0280-logind-process-session-inhibitor-fds-at-higher-prior.patch
+++ /dev/null
@@ -1,59 +0,0 @@
-From 5eeac990b887d7cbe8a4b234918f19f64a57079a Mon Sep 17 00:00:00 2001
-From: Lennart Poettering <lennart@poettering.net>
-Date: Wed, 4 May 2016 19:01:56 +0200
-Subject: [PATCH] logind: process session/inhibitor fds at higher priority
-
-Let's make sure we process session and inhibitor pipe fds (that signal
-sessions/inhibtors going away) at a higher priority
-than new bus calls that might create new sessions or inhibitors. This helps
-ensuring that the number of open sessions stays minimal.
-
-Cherry-picked from: e11544a8305ab9dea097c74bb16e296150c9cc10
-Resolves: #1305608
----
- src/login/logind-inhibit.c | 2 +-
- src/login/logind-session.c | 4 +++-
- src/login/logind.c         | 2 +-
- 3 files changed, 5 insertions(+), 3 deletions(-)
-
-diff --git a/src/login/logind-inhibit.c b/src/login/logind-inhibit.c
-index 84fee0e..bf96898 100644
---- a/src/login/logind-inhibit.c
-+++ b/src/login/logind-inhibit.c
-@@ -303,7 +303,7 @@ int inhibitor_create_fifo(Inhibitor *i) {
-                 if (r < 0)
-                         return r;
- 
--                r = sd_event_source_set_priority(i->event_source, SD_EVENT_PRIORITY_IDLE);
-+                r = sd_event_source_set_priority(i->event_source, SD_EVENT_PRIORITY_IDLE-10);
-                 if (r < 0)
-                         return r;
-         }
-diff --git a/src/login/logind-session.c b/src/login/logind-session.c
-index d2e7b40..f39eb78 100644
---- a/src/login/logind-session.c
-+++ b/src/login/logind-session.c
-@@ -888,7 +888,9 @@ int session_create_fifo(Session *s) {
-                 if (r < 0)
-                         return r;
- 
--                r = sd_event_source_set_priority(s->fifo_event_source, SD_EVENT_PRIORITY_IDLE);
-+                /* Let's make sure we noticed dead sessions before we process new bus requests (which might create new
-+                 * sessions). */
-+                r = sd_event_source_set_priority(s->fifo_event_source, SD_EVENT_PRIORITY_NORMAL-10);
-                 if (r < 0)
-                         return r;
-         }
-diff --git a/src/login/logind.c b/src/login/logind.c
-index 3afbf34..e8d0669 100644
---- a/src/login/logind.c
-+++ b/src/login/logind.c
-@@ -685,7 +685,7 @@ static int manager_connect_bus(Manager *m) {
-         if (r < 0)
-                 return log_error_errno(r, "Failed to register name: %m");
- 
--        r = sd_bus_attach_event(m->bus, m->event, 0);
-+        r = sd_bus_attach_event(m->bus, m->event, SD_EVENT_PRIORITY_NORMAL);
-         if (r < 0)
-                 return log_error_errno(r, "Failed to attach bus to event loop: %m");
- 
diff --git a/SOURCES/0281-journalctl-make-journalctl-dev-sda-work.patch b/SOURCES/0281-journalctl-make-journalctl-dev-sda-work.patch
new file mode 100644
index 0000000..5ce2fbb
--- /dev/null
+++ b/SOURCES/0281-journalctl-make-journalctl-dev-sda-work.patch
@@ -0,0 +1,206 @@
+From 1c33de9e1370bc56e10f3b5306e27c8aa6a18873 Mon Sep 17 00:00:00 2001
+From: Michal Sekletar <msekleta@redhat.com>
+Date: Mon, 1 Feb 2016 10:44:58 +0100
+Subject: [PATCH] journalctl: make "journalctl /dev/sda" work
+
+Currently when journalctl is called with path to block device node we
+add following match _KERNEL_DEVICE=b$MAJOR:$MINOR.
+
+That is not sufficient to actually obtain logs about the disk because
+dev_printk() kernel helper puts to /dev/kmsg information about the
+device in following format, +$SUBSYSTEM:$ADDRESS,
+e.g. "+pci:pci:0000:00:14.0".
+
+Now we will walk upward the syspath and add match for every device in
+format produced by dev_printk() as well as match for its device node if
+it exists.
+
+Cherry-picked from: 795ab08f783e78e85f1493879f13ac44cb113b00
+Resolves: #947636
+---
+ Makefile.am              |   3 +-
+ src/journal/journalctl.c | 118 ++++++++++++++++++++++++++++++++++++++---------
+ 2 files changed, 97 insertions(+), 24 deletions(-)
+
+diff --git a/Makefile.am b/Makefile.am
+index 2645f66..2559376 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -4245,7 +4245,8 @@ journalctl_LDADD = \
+ 	libsystemd-journal-internal.la \
+ 	libsystemd-internal.la \
+ 	libsystemd-logs.la \
+-	libsystemd-shared.la
++	libsystemd-shared.la \
++	libudev-core.la
+ 
+ if HAVE_ACL
+ journalctl_LDADD += \
+diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
+index 836d7d2..3db1cd2 100644
+--- a/src/journal/journalctl.c
++++ b/src/journal/journalctl.c
+@@ -63,6 +63,8 @@
+ #include "mkdir.h"
+ #include "bus-util.h"
+ #include "bus-error.h"
++#include "udev.h"
++#include "udev-util.h"
+ 
+ #define DEFAULT_FSS_INTERVAL_USEC (15*USEC_PER_MINUTE)
+ 
+@@ -134,6 +136,80 @@ typedef struct boot_id_t {
+         LIST_FIELDS(struct boot_id_t, boot_list);
+ } boot_id_t;
+ 
++static int add_matches_for_device(sd_journal *j, const char *devpath) {
++        int r;
++        _cleanup_udev_unref_ struct udev *udev = NULL;
++        _cleanup_udev_device_unref_ struct udev_device *device = NULL;
++        struct udev_device *d = NULL;
++        struct stat st;
++
++        assert(j);
++        assert(devpath);
++
++        if (!path_startswith(devpath, "/dev/")) {
++                log_error("Devpath does not start with /dev/");
++                return -EINVAL;
++        }
++
++        udev = udev_new();
++        if (!udev)
++                return log_oom();
++
++        r = stat(devpath, &st);
++        if (r < 0)
++                log_error_errno(errno, "Couldn't stat file: %m");
++
++        d = device = udev_device_new_from_devnum(udev, S_ISBLK(st.st_mode) ? 'b' : 'c', st.st_rdev);
++        if (!device)
++                return log_error_errno(errno, "Failed to get udev device from devnum %u:%u: %m", major(st.st_rdev), minor(st.st_rdev));
++
++        while (d) {
++                _cleanup_free_ char *match = NULL;
++                const char *subsys, *sysname, *devnode;
++
++                subsys = udev_device_get_subsystem(d);
++                if (!subsys) {
++                        d = udev_device_get_parent(d);
++                        continue;
++                }
++
++                sysname = udev_device_get_sysname(d);
++                if (!sysname) {
++                        d = udev_device_get_parent(d);
++                        continue;
++                }
++
++                match = strjoin("_KERNEL_DEVICE=+", subsys, ":", sysname, NULL);
++                if (!match)
++                        return log_oom();
++
++                r = sd_journal_add_match(j, match, 0);
++                if (r < 0)
++                        return log_error_errno(r, "Failed to add match: %m");
++
++                devnode = udev_device_get_devnode(d);
++                if (devnode) {
++                        _cleanup_free_ char *match1 = NULL;
++
++                        r = stat(devnode, &st);
++                        if (r < 0)
++                                return log_error_errno(r, "Failed to stat() device node \"%s\": %m", devnode);
++
++                        r = asprintf(&match1, "_KERNEL_DEVICE=%c%u:%u", S_ISBLK(st.st_mode) ? 'b' : 'c', major(st.st_rdev), minor(st.st_rdev));
++                        if (r < 0)
++                                return log_oom();
++
++                        r = sd_journal_add_match(j, match1, 0);
++                        if (r < 0)
++                                return log_error_errno(r, "Failed to add match: %m");
++                }
++
++                d = udev_device_get_parent(d);
++        }
++
++        return 0;
++}
++
+ static void pager_open_if_enabled(void) {
+ 
+         if (arg_no_pager)
+@@ -788,13 +864,12 @@ static int add_matches(sd_journal *j, char **args) {
+                         have_term = false;
+ 
+                 } else if (path_is_absolute(*i)) {
+-                        _cleanup_free_ char *p, *t = NULL, *t2 = NULL;
++                        _cleanup_free_ char *p, *t = NULL, *t2 = NULL, *interpreter = NULL;
+                         const char *path;
+-                        _cleanup_free_ char *interpreter = NULL;
+                         struct stat st;
+ 
+                         p = canonicalize_file_name(*i);
+-                        path = p ? p : *i;
++                        path = p ?: *i;
+ 
+                         if (stat(path, &st) < 0)
+                                 return log_error_errno(errno, "Couldn't stat file: %m");
+@@ -808,40 +883,37 @@ static int add_matches(sd_journal *j, char **args) {
+                                                 return log_oom();
+ 
+                                         t = strappend("_COMM=", comm);
++                                        if (!t)
++                                                return log_oom();
+ 
+                                         /* Append _EXE only if the interpreter is not a link.
+                                            Otherwise, it might be outdated often. */
+-                                        if (lstat(interpreter, &st) == 0 &&
+-                                            !S_ISLNK(st.st_mode)) {
++                                        if (lstat(interpreter, &st) == 0 && !S_ISLNK(st.st_mode)) {
+                                                 t2 = strappend("_EXE=", interpreter);
+                                                 if (!t2)
+                                                         return log_oom();
+                                         }
+-                                } else
++                                } else {
+                                         t = strappend("_EXE=", path);
+-                        } else if (S_ISCHR(st.st_mode)) {
+-                                if (asprintf(&t, "_KERNEL_DEVICE=c%u:%u",
+-                                             major(st.st_rdev),
+-                                             minor(st.st_rdev)) < 0)
+-                                        return -ENOMEM;
+-                        } else if (S_ISBLK(st.st_mode)) {
+-                                if (asprintf(&t, "_KERNEL_DEVICE=b%u:%u",
+-                                             major(st.st_rdev),
+-                                             minor(st.st_rdev)) < 0)
+-                                        return -ENOMEM;
++                                        if (!t)
++                                                return log_oom();
++                                }
++
++                                r = sd_journal_add_match(j, t, 0);
++
++                                if (r >=0 && t2)
++                                        r = sd_journal_add_match(j, t2, 0);
++
++                        } else if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) {
++                                r = add_matches_for_device(j, path);
++                                if (r < 0)
++                                        return r;
+                         } else {
+                                 log_error("File is neither a device node, nor regular file, nor executable: %s", *i);
+                                 return -EINVAL;
+                         }
+ 
+-                        if (!t)
+-                                return log_oom();
+-
+-                        r = sd_journal_add_match(j, t, 0);
+-                        if (t2)
+-                                r = sd_journal_add_match(j, t2, 0);
+                         have_term = true;
+-
+                 } else {
+                         r = sd_journal_add_match(j, *i, 0);
+                         have_term = true;
diff --git a/SOURCES/0281-sd-event-expose-the-event-loop-iteration-counter-via.patch b/SOURCES/0281-sd-event-expose-the-event-loop-iteration-counter-via.patch
deleted file mode 100644
index 98ff349..0000000
--- a/SOURCES/0281-sd-event-expose-the-event-loop-iteration-counter-via.patch
+++ /dev/null
@@ -1,69 +0,0 @@
-From 782a6f41f36317fe837f8c85d2fc7b9b5de98200 Mon Sep 17 00:00:00 2001
-From: Lennart Poettering <lennart@poettering.net>
-Date: Wed, 29 Jun 2016 19:03:26 -0700
-Subject: [PATCH] sd-event: expose the event loop iteration counter via
- sd_event_get_iteration()
-
-This extends the existing event loop iteration counter to 64bit, and exposes it
-via a new function sd_event_get_iteration(). This is helpful for cases like
-issue #3612. After all, since we maintain the counter anyway, we might as well
-expose it.
-
-(This also fixes an unrelated issue in the man page for sd_event_wait() where
-micro and milliseconds got mixed up)
-
-Cherry-picked from: 7486322b99da5b4d2d00d35b310b035f936f7964
-Related: #1342173
----
- src/libsystemd/sd-event/sd-event.c | 14 +++++++++++---
- src/systemd/sd-event.h             |  1 +
- 2 files changed, 12 insertions(+), 3 deletions(-)
-
-diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c
-index 1f1e6fe..9d48e5a 100644
---- a/src/libsystemd/sd-event/sd-event.c
-+++ b/src/libsystemd/sd-event/sd-event.c
-@@ -76,8 +76,8 @@ struct sd_event_source {
-         int64_t priority;
-         unsigned pending_index;
-         unsigned prepare_index;
--        unsigned pending_iteration;
--        unsigned prepare_iteration;
-+        uint64_t pending_iteration;
-+        uint64_t prepare_iteration;
- 
-         LIST_FIELDS(sd_event_source, sources);
- 
-@@ -169,7 +169,7 @@ struct sd_event {
- 
-         pid_t original_pid;
- 
--        unsigned iteration;
-+        uint64_t iteration;
-         dual_timestamp timestamp;
-         usec_t timestamp_boottime;
-         int state;
-@@ -2689,3 +2689,11 @@ _public_ int sd_event_get_watchdog(sd_event *e) {
- 
-         return e->watchdog;
- }
-+
-+_public_ int sd_event_get_iteration(sd_event *e, uint64_t *ret) {
-+        assert_return(e, -EINVAL);
-+        assert_return(!event_pid_changed(e), -ECHILD);
-+
-+        *ret = e->iteration;
-+        return 0;
-+}
-diff --git a/src/systemd/sd-event.h b/src/systemd/sd-event.h
-index 25a10f9..4957f3a 100644
---- a/src/systemd/sd-event.h
-+++ b/src/systemd/sd-event.h
-@@ -101,6 +101,7 @@ int sd_event_get_tid(sd_event *e, pid_t *tid);
- int sd_event_get_exit_code(sd_event *e, int *code);
- int sd_event_set_watchdog(sd_event *e, int b);
- int sd_event_get_watchdog(sd_event *e);
-+int sd_event_get_iteration(sd_event *e, uint64_t *ret);
- 
- sd_event_source* sd_event_source_ref(sd_event_source *s);
- sd_event_source* sd_event_source_unref(sd_event_source *s);
diff --git a/SOURCES/0282-journalctl-add-match-for-the-current-boot-when-calle.patch b/SOURCES/0282-journalctl-add-match-for-the-current-boot-when-calle.patch
new file mode 100644
index 0000000..60736b2
--- /dev/null
+++ b/SOURCES/0282-journalctl-add-match-for-the-current-boot-when-calle.patch
@@ -0,0 +1,27 @@
+From fb7acf90df3d675261b18f8e7c2de315dadee756 Mon Sep 17 00:00:00 2001
+From: Michal Sekletar <msekleta@redhat.com>
+Date: Wed, 3 Feb 2016 11:22:52 +0100
+Subject: [PATCH] journalctl: add match for the current boot when called with
+ devpath
+
+Cherry-picked from: 485fd9a7b9d59b9f2302a873f7ee5ccac256dd93
+Related: #947636
+---
+ src/journal/journalctl.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
+index 3db1cd2..6948ed6 100644
+--- a/src/journal/journalctl.c
++++ b/src/journal/journalctl.c
+@@ -207,6 +207,10 @@ static int add_matches_for_device(sd_journal *j, const char *devpath) {
+                 d = udev_device_get_parent(d);
+         }
+ 
++        r = add_match_this_boot(j, arg_machine);
++        if (r < 0)
++                return log_error_errno(r, "Failed to add match for the current boot: %m");
++
+         return 0;
+ }
+ 
diff --git a/SOURCES/0282-manager-Only-invoke-a-single-sigchld-per-unit-within.patch b/SOURCES/0282-manager-Only-invoke-a-single-sigchld-per-unit-within.patch
deleted file mode 100644
index ba20e3a..0000000
--- a/SOURCES/0282-manager-Only-invoke-a-single-sigchld-per-unit-within.patch
+++ /dev/null
@@ -1,85 +0,0 @@
-From f84b01e4d13d155bd0a8a429c5d18e855414de4b Mon Sep 17 00:00:00 2001
-From: Kyle Walker <walker.kyle.t@gmail.com>
-Date: Thu, 30 Jun 2016 15:12:18 -0400
-Subject: [PATCH] manager: Only invoke a single sigchld per unit within a
- cleanup cycle
-
-By default, each iteration of manager_dispatch_sigchld() results in a unit level
-sigchld event being invoked. For scope units, this results in a scope_sigchld_event()
-which can seemingly stall for workloads that have a large number of PIDs within the
-scope. The stall exhibits itself as a SIG_0 being initiated for each u->pids entry
-as a result of pid_is_unwaited().
-
-v2:
-This patch resolves this condition by only paying to cost of a sigchld in the underlying
-scope unit once per sigchld iteration. A new "sigchldgen" member resides within the
-Unit struct. The Manager is incremented via the sd event loop, accessed via
-sd_event_get_iteration, and the Unit member is set to the same value as the manager each
-time that a sigchld event is invoked. If the Manager iteration value and Unit member
-match, the sigchld event is not invoked for that iteration.
-
-Cherry-picked from: 36f20ae3b2975e44b6ef17e453ae06a289e9a122
-Resolves: #1342173
----
- src/core/manager.c | 13 ++++++++++++-
- src/core/unit.c    |  1 +
- src/core/unit.h    |  3 +++
- 3 files changed, 16 insertions(+), 1 deletion(-)
-
-diff --git a/src/core/manager.c b/src/core/manager.c
-index b6d76ca..f2f5c6a 100644
---- a/src/core/manager.c
-+++ b/src/core/manager.c
-@@ -1743,14 +1743,25 @@ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t
- }
- 
- static void invoke_sigchld_event(Manager *m, Unit *u, siginfo_t *si) {
-+        uint64_t iteration;
-+        
-         assert(m);
-         assert(u);
-         assert(si);
- 
-+        sd_event_get_iteration(m->event, &iteration);
-+
-         log_unit_debug(u->id, "Child "PID_FMT" belongs to %s", si->si_pid, u->id);
- 
-         unit_unwatch_pid(u, si->si_pid);
--        UNIT_VTABLE(u)->sigchld_event(u, si->si_pid, si->si_code, si->si_status);
-+
-+        if (UNIT_VTABLE(u)->sigchld_event) {
-+                if (set_size(u->pids) <= 1 || iteration != u->sigchldgen) {
-+                        UNIT_VTABLE(u)->sigchld_event(u, si->si_pid, si->si_code, si->si_status);
-+                        u->sigchldgen = iteration;
-+                } else
-+                        log_debug("%s already issued a sigchld this iteration %llu, skipping. Pids still being watched %d", u->id, iteration, set_size(u->pids));
-+        }
- }
- 
- static int manager_dispatch_sigchld(Manager *m) {
-diff --git a/src/core/unit.c b/src/core/unit.c
-index 4fb2fd3..5b2becc 100644
---- a/src/core/unit.c
-+++ b/src/core/unit.c
-@@ -94,6 +94,7 @@ Unit *unit_new(Manager *m, size_t size) {
-         u->unit_file_state = _UNIT_FILE_STATE_INVALID;
-         u->unit_file_preset = -1;
-         u->on_failure_job_mode = JOB_REPLACE;
-+        u->sigchldgen = 0;
- 
-         return u;
- }
-diff --git a/src/core/unit.h b/src/core/unit.h
-index 0eebc0b..d936457 100644
---- a/src/core/unit.h
-+++ b/src/core/unit.h
-@@ -167,6 +167,9 @@ struct Unit {
-          * process SIGCHLD for */
-         Set *pids;
- 
-+        /* Used in sigchld event invocation to avoid repeat events being invoked */
-+        uint64_t sigchldgen;
-+
-         /* Used during GC sweeps */
-         unsigned gc_marker;
- 
diff --git a/SOURCES/0283-man-clarify-what-happens-when-journalctl-is-called-w.patch b/SOURCES/0283-man-clarify-what-happens-when-journalctl-is-called-w.patch
new file mode 100644
index 0000000..7678f12
--- /dev/null
+++ b/SOURCES/0283-man-clarify-what-happens-when-journalctl-is-called-w.patch
@@ -0,0 +1,33 @@
+From a4f12d4849daed23651ab3c23b5ff830aa32b2a0 Mon Sep 17 00:00:00 2001
+From: Michal Sekletar <msekleta@redhat.com>
+Date: Wed, 3 Feb 2016 10:38:29 +0100
+Subject: [PATCH] man: clarify what happens when journalctl is called with
+ devpath
+
+Cherry-picked from: 3cea8e06e45fc1757de8f74da29fb5fb181db4eb
+Related: #947636
+---
+ man/journalctl.xml | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/man/journalctl.xml b/man/journalctl.xml
+index 2764f66..0981fba 100644
+--- a/man/journalctl.xml
++++ b/man/journalctl.xml
+@@ -91,8 +91,14 @@
+       paths may be specified. If a file path refers to an executable
+       file, this is equivalent to an <literal>_EXE=</literal> match
+       for the canonicalized binary path. Similarly, if a path refers
+-      to a device node, this is equivalent to a
+-      <literal>_KERNEL_DEVICE=</literal> match for the device.</para>
++      to a device node then match is added for the kernel name of the
++      device (<literal>_KERNEL_DEVICE=</literal>). Also, matches for the
++      kernel names of all the parent devices are added automatically.
++      Device node paths are not stable across reboots, therefore match
++      for the current boot id (<literal>_BOOT_ID=</literal>) is
++      always added as well. Note that only the log entries for
++      the existing device nodes maybe queried by providing path to
++      the device node.</para>
+ 
+       <para>Additional constraints may be added using options
+       <option>--boot</option>, <option>--unit=</option>, etc, to
diff --git a/SOURCES/0283-manager-Fixing-a-debug-printf-formatting-mistake.patch b/SOURCES/0283-manager-Fixing-a-debug-printf-formatting-mistake.patch
deleted file mode 100644
index 007e1ab..0000000
--- a/SOURCES/0283-manager-Fixing-a-debug-printf-formatting-mistake.patch
+++ /dev/null
@@ -1,28 +0,0 @@
-From 69ecc270c614acdb5469551ac3dbe41bd43c44ae Mon Sep 17 00:00:00 2001
-From: Kyle Walker <walker.kyle.t@gmail.com>
-Date: Fri, 1 Jul 2016 10:04:40 -0400
-Subject: [PATCH] manager: Fixing a debug printf formatting mistake
-
-A 'llu' formatting statement was used in a debugging printf statement
-instead of a 'PRIu64'. Correcting that mistake here.
-
-Cherry-picked from: 72b0c3f59695239c51b719576f625e789bd00a66
-Related: #1342173
----
- src/core/manager.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
-diff --git a/src/core/manager.c b/src/core/manager.c
-index f2f5c6a..b63d929 100644
---- a/src/core/manager.c
-+++ b/src/core/manager.c
-@@ -1760,7 +1760,8 @@ static void invoke_sigchld_event(Manager *m, Unit *u, siginfo_t *si) {
-                         UNIT_VTABLE(u)->sigchld_event(u, si->si_pid, si->si_code, si->si_status);
-                         u->sigchldgen = iteration;
-                 } else
--                        log_debug("%s already issued a sigchld this iteration %llu, skipping. Pids still being watched %d", u->id, iteration, set_size(u->pids));
-+                        log_debug("%s already issued a sigchld this iteration %" PRIu64 ", skipping. Pids still being watched %d", u->id, iteration, set_size(u->pids));
-+
-         }
- }
- 
diff --git a/SOURCES/0284-core-downgrade-warning-about-duplicate-device-names.patch b/SOURCES/0284-core-downgrade-warning-about-duplicate-device-names.patch
new file mode 100644
index 0000000..70a46a9
--- /dev/null
+++ b/SOURCES/0284-core-downgrade-warning-about-duplicate-device-names.patch
@@ -0,0 +1,26 @@
+From ad2cedec3cf3e6ddefd70d9f3dece3ca837676cf Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Thu, 23 Apr 2015 13:50:01 +0200
+Subject: [PATCH] core: downgrade warning about duplicate device names
+
+http://lists.freedesktop.org/archives/systemd-devel/2015-April/031094.html
+
+Cherry-picked from: 5259bcf6a638d8d489db1ddefd55327aa15f3e51
+Resolves: #1296249
+---
+ src/core/device.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/core/device.c b/src/core/device.c
+index 8a6855d..1995e3c 100644
+--- a/src/core/device.c
++++ b/src/core/device.c
+@@ -317,7 +317,7 @@ static int device_setup_unit(Manager *m, struct udev_device *dev, const char *pa
+         if (u &&
+             DEVICE(u)->sysfs &&
+             !path_equal(DEVICE(u)->sysfs, sysfs)) {
+-                log_unit_error(u->id, "Device %s appeared twice with different sysfs paths %s and %s", e, DEVICE(u)->sysfs, sysfs);
++                log_unit_debug(u->id, "Device %s appeared twice with different sysfs paths %s and %s", e, DEVICE(u)->sysfs, sysfs);
+                 return -EEXIST;
+         }
+ 
diff --git a/SOURCES/0284-manager-don-t-skip-sigchld-handler-for-main-and-cont.patch b/SOURCES/0284-manager-don-t-skip-sigchld-handler-for-main-and-cont.patch
deleted file mode 100644
index d4bc7c1..0000000
--- a/SOURCES/0284-manager-don-t-skip-sigchld-handler-for-main-and-cont.patch
+++ /dev/null
@@ -1,248 +0,0 @@
-From 35bf3bd6a276fa58fa6ed5a258a7fbc4ba8bce05 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Nykr=C3=BDn?= <lnykryn@redhat.com>
-Date: Sat, 16 Jul 2016 21:04:13 +0200
-Subject: [PATCH] manager: don't skip sigchld handler for main and control pid
- for services (#3738)
-
-During stop when service has one "regular" pid one main pid and one
-control pid and the sighld for the regular one is processed first the
-unit_tidy_watch_pids will skip the main and control pid and does not
-remove them from u->pids(). But then we skip the sigchld event because we
-already did one in the iteration and there are two pids in u->pids.
-
-v2: Use general unit_main_pid() and unit_control_pid() instead of
-reaching directly to service structure.
-Cherry-picked from: ccc2c98e1b0c06861577632440b996ca16cefd53
-Resolves: #1342173
----
- src/core/busname.c | 10 ++++++++++
- src/core/manager.c |  5 ++++-
- src/core/mount.c   | 10 ++++++++++
- src/core/service.c | 19 +++++++++++++++++++
- src/core/socket.c  | 10 ++++++++++
- src/core/swap.c    | 10 ++++++++++
- src/core/unit.c    | 18 ++++++++++++++++++
- src/core/unit.h    |  9 +++++++++
- 8 files changed, 90 insertions(+), 1 deletion(-)
-
-diff --git a/src/core/busname.c b/src/core/busname.c
-index 43d7607..f626ba9 100644
---- a/src/core/busname.c
-+++ b/src/core/busname.c
-@@ -997,6 +997,14 @@ static const char* const busname_state_table[_BUSNAME_STATE_MAX] = {
- 
- DEFINE_STRING_TABLE_LOOKUP(busname_state, BusNameState);
- 
-+static int busname_control_pid(Unit *u) {
-+        BusName *n = BUSNAME(u);
-+
-+        assert(n);
-+
-+        return n->control_pid;
-+}
-+
- static const char* const busname_result_table[_BUSNAME_RESULT_MAX] = {
-         [BUSNAME_SUCCESS] = "success",
-         [BUSNAME_FAILURE_RESOURCES] = "resources",
-@@ -1047,6 +1055,8 @@ const UnitVTable busname_vtable = {
- 
-         .supported = busname_supported,
- 
-+        .control_pid = busname_control_pid,
-+
-         .bus_interface = "org.freedesktop.systemd1.BusName",
-         .bus_vtable = bus_busname_vtable,
- 
-diff --git a/src/core/manager.c b/src/core/manager.c
-index b63d929..87b5e57 100644
---- a/src/core/manager.c
-+++ b/src/core/manager.c
-@@ -1756,7 +1756,10 @@ static void invoke_sigchld_event(Manager *m, Unit *u, siginfo_t *si) {
-         unit_unwatch_pid(u, si->si_pid);
- 
-         if (UNIT_VTABLE(u)->sigchld_event) {
--                if (set_size(u->pids) <= 1 || iteration != u->sigchldgen) {
-+                if (set_size(u->pids) <= 1 ||
-+                    iteration != u->sigchldgen ||
-+                    unit_main_pid(u) == si->si_pid ||
-+                    unit_control_pid(u) == si->si_pid) {
-                         UNIT_VTABLE(u)->sigchld_event(u, si->si_pid, si->si_code, si->si_status);
-                         u->sigchldgen = iteration;
-                 } else
-diff --git a/src/core/mount.c b/src/core/mount.c
-index 23f63ce..4dc9f2e 100644
---- a/src/core/mount.c
-+++ b/src/core/mount.c
-@@ -1883,6 +1883,14 @@ static const char* const mount_state_table[_MOUNT_STATE_MAX] = {
- 
- DEFINE_STRING_TABLE_LOOKUP(mount_state, MountState);
- 
-+static int mount_control_pid(Unit *u) {
-+        Mount *m = MOUNT(u);
-+
-+        assert(m);
-+
-+        return m->control_pid;
-+}
-+
- static const char* const mount_exec_command_table[_MOUNT_EXEC_COMMAND_MAX] = {
-         [MOUNT_EXEC_MOUNT] = "ExecMount",
-         [MOUNT_EXEC_UNMOUNT] = "ExecUnmount",
-@@ -1944,6 +1952,8 @@ const UnitVTable mount_vtable = {
- 
-         .reset_failed = mount_reset_failed,
- 
-+        .control_pid = mount_control_pid,
-+
-         .bus_interface = "org.freedesktop.systemd1.Mount",
-         .bus_vtable = bus_mount_vtable,
-         .bus_set_property = bus_mount_set_property,
-diff --git a/src/core/service.c b/src/core/service.c
-index ae5e610..f102ef3 100644
---- a/src/core/service.c
-+++ b/src/core/service.c
-@@ -3028,6 +3028,22 @@ static const char* const service_state_table[_SERVICE_STATE_MAX] = {
- 
- DEFINE_STRING_TABLE_LOOKUP(service_state, ServiceState);
- 
-+static int service_main_pid(Unit *u) {
-+        Service *s = SERVICE(u);
-+
-+        assert(s);
-+
-+        return s->main_pid;
-+}
-+
-+static int service_control_pid(Unit *u) {
-+        Service *s = SERVICE(u);
-+
-+        assert(s);
-+
-+        return s->control_pid;
-+}
-+
- static const char* const service_restart_table[_SERVICE_RESTART_MAX] = {
-         [SERVICE_RESTART_NO] = "no",
-         [SERVICE_RESTART_ON_SUCCESS] = "on-success",
-@@ -3138,6 +3154,9 @@ const UnitVTable service_vtable = {
-         .notify_cgroup_empty = service_notify_cgroup_empty_event,
-         .notify_message = service_notify_message,
- 
-+        .main_pid = service_main_pid,
-+        .control_pid = service_control_pid,
-+
-         .bus_name_owner_change = service_bus_name_owner_change,
- 
-         .bus_interface = "org.freedesktop.systemd1.Service",
-diff --git a/src/core/socket.c b/src/core/socket.c
-index bc677a2..771af0d 100644
---- a/src/core/socket.c
-+++ b/src/core/socket.c
-@@ -2648,6 +2648,14 @@ static const char* const socket_state_table[_SOCKET_STATE_MAX] = {
- 
- DEFINE_STRING_TABLE_LOOKUP(socket_state, SocketState);
- 
-+static int socket_control_pid(Unit *u) {
-+        Socket *s = SOCKET(u);
-+
-+        assert(s);
-+
-+        return s->control_pid;
-+}
-+
- static const char* const socket_exec_command_table[_SOCKET_EXEC_COMMAND_MAX] = {
-         [SOCKET_EXEC_START_PRE] = "StartPre",
-         [SOCKET_EXEC_START_CHOWN] = "StartChown",
-@@ -2713,6 +2721,8 @@ const UnitVTable socket_vtable = {
- 
-         .reset_failed = socket_reset_failed,
- 
-+        .control_pid = socket_control_pid,
-+
-         .bus_interface = "org.freedesktop.systemd1.Socket",
-         .bus_vtable = bus_socket_vtable,
-         .bus_set_property = bus_socket_set_property,
-diff --git a/src/core/swap.c b/src/core/swap.c
-index 34a2c40..42f9959 100644
---- a/src/core/swap.c
-+++ b/src/core/swap.c
-@@ -1426,6 +1426,14 @@ static const char* const swap_state_table[_SWAP_STATE_MAX] = {
- 
- DEFINE_STRING_TABLE_LOOKUP(swap_state, SwapState);
- 
-+static int swap_control_pid(Unit *u) {
-+        Swap *s = SWAP(u);
-+
-+        assert(s);
-+
-+        return s->control_pid;
-+}
-+
- static const char* const swap_exec_command_table[_SWAP_EXEC_COMMAND_MAX] = {
-         [SWAP_EXEC_ACTIVATE] = "ExecActivate",
-         [SWAP_EXEC_DEACTIVATE] = "ExecDeactivate",
-@@ -1487,6 +1495,8 @@ const UnitVTable swap_vtable = {
- 
-         .reset_failed = swap_reset_failed,
- 
-+        .control_pid = swap_control_pid,
-+
-         .bus_interface = "org.freedesktop.systemd1.Swap",
-         .bus_vtable = bus_swap_vtable,
-         .bus_set_property = bus_swap_set_property,
-diff --git a/src/core/unit.c b/src/core/unit.c
-index 5b2becc..f03f185 100644
---- a/src/core/unit.c
-+++ b/src/core/unit.c
-@@ -3667,6 +3667,24 @@ int unit_setup_exec_runtime(Unit *u) {
-         return exec_runtime_make(rt, unit_get_exec_context(u), u->id);
- }
- 
-+pid_t unit_control_pid(Unit *u) {
-+        assert(u);
-+
-+        if (UNIT_VTABLE(u)->control_pid)
-+                return UNIT_VTABLE(u)->control_pid(u);
-+
-+        return 0;
-+}
-+
-+pid_t unit_main_pid(Unit *u) {
-+        assert(u);
-+
-+        if (UNIT_VTABLE(u)->main_pid)
-+                return UNIT_VTABLE(u)->main_pid(u);
-+
-+        return 0;
-+}
-+
- static const char* const unit_active_state_table[_UNIT_ACTIVE_STATE_MAX] = {
-         [UNIT_ACTIVE] = "active",
-         [UNIT_RELOADING] = "reloading",
-diff --git a/src/core/unit.h b/src/core/unit.h
-index d936457..35287a5 100644
---- a/src/core/unit.h
-+++ b/src/core/unit.h
-@@ -399,6 +399,12 @@ struct UnitVTable {
- 
-         int (*get_timeout)(Unit *u, uint64_t *timeout);
- 
-+        /* Returns the main PID if there is any defined, or 0. */
-+        pid_t (*main_pid)(Unit *u);
-+
-+        /* Returns the main PID if there is any defined, or 0. */
-+        pid_t (*control_pid)(Unit *u);
-+
-         /* This is called for each unit type and should be used to
-          * enumerate existing devices and load them. However,
-          * everything that is loaded here should still stay in
-@@ -610,6 +616,9 @@ int unit_make_transient(Unit *u);
- 
- int unit_require_mounts_for(Unit *u, const char *path);
- 
-+pid_t unit_control_pid(Unit *u);
-+pid_t unit_main_pid(Unit *u);
-+
- const char *unit_active_state_to_string(UnitActiveState i) _const_;
- UnitActiveState unit_active_state_from_string(const char *s) _pure_;
- 
diff --git a/SOURCES/0285-udev-downgrade-a-few-warnings-to-debug-messages.patch b/SOURCES/0285-udev-downgrade-a-few-warnings-to-debug-messages.patch
new file mode 100644
index 0000000..461de4d
--- /dev/null
+++ b/SOURCES/0285-udev-downgrade-a-few-warnings-to-debug-messages.patch
@@ -0,0 +1,44 @@
+From 95a6f0f1b2a24e40380af5db1797ee60c8763ca2 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Tue, 14 Apr 2015 15:48:26 +0200
+Subject: [PATCH] udev: downgrade a few warnings to debug messages
+
+https://bugs.freedesktop.org/show_bug.cgi?id=89885
+
+Cherry-picked from: 8d8ce9e2
+Resolves: #1289461
+---
+ src/udev/udev-builtin-blkid.c  | 2 +-
+ src/udev/udev-builtin-usb_id.c | 6 ++----
+ 2 files changed, 3 insertions(+), 5 deletions(-)
+
+diff --git a/src/udev/udev-builtin-blkid.c b/src/udev/udev-builtin-blkid.c
+index 8999583..2b2c3da 100644
+--- a/src/udev/udev-builtin-blkid.c
++++ b/src/udev/udev-builtin-blkid.c
+@@ -263,7 +263,7 @@ static int builtin_blkid(struct udev_device *dev, int argc, char *argv[], bool t
+ 
+         fd = open(udev_device_get_devnode(dev), O_RDONLY|O_CLOEXEC);
+         if (fd < 0) {
+-                fprintf(stderr, "error: %s: %m\n", udev_device_get_devnode(dev));
++                err = log_debug_errno(errno, "Failure opening block device %s: %m", udev_device_get_devnode(dev));
+                 goto out;
+         }
+ 
+diff --git a/src/udev/udev-builtin-usb_id.c b/src/udev/udev-builtin-usb_id.c
+index ab0d96e..64b763c 100644
+--- a/src/udev/udev-builtin-usb_id.c
++++ b/src/udev/udev-builtin-usb_id.c
+@@ -168,10 +168,8 @@ static int dev_if_packed_info(struct udev_device *dev, char *ifs_str, size_t len
+                 return log_oom();
+ 
+         fd = open(filename, O_RDONLY|O_CLOEXEC);
+-        if (fd < 0) {
+-                fprintf(stderr, "error opening USB device 'descriptors' file\n");
+-                return -errno;
+-        }
++        if (fd < 0)
++                return log_debug_errno(errno, "Error opening USB device 'descriptors' file: %m");
+ 
+         size = read(fd, buf, sizeof(buf));
+         if (size < 18 || size == sizeof(buf))
diff --git a/SOURCES/0286-man-LEVEL-in-systemd-analyze-set-log-level-is-not-op.patch b/SOURCES/0286-man-LEVEL-in-systemd-analyze-set-log-level-is-not-op.patch
new file mode 100644
index 0000000..7a72451
--- /dev/null
+++ b/SOURCES/0286-man-LEVEL-in-systemd-analyze-set-log-level-is-not-op.patch
@@ -0,0 +1,26 @@
+From ffe00d391c0cfc52897820bb19c6a0b8a43680d8 Mon Sep 17 00:00:00 2001
+From: Lukas Nykryn <lnykryn@redhat.com>
+Date: Mon, 5 Oct 2015 12:19:13 +0200
+Subject: [PATCH] man: LEVEL in systemd-analyze set-log level is not optional
+
+rhbz#1268336
+
+Cherry-picked from: 62b29f83cdd3059fda5bf5d2e098293f6dccf863
+Resolves: #1268336
+---
+ man/systemd-analyze.xml | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/man/systemd-analyze.xml b/man/systemd-analyze.xml
+index b2e0f42..e58d9a7 100644
+--- a/man/systemd-analyze.xml
++++ b/man/systemd-analyze.xml
+@@ -93,7 +93,7 @@
+       <command>systemd-analyze</command>
+       <arg choice="opt" rep="repeat">OPTIONS</arg>
+       <arg choice="plain">set-log-level</arg>
+-      <arg choice="opt"><replaceable>LEVEL</replaceable></arg>
++      <arg choice="plain"><replaceable>LEVEL</replaceable></arg>
+     </cmdsynopsis>
+     <cmdsynopsis>
+       <command>systemd-analyze</command>
diff --git a/SOURCES/0287-Revert-udev-fibre-channel-fix-NPIV-support.patch b/SOURCES/0287-Revert-udev-fibre-channel-fix-NPIV-support.patch
new file mode 100644
index 0000000..10170d9
--- /dev/null
+++ b/SOURCES/0287-Revert-udev-fibre-channel-fix-NPIV-support.patch
@@ -0,0 +1,57 @@
+From 4c895cb7bbb307f3c865d9a37f448605797d2b42 Mon Sep 17 00:00:00 2001
+From: Michal Sekletar <msekleta@redhat.com>
+Date: Mon, 29 Feb 2016 16:33:38 +0100
+Subject: [PATCH] Revert "udev: fibre channel: fix NPIV support"
+
+This reverts commit 569d98e9caae425120bf28f6b440e6cc117abc0d.
+
+Related: #1266934
+---
+ src/udev/udev-builtin-path_id.c | 27 +++------------------------
+ 1 file changed, 3 insertions(+), 24 deletions(-)
+
+diff --git a/src/udev/udev-builtin-path_id.c b/src/udev/udev-builtin-path_id.c
+index 695ac7f..9ca6084 100644
+--- a/src/udev/udev-builtin-path_id.c
++++ b/src/udev/udev-builtin-path_id.c
+@@ -92,9 +92,6 @@ static struct udev_device *skip_subsystem(struct udev_device *dev, const char *s
+ static struct udev_device *handle_scsi_fibre_channel(struct udev_device *parent, char **path) {
+         struct udev *udev  = udev_device_get_udev(parent);
+         struct udev_device *targetdev;
+-        struct udev_device *rportdev;
+-        struct udev_device *hostdev;
+-        struct udev_device *vportdev;
+         struct udev_device *fcdev = NULL;
+         const char *port;
+         char *lun = NULL;
+@@ -103,27 +100,9 @@ static struct udev_device *handle_scsi_fibre_channel(struct udev_device *parent,
+         if (targetdev == NULL)
+                 return NULL;
+ 
+-        rportdev = udev_device_get_parent(targetdev);
+-        if (rportdev == NULL)
+-                goto skip_npiv_check;
+-
+-        hostdev = udev_device_get_parent(rportdev);
+-        if (hostdev == NULL)
+-                goto skip_npiv_check;
+-
+-        vportdev = udev_device_get_parent(hostdev);
+-        if (vportdev == NULL)
+-                goto skip_npiv_check;
+-
+-        fcdev = udev_device_new_from_subsystem_sysname(udev, "fc_vports", udev_device_get_sysname(vportdev));
+-
+-skip_npiv_check:
+-        if (fcdev == NULL) {
+-                fcdev = udev_device_new_from_subsystem_sysname(udev, "fc_transport", udev_device_get_sysname(targetdev));
+-                if (fcdev == NULL)
+-                        return NULL;
+-        }
+-
++        fcdev = udev_device_new_from_subsystem_sysname(udev, "fc_transport", udev_device_get_sysname(targetdev));
++        if (fcdev == NULL)
++                return NULL;
+         port = udev_device_get_sysattr_value(fcdev, "port_name");
+         if (port == NULL) {
+                 parent = NULL;
diff --git a/SOURCES/0288-udev-path-id-fibre-channel-NPIV-use-fc_vport-s-port_.patch b/SOURCES/0288-udev-path-id-fibre-channel-NPIV-use-fc_vport-s-port_.patch
new file mode 100644
index 0000000..f710d52
--- /dev/null
+++ b/SOURCES/0288-udev-path-id-fibre-channel-NPIV-use-fc_vport-s-port_.patch
@@ -0,0 +1,125 @@
+From 05004e584a76645dcbcaaa4d5c2d3d3255900770 Mon Sep 17 00:00:00 2001
+From: Mauricio Faria de Oliveira <mauricfo@linux.vnet.ibm.com>
+Date: Tue, 23 Feb 2016 15:02:02 -0300
+Subject: [PATCH] udev: path-id: fibre channel NPIV - use fc_vport's port_name
+
+With the Fibre Channel NPIV (N_Port ID Virtualization) feature,
+a single physical N_Port (e.g., PCI address) can have multiple
+N_Port IDs (e.g., different fc_host nodes) - which can connect
+to the same target LUN (e.g., fc_remote_port's port_name and
+LUN number).
+
+Thus, in order to be unique, the device persistent path should
+include the fc_vport's port_name (only if the fc_vport is used),
+in addition to the already in use PCI address, fc_remote_port's
+port_name and LUN number.
+
+The patch merges the 2 proposals submitted upstream, addressing
+some problems with both:
+- #2500 (don't replace the fc_rport's port_name with fc_vport's)
+- #2665 (don't add a fc_host/fc_vport's port_name if not needed)
+
+Links
+- https://github.com/systemd/systemd/pull/2500/
+- https://github.com/systemd/systemd/pull/2665/
+
+Built, checked, tested on RHEL Server 7.1 with no regressions.
+
+With the patch, /dev/disk/by-path symlinks are created correctly,
+and are unique, backward-compatible with the physical port case:
+- physical port (no vport field)
+- virtual ports (w/ vport field)
+
+    # ls -l /dev/disk/by-path | grep 0001:09:00.0
+    <...> pci-0001:09:00.0-fc-0x500507680b2255fe-lun-0 -> ../../sdh
+    <...> pci-0001:09:00.0-fc-0x500507680b2255ff-lun-0 -> ../../sdi
+    <...> pci-0001:09:00.0-vport-0x5001a4aaf00a6785-fc-0x500507680b2255fe-lun-0 -> ../../sde
+    <...> pci-0001:09:00.0-vport-0x5001a4aaf00a6785-fc-0x500507680b2255ff-lun-0 -> ../../sdd
+    <...> pci-0001:09:00.0-vport-0x5001a4ad99d8c2de-fc-0x500507680b2255fe-lun-0 -> ../../sdc
+    <...> pci-0001:09:00.0-vport-0x5001a4ad99d8c2de-fc-0x500507680b2255ff-lun-0 -> ../../sdb
+
+Accordingly w/ sysfs:
+
+    # ls -ld /sys/block/sd* | grep host1
+    <...> /sys/block/sdb -> ../devices/pci0001:00/<...>/0001:09:00.0/host1/vport-1:0-0/host3/rport-3:0-1/target3:0:0/3:0:0:0/block/sdb
+    <...> /sys/block/sdc -> ../devices/pci0001:00/<...>/0001:09:00.0/host1/vport-1:0-0/host3/rport-3:0-2/target3:0:1/3:0:1:0/block/sdc
+    <...> /sys/block/sdd -> ../devices/pci0001:00/<...>/0001:09:00.0/host1/vport-1:0-2/host5/rport-5:0-1/target5:0:0/5:0:0:0/block/sdd
+    <...> /sys/block/sde -> ../devices/pci0001:00/<...>/0001:09:00.0/host1/vport-1:0-2/host5/rport-5:0-2/target5:0:1/5:0:1:0/block/sde
+    <...> /sys/block/sdh -> ../devices/pci0001:00/<...>/0001:09:00.0/host1/rport-1:0-3/target1:0:0/1:0:0:0/block/sdh
+    <...> /sys/block/sdi -> ../devices/pci0001:00/<...>/0001:09:00.0/host1/rport-1:0-4/target1:0:1/1:0:1:0/block/sdi
+
+The symlinks still include the fc_remote_port's (target) port_name:
+
+    # grep . /sys/class/fc_remote_ports/rport-{3:0-{1,2},5:0-{1,2},1:0-{3,4}}/port_name
+    /sys/class/fc_remote_ports/rport-3:0-1/port_name:0x500507680b2255ff
+    /sys/class/fc_remote_ports/rport-3:0-2/port_name:0x500507680b2255fe
+    /sys/class/fc_remote_ports/rport-5:0-1/port_name:0x500507680b2255ff
+    /sys/class/fc_remote_ports/rport-5:0-2/port_name:0x500507680b2255fe
+    /sys/class/fc_remote_ports/rport-1:0-3/port_name:0x500507680b2255fe
+    /sys/class/fc_remote_ports/rport-1:0-4/port_name:0x500507680b2255ff
+
+And now include the fc_vport's (virtual host) port_name *if* it's from a fc_vport:
+
+    # grep . /sys/class/fc_host/host1/port_name /sys/class/fc_vports/vport-1:0-{0,2}/port_name
+    /sys/class/fc_host/host1/port_name:0x10000090fa8f0ebc
+    /sys/class/fc_vports/vport-1:0-0/port_name:0x5001a4ad99d8c2de
+    /sys/class/fc_vports/vport-1:0-2/port_name:0x5001a4aaf00a6785
+
+Signed-off-by: Mauricio Faria de Oliveira <mauricfo@linux.vnet.ibm.com>
+Reported-by: Srikanth B. Aithal <bssrikanth@in.ibm.com>
+
+Cherry-picked from: 6a3d3f9e5970cf982ac37c65d0b856146b675a12
+Resolves: #1266934
+---
+ src/udev/udev-builtin-path_id.c | 30 ++++++++++++++++++++++++++++++
+ 1 file changed, 30 insertions(+)
+
+diff --git a/src/udev/udev-builtin-path_id.c b/src/udev/udev-builtin-path_id.c
+index 9ca6084..3b72922 100644
+--- a/src/udev/udev-builtin-path_id.c
++++ b/src/udev/udev-builtin-path_id.c
+@@ -92,7 +92,11 @@ static struct udev_device *skip_subsystem(struct udev_device *dev, const char *s
+ static struct udev_device *handle_scsi_fibre_channel(struct udev_device *parent, char **path) {
+         struct udev *udev  = udev_device_get_udev(parent);
+         struct udev_device *targetdev;
++        struct udev_device *rportdev;
++        struct udev_device *hostdev;
++        struct udev_device *vportdev;
+         struct udev_device *fcdev = NULL;
++        struct udev_device *fc_vportdev = NULL;
+         const char *port;
+         char *lun = NULL;
+ 
+@@ -113,6 +117,32 @@ static struct udev_device *handle_scsi_fibre_channel(struct udev_device *parent,
+         path_prepend(path, "fc-%s-%s", port, lun);
+         if (lun)
+                 free(lun);
++
++        /* NPIV */
++        rportdev = udev_device_get_parent(targetdev);
++        if (rportdev == NULL)
++                goto out;
++
++        hostdev = udev_device_get_parent(rportdev);
++        if (hostdev == NULL)
++                goto out;
++
++        vportdev = udev_device_get_parent(hostdev);
++        if (vportdev == NULL)
++                goto out;
++
++        fc_vportdev = udev_device_new_from_subsystem_sysname(udev, "fc_vports", udev_device_get_sysname(vportdev));
++        if (fc_vportdev == NULL)
++                goto out;
++
++        port = udev_device_get_sysattr_value(fc_vportdev, "port_name");
++        if (port == NULL)
++                goto out_npiv;
++
++        path_prepend(path, "vport-%s", port);
++
++out_npiv:
++        udev_device_unref(fc_vportdev);
+ out:
+         udev_device_unref(fcdev);
+         return parent;
diff --git a/SOURCES/0289-systemctl-is-active-failed-should-return-0-if-at-lea.patch b/SOURCES/0289-systemctl-is-active-failed-should-return-0-if-at-lea.patch
new file mode 100644
index 0000000..c421414
--- /dev/null
+++ b/SOURCES/0289-systemctl-is-active-failed-should-return-0-if-at-lea.patch
@@ -0,0 +1,45 @@
+From f3b1b4ae42a2d0d6383c6587a842418abad645a9 Mon Sep 17 00:00:00 2001
+From: Lukas Nykryn <lnykryn@redhat.com>
+Date: Mon, 25 Jan 2016 15:21:28 +0100
+Subject: [PATCH] systemctl: is-active/failed should return 0 if at least one
+ unit is in given state
+
+Previously we have return the not-found code, in the case that we found a
+unit which does not belong to set active (resp. failed), which is the
+opposite than what is written in man page.
+
+Cherry-picked from: d60f6ad0cb690d920b8acbfb545bad29554609f1
+Resolves: #1254650
+---
+ src/systemctl/systemctl.c | 9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
+index 5d3a85f..bf5bb39 100644
+--- a/src/systemctl/systemctl.c
++++ b/src/systemctl/systemctl.c
+@@ -3002,6 +3002,7 @@ static int check_unit_generic(sd_bus *bus, int code, const char *good_states, ch
+         _cleanup_strv_free_ char **names = NULL;
+         char **name;
+         int r;
++        bool found = false;
+ 
+         assert(bus);
+         assert(args);
+@@ -3016,11 +3017,13 @@ static int check_unit_generic(sd_bus *bus, int code, const char *good_states, ch
+                 state = check_one_unit(bus, *name, good_states, arg_quiet);
+                 if (state < 0)
+                         return state;
+-                if (state == 0)
+-                        r = code;
++                if (state > 0)
++                        found = true;
+         }
+ 
+-        return r;
++        /* use the given return code for the case that we won't find
++         * any unit which matches the list */
++        return found ? 0 : code;
+ }
+ 
+ static int check_unit_active(sd_bus *bus, char **args) {
diff --git a/SOURCES/0290-rules-set-SYSTEMD_READY-0-on-DM_UDEV_DISABLE_OTHER_R.patch b/SOURCES/0290-rules-set-SYSTEMD_READY-0-on-DM_UDEV_DISABLE_OTHER_R.patch
new file mode 100644
index 0000000..7c60bfd
--- /dev/null
+++ b/SOURCES/0290-rules-set-SYSTEMD_READY-0-on-DM_UDEV_DISABLE_OTHER_R.patch
@@ -0,0 +1,34 @@
+From d77ced281c6d1f47b5dfc3abff6817d8f5756af9 Mon Sep 17 00:00:00 2001
+From: Lukas Nykryn <lnykryn@redhat.com>
+Date: Thu, 25 Feb 2016 15:15:04 +0100
+Subject: [PATCH] rules: set SYSTEMD_READY=0 on
+ DM_UDEV_DISABLE_OTHER_RULES_FLAG=1 only with ADD event
+
+The "SYSTEMD_READY=0" will cause automatic unmount
+of mountpoint that is on top of such DM device
+if this is used with multipath which sets
+DM_UDEV_DISABLE_OTHER_RULES_FLAG in case
+we have a CHANGE event thatcomes after DM multipath
+device reload when one of the paths is down or up.
+
+See https://bugzilla.redhat.com/show_bug.cgi?id=1312011
+
+Cherry-picked from: 83a3642f617975d596b5001b1699c3d16773a6e5
+Resolves: #1312011
+---
+ rules/99-systemd.rules.in | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/rules/99-systemd.rules.in b/rules/99-systemd.rules.in
+index b66d727..a4f4bf3 100644
+--- a/rules/99-systemd.rules.in
++++ b/rules/99-systemd.rules.in
+@@ -12,7 +12,7 @@ SUBSYSTEM=="tty", KERNEL=="tty[a-zA-Z]*|hvc*|xvc*|hvsi*|ttysclp*|sclp_line*|3270
+ KERNEL=="vport*", TAG+="systemd"
+ 
+ SUBSYSTEM=="block", KERNEL!="ram*", TAG+="systemd"
+-SUBSYSTEM=="block", KERNEL!="ram*", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}=="1", ENV{SYSTEMD_READY}="0"
++SUBSYSTEM=="block", KERNEL!="ram*", ACTION=="add", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}=="1", ENV{SYSTEMD_READY}="0"
+ 
+ # Ignore encrypted devices with no identified superblock on it, since
+ # we are probably still calling mke2fs or mkswap on it.
diff --git a/SOURCES/0291-s390-add-personality-support.patch b/SOURCES/0291-s390-add-personality-support.patch
new file mode 100644
index 0000000..1e6fc33
--- /dev/null
+++ b/SOURCES/0291-s390-add-personality-support.patch
@@ -0,0 +1,109 @@
+From 9435bd3d692c7b07e527b6a616018fa5620502e2 Mon Sep 17 00:00:00 2001
+From: Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
+Date: Thu, 24 Sep 2015 12:47:22 +0200
+Subject: [PATCH] s390: add personality support
+
+Introduce personality support for Linux on z Systems to run
+particular services with a 64-bit or 31-bit personality.
+
+Cherry-picked from: 7517f51ef9921d3360453c8eec2c97256d320ceb
+Resolves: #1300344
+---
+ Makefile.am                        |  1 +
+ src/shared/util.c                  | 27 +++++++++++++++++++++++++++
+ src/test/test-execute.c            |  8 ++++++--
+ test/exec-personality-s390.service |  7 +++++++
+ 4 files changed, 41 insertions(+), 2 deletions(-)
+ create mode 100644 test/exec-personality-s390.service
+
+diff --git a/Makefile.am b/Makefile.am
+index 2559376..3af720b 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -1483,6 +1483,7 @@ EXTRA_DIST += \
+ 	test/exec-ignoresigpipe-yes.service \
+ 	test/exec-personality-x86-64.service \
+ 	test/exec-personality-x86.service \
++	test/exec-personality-s390.service \
+ 	test/exec-privatedevices-no.service \
+ 	test/exec-privatedevices-yes.service \
+ 	test/exec-privatetmp-no.service \
+diff --git a/src/shared/util.c b/src/shared/util.c
+index dc51852..a24aa7f 100644
+--- a/src/shared/util.c
++++ b/src/shared/util.c
+@@ -6748,6 +6748,19 @@ unsigned long personality_from_string(const char *p) {
+ 
+         if (streq(p, "x86"))
+                 return PER_LINUX;
++
++#elif defined(__s390x__)
++
++        if (streq(p, "s390"))
++                return PER_LINUX32;
++
++        if (streq(p, "s390x"))
++                return PER_LINUX;
++
++#elif defined(__s390__)
++
++        if (streq(p, "s390"))
++                return PER_LINUX;
+ #endif
+ 
+         /* personality(7) documents that 0xffffffffUL is used for
+@@ -6770,6 +6783,20 @@ const char* personality_to_string(unsigned long p) {
+ 
+         if (p == PER_LINUX)
+                 return "x86";
++
++#elif defined(__s390x__)
++
++        if (p == PER_LINUX)
++                return "s390x";
++
++        if (p == PER_LINUX32)
++                return "s390";
++
++#elif defined(__s390__)
++
++        if (p == PER_LINUX)
++                return "s390";
++
+ #endif
+ 
+         return NULL;
+diff --git a/src/test/test-execute.c b/src/test/test-execute.c
+index 91ccaf7..00f3607 100644
+--- a/src/test/test-execute.c
++++ b/src/test/test-execute.c
+@@ -77,10 +77,14 @@ static void test_exec_workingdirectory(Manager *m) {
+ }
+ 
+ static void test_exec_personality(Manager *m) {
+-        test(m, "exec-personality-x86.service", 0, CLD_EXITED);
+-
+ #if defined(__x86_64__)
+         test(m, "exec-personality-x86-64.service", 0, CLD_EXITED);
++
++#elif defined(__s390__)
++        test(m, "exec-personality-s390.service", 0, CLD_EXITED);
++
++#else
++        test(m, "exec-personality-x86.service", 0, CLD_EXITED);
+ #endif
+ }
+ 
+diff --git a/test/exec-personality-s390.service b/test/exec-personality-s390.service
+new file mode 100644
+index 0000000..f3c3b03
+--- /dev/null
++++ b/test/exec-personality-s390.service
+@@ -0,0 +1,7 @@
++[Unit]
++Description=Test for Personality=s390
++
++[Service]
++ExecStart=/bin/sh -c 'echo $(uname -m); exit $(test $(uname -m) = "s390")'
++Type=oneshot
++Personality=s390
diff --git a/SOURCES/0292-socket_address_listen-do-not-rely-on-errno.patch b/SOURCES/0292-socket_address_listen-do-not-rely-on-errno.patch
new file mode 100644
index 0000000..22eeeb3
--- /dev/null
+++ b/SOURCES/0292-socket_address_listen-do-not-rely-on-errno.patch
@@ -0,0 +1,34 @@
+From 2ae0271ada810c06c12755699f0db955fc51061d Mon Sep 17 00:00:00 2001
+From: Petr Lautrbach <plautrba@redhat.com>
+Date: Thu, 10 Mar 2016 10:19:56 +0100
+Subject: [PATCH] socket_address_listen - do not rely on errno
+
+Currently socket_address_listen() calls mac_selinux_bind() to bind a UNIX
+socket and checks its return value and errno for EADDRINUSE. This is not
+correct. When there's an SELinux context change made for the new socket,
+bind() is not the last function called in mac_selinux_bind(). In that
+case the last call is setfscreatecon() from libselinux which can change
+errno as it uses access() to check if /proc/thread-self is available.
+It fails on kernels before 3.17 and errno is set to ENOENT.
+
+It's safe to check only the return value at it's set to -errno.
+
+Cherry-picked from: a0c9496cc826957fe0f3926f619e073f17a9ab4d
+Resolves: #1316452
+---
+ src/shared/socket-label.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/shared/socket-label.c b/src/shared/socket-label.c
+index a6289eb..713e71b 100644
+--- a/src/shared/socket-label.c
++++ b/src/shared/socket-label.c
+@@ -119,7 +119,7 @@ int socket_address_listen(
+ 
+                 r = mac_selinux_bind(fd, &a->sockaddr.sa, a->size);
+ 
+-                if (r < 0 && errno == EADDRINUSE) {
++                if (r == -EADDRINUSE) {
+                         /* Unlink and try again */
+                         unlink(a->sockaddr.un.sun_path);
+                         r = bind(fd, &a->sockaddr.sa, a->size);
diff --git a/SOURCES/0293-path_id-reintroduce-by-path-links-for-virtio-block-d.patch b/SOURCES/0293-path_id-reintroduce-by-path-links-for-virtio-block-d.patch
new file mode 100644
index 0000000..318baa7
--- /dev/null
+++ b/SOURCES/0293-path_id-reintroduce-by-path-links-for-virtio-block-d.patch
@@ -0,0 +1,48 @@
+From b6fea1a0e0fd830e1aa82accf389cb8bfd0f0f37 Mon Sep 17 00:00:00 2001
+From: Michal Sekletar <msekleta@redhat.com>
+Date: Tue, 9 Feb 2016 09:57:45 +0100
+Subject: [PATCH] path_id: reintroduce by-path links for virtio block devices
+
+Enumeration of virtio buses is global and hence
+non-deterministic. However, we are guaranteed there is never going to be
+more than one virtio bus per parent PCI device. While populating
+ID_PATH we simply skip virtio part of the syspath and we extend the path
+using the sysname of the parent PCI device.
+
+With this patch udev creates following by-path links for virtio-blk
+device /dev/vda which contains two partitions.
+
+ls -l /dev/disk/by-path/
+total 0
+lrwxrwxrwx 1 root root  9 Feb  9 10:47 virtio-pci-0000:00:05.0 -> ../../vda
+lrwxrwxrwx 1 root root 10 Feb  9 10:47 virtio-pci-0000:00:05.0-part1 -> ../../vda1
+lrwxrwxrwx 1 root root 10 Feb  9 10:47 virtio-pci-0000:00:05.0-part2 -> ../../vda2
+
+See:
+http://lists.linuxfoundation.org/pipermail/virtualization/2015-August/030328.html
+
+Fixes #2501
+
+Cherry-picked from: f073b1b3c0f4f0df1b0bd61042ce85fb5d27d407
+Resolves: #952567
+---
+ src/udev/udev-builtin-path_id.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/src/udev/udev-builtin-path_id.c b/src/udev/udev-builtin-path_id.c
+index 3b72922..8359e23 100644
+--- a/src/udev/udev-builtin-path_id.c
++++ b/src/udev/udev-builtin-path_id.c
+@@ -698,6 +698,12 @@ restart:
+                         path_prepend(&path, "xen-%s", udev_device_get_sysname(parent));
+                         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));
++                        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/0294-journal-fix-error-handling-when-compressing-journal-.patch b/SOURCES/0294-journal-fix-error-handling-when-compressing-journal-.patch
new file mode 100644
index 0000000..b5246a5
--- /dev/null
+++ b/SOURCES/0294-journal-fix-error-handling-when-compressing-journal-.patch
@@ -0,0 +1,67 @@
+From f45b66a348f5778bd391ad1b0a0e09bf5789b415 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Sat, 24 Oct 2015 13:17:54 +0200
+Subject: [PATCH] journal: fix error handling when compressing journal objects
+
+Let's make sure we handle compression errors properly, and don't
+misunderstand an error for success.
+
+Also, let's actually compress things if lz4 is enabled.
+
+Fixes #1662.
+
+Cherry-picked from: d1afbcd22170e95c79261340071d376fe41fc3af
+Resolves: #1292447
+---
+ src/journal/journal-file.c | 12 +++++++-----
+ src/journal/journal-file.h |  5 +++++
+ 2 files changed, 12 insertions(+), 5 deletions(-)
+
+diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c
+index f500568..a8f92e2 100644
+--- a/src/journal/journal-file.c
++++ b/src/journal/journal-file.c
+@@ -1051,23 +1051,25 @@ static int journal_file_append_data(
+         o->data.hash = htole64(hash);
+ 
+ #if defined(HAVE_XZ) || defined(HAVE_LZ4)
+-        if (f->compress_xz &&
+-            size >= COMPRESSION_SIZE_THRESHOLD) {
++        if (JOURNAL_FILE_COMPRESS(f) && size >= COMPRESSION_SIZE_THRESHOLD) {
+                 size_t rsize;
+ 
+                 compression = compress_blob(data, size, o->data.payload, &rsize);
+ 
+-                if (compression) {
++                if (compression >= 0) {
+                         o->object.size = htole64(offsetof(Object, data.payload) + rsize);
+                         o->object.flags |= compression;
+ 
+                         log_debug("Compressed data object %"PRIu64" -> %zu using %s",
+                                   size, rsize, object_compressed_to_string(compression));
+-                }
++                } else
++                        /* Compression didn't work, we don't really care why, let's continue without compression */
++                        compression = 0;
++
+         }
+ #endif
+ 
+-        if (!compression && size > 0)
++        if (compression == 0 && size > 0)
+                 memcpy(o->data.payload, data, size);
+ 
+         r = journal_file_link_data(f, o, p, hash);
+diff --git a/src/journal/journal-file.h b/src/journal/journal-file.h
+index 403c8f7..0f29b09 100644
+--- a/src/journal/journal-file.h
++++ b/src/journal/journal-file.h
+@@ -229,3 +229,8 @@ int journal_file_get_cutoff_realtime_usec(JournalFile *f, usec_t *from, usec_t *
+ int journal_file_get_cutoff_monotonic_usec(JournalFile *f, sd_id128_t boot, usec_t *from, usec_t *to);
+ 
+ bool journal_file_rotate_suggested(JournalFile *f, usec_t max_file_usec);
++
++static inline bool JOURNAL_FILE_COMPRESS(JournalFile *f) {
++        assert(f);
++        return f->compress_xz || f->compress_lz4;
++}
diff --git a/SOURCES/0295-journal-irrelevant-coding-style-fixes.patch b/SOURCES/0295-journal-irrelevant-coding-style-fixes.patch
new file mode 100644
index 0000000..db97ef0
--- /dev/null
+++ b/SOURCES/0295-journal-irrelevant-coding-style-fixes.patch
@@ -0,0 +1,45 @@
+From d205f5f85569e2dddca96362ce2db4e2a0b99d00 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Sat, 24 Oct 2015 15:08:15 +0200
+Subject: [PATCH] journal: irrelevant coding style fixes
+
+Cherry-picked from: 0240c603691e006165d8687d6a2c70859755b11f
+Related: #1292447
+---
+ src/journal/compress.c     | 9 +++++----
+ src/journal/journal-file.c | 2 +-
+ 2 files changed, 6 insertions(+), 5 deletions(-)
+
+diff --git a/src/journal/compress.c b/src/journal/compress.c
+index 6923753..c9a3399 100644
+--- a/src/journal/compress.c
++++ b/src/journal/compress.c
+@@ -51,10 +51,11 @@ int compress_blob_xz(const void *src, uint64_t src_size, void *dst, size_t *dst_
+ #ifdef HAVE_XZ
+         static const lzma_options_lzma opt = {
+                 1u << 20u, NULL, 0, LZMA_LC_DEFAULT, LZMA_LP_DEFAULT,
+-                LZMA_PB_DEFAULT, LZMA_MODE_FAST, 128, LZMA_MF_HC3, 4};
+-        static const lzma_filter filters[2] = {
+-                {LZMA_FILTER_LZMA2, (lzma_options_lzma*) &opt},
+-                {LZMA_VLI_UNKNOWN, NULL}
++                LZMA_PB_DEFAULT, LZMA_MODE_FAST, 128, LZMA_MF_HC3, 4
++        };
++        static const lzma_filter filters[] = {
++                { LZMA_FILTER_LZMA2, (lzma_options_lzma*) &opt },
++                { LZMA_VLI_UNKNOWN, NULL }
+         };
+         lzma_ret ret;
+         size_t out_pos = 0;
+diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c
+index a8f92e2..892fe47 100644
+--- a/src/journal/journal-file.c
++++ b/src/journal/journal-file.c
+@@ -1032,7 +1032,7 @@ static int journal_file_append_data(
+         r = journal_file_find_data_object_with_hash(f, data, size, hash, &o, &p);
+         if (r < 0)
+                 return r;
+-        else if (r > 0) {
++        if (r > 0) {
+ 
+                 if (ret)
+                         *ret = o;
diff --git a/SOURCES/0296-install-follow-unit-file-symlinks-in-usr-but-not-etc.patch b/SOURCES/0296-install-follow-unit-file-symlinks-in-usr-but-not-etc.patch
new file mode 100644
index 0000000..21d90a8
--- /dev/null
+++ b/SOURCES/0296-install-follow-unit-file-symlinks-in-usr-but-not-etc.patch
@@ -0,0 +1,4358 @@
+From 272378080241106862a9cca2e4e84857fe1aaf5c Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Thu, 8 Oct 2015 22:31:56 +0200
+Subject: [PATCH] install: follow unit file symlinks in /usr, but not /etc when
+ looking for [Install] data
+
+Some distributions use alias unit files via symlinks in /usr to cover
+for legacy service names. With this change we'll allow "systemctl
+enable" on such aliases.
+
+Previously, our rule was that symlinks are user configuration that
+"systemctl enable" + "systemctl disable" creates and removes, while unit
+files is where the instructions to do so are store. As a result of the
+rule we'd never read install information through symlinks, since that
+would mix enablement state with installation instructions.
+
+Now, the new rule is that only symlinks inside of /etc are
+configuration. Unit files, and symlinks in /usr are now valid for
+installation instructions.
+
+This patch is quite a rework of the whole install logic, and makes the
+following addional changes:
+
+- Adds a complete test "test-instal-root" that tests the install logic
+  pretty comprehensively.
+
+- Never uses canonicalize_file_name(), because that's incompatible with
+  operation relative to a specific root directory.
+
+- unit_file_get_state() is reworked to return a proper error, and
+  returns the state in a call-by-ref parameter. This cleans up confusion
+  between the enum type and errno-like errors.
+
+- The new logic puts a limit on how long to follow unit file symlinks:
+  it will do so only for 64 steps at max.
+
+- The InstallContext object's fields are renamed to will_process and
+  has_processed (will_install and has_installed) since they are also
+  used for deinstallation and all kinds of other operations.
+
+- The root directory is always verified before use.
+
+- install.c is reordered to place the exported functions together.
+
+- Stricter rules are followed when traversing symlinks: the unit suffix
+  must say identical, and it's not allowed to link between regular units
+  and templated units.
+
+- Various modernizations
+
+- The "invalid" unit file state has been renamed to "bad", in order to
+  avoid confusion between UNIT_FILE_INVALID and
+  _UNIT_FILE_STATE_INVALID. Given that the state should normally not be
+  seen and is not documented this should not be a problematic change.
+  The new name is now documented however.
+
+Fixes #1375, #1718, #1706
+
+Cherry-picked from: 79413b673b45adc98dfeaec882bbdda2343cb2f9
+Resolves: #1159308
+---
+ Makefile.am                           |   12 +-
+ man/systemctl.xml                     |   14 +-
+ src/core/dbus-manager.c               |    6 +-
+ src/core/dbus-unit.c                  |    4 +-
+ src/core/load-fragment.c              |    2 +-
+ src/core/manager.c                    |    2 +-
+ src/core/snapshot.c                   |    2 +-
+ src/core/unit.c                       |   19 +-
+ src/dbus1-generator/dbus1-generator.c |    2 +-
+ src/firstboot/firstboot.c             |   18 +-
+ src/shared/cgroup-util.c              |    6 +-
+ src/shared/install.c                  | 1909 +++++++++++++++++++--------------
+ src/shared/install.h                  |   46 +-
+ src/shared/path-util.c                |   34 +
+ src/shared/path-util.h                |   27 +
+ src/shared/unit-name.c                |   32 +-
+ src/shared/unit-name.h                |   14 +-
+ src/shared/util.c                     |   21 +
+ src/shared/util.h                     |    1 +
+ src/systemctl/systemctl.c             |    6 +-
+ src/sysv-generator/sysv-generator.c   |   10 +-
+ src/test/test-install-root.c          |  663 ++++++++++++
+ src/test/test-install.c               |   71 +-
+ 23 files changed, 1998 insertions(+), 923 deletions(-)
+ create mode 100644 src/test/test-install-root.c
+
+diff --git a/Makefile.am b/Makefile.am
+index 3af720b..3a09e0a 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -1427,7 +1427,8 @@ tests += \
+ 	test-copy \
+ 	test-cap-list \
+ 	test-sigbus \
+-	test-verbs
++	test-verbs \
++	test-install-root
+ 
+ EXTRA_DIST += \
+ 	test/a.service \
+@@ -1721,6 +1722,15 @@ test_verbs_SOURCES = \
+ test_verbs_LDADD = \
+ 	libsystemd-shared.la
+ 
++test_install_root_SOURCES = \
++	src/test/test-install-root.c
++
++test_install_root_LDADD = \
++	libsystemd-units.la \
++	libsystemd-label.la \
++	libsystemd-internal.la \
++	libsystemd-shared.la
++
+ test_namespace_LDADD = \
+ 	libsystemd-core.la
+ 
+diff --git a/man/systemctl.xml b/man/systemctl.xml
+index c6f5842..2d0678d 100644
+--- a/man/systemctl.xml
++++ b/man/systemctl.xml
+@@ -905,10 +905,11 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
+           <term><command>list-unit-files <optional><replaceable>PATTERN...</replaceable></optional></command></term>
+ 
+           <listitem>
+-            <para>List installed unit files. If one or more
+-            <replaceable>PATTERN</replaceable>s are specified, only
+-            units whose filename (just the last component of the path)
+-            matches one of them are shown.</para>
++            <para>List installed unit files and their enablement state
++            (as reported by <command>is-enabled</command>). If one or
++            more <replaceable>PATTERN</replaceable>s are specified,
++            only units whose filename (just the last component of the
++            path) matches one of them are shown.</para>
+           </listitem>
+         </varlistentry>
+ 
+@@ -1108,6 +1109,11 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
+                     <entry>Unit file is not enabled.</entry>
+                     <entry>1</entry>
+                   </row>
++                  <row>
++                    <entry><literal>bad</literal></entry>
++                    <entry>Unit file is invalid or another error occured. Note that <command>is-enabled</command> wil not actually return this state, but print an error message instead. However the unit file listing printed by <command>list-unit-files</command> might show it.</entry>
++                    <entry>&gt; 0</entry>
++                  </row>
+                 </tbody>
+               </tgroup>
+             </table>
+diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
+index 1ec350e..faa124d 100644
+--- a/src/core/dbus-manager.c
++++ b/src/core/dbus-manager.c
+@@ -1530,9 +1530,9 @@ static int method_get_unit_file_state(sd_bus *bus, sd_bus_message *message, void
+ 
+         scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
+ 
+-        state = unit_file_get_state(scope, NULL, name);
+-        if (state < 0)
+-                return state;
++        r = unit_file_get_state(scope, NULL, name, &state);
++        if (r < 0)
++                return r;
+ 
+         return sd_bus_reply_method_return(message, "s", unit_file_state_to_string(state));
+ }
+diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c
+index 625d21a..227915e 100644
+--- a/src/core/dbus-unit.c
++++ b/src/core/dbus-unit.c
+@@ -919,7 +919,7 @@ static int bus_unit_set_transient_property(
+                 if (r < 0)
+                         return r;
+ 
+-                if (!unit_name_is_valid(s, TEMPLATE_INVALID) || !endswith(s, ".slice"))
++                if (!unit_name_is_valid(s, UNIT_NAME_PLAIN) || !endswith(s, ".slice"))
+                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid slice name %s", s);
+ 
+                 if (isempty(s)) {
+@@ -967,7 +967,7 @@ static int bus_unit_set_transient_property(
+                         return r;
+ 
+                 while ((r = sd_bus_message_read(message, "s", &other)) > 0) {
+-                        if (!unit_name_is_valid(other, TEMPLATE_INVALID))
++                        if (!unit_name_is_valid(other, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE))
+                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid unit name %s", other);
+ 
+                         if (mode != UNIT_CHECK) {
+diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
+index ec4cf4e..70c0918 100644
+--- a/src/core/load-fragment.c
++++ b/src/core/load-fragment.c
+@@ -3409,7 +3409,7 @@ static int open_follow(char **filename, FILE **_f, Set *names, char **_final) {
+                  * unit name. */
+                 name = basename(*filename);
+ 
+-                if (unit_name_is_valid(name, TEMPLATE_VALID)) {
++                if (unit_name_is_valid(name, UNIT_NAME_ANY)) {
+ 
+                         id = set_get(names, name);
+                         if (!id) {
+diff --git a/src/core/manager.c b/src/core/manager.c
+index 7483a96..bde17ce 100644
+--- a/src/core/manager.c
++++ b/src/core/manager.c
+@@ -1328,7 +1328,7 @@ int manager_load_unit_prepare(
+ 
+         t = unit_name_to_type(name);
+ 
+-        if (t == _UNIT_TYPE_INVALID || !unit_name_is_valid(name, TEMPLATE_INVALID))
++        if (t == _UNIT_TYPE_INVALID || !unit_name_is_valid(name, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE))
+                 return sd_bus_error_setf(e, SD_BUS_ERROR_INVALID_ARGS, "Unit name %s is not valid.", name);
+ 
+         ret = manager_get_unit(m, name);
+diff --git a/src/core/snapshot.c b/src/core/snapshot.c
+index b1d8448..f222ec2 100644
+--- a/src/core/snapshot.c
++++ b/src/core/snapshot.c
+@@ -201,7 +201,7 @@ int snapshot_create(Manager *m, const char *name, bool cleanup, sd_bus_error *e,
+         assert(_s);
+ 
+         if (name) {
+-                if (!unit_name_is_valid(name, TEMPLATE_INVALID))
++                if (!unit_name_is_valid(name, UNIT_NAME_PLAIN))
+                         return sd_bus_error_setf(e, SD_BUS_ERROR_INVALID_ARGS, "Unit name %s is not valid.", name);
+ 
+                 if (unit_name_to_type(name) != UNIT_SNAPSHOT)
+diff --git a/src/core/unit.c b/src/core/unit.c
+index 4fb2fd3..db5aa98 100644
+--- a/src/core/unit.c
++++ b/src/core/unit.c
+@@ -158,7 +158,7 @@ int unit_add_name(Unit *u, const char *text) {
+         if (!s)
+                 return -ENOMEM;
+ 
+-        if (!unit_name_is_valid(s, TEMPLATE_INVALID))
++        if (!unit_name_is_valid(s, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE))
+                 return -EINVAL;
+ 
+         assert_se((t = unit_name_to_type(s)) >= 0);
+@@ -3119,12 +3119,18 @@ int unit_following_set(Unit *u, Set **s) {
+ }
+ 
+ UnitFileState unit_get_unit_file_state(Unit *u) {
++        int r;
++
+         assert(u);
+ 
+-        if (u->unit_file_state < 0 && u->fragment_path)
+-                u->unit_file_state = unit_file_get_state(
+-                                u->manager->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER,
+-                                NULL, basename(u->fragment_path));
++        if (u->unit_file_state < 0 && u->fragment_path) {
++                r = unit_file_get_state(u->manager->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER,
++                                        NULL,
++                                        basename(u->fragment_path),
++                                        &u->unit_file_state);
++                if (r < 0)
++                        u->unit_file_state = UNIT_FILE_BAD;
++        }
+ 
+         return u->unit_file_state;
+ }
+@@ -3135,7 +3141,8 @@ int unit_get_unit_file_preset(Unit *u) {
+         if (u->unit_file_preset < 0 && u->fragment_path)
+                 u->unit_file_preset = unit_file_query_preset(
+                                 u->manager->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER,
+-                                NULL, basename(u->fragment_path));
++                                NULL,
++                                basename(u->fragment_path));
+ 
+         return u->unit_file_preset;
+ }
+diff --git a/src/dbus1-generator/dbus1-generator.c b/src/dbus1-generator/dbus1-generator.c
+index 2e08af2..c909a4b 100644
+--- a/src/dbus1-generator/dbus1-generator.c
++++ b/src/dbus1-generator/dbus1-generator.c
+@@ -188,7 +188,7 @@ static int add_dbus(const char *path, const char *fname, const char *type) {
+         }
+ 
+         if (service) {
+-                if (!unit_name_is_valid(service, TEMPLATE_INVALID)) {
++                if (!unit_name_is_valid(service, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE)) {
+                         log_warning("Unit name %s is not valid, ignoring.", service);
+                         return 0;
+                 }
+diff --git a/src/firstboot/firstboot.c b/src/firstboot/firstboot.c
+index a37ca17..b77c1d8 100644
+--- a/src/firstboot/firstboot.c
++++ b/src/firstboot/firstboot.c
+@@ -50,8 +50,6 @@ static bool arg_copy_locale = false;
+ static bool arg_copy_timezone = false;
+ static bool arg_copy_root_password = false;
+ 
+-#define prefix_roota(p) (arg_root ? (const char*) strjoina(arg_root, p) : (const char*) p)
+-
+ static void clear_string(char *x) {
+ 
+         if (!x)
+@@ -85,13 +83,13 @@ static void print_welcome(void) {
+         if (done)
+                 return;
+ 
+-        os_release = prefix_roota("/etc/os-release");
++        os_release = prefix_roota(arg_root, "/etc/os-release");
+         r = parse_env_file(os_release, NEWLINE,
+                            "PRETTY_NAME", &pretty_name,
+                            NULL);
+         if (r == -ENOENT) {
+ 
+-                os_release = prefix_roota("/usr/lib/os-release");
++                os_release = prefix_roota(arg_root, "/usr/lib/os-release");
+                 r = parse_env_file(os_release, NEWLINE,
+                                    "PRETTY_NAME", &pretty_name,
+                                    NULL);
+@@ -249,7 +247,7 @@ static int process_locale(void) {
+         unsigned i = 0;
+         int r;
+ 
+-        etc_localeconf = prefix_roota("/etc/locale.conf");
++        etc_localeconf = prefix_roota(arg_root, "/etc/locale.conf");
+         if (faccessat(AT_FDCWD, etc_localeconf, F_OK, AT_SYMLINK_NOFOLLOW) >= 0)
+                 return 0;
+ 
+@@ -323,7 +321,7 @@ static int process_timezone(void) {
+         const char *etc_localtime, *e;
+         int r;
+ 
+-        etc_localtime = prefix_roota("/etc/localtime");
++        etc_localtime = prefix_roota(arg_root, "/etc/localtime");
+         if (faccessat(AT_FDCWD, etc_localtime, F_OK, AT_SYMLINK_NOFOLLOW) >= 0)
+                 return 0;
+ 
+@@ -402,7 +400,7 @@ static int process_hostname(void) {
+         const char *etc_hostname;
+         int r;
+ 
+-        etc_hostname = prefix_roota("/etc/hostname");
++        etc_hostname = prefix_roota(arg_root, "/etc/hostname");
+         if (faccessat(AT_FDCWD, etc_hostname, F_OK, AT_SYMLINK_NOFOLLOW) >= 0)
+                 return 0;
+ 
+@@ -427,7 +425,7 @@ static int process_machine_id(void) {
+         char id[SD_ID128_STRING_MAX];
+         int r;
+ 
+-        etc_machine_id = prefix_roota("/etc/machine-id");
++        etc_machine_id = prefix_roota(arg_root, "/etc/machine-id");
+         if (faccessat(AT_FDCWD, etc_machine_id, F_OK, AT_SYMLINK_NOFOLLOW) >= 0)
+                 return 0;
+ 
+@@ -453,7 +451,7 @@ static int prompt_root_password(void) {
+         if (!arg_prompt_root_password)
+                 return 0;
+ 
+-        etc_shadow = prefix_roota("/etc/shadow");
++        etc_shadow = prefix_roota(arg_root, "/etc/shadow");
+         if (faccessat(AT_FDCWD, etc_shadow, F_OK, AT_SYMLINK_NOFOLLOW) >= 0)
+                 return 0;
+ 
+@@ -542,7 +540,7 @@ static int process_root_password(void) {
+         const char *etc_shadow;
+         int r;
+ 
+-        etc_shadow = prefix_roota("/etc/shadow");
++        etc_shadow = prefix_roota(arg_root, "/etc/shadow");
+         if (faccessat(AT_FDCWD, etc_shadow, F_OK, AT_SYMLINK_NOFOLLOW) >= 0)
+                 return 0;
+ 
+diff --git a/src/shared/cgroup-util.c b/src/shared/cgroup-util.c
+index dfd8689..cf757d2 100644
+--- a/src/shared/cgroup-util.c
++++ b/src/shared/cgroup-util.c
+@@ -1147,7 +1147,7 @@ int cg_path_decode_unit(const char *cgroup, char **unit){
+         c = strndupa(cgroup, e - cgroup);
+         c = cg_unescape(c);
+ 
+-        if (!unit_name_is_valid(c, TEMPLATE_INVALID))
++        if (!unit_name_is_valid(c, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE))
+                 return -EINVAL;
+ 
+         s = strdup(c);
+@@ -1536,7 +1536,7 @@ int cg_slice_to_path(const char *unit, char **ret) {
+         assert(unit);
+         assert(ret);
+ 
+-        if (!unit_name_is_valid(unit, TEMPLATE_INVALID))
++        if (!unit_name_is_valid(unit, UNIT_NAME_PLAIN))
+                 return -EINVAL;
+ 
+         if (!endswith(unit, ".slice"))
+@@ -1553,7 +1553,7 @@ int cg_slice_to_path(const char *unit, char **ret) {
+ 
+                 strcpy(stpncpy(n, p, dash - p), ".slice");
+ 
+-                if (!unit_name_is_valid(n, TEMPLATE_INVALID))
++                if (!unit_name_is_valid(n, UNIT_NAME_PLAIN))
+                         return -EINVAL;
+ 
+                 escaped = cg_escape(n);
+diff --git a/src/shared/install.c b/src/shared/install.c
+index aa197e9..5288bb4 100644
+--- a/src/shared/install.c
++++ b/src/shared/install.c
+@@ -39,15 +39,24 @@
+ #include "specifier.h"
+ #include "install-printf.h"
+ #include "special.h"
++#include "fileio.h"
++
++#define UNIT_FILE_FOLLOW_SYMLINK_MAX 64
++
++typedef enum SearchFlags {
++        SEARCH_LOAD = 1,
++        SEARCH_FOLLOW_CONFIG_SYMLINKS = 2,
++} SearchFlags;
+ 
+ typedef struct {
+-        OrderedHashmap *will_install;
+-        OrderedHashmap *have_installed;
++        OrderedHashmap *will_process;
++        OrderedHashmap *have_processed;
+ } InstallContext;
+ 
+ static int in_search_path(const char *path, char **search) {
+         _cleanup_free_ char *parent = NULL;
+         int r;
++        char **i;
+ 
+         assert(path);
+ 
+@@ -55,7 +64,11 @@ static int in_search_path(const char *path, char **search) {
+         if (r < 0)
+                 return r;
+ 
+-        return strv_contains(search, parent);
++        STRV_FOREACH(i, search)
++                if (path_equal(parent, *i))
++                        return true;
++
++        return false;
+ }
+ 
+ static int get_config_path(UnitFileScope scope, bool runtime, const char *root_dir, char **ret) {
+@@ -66,6 +79,9 @@ static int get_config_path(UnitFileScope scope, bool runtime, const char *root_d
+         assert(scope < _UNIT_FILE_SCOPE_MAX);
+         assert(ret);
+ 
++        /* This determines where we shall create or remove our
++         * installation ("configuration") symlinks */
++
+         switch (scope) {
+ 
+         case UNIT_FILE_SYSTEM:
+@@ -113,6 +129,186 @@ static int get_config_path(UnitFileScope scope, bool runtime, const char *root_d
+         return 0;
+ }
+ 
++static bool is_config_path(UnitFileScope scope, const char *path) {
++        int r;
++
++        assert(scope >= 0);
++        assert(scope < _UNIT_FILE_SCOPE_MAX);
++        assert(path);
++
++        /* Checks whether the specified path is intended for
++         * configuration or is outside of it */
++
++        switch (scope) {
++
++        case UNIT_FILE_SYSTEM:
++        case UNIT_FILE_GLOBAL:
++                return path_startswith(path, "/etc") ||
++                        path_startswith(path, SYSTEM_CONFIG_UNIT_PATH) ||
++                        path_startswith(path, "/run");
++
++
++        case UNIT_FILE_USER: {
++                _cleanup_free_ char *p = NULL;
++
++                r = user_config_home(&p);
++                if (r < 0)
++                        return r;
++                if (r > 0 && path_startswith(path, p))
++                        return true;
++
++                free(p);
++                p = NULL;
++
++                r = user_runtime_dir(&p);
++                if (r < 0)
++                        return r;
++                if (r > 0 && path_startswith(path, p))
++                        return true;
++
++                return false;
++        }
++
++        default:
++                assert_not_reached("Bad scope");
++        }
++}
++
++
++static int verify_root_dir(UnitFileScope scope, const char **root_dir) {
++        int r;
++
++        assert(root_dir);
++
++        /* Verifies that the specified root directory to operate on
++         * makes sense. Reset it to NULL if it is the root directory
++         * or set to empty */
++
++        if (isempty(*root_dir) || path_equal(*root_dir, "/")) {
++                *root_dir = NULL;
++                return 0;
++        }
++
++        if (scope != UNIT_FILE_SYSTEM)
++                return -EINVAL;
++
++        r = is_dir(*root_dir, true);
++        if (r < 0)
++                return r;
++        if (r == 0)
++                return -ENOTDIR;
++
++        return 0;
++}
++
++int unit_file_changes_add(
++                UnitFileChange **changes,
++                unsigned *n_changes,
++                UnitFileChangeType type,
++                const char *path,
++                const char *source) {
++
++        UnitFileChange *c;
++        unsigned i;
++
++        assert(path);
++        assert(!changes == !n_changes);
++
++        if (!changes)
++                return 0;
++
++        c = realloc(*changes, (*n_changes + 1) * sizeof(UnitFileChange));
++        if (!c)
++                return -ENOMEM;
++
++        *changes = c;
++        i = *n_changes;
++
++        c[i].type = type;
++        c[i].path = strdup(path);
++        if (!c[i].path)
++                return -ENOMEM;
++
++        path_kill_slashes(c[i].path);
++
++        if (source) {
++                c[i].source = strdup(source);
++                if (!c[i].source) {
++                        free(c[i].path);
++                        return -ENOMEM;
++                }
++
++                path_kill_slashes(c[i].path);
++        } else
++                c[i].source = NULL;
++
++        *n_changes = i+1;
++        return 0;
++}
++
++void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes) {
++        unsigned i;
++
++        assert(changes || n_changes == 0);
++
++        if (!changes)
++                return;
++
++        for (i = 0; i < n_changes; i++) {
++                free(changes[i].path);
++                free(changes[i].source);
++        }
++
++        free(changes);
++}
++
++static int create_symlink(
++                const char *old_path,
++                const char *new_path,
++                bool force,
++                UnitFileChange **changes,
++                unsigned *n_changes) {
++
++        _cleanup_free_ char *dest = NULL;
++        int r;
++
++        assert(old_path);
++        assert(new_path);
++
++        /* Actually create a symlink, and remember that we did. Is
++         * smart enough to check if there's already a valid symlink in
++         * place. */
++
++        mkdir_parents_label(new_path, 0755);
++
++        if (symlink(old_path, new_path) >= 0) {
++                unit_file_changes_add(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
++                return 0;
++        }
++
++        if (errno != EEXIST)
++                return -errno;
++
++        r = readlink_malloc(new_path, &dest);
++        if (r < 0)
++                return r;
++
++        if (path_equal(dest, old_path))
++                return 0;
++
++        if (!force)
++                return -EEXIST;
++
++        r = symlink_atomic(old_path, new_path);
++        if (r < 0)
++                return r;
++
++        unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, new_path, NULL);
++        unit_file_changes_add(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
++
++        return 0;
++}
++
+ static int mark_symlink_for_removal(
+                 Set **remove_symlinks_to,
+                 const char *p) {
+@@ -136,7 +332,7 @@ static int mark_symlink_for_removal(
+         if (r < 0)
+                 return r == -EEXIST ? 0 : r;
+ 
+-        return 0;
++        return 1;
+ }
+ 
+ static int remove_marked_symlinks_fd(
+@@ -144,10 +340,9 @@ static int remove_marked_symlinks_fd(
+                 int fd,
+                 const char *path,
+                 const char *config_path,
+-                bool *deleted,
++                bool *restart,
+                 UnitFileChange **changes,
+-                unsigned *n_changes,
+-                char** instance_whitelist) {
++                unsigned *n_changes) {
+ 
+         _cleanup_closedir_ DIR *d = NULL;
+         int r = 0;
+@@ -156,7 +351,7 @@ static int remove_marked_symlinks_fd(
+         assert(fd >= 0);
+         assert(path);
+         assert(config_path);
+-        assert(deleted);
++        assert(restart);
+ 
+         d = fdopendir(fd);
+         if (!d) {
+@@ -205,42 +400,23 @@ static int remove_marked_symlinks_fd(
+                         }
+ 
+                         /* This will close nfd, regardless whether it succeeds or not */
+-                        q = remove_marked_symlinks_fd(remove_symlinks_to, nfd, p, config_path, deleted, changes, n_changes, instance_whitelist);
++                        q = remove_marked_symlinks_fd(remove_symlinks_to, nfd, p, config_path, restart, changes, n_changes);
+                         if (q < 0 && r == 0)
+                                 r = q;
+ 
+                 } else if (de->d_type == DT_LNK) {
+                         _cleanup_free_ char *p = NULL, *dest = NULL;
+-                        int q;
+                         bool found;
++                        int q;
+ 
+-                        if (!unit_name_is_valid(de->d_name, TEMPLATE_VALID))
++                        if (!unit_name_is_valid(de->d_name, UNIT_NAME_ANY))
+                                 continue;
+ 
+-                        if (unit_name_is_instance(de->d_name) &&
+-                            instance_whitelist &&
+-                            !strv_contains(instance_whitelist, de->d_name)) {
+-
+-                                _cleanup_free_ char *w;
+-
+-                                /* OK, the file is not listed directly
+-                                 * in the whitelist, so let's check if
+-                                 * the template of it might be
+-                                 * listed. */
+-
+-                                w = unit_name_template(de->d_name);
+-                                if (!w)
+-                                        return -ENOMEM;
+-
+-                                if (!strv_contains(instance_whitelist, w))
+-                                        continue;
+-                        }
+-
+                         p = path_make_absolute(de->d_name, path);
+                         if (!p)
+                                 return -ENOMEM;
+ 
+-                        q = readlink_and_canonicalize(p, &dest);
++                        q = readlink_malloc(p, &dest);
+                         if (q < 0) {
+                                 if (q == -ENOENT)
+                                         continue;
+@@ -250,9 +426,15 @@ static int remove_marked_symlinks_fd(
+                                 continue;
+                         }
+ 
++                        /* We remove all links pointing to a file or
++                         * path that is marked, as well as all files
++                         * sharing the same name as a file that is
++                         * marked. */
++
+                         found =
+-                                set_get(remove_symlinks_to, dest) ||
+-                                set_get(remove_symlinks_to, basename(dest));
++                                set_contains(remove_symlinks_to, dest) ||
++                                set_contains(remove_symlinks_to, basename(dest)) ||
++                                set_contains(remove_symlinks_to, de->d_name);
+ 
+                         if (!found)
+                                 continue;
+@@ -264,18 +446,15 @@ static int remove_marked_symlinks_fd(
+                         }
+ 
+                         path_kill_slashes(p);
+-                        rmdir_parents(p, config_path);
+-                        unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, p, NULL);
++                        (void) rmdir_parents(p, config_path);
+ 
+-                        if (!set_get(remove_symlinks_to, p)) {
++                        unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, p, NULL);
+ 
+-                                q = mark_symlink_for_removal(&remove_symlinks_to, p);
+-                                if (q < 0) {
+-                                        if (r == 0)
+-                                                r = q;
+-                                } else
+-                                        *deleted = true;
+-                        }
++                        q = mark_symlink_for_removal(&remove_symlinks_to, p);
++                        if (q < 0)
++                                return q;
++                        if (q > 0)
++                                *restart = true;
+                 }
+         }
+ 
+@@ -286,12 +465,11 @@ static int remove_marked_symlinks(
+                 Set *remove_symlinks_to,
+                 const char *config_path,
+                 UnitFileChange **changes,
+-                unsigned *n_changes,
+-                char** instance_whitelist) {
++                unsigned *n_changes) {
+ 
+         _cleanup_close_ int fd = -1;
+         int r = 0;
+-        bool deleted;
++        bool restart;
+ 
+         assert(config_path);
+ 
+@@ -304,7 +482,7 @@ static int remove_marked_symlinks(
+ 
+         do {
+                 int q, cfd;
+-                deleted = false;
++                restart = false;
+ 
+                 cfd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
+                 if (cfd < 0) {
+@@ -313,15 +491,16 @@ static int remove_marked_symlinks(
+                 }
+ 
+                 /* This takes possession of cfd and closes it */
+-                q = remove_marked_symlinks_fd(remove_symlinks_to, cfd, config_path, config_path, &deleted, changes, n_changes, instance_whitelist);
++                q = remove_marked_symlinks_fd(remove_symlinks_to, cfd, config_path, config_path, &restart, changes, n_changes);
+                 if (r == 0)
+                         r = q;
+-        } while (deleted);
++        } while (restart);
+ 
+         return r;
+ }
+ 
+ static int find_symlinks_fd(
++                const char *root_dir,
+                 const char *name,
+                 int fd,
+                 const char *path,
+@@ -380,7 +559,7 @@ static int find_symlinks_fd(
+                         }
+ 
+                         /* This will close nfd, regardless whether it succeeds or not */
+-                        q = find_symlinks_fd(name, nfd, p, config_path, same_name_link);
++                        q = find_symlinks_fd(root_dir, name, nfd, p, config_path, same_name_link);
+                         if (q > 0)
+                                 return 1;
+                         if (r == 0)
+@@ -397,7 +576,7 @@ static int find_symlinks_fd(
+                                 return -ENOMEM;
+ 
+                         /* Acquire symlink destination */
+-                        q = readlink_and_canonicalize(p, &dest);
++                        q = readlink_malloc(p, &dest);
+                         if (q < 0) {
+                                 if (q == -ENOENT)
+                                         continue;
+@@ -407,6 +586,18 @@ static int find_symlinks_fd(
+                                 continue;
+                         }
+ 
++                        /* Make absolute */
++                        if (!path_is_absolute(dest)) {
++                                char *x;
++
++                                x = prefix_root(root_dir, dest);
++                                if (!x)
++                                        return -ENOMEM;
++
++                                free(dest);
++                                dest = x;
++                        }
++
+                         /* Check if the symlink itself matches what we
+                          * are looking for */
+                         if (path_is_absolute(name))
+@@ -442,6 +633,7 @@ static int find_symlinks_fd(
+ }
+ 
+ static int find_symlinks(
++                const char *root_dir,
+                 const char *name,
+                 const char *config_path,
+                 bool *same_name_link) {
+@@ -460,7 +652,7 @@ static int find_symlinks(
+         }
+ 
+         /* This takes possession of fd and closes it */
+-        return find_symlinks_fd(name, fd, config_path, config_path, same_name_link);
++        return find_symlinks_fd(root_dir, name, fd, config_path, config_path, same_name_link);
+ }
+ 
+ static int find_symlinks_in_scope(
+@@ -469,385 +661,104 @@ static int find_symlinks_in_scope(
+                 const char *name,
+                 UnitFileState *state) {
+ 
+-        int r;
+         _cleanup_free_ char *normal_path = NULL, *runtime_path = NULL;
+         bool same_name_link_runtime = false, same_name_link = false;
++        int r;
+ 
+         assert(scope >= 0);
+         assert(scope < _UNIT_FILE_SCOPE_MAX);
+         assert(name);
+ 
+-        /* First look in runtime config path */
+-        r = get_config_path(scope, true, root_dir, &normal_path);
++        /* First look in the normal config path */
++        r = get_config_path(scope, false, root_dir, &normal_path);
+         if (r < 0)
+                 return r;
+ 
+-        r = find_symlinks(name, normal_path, &same_name_link_runtime);
++        r = find_symlinks(root_dir, name, normal_path, &same_name_link);
+         if (r < 0)
+                 return r;
+-        else if (r > 0) {
+-                *state = UNIT_FILE_ENABLED_RUNTIME;
++        if (r > 0) {
++                *state = UNIT_FILE_ENABLED;
+                 return r;
+         }
+ 
+-        /* Then look in the normal config path */
+-        r = get_config_path(scope, false, root_dir, &runtime_path);
++        /* Then look in runtime config path */
++        r = get_config_path(scope, true, root_dir, &runtime_path);
+         if (r < 0)
+                 return r;
+ 
+-        r = find_symlinks(name, runtime_path, &same_name_link);
++        r = find_symlinks(root_dir, name, runtime_path, &same_name_link_runtime);
+         if (r < 0)
+                 return r;
+-        else if (r > 0) {
+-                *state = UNIT_FILE_ENABLED;
++        if (r > 0) {
++                *state = UNIT_FILE_ENABLED_RUNTIME;
+                 return r;
+         }
+ 
+         /* Hmm, we didn't find it, but maybe we found the same name
+          * link? */
++        if (same_name_link) {
++                *state = UNIT_FILE_LINKED;
++                return 1;
++        }
+         if (same_name_link_runtime) {
+                 *state = UNIT_FILE_LINKED_RUNTIME;
+                 return 1;
+-        } else if (same_name_link) {
+-                *state = UNIT_FILE_LINKED;
+-                return 1;
+         }
+ 
+         return 0;
+ }
+ 
+-int unit_file_mask(
+-                UnitFileScope scope,
+-                bool runtime,
+-                const char *root_dir,
+-                char **files,
+-                bool force,
+-                UnitFileChange **changes,
+-                unsigned *n_changes) {
+-
+-        char **i;
+-        _cleanup_free_ char *prefix = NULL;
+-        int r;
++static void install_info_free(InstallInfo *i) {
+ 
+-        assert(scope >= 0);
+-        assert(scope < _UNIT_FILE_SCOPE_MAX);
++        if (!i)
++                return;
+ 
+-        r = get_config_path(scope, runtime, root_dir, &prefix);
+-        if (r < 0)
+-                return r;
++        free(i->name);
++        free(i->path);
++        strv_free(i->aliases);
++        strv_free(i->wanted_by);
++        strv_free(i->required_by);
++        strv_free(i->also);
++        free(i->default_instance);
++        free(i->symlink_target);
++        free(i);
++}
+ 
+-        STRV_FOREACH(i, files) {
+-                _cleanup_free_ char *path = NULL;
++static OrderedHashmap* install_info_hashmap_free(OrderedHashmap *m) {
++        InstallInfo *i;
+ 
+-                if (!unit_name_is_valid(*i, TEMPLATE_VALID)) {
+-                        if (r == 0)
+-                                r = -EINVAL;
+-                        continue;
+-                }
++        while ((i = ordered_hashmap_steal_first(m)))
++                install_info_free(i);
+ 
+-                path = path_make_absolute(*i, prefix);
+-                if (!path) {
+-                        r = -ENOMEM;
+-                        break;
+-                }
++        ordered_hashmap_free(m);
+ 
+-                if (symlink("/dev/null", path) >= 0) {
+-                        unit_file_changes_add(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
+-                        continue;
+-                }
++        return NULL;
++}
+ 
+-                if (errno == EEXIST) {
++static void install_context_done(InstallContext *c) {
++        assert(c);
+ 
+-                        if (null_or_empty_path(path) > 0)
+-                                continue;
++        c->will_process = install_info_hashmap_free(c->will_process);
++        c->have_processed = install_info_hashmap_free(c->have_processed);
++}
+ 
+-                        if (force) {
+-                                if (symlink_atomic("/dev/null", path) >= 0) {
+-                                        unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
+-                                        unit_file_changes_add(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
+-                                        continue;
+-                                }
+-                        }
++static InstallInfo *install_info_find(InstallContext *c, const char *name) {
++        InstallInfo *i;
+ 
+-                        if (r == 0)
+-                                r = -EEXIST;
+-                } else {
+-                        if (r == 0)
+-                                r = -errno;
+-                }
+-        }
++        i = ordered_hashmap_get(c->have_processed, name);
++        if (i)
++                return i;
+ 
+-        return r;
+-}
+-
+-int unit_file_unmask(
+-                UnitFileScope scope,
+-                bool runtime,
+-                const char *root_dir,
+-                char **files,
+-                UnitFileChange **changes,
+-                unsigned *n_changes) {
+-
+-        char **i, *config_path = NULL;
+-        int r, q;
+-        Set *remove_symlinks_to = NULL;
+-
+-        assert(scope >= 0);
+-        assert(scope < _UNIT_FILE_SCOPE_MAX);
+-
+-        r = get_config_path(scope, runtime, root_dir, &config_path);
+-        if (r < 0)
+-                goto finish;
+-
+-        STRV_FOREACH(i, files) {
+-                _cleanup_free_ char *path = NULL;
+-
+-                if (!unit_name_is_valid(*i, TEMPLATE_VALID)) {
+-                        if (r == 0)
+-                                r = -EINVAL;
+-                        continue;
+-                }
+-
+-                path = path_make_absolute(*i, config_path);
+-                if (!path) {
+-                        r = -ENOMEM;
+-                        break;
+-                }
+-
+-                q = null_or_empty_path(path);
+-                if (q > 0) {
+-                        if (unlink(path) < 0)
+-                                q = -errno;
+-                        else {
+-                                q = mark_symlink_for_removal(&remove_symlinks_to, path);
+-                                unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
+-                        }
+-                }
+-
+-                if (q != -ENOENT && r == 0)
+-                        r = q;
+-        }
+-
+-
+-finish:
+-        q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
+-        if (r == 0)
+-                r = q;
+-
+-        set_free_free(remove_symlinks_to);
+-        free(config_path);
+-
+-        return r;
+-}
+-
+-int unit_file_link(
+-                UnitFileScope scope,
+-                bool runtime,
+-                const char *root_dir,
+-                char **files,
+-                bool force,
+-                UnitFileChange **changes,
+-                unsigned *n_changes) {
+-
+-        _cleanup_lookup_paths_free_ LookupPaths paths = {};
+-        char **i;
+-        _cleanup_free_ char *config_path = NULL;
+-        int r, q;
+-
+-        assert(scope >= 0);
+-        assert(scope < _UNIT_FILE_SCOPE_MAX);
+-
+-        r = lookup_paths_init_from_scope(&paths, scope, root_dir);
+-        if (r < 0)
+-                return r;
+-
+-        r = get_config_path(scope, runtime, root_dir, &config_path);
+-        if (r < 0)
+-                return r;
+-
+-        STRV_FOREACH(i, files) {
+-                _cleanup_free_ char *path = NULL;
+-                char *fn;
+-                struct stat st;
+-
+-                fn = basename(*i);
+-
+-                if (!path_is_absolute(*i) ||
+-                    !unit_name_is_valid(fn, TEMPLATE_VALID)) {
+-                        if (r == 0)
+-                                r = -EINVAL;
+-                        continue;
+-                }
+-
+-                if (lstat(*i, &st) < 0) {
+-                        if (r == 0)
+-                                r = -errno;
+-                        continue;
+-                }
+-
+-                if (!S_ISREG(st.st_mode)) {
+-                        r = -ENOENT;
+-                        continue;
+-                }
+-
+-                q = in_search_path(*i, paths.unit_path);
+-                if (q < 0)
+-                        return q;
+-
+-                if (q > 0)
+-                        continue;
+-
+-                path = path_make_absolute(fn, config_path);
+-                if (!path)
+-                        return -ENOMEM;
+-
+-                if (symlink(*i, path) >= 0) {
+-                        unit_file_changes_add(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
+-                        continue;
+-                }
+-
+-                if (errno == EEXIST) {
+-                        _cleanup_free_ char *dest = NULL;
+-
+-                        q = readlink_and_make_absolute(path, &dest);
+-                        if (q < 0 && errno != ENOENT) {
+-                                if (r == 0)
+-                                        r = q;
+-                                continue;
+-                        }
+-
+-                        if (q >= 0 && path_equal(dest, *i))
+-                                continue;
+-
+-                        if (force) {
+-                                if (symlink_atomic(*i, path) >= 0) {
+-                                        unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
+-                                        unit_file_changes_add(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
+-                                        continue;
+-                                }
+-                        }
+-
+-                        if (r == 0)
+-                                r = -EEXIST;
+-                } else {
+-                        if (r == 0)
+-                                r = -errno;
+-                }
+-        }
+-
+-        return r;
+-}
+-
+-void unit_file_list_free(Hashmap *h) {
+-        UnitFileList *i;
+-
+-        while ((i = hashmap_steal_first(h))) {
+-                free(i->path);
+-                free(i);
+-        }
+-
+-        hashmap_free(h);
+-}
+-
+-int unit_file_changes_add(
+-                UnitFileChange **changes,
+-                unsigned *n_changes,
+-                UnitFileChangeType type,
+-                const char *path,
+-                const char *source) {
+-
+-        UnitFileChange *c;
+-        unsigned i;
+-
+-        assert(path);
+-        assert(!changes == !n_changes);
+-
+-        if (!changes)
+-                return 0;
+-
+-        c = realloc(*changes, (*n_changes + 1) * sizeof(UnitFileChange));
+-        if (!c)
+-                return -ENOMEM;
+-
+-        *changes = c;
+-        i = *n_changes;
+-
+-        c[i].type = type;
+-        c[i].path = strdup(path);
+-        if (!c[i].path)
+-                return -ENOMEM;
+-
+-        path_kill_slashes(c[i].path);
+-
+-        if (source) {
+-                c[i].source = strdup(source);
+-                if (!c[i].source) {
+-                        free(c[i].path);
+-                        return -ENOMEM;
+-                }
+-
+-                path_kill_slashes(c[i].path);
+-        } else
+-                c[i].source = NULL;
+-
+-        *n_changes = i+1;
+-        return 0;
+-}
+-
+-void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes) {
+-        unsigned i;
+-
+-        assert(changes || n_changes == 0);
+-
+-        if (!changes)
+-                return;
+-
+-        for (i = 0; i < n_changes; i++) {
+-                free(changes[i].path);
+-                free(changes[i].source);
+-        }
+-
+-        free(changes);
+-}
+-
+-static void install_info_free(InstallInfo *i) {
+-        assert(i);
+-
+-        free(i->name);
+-        free(i->path);
+-        strv_free(i->aliases);
+-        strv_free(i->wanted_by);
+-        strv_free(i->required_by);
+-        strv_free(i->also);
+-        free(i->default_instance);
+-        free(i);
+-}
+-
+-static void install_info_hashmap_free(OrderedHashmap *m) {
+-        InstallInfo *i;
+-
+-        if (!m)
+-                return;
+-
+-        while ((i = ordered_hashmap_steal_first(m)))
+-                install_info_free(i);
+-
+-        ordered_hashmap_free(m);
+-}
+-
+-static void install_context_done(InstallContext *c) {
+-        assert(c);
+-
+-        install_info_hashmap_free(c->will_install);
+-        install_info_hashmap_free(c->have_installed);
+-
+-        c->will_install = c->have_installed = NULL;
++        return ordered_hashmap_get(c->will_process, name);
+ }
+ 
+ static int install_info_add(
+                 InstallContext *c,
+                 const char *name,
+-                const char *path) {
++                const char *path,
++                InstallInfo **ret) {
++
+         InstallInfo *i = NULL;
+         int r;
+ 
+@@ -857,20 +768,24 @@ static int install_info_add(
+         if (!name)
+                 name = basename(path);
+ 
+-        if (!unit_name_is_valid(name, TEMPLATE_VALID))
++        if (!unit_name_is_valid(name, UNIT_NAME_ANY))
+                 return -EINVAL;
+ 
+-        if (ordered_hashmap_get(c->have_installed, name) ||
+-            ordered_hashmap_get(c->will_install, name))
++        i = install_info_find(c, name);
++        if (i) {
++                if (ret)
++                        *ret = i;
+                 return 0;
++        }
+ 
+-        r = ordered_hashmap_ensure_allocated(&c->will_install, &string_hash_ops);
++        r = ordered_hashmap_ensure_allocated(&c->will_process, &string_hash_ops);
+         if (r < 0)
+                 return r;
+ 
+         i = new0(InstallInfo, 1);
+         if (!i)
+                 return -ENOMEM;
++        i->type = _UNIT_FILE_TYPE_INVALID;
+ 
+         i->name = strdup(name);
+         if (!i->name) {
+@@ -886,10 +801,13 @@ static int install_info_add(
+                 }
+         }
+ 
+-        r = ordered_hashmap_put(c->will_install, i->name, i);
++        r = ordered_hashmap_put(c->will_process, i->name, i);
+         if (r < 0)
+                 goto fail;
+ 
++        if (ret)
++                *ret = i;
++
+         return 0;
+ 
+ fail:
+@@ -901,15 +819,16 @@ fail:
+ 
+ static int install_info_add_auto(
+                 InstallContext *c,
+-                const char *name_or_path) {
++                const char *name_or_path,
++                InstallInfo **ret) {
+ 
+         assert(c);
+         assert(name_or_path);
+ 
+         if (path_is_absolute(name_or_path))
+-                return install_info_add(c, NULL, name_or_path);
++                return install_info_add(c, NULL, name_or_path, ret);
+         else
+-                return install_info_add(c, name_or_path, NULL);
++                return install_info_add(c, name_or_path, NULL, ret);
+ }
+ 
+ static int config_parse_also(
+@@ -928,6 +847,7 @@ static int config_parse_also(
+         const char *word, *state;
+         InstallContext *c = data;
+         InstallInfo *i = userdata;
++        int r;
+ 
+         assert(filename);
+         assert(lvalue);
+@@ -935,19 +855,20 @@ static int config_parse_also(
+ 
+         FOREACH_WORD_QUOTED(word, l, rvalue, state) {
+                 _cleanup_free_ char *n;
+-                int r;
+ 
+                 n = strndup(word, l);
+                 if (!n)
+                         return -ENOMEM;
+ 
+-                r = install_info_add(c, n, NULL);
++                r = install_info_add(c, n, NULL, NULL);
+                 if (r < 0)
+                         return r;
+ 
+-                r = strv_extend(&i->also, n);
++                r = strv_push(&i->also, n);
+                 if (r < 0)
+                         return r;
++
++                n = NULL;
+         }
+         if (!isempty(state))
+                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
+@@ -1026,9 +947,7 @@ static int unit_file_load(
+                 InstallInfo *info,
+                 const char *path,
+                 const char *root_dir,
+-                bool allow_symlink,
+-                bool load,
+-                bool *also) {
++                SearchFlags flags) {
+ 
+         const ConfigTableItem items[] = {
+                 { "Install", "Alias",           config_parse_strv,             0, &info->aliases           },
+@@ -1041,7 +960,9 @@ static int unit_file_load(
+         };
+ 
+         _cleanup_fclose_ FILE *f = NULL;
+-        int fd, r;
++        _cleanup_close_ int fd = -1;
++        struct stat st;
++        int r;
+ 
+         assert(c);
+         assert(info);
+@@ -1050,20 +971,43 @@ static int unit_file_load(
+         if (!isempty(root_dir))
+                 path = strjoina(root_dir, "/", path);
+ 
+-        if (!load) {
+-                r = access(path, F_OK) ? -errno : 0;
+-                return r;
++        if (!(flags & SEARCH_LOAD)) {
++                r = lstat(path, &st);
++                if (r < 0)
++                        return -errno;
++
++                if (null_or_empty(&st))
++                        info->type = UNIT_FILE_TYPE_MASKED;
++                else if (S_ISREG(st.st_mode))
++                        info->type = UNIT_FILE_TYPE_REGULAR;
++                else if (S_ISLNK(st.st_mode))
++                        return -ELOOP;
++                else if (S_ISDIR(st.st_mode))
++                        return -EISDIR;
++                else
++                        return -ENOTTY;
++
++                return 0;
+         }
+ 
+-        fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|(allow_symlink ? 0 : O_NOFOLLOW));
++        fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
+         if (fd < 0)
+                 return -errno;
++        if (fstat(fd, &st) < 0)
++                return -errno;
++        if (null_or_empty(&st)) {
++               info->type = UNIT_FILE_MASKED;
++                return 0;
++        }
++        if (S_ISDIR(st.st_mode))
++                return -EISDIR;
++        if (!S_ISREG(st.st_mode))
++                return -ENOTTY;
+ 
+         f = fdopen(fd, "re");
+-        if (!f) {
+-                safe_close(fd);
+-                return -ENOMEM;
+-        }
++        if (!f)
++                return -errno;
++        fd = -1;
+ 
+         r = config_parse(NULL, path, f,
+                          NULL,
+@@ -1072,8 +1016,7 @@ static int unit_file_load(
+         if (r < 0)
+                 return r;
+ 
+-        if (also)
+-                *also = !strv_isempty(info->also);
++        info->type = UNIT_FILE_TYPE_REGULAR;
+ 
+         return
+                 (int) strv_length(info->aliases) +
+@@ -1081,14 +1024,73 @@ static int unit_file_load(
+                 (int) strv_length(info->required_by);
+ }
+ 
++static int unit_file_load_or_readlink(
++                InstallContext *c,
++                InstallInfo *info,
++                const char *path,
++                const char *root_dir,
++                SearchFlags flags) {
++
++        _cleanup_free_ char *np = NULL;
++        int r;
++
++        r = unit_file_load(c, info, path, root_dir, flags);
++        if (r != -ELOOP)
++                return r;
++
++        /* This is a symlink, let's read it. */
++
++        r = readlink_and_make_absolute_root(root_dir, path, &np);
++        if (r < 0)
++                return r;
++
++        if (path_equal(np, "/dev/null"))
++                info->type = UNIT_FILE_TYPE_MASKED;
++        else {
++                const char *bn;
++                UnitType a, b;
++
++                bn = basename(np);
++
++                if (unit_name_is_valid(info->name, UNIT_NAME_PLAIN)) {
++
++                        if (!unit_name_is_valid(bn, UNIT_NAME_PLAIN))
++                                return -EINVAL;
++
++                } else if (unit_name_is_valid(info->name, UNIT_NAME_INSTANCE)) {
++
++                        if (!unit_name_is_valid(bn, UNIT_NAME_INSTANCE|UNIT_NAME_TEMPLATE))
++                                return -EINVAL;
++
++                } else if (unit_name_is_valid(info->name, UNIT_NAME_TEMPLATE)) {
++
++                        if (!unit_name_is_valid(bn, UNIT_NAME_TEMPLATE))
++                                return -EINVAL;
++                } else
++                        return -EINVAL;
++
++                /* Enforce that the symlink destination does not
++                 * change the unit file type. */
++
++                a = unit_name_to_type(info->name);
++                b = unit_name_to_type(bn);
++                if (a < 0 || b < 0 || a != b)
++                        return -EINVAL;
++
++                info->type = UNIT_FILE_TYPE_SYMLINK;
++                info->symlink_target = np;
++                np = NULL;
++        }
++
++        return 0;
++}
++
+ static int unit_file_search(
+                 InstallContext *c,
+                 InstallInfo *info,
+                 const LookupPaths *paths,
+                 const char *root_dir,
+-                bool allow_symlink,
+-                bool load,
+-                bool *also) {
++                SearchFlags flags) {
+ 
+         char **p;
+         int r;
+@@ -1097,8 +1099,12 @@ static int unit_file_search(
+         assert(info);
+         assert(paths);
+ 
++        /* Was this unit already loaded? */
++        if (info->type != _UNIT_FILE_TYPE_INVALID)
++                return 0;
++
+         if (info->path)
+-                return unit_file_load(c, info, info->path, root_dir, allow_symlink, load, also);
++                return unit_file_load_or_readlink(c, info, info->path, root_dir, flags);
+ 
+         assert(info->name);
+ 
+@@ -1109,14 +1115,15 @@ static int unit_file_search(
+                 if (!path)
+                         return -ENOMEM;
+ 
+-                r = unit_file_load(c, info, path, root_dir, allow_symlink, load, also);
+-                if (r >= 0) {
++                r = unit_file_load_or_readlink(c, info, path, root_dir, flags);
++                if (r < 0) {
++                        if (r != -ENOENT)
++                                return r;
++                } else {
+                         info->path = path;
+                         path = NULL;
+                         return r;
+                 }
+-                if (r != -ENOENT && r != -ELOOP)
+-                        return r;
+         }
+ 
+         if (unit_name_is_instance(info->name)) {
+@@ -1138,92 +1145,149 @@ static int unit_file_search(
+                         if (!path)
+                                 return -ENOMEM;
+ 
+-                        r = unit_file_load(c, info, path, root_dir, allow_symlink, load, also);
+-                        if (r >= 0) {
++                        r = unit_file_load_or_readlink(c, info, path, root_dir, flags);
++                        if (r < 0) {
++                                if (r != -ENOENT)
++                                        return r;
++                        } else {
+                                 info->path = path;
+                                 path = NULL;
+                                 return r;
+                         }
+-                        if (r != -ENOENT && r != -ELOOP)
+-                                return r;
+                 }
+         }
+ 
+         return -ENOENT;
+ }
+ 
+-static int unit_file_can_install(
+-                const LookupPaths *paths,
++static int install_info_follow(
++                InstallContext *c,
++                InstallInfo *i,
+                 const char *root_dir,
+-                const char *name,
+-                bool allow_symlink,
+-                bool *also) {
++                SearchFlags flags) {
++
++        assert(c);
++        assert(i);
++
++        if (i->type != UNIT_FILE_TYPE_SYMLINK)
++                return -EINVAL;
++        if (!i->symlink_target)
++                return -EINVAL;
++
++        /* If the basename doesn't match, the caller should add a
++         * complete new entry for this. */
++
++        if (!streq(basename(i->symlink_target), i->name))
++                return -EXDEV;
++
++        free(i->path);
++        i->path = i->symlink_target;
++        i->symlink_target = NULL;
++        i->type = _UNIT_FILE_TYPE_INVALID;
++
++        return unit_file_load_or_readlink(c, i, i->path, root_dir, flags);
++}
++
++static int install_info_traverse(
++                UnitFileScope scope,
++                InstallContext *c,
++                const char *root_dir,
++                const LookupPaths *paths,
++                InstallInfo *start,
++                SearchFlags flags,
++                InstallInfo **ret) {
+ 
+-        _cleanup_(install_context_done) InstallContext c = {};
+         InstallInfo *i;
++        unsigned k = 0;
+         int r;
+ 
+         assert(paths);
+-        assert(name);
++        assert(start);
++        assert(c);
+ 
+-        r = install_info_add_auto(&c, name);
++        r = unit_file_search(c, start, paths, root_dir, flags);
+         if (r < 0)
+                 return r;
+ 
+-        assert_se(i = ordered_hashmap_first(c.will_install));
++        i = start;
++        while (i->type == UNIT_FILE_TYPE_SYMLINK) {
++                /* Follow the symlink */
+ 
+-        r = unit_file_search(&c, i, paths, root_dir, allow_symlink, true, also);
++                if (++k > UNIT_FILE_FOLLOW_SYMLINK_MAX)
++                        return -ELOOP;
+ 
+-        if (r >= 0)
+-                r =
+-                        (int) strv_length(i->aliases) +
+-                        (int) strv_length(i->wanted_by) +
+-                        (int) strv_length(i->required_by);
++                if (!(flags & SEARCH_FOLLOW_CONFIG_SYMLINKS) && is_config_path(scope, i->path))
++                        return -ELOOP;
+ 
+-        return r;
+-}
++                r = install_info_follow(c, i, root_dir, flags);
++                if (r < 0) {
++                        _cleanup_free_ char *buffer = NULL;
++                        const char *bn;
+ 
+-static int create_symlink(
+-                const char *old_path,
+-                const char *new_path,
+-                bool force,
+-                UnitFileChange **changes,
+-                unsigned *n_changes) {
++                        if (r != -EXDEV)
++                                return r;
+ 
+-        _cleanup_free_ char *dest = NULL;
+-        int r;
++                        /* Target has a different name, create a new
++                         * install info object for that, and continue
++                         * with that. */
+ 
+-        assert(old_path);
+-        assert(new_path);
++                        bn = basename(i->symlink_target);
+ 
+-        mkdir_parents_label(new_path, 0755);
++                        if (unit_name_is_valid(i->name, UNIT_NAME_INSTANCE) &&
++                            unit_name_is_valid(bn, UNIT_NAME_TEMPLATE)) {
+ 
+-        if (symlink(old_path, new_path) >= 0) {
+-                unit_file_changes_add(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
+-                return 0;
++                                _cleanup_free_ char *instance = NULL;
++
++                                r = unit_name_to_instance(i->name, &instance);
++                                if (r < 0)
++                                        return r;
++
++                                buffer = unit_name_replace_instance(bn, instance);
++                                if (!buffer)
++                                        return -ENOMEM;
++
++                                bn = buffer;
++                        }
++
++                        r = install_info_add(c, bn, NULL, &i);
++                        if (r < 0)
++                                return r;
++
++                        r = unit_file_search(c, i, paths, root_dir, flags);
++                        if (r < 0)
++                                return r;
++                }
++
++                /* Try again, with the new target we found. */
+         }
+ 
+-        if (errno != EEXIST)
+-                return -errno;
++        if (ret)
++                *ret = i;
+ 
+-        r = readlink_and_make_absolute(new_path, &dest);
+-        if (r < 0)
+-                return r;
++        return 0;
++}
++
++static int install_info_discover(
++                UnitFileScope scope,
++                InstallContext *c,
++                const char *root_dir,
++                const LookupPaths *paths,
++                const char *name,
++                SearchFlags flags,
++                InstallInfo **ret) {
+ 
+-        if (path_equal(dest, old_path))
+-                return 0;
++        InstallInfo *i;
++        int r;
+ 
+-        if (!force)
+-                return -EEXIST;
++        assert(c);
++        assert(paths);
++        assert(name);
+ 
+-        r = symlink_atomic(old_path, new_path);
++        r = install_info_add_auto(c, name, &i);
+         if (r < 0)
+                 return r;
+ 
+-        unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, new_path, NULL);
+-        unit_file_changes_add(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
+-
+-        return 0;
++        return install_info_traverse(scope, c, root_dir, paths, i, flags, ret);
+ }
+ 
+ static int install_info_symlink_alias(
+@@ -1298,7 +1362,7 @@ static int install_info_symlink_wants(
+                 if (q < 0)
+                         return q;
+ 
+-                if (!unit_name_is_valid(dst, TEMPLATE_VALID)) {
++                if (!unit_name_is_valid(dst, UNIT_NAME_ANY)) {
+                         r = -EINVAL;
+                         continue;
+                 }
+@@ -1358,6 +1422,9 @@ static int install_info_apply(
+         assert(paths);
+         assert(config_path);
+ 
++        if (i->type != UNIT_FILE_TYPE_REGULAR)
++                return 0;
++
+         r = install_info_symlink_alias(i, config_path, force, changes, n_changes);
+ 
+         q = install_info_symlink_wants(i, config_path, i->wanted_by, ".wants/", force, changes, n_changes);
+@@ -1376,53 +1443,59 @@ static int install_info_apply(
+ }
+ 
+ static int install_context_apply(
++                UnitFileScope scope,
+                 InstallContext *c,
+                 const LookupPaths *paths,
+                 const char *config_path,
+                 const char *root_dir,
+                 bool force,
++                SearchFlags flags,
+                 UnitFileChange **changes,
+                 unsigned *n_changes) {
+ 
+         InstallInfo *i;
+-        int r, q;
++        int r;
+ 
+         assert(c);
+         assert(paths);
+         assert(config_path);
+ 
+-        if (!ordered_hashmap_isempty(c->will_install)) {
+-                r = ordered_hashmap_ensure_allocated(&c->have_installed, &string_hash_ops);
+-                if (r < 0)
+-                        return r;
++        if (ordered_hashmap_isempty(c->will_process))
++                return 0;
+ 
+-                r = ordered_hashmap_reserve(c->have_installed, ordered_hashmap_size(c->will_install));
+-                if (r < 0)
+-                        return r;
+-        }
++        r = ordered_hashmap_ensure_allocated(&c->have_processed, &string_hash_ops);
++        if (r < 0)
++                return r;
+ 
+         r = 0;
+-        while ((i = ordered_hashmap_first(c->will_install))) {
+-                assert_se(ordered_hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
++        while ((i = ordered_hashmap_first(c->will_process))) {
++                int q;
+ 
+-                q = unit_file_search(c, i, paths, root_dir, false, true, NULL);
+-                if (q < 0) {
+-                        if (r >= 0)
+-                                r = q;
++                q = ordered_hashmap_move_one(c->have_processed, c->will_process, i->name);
++                if (q < 0)
++                        return q;
+ 
++                r = install_info_traverse(scope, c, root_dir, paths, i, flags, NULL);
++                if (r < 0)
+                         return r;
+-                } else if (r >= 0)
+-                        r += q;
++
++                if (i->type != UNIT_FILE_TYPE_REGULAR)
++                        continue;
+ 
+                 q = install_info_apply(i, paths, config_path, root_dir, force, changes, n_changes);
+-                if (r >= 0 && q < 0)
+-                        r = q;
++                if (r >= 0) {
++                        if (q < 0)
++                                r = q;
++                        else
++                                r+= q;
++                }
+         }
+ 
+         return r;
+ }
+ 
+ static int install_context_mark_for_removal(
++                UnitFileScope scope,
+                 InstallContext *c,
+                 const LookupPaths *paths,
+                 Set **remove_symlinks_to,
+@@ -1430,96 +1503,109 @@ static int install_context_mark_for_removal(
+                 const char *root_dir) {
+ 
+         InstallInfo *i;
+-        int r, q;
++        int r;
+ 
+         assert(c);
+         assert(paths);
+         assert(config_path);
+ 
+         /* Marks all items for removal */
+-
+-        if (!ordered_hashmap_isempty(c->will_install)) {
+-                r = ordered_hashmap_ensure_allocated(&c->have_installed, &string_hash_ops);
++        if (!ordered_hashmap_isempty(c->will_process)) {
++                r = ordered_hashmap_ensure_allocated(&c->have_processed, &string_hash_ops);
+                 if (r < 0)
+                         return r;
+ 
+-                r = ordered_hashmap_reserve(c->have_installed, ordered_hashmap_size(c->will_install));
++                r = ordered_hashmap_reserve(c->have_processed, ordered_hashmap_size(c->will_process));
+                 if (r < 0)
+                         return r;
+         }
+ 
+         r = 0;
+-        while ((i = ordered_hashmap_first(c->will_install))) {
+-                assert_se(ordered_hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
+-
+-                q = unit_file_search(c, i, paths, root_dir, false, true, NULL);
+-                if (q == -ENOENT) {
+-                        /* do nothing */
+-                } else if (q < 0) {
+-                        if (r >= 0)
+-                                r = q;
++        while ((i = ordered_hashmap_first(c->will_process))) {
++
++                r = ordered_hashmap_move_one(c->have_processed, c->will_process, i->name);
++                if (r < 0)
++                        return r;
+ 
++                r = install_info_traverse(scope, c, root_dir, paths, i, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS, NULL);
++                if (r < 0)
+                         return r;
+-                } else if (r >= 0)
+-                        r += q;
+-
+-                if (unit_name_is_instance(i->name)) {
+-                        char *unit_file;
+-
+-                        if (i->path) {
+-                                unit_file = basename(i->path);
+-
+-                                if (unit_name_is_instance(unit_file))
+-                                        /* unit file named as instance exists, thus all symlinks
+-                                         * pointing to it will be removed */
+-                                        q = mark_symlink_for_removal(remove_symlinks_to, i->name);
+-                                else
+-                                        /* does not exist, thus we will mark for removal symlinks
+-                                         * to template unit file */
+-                                        q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
+-                        } else {
+-                                /* If i->path is not set, it means that we didn't actually find
+-                                 * the unit file. But we can still remove symlinks to the
+-                                 * nonexistent template. */
+-                                unit_file = unit_name_template(i->name);
+-                                if (!unit_file)
+-                                        return log_oom();
+-
+-                                q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
+-                                free(unit_file);
+-                        }
+-                } else
+-                        q = mark_symlink_for_removal(remove_symlinks_to, i->name);
+ 
+-                if (r >= 0 && q < 0)
++                if (i->type != UNIT_FILE_TYPE_REGULAR)
++                        continue;
++
++                r = mark_symlink_for_removal(remove_symlinks_to, i->name);
++                if (r < 0)
++                        return r;
++        }
++
++        return 0;
++}
++
++int unit_file_mask(
++                UnitFileScope scope,
++                bool runtime,
++                const char *root_dir,
++                char **files,
++                bool force,
++                UnitFileChange **changes,
++                unsigned *n_changes) {
++
++        _cleanup_free_ char *prefix = NULL;
++        char **i;
++        int r;
++
++        assert(scope >= 0);
++        assert(scope < _UNIT_FILE_SCOPE_MAX);
++
++        r = verify_root_dir(scope, &root_dir);
++        if (r < 0)
++                return r;
++
++        r = get_config_path(scope, runtime, root_dir, &prefix);
++        if (r < 0)
++                return r;
++
++        STRV_FOREACH(i, files) {
++                _cleanup_free_ char *path = NULL;
++                int q;
++                if (!unit_name_is_valid(*i, UNIT_NAME_ANY)) {
++                        if (r == 0)
++                                r = -EINVAL;
++                        continue;
++                }
++
++                path = path_make_absolute(*i, prefix);
++                if (!path)
++                        return -ENOMEM;
++
++                q = create_symlink("/dev/null", path, force, changes, n_changes);
++                if (q < 0 && r >= 0)
+                         r = q;
+         }
+ 
+         return r;
+ }
+ 
+-int unit_file_add_dependency(
++int unit_file_unmask(
+                 UnitFileScope scope,
+                 bool runtime,
+                 const char *root_dir,
+                 char **files,
+-                char *target,
+-                UnitDependency dep,
+-                bool force,
+                 UnitFileChange **changes,
+                 unsigned *n_changes) {
+ 
+-        _cleanup_lookup_paths_free_ LookupPaths paths = {};
+-        _cleanup_(install_context_done) InstallContext c = {};
++        _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
+         _cleanup_free_ char *config_path = NULL;
++        _cleanup_free_ char **todo = NULL;
++        size_t n_todo = 0, n_allocated = 0;
+         char **i;
+-        int r;
+-        InstallInfo *info;
++        int r, q;
+ 
+         assert(scope >= 0);
+         assert(scope < _UNIT_FILE_SCOPE_MAX);
+ 
+-        r = lookup_paths_init_from_scope(&paths, scope, root_dir);
++        r = verify_root_dir(scope, &root_dir);
+         if (r < 0)
+                 return r;
+ 
+@@ -1528,57 +1614,222 @@ int unit_file_add_dependency(
+                 return r;
+ 
+         STRV_FOREACH(i, files) {
+-                UnitFileState state;
++                _cleanup_free_ char *path = NULL;
+ 
+-                state = unit_file_get_state(scope, root_dir, *i);
+-                if (state < 0)
+-                        return log_error_errno(state, "Failed to get unit file state for %s: %m", *i);
++                if (!unit_name_is_valid(*i, UNIT_NAME_ANY))
++                        return -EINVAL;
+ 
+-                if (state == UNIT_FILE_MASKED || state == UNIT_FILE_MASKED_RUNTIME) {
+-                        log_error("Failed to enable unit: Unit %s is masked", *i);
+-                        return -ENOTSUP;
+-                }
++                path = path_make_absolute(*i, config_path);
++                if (!path)
++                        return -ENOMEM;
+ 
+-                r = install_info_add_auto(&c, *i);
++                r = null_or_empty_path(path);
++                if (r == -ENOENT)
++                        continue;
+                 if (r < 0)
+                         return r;
++                if (r == 0)
++                        continue;
++
++                if (!GREEDY_REALLOC0(todo, n_allocated, n_todo + 2))
++                        return -ENOMEM;
++
++                todo[n_todo++] = *i;
+         }
+ 
+-        if (!ordered_hashmap_isempty(c.will_install)) {
+-                r = ordered_hashmap_ensure_allocated(&c.have_installed, &string_hash_ops);
+-                if (r < 0)
+-                        return r;
++        strv_uniq(todo);
+ 
+-                r = ordered_hashmap_reserve(c.have_installed, ordered_hashmap_size(c.will_install));
+-                if (r < 0)
+-                        return r;
++        r = 0;
++        STRV_FOREACH(i, todo) {
++                _cleanup_free_ char *path = NULL;
++
++                path = path_make_absolute(*i, config_path);
++                if (!path)
++                        return -ENOMEM;
++
++                if (unlink(path) < 0) {
++                        if (errno != -ENOENT && r >= 0)
++                                r = -errno;
++                } else {
++                        q = mark_symlink_for_removal(&remove_symlinks_to, path);
++                        if (q < 0)
++                                return q;
++
++                        unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
++                }
+         }
+ 
+-        while ((info = ordered_hashmap_first(c.will_install))) {
+-                assert_se(ordered_hashmap_move_one(c.have_installed, c.will_install, info->name) == 0);
++        q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes);
++        if (r >= 0)
++                r = q;
+ 
+-                r = unit_file_search(&c, info, &paths, root_dir, false, false, NULL);
+-                if (r < 0)
+-                        return r;
++        return r;
++}
+ 
+-                if (dep == UNIT_WANTS)
+-                        r = strv_extend(&info->wanted_by, target);
+-                else if (dep == UNIT_REQUIRES)
+-                        r = strv_extend(&info->required_by, target);
+-                else
+-                        r = -EINVAL;
++int unit_file_link(
++                UnitFileScope scope,
++                bool runtime,
++                const char *root_dir,
++                char **files,
++                bool force,
++                UnitFileChange **changes,
++                unsigned *n_changes) {
+ 
+-                if (r < 0)
+-                        return r;
++        _cleanup_lookup_paths_free_ LookupPaths paths = {};
++        _cleanup_free_ char *config_path = NULL;
++        _cleanup_free_ char **todo = NULL;
++        size_t n_todo = 0, n_allocated = 0;
++        char **i;
++        int r,q;
+ 
+-                r = install_info_apply(info, &paths, config_path, root_dir, force, changes, n_changes);
+-                if (r < 0)
+-                        return r;
++        assert(scope >= 0);
++        assert(scope < _UNIT_FILE_SCOPE_MAX);
++
++        r = verify_root_dir(scope, &root_dir);
++        if (r < 0)
++                return r;
++
++        r = lookup_paths_init_from_scope(&paths, scope, root_dir);
++        if (r < 0)
++                return r;
++
++        r = get_config_path(scope, runtime, root_dir, &config_path);
++        if (r < 0)
++                return r;
++
++        STRV_FOREACH(i, files) {
++                _cleanup_free_ char *full = NULL;
++                struct stat st;
++                char *fn;
++
++                if (!path_is_absolute(*i))
++                        return -EINVAL;
++
++                fn = basename(*i);
++                if (!unit_name_is_valid(fn, UNIT_NAME_ANY))
++                        return -EINVAL;
++
++                full = prefix_root(root_dir, *i);
++                if (!full)
++                        return -ENOMEM;
++
++                if (lstat(full, &st) < 0)
++                        return -errno;
++                if (S_ISLNK(st.st_mode))
++                        return -ELOOP;
++                if (S_ISDIR(st.st_mode))
++                        return -EISDIR;
++                if (!S_ISREG(st.st_mode))
++                        return -ENOTTY;
++
++                q = in_search_path(*i, paths.unit_path);
++                if (q < 0)
++                        return q;
++                if (q > 0)
++                        continue;
++
++                if (!GREEDY_REALLOC0(todo, n_allocated, n_todo + 2))
++                        return -ENOMEM;
++
++                todo[n_todo++] = *i;
+         }
+ 
+-        return 0;
++        strv_uniq(todo);
++
++        r = 0;
++        STRV_FOREACH(i, todo) {
++                _cleanup_free_ char *path = NULL;
++
++                path = path_make_absolute(basename(*i), config_path);
++                if (!path)
++                        return -ENOMEM;
++
++                q = create_symlink(*i, path, force, changes, n_changes);
++                if (q < 0 && r >= 0)
++                        r = q;
++        }
++
++        return r;
++}
++
++int unit_file_add_dependency(
++                UnitFileScope scope,
++                bool runtime,
++                const char *root_dir,
++                char **files,
++                const char *target,
++                UnitDependency dep,
++                bool force,
++                UnitFileChange **changes,
++                unsigned *n_changes) {
++
++        _cleanup_lookup_paths_free_ LookupPaths paths = {};
++        _cleanup_(install_context_done) InstallContext c = {};
++        _cleanup_free_ char *config_path = NULL;
++        InstallInfo *i, *target_info;
++        char **f;
++        int r;
++
++        assert(scope >= 0);
++        assert(scope < _UNIT_FILE_SCOPE_MAX);
++        assert(target);
++
++        if (!IN_SET(dep, UNIT_WANTS, UNIT_REQUIRES))
++                return -EINVAL;
++
++        if (!unit_name_is_valid(target, UNIT_NAME_ANY))
++                return -EINVAL;
++
++        r = verify_root_dir(scope, &root_dir);
++        if (r < 0)
++                return r;
++
++        r = lookup_paths_init_from_scope(&paths, scope, root_dir);
++        if (r < 0)
++                return r;
++
++        r = get_config_path(scope, runtime, root_dir, &config_path);
++        if (r < 0)
++                return r;
++
++        r = install_info_discover(scope, &c, root_dir, &paths, target, SEARCH_FOLLOW_CONFIG_SYMLINKS, &target_info);
++        if (r < 0)
++                return r;
++        if (target_info->type == UNIT_FILE_TYPE_MASKED)
++                return -ESHUTDOWN;
++
++        assert(target_info->type == UNIT_FILE_TYPE_REGULAR);
++
++        STRV_FOREACH(f, files) {
++                char ***l;
++
++                r = install_info_discover(scope, &c, root_dir, &paths, *f, SEARCH_FOLLOW_CONFIG_SYMLINKS, &i);
++                 if (r < 0)
++                         return r;
++                if (i->type == UNIT_FILE_TYPE_MASKED)
++                        return -ESHUTDOWN;
++
++                assert(i->type == UNIT_FILE_TYPE_REGULAR);
++
++                /* We didn't actually load anything from the unit
++                 * file, but instead just add in our new symlink to
++                 * create. */
++
++                 if (dep == UNIT_WANTS)
++                        l = &i->wanted_by;
++                 else
++                        l = &i->required_by;
++
++                strv_free(*l);
++                *l = strv_new(target_info->name, NULL);
++                if (!*l)
++                        return -ENOMEM;
++         }
++
++        return install_context_apply(scope, &c, &paths, config_path, root_dir, force, SEARCH_FOLLOW_CONFIG_SYMLINKS, changes, n_changes);
+ }
+ 
++
+ int unit_file_enable(
+                 UnitFileScope scope,
+                 bool runtime,
+@@ -1590,13 +1841,18 @@ int unit_file_enable(
+ 
+         _cleanup_lookup_paths_free_ LookupPaths paths = {};
+         _cleanup_(install_context_done) InstallContext c = {};
+-        char **i;
+         _cleanup_free_ char *config_path = NULL;
++        InstallInfo *i;
++        char **f;
+         int r;
+ 
+         assert(scope >= 0);
+         assert(scope < _UNIT_FILE_SCOPE_MAX);
+ 
++        r = verify_root_dir(scope, &root_dir);
++        if (r < 0)
++                return r;
++
+         r = lookup_paths_init_from_scope(&paths, scope, root_dir);
+         if (r < 0)
+                 return r;
+@@ -1605,21 +1861,14 @@ int unit_file_enable(
+         if (r < 0)
+                 return r;
+ 
+-        STRV_FOREACH(i, files) {
+-                UnitFileState state;
+-
+-                /* We only want to know if this unit is masked, so we ignore
+-                 * errors from unit_file_get_state, deferring other checks.
+-                 * This allows templated units to be enabled on the fly. */
+-                state = unit_file_get_state(scope, root_dir, *i);
+-                if (state == UNIT_FILE_MASKED || state == UNIT_FILE_MASKED_RUNTIME) {
+-                        log_error("Failed to enable unit: Unit %s is masked", *i);
+-                        return -ENOTSUP;
+-                }
+-
+-                r = install_info_add_auto(&c, *i);
++        STRV_FOREACH(f, files) {
++                r = install_info_discover(scope, &c, root_dir, &paths, *f, SEARCH_LOAD, &i);
+                 if (r < 0)
+                         return r;
++                if (i->type == UNIT_FILE_TYPE_MASKED)
++                        return -ESHUTDOWN;
++
++                assert(i->type == UNIT_FILE_TYPE_REGULAR);
+         }
+ 
+         /* This will return the number of symlink rules that were
+@@ -1627,7 +1876,7 @@ int unit_file_enable(
+         useful to determine whether the passed files had any
+         installation data at all. */
+ 
+-        return install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes);
++        return install_context_apply(scope, &c, &paths, config_path, root_dir, force, SEARCH_LOAD, changes, n_changes);
+ }
+ 
+ int unit_file_disable(
+@@ -1640,14 +1889,18 @@ int unit_file_disable(
+ 
+         _cleanup_lookup_paths_free_ LookupPaths paths = {};
+         _cleanup_(install_context_done) InstallContext c = {};
+-        char **i;
+         _cleanup_free_ char *config_path = NULL;
+         _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
+-        int r, q;
++        char **i;
++        int r;
+ 
+         assert(scope >= 0);
+         assert(scope < _UNIT_FILE_SCOPE_MAX);
+ 
++        r = verify_root_dir(scope, &root_dir);
++        if (r < 0)
++                return r;
++
+         r = lookup_paths_init_from_scope(&paths, scope, root_dir);
+         if (r < 0)
+                 return r;
+@@ -1657,18 +1910,19 @@ int unit_file_disable(
+                 return r;
+ 
+         STRV_FOREACH(i, files) {
+-                r = install_info_add_auto(&c, *i);
++                if (!unit_name_is_valid(*i, UNIT_NAME_ANY))
++                        return -EINVAL;
++
++                r = install_info_add(&c, *i, NULL, NULL);
+                 if (r < 0)
+                         return r;
+         }
+ 
+-        r = install_context_mark_for_removal(&c, &paths, &remove_symlinks_to, config_path, root_dir);
+-
+-        q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
+-        if (r >= 0)
+-                r = q;
++        r = install_context_mark_for_removal(scope, &c, &paths, &remove_symlinks_to, config_path, root_dir);
++        if (r < 0)
++                return r;
+ 
+-        return r;
++        return remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes);
+ }
+ 
+ int unit_file_reenable(
+@@ -1679,21 +1933,30 @@ int unit_file_reenable(
+                 bool force,
+                 UnitFileChange **changes,
+                 unsigned *n_changes) {
++
++        char **n;
+         int r;
++        size_t l, i;
++
++        /* First, we invoke the disable command with only the basename... */
++        l = strv_length(files);
++        n = newa(char*, l+1);
++        for (i = 0; i < l; i++)
++                n[i] = basename(files[i]);
++        n[i] = NULL;
+ 
+-        r = unit_file_disable(scope, runtime, root_dir, files,
+-                              changes, n_changes);
++        r = unit_file_disable(scope, runtime, root_dir, n, changes, n_changes);
+         if (r < 0)
+                 return r;
+ 
+-        return unit_file_enable(scope, runtime, root_dir, files, force,
+-                                changes, n_changes);
++        /* But the enable command with the full name */
++        return unit_file_enable(scope, runtime, root_dir, files, force, changes, n_changes);
+ }
+ 
+ int unit_file_set_default(
+                 UnitFileScope scope,
+                 const char *root_dir,
+-                const char *file,
++                const char *name,
+                 bool force,
+                 UnitFileChange **changes,
+                 unsigned *n_changes) {
+@@ -1701,42 +1964,40 @@ int unit_file_set_default(
+         _cleanup_lookup_paths_free_ LookupPaths paths = {};
+         _cleanup_(install_context_done) InstallContext c = {};
+         _cleanup_free_ char *config_path = NULL;
+-        char *path;
++        InstallInfo *i;
++        const char *path;
+         int r;
+-        InstallInfo *i = NULL;
+ 
+         assert(scope >= 0);
+         assert(scope < _UNIT_FILE_SCOPE_MAX);
+-        assert(file);
++        assert(name);
+ 
+-        if (unit_name_to_type(file) != UNIT_TARGET)
++        if (unit_name_to_type(name) != UNIT_TARGET)
++                return -EINVAL;
++        if (streq(name, SPECIAL_DEFAULT_TARGET))
+                 return -EINVAL;
+ 
+-        r = lookup_paths_init_from_scope(&paths, scope, root_dir);
++        r = verify_root_dir(scope, &root_dir);
+         if (r < 0)
+                 return r;
+ 
+-        r = get_config_path(scope, false, root_dir, &config_path);
++        r = lookup_paths_init_from_scope(&paths, scope, root_dir);
+         if (r < 0)
+                 return r;
+ 
+-        r = install_info_add_auto(&c, file);
++        r = get_config_path(scope, false, root_dir, &config_path);
+         if (r < 0)
+                 return r;
+ 
+-        assert_se(i = ordered_hashmap_first(c.will_install));
+-
+-        r = unit_file_search(&c, i, &paths, root_dir, false, true, NULL);
++        r = install_info_discover(scope, &c, root_dir, &paths, name, 0, &i);
+         if (r < 0)
+                 return r;
++        if (i->type == UNIT_FILE_TYPE_MASKED)
++                return -ESHUTDOWN;
+ 
+         path = strjoina(config_path, "/" SPECIAL_DEFAULT_TARGET);
+ 
+-        r = create_symlink(i->path, path, force, changes, n_changes);
+-        if (r < 0)
+-                return r;
+-
+-        return 0;
++        return create_symlink(i->path, path, force, changes, n_changes);
+ }
+ 
+ int unit_file_get_default(
+@@ -1745,127 +2006,100 @@ int unit_file_get_default(
+                 char **name) {
+ 
+         _cleanup_lookup_paths_free_ LookupPaths paths = {};
+-        char **p;
++        _cleanup_(install_context_done) InstallContext c = {};
++        InstallInfo *i;
++        char *n;
+         int r;
+ 
+         assert(scope >= 0);
+         assert(scope < _UNIT_FILE_SCOPE_MAX);
+         assert(name);
+ 
+-        r = lookup_paths_init_from_scope(&paths, scope, root_dir);
++        r = verify_root_dir(scope, &root_dir);
+         if (r < 0)
+                 return r;
+ 
+-        STRV_FOREACH(p, paths.unit_path) {
+-                _cleanup_free_ char *path = NULL, *tmp = NULL;
+-                char *n;
+-
+-                path = path_join(root_dir, *p, SPECIAL_DEFAULT_TARGET);
+-                if (!path)
+-                        return -ENOMEM;
+-
+-                r = readlink_malloc(path, &tmp);
+-                if (r == -ENOENT)
+-                        continue;
+-                else if (r == -EINVAL)
+-                        /* not a symlink */
+-                        n = strdup(SPECIAL_DEFAULT_TARGET);
+-                else if (r < 0)
+-                        return r;
+-                else
+-                        n = strdup(basename(tmp));
++        r = lookup_paths_init_from_scope(&paths, scope, root_dir);
++        if (r < 0)
++                return r;
+ 
+-                if (!n)
+-                        return -ENOMEM;
++        r = install_info_discover(scope, &c, root_dir, &paths, SPECIAL_DEFAULT_TARGET, SEARCH_FOLLOW_CONFIG_SYMLINKS, &i);
++        if (r < 0)
++                return r;
++        if (i->type == UNIT_FILE_TYPE_MASKED)
++                return -ESHUTDOWN;
+ 
+-                *name = n;
+-                return 0;
+-        }
++        n = strdup(i->name);
++        if (!n)
++                return -ENOMEM;
+ 
+-        return -ENOENT;
++        *name = n;
++        return 0;
+ }
+ 
+ UnitFileState unit_file_lookup_state(
+                 UnitFileScope scope,
+                 const char *root_dir,
+                 const LookupPaths *paths,
+-                const char *name) {
+-
+-        UnitFileState state = _UNIT_FILE_STATE_INVALID;
+-        char **i;
+-        _cleanup_free_ char *path = NULL;
++                const char *name,
++                UnitFileState *ret) {
++        _cleanup_(install_context_done) InstallContext c = {};
++        InstallInfo *i;
++        UnitFileState state;
+         int r;
+ 
+         assert(paths);
++        assert(name);
+ 
+-        if (!unit_name_is_valid(name, TEMPLATE_VALID))
++        if (!unit_name_is_valid(name, UNIT_NAME_ANY))
+                 return -EINVAL;
+ 
+-        STRV_FOREACH(i, paths->unit_path) {
+-                struct stat st;
+-                char *partial;
+-                bool also = false;
+-
+-                free(path);
+-                path = path_join(root_dir, *i, name);
+-                if (!path)
+-                        return -ENOMEM;
++        r = verify_root_dir(scope, &root_dir);
++        if (r < 0)
++                return r;
+ 
+-                if (root_dir)
+-                        partial = path + strlen(root_dir);
+-                else
+-                        partial = path;
++        r = install_info_discover(scope, &c, root_dir, paths, name, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS, &i);
++        if (r < 0)
++                return r;
+ 
+-                /*
+-                 * Search for a unit file in our default paths, to
+-                 * be sure, that there are no broken symlinks.
+-                 */
+-                if (lstat(path, &st) < 0) {
+-                        r = -errno;
+-                        if (errno != ENOENT)
+-                                return r;
++        /* Shortcut things, if the caller just wants to know if this unit exists. */
++        if (!ret)
++                return 0;
+ 
+-                        if (!unit_name_is_instance(name))
+-                                continue;
+-                } else {
+-                        if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode))
+-                                return -ENOENT;
++        switch (i->type) {
+ 
+-                        r = null_or_empty_path(path);
+-                        if (r < 0 && r != -ENOENT)
+-                                return r;
+-                        else if (r > 0) {
+-                                state = path_startswith(*i, "/run") ?
+-                                        UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
+-                                return state;
+-                        }
+-                }
++        case UNIT_FILE_TYPE_MASKED:
++                state = path_startswith(i->path, "/run") ? UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
++                break;
+ 
+-                r = find_symlinks_in_scope(scope, root_dir, name, &state);
++        case UNIT_FILE_TYPE_REGULAR:
++                r = find_symlinks_in_scope(scope, root_dir, i->name, &state);
+                 if (r < 0)
+                         return r;
+-                else if (r > 0)
+-                        return state;
+-
+-                r = unit_file_can_install(paths, root_dir, partial, true, &also);
+-                if (r < 0 && errno != ENOENT)
+-                        return r;
+-                else if (r > 0)
+-                        return UNIT_FILE_DISABLED;
+-                else if (r == 0) {
+-                        if (also)
+-                                return UNIT_FILE_INDIRECT;
+-                        return UNIT_FILE_STATIC;
++                if (r == 0) {
++                        if (UNIT_FILE_INSTALL_INFO_HAS_RULES(i))
++                                state = UNIT_FILE_DISABLED;
++                        else if (UNIT_FILE_INSTALL_INFO_HAS_ALSO(i))
++                                state = UNIT_FILE_INDIRECT;
++                        else
++                                state = UNIT_FILE_STATIC;
+                 }
++
++                break;
++
++        default:
++                assert_not_reached("Unexpect unit file type.");
+         }
+ 
+-        return r < 0 ? r : state;
++        *ret = state;
++        return 0;
+ }
+ 
+-UnitFileState unit_file_get_state(
++int unit_file_get_state(
+                 UnitFileScope scope,
+                 const char *root_dir,
+-                const char *name) {
++                const char *name,
++                UnitFileState *ret) {
+ 
+         _cleanup_lookup_paths_free_ LookupPaths paths = {};
+         int r;
+@@ -1874,14 +2108,15 @@ UnitFileState unit_file_get_state(
+         assert(scope < _UNIT_FILE_SCOPE_MAX);
+         assert(name);
+ 
+-        if (root_dir && scope != UNIT_FILE_SYSTEM)
+-                return -EINVAL;
++        r = verify_root_dir(scope, &root_dir);
++        if (r < 0)
++                return r;
+ 
+         r = lookup_paths_init_from_scope(&paths, scope, root_dir);
+         if (r < 0)
+                 return r;
+ 
+-        return unit_file_lookup_state(scope, root_dir, &paths, name);
++        return unit_file_lookup_state(scope, root_dir, &paths, name, ret);
+ }
+ 
+ int unit_file_query_preset(UnitFileScope scope, const char *root_dir, const char *name) {
+@@ -1893,6 +2128,13 @@ int unit_file_query_preset(UnitFileScope scope, const char *root_dir, const char
+         assert(scope < _UNIT_FILE_SCOPE_MAX);
+         assert(name);
+ 
++        r = verify_root_dir(scope, &root_dir);
++        if (r < 0)
++                return r;
++
++        if (!unit_name_is_valid(name, UNIT_NAME_ANY))
++                return -EINVAL;
++
+         if (scope == UNIT_FILE_SYSTEM)
+                 r = conf_files_list(&files, ".preset", root_dir,
+                                     "/etc/systemd/system-preset",
+@@ -1909,13 +2151,14 @@ int unit_file_query_preset(UnitFileScope scope, const char *root_dir, const char
+                                     "/usr/lib/systemd/user-preset",
+                                     NULL);
+         else
+-                return 1;
++                return 1; /* Default is "enable" */
+ 
+         if (r < 0)
+                 return r;
+ 
+         STRV_FOREACH(p, files) {
+                 _cleanup_fclose_ FILE *f;
++                char line[LINE_MAX];
+ 
+                 f = fopen(*p, "re");
+                 if (!f) {
+@@ -1925,39 +2168,38 @@ int unit_file_query_preset(UnitFileScope scope, const char *root_dir, const char
+                         return -errno;
+                 }
+ 
+-                for (;;) {
+-                        char line[LINE_MAX], *l;
+-
+-                        if (!fgets(line, sizeof(line), f))
+-                                break;
++                FOREACH_LINE(line, f, return -errno) {
++                        const char *parameter;
++                        char *l;
+ 
+                         l = strstrip(line);
+-                        if (!*l)
+-                                continue;
+ 
+-                        if (strchr(COMMENTS "\n", *l))
++                        if (isempty(l))
++                                continue;
++                        if (strchr(COMMENTS, *l))
+                                 continue;
+ 
+-                        if (first_word(l, "enable")) {
+-                                l += 6;
+-                                l += strspn(l, WHITESPACE);
+-
+-                                if (fnmatch(l, name, FNM_NOESCAPE) == 0) {
++                        parameter = first_word(l, "enable");
++                        if (parameter) {
++                                if (fnmatch(parameter, name, FNM_NOESCAPE) == 0) {
+                                         log_debug("Preset file says enable %s.", name);
+                                         return 1;
+                                 }
+ 
+-                        } else if (first_word(l, "disable")) {
+-                                l += 7;
+-                                l += strspn(l, WHITESPACE);
++                                continue;
++                        }
+ 
+-                                if (fnmatch(l, name, FNM_NOESCAPE) == 0) {
++                        parameter = first_word(l, "disable");
++                        if (parameter) {
++                                if (fnmatch(parameter, name, FNM_NOESCAPE) == 0) {
+                                         log_debug("Preset file says disable %s.", name);
+                                         return 0;
+                                 }
+ 
+-                        } else
+-                                log_debug("Couldn't parse line '%s'", l);
++                                continue;
++                        }
++
++                        log_debug("Couldn't parse line '%s'", l);
+                 }
+         }
+ 
+@@ -1966,6 +2208,86 @@ int unit_file_query_preset(UnitFileScope scope, const char *root_dir, const char
+         return 1;
+ }
+ 
++static int execute_preset(
++                UnitFileScope scope,
++                InstallContext *plus,
++                InstallContext *minus,
++                const LookupPaths *paths,
++                const char *config_path,
++                const char *root_dir,
++                char **files,
++                UnitFilePresetMode mode,
++                bool force,
++                UnitFileChange **changes,
++                unsigned *n_changes) {
++
++        int r;
++
++        assert(plus);
++        assert(minus);
++        assert(paths);
++        assert(config_path);
++
++        if (mode != UNIT_FILE_PRESET_ENABLE_ONLY) {
++                _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
++
++                r = install_context_mark_for_removal(scope, minus, paths, &remove_symlinks_to, config_path, root_dir);
++                if (r < 0)
++                        return r;
++
++                r = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes);
++        } else
++                r = 0;
++
++        if (mode != UNIT_FILE_PRESET_DISABLE_ONLY) {
++                int q;
++
++                /* Returns number of symlinks that where supposed to be installed. */
++                q = install_context_apply(scope, plus, paths, config_path, root_dir, force, SEARCH_LOAD, changes, n_changes);
++                if (r >= 0) {
++                        if (q < 0)
++                                r = q;
++                        else
++                                r+= q;
++                }
++        }
++
++        return r;
++}
++
++static int preset_prepare_one(
++                UnitFileScope scope,
++                InstallContext *plus,
++                InstallContext *minus,
++                LookupPaths *paths,
++                const char *root_dir,
++                UnitFilePresetMode mode,
++                const char *name) {
++
++        InstallInfo *i;
++        int r;
++
++        if (install_info_find(plus, name) ||
++            install_info_find(minus, name))
++                return 0;
++
++        r = unit_file_query_preset(scope, root_dir, name);
++        if (r < 0)
++                return r;
++
++        if (r > 0) {
++                r = install_info_discover(scope, plus, root_dir, paths, name, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS, &i);
++                if (r < 0)
++                        return r;
++
++                if (i->type == UNIT_FILE_TYPE_MASKED)
++                        return -ESHUTDOWN;
++        } else
++                r = install_info_discover(scope, minus, root_dir, paths, name, SEARCH_FOLLOW_CONFIG_SYMLINKS, &i);
++
++        return r;
++}
++
+ int unit_file_preset(
+                 UnitFileScope scope,
+                 bool runtime,
+@@ -1980,12 +2302,16 @@ int unit_file_preset(
+         _cleanup_lookup_paths_free_ LookupPaths paths = {};
+         _cleanup_free_ char *config_path = NULL;
+         char **i;
+-        int r, q;
++        int r;
+ 
+         assert(scope >= 0);
+         assert(scope < _UNIT_FILE_SCOPE_MAX);
+         assert(mode < _UNIT_FILE_PRESET_MAX);
+ 
++        r = verify_root_dir(scope, &root_dir);
++        if (r < 0)
++                return r;
++
+         r = lookup_paths_init_from_scope(&paths, scope, root_dir);
+         if (r < 0)
+                 return r;
+@@ -1995,44 +2321,15 @@ int unit_file_preset(
+                 return r;
+ 
+         STRV_FOREACH(i, files) {
+-
+-                if (!unit_name_is_valid(*i, TEMPLATE_VALID))
++                if (!unit_name_is_valid(*i, UNIT_NAME_ANY))
+                         return -EINVAL;
+ 
+-                r = unit_file_query_preset(scope, root_dir, *i);
+-                if (r < 0)
+-                        return r;
+-
+-                if (r && mode != UNIT_FILE_PRESET_DISABLE_ONLY)
+-                        r = install_info_add_auto(&plus, *i);
+-                else if (!r && mode != UNIT_FILE_PRESET_ENABLE_ONLY)
+-                        r = install_info_add_auto(&minus, *i);
+-                else
+-                        r = 0;
++                r = preset_prepare_one(scope, &plus, &minus, &paths, root_dir, mode, *i);
+                 if (r < 0)
+                         return r;
+         }
+ 
+-        r = 0;
+-
+-        if (mode != UNIT_FILE_PRESET_ENABLE_ONLY) {
+-                _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
+-
+-                r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to, config_path, root_dir);
+-
+-                q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
+-                if (r == 0)
+-                        r = q;
+-        }
+-
+-        if (mode != UNIT_FILE_PRESET_DISABLE_ONLY) {
+-                /* Returns number of symlinks that where supposed to be installed. */
+-                q = install_context_apply(&plus, &paths, config_path, root_dir, force, changes, n_changes);
+-                if (r == 0)
+-                        r = q;
+-        }
+-
+-        return r;
++        return execute_preset(scope, &plus, &minus, &paths, config_path, root_dir, files, mode, force, changes, n_changes);
+ }
+ 
+ int unit_file_preset_all(
+@@ -2048,12 +2345,16 @@ int unit_file_preset_all(
+         _cleanup_lookup_paths_free_ LookupPaths paths = {};
+         _cleanup_free_ char *config_path = NULL;
+         char **i;
+-        int r, q;
++        int r;
+ 
+         assert(scope >= 0);
+         assert(scope < _UNIT_FILE_SCOPE_MAX);
+         assert(mode < _UNIT_FILE_PRESET_MAX);
+ 
++        r = verify_root_dir(scope, &root_dir);
++        if (r < 0)
++                return r;
++
+         r = lookup_paths_init_from_scope(&paths, scope, root_dir);
+         if (r < 0)
+                 return r;
+@@ -2092,48 +2393,21 @@ int unit_file_preset_all(
+                         if (hidden_file(de->d_name))
+                                 continue;
+ 
+-                        if (!unit_name_is_valid(de->d_name, TEMPLATE_VALID))
++                        if (!unit_name_is_valid(de->d_name, UNIT_NAME_ANY))
+                                 continue;
+ 
+                         dirent_ensure_type(d, de);
+ 
+-                        if (de->d_type != DT_REG)
++                        if (!IN_SET(de->d_type, DT_LNK, DT_REG))
+                                 continue;
+ 
+-                        r = unit_file_query_preset(scope, root_dir, de->d_name);
+-                        if (r < 0)
+-                                return r;
+-
+-                        if (r && mode != UNIT_FILE_PRESET_DISABLE_ONLY)
+-                                r = install_info_add_auto(&plus, de->d_name);
+-                        else if (!r && mode != UNIT_FILE_PRESET_ENABLE_ONLY)
+-                                r = install_info_add_auto(&minus, de->d_name);
+-                        else
+-                                r = 0;
++                        r = preset_prepare_one(scope, &plus, &minus, &paths, root_dir, mode, de->d_name);
+                         if (r < 0)
+                                 return r;
+                 }
+         }
+ 
+-        r = 0;
+-
+-        if (mode != UNIT_FILE_PRESET_ENABLE_ONLY) {
+-                _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
+-
+-                r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to, config_path, root_dir);
+-
+-                q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, NULL);
+-                if (r == 0)
+-                        r = q;
+-        }
+-
+-        if (mode != UNIT_FILE_PRESET_DISABLE_ONLY) {
+-                q = install_context_apply(&plus, &paths, config_path, root_dir, force, changes, n_changes);
+-                if (r == 0)
+-                        r = q;
+-        }
+-
+-        return r;
++        return execute_preset(scope, &plus, &minus, &paths, config_path, root_dir, NULL, mode, force, changes, n_changes);
+ }
+ 
+ static void unit_file_list_free_one(UnitFileList *f) {
+@@ -2144,6 +2418,17 @@ static void unit_file_list_free_one(UnitFileList *f) {
+         free(f);
+ }
+ 
++Hashmap* unit_file_list_free(Hashmap *h) {
++        UnitFileList *i;
++
++        while ((i = hashmap_steal_first(h)))
++                unit_file_list_free_one(i);
++
++        hashmap_free(h);
++
++        return NULL;
++}
++
+ DEFINE_TRIVIAL_CLEANUP_FUNC(UnitFileList*, unit_file_list_free_one);
+ 
+ int unit_file_get_list(
+@@ -2159,14 +2444,9 @@ int unit_file_get_list(
+         assert(scope < _UNIT_FILE_SCOPE_MAX);
+         assert(h);
+ 
+-        if (root_dir && scope != UNIT_FILE_SYSTEM)
+-                return -EINVAL;
+-
+-        if (root_dir) {
+-                r = access(root_dir, F_OK);
+-                if (r < 0)
+-                        return -errno;
+-        }
++        r = verify_root_dir(scope, &root_dir);
++        if (r < 0)
++                return r;
+ 
+         r = lookup_paths_init_from_scope(&paths, scope, root_dir);
+         if (r < 0)
+@@ -2191,7 +2471,6 @@ int unit_file_get_list(
+                 for (;;) {
+                         _cleanup_(unit_file_list_free_onep) UnitFileList *f = NULL;
+                         struct dirent *de;
+-                        _cleanup_free_ char *path = NULL;
+ 
+                         errno = 0;
+                         de = readdir(d);
+@@ -2204,7 +2483,7 @@ int unit_file_get_list(
+                         if (hidden_file(de->d_name))
+                                 continue;
+ 
+-                        if (!unit_name_is_valid(de->d_name, TEMPLATE_VALID))
++                        if (!unit_name_is_valid(de->d_name, UNIT_NAME_ANY))
+                                 continue;
+ 
+                         if (hashmap_get(h, de->d_name))
+@@ -2223,44 +2502,14 @@ int unit_file_get_list(
+                         if (!f->path)
+                                 return -ENOMEM;
+ 
+-                        r = null_or_empty_path(f->path);
+-                        if (r < 0 && r != -ENOENT)
+-                                return r;
+-                        else if (r > 0) {
+-                                f->state =
+-                                        path_startswith(*i, "/run") ?
+-                                        UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
+-                                goto found;
+-                        }
+-
+-                        r = find_symlinks_in_scope(scope, root_dir, de->d_name, &f->state);
++                        r = unit_file_lookup_state(scope, root_dir, &paths, basename(f->path), &f->state);
+                         if (r < 0)
+-                                return r;
+-                        else if (r > 0) {
+-                                f->state = UNIT_FILE_ENABLED;
+-                                goto found;
+-                        }
+-
+-                        path = path_make_absolute(de->d_name, *i);
+-                        if (!path)
+-                                return -ENOMEM;
++                                f->state = UNIT_FILE_BAD;
+ 
+-                        r = unit_file_can_install(&paths, root_dir, path, true, NULL);
+-                        if (r == -EINVAL ||  /* Invalid setting? */
+-                            r == -EBADMSG || /* Invalid format? */
+-                            r == -ENOENT     /* Included file not found? */)
+-                                f->state = UNIT_FILE_INVALID;
+-                        else if (r < 0)
+-                                return r;
+-                        else if (r > 0)
+-                                f->state = UNIT_FILE_DISABLED;
+-                        else
+-                                f->state = UNIT_FILE_STATIC;
+-
+-                found:
+                         r = hashmap_put(h, basename(f->path), f);
+                         if (r < 0)
+                                 return r;
++
+                         f = NULL; /* prevent cleanup */
+                 }
+         }
+@@ -2278,7 +2527,7 @@ static const char* const unit_file_state_table[_UNIT_FILE_STATE_MAX] = {
+         [UNIT_FILE_STATIC] = "static",
+         [UNIT_FILE_DISABLED] = "disabled",
+         [UNIT_FILE_INDIRECT] = "indirect",
+-        [UNIT_FILE_INVALID] = "invalid",
++        [UNIT_FILE_BAD] = "bad",
+ };
+ 
+ DEFINE_STRING_TABLE_LOOKUP(unit_file_state, UnitFileState);
+diff --git a/src/shared/install.h b/src/shared/install.h
+index d729e6e..87a40b6 100644
+--- a/src/shared/install.h
++++ b/src/shared/install.h
+@@ -24,6 +24,7 @@
+ #include "hashmap.h"
+ #include "unit-name.h"
+ #include "path-lookup.h"
++#include "strv.h"
+ 
+ typedef enum UnitFileScope {
+         UNIT_FILE_SYSTEM,
+@@ -43,7 +44,7 @@ typedef enum UnitFileState {
+         UNIT_FILE_STATIC,
+         UNIT_FILE_DISABLED,
+         UNIT_FILE_INDIRECT,
+-        UNIT_FILE_INVALID,
++        UNIT_FILE_BAD,
+         _UNIT_FILE_STATE_MAX,
+         _UNIT_FILE_STATE_INVALID = -1
+ } UnitFileState;
+@@ -74,6 +75,14 @@ typedef struct UnitFileList {
+         UnitFileState state;
+ } UnitFileList;
+ 
++typedef enum UnitFileType {
++        UNIT_FILE_TYPE_REGULAR,
++        UNIT_FILE_TYPE_SYMLINK,
++        UNIT_FILE_TYPE_MASKED,
++       _UNIT_FILE_TYPE_MAX,
++        _UNIT_FILE_TYPE_INVALID = -1,
++} UnitFileType;
++
+ typedef struct {
+         char *name;
+         char *path;
+@@ -85,8 +94,26 @@ typedef struct {
+         char **also;
+ 
+         char *default_instance;
++
++        UnitFileType type;
++
++        char *symlink_target;
+ } InstallInfo;
+ 
++static inline bool UNIT_FILE_INSTALL_INFO_HAS_RULES(InstallInfo *i) {
++        assert(i);
++
++        return !strv_isempty(i->aliases) ||
++               !strv_isempty(i->wanted_by) ||
++               !strv_isempty(i->required_by);
++}
++
++static inline bool UNIT_FILE_INSTALL_INFO_HAS_ALSO(InstallInfo *i) {
++        assert(i);
++
++        return !strv_isempty(i->also);
++}
++
+ int unit_file_enable(UnitFileScope scope, bool runtime, const char *root_dir, char **files, bool force, UnitFileChange **changes, unsigned *n_changes);
+ int unit_file_disable(UnitFileScope scope, bool runtime, const char *root_dir, char **files, UnitFileChange **changes, unsigned *n_changes);
+ int unit_file_reenable(UnitFileScope scope, bool runtime, const char *root_dir, char **files, bool force, UnitFileChange **changes, unsigned *n_changes);
+@@ -97,21 +124,14 @@ int unit_file_mask(UnitFileScope scope, bool runtime, const char *root_dir, char
+ int unit_file_unmask(UnitFileScope scope, bool runtime, const char *root_dir, char **files, UnitFileChange **changes, unsigned *n_changes);
+ int unit_file_set_default(UnitFileScope scope, const char *root_dir, const char *file, bool force, UnitFileChange **changes, unsigned *n_changes);
+ int unit_file_get_default(UnitFileScope scope, const char *root_dir, char **name);
+-int unit_file_add_dependency(UnitFileScope scope, bool runtime, const char *root_dir, char **files, char *target, UnitDependency dep, bool force, UnitFileChange **changes, unsigned *n_changes);
+-
+-UnitFileState unit_file_lookup_state(
+-                UnitFileScope scope,
+-                const char *root_dir,
+-                const LookupPaths *paths,
+-                const char *name);
+-UnitFileState unit_file_get_state(
+-                UnitFileScope scope,
+-                const char *root_dir,
+-                const char *filename);
++int unit_file_add_dependency(UnitFileScope scope, bool runtime, const char *root_dir, char **files, const char *target, UnitDependency dep, bool force, UnitFileChange **changes, unsigned *n_changes);
++
++int unit_file_lookup_state(UnitFileScope scope, const char *root_dir,const LookupPaths *paths, const char *name, UnitFileState *ret);
++int unit_file_get_state(UnitFileScope scope, const char *root_dir, const char *filename, UnitFileState *ret);
+ 
+ int unit_file_get_list(UnitFileScope scope, const char *root_dir, Hashmap *h);
++Hashmap* unit_file_list_free(Hashmap *h);
+ 
+-void unit_file_list_free(Hashmap *h);
+ int unit_file_changes_add(UnitFileChange **changes, unsigned *n_changes, UnitFileChangeType type, const char *path, const char *source);
+ void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes);
+ 
+diff --git a/src/shared/path-util.c b/src/shared/path-util.c
+index d5510bf..1181ffb 100644
+--- a/src/shared/path-util.c
++++ b/src/shared/path-util.c
+@@ -704,3 +704,37 @@ int fsck_exists(const char *fstype) {
+ 
+         return 0;
+ }
++
++char *prefix_root(const char *root, const char *path) {
++        char *n, *p;
++        size_t l;
++
++        /* If root is passed, prefixes path with it. Otherwise returns
++         * it as is. */
++
++        assert(path);
++
++        /* First, drop duplicate prefixing slashes from the path */
++        while (path[0] == '/' && path[1] == '/')
++                path++;
++
++        if (isempty(root) || path_equal(root, "/"))
++                return strdup(path);
++
++        l = strlen(root) + 1 + strlen(path) + 1;
++
++        n = new(char, l);
++        if (!n)
++                return NULL;
++
++        p = stpcpy(n, root);
++
++        while (p > n && p[-1] == '/')
++                p--;
++
++        if (path[0] != '/')
++                *(p++) = '/';
++
++        strcpy(p, path);
++        return n;
++}
+diff --git a/src/shared/path-util.h b/src/shared/path-util.h
+index ca81b49..71bb740 100644
+--- a/src/shared/path-util.h
++++ b/src/shared/path-util.h
+@@ -63,6 +63,33 @@ bool paths_check_timestamp(const char* const* paths, usec_t *paths_ts_usec, bool
+ 
+ int fsck_exists(const char *fstype);
+ 
++char *prefix_root(const char *root, const char *path);
++
++/* Similar to prefix_root(), but returns an alloca() buffer, or
++ * possibly a const pointer into the path parameter */
++#define prefix_roota(root, path)                                        \
++        ({                                                              \
++                const char* _path = (path), *_root = (root), *_ret;     \
++                char *_p, *_n;                                          \
++                size_t _l;                                              \
++                while (_path[0] == '/' && _path[1] == '/')              \
++                        _path ++;                                       \
++                if (isempty(_root) || path_equal(_root, "/"))           \
++                        _ret = _path;                                   \
++                else {                                                  \
++                        _l = strlen(_root) + 1 + strlen(_path) + 1;     \
++                        _n = alloca(_l);                                \
++                        _p = stpcpy(_n, _root);                         \
++                        while (_p > _n && _p[-1] == '/')                \
++                                _p--;                                   \
++                        if (_path[0] != '/')                            \
++                                *(_p++) = '/';                          \
++                        strcpy(_p, _path);                              \
++                        _ret = _n;                                      \
++                }                                                       \
++                _ret;                                                   \
++        })
++
+ /* Iterates through the path prefixes of the specified path, going up
+  * the tree, to root. Also returns "" (and not "/"!) for the root
+  * directory. Excludes the specified directory itself */
+diff --git a/src/shared/unit-name.c b/src/shared/unit-name.c
+index f728af4..b7827d1 100644
+--- a/src/shared/unit-name.c
++++ b/src/shared/unit-name.c
+@@ -63,16 +63,13 @@ static const char* const unit_load_state_table[_UNIT_LOAD_STATE_MAX] = {
+ 
+ DEFINE_STRING_TABLE_LOOKUP(unit_load_state, UnitLoadState);
+ 
+-bool unit_name_is_valid(const char *n, enum template_valid template_ok) {
++bool unit_name_is_valid(const char *n, UnitNameFlags flags) {
+         const char *e, *i, *at;
+ 
+-        /* Valid formats:
+-         *
+-         *         string@instance.suffix
+-         *         string.suffix
+-         */
++        assert((flags & ~(UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE|UNIT_NAME_TEMPLATE)) == 0);
+ 
+-        assert(IN_SET(template_ok, TEMPLATE_VALID, TEMPLATE_INVALID));
++        if (_unlikely_(flags == 0))
++                return false;
+ 
+         if (isempty(n))
+                 return false;
+@@ -96,15 +93,22 @@ bool unit_name_is_valid(const char *n, enum template_valid template_ok) {
+                         return false;
+         }
+ 
+-        if (at) {
+-                if (at == n)
+-                        return false;
++        if (at == n)
++                return false;
+ 
+-                if (template_ok != TEMPLATE_VALID && at+1 == e)
+-                        return false;
+-        }
++        if (flags & UNIT_NAME_PLAIN)
++                if (!at)
++                        return true;
++
++        if (flags & UNIT_NAME_INSTANCE)
++                if (at && e > at + 1)
++                        return true;
++
++        if (flags & UNIT_NAME_TEMPLATE)
++                if (at && e == at + 1)
++                        return true;
+ 
+-        return true;
++        return false;
+ }
+ 
+ bool unit_instance_is_valid(const char *i) {
+diff --git a/src/shared/unit-name.h b/src/shared/unit-name.h
+index 6f139cc..4364860 100644
+--- a/src/shared/unit-name.h
++++ b/src/shared/unit-name.h
+@@ -107,6 +107,13 @@ enum UnitDependency {
+         _UNIT_DEPENDENCY_INVALID = -1
+ };
+ 
++typedef enum UnitNameFlags {
++        UNIT_NAME_PLAIN = 1,      /* Allow foo.service */
++        UNIT_NAME_INSTANCE = 2,   /* Allow foo@bar.service */
++        UNIT_NAME_TEMPLATE = 4,   /* Allow foo@.service */
++        UNIT_NAME_ANY = UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE|UNIT_NAME_TEMPLATE,
++} UnitNameFlags;
++
+ const char *unit_type_to_string(UnitType i) _const_;
+ UnitType unit_type_from_string(const char *s) _pure_;
+ 
+@@ -117,12 +124,7 @@ int unit_name_to_instance(const char *n, char **instance);
+ char* unit_name_to_prefix(const char *n);
+ char* unit_name_to_prefix_and_instance(const char *n);
+ 
+-enum template_valid {
+-        TEMPLATE_INVALID,
+-        TEMPLATE_VALID,
+-};
+-
+-bool unit_name_is_valid(const char *n, enum template_valid template_ok) _pure_;
++bool unit_name_is_valid(const char *n, UnitNameFlags flags) _pure_;
+ bool unit_prefix_is_valid(const char *p) _pure_;
+ bool unit_instance_is_valid(const char *i) _pure_;
+ 
+diff --git a/src/shared/util.c b/src/shared/util.c
+index a24aa7f..036677e 100644
+--- a/src/shared/util.c
++++ b/src/shared/util.c
+@@ -1094,6 +1094,27 @@ int readlink_and_canonicalize(const char *p, char **r) {
+         return 0;
+ }
+ 
++
++int readlink_and_make_absolute_root(const char *root, const char *path, char **ret) {
++        _cleanup_free_ char *target = NULL, *t = NULL;
++        const char *full;
++        int r;
++
++        full = prefix_roota(root, path);
++        r = readlink_malloc(full, &target);
++        if (r < 0)
++                return r;
++
++        t = file_in_same_dir(path, target);
++        if (!t)
++                return -ENOMEM;
++
++        *ret = t;
++        t = NULL;
++
++        return 0;
++}
++
+ int reset_all_signal_handlers(void) {
+         int sig, r = 0;
+ 
+diff --git a/src/shared/util.h b/src/shared/util.h
+index b4a4a49..a441e44 100644
+--- a/src/shared/util.h
++++ b/src/shared/util.h
+@@ -281,6 +281,7 @@ int readlink_malloc(const char *p, char **r);
+ int readlink_value(const char *p, char **ret);
+ int readlink_and_make_absolute(const char *p, char **r);
+ int readlink_and_canonicalize(const char *p, char **r);
++int readlink_and_make_absolute_root(const char *root, const char *path, char **ret);
+ 
+ int reset_all_signal_handlers(void);
+ int reset_signal_mask(void);
+diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
+index bf5bb39..95ddf3b 100644
+--- a/src/systemctl/systemctl.c
++++ b/src/systemctl/systemctl.c
+@@ -1304,7 +1304,7 @@ static void output_unit_file_list(const UnitFileList *units, unsigned c) {
+                 if (u->state == UNIT_FILE_MASKED ||
+                     u->state == UNIT_FILE_MASKED_RUNTIME ||
+                     u->state == UNIT_FILE_DISABLED ||
+-                    u->state == UNIT_FILE_INVALID) {
++                    u->state == UNIT_FILE_BAD) {
+                         on  = ansi_highlight_red();
+                         off = ansi_highlight_off();
+                 } else if (u->state == UNIT_FILE_ENABLED) {
+@@ -5637,8 +5637,8 @@ static int unit_is_enabled(sd_bus *bus, char **args) {
+                 STRV_FOREACH(name, names) {
+                         UnitFileState state;
+ 
+-                        state = unit_file_get_state(arg_scope, arg_root, *name);
+-                        if (state < 0)
++                        r = unit_file_get_state(arg_scope, arg_root, *name, &state);
++                        if (r < 0)
+                                 return log_error_errno(state, "Failed to get unit file state for %s: %m", *name);
+ 
+                         if (state == UNIT_FILE_ENABLED ||
+diff --git a/src/sysv-generator/sysv-generator.c b/src/sysv-generator/sysv-generator.c
+index d60e75a..7e0e7fc 100644
+--- a/src/sysv-generator/sysv-generator.c
++++ b/src/sysv-generator/sysv-generator.c
+@@ -712,6 +712,7 @@ static int fix_order(SysvStub *s, Hashmap *all_services) {
+ 
+ static int enumerate_sysv(const LookupPaths *lp, Hashmap *all_services) {
+         char **path;
++        int r;
+ 
+         STRV_FOREACH(path, lp->sysvinit_path) {
+                 _cleanup_closedir_ DIR *d = NULL;
+@@ -728,7 +729,6 @@ static int enumerate_sysv(const LookupPaths *lp, Hashmap *all_services) {
+                         _cleanup_free_ char *fpath = NULL, *name = NULL;
+                         _cleanup_free_ SysvStub *service = NULL;
+                         struct stat st;
+-                        int r;
+ 
+                         if (hidden_file(de->d_name))
+                                 continue;
+@@ -755,8 +755,12 @@ static int enumerate_sysv(const LookupPaths *lp, Hashmap *all_services) {
+                         if (!fpath)
+                                 return log_oom();
+ 
+-                        if (unit_file_lookup_state(UNIT_FILE_SYSTEM, NULL, lp, name) >= 0) {
+-                                log_debug("Native unit for %s already exists, skipping", name);
++                        r = unit_file_lookup_state(UNIT_FILE_SYSTEM, NULL, lp, name, NULL);
++                        if (r < 0 && r != -ENOENT) {
++                                log_debug_errno(r, "Failed to detect whether %s exists, skipping: %m", name);
++                                continue;
++                        } else if (r >= 0) {
++                                log_debug("Native unit for %s already exists, skipping.", name);
+                                 continue;
+                         }
+ 
+diff --git a/src/test/test-install-root.c b/src/test/test-install-root.c
+new file mode 100644
+index 0000000..89d91d3
+--- /dev/null
++++ b/src/test/test-install-root.c
+@@ -0,0 +1,663 @@
++/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
++
++/***
++  This file is part of systemd.
++
++  Copyright 2011 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 "fileio.h"
++#include "install.h"
++#include "mkdir.h"
++#include "util.h"
++
++static void test_basic_mask_and_enable(const char *root) {
++        const char *p;
++        UnitFileState state;
++        UnitFileChange *changes = NULL;
++        unsigned n_changes = 0;
++
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", NULL) == -ENOENT);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", NULL) == -ENOENT);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", NULL) == -ENOENT);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", NULL) == -ENOENT);
++
++        p = strjoina(root, "/usr/lib/systemd/system/a.service");
++        assert_se(write_string_file(p,
++                                    "[Install]\n"
++                                    "WantedBy=multi-user.target\n") >= 0);
++
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", NULL) >= 0);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
++
++        p = strjoina(root, "/usr/lib/systemd/system/b.service");
++        assert_se(symlink("a.service", p) >= 0);
++
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", NULL) >= 0);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
++
++        p = strjoina(root, "/usr/lib/systemd/system/c.service");
++        assert_se(symlink("/usr/lib/systemd/system/a.service", p) >= 0);
++
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", NULL) >= 0);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
++
++        p = strjoina(root, "/usr/lib/systemd/system/d.service");
++        assert_se(symlink("c.service", p) >= 0);
++
++        /* This one is interesting, as d follows a relative, then an absolute symlink */
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", NULL) >= 0);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
++
++        assert_se(unit_file_mask(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("a.service"), false, &changes, &n_changes) >= 0);
++        assert_se(n_changes == 1);
++        assert_se(changes[0].type == UNIT_FILE_SYMLINK);
++        assert_se(streq(changes[0].source, "/dev/null"));
++        p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/a.service");
++        assert_se(streq(changes[0].path, p));
++
++        unit_file_changes_free(changes, n_changes);
++        changes = NULL; n_changes = 0;
++
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_MASKED);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_MASKED);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_MASKED);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_MASKED);
++
++        /* Enabling a masked unit should fail! */
++        assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("a.service"), false, &changes, &n_changes) == -ESHUTDOWN);
++        unit_file_changes_free(changes, n_changes);
++        changes = NULL; n_changes = 0;
++
++        assert_se(unit_file_unmask(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("a.service"), &changes, &n_changes) >= 0);
++        assert_se(n_changes == 1);
++        assert_se(changes[0].type == UNIT_FILE_UNLINK);
++        p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/a.service");
++        assert_se(streq(changes[0].path, p));
++        unit_file_changes_free(changes, n_changes);
++        changes = NULL; n_changes = 0;
++
++        assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("a.service"), false, &changes, &n_changes) == 1);
++        assert_se(n_changes == 1);
++        assert_se(changes[0].type == UNIT_FILE_SYMLINK);
++        assert_se(streq(changes[0].source, "/usr/lib/systemd/system/a.service"));
++        p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/a.service");
++        assert_se(streq(changes[0].path, p));
++        unit_file_changes_free(changes, n_changes);
++        changes = NULL; n_changes = 0;
++
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
++
++        /* Enabling it again should succeed but be a NOP */
++        assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("a.service"), false, &changes, &n_changes) == 1);
++        assert_se(n_changes == 0);
++        unit_file_changes_free(changes, n_changes);
++        changes = NULL; n_changes = 0;
++
++        assert_se(unit_file_disable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("a.service"), &changes, &n_changes) >= 0);
++        assert_se(n_changes == 1);
++        assert_se(changes[0].type == UNIT_FILE_UNLINK);
++        p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/a.service");
++        assert_se(streq(changes[0].path, p));
++        unit_file_changes_free(changes, n_changes);
++        changes = NULL; n_changes = 0;
++
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
++
++        /* Disabling a disabled unit must suceed but be a NOP */
++        assert_se(unit_file_disable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("a.service"), &changes, &n_changes) >= 0);
++        assert_se(n_changes == 0);
++        unit_file_changes_free(changes, n_changes);
++        changes = NULL; n_changes = 0;
++
++        /* Let's enable this indirectly via a symlink */
++        assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("d.service"), false, &changes, &n_changes) >= 0);
++        assert_se(n_changes == 1);
++        assert_se(changes[0].type == UNIT_FILE_SYMLINK);
++        assert_se(streq(changes[0].source, "/usr/lib/systemd/system/a.service"));
++        p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/a.service");
++        assert_se(streq(changes[0].path, p));
++        unit_file_changes_free(changes, n_changes);
++        changes = NULL; n_changes = 0;
++
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
++
++        /* Let's try to reenable */
++
++        assert_se(unit_file_reenable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("b.service"), false, &changes, &n_changes) >= 0);
++        assert_se(n_changes == 2);
++        assert_se(changes[0].type == UNIT_FILE_UNLINK);
++        p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/a.service");
++        assert_se(streq(changes[0].path, p));
++        assert_se(changes[1].type == UNIT_FILE_SYMLINK);
++        assert_se(streq(changes[1].source, "/usr/lib/systemd/system/a.service"));
++        assert_se(streq(changes[1].path, p));
++        unit_file_changes_free(changes, n_changes);
++        changes = NULL; n_changes = 0;
++
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
++}
++
++static void test_linked_units(const char *root) {
++        const char *p, *q;
++        UnitFileState state;
++        UnitFileChange *changes = NULL;
++        unsigned n_changes = 0, i;
++
++        /*
++         * We'll test three cases here:
++         *
++         * a) a unit file in /opt, that we use "systemctl link" and
++         * "systemctl enable" on to make it available to the system
++         *
++         * b) a unit file in /opt, that is statically linked into
++         * /usr/lib/systemd/system, that "enable" should work on
++         * correctly.
++         *
++         * c) a unit file in /opt, that is linked into
++         * /etc/systemd/system, and where "enable" should result in
++         * -ELOOP, since using information from /etc to generate
++         * information in /etc should not be allowed.
++         */
++
++        p = strjoina(root, "/opt/linked.service");
++        assert_se(write_string_file(p,
++                                    "[Install]\n"
++                                    "WantedBy=multi-user.target\n") >= 0);
++
++        p = strjoina(root, "/opt/linked2.service");
++        assert_se(write_string_file(p,
++                                    "[Install]\n"
++                                    "WantedBy=multi-user.target\n") >= 0);
++
++        p = strjoina(root, "/opt/linked3.service");
++        assert_se(write_string_file(p,
++                                    "[Install]\n"
++                                    "WantedBy=multi-user.target\n") >= 0);
++
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", NULL) == -ENOENT);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked2.service", NULL) == -ENOENT);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked3.service", NULL) == -ENOENT);
++
++        p = strjoina(root, "/usr/lib/systemd/system/linked2.service");
++        assert_se(symlink("/opt/linked2.service", p) >= 0);
++
++        p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked3.service");
++        assert_se(symlink("/opt/linked3.service", p) >= 0);
++
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", &state) == -ENOENT);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked2.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked3.service", &state) >= 0 && state == UNIT_FILE_LINKED);
++
++        /* First, let's link the unit into the search path */
++        assert_se(unit_file_link(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("/opt/linked.service"), false, &changes, &n_changes) >= 0);
++        assert_se(n_changes == 1);
++        assert_se(changes[0].type == UNIT_FILE_SYMLINK);
++        assert_se(streq(changes[0].source, "/opt/linked.service"));
++        p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked.service");
++        assert_se(streq(changes[0].path, p));
++        unit_file_changes_free(changes, n_changes);
++        changes = NULL; n_changes = 0;
++
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", &state) >= 0 && state == UNIT_FILE_LINKED);
++
++        /* Let's unlink it from the search path again */
++        assert_se(unit_file_disable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("linked.service"), &changes, &n_changes) >= 0);
++        assert_se(n_changes == 1);
++        assert_se(changes[0].type == UNIT_FILE_UNLINK);
++        p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked.service");
++        assert_se(streq(changes[0].path, p));
++        unit_file_changes_free(changes, n_changes);
++        changes = NULL; n_changes = 0;
++
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", NULL) == -ENOENT);
++
++        /* Now, let's not just link it, but also enable it */
++        assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("/opt/linked.service"), false, &changes, &n_changes) >= 0);
++        assert_se(n_changes == 2);
++        p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/linked.service");
++        q = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked.service");
++        for (i = 0 ; i < n_changes; i++) {
++                assert_se(changes[i].type == UNIT_FILE_SYMLINK);
++                assert_se(streq(changes[i].source, "/opt/linked.service"));
++
++                if (p && streq(changes[i].path, p))
++                        p = NULL;
++                else if (q && streq(changes[i].path, q))
++                        q = NULL;
++                else
++                        assert_not_reached("wut?");
++        }
++        assert(!p && !q);
++        unit_file_changes_free(changes, n_changes);
++        changes = NULL; n_changes = 0;
++
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
++
++        /* And let's unlink it again */
++        assert_se(unit_file_disable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("linked.service"), &changes, &n_changes) >= 0);
++        assert_se(n_changes == 2);
++        p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/linked.service");
++        q = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked.service");
++        for (i = 0; i < n_changes; i++) {
++                assert_se(changes[i].type == UNIT_FILE_UNLINK);
++
++                if (p && streq(changes[i].path, p))
++                        p = NULL;
++                else if (q && streq(changes[i].path, q))
++                        q = NULL;
++                else
++                        assert_not_reached("wut?");
++        }
++        assert(!p && !q);
++        unit_file_changes_free(changes, n_changes);
++        changes = NULL; n_changes = 0;
++
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", NULL) == -ENOENT);
++
++        assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("linked2.service"), false, &changes, &n_changes) >= 0);
++        assert_se(n_changes == 2);
++        p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/linked2.service");
++        q = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked2.service");
++        for (i = 0 ; i < n_changes; i++) {
++                assert_se(changes[i].type == UNIT_FILE_SYMLINK);
++                assert_se(streq(changes[i].source, "/opt/linked2.service"));
++
++                if (p && streq(changes[i].path, p))
++                        p = NULL;
++                else if (q && streq(changes[i].path, q))
++                        q = NULL;
++                else
++                        assert_not_reached("wut?");
++        }
++        assert(!p && !q);
++        unit_file_changes_free(changes, n_changes);
++        changes = NULL; n_changes = 0;
++
++        assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("linked3.service"), false, &changes, &n_changes) == -ELOOP);
++        unit_file_changes_free(changes, n_changes);
++        changes = NULL; n_changes = 0;
++}
++
++static void test_default(const char *root) {
++        _cleanup_free_ char *def = NULL;
++        UnitFileChange *changes = NULL;
++        unsigned n_changes = 0;
++        const char *p;
++
++        p = strjoina(root, "/usr/lib/systemd/system/test-default-real.target");
++        assert_se(write_string_file(p, "# pretty much empty") >= 0);
++
++        p = strjoina(root, "/usr/lib/systemd/system/test-default.target");
++        assert_se(symlink("test-default-real.target", p) >= 0);
++
++        assert_se(unit_file_get_default(UNIT_FILE_SYSTEM, root, &def) == -ENOENT);
++
++        assert_se(unit_file_set_default(UNIT_FILE_SYSTEM, root, "idontexist.target", false, &changes, &n_changes) == -ENOENT);
++        assert_se(n_changes == 0);
++        unit_file_changes_free(changes, n_changes);
++        changes = NULL; n_changes = 0;
++
++        assert_se(unit_file_get_default(UNIT_FILE_SYSTEM, root, &def) == -ENOENT);
++
++        assert_se(unit_file_set_default(UNIT_FILE_SYSTEM, root, "test-default.target", false, &changes, &n_changes) >= 0);
++        assert_se(n_changes == 1);
++        assert_se(changes[0].type == UNIT_FILE_SYMLINK);
++        assert_se(streq(changes[0].source, "/usr/lib/systemd/system/test-default-real.target"));
++        p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/default.target");
++        assert_se(streq(changes[0].path, p));
++        unit_file_changes_free(changes, n_changes);
++        changes = NULL; n_changes = 0;
++
++        assert_se(unit_file_get_default(UNIT_FILE_SYSTEM, root, &def) >= 0);
++        assert_se(streq_ptr(def, "test-default-real.target"));
++}
++
++static void test_add_dependency(const char *root) {
++        UnitFileChange *changes = NULL;
++        unsigned n_changes = 0;
++        const char *p;
++
++        p = strjoina(root, "/usr/lib/systemd/system/real-add-dependency-test-target.target");
++        assert_se(write_string_file(p, "# pretty much empty") >= 0);
++
++        p = strjoina(root, "/usr/lib/systemd/system/add-dependency-test-target.target");
++        assert_se(symlink("real-add-dependency-test-target.target", p) >= 0);
++
++        p = strjoina(root, "/usr/lib/systemd/system/real-add-dependency-test-service.service");
++        assert_se(write_string_file(p, "# pretty much empty") >= 0);
++
++        p = strjoina(root, "/usr/lib/systemd/system/add-dependency-test-service.service");
++        assert_se(symlink("real-add-dependency-test-service.service", p) >= 0);
++
++        assert_se(unit_file_add_dependency(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("add-dependency-test-service.service"), "add-dependency-test-target.target", UNIT_WANTS, false, &changes, &n_changes) >= 0);
++        assert_se(n_changes == 1);
++        assert_se(changes[0].type == UNIT_FILE_SYMLINK);
++        assert_se(streq(changes[0].source, "/usr/lib/systemd/system/real-add-dependency-test-service.service"));
++        p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/real-add-dependency-test-target.target.wants/real-add-dependency-test-service.service");
++        assert_se(streq(changes[0].path, p));
++        unit_file_changes_free(changes, n_changes);
++        changes = NULL; n_changes = 0;
++}
++
++static void test_template_enable(const char *root) {
++        UnitFileChange *changes = NULL;
++        unsigned n_changes = 0;
++        UnitFileState state;
++        const char *p;
++
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) == -ENOENT);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) == -ENOENT);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) == -ENOENT);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) == -ENOENT);
++
++        p = strjoina(root, "/usr/lib/systemd/system/template@.service");
++        assert_se(write_string_file(p,
++                                    "[Install]\n"
++                                    "DefaultInstance=def\n"
++                                    "WantedBy=multi-user.target\n") >= 0);
++
++        p = strjoina(root, "/usr/lib/systemd/system/template-symlink@.service");
++        assert_se(symlink("template@.service", p) >= 0);
++
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
++
++        assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("template@.service"), false, &changes, &n_changes) >= 0);
++        assert_se(n_changes == 1);
++        assert_se(changes[0].type == UNIT_FILE_SYMLINK);
++        assert_se(streq(changes[0].source, "/usr/lib/systemd/system/template@.service"));
++        p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/template@def.service");
++        assert_se(streq(changes[0].path, p));
++        unit_file_changes_free(changes, n_changes);
++        changes = NULL; n_changes = 0;
++
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
++
++        assert_se(unit_file_disable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("template@.service"), &changes, &n_changes) >= 0);
++        assert_se(n_changes == 1);
++        assert_se(changes[0].type == UNIT_FILE_UNLINK);
++        assert_se(streq(changes[0].path, p));
++        unit_file_changes_free(changes, n_changes);
++        changes = NULL; n_changes = 0;
++
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
++
++        assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("template@foo.service"), false, &changes, &n_changes) >= 0);
++        assert_se(changes[0].type == UNIT_FILE_SYMLINK);
++        assert_se(streq(changes[0].source, "/usr/lib/systemd/system/template@.service"));
++        p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/template@foo.service");
++        assert_se(streq(changes[0].path, p));
++        unit_file_changes_free(changes, n_changes);
++        changes = NULL; n_changes = 0;
++
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
++
++        assert_se(unit_file_disable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("template@foo.service"), &changes, &n_changes) >= 0);
++        assert_se(n_changes == 1);
++        assert_se(changes[0].type == UNIT_FILE_UNLINK);
++        assert_se(streq(changes[0].path, p));
++        unit_file_changes_free(changes, n_changes);
++        changes = NULL; n_changes = 0;
++
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@quux.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@quux.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
++
++        assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("template-symlink@quux.service"), false, &changes, &n_changes) >= 0);
++        assert_se(changes[0].type == UNIT_FILE_SYMLINK);
++        assert_se(streq(changes[0].source, "/usr/lib/systemd/system/template@.service"));
++        p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/template@quux.service");
++        assert_se(streq(changes[0].path, p));
++        unit_file_changes_free(changes, n_changes);
++        changes = NULL; n_changes = 0;
++
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@quux.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@quux.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
++}
++
++static void test_indirect(const char *root) {
++        UnitFileChange *changes = NULL;
++        unsigned n_changes = 0;
++        UnitFileState state;
++        const char *p;
++
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirecta.service", &state) == -ENOENT);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectb.service", &state) == -ENOENT);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectc.service", &state) == -ENOENT);
++
++        p = strjoina(root, "/usr/lib/systemd/system/indirecta.service");
++        assert_se(write_string_file(p,
++                                    "[Install]\n"
++                                    "Also=indirectb.service\n") >= 0);
++
++        p = strjoina(root, "/usr/lib/systemd/system/indirectb.service");
++        assert_se(write_string_file(p,
++                                    "[Install]\n"
++                                    "WantedBy=multi-user.target\n") >= 0);
++
++        p = strjoina(root, "/usr/lib/systemd/system/indirectc.service");
++        assert_se(symlink("indirecta.service", p) >= 0);
++
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirecta.service", &state) >= 0 && state == UNIT_FILE_INDIRECT);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectb.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectc.service", &state) >= 0 && state == UNIT_FILE_INDIRECT);
++
++        assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("indirectc.service"), false, &changes, &n_changes) >= 0);
++        assert_se(n_changes == 1);
++        assert_se(changes[0].type == UNIT_FILE_SYMLINK);
++        assert_se(streq(changes[0].source, "/usr/lib/systemd/system/indirectb.service"));
++        p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/indirectb.service");
++        assert_se(streq(changes[0].path, p));
++        unit_file_changes_free(changes, n_changes);
++        changes = NULL; n_changes = 0;
++
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirecta.service", &state) >= 0 && state == UNIT_FILE_INDIRECT);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectb.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectc.service", &state) >= 0 && state == UNIT_FILE_INDIRECT);
++
++        assert_se(unit_file_disable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("indirectc.service"), &changes, &n_changes) >= 0);
++        assert_se(n_changes == 1);
++        assert_se(changes[0].type == UNIT_FILE_UNLINK);
++        p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/indirectb.service");
++        assert_se(streq(changes[0].path, p));
++        unit_file_changes_free(changes, n_changes);
++        changes = NULL; n_changes = 0;
++}
++
++static void test_preset_and_list(const char *root) {
++        UnitFileChange *changes = NULL;
++        unsigned n_changes = 0, i;
++        const char *p, *q;
++        UnitFileState state;
++        bool got_yes = false, got_no = false;
++        Iterator j;
++        UnitFileList *fl;
++        Hashmap *h;
++
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) == -ENOENT);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) == -ENOENT);
++
++        p = strjoina(root, "/usr/lib/systemd/system/preset-yes.service");
++        assert_se(write_string_file(p,
++                                    "[Install]\n"
++                                    "WantedBy=multi-user.target\n") >= 0);
++
++        p = strjoina(root, "/usr/lib/systemd/system/preset-no.service");
++        assert_se(write_string_file(p,
++                                    "[Install]\n"
++                                    "WantedBy=multi-user.target\n") >= 0);
++
++        p = strjoina(root, "/usr/lib/systemd/system-preset/test.preset");
++        assert_se(write_string_file(p,
++                                    "enable *-yes.*\n"
++                                    "disable *\n") >= 0);
++
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
++
++        assert_se(unit_file_preset(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("preset-yes.service"), UNIT_FILE_PRESET_FULL, false, &changes, &n_changes) >= 0);
++        assert_se(n_changes == 1);
++        assert_se(changes[0].type == UNIT_FILE_SYMLINK);
++        assert_se(streq(changes[0].source, "/usr/lib/systemd/system/preset-yes.service"));
++        p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/preset-yes.service");
++        assert_se(streq(changes[0].path, p));
++        unit_file_changes_free(changes, n_changes);
++        changes = NULL; n_changes = 0;
++
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
++
++        assert_se(unit_file_disable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("preset-yes.service"), &changes, &n_changes) >= 0);
++        assert_se(n_changes == 1);
++        assert_se(changes[0].type == UNIT_FILE_UNLINK);
++        p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/preset-yes.service");
++        assert_se(streq(changes[0].path, p));
++        unit_file_changes_free(changes, n_changes);
++        changes = NULL; n_changes = 0;
++
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
++
++        assert_se(unit_file_preset(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("preset-no.service"), UNIT_FILE_PRESET_FULL, false, &changes, &n_changes) >= 0);
++        assert_se(n_changes == 0);
++        unit_file_changes_free(changes, n_changes);
++        changes = NULL; n_changes = 0;
++
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
++
++        assert_se(unit_file_preset_all(UNIT_FILE_SYSTEM, false, root, UNIT_FILE_PRESET_FULL, false, &changes, &n_changes) >= 0);
++
++        assert_se(n_changes > 0);
++
++        p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/preset-yes.service");
++
++        for (i = 0; i < n_changes; i++) {
++
++                if (changes[i].type == UNIT_FILE_SYMLINK) {
++                        assert_se(streq(changes[i].source, "/usr/lib/systemd/system/preset-yes.service"));
++                        assert_se(streq(changes[i].path, p));
++                } else
++                        assert_se(changes[i].type == UNIT_FILE_UNLINK);
++        }
++
++        unit_file_changes_free(changes, n_changes);
++        changes = NULL; n_changes = 0;
++
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
++        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
++
++        assert_se(h = hashmap_new(&string_hash_ops));
++        assert_se(unit_file_get_list(UNIT_FILE_SYSTEM, root, h) >= 0);
++
++        p = strjoina(root, "/usr/lib/systemd/system/preset-yes.service");
++        q = strjoina(root, "/usr/lib/systemd/system/preset-no.service");
++
++        HASHMAP_FOREACH(fl, h, j) {
++                assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, basename(fl->path), &state) >= 0);
++                assert_se(fl->state == state);
++
++                if (streq(fl->path, p)) {
++                        got_yes = true;
++                        assert_se(fl->state == UNIT_FILE_ENABLED);
++                } else if (streq(fl->path, q)) {
++                        got_no = true;
++                        assert_se(fl->state == UNIT_FILE_DISABLED);
++                } else
++                        assert_se(IN_SET(fl->state, UNIT_FILE_DISABLED, UNIT_FILE_STATIC, UNIT_FILE_INDIRECT));
++        }
++
++        unit_file_list_free(h);
++
++        assert_se(got_yes && got_no);
++}
++
++int main(int argc, char *argv[]) {
++        char root[] = "/tmp/rootXXXXXX";
++        const char *p;
++
++        assert_se(mkdtemp(root));
++
++        p = strjoina(root, "/usr/lib/systemd/system/");
++        assert_se(mkdir_p(p, 0755) >= 0);
++
++        p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/");
++        assert_se(mkdir_p(p, 0755) >= 0);
++
++        p = strjoina(root, "/run/systemd/system/");
++        assert_se(mkdir_p(p, 0755) >= 0);
++
++        p = strjoina(root, "/opt/");
++        assert_se(mkdir_p(p, 0755) >= 0);
++
++        p = strjoina(root, "/usr/lib/systemd/system-preset/");
++        assert_se(mkdir_p(p, 0755) >= 0);
++
++        test_basic_mask_and_enable(root);
++        test_linked_units(root);
++        test_default(root);
++        test_add_dependency(root);
++        test_template_enable(root);
++        test_indirect(root);
++        test_preset_and_list(root);
++
++        assert_se(rm_rf_dangerous(root, false, true, false));
++
++        return 0;
++}
+diff --git a/src/test/test-install.c b/src/test/test-install.c
+index 467970b..08a1faf 100644
+--- a/src/test/test-install.c
++++ b/src/test/test-install.c
+@@ -50,17 +50,19 @@ int main(int argc, char* argv[]) {
+         const char *const files2[] = { "/home/lennart/test.service", NULL };
+         UnitFileChange *changes = NULL;
+         unsigned n_changes = 0;
++        UnitFileState state = 0;
+ 
+         h = hashmap_new(&string_hash_ops);
+         r = unit_file_get_list(UNIT_FILE_SYSTEM, NULL, h);
+         assert_se(r == 0);
+ 
+         HASHMAP_FOREACH(p, h, i) {
+-                UnitFileState s;
++                UnitFileState s = _UNIT_FILE_STATE_INVALID;
+ 
+-                s = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(p->path));
++                r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(p->path), &s);
+ 
+-                assert_se(p->state == s);
++                assert_se((r < 0 && p->state == UNIT_FILE_BAD) ||
++                          (p->state == s));
+ 
+                 fprintf(stderr, "%s (%s)\n",
+                         p->path,
+@@ -82,7 +84,9 @@ int main(int argc, char* argv[]) {
+         dump_changes(changes, n_changes);
+         unit_file_changes_free(changes, n_changes);
+ 
+-        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0]) == UNIT_FILE_ENABLED);
++        r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0], &state);
++        assert_se(r >= 0);
++        assert_se(state == UNIT_FILE_ENABLED);
+ 
+         log_error("disable");
+ 
+@@ -95,7 +99,9 @@ int main(int argc, char* argv[]) {
+         dump_changes(changes, n_changes);
+         unit_file_changes_free(changes, n_changes);
+ 
+-        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0]) == UNIT_FILE_DISABLED);
++        r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0], &state);
++        assert_se(r >= 0);
++        assert_se(state == UNIT_FILE_DISABLED);
+ 
+         log_error("mask");
+         changes = NULL;
+@@ -110,7 +116,9 @@ int main(int argc, char* argv[]) {
+         dump_changes(changes, n_changes);
+         unit_file_changes_free(changes, n_changes);
+ 
+-        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0]) == UNIT_FILE_MASKED);
++        r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0], &state);
++        assert_se(r >= 0);
++        assert_se(state == UNIT_FILE_MASKED);
+ 
+         log_error("unmask");
+         changes = NULL;
+@@ -125,7 +133,9 @@ int main(int argc, char* argv[]) {
+         dump_changes(changes, n_changes);
+         unit_file_changes_free(changes, n_changes);
+ 
+-        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0]) == UNIT_FILE_DISABLED);
++        r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0], &state);
++        assert_se(r >= 0);
++        assert_se(state == UNIT_FILE_DISABLED);
+ 
+         log_error("mask");
+         changes = NULL;
+@@ -137,7 +147,9 @@ int main(int argc, char* argv[]) {
+         dump_changes(changes, n_changes);
+         unit_file_changes_free(changes, n_changes);
+ 
+-        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0]) == UNIT_FILE_MASKED);
++        r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0], &state);
++        assert_se(r >= 0);
++        assert_se(state == UNIT_FILE_MASKED);
+ 
+         log_error("disable");
+         changes = NULL;
+@@ -152,7 +164,9 @@ int main(int argc, char* argv[]) {
+         dump_changes(changes, n_changes);
+         unit_file_changes_free(changes, n_changes);
+ 
+-        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0]) == UNIT_FILE_MASKED);
++        r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0], &state);
++        assert_se(r >= 0);
++        assert_se(state == UNIT_FILE_MASKED);
+ 
+         log_error("umask");
+         changes = NULL;
+@@ -164,7 +178,9 @@ int main(int argc, char* argv[]) {
+         dump_changes(changes, n_changes);
+         unit_file_changes_free(changes, n_changes);
+ 
+-        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0]) == UNIT_FILE_DISABLED);
++        r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0], &state);
++        assert_se(r >= 0);
++        assert_se(state == UNIT_FILE_DISABLED);
+ 
+         log_error("enable files2");
+         changes = NULL;
+@@ -176,19 +192,22 @@ int main(int argc, char* argv[]) {
+         dump_changes(changes, n_changes);
+         unit_file_changes_free(changes, n_changes);
+ 
+-        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0])) == UNIT_FILE_ENABLED);
++        r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0]), &state);
++        assert_se(r >= 0);
++        assert_se(state == UNIT_FILE_ENABLED);
+ 
+         log_error("disable files2");
+         changes = NULL;
+         n_changes = 0;
+ 
+-        r = unit_file_disable(UNIT_FILE_SYSTEM, false, NULL, (char**) files2, &changes, &n_changes);
++        r = unit_file_disable(UNIT_FILE_SYSTEM, false, NULL, STRV_MAKE(basename(files2[0])), &changes, &n_changes);
+         assert_se(r >= 0);
+ 
+         dump_changes(changes, n_changes);
+         unit_file_changes_free(changes, n_changes);
+ 
+-        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0])) == _UNIT_FILE_STATE_INVALID);
++        r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0]), &state);
++        assert_se(r < 0);
+ 
+         log_error("link files2");
+         changes = NULL;
+@@ -200,19 +219,22 @@ int main(int argc, char* argv[]) {
+         dump_changes(changes, n_changes);
+         unit_file_changes_free(changes, n_changes);
+ 
+-        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0])) == UNIT_FILE_LINKED);
++        r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0]), &state);
++        assert_se(r >= 0);
++        assert_se(state == UNIT_FILE_LINKED);
+ 
+         log_error("disable files2");
+         changes = NULL;
+         n_changes = 0;
+ 
+-        r = unit_file_disable(UNIT_FILE_SYSTEM, false, NULL, (char**) files2, &changes, &n_changes);
++        r = unit_file_disable(UNIT_FILE_SYSTEM, false, NULL, STRV_MAKE(basename(files2[0])), &changes, &n_changes);
+         assert_se(r >= 0);
+ 
+         dump_changes(changes, n_changes);
+         unit_file_changes_free(changes, n_changes);
+ 
+-        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0])) == _UNIT_FILE_STATE_INVALID);
++        r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0]), &state);
++        assert_se(r < 0);
+ 
+         log_error("link files2");
+         changes = NULL;
+@@ -224,7 +246,9 @@ int main(int argc, char* argv[]) {
+         dump_changes(changes, n_changes);
+         unit_file_changes_free(changes, n_changes);
+ 
+-        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0])) == UNIT_FILE_LINKED);
++        r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0]), &state);
++        assert_se(r >= 0);
++        assert_se(state == UNIT_FILE_LINKED);
+ 
+         log_error("reenable files2");
+         changes = NULL;
+@@ -236,19 +260,22 @@ int main(int argc, char* argv[]) {
+         dump_changes(changes, n_changes);
+         unit_file_changes_free(changes, n_changes);
+ 
+-        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0])) == UNIT_FILE_ENABLED);
++        r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0]), &state);
++        assert_se(r >= 0);
++        assert_se(state == UNIT_FILE_ENABLED);
+ 
+         log_error("disable files2");
+         changes = NULL;
+         n_changes = 0;
+ 
+-        r = unit_file_disable(UNIT_FILE_SYSTEM, false, NULL, (char**) files2, &changes, &n_changes);
++        r = unit_file_disable(UNIT_FILE_SYSTEM, false, NULL, STRV_MAKE(basename(files2[0])), &changes, &n_changes);
+         assert_se(r >= 0);
+ 
+         dump_changes(changes, n_changes);
+         unit_file_changes_free(changes, n_changes);
+ 
+-        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0])) == _UNIT_FILE_STATE_INVALID);
++        r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0]), &state);
++        assert_se(r < 0);
+         log_error("preset files");
+         changes = NULL;
+         n_changes = 0;
+@@ -259,7 +286,9 @@ int main(int argc, char* argv[]) {
+         dump_changes(changes, n_changes);
+         unit_file_changes_free(changes, n_changes);
+ 
+-        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files[0])) == UNIT_FILE_ENABLED);
++        r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files[0]), &state);
++        assert_se(r >= 0);
++        assert_se(state == UNIT_FILE_ENABLED);
+ 
+         return 0;
+ }
diff --git a/SOURCES/0297-core-look-for-instance-when-processing-template-name.patch b/SOURCES/0297-core-look-for-instance-when-processing-template-name.patch
new file mode 100644
index 0000000..6179f44
--- /dev/null
+++ b/SOURCES/0297-core-look-for-instance-when-processing-template-name.patch
@@ -0,0 +1,41 @@
+From 0e6ec33b5e8c8790e60d1b79801dc360dad010d3 Mon Sep 17 00:00:00 2001
+From: Michal Sekletar <msekleta@redhat.com>
+Date: Wed, 16 Mar 2016 15:47:18 +0100
+Subject: [PATCH] core: look for instance when processing template name
+
+If first attempt to merge units failed and we are trying to do
+merge the other way around and at the same time we are working with
+template name, then other unit can't possibly be template, because it is
+not possible to have template unit running, only instances of the
+template. Thus we need to look for already active instance instead.
+
+rhel-only (upstream review pending)
+
+Related: #1159308
+---
+ src/core/load-fragment.c | 11 ++++++++++-
+ 1 file changed, 10 insertions(+), 1 deletion(-)
+
+diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
+index 70c0918..b188ec9 100644
+--- a/src/core/load-fragment.c
++++ b/src/core/load-fragment.c
+@@ -3472,8 +3472,17 @@ static int merge_by_names(Unit **u, Set *names, const char *id) {
+                         /* Hmm, we couldn't merge the other unit into
+                          * ours? Then let's try it the other way
+                          * round */
++                        if (unit_name_is_template(k) && (*u)->instance) {
++                                _cleanup_free_ char *instance = NULL;
++
++                                instance = unit_name_replace_instance(k, (*u)->instance);
++                                if(!instance)
++                                        return -ENOMEM;
++                                other = manager_get_unit((*u)->manager, instance);
++
++                        } else
++                                other = manager_get_unit((*u)->manager, k);
+ 
+-                        other = manager_get_unit((*u)->manager, k);
+                         free(k);
+ 
+                         if (other) {
diff --git a/SOURCES/0298-core-improve-error-message-when-starting-template-wi.patch b/SOURCES/0298-core-improve-error-message-when-starting-template-wi.patch
new file mode 100644
index 0000000..c18cb11
--- /dev/null
+++ b/SOURCES/0298-core-improve-error-message-when-starting-template-wi.patch
@@ -0,0 +1,30 @@
+From 9b33863a2cfa31bbe57bab685776b64731f528f1 Mon Sep 17 00:00:00 2001
+From: Lukas Nykryn <lnykryn@redhat.com>
+Date: Wed, 30 Mar 2016 13:49:50 +0200
+Subject: [PATCH] core: improve error message when starting template without
+ instance
+
+Cherry-picked from: 5d512d54429aa9d2f4a0ca215bb2e982db720d6b
+Resolves: #1142369
+---
+ src/core/manager.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/src/core/manager.c b/src/core/manager.c
+index bde17ce..bb50503 100644
+--- a/src/core/manager.c
++++ b/src/core/manager.c
+@@ -1328,8 +1328,12 @@ int manager_load_unit_prepare(
+ 
+         t = unit_name_to_type(name);
+ 
+-        if (t == _UNIT_TYPE_INVALID || !unit_name_is_valid(name, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE))
++        if (t == _UNIT_TYPE_INVALID || !unit_name_is_valid(name, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE)) {
++                if (unit_name_is_valid(name, UNIT_NAME_TEMPLATE))
++                        return sd_bus_error_setf(e, SD_BUS_ERROR_INVALID_ARGS, "Unit name %s is missing the instance name.", name);
++
+                 return sd_bus_error_setf(e, SD_BUS_ERROR_INVALID_ARGS, "Unit name %s is not valid.", name);
++        }
+ 
+         ret = manager_get_unit(m, name);
+         if (ret) {
diff --git a/SOURCES/0299-man-tmpfiles.d-add-note-about-permissions-and-owners.patch b/SOURCES/0299-man-tmpfiles.d-add-note-about-permissions-and-owners.patch
new file mode 100644
index 0000000..2468eac
--- /dev/null
+++ b/SOURCES/0299-man-tmpfiles.d-add-note-about-permissions-and-owners.patch
@@ -0,0 +1,28 @@
+From b0edbac36cd75bfd5624f20884043553da14ced2 Mon Sep 17 00:00:00 2001
+From: Jan Synacek <jsynacek@redhat.com>
+Date: Wed, 13 Jan 2016 08:41:54 +0100
+Subject: [PATCH] man/tmpfiles.d: add note about permissions and ownership of
+ symlinks
+
+...because this is might not be obvious.
+
+Cherry-picked from: b908bb63c41eaf3c44004b6b737d105c39df2075
+Resolves: #1296288
+---
+ man/tmpfiles.d.xml | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/man/tmpfiles.d.xml b/man/tmpfiles.d.xml
+index 9b4e11c..fc1fe13 100644
+--- a/man/tmpfiles.d.xml
++++ b/man/tmpfiles.d.xml
+@@ -187,7 +187,8 @@
+           be removed and be replaced by the symlink. If the argument
+           is omitted, symlinks to files with the same name residing in
+           the directory <filename>/usr/share/factory/</filename> are
+-          created.</para></listitem>
++          created. Note that permissions and ownership on symlinks
++          are ignored.</para></listitem>
+         </varlistentry>
+ 
+         <varlistentry>
diff --git a/SOURCES/0300-tmpfiles-don-t-follow-symlinks-when-adjusting-ACLs-f.patch b/SOURCES/0300-tmpfiles-don-t-follow-symlinks-when-adjusting-ACLs-f.patch
new file mode 100644
index 0000000..973aaf0
--- /dev/null
+++ b/SOURCES/0300-tmpfiles-don-t-follow-symlinks-when-adjusting-ACLs-f.patch
@@ -0,0 +1,185 @@
+From 595a93d716680715a751737ec2f87b06ea582763 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Mon, 13 Apr 2015 15:16:54 +0200
+Subject: [PATCH] tmpfiles: don't follow symlinks when adjusting ACLs, fille
+ attributes, access modes or ownership
+
+Cherry-picked from: 48b8aaa82724bc2d8440470f414fb0d2416f29c
+Resolves: #1296288
+---
+ src/tmpfiles/tmpfiles.c | 112 ++++++++++++++++++++++++++++++++----------------
+ 1 file changed, 74 insertions(+), 38 deletions(-)
+
+diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
+index d0e6567..64c733a 100644
+--- a/src/tmpfiles/tmpfiles.c
++++ b/src/tmpfiles/tmpfiles.c
+@@ -570,51 +570,69 @@ finish:
+ }
+ 
+ static int path_set_perms(Item *i, const char *path) {
++        _cleanup_close_ int fd = -1;
+         struct stat st;
+-        bool st_valid;
+ 
+         assert(i);
+         assert(path);
+ 
+-        st_valid = stat(path, &st) == 0;
++        /* We open the file with O_PATH here, to make the operation
++         * somewhat atomic. Also there's unfortunately no fchmodat()
++         * with AT_SYMLINK_NOFOLLOW, hence we emulate it here via
++         * 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 (fstatat(fd, "", &st, AT_EMPTY_PATH) < 0)
++                return log_error_errno(errno, "Failed to fstat() file %s: %m", path);
++
++        if (S_ISLNK(st.st_mode))
++                log_debug("Skipping mode an owner fix for symlink %s.", path);
++        else {
++                char fn[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
++                xsprintf(fn, "/proc/self/fd/%i", fd);
+ 
+-        /* not using i->path directly because it may be a glob */
+-        if (i->mode_set) {
+-                mode_t m = i->mode;
++                /* not using i->path directly because it may be a glob */
++                if (i->mode_set) {
++                        mode_t m = i->mode;
+ 
+-                if (i->mask_perms && st_valid) {
+-                        if (!(st.st_mode & 0111))
+-                                m &= ~0111;
+-                        if (!(st.st_mode & 0222))
++                        if (i->mask_perms) {
++                                if (!(st.st_mode & 0111))
++                                        m &= ~0111;
++                                if (!(st.st_mode & 0222))
+                                 m &= ~0222;
+-                        if (!(st.st_mode & 0444))
+-                                m &= ~0444;
+-                        if (!S_ISDIR(st.st_mode))
+-                                m &= ~07000; /* remove sticky/sgid/suid bit, unless directory */
+-                }
++                                if (!(st.st_mode & 0444))
++                                        m &= ~0444;
++                                if (!S_ISDIR(st.st_mode))
++                                        m &= ~07000; /* remove sticky/sgid/suid bit, unless directory */
++                        }
+ 
+-                if (st_valid && m == (st.st_mode & 07777))
+-                        log_debug("\"%s\" has right mode %o", path, st.st_mode);
+-                else {
+-                        log_debug("chmod \"%s\" to mode %o", path, m);
+-                        if (chmod(path, m) < 0)
+-                                return log_error_errno(errno, "chmod(%s) failed: %m", path);
++                        if (m == (st.st_mode & 07777))
++                                log_debug("\"%s\" has right mode %o", path, st.st_mode);
++                        else {
++                                log_debug("chmod \"%s\" to mode %o", path, m);
++                                if (chmod(fn, m) < 0)
++                                        return log_error_errno(errno, "chmod(%s) failed: %m", path);
++                        }
+                 }
+-        }
+-
+-        if ((!st_valid || i->uid != st.st_uid || i->gid != st.st_gid) &&
+-            (i->uid_set || i->gid_set)) {
+-                log_debug("chown \"%s\" to "UID_FMT"."GID_FMT,
+-                          path,
+-                          i->uid_set ? i->uid : UID_INVALID,
+-                          i->gid_set ? i->gid : GID_INVALID);
+-                if (chown(path,
+-                          i->uid_set ? i->uid : UID_INVALID,
+-                          i->gid_set ? i->gid : GID_INVALID) < 0)
+ 
++                if ((i->uid != st.st_uid || i->gid != st.st_gid) &&
++                    (i->uid_set || i->gid_set)) {
++                        log_debug("chown \"%s\" to "UID_FMT"."GID_FMT,
++                                  path,
++                                  i->uid_set ? i->uid : UID_INVALID,
++                                  i->gid_set ? i->gid : GID_INVALID);
++                        if (chown(fn,
++                                  i->uid_set ? i->uid : UID_INVALID,
++                                  i->gid_set ? i->gid : GID_INVALID) < 0)
+                         return log_error_errno(errno, "chown(%s) failed: %m", path);
++                }
+         }
+ 
++        fd = safe_close(fd);
++
+         return label_fix(path, false, false);
+ }
+ 
+@@ -699,10 +717,10 @@ static int get_acls_from_arg(Item *item) {
+ }
+ 
+ #ifdef HAVE_ACL
+-static int path_set_acl(const char *path, acl_type_t type, acl_t acl, bool modify) {
++static int path_set_acl(const char *path, const char *pretty, acl_type_t type, acl_t acl, bool modify) {
++        _cleanup_(acl_free_charpp) char *t = NULL;
+         _cleanup_(acl_freep) acl_t dup = NULL;
+         int r;
+-        _cleanup_(acl_free_charpp) char *t = NULL;
+ 
+         /* Returns 0 for success, positive error if already warned,
+          * negative error otherwise. */
+@@ -728,16 +746,16 @@ static int path_set_acl(const char *path, acl_type_t type, acl_t acl, bool modif
+                 return r;
+ 
+         t = acl_to_any_text(dup, NULL, ',', TEXT_ABBREVIATE);
+-        log_debug("\"%s\": setting %s ACL \"%s\"", path,
++        log_debug("Setting %s ACL %s on %s.",
+                   type == ACL_TYPE_ACCESS ? "access" : "default",
+-                  strna(t));
++                  strna(t), pretty);
+ 
+         r = acl_set_file(path, type, dup);
+         if (r < 0)
+                 return -log_error_errno(errno,
+                                         "Setting %s ACL \"%s\" on %s failed: %m",
+                                         type == ACL_TYPE_ACCESS ? "access" : "default",
+-                                        strna(t), path);
++                                        strna(t), pretty);
+ 
+         return 0;
+ }
+@@ -746,14 +764,32 @@ static int path_set_acl(const char *path, acl_type_t type, acl_t acl, bool modif
+ static int path_set_acls(Item *item, const char *path) {
+         int r = 0;
+ #ifdef HAVE_ACL
++        char fn[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
++        _cleanup_close_ int fd = -1;
++        struct stat st;
++
+         assert(item);
+         assert(path);
+ 
++        fd = open(path, O_RDONLY|O_NOFOLLOW|O_CLOEXEC|O_PATH|O_NOATIME);
++        if (fd < 0)
++                return log_error_errno(errno, "Adjusting ACL of %s failed: %m", path);
++
++        if (fstatat(fd, "", &st, AT_EMPTY_PATH) < 0)
++                return log_error_errno(errno, "Failed to fstat() file %s: %m", path);
++
++        if (S_ISLNK(st.st_mode)) {
++                log_debug("Skipping ACL fix for symlink %s.", path);
++                return 0;
++        }
++
++        xsprintf(fn, "/proc/self/fd/%i", fd);
++
+         if (item->acl_access)
+-                r = path_set_acl(path, ACL_TYPE_ACCESS, item->acl_access, item->force);
++                r = path_set_acl(fn, path, ACL_TYPE_ACCESS, item->acl_access, item->force);
+ 
+         if (r == 0 && item->acl_default)
+-                r = path_set_acl(path, ACL_TYPE_DEFAULT, item->acl_default, item->force);
++                r = path_set_acl(fn, path, ACL_TYPE_DEFAULT, item->acl_default, item->force);
+ 
+         if (r > 0)
+                 return -r; /* already warned */
diff --git a/SOURCES/0301-udev-filter-out-non-sensically-high-onboard-indexes-.patch b/SOURCES/0301-udev-filter-out-non-sensically-high-onboard-indexes-.patch
new file mode 100644
index 0000000..b261d9c
--- /dev/null
+++ b/SOURCES/0301-udev-filter-out-non-sensically-high-onboard-indexes-.patch
@@ -0,0 +1,43 @@
+From 0fa424a08a31af512a698b60b497cfc0cf0554e0 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Mon, 25 Jan 2016 17:16:27 +0100
+Subject: [PATCH] udev: filter out non-sensically high onboard indexes reported
+ by the kernel
+
+Let's not accept onboard interface indexes, that are so high that they are obviously non-sensical.
+
+Fixes: #2407
+
+Cherry-picked from: 6c1e69f9456d022f14dd00737126cfa4d9cca10
+Resolves: #1230210
+---
+ src/udev/udev-builtin-net_id.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/src/udev/udev-builtin-net_id.c b/src/udev/udev-builtin-net_id.c
+index ffd6ea4..19e1f26 100644
+--- a/src/udev/udev-builtin-net_id.c
++++ b/src/udev/udev-builtin-net_id.c
+@@ -101,6 +101,8 @@
+ #include "udev.h"
+ #include "fileio.h"
+ 
++#define ONBOARD_INDEX_MAX (16*1024-1)
++
+ enum netname_type{
+         NET_UNDEF,
+         NET_PCI,
+@@ -147,6 +149,13 @@ static int dev_pci_onboard(struct udev_device *dev, struct netnames *names) {
+         if (idx <= 0)
+                 return -EINVAL;
+ 
++        /* Some BIOSes report rubbish indexes that are excessively high (2^24-1 is an index VMware likes to report for
++         * example). Let's define a cut-off where we don't consider the index reliable anymore. We pick some arbitrary
++         * cut-off, which is somewhere beyond the realistic number of physical network interface a system might
++         * have. Ideally the kernel would already filter his crap for us, but it doesn't currently. */
++        if (idx > ONBOARD_INDEX_MAX)
++                return -ENOENT;
++
+         /* kernel provided port index for multiple ports on a single PCI function */
+         attr = udev_device_get_sysattr_value(dev, "dev_port");
+         if (attr)
diff --git a/SOURCES/0302-test-execute-add-tests-for-RuntimeDirectory.patch b/SOURCES/0302-test-execute-add-tests-for-RuntimeDirectory.patch
new file mode 100644
index 0000000..db487ec
--- /dev/null
+++ b/SOURCES/0302-test-execute-add-tests-for-RuntimeDirectory.patch
@@ -0,0 +1,74 @@
+From fb798a267d2bad8df98f49c2a4a309efa5569759 Mon Sep 17 00:00:00 2001
+From: Ronny Chevalier <chevalier.ronny@gmail.com>
+Date: Mon, 21 Sep 2015 15:36:07 +0200
+Subject: [PATCH] test-execute: add tests for RuntimeDirectory
+
+Cherry-picked from: cc3ddc851fbe5adf9dfc7e4a702a8b5b6a1186d6
+Resolves: #1324826
+---
+ src/test/test-execute.c                 | 7 +++++++
+ test/exec-runtimedirectory-mode.service | 8 ++++++++
+ test/exec-runtimedirectory.service      | 7 +++++++
+ 3 files changed, 22 insertions(+)
+ create mode 100644 test/exec-runtimedirectory-mode.service
+ create mode 100644 test/exec-runtimedirectory.service
+
+diff --git a/src/test/test-execute.c b/src/test/test-execute.c
+index 00f3607..90b1c87 100644
+--- a/src/test/test-execute.c
++++ b/src/test/test-execute.c
+@@ -141,6 +141,11 @@ static void test_exec_umask(Manager *m) {
+         test(m, "exec-umask-0177.service", 0, CLD_EXITED);
+ }
+ 
++static void test_exec_runtimedirectory(Manager *m) {
++        test(m, "exec-runtimedirectory.service", 0, CLD_EXITED);
++        test(m, "exec-runtimedirectory-mode.service", 0, CLD_EXITED);
++}
++
+ int main(int argc, char *argv[]) {
+         test_function_t tests[] = {
+                 test_exec_workingdirectory,
+@@ -154,6 +159,7 @@ int main(int argc, char *argv[]) {
+                 test_exec_group,
+                 test_exec_environment,
+                 test_exec_umask,
++                test_exec_runtimedirectory,
+                 NULL,
+         };
+         test_function_t *test = NULL;
+@@ -169,6 +175,7 @@ int main(int argc, char *argv[]) {
+                 return EXIT_TEST_SKIP;
+         }
+ 
++        assert_se(setenv("XDG_RUNTIME_DIR", "/tmp/", 1) == 0);
+         assert_se(set_unit_path(TEST_DIR ":") >= 0);
+ 
+         r = manager_new(SYSTEMD_USER, true, &m);
+diff --git a/test/exec-runtimedirectory-mode.service b/test/exec-runtimedirectory-mode.service
+new file mode 100644
+index 0000000..ba6d7ee
+--- /dev/null
++++ b/test/exec-runtimedirectory-mode.service
+@@ -0,0 +1,8 @@
++[Unit]
++Description=Test for RuntimeDirectoryMode
++
++[Service]
++ExecStart=/bin/sh -c 's=$(stat -c %a /tmp/test-exec_runtimedirectory-mode); echo $s; exit $(test $s = "750")'
++Type=oneshot
++RuntimeDirectory=test-exec_runtimedirectory-mode
++RuntimeDirectoryMode=0750
+diff --git a/test/exec-runtimedirectory.service b/test/exec-runtimedirectory.service
+new file mode 100644
+index 0000000..c12a6c6
+--- /dev/null
++++ b/test/exec-runtimedirectory.service
+@@ -0,0 +1,7 @@
++[Unit]
++Description=Test for RuntimeDirectory
++
++[Service]
++ExecStart=/bin/sh -c 'exit $(test -d /tmp/test-exec_runtimedirectory)'
++Type=oneshot
++RuntimeDirectory=test-exec_runtimedirectory
diff --git a/SOURCES/0303-core-fix-group-ownership-when-Group-is-set.patch b/SOURCES/0303-core-fix-group-ownership-when-Group-is-set.patch
new file mode 100644
index 0000000..5d195a6
--- /dev/null
+++ b/SOURCES/0303-core-fix-group-ownership-when-Group-is-set.patch
@@ -0,0 +1,84 @@
+From f2300a5c3226d3a66d77c34ae811401c638f430f Mon Sep 17 00:00:00 2001
+From: Ronny Chevalier <chevalier.ronny@gmail.com>
+Date: Mon, 21 Sep 2015 15:45:51 +0200
+Subject: [PATCH] core: fix group ownership when Group is set
+
+When Group is set in the unit, the runtime directories are owned by
+this group and not the default group of the user (same for cgroup paths
+and standard outputs)
+
+Fix #1231
+
+Cherry-picked from: 5bc7452b3219456e07f931e40da30bb94a884293
+Resolves: #1324826
+---
+ src/core/execute.c                       | 19 +++++++++++--------
+ src/test/test-execute.c                  |  1 +
+ test/exec-runtimedirectory-owner.service |  9 +++++++++
+ 3 files changed, 21 insertions(+), 8 deletions(-)
+ create mode 100644 test/exec-runtimedirectory-owner.service
+
+diff --git a/src/core/execute.c b/src/core/execute.c
+index 1815e3d..8172c8b 100644
+--- a/src/core/execute.c
++++ b/src/core/execute.c
+@@ -629,14 +629,6 @@ static int enforce_groups(const ExecContext *context, const char *username, gid_
+          * we avoid NSS lookups for gid=0. */
+ 
+         if (context->group || username) {
+-
+-                if (context->group) {
+-                        const char *g = context->group;
+-
+-                        if ((r = get_group_creds(&g, &gid)) < 0)
+-                                return r;
+-                }
+-
+                 /* First step, initialize groups from /etc/groups */
+                 if (username && gid != 0) {
+                         if (initgroups(username, gid) < 0)
+@@ -1374,6 +1366,17 @@ static int exec_child(
+                 }
+         }
+ 
++        if (context->group) {
++                const char *g = context->group;
++
++                r = get_group_creds(&g, &gid);
++                if (r < 0) {
++                        *exit_status = EXIT_GROUP;
++                        return r;
++                }
++        }
++
++
+         /* If a socket is connected to STDIN/STDOUT/STDERR, we
+          * must sure to drop O_NONBLOCK */
+         if (socket_fd >= 0)
+diff --git a/src/test/test-execute.c b/src/test/test-execute.c
+index 90b1c87..38522a1 100644
+--- a/src/test/test-execute.c
++++ b/src/test/test-execute.c
+@@ -144,6 +144,7 @@ static void test_exec_umask(Manager *m) {
+ static void test_exec_runtimedirectory(Manager *m) {
+         test(m, "exec-runtimedirectory.service", 0, CLD_EXITED);
+         test(m, "exec-runtimedirectory-mode.service", 0, CLD_EXITED);
++        test(m, "exec-runtimedirectory-owner.service", 0, CLD_EXITED);
+ }
+ 
+ int main(int argc, char *argv[]) {
+diff --git a/test/exec-runtimedirectory-owner.service b/test/exec-runtimedirectory-owner.service
+new file mode 100644
+index 0000000..077e08d
+--- /dev/null
++++ b/test/exec-runtimedirectory-owner.service
+@@ -0,0 +1,9 @@
++[Unit]
++Description=Test for RuntimeDirectory owner (must not be the default group of the user if Group is set)
++
++[Service]
++ExecStart=/bin/sh -c 'f=/tmp/test-exec_runtimedirectory-owner;g=$(stat -c %G $f); echo "$g"; exit $(test $g = "nobody")'
++Type=oneshot
++Group=nobody
++User=root
++RuntimeDirectory=test-exec_runtimedirectory-owner
diff --git a/SOURCES/0304-fstab-generator-cescape-device-name-in-root-fsck-ser.patch b/SOURCES/0304-fstab-generator-cescape-device-name-in-root-fsck-ser.patch
new file mode 100644
index 0000000..3928b66
--- /dev/null
+++ b/SOURCES/0304-fstab-generator-cescape-device-name-in-root-fsck-ser.patch
@@ -0,0 +1,49 @@
+From e591c1a47c067cd2d14dca569cc9f0cce9072200 Mon Sep 17 00:00:00 2001
+From: Andrei Borzenkov <arvidjaar@gmail.com>
+Date: Wed, 3 Jun 2015 20:50:59 +0300
+Subject: [PATCH] fstab-generator: cescape device name in root-fsck service
+
+We unescape ExecStart line when parsing it, so escape device name
+before adding it to unit file.
+
+fixes #50
+
+Cherry-picked from: fa05e97
+Resolves: #1306126
+---
+ src/shared/generator.c | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/src/shared/generator.c b/src/shared/generator.c
+index 3af84a3..be8e24e 100644
+--- a/src/shared/generator.c
++++ b/src/shared/generator.c
+@@ -35,8 +35,13 @@
+ static int write_fsck_sysroot_service(const char *dir, const char *what) {
+         const char *unit;
+         _cleanup_free_ char *device = NULL;
++        _cleanup_free_ char *escaped;
+         _cleanup_fclose_ FILE *f = NULL;
+ 
++        escaped = cescape(what);
++        if (!escaped)
++                return log_oom();
++
+         unit = strjoina(dir, "/systemd-fsck-root.service");
+         log_debug("Creating %s", unit);
+ 
+@@ -61,11 +66,12 @@ static int write_fsck_sysroot_service(const char *dir, const char *what) {
+                 "[Service]\n"
+                 "Type=oneshot\n"
+                 "RemainAfterExit=yes\n"
+-                "ExecStart=" SYSTEMD_FSCK_PATH " %2$s\n"
++                "ExecStart=" SYSTEMD_FSCK_PATH " %4$s\n"
+                 "TimeoutSec=0\n",
+                 program_invocation_short_name,
+                 what,
+-                device);
++                device,
++                escaped);
+ 
+         fflush(f);
+         if (ferror(f))
diff --git a/SOURCES/0305-core-add-new-RandomSec-setting-for-time-units.patch b/SOURCES/0305-core-add-new-RandomSec-setting-for-time-units.patch
new file mode 100644
index 0000000..57c910c
--- /dev/null
+++ b/SOURCES/0305-core-add-new-RandomSec-setting-for-time-units.patch
@@ -0,0 +1,227 @@
+From 338b8f9bca1cd7bd65123808fc7f7b2773e637db Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Wed, 18 Nov 2015 13:37:30 +0100
+Subject: [PATCH] core: add new RandomSec= setting for time units
+
+This allows configuration of a random time on top of the elapse events,
+in order to spread time events in a network evenly across a range.
+
+Cherry-picked from: 744c7693751830149ae78fdaf95c6c6f99d59f07
+Resolves: #1305279
+---
+ man/systemd.timer.xml                 | 43 ++++++++++++++++++++++++++++++-----
+ src/core/dbus-timer.c                 | 17 ++++++++++++++
+ src/core/load-fragment-gperf.gperf.m4 |  1 +
+ src/core/timer.c                      | 28 +++++++++++++++++++++++
+ src/core/timer.h                      |  1 +
+ src/libsystemd/sd-bus/bus-util.c      | 16 +++++++++++++
+ 6 files changed, 100 insertions(+), 6 deletions(-)
+
+diff --git a/man/systemd.timer.xml b/man/systemd.timer.xml
+index 20890f2..bdd14d8 100644
+--- a/man/systemd.timer.xml
++++ b/man/systemd.timer.xml
+@@ -180,13 +180,12 @@
+         <varname>OnUnitInactiveSec=</varname> and ending the time
+         configured with <varname>AccuracySec=</varname> later. Within
+         this time window, the expiry time will be placed at a
+-        host-specific, randomized but stable position that is
++        host-specific, randomized, but stable position that is
+         synchronized between all local timer units. This is done in
+-        order to distribute the wake-up time in networked
+-        installations, as well as optimizing power consumption to
+-        suppress unnecessary CPU wake-ups. To get best accuracy, set
+-        this option to 1us. Note that the timer is still subject to
+-        the timer slack configured via
++        order to optimize power consumption to suppress unnecessary
++        CPU wake-ups. To get best accuracy, set this option to
++        1us. Note that the timer is still subject to the timer slack
++        configured via
+         <citerefentry><refentrytitle>systemd-system.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>'s
+         <varname>TimerSlackNSec=</varname> setting. See
+         <citerefentry><refentrytitle>prctl</refentrytitle><manvolnum>2</manvolnum></citerefentry>
+@@ -194,6 +193,38 @@
+         this value as high as possible and as low as
+         necessary.</para></listitem>
+       </varlistentry>
++
++      <varlistentry>
++        <term><varname>RandomSec=</varname></term>
++
++        <listitem><para>Delay the timer by a randomly selected, evenly
++        distributed amount of time between 0 and the specified time
++        value. Defaults to 0, indicating that no randomized delay
++        shall be applied. Each timer unit will determine this delay
++        randomly each time it is started, and the delay will simply be
++        added on top of the next determined elapsing time. This is
++        useful to stretch dispatching of similarly configured timer
++        events over a certain amount time, to avoid that they all fire
++        at the same time, possibly resulting in resource
++        congestion. Note the relation to
++        <varname>AccuracySec=</varname> above: the latter allows the
++        service manager to coalesce timer events within a specified
++        time range in order to minimize wakeups, the former does the
++        opposite: it stretches timer events over a time range, to make
++        it unlikely that they fire simultaneously. If
++        <varname>RandomSec=</varname> and
++        <varname>AccuracySec=</varname> are used in conjunction, first
++        the a randomized time is added, and the result is then
++        possibly shifted further to coalesce it with other timer
++        events possibly happening on the system. As mentioned above
++        <varname>AccuracySec=</varname> defaults to 1min and
++        <varname>RandomSec=</varname> to 0, thus encouraging
++        coalescing of timer events. In order to optimally stretch
++        timer events over a certain range of time, make sure to set
++        <varname>RandomSec=</varname> to a higher value, and
++        <varname>AccuracySec=1us</varname>.</para></listitem>
++      </varlistentry>
++
+       <varlistentry>
+         <term><varname>Unit=</varname></term>
+ 
+diff --git a/src/core/dbus-timer.c b/src/core/dbus-timer.c
+index 43e7852..cd7bf44 100644
+--- a/src/core/dbus-timer.c
++++ b/src/core/dbus-timer.c
+@@ -181,6 +181,7 @@ const sd_bus_vtable bus_timer_vtable[] = {
+         BUS_PROPERTY_DUAL_TIMESTAMP("LastTriggerUSec", offsetof(Timer, last_trigger), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+         SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Timer, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+         SD_BUS_PROPERTY("AccuracyUSec", "t", bus_property_get_usec, offsetof(Timer, accuracy_usec), SD_BUS_VTABLE_PROPERTY_CONST),
++        SD_BUS_PROPERTY("RandomUSec", "t", bus_property_get_usec, offsetof(Timer, random_usec), SD_BUS_VTABLE_PROPERTY_CONST),
+         SD_BUS_PROPERTY("Persistent", "b", bus_property_get_bool, offsetof(Timer, persistent), SD_BUS_VTABLE_PROPERTY_CONST),
+         SD_BUS_PROPERTY("WakeSystem", "b", bus_property_get_bool, offsetof(Timer, wake_system), SD_BUS_VTABLE_PROPERTY_CONST),
+         SD_BUS_VTABLE_END
+@@ -284,6 +285,22 @@ static int bus_timer_set_transient_property(
+ 
+                 return 1;
+ 
++        } else if (streq(name, "RandomUSec")) {
++                usec_t u = 0;
++
++                r = sd_bus_message_read(message, "t", &u);
++                if (r < 0)
++                        return r;
++
++                if (mode != UNIT_CHECK) {
++                        char time[FORMAT_TIMESPAN_MAX];
++
++                        t->random_usec = u;
++                        unit_write_drop_in_private_format(UNIT(t), mode, name, "RandomSec=%s\n", format_timespan(time, sizeof(time), u, USEC_PER_MSEC));
++                }
++
++                return 1;
++
+         } else if (streq(name, "WakeSystem")) {
+ 
+                 int b;
+diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
+index 5305984..5106a98 100644
+--- a/src/core/load-fragment-gperf.gperf.m4
++++ b/src/core/load-fragment-gperf.gperf.m4
+@@ -336,6 +336,7 @@ Timer.OnUnitInactiveSec,         config_parse_timer,                 0,
+ Timer.Persistent,                config_parse_bool,                  0,                             offsetof(Timer, persistent)
+ Timer.WakeSystem,                config_parse_bool,                  0,                             offsetof(Timer, wake_system)
+ Timer.AccuracySec,               config_parse_sec,                   0,                             offsetof(Timer, accuracy_usec)
++Timer.RandomSec,                 config_parse_sec,                   0,                             offsetof(Timer, random_usec)
+ Timer.Unit,                      config_parse_trigger_unit,          0,                             0
+ m4_dnl
+ Path.PathExists,                 config_parse_path_spec,             0,                             0
+diff --git a/src/core/timer.c b/src/core/timer.c
+index 48cf9c1..972dd73 100644
+--- a/src/core/timer.c
++++ b/src/core/timer.c
+@@ -29,6 +29,7 @@
+ #include "bus-util.h"
+ #include "bus-error.h"
+ #include "mkdir.h"
++#include "util.h"
+ 
+ static const UnitActiveState state_translation_table[_TIMER_STATE_MAX] = {
+         [TIMER_DEAD] = UNIT_INACTIVE,
+@@ -315,6 +316,28 @@ static usec_t monotonic_to_boottime(usec_t t) {
+                 return 0;
+ }
+ 
++static void add_random(Timer *t, usec_t *v) {
++        char s[FORMAT_TIMESPAN_MAX];
++        usec_t add;
++
++        assert(t);
++        assert(*v);
++
++        if (t->random_usec == 0)
++                return;
++        if (*v == USEC_INFINITY)
++                return;
++
++        add = random_u64() % t->random_usec;
++
++        if (*v + add < *v) /* overflow */
++                *v = (usec_t) -2; /* Highest possible value, that is not USEC_INFINITY */
++        else
++                *v += add;
++
++        log_unit_info(UNIT(t)->id, "Adding %s random time.", format_timespan(s, sizeof(s), add, 0));
++}
++
+ static void timer_enter_waiting(Timer *t, bool initial) {
+         bool found_monotonic = false, found_realtime = false;
+         usec_t ts_realtime, ts_monotonic;
+@@ -431,6 +454,8 @@ static void timer_enter_waiting(Timer *t, bool initial) {
+         if (found_monotonic) {
+                 char buf[FORMAT_TIMESPAN_MAX];
+ 
++                add_random(t, &t->next_elapse_monotonic_or_boottime);
++
+                 log_unit_debug(UNIT(t)->id, "%s: Monotonic timer elapses in %s.",
+                                UNIT(t)->id,
+                                format_timespan(buf, sizeof(buf), t->next_elapse_monotonic_or_boottime > ts_monotonic ? t->next_elapse_monotonic_or_boottime - ts_monotonic : 0, 0));
+@@ -460,6 +485,9 @@ static void timer_enter_waiting(Timer *t, bool initial) {
+ 
+         if (found_realtime) {
+                 char buf[FORMAT_TIMESTAMP_MAX];
++
++                add_random(t, &t->next_elapse_realtime);
++
+                 log_unit_debug(UNIT(t)->id, "%s: Realtime timer elapses at %s.", UNIT(t)->id, format_timestamp(buf, sizeof(buf), t->next_elapse_realtime));
+ 
+                 if (t->realtime_event_source) {
+diff --git a/src/core/timer.h b/src/core/timer.h
+index de412a0..b977245 100644
+--- a/src/core/timer.h
++++ b/src/core/timer.h
+@@ -69,6 +69,7 @@ struct Timer {
+         Unit meta;
+ 
+         usec_t accuracy_usec;
++        usec_t random_usec;
+ 
+         LIST_HEAD(TimerValue, values);
+         usec_t next_elapse_realtime;
+diff --git a/src/libsystemd/sd-bus/bus-util.c b/src/libsystemd/sd-bus/bus-util.c
+index 6d56150..5ecb3be 100644
+--- a/src/libsystemd/sd-bus/bus-util.c
++++ b/src/libsystemd/sd-bus/bus-util.c
+@@ -1364,6 +1364,22 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
+                         return bus_log_create_error(r);
+ 
+                 return 0;
++        } else if (streq(field, "RandomSec")) {
++                usec_t t;
++
++                r = parse_sec(eq, &t);
++                if (r < 0)
++                        return log_error_errno(r, "Failed to parse RandomSec= parameter: %s", eq);
++
++                r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "RandomUSec");
++                if (r < 0)
++                        return bus_log_create_error(r);
++
++                r = sd_bus_message_append(m, "v", "t", t);
++                if (r < 0)
++                        return bus_log_create_error(r);
++
++                return 0;
+         }
+ 
+         r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field);
diff --git a/SOURCES/0306-core-rename-Random-to-RandomizedDelay.patch b/SOURCES/0306-core-rename-Random-to-RandomizedDelay.patch
new file mode 100644
index 0000000..522a8a2
--- /dev/null
+++ b/SOURCES/0306-core-rename-Random-to-RandomizedDelay.patch
@@ -0,0 +1,118 @@
+From 510ba7ebe71c8e4e64ead26a44b330d2e4375d9c Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
+Date: Thu, 26 Nov 2015 16:32:41 -0500
+Subject: [PATCH] core: rename Random* to RandomizedDelay*
+
+The name RandomSec is too generic: "Sec" just specifies the default
+unit type, and "Random" by itself is not enough. Rename to something
+that should give the user general idea what the setting does without
+looking at documentation.
+
+Cherry-picked from: 6f5d79986a9c98b9cacc83f865fed957e4e6e4e6
+Resolves: #1305279
+---
+ man/systemd.timer.xml                 | 8 ++++----
+ src/core/dbus-timer.c                 | 6 +++---
+ src/core/load-fragment-gperf.gperf.m4 | 2 +-
+ src/libsystemd/sd-bus/bus-util.c      | 6 +++---
+ 4 files changed, 11 insertions(+), 11 deletions(-)
+
+diff --git a/man/systemd.timer.xml b/man/systemd.timer.xml
+index bdd14d8..ab83b2c 100644
+--- a/man/systemd.timer.xml
++++ b/man/systemd.timer.xml
+@@ -195,7 +195,7 @@
+       </varlistentry>
+ 
+       <varlistentry>
+-        <term><varname>RandomSec=</varname></term>
++        <term><varname>RandomizedDelaySec=</varname></term>
+ 
+         <listitem><para>Delay the timer by a randomly selected, evenly
+         distributed amount of time between 0 and the specified time
+@@ -212,16 +212,16 @@
+         time range in order to minimize wakeups, the former does the
+         opposite: it stretches timer events over a time range, to make
+         it unlikely that they fire simultaneously. If
+-        <varname>RandomSec=</varname> and
++        <varname>RandomizedDelaySec=</varname> and
+         <varname>AccuracySec=</varname> are used in conjunction, first
+         the a randomized time is added, and the result is then
+         possibly shifted further to coalesce it with other timer
+         events possibly happening on the system. As mentioned above
+         <varname>AccuracySec=</varname> defaults to 1min and
+-        <varname>RandomSec=</varname> to 0, thus encouraging
++        <varname>RandomizedDelaySec=</varname> to 0, thus encouraging
+         coalescing of timer events. In order to optimally stretch
+         timer events over a certain range of time, make sure to set
+-        <varname>RandomSec=</varname> to a higher value, and
++        <varname>RandomizedDelaySec=</varname> to a higher value, and
+         <varname>AccuracySec=1us</varname>.</para></listitem>
+       </varlistentry>
+ 
+diff --git a/src/core/dbus-timer.c b/src/core/dbus-timer.c
+index cd7bf44..478905a 100644
+--- a/src/core/dbus-timer.c
++++ b/src/core/dbus-timer.c
+@@ -181,7 +181,7 @@ const sd_bus_vtable bus_timer_vtable[] = {
+         BUS_PROPERTY_DUAL_TIMESTAMP("LastTriggerUSec", offsetof(Timer, last_trigger), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+         SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Timer, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+         SD_BUS_PROPERTY("AccuracyUSec", "t", bus_property_get_usec, offsetof(Timer, accuracy_usec), SD_BUS_VTABLE_PROPERTY_CONST),
+-        SD_BUS_PROPERTY("RandomUSec", "t", bus_property_get_usec, offsetof(Timer, random_usec), SD_BUS_VTABLE_PROPERTY_CONST),
++        SD_BUS_PROPERTY("RandomizedDelayUSec", "t", bus_property_get_usec, offsetof(Timer, random_usec), SD_BUS_VTABLE_PROPERTY_CONST),
+         SD_BUS_PROPERTY("Persistent", "b", bus_property_get_bool, offsetof(Timer, persistent), SD_BUS_VTABLE_PROPERTY_CONST),
+         SD_BUS_PROPERTY("WakeSystem", "b", bus_property_get_bool, offsetof(Timer, wake_system), SD_BUS_VTABLE_PROPERTY_CONST),
+         SD_BUS_VTABLE_END
+@@ -285,7 +285,7 @@ static int bus_timer_set_transient_property(
+ 
+                 return 1;
+ 
+-        } else if (streq(name, "RandomUSec")) {
++        } else if (streq(name, "RandomizedDelayUSec")) {
+                 usec_t u = 0;
+ 
+                 r = sd_bus_message_read(message, "t", &u);
+@@ -296,7 +296,7 @@ static int bus_timer_set_transient_property(
+                         char time[FORMAT_TIMESPAN_MAX];
+ 
+                         t->random_usec = u;
+-                        unit_write_drop_in_private_format(UNIT(t), mode, name, "RandomSec=%s\n", format_timespan(time, sizeof(time), u, USEC_PER_MSEC));
++                        unit_write_drop_in_private_format(UNIT(t), mode, name, "RandomizedDelaySec=%s\n", format_timespan(time, sizeof(time), u, USEC_PER_MSEC));
+                 }
+ 
+                 return 1;
+diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
+index 5106a98..85d9797 100644
+--- a/src/core/load-fragment-gperf.gperf.m4
++++ b/src/core/load-fragment-gperf.gperf.m4
+@@ -336,7 +336,7 @@ Timer.OnUnitInactiveSec,         config_parse_timer,                 0,
+ Timer.Persistent,                config_parse_bool,                  0,                             offsetof(Timer, persistent)
+ Timer.WakeSystem,                config_parse_bool,                  0,                             offsetof(Timer, wake_system)
+ Timer.AccuracySec,               config_parse_sec,                   0,                             offsetof(Timer, accuracy_usec)
+-Timer.RandomSec,                 config_parse_sec,                   0,                             offsetof(Timer, random_usec)
++Timer.RandomizedDelaySec,        config_parse_sec,                   0,                             offsetof(Timer, random_usec)
+ Timer.Unit,                      config_parse_trigger_unit,          0,                             0
+ m4_dnl
+ Path.PathExists,                 config_parse_path_spec,             0,                             0
+diff --git a/src/libsystemd/sd-bus/bus-util.c b/src/libsystemd/sd-bus/bus-util.c
+index 5ecb3be..3a91836 100644
+--- a/src/libsystemd/sd-bus/bus-util.c
++++ b/src/libsystemd/sd-bus/bus-util.c
+@@ -1364,14 +1364,14 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
+                         return bus_log_create_error(r);
+ 
+                 return 0;
+-        } else if (streq(field, "RandomSec")) {
++        } else if (streq(field, "RandomizedDelaySec")) {
+                 usec_t t;
+ 
+                 r = parse_sec(eq, &t);
+                 if (r < 0)
+-                        return log_error_errno(r, "Failed to parse RandomSec= parameter: %s", eq);
++                        return log_error_errno(r, "Failed to parse RandomizedDelaySec= parameter: %s", eq);
+ 
+-                r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "RandomUSec");
++                r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "RandomizedDelayUSec");
+                 if (r < 0)
+                         return bus_log_create_error(r);
+ 
diff --git a/SOURCES/0307-journal-remote-change-owner-of-var-log-journal-remot.patch b/SOURCES/0307-journal-remote-change-owner-of-var-log-journal-remot.patch
new file mode 100644
index 0000000..fdc6b1e
--- /dev/null
+++ b/SOURCES/0307-journal-remote-change-owner-of-var-log-journal-remot.patch
@@ -0,0 +1,26 @@
+From 1c6075b30786cefc73e41b2f1f5459006f37b616 Mon Sep 17 00:00:00 2001
+From: Yu Watanabe <watanabe.yu+github@gmail.com>
+Date: Fri, 15 Jan 2016 15:19:52 +0900
+Subject: [PATCH] journal-remote: change owner of /var/log/journal/remote and
+ create /var/lib/systemd/journal-upload
+
+Cherry-picked from: dcdd4411407067fa1e464dc26ab85ae598fcad7d
+Resolves: #1327303
+---
+ tmpfiles.d/systemd-remote.conf | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/tmpfiles.d/systemd-remote.conf b/tmpfiles.d/systemd-remote.conf
+index 1b8973a..e19230f 100644
+--- a/tmpfiles.d/systemd-remote.conf
++++ b/tmpfiles.d/systemd-remote.conf
+@@ -7,5 +7,7 @@
+ 
+ # See tmpfiles.d(5) for details
+ 
+-z /var/log/journal/remote 2755 root systemd-journal-remote - -
+-z /run/log/journal/remote 2755 root systemd-journal-remote - -
++d /var/lib/systemd/journal-upload 0755 systemd-journal-upload systemd-journal-upload - -
++
++z /var/log/journal/remote 2755 systemd-journal-remote systemd-journal-remote - -
++z /run/log/journal/remote 2755 systemd-journal-remote systemd-journal-remote - -
diff --git a/SOURCES/0308-Add-Seal-option-in-the-configuration-file-for-journa.patch b/SOURCES/0308-Add-Seal-option-in-the-configuration-file-for-journa.patch
new file mode 100644
index 0000000..b0af3aa
--- /dev/null
+++ b/SOURCES/0308-Add-Seal-option-in-the-configuration-file-for-journa.patch
@@ -0,0 +1,57 @@
+From f6a8db04fb20d142e514d805c613a1b3e70c454d Mon Sep 17 00:00:00 2001
+From: Michael Scherer <misc@redhat.com>
+Date: Sun, 20 Dec 2015 13:23:33 +0100
+Subject: [PATCH] Add Seal option in the configuration file for journald-remote
+
+While journal received remotely can be sealed, it can only be done
+on the command line using --seal, so for consistency, we will
+also permit to set it in the configuration file.
+
+Cherry-picked from: 9d3737f13e9b38f88ed7acc800db66c2f025fac9
+Resolves: #1329233
+---
+ man/journal-remote.conf.xml               | 7 +++++++
+ src/journal-remote/journal-remote.c       | 1 +
+ src/journal-remote/journal-remote.conf.in | 1 +
+ 3 files changed, 9 insertions(+)
+
+diff --git a/man/journal-remote.conf.xml b/man/journal-remote.conf.xml
+index a7b2227..9a385c7 100644
+--- a/man/journal-remote.conf.xml
++++ b/man/journal-remote.conf.xml
+@@ -72,6 +72,13 @@
+     <literal>[Remote]</literal> section:</para>
+ 
+     <variablelist>
++      <varlistentry>
++        <term><varname>Seal=</varname></term>
++
++        <listitem><para>Periodically sign the data in the journal using Forward Secure Sealing.
++        </para></listitem>
++      </varlistentry>
++
+ 
+       <varlistentry>
+         <term><varname>SplitMode=</varname></term>
+diff --git a/src/journal-remote/journal-remote.c b/src/journal-remote/journal-remote.c
+index b7cc6d7..9c515f9 100644
+--- a/src/journal-remote/journal-remote.c
++++ b/src/journal-remote/journal-remote.c
+@@ -1174,6 +1174,7 @@ static DEFINE_CONFIG_PARSE_ENUM(config_parse_write_split_mode,
+ 
+ static int parse_config(void) {
+         const ConfigTableItem items[] = {
++                { "Remote",  "Seal",                   config_parse_bool,             0, &arg_seal       },
+                 { "Remote",  "SplitMode",              config_parse_write_split_mode, 0, &arg_split_mode },
+                 { "Remote",  "ServerKeyFile",          config_parse_path,             0, &arg_key        },
+                 { "Remote",  "ServerCertificateFile",  config_parse_path,             0, &arg_cert       },
+diff --git a/src/journal-remote/journal-remote.conf.in b/src/journal-remote/journal-remote.conf.in
+index 3e32f34..7122d63 100644
+--- a/src/journal-remote/journal-remote.conf.in
++++ b/src/journal-remote/journal-remote.conf.in
+@@ -1,4 +1,5 @@
+ [Remote]
++# Seal=false
+ # SplitMode=host
+ # ServerKeyFile=@CERTIFICATEROOT@/private/journal-remote.pem
+ # ServerCertificateFile=@CERTIFICATEROOT@/certs/journal-remote.pem
diff --git a/SOURCES/0309-tests-fix-make-check-failure.patch b/SOURCES/0309-tests-fix-make-check-failure.patch
new file mode 100644
index 0000000..4eae4c3
--- /dev/null
+++ b/SOURCES/0309-tests-fix-make-check-failure.patch
@@ -0,0 +1,26 @@
+From 44eb30c33deb46f92d2c67e78a5fb7aa6b21d145 Mon Sep 17 00:00:00 2001
+From: Michal Sekletar <msekleta@redhat.com>
+Date: Thu, 28 Apr 2016 16:04:52 +0200
+Subject: [PATCH] tests: fix make check failure
+
+Don't call abort() on success. Actually rm_rf_dangerous() returns 0 if
+all went well.
+
+Related: #1159308
+---
+ src/test/test-install-root.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/test/test-install-root.c b/src/test/test-install-root.c
+index 89d91d3..667c374 100644
+--- a/src/test/test-install-root.c
++++ b/src/test/test-install-root.c
+@@ -657,7 +657,7 @@ int main(int argc, char *argv[]) {
+         test_indirect(root);
+         test_preset_and_list(root);
+ 
+-        assert_se(rm_rf_dangerous(root, false, true, false));
++        assert_se(rm_rf_dangerous(root, false, true, false) == 0);
+ 
+         return 0;
+ }
diff --git a/SOURCES/0310-device-make-sure-to-not-ignore-re-plugged-device.patch b/SOURCES/0310-device-make-sure-to-not-ignore-re-plugged-device.patch
new file mode 100644
index 0000000..0bc39b6
--- /dev/null
+++ b/SOURCES/0310-device-make-sure-to-not-ignore-re-plugged-device.patch
@@ -0,0 +1,65 @@
+From 45ff3d79f079c73c73209940cf6eaa0ea0a95708 Mon Sep 17 00:00:00 2001
+From: Franck Bui <fbui@suse.com>
+Date: Fri, 22 Jan 2016 07:18:19 +0100
+Subject: [PATCH] device: make sure to not ignore re-plugged device
+
+systemd automatically mounts device unless 'noauto' is part of the
+mount options. This can happen during boot if the device is plugged at
+that time or later when the system is already running (the latter case
+is not documented AFAICS).
+
+After the systemd booted, I plugged my USB device which had an entry
+in /etc/fstab with the default options and systemd automatically
+mounted it.
+
+However I noticed that if I unplugged and re-plugged the device the
+automatic mounting of the device didn't work anymore: systemd didn't
+notice that the device was re-plugged.
+
+This was due to the device unit which was not recycled by the GC
+during the unplug event because in the case of automounting, the mount
+unit still referenced it. When the device was re-plugged, the old
+device unit was reused but it still had the old sysfs path (amongst
+other useful information).
+
+Systemd was confused by the stalled sysfs path and decided to ignore
+the plug event.
+
+This patch fixes this issue by simply not doing the sanity checking on
+the sysfs path if the device is in unplugged state.
+
+Cherry-picked from: ac9d396b2abbae4e7ab84f7b556f70681b66236b
+Resolves: #1332606
+---
+ src/core/device.c | 18 +++++++++++++-----
+ 1 file changed, 13 insertions(+), 5 deletions(-)
+
+diff --git a/src/core/device.c b/src/core/device.c
+index 1995e3c..fc73e26 100644
+--- a/src/core/device.c
++++ b/src/core/device.c
+@@ -314,11 +314,19 @@ static int device_setup_unit(Manager *m, struct udev_device *dev, const char *pa
+ 
+         u = manager_get_unit(m, e);
+ 
+-        if (u &&
+-            DEVICE(u)->sysfs &&
+-            !path_equal(DEVICE(u)->sysfs, sysfs)) {
+-                log_unit_debug(u->id, "Device %s appeared twice with different sysfs paths %s and %s", e, DEVICE(u)->sysfs, sysfs);
+-                return -EEXIST;
++        /* The device unit can still be present even if the device was
++         * unplugged: a mount unit can reference it hence preventing
++         * the GC to have garbaged it. That's desired since the device
++         * unit may have a dependency on the mount unit which was
++         * added during the loading of the later. */
++        if (u && DEVICE(u)->state == DEVICE_PLUGGED) {
++                /* This unit is in plugged state: we're sure it's
++                 * attached to a device. */
++                if (!path_equal(DEVICE(u)->sysfs, sysfs)) {
++                        log_unit_debug(u->id, "Dev %s appeared twice with different sysfs paths %s and %s",
++                                       e, DEVICE(u)->sysfs, sysfs);
++                        return -EEXIST;
++                }
+         }
+ 
+         if (!u) {
diff --git a/SOURCES/0311-device-Ensure-we-have-sysfs-path-before-comparing.patch b/SOURCES/0311-device-Ensure-we-have-sysfs-path-before-comparing.patch
new file mode 100644
index 0000000..f695fad
--- /dev/null
+++ b/SOURCES/0311-device-Ensure-we-have-sysfs-path-before-comparing.patch
@@ -0,0 +1,33 @@
+From ce046ce7f8545d174dc8ecb45b27c2049d96f935 Mon Sep 17 00:00:00 2001
+From: Colin Guthrie <colin@mageia.org>
+Date: Mon, 14 Mar 2016 09:42:07 +0000
+Subject: [PATCH] device: Ensure we have sysfs path before comparing.
+
+In some cases we do not have a udev device when setting up a unit
+(certainly the code gracefully handles this). However, we do
+then go on to compare the path via path_equal which will assert
+if a null value is passed in.
+
+See https://bugs.mageia.org/show_bug.cgi?id=17766
+
+Not sure if this is the correct fix, but it avoids the crash
+
+Cherry-picked from: 5e1558f4a09e596561c9168384f2258e7c0718a1
+Resolves: #1332606
+---
+ src/core/device.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/core/device.c b/src/core/device.c
+index fc73e26..bdc8466 100644
+--- a/src/core/device.c
++++ b/src/core/device.c
+@@ -319,7 +319,7 @@ static int device_setup_unit(Manager *m, struct udev_device *dev, const char *pa
+          * the GC to have garbaged it. That's desired since the device
+          * unit may have a dependency on the mount unit which was
+          * added during the loading of the later. */
+-        if (u && DEVICE(u)->state == DEVICE_PLUGGED) {
++        if (sysfs && u && DEVICE(u)->state == DEVICE_PLUGGED) {
+                 /* This unit is in plugged state: we're sure it's
+                  * attached to a device. */
+                 if (!path_equal(DEVICE(u)->sysfs, sysfs)) {
diff --git a/SOURCES/0312-core-fix-memory-leak-on-set-default-enable-disable-e.patch b/SOURCES/0312-core-fix-memory-leak-on-set-default-enable-disable-e.patch
new file mode 100644
index 0000000..958c0d7
--- /dev/null
+++ b/SOURCES/0312-core-fix-memory-leak-on-set-default-enable-disable-e.patch
@@ -0,0 +1,23 @@
+From 805365980feaec626e80c6514b46a6e4de319b77 Mon Sep 17 00:00:00 2001
+From: Evgeny Vereshchagin <evvers@ya.ru>
+Date: Fri, 29 Apr 2016 09:40:23 +0200
+Subject: [PATCH] core: fix memory leak on set-default, enable, disable etc
+
+Cherry-picked from: 24f412ca4150b490648ab8de45c6eda5bd697fd8
+Related: #1331667
+---
+ src/core/dbus-manager.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
+index faa124d..1a5525e 100644
+--- a/src/core/dbus-manager.c
++++ b/src/core/dbus-manager.c
+@@ -1621,6 +1621,7 @@ static int reply_unit_file_changes_and_free(
+         if (r < 0)
+                 goto fail;
+ 
++        unit_file_changes_free(changes, n_changes);
+         return sd_bus_send(bus, reply, NULL);
+ 
+ fail:
diff --git a/SOURCES/0313-nspawn-fix-minor-memory-leak.patch b/SOURCES/0313-nspawn-fix-minor-memory-leak.patch
new file mode 100644
index 0000000..12818bc
--- /dev/null
+++ b/SOURCES/0313-nspawn-fix-minor-memory-leak.patch
@@ -0,0 +1,26 @@
+From 94f823629031f8849c8dc001d56a2c057531f0f2 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Wed, 28 Oct 2015 18:22:23 +0100
+Subject: [PATCH] nspawn: fix minor memory leak
+
+When rebooting nspawn containers about 400 times we'd otherwise hit the
+fd limit and refuse further reboots.
+
+Cherry-picked from: 3c747da38ca2f0642b4811812f6e2e2e1449a622
+Related: #1331667
+---
+ src/shared/ptyfwd.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/src/shared/ptyfwd.c b/src/shared/ptyfwd.c
+index 31274a1..88b3f4e 100644
+--- a/src/shared/ptyfwd.c
++++ b/src/shared/ptyfwd.c
+@@ -388,6 +388,7 @@ PTYForward *pty_forward_free(PTYForward *f) {
+                 sd_event_source_unref(f->stdin_event_source);
+                 sd_event_source_unref(f->stdout_event_source);
+                 sd_event_source_unref(f->master_event_source);
++                sd_event_source_unref(f->sigwinch_event_source);
+                 sd_event_unref(f->event);
+ 
+                 if (f->saved_stdout)
diff --git a/SOURCES/0314-basic-fix-error-memleak-in-socket-util.patch b/SOURCES/0314-basic-fix-error-memleak-in-socket-util.patch
new file mode 100644
index 0000000..fcd43b4
--- /dev/null
+++ b/SOURCES/0314-basic-fix-error-memleak-in-socket-util.patch
@@ -0,0 +1,28 @@
+From 605a35e6e8dcb2518a1fa8f92fb5fb00a0419345 Mon Sep 17 00:00:00 2001
+From: David Herrmann <dh.herrmann@gmail.com>
+Date: Fri, 29 Apr 2016 12:13:06 +0200
+Subject: [PATCH] basic: fix error/memleak in socket-util
+
+Probably a typo, checking 'ret' instead of the return value 'p'. This
+might cause the function to return failure, even though it succeeded.
+Furthermore, it might leak resources.
+
+Cherry-picked from: 0810bc568ace619b16e440805e93256730d45541
+Related: #1331667
+---
+ src/shared/socket-util.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/shared/socket-util.c b/src/shared/socket-util.c
+index a4e26b1..407d0af 100644
+--- a/src/shared/socket-util.c
++++ b/src/shared/socket-util.c
+@@ -544,7 +544,7 @@ int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_
+ 
+                 } else {
+                         p = strndup(sa->un.sun_path, sizeof(sa->un.sun_path));
+-                        if (!ret)
++                        if (!p)
+                                 return -ENOMEM;
+                 }
+ 
diff --git a/SOURCES/0315-core-fix-memory-leak-in-manager_run_generators.patch b/SOURCES/0315-core-fix-memory-leak-in-manager_run_generators.patch
new file mode 100644
index 0000000..2e0202d
--- /dev/null
+++ b/SOURCES/0315-core-fix-memory-leak-in-manager_run_generators.patch
@@ -0,0 +1,52 @@
+From fa5a3a16e94773baf1dce3881d5cfab556b87113 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Cristian=20Rodr=C3=ADguez?= <crrodriguez@opensuse.org>
+Date: Mon, 11 May 2015 23:30:38 -0300
+Subject: [PATCH] core: fix memory leak in manager_run_generators()
+
+If systemd is built with GCC address sanitizer or leak sanitizer
+the following memory leak ocurs:
+
+May 12 02:02:46 linux.site systemd[326]: =================================================================
+May 12 02:02:46 linux.site systemd[326]: ==326==ERROR: LeakSanitizer: detected memory leaks
+May 12 02:02:46 linux.site systemd[326]: Direct leak of 101 byte(s) in 3 object(s) allocated from:
+May 12 02:02:46 linux.site systemd[326]: #0 0x7fd1f504993f in strdup (/usr/lib64/libasan.so.2+0x6293f)
+May 12 02:02:46 linux.site systemd[326]: #1 0x55d6ffac5336 in strv_new_ap src/shared/strv.c:163
+May 12 02:02:46 linux.site systemd[326]: #2 0x55d6ffac56a9 in strv_new src/shared/strv.c:185
+May 12 02:02:46 linux.site systemd[326]: #3 0x55d6ffa80272 in generator_paths src/shared/path-lookup.c:223
+May 12 02:02:46 linux.site systemd[326]: #4 0x55d6ff9bdb0f in manager_run_generators src/core/manager.c:2828
+May 12 02:02:46 linux.site systemd[326]: #5 0x55d6ff9b1a10 in manager_startup src/core/manager.c:1121
+May 12 02:02:46 linux.site systemd[326]: #6 0x55d6ff9a78e3 in main src/core/main.c:1667
+May 12 02:02:46 linux.site systemd[326]: #7 0x7fd1f394e8c4 in __libc_start_main (/lib64/libc.so.6+0x208c4)
+May 12 02:02:46 linux.site systemd[326]: Direct leak of 29 byte(s) in 1 object(s) allocated from:
+May 12 02:02:46 linux.site systemd[326]: #0 0x7fd1f504993f in strdup (/usr/lib64/libasan.so.2+0x6293f)
+May 12 02:02:46 linux.site systemd[326]: #1 0x55d6ffac5288 in strv_new_ap src/shared/strv.c:152
+May 12 02:02:46 linux.site systemd[326]: #2 0x55d6ffac56a9 in strv_new src/shared/strv.c:185
+May 12 02:02:46 linux.site systemd[326]: #3 0x55d6ffa80272 in generator_paths src/shared/path-lookup.c:223
+May 12 02:02:46 linux.site systemd[326]: #4 0x55d6ff9bdb0f in manager_run_generators src/core/manager.c:2828
+May 12 02:02:46 linux.site systemd[326]: #5 0x55d6ff9b1a10 in manager_startup src/core/manager.c:1121
+May 12 02:02:46 linux.site systemd[326]: #6 0x55d6ff9a78e3 in main src/core/main.c:1667
+May 12 02:02:46 linux.site systemd[326]: #7 0x7fd1f394e8c4 in __libc_start_main (/lib64/libc.so.6+0x208c4)
+May 12 02:02:46 linux.site systemd[326]: SUMMARY: AddressSanitizer: 130 byte(s) leaked in 4 allocation(s).
+
+There is a leak due to the the use of cleanup_free instead
+_cleanup_strv_free_
+
+Cherry-picked from: f42348ace7feb2311593b8cf6c876856eecf256a
+Related: #1331667
+---
+ 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 bb50503..a1504bf 100644
+--- a/src/core/manager.c
++++ b/src/core/manager.c
+@@ -2827,7 +2827,7 @@ static void trim_generator_dir(Manager *m, char **generator) {
+ }
+ 
+ static int manager_run_generators(Manager *m) {
+-        _cleanup_free_ char **paths = NULL;
++        _cleanup_strv_free_ char **paths = NULL;
+         const char *argv[5];
+         char **path;
+         int r;
diff --git a/SOURCES/0316-modules-load-fix-memory-leak.patch b/SOURCES/0316-modules-load-fix-memory-leak.patch
new file mode 100644
index 0000000..32e483b
--- /dev/null
+++ b/SOURCES/0316-modules-load-fix-memory-leak.patch
@@ -0,0 +1,41 @@
+From 3c3d3e3e040d980186fec05506018db2d24faa83 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Cristian=20Rodr=C3=ADguez?= <crrodriguez@opensuse.org>
+Date: Mon, 11 May 2015 15:37:47 -0300
+Subject: [PATCH] modules-load: fix memory leak
+
+=================================================================
+==64281==ERROR: LeakSanitizer: detected memory leaks
+
+Direct leak of 32 byte(s) in 1 object(s) allocated from:
+    #0 0x7f623c961c4a in malloc (/usr/lib64/libasan.so.2+0x96c4a)
+    #1 0x5651f79ad34e in malloc_multiply (/home/crrodriguez/scm/systemd/systemd-modules-load+0x2134e)
+    #2 0x5651f79b02d6 in strjoin (/home/crrodriguez/scm/systemd/systemd-modules-load+0x242d6)
+    #3 0x5651f79be1f5 in files_add (/home/crrodriguez/scm/systemd/systemd-modules-load+0x321f5)
+    #4 0x5651f79be6a3 in conf_files_list_strv_internal (/home/crrodriguez/scm/systemd/systemd-modules-load+0x326a3)
+    #5 0x5651f79bea24 in conf_files_list_nulstr (/home/crrodriguez/scm/systemd/systemd-modules-load+0x32a24)
+    #6 0x5651f79ad01a in main (/home/crrodriguez/scm/systemd/systemd-modules-load+0x2101a)
+    #7 0x7f623c11586f in __libc_start_main (/lib64/libc.so.6+0x2086f)
+
+SUMMARY: AddressSanitizer: 32 byte(s) leaked in 1 allocation(s).
+
+This happens due to the wrong cleanup attribute is used (free vs strv_free)
+
+Cherry-picked from: 4df3277881cffcd3bc9a5238203d6af7e1fd960f
+Related: #1331667
+---
+ src/modules-load/modules-load.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/modules-load/modules-load.c b/src/modules-load/modules-load.c
+index 5f67878..bab9246 100644
+--- a/src/modules-load/modules-load.c
++++ b/src/modules-load/modules-load.c
+@@ -256,7 +256,7 @@ int main(int argc, char *argv[]) {
+                 }
+ 
+         } else {
+-                _cleanup_free_ char **files = NULL;
++                _cleanup_strv_free_ char **files = NULL;
+                 char **fn, **i;
+ 
+                 STRV_FOREACH(i, arg_proc_cmdline_modules) {
diff --git a/SOURCES/0317-core-fix-memory-leak-on-failed-preset-all.patch b/SOURCES/0317-core-fix-memory-leak-on-failed-preset-all.patch
new file mode 100644
index 0000000..882253a
--- /dev/null
+++ b/SOURCES/0317-core-fix-memory-leak-on-failed-preset-all.patch
@@ -0,0 +1,66 @@
+From 9d00fbb87c43e129e1ab29298afc86b7e8eed25c Mon Sep 17 00:00:00 2001
+From: Evgeny Vereshchagin <evvers@ya.ru>
+Date: Mon, 18 Jan 2016 06:10:33 +0000
+Subject: [PATCH] core: fix memory leak on failed preset-all
+
+How to reproduce
+$ systemctl set-default multi-user # https://github.com/systemd/systemd/issues/2298
+$ systemctl preset-all
+Failed to execute operation: Too many levels of symbolic links
+
+$ systemctl poweroff
+
+Fixes:
+==1==
+==1== HEAP SUMMARY:
+==1==     in use at exit: 65,645 bytes in 7 blocks
+==1==   total heap usage: 40,539 allocs, 40,532 frees, 30,147,547 bytes allocated
+==1==
+==1== 109 (24 direct, 85 indirect) bytes in 1 blocks are definitely lost in loss record 2 of 7
+==1==    at 0x4C2BBCF: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
+==1==    by 0x4C2DE2F: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
+==1==    by 0x23DA71: unit_file_changes_add (install.c:233)
+==1==    by 0x23E45D: remove_marked_symlinks_fd (install.c:453)
+==1==    by 0x23E267: remove_marked_symlinks_fd (install.c:405)
+==1==    by 0x23E641: remove_marked_symlinks (install.c:494)
+==1==    by 0x243A91: execute_preset (install.c:2190)
+==1==    by 0x244343: unit_file_preset_all (install.c:2351)
+==1==    by 0x18AAA2: method_preset_all_unit_files (dbus-manager.c:1846)
+==1==    by 0x1D8157: method_callbacks_run (bus-objects.c:420)
+==1==    by 0x1DA9E9: object_find_and_run (bus-objects.c:1257)
+==1==    by 0x1DB02B: bus_process_object (bus-objects.c:1373)
+==1==
+==1== LEAK SUMMARY:
+==1==    definitely lost: 24 bytes in 1 blocks
+==1==    indirectly lost: 85 bytes in 1 blocks
+==1==      possibly lost: 0 bytes in 0 blocks
+==1==    still reachable: 65,536 bytes in 5 blocks
+==1==         suppressed: 0 bytes in 0 blocks
+==1== Reachable blocks (those to which a pointer was found) are not shown.
+==1== To see them, rerun with: --leak-check=full --show-leak-kinds=all
+==1==
+==1== For counts of detected and suppressed errors, rerun with: -v
+==1== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
+
+Cherry-picked from: c292c3af38c8c23e183f3e63ef492926cea64bab
+Related: #1331667
+---
+ src/core/dbus-manager.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
+index 1a5525e..9eef290 100644
+--- a/src/core/dbus-manager.c
++++ b/src/core/dbus-manager.c
+@@ -1875,8 +1875,10 @@ static int method_preset_all_unit_files(sd_bus *bus, sd_bus_message *message, vo
+         scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
+ 
+         r = unit_file_preset_all(scope, runtime, NULL, mm, force, &changes, &n_changes);
+-        if (r < 0)
++        if (r < 0) {
++                unit_file_changes_free(changes, n_changes);
+                 return r;
++        }
+ 
+         return reply_unit_file_changes_and_free(m, bus, message, -1, changes, n_changes);
+ }
diff --git a/SOURCES/0318-sd-bus-fix-memory-leak-in-test-bus-chat.patch b/SOURCES/0318-sd-bus-fix-memory-leak-in-test-bus-chat.patch
new file mode 100644
index 0000000..1dc4f72
--- /dev/null
+++ b/SOURCES/0318-sd-bus-fix-memory-leak-in-test-bus-chat.patch
@@ -0,0 +1,37 @@
+From 68550741351080ab8458d54a6900b2b6ea1ef511 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Cristian=20Rodr=C3=ADguez?= <crrodriguez@opensuse.org>
+Date: Sat, 9 May 2015 22:14:09 -0300
+Subject: [PATCH] sd-bus: fix memory leak in test-bus-chat
+
+Building with address sanitizer enabled on GCC 5.1.x a memory leak
+is reported because we never close the bus, fix it by using
+cleanup variable attribute.
+
+Cherry-picked from: 2f50a2d55bf0a8b5959a6864ae1b39e7e9e0ce08
+Related: #1331667
+---
+ src/libsystemd/sd-bus/test-bus-chat.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+diff --git a/src/libsystemd/sd-bus/test-bus-chat.c b/src/libsystemd/sd-bus/test-bus-chat.c
+index 8625ee6..a80aaae 100644
+--- a/src/libsystemd/sd-bus/test-bus-chat.c
++++ b/src/libsystemd/sd-bus/test-bus-chat.c
+@@ -264,7 +264,7 @@ fail:
+ 
+ static void* client1(void*p) {
+         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+-        sd_bus *bus = NULL;
++        _cleanup_bus_close_unref_ sd_bus *bus = NULL;
+         sd_bus_error error = SD_BUS_ERROR_NULL;
+         const char *hello;
+         int r;
+@@ -347,8 +347,6 @@ finish:
+                 else
+                         sd_bus_send(bus, q, NULL);
+ 
+-                sd_bus_flush(bus);
+-                sd_bus_unref(bus);
+         }
+ 
+         sd_bus_error_free(&error);
diff --git a/SOURCES/0319-core-fix-memory-leak-in-transient-units.patch b/SOURCES/0319-core-fix-memory-leak-in-transient-units.patch
new file mode 100644
index 0000000..9ef8b84
--- /dev/null
+++ b/SOURCES/0319-core-fix-memory-leak-in-transient-units.patch
@@ -0,0 +1,55 @@
+From c7d030b3f2b5969751872673e9082d0c10c031b5 Mon Sep 17 00:00:00 2001
+From: Evgeny Vereshchagin <evvers@ya.ru>
+Date: Fri, 15 Jan 2016 02:41:27 +0000
+Subject: [PATCH] core: fix memory leak in transient units
+
+Fixes:
+==1== HEAP SUMMARY:
+==1==     in use at exit: 67,182 bytes in 91 blocks
+==1==   total heap usage: 70,485 allocs, 70,394 frees, 42,184,635 bytes
+allocated
+==1==
+==1== 5,742 (696 direct, 5,046 indirect) bytes in 29 blocks are
+definitely lost in loss record 4 of 7
+==1==    at 0x4C2DD9F: realloc (in
+/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
+==1==    by 0x21ADDD: realloc_multiply (alloc-util.h:67)
+==1==    by 0x21BFB0: strv_push (strv.c:448)
+==1==    by 0x21C245: strv_consume (strv.c:520)
+==1==    by 0x21C33C: strv_extend (strv.c:559)
+==1==    by 0x278AD7: unit_write_drop_in (unit.c:3352)
+==1==    by 0x278EEB: unit_write_drop_in_private (unit.c:3403)
+==1==    by 0x190C21: bus_service_set_transient_property
+(dbus-service.c:254)
+==1==    by 0x190DBC: bus_service_set_property (dbus-service.c:284)
+==1==    by 0x18F00E: bus_unit_set_properties (dbus-unit.c:1226)
+==1==    by 0x186F6A: transient_unit_from_message (dbus-manager.c:683)
+==1==    by 0x1872B7: method_start_transient_unit (dbus-manager.c:763)
+==1==
+==1== LEAK SUMMARY:
+==1==    definitely lost: 696 bytes in 29 blocks
+==1==    indirectly lost: 5,046 bytes in 58 blocks
+==1==      possibly lost: 0 bytes in 0 blocks
+==1==    still reachable: 61,440 bytes in 4 blocks
+==1==         suppressed: 0 bytes in 0 blocks
+
+Cherry-picked from: af4fbf3c1fdd4196f7a325602daaa846fe5f3012
+Related: #1331667
+---
+ src/core/load-dropin.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/src/core/load-dropin.c b/src/core/load-dropin.c
+index 8be1900..42cf005 100644
+--- a/src/core/load-dropin.c
++++ b/src/core/load-dropin.c
+@@ -68,6 +68,9 @@ int unit_load_dropin(Unit *u) {
+                 }
+         }
+ 
++        strv_free(u->dropin_paths);
++        u->dropin_paths = NULL;
++
+         r = unit_find_dropin_paths(u, &u->dropin_paths);
+         if (r <= 0)
+                 return 0;
diff --git a/SOURCES/0320-bus-fix-leak-in-error-path.patch b/SOURCES/0320-bus-fix-leak-in-error-path.patch
new file mode 100644
index 0000000..834a358
--- /dev/null
+++ b/SOURCES/0320-bus-fix-leak-in-error-path.patch
@@ -0,0 +1,52 @@
+From 69aaf3c41923fafd9616b1bbec51fa6bcb23b886 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
+Date: Sat, 7 Mar 2015 15:05:50 -0500
+Subject: [PATCH] bus: fix leak in error path
+
+CID #1271349.
+
+Cherry-picked from: bcf88fc3f14867f1cabc911c27b661d738281df0
+Related: #1331667
+---
+ src/libsystemd/sd-bus/bus-message.c | 9 ++++-----
+ 1 file changed, 4 insertions(+), 5 deletions(-)
+
+diff --git a/src/libsystemd/sd-bus/bus-message.c b/src/libsystemd/sd-bus/bus-message.c
+index 2959303..c8402a2 100644
+--- a/src/libsystemd/sd-bus/bus-message.c
++++ b/src/libsystemd/sd-bus/bus-message.c
+@@ -441,7 +441,7 @@ int bus_message_from_header(
+                 size_t extra,
+                 sd_bus_message **ret) {
+ 
+-        sd_bus_message *m;
++        _cleanup_free_ sd_bus_message *m = NULL;
+         struct bus_header *h;
+         size_t a, label_sz;
+ 
+@@ -460,15 +460,13 @@ int bus_message_from_header(
+                 return -EBADMSG;
+ 
+         h = header;
+-        if (h->version != 1 &&
+-            h->version != 2)
++        if (!IN_SET(h->version, 1, 2))
+                 return -EBADMSG;
+ 
+         if (h->type == _SD_BUS_MESSAGE_TYPE_INVALID)
+                 return -EBADMSG;
+ 
+-        if (h->endian != BUS_LITTLE_ENDIAN &&
+-            h->endian != BUS_BIG_ENDIAN)
++        if (!IN_SET(h->endian, BUS_LITTLE_ENDIAN, BUS_BIG_ENDIAN))
+                 return -EBADMSG;
+ 
+         /* Note that we are happy with unknown flags in the flags header! */
+@@ -557,6 +555,7 @@ int bus_message_from_header(
+ 
+         m->bus = sd_bus_ref(bus);
+         *ret = m;
++        m = NULL;
+ 
+         return 0;
+ }
diff --git a/SOURCES/0321-shared-logs-show-fix-memleak-in-add_matches_for_unit.patch b/SOURCES/0321-shared-logs-show-fix-memleak-in-add_matches_for_unit.patch
new file mode 100644
index 0000000..54d207e
--- /dev/null
+++ b/SOURCES/0321-shared-logs-show-fix-memleak-in-add_matches_for_unit.patch
@@ -0,0 +1,24 @@
+From c95edddeb70a48202a0baf7b71450be87d2d921c Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
+Date: Tue, 12 Apr 2016 23:36:37 -0400
+Subject: [PATCH] shared/logs-show: fix memleak in add_matches_for_unit
+
+Cherry-picked from: 42fbdf45864b46f3eb62a3738b81e687685eb9bd
+Related: #1331667
+---
+ src/shared/logs-show.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c
+index c249505..8c37411 100644
+--- a/src/shared/logs-show.c
++++ b/src/shared/logs-show.c
+@@ -1060,7 +1060,7 @@ int add_matches_for_unit(sd_journal *j, const char *unit) {
+         );
+ 
+         if (r == 0 && endswith(unit, ".slice")) {
+-                char *m5 = strappend("_SYSTEMD_SLICE=", unit);
++                const char *m5 = strjoina("_SYSTEMD_SLICE=", unit);
+ 
+                 /* Show all messages belonging to a slice */
+                 (void)(
diff --git a/SOURCES/0322-logind-introduce-LockedHint-and-SetLockedHint-3238.patch b/SOURCES/0322-logind-introduce-LockedHint-and-SetLockedHint-3238.patch
new file mode 100644
index 0000000..bdf69ca
--- /dev/null
+++ b/SOURCES/0322-logind-introduce-LockedHint-and-SetLockedHint-3238.patch
@@ -0,0 +1,164 @@
+From 75131b469fa9e1e2e3cb623fa1f3d36cba36af78 Mon Sep 17 00:00:00 2001
+From: Victor Toso <me@victortoso.com>
+Date: Wed, 11 May 2016 19:34:13 +0200
+Subject: [PATCH] logind: introduce LockedHint and SetLockedHint (#3238)
+
+Desktop environments can keep this property up to date to allow
+applications to easily track session's Lock status.
+
+Cherry-picked from: 42d35e1301928d08dd32ec51f0205252ae658ba5
+Resolves: #1335499
+---
+ src/login/logind-session-dbus.c       | 50 +++++++++++++++++++++++++++++++++++
+ src/login/logind-session.c            | 17 ++++++++++++
+ src/login/logind-session.h            |  4 +++
+ src/login/org.freedesktop.login1.conf |  4 +++
+ 4 files changed, 75 insertions(+)
+
+diff --git a/src/login/logind-session-dbus.c b/src/login/logind-session-dbus.c
+index 4e7edef..75b7186 100644
+--- a/src/login/logind-session-dbus.c
++++ b/src/login/logind-session-dbus.c
+@@ -180,6 +180,24 @@ static int property_get_idle_since_hint(
+         return sd_bus_message_append(reply, "t", u);
+ }
+ 
++static int property_get_locked_hint(
++                sd_bus *bus,
++                const char *path,
++                const char *interface,
++                const char *property,
++                sd_bus_message *reply,
++                void *userdata,
++                sd_bus_error *error) {
++
++        Session *s = userdata;
++
++        assert(bus);
++        assert(reply);
++        assert(s);
++
++        return sd_bus_message_append(reply, "b", session_get_locked_hint(s) > 0);
++}
++
+ static int method_terminate(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+         Session *s = userdata;
+         int r;
+@@ -255,6 +273,36 @@ static int method_set_idle_hint(sd_bus *bus, sd_bus_message *message, void *user
+         return sd_bus_reply_method_return(message, NULL);
+ }
+ 
++static int method_set_locked_hint(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
++        _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
++        Session *s = userdata;
++        uid_t uid;
++        int r, b;
++
++        assert(bus);
++        assert(message);
++        assert(s);
++
++        r = sd_bus_message_read(message, "b", &b);
++        if (r < 0)
++                return r;
++
++        r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
++        if (r < 0)
++                return r;
++
++        r = sd_bus_creds_get_euid(creds, &uid);
++        if (r < 0)
++                return r;
++
++        if (uid != 0 && uid != s->user->uid)
++                return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Only owner of session may set locked hint");
++
++        session_set_locked_hint(s, b);
++
++        return sd_bus_reply_method_return(message, NULL);
++}
++
+ static int method_kill(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+         Session *s = userdata;
+         const char *swho;
+@@ -455,6 +503,7 @@ const sd_bus_vtable session_vtable[] = {
+         SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+         SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+         SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
++        SD_BUS_PROPERTY("LockedHint", "b", property_get_locked_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+ 
+         SD_BUS_METHOD("Terminate", NULL, NULL, method_terminate, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)),
+         SD_BUS_METHOD("Activate", NULL, NULL, method_activate, SD_BUS_VTABLE_UNPRIVILEGED),
+@@ -462,6 +511,7 @@ const sd_bus_vtable session_vtable[] = {
+         SD_BUS_METHOD("Unlock", NULL, NULL, method_lock, 0),
+         SD_BUS_METHOD("SetIdleHint", "b", NULL, method_set_idle_hint, SD_BUS_VTABLE_UNPRIVILEGED),
+         SD_BUS_METHOD("Kill", "si", NULL, method_kill, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)),
++        SD_BUS_METHOD("SetLockedHint", "b", NULL, method_set_locked_hint, SD_BUS_VTABLE_UNPRIVILEGED),
+         SD_BUS_METHOD("TakeControl", "b", NULL, method_take_control, SD_BUS_VTABLE_UNPRIVILEGED),
+         SD_BUS_METHOD("ReleaseControl", NULL, NULL, method_release_control, SD_BUS_VTABLE_UNPRIVILEGED),
+         SD_BUS_METHOD("TakeDevice", "uu", "hb", method_take_device, SD_BUS_VTABLE_UNPRIVILEGED),
+diff --git a/src/login/logind-session.c b/src/login/logind-session.c
+index d2e7b40..dc24539 100644
+--- a/src/login/logind-session.c
++++ b/src/login/logind-session.c
+@@ -843,6 +843,23 @@ void session_set_idle_hint(Session *s, bool b) {
+         manager_send_changed(s->manager, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
+ }
+ 
++int session_get_locked_hint(Session *s) {
++        assert(s);
++
++        return s->locked_hint;
++}
++
++void session_set_locked_hint(Session *s, bool b) {
++        assert(s);
++
++        if (s->locked_hint == b)
++                return;
++
++        s->locked_hint = b;
++
++        session_send_changed(s, "LockedHint", NULL);
++}
++
+ static int session_dispatch_fifo(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
+         Session *s = userdata;
+ 
+diff --git a/src/login/logind-session.h b/src/login/logind-session.h
+index a007fb5..5002b68 100644
+--- a/src/login/logind-session.h
++++ b/src/login/logind-session.h
+@@ -111,6 +111,8 @@ struct Session {
+         bool idle_hint;
+         dual_timestamp idle_hint_timestamp;
+ 
++        bool locked_hint;
++
+         bool in_gc_queue:1;
+         bool started:1;
+         bool stopping:1;
+@@ -137,6 +139,8 @@ int session_activate(Session *s);
+ bool session_is_active(Session *s);
+ int session_get_idle_hint(Session *s, dual_timestamp *t);
+ void session_set_idle_hint(Session *s, bool b);
++int session_get_locked_hint(Session *s);
++void session_set_locked_hint(Session *s, bool b);
+ int session_create_fifo(Session *s);
+ int session_start(Session *s);
+ int session_stop(Session *s, bool force);
+diff --git a/src/login/org.freedesktop.login1.conf b/src/login/org.freedesktop.login1.conf
+index 1318328..dc7e0be 100644
+--- a/src/login/org.freedesktop.login1.conf
++++ b/src/login/org.freedesktop.login1.conf
+@@ -162,6 +162,10 @@
+ 
+                 <allow send_destination="org.freedesktop.login1"
+                        send_interface="org.freedesktop.login1.Session"
++                       send_member="SetLockedHint"/>
++
++                <allow send_destination="org.freedesktop.login1"
++                       send_interface="org.freedesktop.login1.Session"
+                        send_member="TakeControl"/>
+ 
+                 <allow send_destination="org.freedesktop.login1"
diff --git a/SOURCES/0323-import-use-the-old-curl-api.patch b/SOURCES/0323-import-use-the-old-curl-api.patch
new file mode 100644
index 0000000..8f3a938
--- /dev/null
+++ b/SOURCES/0323-import-use-the-old-curl-api.patch
@@ -0,0 +1,40 @@
+From 575f559bcd992d7fd2d7d46b695b7f42923b4463 Mon Sep 17 00:00:00 2001
+From: Lukas Nykryn <lnykryn@redhat.com>
+Date: Wed, 6 Apr 2016 15:39:09 +0200
+Subject: [PATCH] import: use the old curl api
+
+libcurl in rhel does not have CURLOPT_XFERINFO* symbols, so lets use the
+old interface.
+
+RHEL-only
+Resolves: #1284974
+---
+ src/import/import-job.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/src/import/import-job.c b/src/import/import-job.c
+index 8094865..5f9cfd3 100644
+--- a/src/import/import-job.c
++++ b/src/import/import-job.c
+@@ -587,7 +587,7 @@ fail:
+         return 0;
+ }
+ 
+-static int import_job_progress_callback(void *userdata, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow) {
++static int import_job_progress_callback(void *userdata, double dltotal, double dlnow, double ultotal, double ulnow) {
+         ImportJob *j = userdata;
+         unsigned percent;
+         usec_t n;
+@@ -714,10 +714,10 @@ int import_job_begin(ImportJob *j) {
+         if (curl_easy_setopt(j->curl, CURLOPT_HEADERDATA, j) != CURLE_OK)
+                 return -EIO;
+ 
+-        if (curl_easy_setopt(j->curl, CURLOPT_XFERINFOFUNCTION, import_job_progress_callback) != CURLE_OK)
++        if (curl_easy_setopt(j->curl, CURLOPT_PROGRESSFUNCTION, import_job_progress_callback) != CURLE_OK)
+                 return -EIO;
+ 
+-        if (curl_easy_setopt(j->curl, CURLOPT_XFERINFODATA, j) != CURLE_OK)
++        if (curl_easy_setopt(j->curl, CURLOPT_PROGRESSDATA, j) != CURLE_OK)
+                 return -EIO;
+ 
+         if (curl_easy_setopt(j->curl, CURLOPT_NOPROGRESS, 0) != CURLE_OK)
diff --git a/SOURCES/0324-importd-drop-dkr-support.patch b/SOURCES/0324-importd-drop-dkr-support.patch
new file mode 100644
index 0000000..e6c1d55
--- /dev/null
+++ b/SOURCES/0324-importd-drop-dkr-support.patch
@@ -0,0 +1,1694 @@
+From b4bfb025f7ab0878e8e7e980dbad5b0a5bed1555 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Thu, 10 Dec 2015 12:40:04 +0100
+Subject: [PATCH] importd: drop dkr support
+
+The current code is not compatible with current dkr protocols anyway,
+and dkr has a different focus ("microservices") than nspawn anyway
+("whole machine containers"), hence drop support for it, we cannot
+reasonably keep this up to date, and it creates the impression we'd
+actually care for the microservices usecase.
+
+Cherry-picked from: b43d75c
+Related: #1284974
+---
+ Makefile.am                             |   2 -
+ TODO                                    |   4 -
+ configure.ac                            |   9 -
+ man/machinectl.xml                      |  58 ---
+ src/import/import-dkr.c                 | 891 --------------------------------
+ src/import/import-dkr.h                 |  36 --
+ src/import/importd.c                    | 111 +---
+ src/import/org.freedesktop.import1.conf |   4 -
+ src/import/pull.c                       | 119 +----
+ src/machine/machinectl.c                |  90 +---
+ src/shared/import-util.c                |  31 --
+ src/shared/import-util.h                |   4 -
+ 12 files changed, 5 insertions(+), 1354 deletions(-)
+ delete mode 100644 src/import/import-dkr.c
+ delete mode 100644 src/import/import-dkr.h
+
+diff --git a/Makefile.am b/Makefile.am
+index 3a09e0a..b0a34b2 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -5369,8 +5369,6 @@ systemd_pull_SOURCES = \
+ 	src/import/import-raw.h \
+ 	src/import/import-tar.c \
+ 	src/import/import-tar.h \
+-	src/import/import-dkr.c \
+-	src/import/import-dkr.h \
+ 	src/import/import-job.c \
+ 	src/import/import-job.h \
+ 	src/import/import-common.c \
+diff --git a/TODO b/TODO
+index 90b2c4b..d96d2bf 100644
+--- a/TODO
++++ b/TODO
+@@ -126,10 +126,6 @@ Features:
+ 
+ * rework journald sigbus stuff to use mutex
+ 
+-* import-dkr: support tarsum checksum verification, if it becomes reality one day...
+-
+-* import-dkr: convert json bits to nspawn configuration
+-
+ * import: support import from local files, and export to local files
+ 
+ * core/cgroup: support net_cls modules, and support automatically allocating class ids, then add support for making firewall changes depending on it, to implement a per-service firewall
+diff --git a/configure.ac b/configure.ac
+index 9103f9b..2734368 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -1389,14 +1389,6 @@ AC_ARG_ENABLE([split-usr],
+                 enable_split_usr=no
+         ])])
+ 
+-AC_ARG_WITH([dkr-index-url],
+-        [AS_HELP_STRING([--dkr-index-url=URL], [Specify the default index URL to use for image downloads])],
+-        [DEFAULT_DKR_INDEX_URL="\"$withval\""],
+-        [DEFAULT_DKR_INDEX_URL="NULL"])
+-
+-AC_DEFINE_UNQUOTED(DEFAULT_DKR_INDEX_URL, [$DEFAULT_DKR_INDEX_URL], [Default index URL to use for image downloads])
+-AC_SUBST(DEFAULT_DKR_INDEX_URL)
+-
+ AS_IF([test "x${enable_split_usr}" = "xyes"], [
+         AC_DEFINE(HAVE_SPLIT_USR, 1, [Define if /bin, /sbin aren't symlinks into /usr])
+ ])
+@@ -1564,7 +1556,6 @@ AC_MSG_RESULT([
+         Maximum System UID:      ${SYSTEM_UID_MAX}
+         Maximum System GID:      ${SYSTEM_GID_MAX}
+         Certificate root:        ${CERTIFICATEROOT}
+-        Default dkr Index        ${DEFAULT_DKR_INDEX_URL}
+ 
+         CFLAGS:                  ${OUR_CFLAGS} ${CFLAGS}
+         CPPFLAGS:                ${OUR_CPPFLAGS} ${CPPFLAGS}
+diff --git a/man/machinectl.xml b/man/machinectl.xml
+index 640cb8b..b0a7f2a 100644
+--- a/man/machinectl.xml
++++ b/man/machinectl.xml
+@@ -204,16 +204,6 @@
+         image.</para></listitem>
+       </varlistentry>
+ 
+-      <varlistentry>
+-        <term><option>--dkr-index-url</option></term>
+-
+-        <listitem><para>Specifies the index server to use for
+-        downloading <literal>dkr</literal> images with the
+-        <command>pull-dkr</command>. Takes a
+-        <literal>http://</literal>, <literal>https://</literal>
+-        URL.</para></listitem>
+-      </varlistentry>
+-
+       <xi:include href="user-system-options.xml" xpointer="host" />
+       <xi:include href="user-system-options.xml" xpointer="machine" />
+ 
+@@ -603,42 +593,6 @@
+       </varlistentry>
+ 
+       <varlistentry>
+-        <term><command>pull-dkr</command> <replaceable>REMOTE</replaceable> [<replaceable>NAME</replaceable>]</term>
+-
+-        <listitem><para>Downloads a <literal>dkr</literal> container
+-        image and makes it available locally. The remote name refers
+-        to a <literal>dkr</literal> container name. If omitted, the
+-        local machine name is derived from the <literal>dkr</literal>
+-        container name.</para>
+-
+-        <para>Image verification is not available for
+-        <literal>dkr</literal> containers, and thus
+-        <option>--verify=no</option> must always be specified with
+-        this command.</para>
+-
+-        <para>This command downloads all (missing) layers for the
+-        specified container and places them in read-only subvolumes in
+-        <filename>/var/lib/machines/</filename>. A writable snapshot
+-        of the newest layer is then created under the specified local
+-        machine name. To omit creation of this writable snapshot, pass
+-        <literal>-</literal> as local machine name.</para>
+-
+-        <para>The read-only layer subvolumes are prefixed with
+-        <filename>.dkr-</filename>, and thus now shown by
+-        <command>list-images</command>, unless <option>--all</option>
+-        is passed.</para>
+-
+-        <para>To specify the <literal>dkr</literal> index server to
+-        use for looking up the specified container, use
+-        <option>--dkr-index-url=</option>.</para>
+-
+-        <para>Note that pressing C-c during execution of this command
+-        will not abort the download. Use
+-        <command>cancel-transfer</command>, described
+-        below.</para></listitem>
+-      </varlistentry>
+-
+-      <varlistentry>
+         <term><command>list-transfers</command></term>
+ 
+         <listitem><para>Shows a list of container or VM image
+@@ -728,18 +682,6 @@
+       the machine started as system service. With the last command a
+       login prompt into the container is requested.</para>
+     </example>
+-
+-    <example>
+-      <title>Download a Fedora <literal>dkr</literal> image</title>
+-
+-      <programlisting># machinectl pull-dkr --verify=no mattdm/fedora
+-# systemd-nspawn -M fedora</programlisting>
+-
+-      <para>Downloads a <literal>dkr</literal> image and opens a shell
+-      in it. Note that the specified download command might require an
+-      index server to be specified with the
+-      <literal>--dkr-index-url=</literal>.</para>
+-    </example>
+   </refsect1>
+ 
+   <refsect1>
+diff --git a/src/import/import-dkr.c b/src/import/import-dkr.c
+deleted file mode 100644
+index fb72f6c..0000000
+--- a/src/import/import-dkr.c
++++ /dev/null
+@@ -1,891 +0,0 @@
+-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+-
+-/***
+-  This file is part of systemd.
+-
+-  Copyright 2014 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 <curl/curl.h>
+-#include <sys/prctl.h>
+-
+-#include "sd-daemon.h"
+-#include "json.h"
+-#include "strv.h"
+-#include "btrfs-util.h"
+-#include "utf8.h"
+-#include "mkdir.h"
+-#include "import-util.h"
+-#include "curl-util.h"
+-#include "aufs-util.h"
+-#include "import-job.h"
+-#include "import-common.h"
+-#include "import-dkr.h"
+-
+-typedef enum DkrProgress {
+-        DKR_SEARCHING,
+-        DKR_RESOLVING,
+-        DKR_METADATA,
+-        DKR_DOWNLOADING,
+-        DKR_COPYING,
+-} DkrProgress;
+-
+-struct DkrImport {
+-        sd_event *event;
+-        CurlGlue *glue;
+-
+-        char *index_url;
+-        char *image_root;
+-
+-        ImportJob *images_job;
+-        ImportJob *tags_job;
+-        ImportJob *ancestry_job;
+-        ImportJob *json_job;
+-        ImportJob *layer_job;
+-
+-        char *name;
+-        char *tag;
+-        char *id;
+-
+-        char *response_token;
+-        char **response_registries;
+-
+-        char **ancestry;
+-        unsigned n_ancestry;
+-        unsigned current_ancestry;
+-
+-        DkrImportFinished on_finished;
+-        void *userdata;
+-
+-        char *local;
+-        bool force_local;
+-
+-        char *temp_path;
+-        char *final_path;
+-
+-        pid_t tar_pid;
+-};
+-
+-#define PROTOCOL_PREFIX "https://"
+-
+-#define HEADER_TOKEN "X-Do" /* the HTTP header for the auth token */ "cker-Token:"
+-#define HEADER_REGISTRY "X-Do" /*the HTTP header for the registry */ "cker-Endpoints:"
+-
+-#define LAYERS_MAX 2048
+-
+-static void dkr_import_job_on_finished(ImportJob *j);
+-
+-DkrImport* dkr_import_unref(DkrImport *i) {
+-        if (!i)
+-                return NULL;
+-
+-        if (i->tar_pid > 1) {
+-                (void) kill_and_sigcont(i->tar_pid, SIGKILL);
+-                (void) wait_for_terminate(i->tar_pid, NULL);
+-        }
+-
+-        import_job_unref(i->images_job);
+-        import_job_unref(i->tags_job);
+-        import_job_unref(i->ancestry_job);
+-        import_job_unref(i->json_job);
+-        import_job_unref(i->layer_job);
+-
+-        curl_glue_unref(i->glue);
+-        sd_event_unref(i->event);
+-
+-        if (i->temp_path) {
+-                (void) btrfs_subvol_remove(i->temp_path);
+-                (void) rm_rf_dangerous(i->temp_path, false, true, false);
+-                free(i->temp_path);
+-        }
+-
+-        free(i->name);
+-        free(i->tag);
+-        free(i->id);
+-        free(i->response_token);
+-        free(i->response_registries);
+-        strv_free(i->ancestry);
+-        free(i->final_path);
+-        free(i->index_url);
+-        free(i->image_root);
+-        free(i->local);
+-        free(i);
+-
+-        return NULL;
+-}
+-
+-int dkr_import_new(
+-                DkrImport **ret,
+-                sd_event *event,
+-                const char *index_url,
+-                const char *image_root,
+-                DkrImportFinished on_finished,
+-                void *userdata) {
+-
+-        _cleanup_(dkr_import_unrefp) DkrImport *i = NULL;
+-        char *e;
+-        int r;
+-
+-        assert(ret);
+-        assert(index_url);
+-
+-        if (!http_url_is_valid(index_url))
+-                return -EINVAL;
+-
+-        i = new0(DkrImport, 1);
+-        if (!i)
+-                return -ENOMEM;
+-
+-        i->on_finished = on_finished;
+-        i->userdata = userdata;
+-
+-        i->image_root = strdup(image_root ?: "/var/lib/machines");
+-        if (!i->image_root)
+-                return -ENOMEM;
+-
+-        i->index_url = strdup(index_url);
+-        if (!i->index_url)
+-                return -ENOMEM;
+-
+-        e = endswith(i->index_url, "/");
+-        if (e)
+-                *e = 0;
+-
+-        if (event)
+-                i->event = sd_event_ref(event);
+-        else {
+-                r = sd_event_default(&i->event);
+-                if (r < 0)
+-                        return r;
+-        }
+-
+-        r = curl_glue_new(&i->glue, i->event);
+-        if (r < 0)
+-                return r;
+-
+-        i->glue->on_finished = import_job_curl_on_finished;
+-        i->glue->userdata = i;
+-
+-        *ret = i;
+-        i = NULL;
+-
+-        return 0;
+-}
+-
+-static void dkr_import_report_progress(DkrImport *i, DkrProgress p) {
+-        unsigned percent;
+-
+-        assert(i);
+-
+-        switch (p) {
+-
+-        case DKR_SEARCHING:
+-                percent = 0;
+-                if (i->images_job)
+-                        percent += i->images_job->progress_percent * 5 / 100;
+-                break;
+-
+-        case DKR_RESOLVING:
+-                percent = 5;
+-                if (i->tags_job)
+-                        percent += i->tags_job->progress_percent * 5 / 100;
+-                break;
+-
+-        case DKR_METADATA:
+-                percent = 10;
+-                if (i->ancestry_job)
+-                        percent += i->ancestry_job->progress_percent * 5 / 100;
+-                if (i->json_job)
+-                        percent += i->json_job->progress_percent * 5 / 100;
+-                break;
+-
+-        case DKR_DOWNLOADING:
+-                percent = 20;
+-                percent += 75 * i->current_ancestry / MAX(1U, i->n_ancestry);
+-                if (i->layer_job)
+-                        percent += i->layer_job->progress_percent * 75 / MAX(1U, i->n_ancestry) / 100;
+-
+-                break;
+-
+-        case DKR_COPYING:
+-                percent = 95;
+-                break;
+-
+-        default:
+-                assert_not_reached("Unknown progress state");
+-        }
+-
+-        sd_notifyf(false, "X_IMPORT_PROGRESS=%u", percent);
+-        log_debug("Combined progress %u%%", percent);
+-}
+-
+-static int parse_id(const void *payload, size_t size, char **ret) {
+-        _cleanup_free_ char *buf = NULL, *id = NULL, *other = NULL;
+-        union json_value v = {};
+-        void *json_state = NULL;
+-        const char *p;
+-        int t;
+-
+-        assert(payload);
+-        assert(ret);
+-
+-        if (size <= 0)
+-                return -EBADMSG;
+-
+-        if (memchr(payload, 0, size))
+-                return -EBADMSG;
+-
+-        buf = strndup(payload, size);
+-        if (!buf)
+-                return -ENOMEM;
+-
+-        p = buf;
+-        t = json_tokenize(&p, &id, &v, &json_state, NULL);
+-        if (t < 0)
+-                return t;
+-        if (t != JSON_STRING)
+-                return -EBADMSG;
+-
+-        t = json_tokenize(&p, &other, &v, &json_state, NULL);
+-        if (t < 0)
+-                return t;
+-        if (t != JSON_END)
+-                return -EBADMSG;
+-
+-        if (!dkr_id_is_valid(id))
+-                return -EBADMSG;
+-
+-        *ret = id;
+-        id = NULL;
+-
+-        return 0;
+-}
+-
+-static int parse_ancestry(const void *payload, size_t size, char ***ret) {
+-        _cleanup_free_ char *buf = NULL;
+-        void *json_state = NULL;
+-        const char *p;
+-        enum {
+-                STATE_BEGIN,
+-                STATE_ITEM,
+-                STATE_COMMA,
+-                STATE_END,
+-        } state = STATE_BEGIN;
+-        _cleanup_strv_free_ char **l = NULL;
+-        size_t n = 0, allocated = 0;
+-
+-        if (size <= 0)
+-                return -EBADMSG;
+-
+-        if (memchr(payload, 0, size))
+-                return -EBADMSG;
+-
+-        buf = strndup(payload, size);
+-        if (!buf)
+-                return -ENOMEM;
+-
+-        p = buf;
+-        for (;;) {
+-                _cleanup_free_ char *str;
+-                union json_value v = {};
+-                int t;
+-
+-                t = json_tokenize(&p, &str, &v, &json_state, NULL);
+-                if (t < 0)
+-                        return t;
+-
+-                switch (state) {
+-
+-                case STATE_BEGIN:
+-                        if (t == JSON_ARRAY_OPEN)
+-                                state = STATE_ITEM;
+-                        else
+-                                return -EBADMSG;
+-
+-                        break;
+-
+-                case STATE_ITEM:
+-                        if (t == JSON_STRING) {
+-                                if (!dkr_id_is_valid(str))
+-                                        return -EBADMSG;
+-
+-                                if (n+1 > LAYERS_MAX)
+-                                        return -EFBIG;
+-
+-                                if (!GREEDY_REALLOC(l, allocated, n + 2))
+-                                        return -ENOMEM;
+-
+-                                l[n++] = str;
+-                                str = NULL;
+-                                l[n] = NULL;
+-
+-                                state = STATE_COMMA;
+-
+-                        } else if (t == JSON_ARRAY_CLOSE)
+-                                state = STATE_END;
+-                        else
+-                                return -EBADMSG;
+-
+-                        break;
+-
+-                case STATE_COMMA:
+-                        if (t == JSON_COMMA)
+-                                state = STATE_ITEM;
+-                        else if (t == JSON_ARRAY_CLOSE)
+-                                state = STATE_END;
+-                        else
+-                                return -EBADMSG;
+-                        break;
+-
+-                case STATE_END:
+-                        if (t == JSON_END) {
+-
+-                                if (strv_isempty(l))
+-                                        return -EBADMSG;
+-
+-                                if (!strv_is_uniq(l))
+-                                        return -EBADMSG;
+-
+-                                l = strv_reverse(l);
+-
+-                                *ret = l;
+-                                l = NULL;
+-                                return 0;
+-                        } else
+-                                return -EBADMSG;
+-                }
+-
+-        }
+-}
+-
+-static const char *dkr_import_current_layer(DkrImport *i) {
+-        assert(i);
+-
+-        if (strv_isempty(i->ancestry))
+-                return NULL;
+-
+-        return i->ancestry[i->current_ancestry];
+-}
+-
+-static const char *dkr_import_current_base_layer(DkrImport *i) {
+-        assert(i);
+-
+-        if (strv_isempty(i->ancestry))
+-                return NULL;
+-
+-        if (i->current_ancestry <= 0)
+-                return NULL;
+-
+-        return i->ancestry[i->current_ancestry-1];
+-}
+-
+-static int dkr_import_add_token(DkrImport *i, ImportJob *j) {
+-        const char *t;
+-
+-        assert(i);
+-        assert(j);
+-
+-        if (i->response_token)
+-                t = strjoina("Authorization: Token ", i->response_token);
+-        else
+-                t = HEADER_TOKEN " true";
+-
+-        j->request_header = curl_slist_new("Accept: application/json", t, NULL);
+-        if (!j->request_header)
+-                return -ENOMEM;
+-
+-        return 0;
+-}
+-
+-static bool dkr_import_is_done(DkrImport *i) {
+-        assert(i);
+-        assert(i->images_job);
+-
+-        if (i->images_job->state != IMPORT_JOB_DONE)
+-                return false;
+-
+-        if (!i->tags_job || i->tags_job->state != IMPORT_JOB_DONE)
+-                return false;
+-
+-        if (!i->ancestry_job || i->ancestry_job->state != IMPORT_JOB_DONE)
+-                return false;
+-
+-        if (!i->json_job || i->json_job->state != IMPORT_JOB_DONE)
+-                return false;
+-
+-        if (i->layer_job && i->layer_job->state != IMPORT_JOB_DONE)
+-                return false;
+-
+-        if (dkr_import_current_layer(i))
+-                return false;
+-
+-        return true;
+-}
+-
+-static int dkr_import_make_local_copy(DkrImport *i) {
+-        int r;
+-
+-        assert(i);
+-
+-        if (!i->local)
+-                return 0;
+-
+-        if (!i->final_path) {
+-                i->final_path = strjoin(i->image_root, "/.dkr-", i->id, NULL);
+-                if (!i->final_path)
+-                        return log_oom();
+-        }
+-
+-        r = import_make_local_copy(i->final_path, i->image_root, i->local, i->force_local);
+-        if (r < 0)
+-                return r;
+-
+-        return 0;
+-}
+-
+-static int dkr_import_job_on_open_disk(ImportJob *j) {
+-        const char *base;
+-        DkrImport *i;
+-        int r;
+-
+-        assert(j);
+-        assert(j->userdata);
+-
+-        i = j->userdata;
+-        assert(i->layer_job == j);
+-        assert(i->final_path);
+-        assert(!i->temp_path);
+-        assert(i->tar_pid <= 0);
+-
+-        r = tempfn_random(i->final_path, &i->temp_path);
+-        if (r < 0)
+-                return log_oom();
+-
+-        mkdir_parents_label(i->temp_path, 0700);
+-
+-        base = dkr_import_current_base_layer(i);
+-        if (base) {
+-                const char *base_path;
+-
+-                base_path = strjoina(i->image_root, "/.dkr-", base);
+-                r = btrfs_subvol_snapshot(base_path, i->temp_path, false, true);
+-        } else
+-                r = btrfs_subvol_make(i->temp_path);
+-        if (r < 0)
+-                return log_error_errno(r, "Failed to make btrfs subvolume %s: %m", i->temp_path);
+-
+-        j->disk_fd = import_fork_tar(i->temp_path, &i->tar_pid);
+-        if (j->disk_fd < 0)
+-                return j->disk_fd;
+-
+-        return 0;
+-}
+-
+-static void dkr_import_job_on_progress(ImportJob *j) {
+-        DkrImport *i;
+-
+-        assert(j);
+-        assert(j->userdata);
+-
+-        i = j->userdata;
+-
+-        dkr_import_report_progress(
+-                        i,
+-                        j == i->images_job                       ? DKR_SEARCHING :
+-                        j == i->tags_job                         ? DKR_RESOLVING :
+-                        j == i->ancestry_job || j == i->json_job ? DKR_METADATA :
+-                                                                   DKR_DOWNLOADING);
+-}
+-
+-static int dkr_import_pull_layer(DkrImport *i) {
+-        _cleanup_free_ char *path = NULL;
+-        const char *url, *layer = NULL;
+-        int r;
+-
+-        assert(i);
+-        assert(!i->layer_job);
+-        assert(!i->temp_path);
+-        assert(!i->final_path);
+-
+-        for (;;) {
+-                layer = dkr_import_current_layer(i);
+-                if (!layer)
+-                        return 0; /* no more layers */
+-
+-                path = strjoin(i->image_root, "/.dkr-", layer, NULL);
+-                if (!path)
+-                        return log_oom();
+-
+-                if (laccess(path, F_OK) < 0) {
+-                        if (errno == ENOENT)
+-                                break;
+-
+-                        return log_error_errno(errno, "Failed to check for container: %m");
+-                }
+-
+-                log_info("Layer %s already exists, skipping.", layer);
+-
+-                i->current_ancestry++;
+-
+-                free(path);
+-                path = NULL;
+-        }
+-
+-        log_info("Pulling layer %s...", layer);
+-
+-        i->final_path = path;
+-        path = NULL;
+-
+-        url = strjoina(PROTOCOL_PREFIX, i->response_registries[0], "/v1/images/", layer, "/layer");
+-        r = import_job_new(&i->layer_job, url, i->glue, i);
+-        if (r < 0)
+-                return log_error_errno(r, "Failed to allocate layer job: %m");
+-
+-        r = dkr_import_add_token(i, i->layer_job);
+-        if (r < 0)
+-                return log_oom();
+-
+-        i->layer_job->on_finished = dkr_import_job_on_finished;
+-        i->layer_job->on_open_disk = dkr_import_job_on_open_disk;
+-        i->layer_job->on_progress = dkr_import_job_on_progress;
+-
+-        r = import_job_begin(i->layer_job);
+-        if (r < 0)
+-                return log_error_errno(r, "Failed to start layer job: %m");
+-
+-        return 0;
+-}
+-
+-static void dkr_import_job_on_finished(ImportJob *j) {
+-        DkrImport *i;
+-        int r;
+-
+-        assert(j);
+-        assert(j->userdata);
+-
+-        i = j->userdata;
+-        if (j->error != 0) {
+-                if (j == i->images_job)
+-                        log_error_errno(j->error, "Failed to retrieve images list. (Wrong index URL?)");
+-                else if (j == i->tags_job)
+-                        log_error_errno(j->error, "Failed to retrieve tags list.");
+-                else if (j == i->ancestry_job)
+-                        log_error_errno(j->error, "Failed to retrieve ancestry list.");
+-                else if (j == i->json_job)
+-                        log_error_errno(j->error, "Failed to retrieve json data.");
+-                else
+-                        log_error_errno(j->error, "Failed to retrieve layer data.");
+-
+-                r = j->error;
+-                goto finish;
+-        }
+-
+-        if (i->images_job == j) {
+-                const char *url;
+-
+-                assert(!i->tags_job);
+-                assert(!i->ancestry_job);
+-                assert(!i->json_job);
+-                assert(!i->layer_job);
+-
+-                if (strv_isempty(i->response_registries)) {
+-                        r = -EBADMSG;
+-                        log_error("Didn't get registry information.");
+-                        goto finish;
+-                }
+-
+-                log_info("Index lookup succeeded, directed to registry %s.", i->response_registries[0]);
+-                dkr_import_report_progress(i, DKR_RESOLVING);
+-
+-                url = strjoina(PROTOCOL_PREFIX, i->response_registries[0], "/v1/repositories/", i->name, "/tags/", i->tag);
+-                r = import_job_new(&i->tags_job, url, i->glue, i);
+-                if (r < 0) {
+-                        log_error_errno(r, "Failed to allocate tags job: %m");
+-                        goto finish;
+-                }
+-
+-                r = dkr_import_add_token(i, i->tags_job);
+-                if (r < 0) {
+-                        log_oom();
+-                        goto finish;
+-                }
+-
+-                i->tags_job->on_finished = dkr_import_job_on_finished;
+-                i->tags_job->on_progress = dkr_import_job_on_progress;
+-
+-                r = import_job_begin(i->tags_job);
+-                if (r < 0) {
+-                        log_error_errno(r, "Failed to start tags job: %m");
+-                        goto finish;
+-                }
+-
+-        } else if (i->tags_job == j) {
+-                const char *url;
+-                char *id = NULL;
+-
+-                assert(!i->ancestry_job);
+-                assert(!i->json_job);
+-                assert(!i->layer_job);
+-
+-                r = parse_id(j->payload, j->payload_size, &id);
+-                if (r < 0) {
+-                        log_error_errno(r, "Failed to parse JSON id.");
+-                        goto finish;
+-                }
+-
+-                free(i->id);
+-                i->id = id;
+-
+-                log_info("Tag lookup succeeded, resolved to layer %s.", i->id);
+-                dkr_import_report_progress(i, DKR_METADATA);
+-
+-                url = strjoina(PROTOCOL_PREFIX, i->response_registries[0], "/v1/images/", i->id, "/ancestry");
+-                r = import_job_new(&i->ancestry_job, url, i->glue, i);
+-                if (r < 0) {
+-                        log_error_errno(r, "Failed to allocate ancestry job: %m");
+-                        goto finish;
+-                }
+-
+-                r = dkr_import_add_token(i, i->ancestry_job);
+-                if (r < 0) {
+-                        log_oom();
+-                        goto finish;
+-                }
+-
+-                i->ancestry_job->on_finished = dkr_import_job_on_finished;
+-                i->ancestry_job->on_progress = dkr_import_job_on_progress;
+-
+-                url = strjoina(PROTOCOL_PREFIX, i->response_registries[0], "/v1/images/", i->id, "/json");
+-                r = import_job_new(&i->json_job, url, i->glue, i);
+-                if (r < 0) {
+-                        log_error_errno(r, "Failed to allocate json job: %m");
+-                        goto finish;
+-                }
+-
+-                r = dkr_import_add_token(i, i->json_job);
+-                if (r < 0) {
+-                        log_oom();
+-                        goto finish;
+-                }
+-
+-                i->json_job->on_finished = dkr_import_job_on_finished;
+-                i->json_job->on_progress = dkr_import_job_on_progress;
+-
+-                r = import_job_begin(i->ancestry_job);
+-                if (r < 0) {
+-                        log_error_errno(r, "Failed to start ancestry job: %m");
+-                        goto finish;
+-                }
+-
+-                r = import_job_begin(i->json_job);
+-                if (r < 0) {
+-                        log_error_errno(r, "Failed to start json job: %m");
+-                        goto finish;
+-                }
+-
+-        } else if (i->ancestry_job == j) {
+-                char **ancestry = NULL, **k;
+-                unsigned n;
+-
+-                assert(!i->layer_job);
+-
+-                r = parse_ancestry(j->payload, j->payload_size, &ancestry);
+-                if (r < 0) {
+-                        log_error_errno(r, "Failed to parse JSON id.");
+-                        goto finish;
+-                }
+-
+-                n = strv_length(ancestry);
+-                if (n <= 0 || !streq(ancestry[n-1], i->id)) {
+-                        log_error("Ancestry doesn't end in main layer.");
+-                        strv_free(ancestry);
+-                        r = -EBADMSG;
+-                        goto finish;
+-                }
+-
+-                log_info("Ancestor lookup succeeded, requires layers:\n");
+-                STRV_FOREACH(k, ancestry)
+-                        log_info("\t%s", *k);
+-
+-                strv_free(i->ancestry);
+-                i->ancestry = ancestry;
+-                i->n_ancestry = n;
+-                i->current_ancestry = 0;
+-
+-                dkr_import_report_progress(i, DKR_DOWNLOADING);
+-
+-                r = dkr_import_pull_layer(i);
+-                if (r < 0)
+-                        goto finish;
+-
+-        } else if (i->layer_job == j) {
+-                assert(i->temp_path);
+-                assert(i->final_path);
+-
+-                j->disk_fd = safe_close(j->disk_fd);
+-
+-                if (i->tar_pid > 0) {
+-                        r = wait_for_terminate_and_warn("tar", i->tar_pid, true);
+-                        i->tar_pid = 0;
+-                        if (r < 0)
+-                                goto finish;
+-                }
+-
+-                r = aufs_resolve(i->temp_path);
+-                if (r < 0) {
+-                        log_error_errno(r, "Failed to resolve aufs whiteouts: %m");
+-                        goto finish;
+-                }
+-
+-                r = btrfs_subvol_set_read_only(i->temp_path, true);
+-                if (r < 0) {
+-                        log_error_errno(r, "Failed to mark snapshot read-only: %m");
+-                        goto finish;
+-                }
+-
+-                if (rename(i->temp_path, i->final_path) < 0) {
+-                        log_error_errno(errno, "Failed to rename snaphsot: %m");
+-                        goto finish;
+-                }
+-
+-                log_info("Completed writing to layer %s.", i->final_path);
+-
+-                i->layer_job = import_job_unref(i->layer_job);
+-                free(i->temp_path);
+-                i->temp_path = NULL;
+-                free(i->final_path);
+-                i->final_path = NULL;
+-
+-                i->current_ancestry ++;
+-                r = dkr_import_pull_layer(i);
+-                if (r < 0)
+-                        goto finish;
+-
+-        } else if (i->json_job != j)
+-                assert_not_reached("Got finished event for unknown curl object");
+-
+-        if (!dkr_import_is_done(i))
+-                return;
+-
+-        dkr_import_report_progress(i, DKR_COPYING);
+-
+-        r = dkr_import_make_local_copy(i);
+-        if (r < 0)
+-                goto finish;
+-
+-        r = 0;
+-
+-finish:
+-        if (i->on_finished)
+-                i->on_finished(i, r, i->userdata);
+-        else
+-                sd_event_exit(i->event, r);
+-}
+-
+-static int dkr_import_job_on_header(ImportJob *j, const char *header, size_t sz)  {
+-        _cleanup_free_ char *registry = NULL;
+-        char *token;
+-        DkrImport *i;
+-        int r;
+-
+-        assert(j);
+-        assert(j->userdata);
+-
+-        i = j->userdata;
+-
+-        r = curl_header_strdup(header, sz, HEADER_TOKEN, &token);
+-        if (r < 0)
+-                return log_oom();
+-        if (r > 0) {
+-                free(i->response_token);
+-                i->response_token = token;
+-                return 0;
+-        }
+-
+-        r = curl_header_strdup(header, sz, HEADER_REGISTRY, &registry);
+-        if (r < 0)
+-                return log_oom();
+-        if (r > 0) {
+-                char **l, **k;
+-
+-                l = strv_split(registry, ",");
+-                if (!l)
+-                        return log_oom();
+-
+-                STRV_FOREACH(k, l) {
+-                        if (!hostname_is_valid(*k)) {
+-                                log_error("Registry hostname is not valid.");
+-                                strv_free(l);
+-                                return -EBADMSG;
+-                        }
+-                }
+-
+-                strv_free(i->response_registries);
+-                i->response_registries = l;
+-        }
+-
+-        return 0;
+-}
+-
+-int dkr_import_pull(DkrImport *i, const char *name, const char *tag, const char *local, bool force_local) {
+-        const char *url;
+-        int r;
+-
+-        assert(i);
+-
+-        if (!dkr_name_is_valid(name))
+-                return -EINVAL;
+-
+-        if (tag && !dkr_tag_is_valid(tag))
+-                return -EINVAL;
+-
+-        if (local && !machine_name_is_valid(local))
+-                return -EINVAL;
+-
+-        if (i->images_job)
+-                return -EBUSY;
+-
+-        if (!tag)
+-                tag = "latest";
+-
+-        r = free_and_strdup(&i->local, local);
+-        if (r < 0)
+-                return r;
+-        i->force_local = force_local;
+-
+-        r = free_and_strdup(&i->name, name);
+-        if (r < 0)
+-                return r;
+-        r = free_and_strdup(&i->tag, tag);
+-        if (r < 0)
+-                return r;
+-
+-        url = strjoina(i->index_url, "/v1/repositories/", name, "/images");
+-
+-        r = import_job_new(&i->images_job, url, i->glue, i);
+-        if (r < 0)
+-                return r;
+-
+-        r = dkr_import_add_token(i, i->images_job);
+-        if (r < 0)
+-                return r;
+-
+-        i->images_job->on_finished = dkr_import_job_on_finished;
+-        i->images_job->on_header = dkr_import_job_on_header;
+-        i->images_job->on_progress = dkr_import_job_on_progress;
+-
+-        return import_job_begin(i->images_job);
+-}
+diff --git a/src/import/import-dkr.h b/src/import/import-dkr.h
+deleted file mode 100644
+index 633c767..0000000
+--- a/src/import/import-dkr.h
++++ /dev/null
+@@ -1,36 +0,0 @@
+-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+-
+-/***
+-  This file is part of systemd.
+-
+-  Copyright 2014 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/>.
+-***/
+-
+-#pragma once
+-
+-#include "sd-event.h"
+-#include "util.h"
+-
+-typedef struct DkrImport DkrImport;
+-
+-typedef void (*DkrImportFinished)(DkrImport *import, int error, void *userdata);
+-
+-int dkr_import_new(DkrImport **import, sd_event *event, const char *index_url, const char *image_root, DkrImportFinished on_finished, void *userdata);
+-DkrImport* dkr_import_unref(DkrImport *import);
+-
+-DEFINE_TRIVIAL_CLEANUP_FUNC(DkrImport*, dkr_import_unref);
+-
+-int dkr_import_pull(DkrImport *import, const char *name, const char *tag, const char *local, bool force_local);
+diff --git a/src/import/importd.c b/src/import/importd.c
+index 1222bf3..9aaf991 100644
+--- a/src/import/importd.c
++++ b/src/import/importd.c
+@@ -38,7 +38,6 @@ typedef struct Manager Manager;
+ typedef enum TransferType {
+         TRANSFER_TAR,
+         TRANSFER_RAW,
+-        TRANSFER_DKR,
+         _TRANSFER_TYPE_MAX,
+         _TRANSFER_TYPE_INVALID = -1,
+ } TransferType;
+@@ -56,8 +55,6 @@ struct Transfer {
+         char *local;
+         bool force_local;
+ 
+-        char *dkr_index_url;
+-
+         pid_t pid;
+ 
+         int log_fd;
+@@ -91,7 +88,6 @@ struct Manager {
+ static const char* const transfer_type_table[_TRANSFER_TYPE_MAX] = {
+         [TRANSFER_TAR] = "tar",
+         [TRANSFER_RAW] = "raw",
+-        [TRANSFER_DKR] = "dkr",
+ };
+ 
+ DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(transfer_type, TransferType);
+@@ -108,7 +104,6 @@ static Transfer *transfer_unref(Transfer *t) {
+ 
+         free(t->remote);
+         free(t->local);
+-        free(t->dkr_index_url);
+         free(t->object_path);
+ 
+         if (t->pid > 0) {
+@@ -355,7 +350,6 @@ static int transfer_start(Transfer *t) {
+                         "--verify",
+                         NULL, /* verify argument */
+                         NULL, /* maybe --force */
+-                        NULL, /* maybe --dkr-index-url */
+                         NULL, /* the actual URL */
+                         NULL, /* remote */
+                         NULL, /* local */
+@@ -410,11 +404,6 @@ static int transfer_start(Transfer *t) {
+                 if (t->force_local)
+                         cmd[k++] = "--force";
+ 
+-                if (t->dkr_index_url) {
+-                        cmd[k++] = "--dkr-index-url";
+-                        cmd[k++] = t->dkr_index_url;
+-                }
+-
+                 cmd[k++] = t->remote;
+                 if (t->local)
+                         cmd[k++] = t->local;
+@@ -624,7 +613,7 @@ static int manager_new(Manager **ret) {
+         return 0;
+ }
+ 
+-static Transfer *manager_find(Manager *m, TransferType type, const char *dkr_index_url, const char *remote) {
++static Transfer *manager_find(Manager *m, TransferType type, const char *remote) {
+         Transfer *t;
+         Iterator i;
+ 
+@@ -635,8 +624,7 @@ static Transfer *manager_find(Manager *m, TransferType type, const char *dkr_ind
+         HASHMAP_FOREACH(t, m->transfers, i) {
+ 
+                 if (t->type == type &&
+-                    streq_ptr(t->remote, remote) &&
+-                    streq_ptr(t->dkr_index_url, dkr_index_url))
++                    streq_ptr(t->remote, remote))
+                         return t;
+         }
+ 
+@@ -689,7 +677,7 @@ static int method_pull_tar_or_raw(sd_bus *bus, sd_bus_message *msg, void *userda
+ 
+         type = streq_ptr(sd_bus_message_get_member(msg), "PullTar") ? TRANSFER_TAR : TRANSFER_RAW;
+ 
+-        if (manager_find(m, type, NULL, remote))
++        if (manager_find(m, type, remote))
+                 return sd_bus_error_setf(error, BUS_ERROR_TRANSFER_IN_PROGRESS, "Transfer for %s already in progress.", remote);
+ 
+         r = transfer_new(m, &t);
+@@ -719,98 +707,6 @@ static int method_pull_tar_or_raw(sd_bus *bus, sd_bus_message *msg, void *userda
+         return sd_bus_reply_method_return(msg, "uo", id, object);
+ }
+ 
+-static int method_pull_dkr(sd_bus *bus, sd_bus_message *msg, void *userdata, sd_bus_error *error) {
+-        _cleanup_(transfer_unrefp) Transfer *t = NULL;
+-        const char *index_url, *remote, *tag, *local, *verify, *object;
+-        Manager *m = userdata;
+-        ImportVerify v;
+-        int force, r;
+-        uint32_t id;
+-
+-        assert(bus);
+-        assert(msg);
+-        assert(m);
+-
+-        r = bus_verify_polkit_async(
+-                        msg,
+-                        CAP_SYS_ADMIN,
+-                        "org.freedesktop.import1.pull",
+-                        false,
+-                        &m->polkit_registry,
+-                        error);
+-        if (r < 0)
+-                return r;
+-        if (r == 0)
+-                return 1; /* Will call us back */
+-
+-        r = sd_bus_message_read(msg, "sssssb", &index_url, &remote, &tag, &local, &verify, &force);
+-        if (r < 0)
+-                return r;
+-
+-        if (isempty(index_url))
+-                index_url = DEFAULT_DKR_INDEX_URL;
+-        if (!index_url)
+-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Index URL must be specified.");
+-        if (!http_url_is_valid(index_url))
+-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Index URL %s is invalid", index_url);
+-
+-        if (!dkr_name_is_valid(remote))
+-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Remote name %s is not valid", remote);
+-
+-        if (isempty(tag))
+-                tag = "latest";
+-        else if (!dkr_tag_is_valid(tag))
+-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Tag %s is not valid", tag);
+-
+-        if (isempty(local))
+-                local = NULL;
+-        else if (!machine_name_is_valid(local))
+-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Local name %s is invalid", local);
+-
+-        if (isempty(verify))
+-                v = IMPORT_VERIFY_SIGNATURE;
+-        else
+-                v = import_verify_from_string(verify);
+-        if (v < 0)
+-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown verification mode %s", verify);
+-
+-        if (v != IMPORT_VERIFY_NO)
+-                return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "DKR does not support verification.");
+-
+-        if (manager_find(m, TRANSFER_DKR, index_url, remote))
+-                return sd_bus_error_setf(error, BUS_ERROR_TRANSFER_IN_PROGRESS, "Transfer for %s already in progress.", remote);
+-
+-        r = transfer_new(m, &t);
+-        if (r < 0)
+-                return r;
+-
+-        t->type = TRANSFER_DKR;
+-        t->verify = v;
+-        t->force_local = force;
+-
+-        t->dkr_index_url = strdup(index_url);
+-        if (!t->dkr_index_url)
+-                return -ENOMEM;
+-
+-        t->remote = strjoin(remote, ":", tag, NULL);
+-        if (!t->remote)
+-                return -ENOMEM;
+-
+-        t->local = strdup(local);
+-        if (!t->local)
+-                return -ENOMEM;
+-
+-        r = transfer_start(t);
+-        if (r < 0)
+-                return r;
+-
+-        object = t->object_path;
+-        id = t->id;
+-        t = NULL;
+-
+-        return sd_bus_reply_method_return(msg, "uo", id, object);
+-}
+-
+ static int method_list_transfers(sd_bus *bus, sd_bus_message *msg, void *userdata, sd_bus_error *error) {
+         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+         Manager *m = userdata;
+@@ -956,7 +852,6 @@ static const sd_bus_vtable manager_vtable[] = {
+         SD_BUS_VTABLE_START(0),
+         SD_BUS_METHOD("PullTar", "sssb", "uo", method_pull_tar_or_raw, SD_BUS_VTABLE_UNPRIVILEGED),
+         SD_BUS_METHOD("PullRaw", "sssb", "uo", method_pull_tar_or_raw, SD_BUS_VTABLE_UNPRIVILEGED),
+-        SD_BUS_METHOD("PullDkr", "sssssb", "uo", method_pull_dkr, SD_BUS_VTABLE_UNPRIVILEGED),
+         SD_BUS_METHOD("ListTransfers", NULL, "a(usssdo)", method_list_transfers, SD_BUS_VTABLE_UNPRIVILEGED),
+         SD_BUS_METHOD("CancelTransfer", "u", NULL, method_cancel_transfer, SD_BUS_VTABLE_UNPRIVILEGED),
+         SD_BUS_SIGNAL("TransferNew", "uo", 0),
+diff --git a/src/import/org.freedesktop.import1.conf b/src/import/org.freedesktop.import1.conf
+index ae36af4..ed2539a 100644
+--- a/src/import/org.freedesktop.import1.conf
++++ b/src/import/org.freedesktop.import1.conf
+@@ -53,10 +53,6 @@
+                        send_member="PullRaw"/>
+ 
+                 <allow send_destination="org.freedesktop.import1"
+-                       send_interface="org.freedesktop.import1.Manager"
+-                       send_member="PullDkr"/>
+-
+-                <allow send_destination="org.freedesktop.import1"
+                        send_interface="org.freedesktop.import1.Transfer"
+                        send_member="Cancel"/>
+ 
+diff --git a/src/import/pull.c b/src/import/pull.c
+index ee3ff68..9cb1088 100644
+--- a/src/import/pull.c
++++ b/src/import/pull.c
+@@ -28,13 +28,11 @@
+ #include "machine-image.h"
+ #include "import-tar.h"
+ #include "import-raw.h"
+-#include "import-dkr.h"
+ #include "import-util.h"
+ 
+ static bool arg_force = false;
+ static const char *arg_image_root = "/var/lib/machines";
+ static ImportVerify arg_verify = IMPORT_VERIFY_SIGNATURE;
+-static const char* arg_dkr_index_url = DEFAULT_DKR_INDEX_URL;
+ 
+ static int interrupt_signal_handler(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
+         log_notice("Transfer aborted.");
+@@ -214,107 +212,6 @@ static int pull_raw(int argc, char *argv[], void *userdata) {
+         return -r;
+ }
+ 
+-static void on_dkr_finished(DkrImport *import, int error, void *userdata) {
+-        sd_event *event = userdata;
+-        assert(import);
+-
+-        if (error == 0)
+-                log_info("Operation completed successfully.");
+-
+-        sd_event_exit(event, abs(error));
+-}
+-
+-static int pull_dkr(int argc, char *argv[], void *userdata) {
+-        _cleanup_(dkr_import_unrefp) DkrImport *import = NULL;
+-        _cleanup_event_unref_ sd_event *event = NULL;
+-        const char *name, *tag, *local;
+-        int r;
+-
+-        if (!arg_dkr_index_url) {
+-                log_error("Please specify an index URL with --dkr-index-url=");
+-                return -EINVAL;
+-        }
+-
+-        if (arg_verify != IMPORT_VERIFY_NO) {
+-                log_error("Imports from dkr do not support image verification, please pass --verify=no.");
+-                return -EINVAL;
+-        }
+-
+-        tag = strchr(argv[1], ':');
+-        if (tag) {
+-                name = strndupa(argv[1], tag - argv[1]);
+-                tag++;
+-        } else {
+-                name = argv[1];
+-                tag = "latest";
+-        }
+-
+-        if (!dkr_name_is_valid(name)) {
+-                log_error("Remote name '%s' is not valid.", name);
+-                return -EINVAL;
+-        }
+-
+-        if (!dkr_tag_is_valid(tag)) {
+-                log_error("Tag name '%s' is not valid.", tag);
+-                return -EINVAL;
+-        }
+-
+-        if (argc >= 3)
+-                local = argv[2];
+-        else {
+-                local = strchr(name, '/');
+-                if (local)
+-                        local++;
+-                else
+-                        local = name;
+-        }
+-
+-        if (isempty(local) || streq(local, "-"))
+-                local = NULL;
+-
+-        if (local) {
+-                if (!machine_name_is_valid(local)) {
+-                        log_error("Local image name '%s' is not valid.", local);
+-                        return -EINVAL;
+-                }
+-
+-                if (!arg_force) {
+-                        r = image_find(local, NULL);
+-                        if (r < 0)
+-                                return log_error_errno(r, "Failed to check whether image '%s' exists: %m", local);
+-                        else if (r > 0) {
+-                                log_error_errno(EEXIST, "Image '%s' already exists.", local);
+-                                return -EEXIST;
+-                        }
+-                }
+-
+-                log_info("Pulling '%s' with tag '%s', saving as '%s'.", name, tag, local);
+-        } else
+-                log_info("Pulling '%s' with tag '%s'.", name, tag);
+-
+-        r = sd_event_default(&event);
+-        if (r < 0)
+-                return log_error_errno(r, "Failed to allocate event loop: %m");
+-
+-        assert_se(sigprocmask_many(SIG_BLOCK, SIGTERM, SIGINT, -1) == 0);
+-        sd_event_add_signal(event, NULL, SIGTERM, interrupt_signal_handler,  NULL);
+-        sd_event_add_signal(event, NULL, SIGINT, interrupt_signal_handler, NULL);
+-
+-        r = dkr_import_new(&import, event, arg_dkr_index_url, arg_image_root, on_dkr_finished, event);
+-        if (r < 0)
+-                return log_error_errno(r, "Failed to allocate importer: %m");
+-
+-        r = dkr_import_pull(import, name, tag, local, arg_force);
+-        if (r < 0)
+-                return log_error_errno(r, "Failed to pull image: %m");
+-
+-        r = sd_event_loop(event);
+-        if (r < 0)
+-                return log_error_errno(r, "Failed to run event loop: %m");
+-
+-        log_info("Exiting.");
+-        return -r;
+-}
+ 
+ static int help(int argc, char *argv[], void *userdata) {
+ 
+@@ -326,11 +223,9 @@ static int help(int argc, char *argv[], void *userdata) {
+                "     --verify=                Verify downloaded image, one of: 'no',\n"
+                "                              'checksum', 'signature'.\n"
+                "     --image-root=            Image root directory\n"
+-               "     --dkr-index-url=URL      Specify index URL to use for downloads\n\n"
+                "Commands:\n"
+                "  tar URL [NAME]              Download a TAR image\n"
+-               "  raw URL [NAME]              Download a RAW image\n"
+-               "  dkr REMOTE [NAME]           Download a DKR image\n",
++               "  raw URL [NAME]              Download a RAW image\n",
+                program_invocation_short_name);
+ 
+         return 0;
+@@ -341,7 +236,6 @@ static int parse_argv(int argc, char *argv[]) {
+         enum {
+                 ARG_VERSION = 0x100,
+                 ARG_FORCE,
+-                ARG_DKR_INDEX_URL,
+                 ARG_IMAGE_ROOT,
+                 ARG_VERIFY,
+         };
+@@ -350,7 +244,6 @@ static int parse_argv(int argc, char *argv[]) {
+                 { "help",            no_argument,       NULL, 'h'                 },
+                 { "version",         no_argument,       NULL, ARG_VERSION         },
+                 { "force",           no_argument,       NULL, ARG_FORCE           },
+-                { "dkr-index-url",   required_argument, NULL, ARG_DKR_INDEX_URL   },
+                 { "image-root",      required_argument, NULL, ARG_IMAGE_ROOT      },
+                 { "verify",          required_argument, NULL, ARG_VERIFY          },
+                 {}
+@@ -377,15 +270,6 @@ static int parse_argv(int argc, char *argv[]) {
+                         arg_force = true;
+                         break;
+ 
+-                case ARG_DKR_INDEX_URL:
+-                        if (!http_url_is_valid(optarg)) {
+-                                log_error("Index URL is not valid: %s", optarg);
+-                                return -EINVAL;
+-                        }
+-
+-                        arg_dkr_index_url = optarg;
+-                        break;
+-
+                 case ARG_IMAGE_ROOT:
+                         arg_image_root = optarg;
+                         break;
+@@ -415,7 +299,6 @@ static int import_main(int argc, char *argv[]) {
+                 { "help", VERB_ANY, VERB_ANY, 0, help     },
+                 { "tar",  2,        3,        0, pull_tar },
+                 { "raw",  2,        3,        0, pull_raw },
+-                { "dkr",  2,        3,        0, pull_dkr },
+                 {}
+         };
+ 
+diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c
+index ef1214a..cfd3162 100644
+--- a/src/machine/machinectl.c
++++ b/src/machine/machinectl.c
+@@ -77,7 +77,6 @@ static unsigned arg_lines = 10;
+ static OutputMode arg_output = OUTPUT_SHORT;
+ static bool arg_force = false;
+ static ImportVerify arg_verify = IMPORT_VERIFY_SIGNATURE;
+-static const char* arg_dkr_index_url = NULL;
+ 
+ static void pager_open_if_enabled(void) {
+ 
+@@ -1998,78 +1997,6 @@ static int pull_raw(int argc, char *argv[], void *userdata) {
+         return pull_image_common(bus, m);
+ }
+ 
+-static int pull_dkr(int argc, char *argv[], void *userdata) {
+-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+-        const char *local, *remote, *tag;
+-        sd_bus *bus = userdata;
+-        int r;
+-
+-        if (arg_verify != IMPORT_VERIFY_NO) {
+-                log_error("Imports from DKR do not support image verification, please pass --verify=no.");
+-                return -EINVAL;
+-        }
+-
+-        remote = argv[1];
+-        tag = strchr(remote, ':');
+-        if (tag) {
+-                remote = strndupa(remote, tag - remote);
+-                tag++;
+-        }
+-
+-        if (!dkr_name_is_valid(remote)) {
+-                log_error("DKR name '%s' is invalid.", remote);
+-                return -EINVAL;
+-        }
+-        if (tag && !dkr_tag_is_valid(tag)) {
+-                log_error("DKR tag '%s' is invalid.", remote);
+-                return -EINVAL;
+-        }
+-
+-        if (argc >= 3)
+-                local = argv[2];
+-        else {
+-                local = strchr(remote, '/');
+-                if (local)
+-                        local++;
+-                else
+-                        local = remote;
+-        }
+-
+-        if (isempty(local) || streq(local, "-"))
+-                local = NULL;
+-
+-        if (local) {
+-                if (!machine_name_is_valid(local)) {
+-                        log_error("Local name %s is not a suitable machine name.", local);
+-                        return -EINVAL;
+-                }
+-        }
+-
+-        r = sd_bus_message_new_method_call(
+-                        bus,
+-                        &m,
+-                        "org.freedesktop.import1",
+-                        "/org/freedesktop/import1",
+-                        "org.freedesktop.import1.Manager",
+-                        "PullDkr");
+-        if (r < 0)
+-                return bus_log_create_error(r);
+-
+-        r = sd_bus_message_append(
+-                        m,
+-                        "sssssb",
+-                        arg_dkr_index_url,
+-                        remote,
+-                        tag,
+-                        local,
+-                        import_verify_to_string(arg_verify),
+-                        arg_force);
+-        if (r < 0)
+-                return bus_log_create_error(r);
+-
+-        return pull_image_common(bus, m);
+-}
+-
+ typedef struct TransferInfo {
+         uint32_t id;
+         const char *type;
+@@ -2237,8 +2164,6 @@ static int help(int argc, char *argv[], void *userdata) {
+                "      --verify=MODE           Verification mode for downloaded images (no,\n"
+                "                              checksum, signature)\n"
+                "      --force                 Download image even if already exists\n"
+-               "      --dkr-index-url=URL     Specify the index URL to use for DKR image\n"
+-               "                              downloads\n\n"
+                "Machine Commands:\n"
+                "  list                        List running VMs and containers\n"
+                "  status NAME...              Show VM/container details\n"
+@@ -2265,7 +2190,6 @@ static int help(int argc, char *argv[], void *userdata) {
+                "Image Transfer Commands:\n"
+                "  pull-tar URL [NAME]         Download a TAR container image\n"
+                "  pull-raw URL [NAME]         Download a RAW container or VM image\n"
+-               "  pull-dkr REMOTE [NAME]      Download a DKR container image\n"
+                "  list-transfers              Show list of downloads in progress\n"
+                "  cancel-transfer             Cancel a download\n"
+                , program_invocation_short_name);
+@@ -2284,8 +2208,7 @@ static int parse_argv(int argc, char *argv[]) {
+                 ARG_MKDIR,
+                 ARG_NO_ASK_PASSWORD,
+                 ARG_VERIFY,
+-                ARG_FORCE,
+-                ARG_DKR_INDEX_URL,
++                ARG_FORCE
+         };
+ 
+         static const struct option options[] = {
+@@ -2308,7 +2231,6 @@ static int parse_argv(int argc, char *argv[]) {
+                 { "no-ask-password", no_argument,       NULL, ARG_NO_ASK_PASSWORD },
+                 { "verify",          required_argument, NULL, ARG_VERIFY          },
+                 { "force",           no_argument,       NULL, ARG_FORCE           },
+-                { "dkr-index-url",   required_argument, NULL, ARG_DKR_INDEX_URL   },
+                 {}
+         };
+ 
+@@ -2421,15 +2343,6 @@ static int parse_argv(int argc, char *argv[]) {
+                         arg_force = true;
+                         break;
+ 
+-                case ARG_DKR_INDEX_URL:
+-                        if (!http_url_is_valid(optarg)) {
+-                                log_error("Index URL is invalid: %s", optarg);
+-                                return -EINVAL;
+-                        }
+-
+-                        arg_dkr_index_url = optarg;
+-                        break;
+-
+                 case '?':
+                         return -EINVAL;
+ 
+@@ -2467,7 +2380,6 @@ static int machinectl_main(int argc, char *argv[], sd_bus *bus) {
+                 { "disable",         2,        VERB_ANY, 0,            enable_machine    },
+                 { "pull-tar",        2,        3,        0,            pull_tar          },
+                 { "pull-raw",        2,        3,        0,            pull_raw          },
+-                { "pull-dkr",        2,        3,        0,            pull_dkr          },
+                 { "list-transfers",  VERB_ANY, 1,        0,            list_transfers    },
+                 { "cancel-transfer", 2,        VERB_ANY, 0,            cancel_transfer   },
+                 {}
+diff --git a/src/shared/import-util.c b/src/shared/import-util.c
+index 660d92a..c0aba30 100644
+--- a/src/shared/import-util.c
++++ b/src/shared/import-util.c
+@@ -149,34 +149,3 @@ int raw_strip_suffixes(const char *p, char **ret) {
+ 
+         return 0;
+ }
+-
+-bool dkr_name_is_valid(const char *name) {
+-        const char *slash, *p;
+-
+-        if (isempty(name))
+-                return false;
+-
+-        slash = strchr(name, '/');
+-        if (!slash)
+-                return false;
+-
+-        if (!filename_is_valid(slash + 1))
+-                return false;
+-
+-        p = strndupa(name, slash - name);
+-        if (!filename_is_valid(p))
+-                return false;
+-
+-        return true;
+-}
+-
+-bool dkr_id_is_valid(const char *id) {
+-
+-        if (!filename_is_valid(id))
+-                return false;
+-
+-        if (!in_charset(id, "0123456789abcdef"))
+-                return false;
+-
+-        return true;
+-}
+diff --git a/src/shared/import-util.h b/src/shared/import-util.h
+index ff155b0..22773c5 100644
+--- a/src/shared/import-util.h
++++ b/src/shared/import-util.h
+@@ -41,7 +41,3 @@ ImportVerify import_verify_from_string(const char *s) _pure_;
+ 
+ int tar_strip_suffixes(const char *name, char **ret);
+ int raw_strip_suffixes(const char *name, char **ret);
+-
+-bool dkr_name_is_valid(const char *name);
+-bool dkr_id_is_valid(const char *id);
+-#define dkr_tag_is_valid(tag) filename_is_valid(tag)
diff --git a/SOURCES/0325-import-add-support-for-gpg2-for-verifying-imported-i.patch b/SOURCES/0325-import-add-support-for-gpg2-for-verifying-imported-i.patch
new file mode 100644
index 0000000..0b5c5bc
--- /dev/null
+++ b/SOURCES/0325-import-add-support-for-gpg2-for-verifying-imported-i.patch
@@ -0,0 +1,88 @@
+From 1b7d1234cd22bb0fd2677d54dc670a6d2c6f8089 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Mon, 2 Mar 2015 20:24:11 +0100
+Subject: [PATCH] import: add support for gpg2 for verifying imported images
+
+gpg2 insists on created a trust db even if we tun off all trust db
+support. Hence create a temporary home where the trust db is placed, and
+remove it after use.
+
+Cherry-picked from: 0acfdffe9417b4218e97b6d981c99a1a85e633c9
+Resolves: #1284974
+---
+ src/import/import-common.c | 21 ++++++++++++++++++---
+ 1 file changed, 18 insertions(+), 3 deletions(-)
+
+diff --git a/src/import/import-common.c b/src/import/import-common.c
+index 2acf380..f10a453 100644
+--- a/src/import/import-common.c
++++ b/src/import/import-common.c
+@@ -281,8 +281,9 @@ int import_verify(
+         _cleanup_free_ char *fn = NULL;
+         _cleanup_close_ int sig_file = -1;
+         const char *p, *line;
+-        char sig_file_path[] = "/tmp/sigXXXXXX";
++        char sig_file_path[] = "/tmp/sigXXXXXX", gpg_home[] = "/tmp/gpghomeXXXXXX";
+         _cleanup_sigkill_wait_ pid_t pid = 0;
++        bool gpg_home_created = false;
+         int r;
+ 
+         assert(main_job);
+@@ -347,6 +348,13 @@ int import_verify(
+                 goto finish;
+         }
+ 
++        if (!mkdtemp(gpg_home)) {
++                r = log_error_errno(errno, "Failed to create tempory home for gpg: %m");
++                goto finish;
++        }
++
++        gpg_home_created = true;
++
+         pid = fork();
+         if (pid < 0)
+                 return log_error_errno(errno, "Failed to fork off gpg: %m");
+@@ -359,13 +367,14 @@ int import_verify(
+                         "--no-auto-check-trustdb",
+                         "--batch",
+                         "--trust-model=always",
+-                        NULL, /* keyring to use */
++                        NULL, /* --homedir=  */
++                        NULL, /* --keyring= */
+                         NULL, /* --verify */
+                         NULL, /* signature file */
+                         NULL, /* dash */
+                         NULL  /* trailing NULL */
+                 };
+-                unsigned k = ELEMENTSOF(cmd) - 5;
++                unsigned k = ELEMENTSOF(cmd) - 6;
+                 int null_fd;
+ 
+                 /* Child */
+@@ -398,6 +407,8 @@ int import_verify(
+                 if (null_fd != STDOUT_FILENO)
+                         null_fd = safe_close(null_fd);
+ 
++                cmd[k++] = strjoina("--homedir=", gpg_home);
++
+                 /* We add the user keyring only to the command line
+                  * arguments, if it's around since gpg fails
+                  * otherwise. */
+@@ -415,6 +426,7 @@ int import_verify(
+                 fd_cloexec(STDOUT_FILENO, false);
+                 fd_cloexec(STDERR_FILENO, false);
+ 
++                execvp("gpg2", (char * const *) cmd);
+                 execvp("gpg", (char * const *) cmd);
+                 log_error_errno(errno, "Failed to execute gpg: %m");
+                 _exit(EXIT_FAILURE);
+@@ -446,6 +458,9 @@ finish:
+         if (sig_file >= 0)
+                 unlink(sig_file_path);
+ 
++        if (gpg_home_created)
++                rm_rf_dangerous(gpg_home, false, true, false);
++
+         return r;
+ }
+ 
diff --git a/SOURCES/0326-nspawn-when-connected-to-pipes-for-stdin-stdout-pass.patch b/SOURCES/0326-nspawn-when-connected-to-pipes-for-stdin-stdout-pass.patch
new file mode 100644
index 0000000..5145384
--- /dev/null
+++ b/SOURCES/0326-nspawn-when-connected-to-pipes-for-stdin-stdout-pass.patch
@@ -0,0 +1,293 @@
+From 98e5c02b1602eaaac5c63045fa7a06e40249445e Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Wed, 18 Feb 2015 23:32:55 +0100
+Subject: [PATCH] nspawn: when connected to pipes for stdin/stdout, pass them
+ as-is to PID 1
+
+Previously we always invoked the container PID 1 on /dev/console of the
+container. With this change we do so only if nspawn was invoked
+interactively (i.e. its stdin/stdout was connected to a TTY). In all other
+cases we directly pass through the fds unmodified.
+
+This has the benefit that nspawn can be added into shell pipelines.
+
+https://bugs.freedesktop.org/show_bug.cgi?id=87732
+
+Cherry-picked from: 9c857b9d160c10b4454fc9f83442c1878343422f
+Resolves: #1307080
+---
+ src/machine/machinectl.c |  2 +-
+ src/nspawn/nspawn.c      | 48 +++++++++++++++++--------------
+ src/run/run.c            |  2 +-
+ src/shared/ptyfwd.c      | 75 ++++++++++++++++++++++++++++--------------------
+ src/shared/ptyfwd.h      |  2 +-
+ 5 files changed, 74 insertions(+), 55 deletions(-)
+
+diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c
+index cfd3162..1a58aea 100644
+--- a/src/machine/machinectl.c
++++ b/src/machine/machinectl.c
+@@ -1427,7 +1427,7 @@ static int login_machine(int argc, char *argv[], void *userdata) {
+         sd_event_add_signal(event, NULL, SIGINT, NULL, NULL);
+         sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL);
+ 
+-        r = pty_forward_new(event, master, true, &forward);
++        r = pty_forward_new(event, master, true, false, &forward);
+         if (r < 0)
+                 return log_error_errno(r, "Failed to create PTY forwarder: %m");
+ 
+diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
+index 78bd584..a37b640 100644
+--- a/src/nspawn/nspawn.c
++++ b/src/nspawn/nspawn.c
+@@ -3581,6 +3581,7 @@ int main(int argc, char *argv[]) {
+         int ret = EXIT_SUCCESS;
+         union in_addr_union exposed = {};
+         _cleanup_release_lock_file_ LockFile tree_global_lock = LOCK_FILE_INIT, tree_local_lock = LOCK_FILE_INIT;
++        bool interactive;
+ 
+         log_parse_environment();
+         log_open();
+@@ -3754,6 +3755,8 @@ int main(int argc, char *argv[]) {
+                         goto finish;
+         }
+ 
++        interactive = isatty(STDIN_FILENO) > 0 && isatty(STDOUT_FILENO) > 0;
++
+         master = posix_openpt(O_RDWR|O_NOCTTY|O_CLOEXEC|O_NDELAY);
+         if (master < 0) {
+                 r = log_error_errno(errno, "Failed to acquire pseudo tty: %m");
+@@ -3766,15 +3769,15 @@ int main(int argc, char *argv[]) {
+                 goto finish;
+         }
+ 
+-        if (!arg_quiet)
+-                log_info("Spawning container %s on %s.\nPress ^] three times within 1s to kill container.",
+-                         arg_machine, arg_image ?: arg_directory);
+-
+         if (unlockpt(master) < 0) {
+                 r = log_error_errno(errno, "Failed to unlock tty: %m");
+                 goto finish;
+         }
+ 
++        if (!arg_quiet)
++                log_info("Spawning container %s on %s.\nPress ^] three times within 1s to kill container.",
++                         arg_machine, arg_image ?: arg_directory);
++
+         assert_se(sigemptyset(&mask) == 0);
+         sigset_add_many(&mask, SIGCHLD, SIGWINCH, SIGTERM, SIGINT, -1);
+         assert_se(sigprocmask(SIG_BLOCK, &mask, NULL) == 0);
+@@ -3860,9 +3863,6 @@ int main(int argc, char *argv[]) {
+ 
+                         master = safe_close(master);
+ 
+-                        close_nointr(STDIN_FILENO);
+-                        close_nointr(STDOUT_FILENO);
+-                        close_nointr(STDERR_FILENO);
+ 
+                         kmsg_socket_pair[0] = safe_close(kmsg_socket_pair[0]);
+                         rtnl_socket_pair[0] = safe_close(rtnl_socket_pair[0]);
+@@ -3870,21 +3870,27 @@ int main(int argc, char *argv[]) {
+                         reset_all_signal_handlers();
+                         reset_signal_mask();
+ 
+-                        r = open_terminal(console, O_RDWR);
+-                        if (r != STDIN_FILENO) {
+-                                if (r >= 0) {
+-                                        safe_close(r);
+-                                        r = -EINVAL;
+-                                }
++                        if (interactive) {
++                                close_nointr(STDIN_FILENO);
++                                close_nointr(STDOUT_FILENO);
++                                close_nointr(STDERR_FILENO);
+ 
+-                                log_error_errno(r, "Failed to open console: %m");
+-                                _exit(EXIT_FAILURE);
+-                        }
++                                r = open_terminal(console, O_RDWR);
++                                if (r != STDIN_FILENO) {
++                                        if (r >= 0) {
++                                                safe_close(r);
++                                                r = -EINVAL;
++                                        }
+ 
+-                        if (dup2(STDIN_FILENO, STDOUT_FILENO) != STDOUT_FILENO ||
+-                            dup2(STDIN_FILENO, STDERR_FILENO) != STDERR_FILENO) {
+-                                log_error_errno(errno, "Failed to duplicate console: %m");
+-                                _exit(EXIT_FAILURE);
++                                        log_error_errno(r, "Failed to open console: %m");
++                                        _exit(EXIT_FAILURE);
++                                }
++
++                                if (dup2(STDIN_FILENO, STDOUT_FILENO) != STDOUT_FILENO ||
++                                    dup2(STDIN_FILENO, STDERR_FILENO) != STDERR_FILENO) {
++                                        log_error_errno(errno, "Failed to duplicate console: %m");
++                                        _exit(EXIT_FAILURE);
++                                }
+                         }
+ 
+                         if (setsid() < 0) {
+@@ -4227,7 +4233,7 @@ int main(int argc, char *argv[]) {
+ 
+                                 rtnl_socket_pair[0] = safe_close(rtnl_socket_pair[0]);
+ 
+-                                r = pty_forward_new(event, master, true, &forward);
++                                r = pty_forward_new(event, master, true, !interactive, &forward);
+                                 if (r < 0) {
+                                         log_error_errno(r, "Failed to create PTY forwarder: %m");
+                                         goto finish;
+diff --git a/src/run/run.c b/src/run/run.c
+index dd1338f..4680342 100644
+--- a/src/run/run.c
++++ b/src/run/run.c
+@@ -780,7 +780,7 @@ static int start_transient_service(
+                 if (!arg_quiet)
+                         log_info("Running as unit %s.\nPress ^] three times within 1s to disconnect TTY.", service);
+ 
+-                r = pty_forward_new(event, master, false, &forward);
++                r = pty_forward_new(event, master, false, false, &forward);
+                 if (r < 0)
+                         return log_error_errno(r, "Failed to create PTY forwarder: %m");
+ 
+diff --git a/src/shared/ptyfwd.c b/src/shared/ptyfwd.c
+index 88b3f4e..4402af1 100644
+--- a/src/shared/ptyfwd.c
++++ b/src/shared/ptyfwd.c
+@@ -42,6 +42,8 @@ struct PTYForward {
+         struct termios saved_stdin_attr;
+         struct termios saved_stdout_attr;
+ 
++        bool read_only:1;
++
+         bool saved_stdin:1;
+         bool saved_stdout:1;
+ 
+@@ -298,7 +300,13 @@ static int on_sigwinch_event(sd_event_source *e, const struct signalfd_siginfo *
+         return 0;
+ }
+ 
+-int pty_forward_new(sd_event *event, int master, bool ignore_vhangup, PTYForward **ret) {
++int pty_forward_new(
++                sd_event *event,
++                int master,
++                bool ignore_vhangup,
++                bool read_only,
++                PTYForward **ret) {
++
+         _cleanup_(pty_forward_freep) PTYForward *f = NULL;
+         struct winsize ws;
+         int r;
+@@ -307,6 +315,7 @@ int pty_forward_new(sd_event *event, int master, bool ignore_vhangup, PTYForward
+         if (!f)
+                 return -ENOMEM;
+ 
++        f->read_only = read_only;
+         f->ignore_vhangup = ignore_vhangup;
+ 
+         if (event)
+@@ -317,13 +326,15 @@ int pty_forward_new(sd_event *event, int master, bool ignore_vhangup, PTYForward
+                         return r;
+         }
+ 
+-        r = fd_nonblock(STDIN_FILENO, true);
+-        if (r < 0)
+-                return r;
++        if (!read_only) {
++                r = fd_nonblock(STDIN_FILENO, true);
++                if (r < 0)
++                        return r;
+ 
+-        r = fd_nonblock(STDOUT_FILENO, true);
+-        if (r < 0)
+-                return r;
++                r = fd_nonblock(STDOUT_FILENO, true);
++                if (r < 0)
++                        return r;
++        }
+ 
+         r = fd_nonblock(master, true);
+         if (r < 0)
+@@ -334,36 +345,34 @@ int pty_forward_new(sd_event *event, int master, bool ignore_vhangup, PTYForward
+         if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) >= 0)
+                 (void)ioctl(master, TIOCSWINSZ, &ws);
+ 
+-        if (tcgetattr(STDIN_FILENO, &f->saved_stdin_attr) >= 0) {
+-                struct termios raw_stdin_attr;
+-
+-                f->saved_stdin = true;
++        if (!read_only) {
++                if (tcgetattr(STDIN_FILENO, &f->saved_stdin_attr) >= 0) {
++                        struct termios raw_stdin_attr;
+ 
+-                raw_stdin_attr = f->saved_stdin_attr;
+-                cfmakeraw(&raw_stdin_attr);
+-                raw_stdin_attr.c_oflag = f->saved_stdin_attr.c_oflag;
+-                tcsetattr(STDIN_FILENO, TCSANOW, &raw_stdin_attr);
+-        }
++                        f->saved_stdin = true;
+ 
+-        if (tcgetattr(STDOUT_FILENO, &f->saved_stdout_attr) >= 0) {
+-                struct termios raw_stdout_attr;
++                        raw_stdin_attr = f->saved_stdin_attr;
++                        cfmakeraw(&raw_stdin_attr);
++                        raw_stdin_attr.c_oflag = f->saved_stdin_attr.c_oflag;
++                        tcsetattr(STDIN_FILENO, TCSANOW, &raw_stdin_attr);
++                }
+ 
+-                f->saved_stdout = true;
++                if (tcgetattr(STDOUT_FILENO, &f->saved_stdout_attr) >= 0) {
++                        struct termios raw_stdout_attr;
+ 
+-                raw_stdout_attr = f->saved_stdout_attr;
+-                cfmakeraw(&raw_stdout_attr);
+-                raw_stdout_attr.c_iflag = f->saved_stdout_attr.c_iflag;
+-                raw_stdout_attr.c_lflag = f->saved_stdout_attr.c_lflag;
+-                tcsetattr(STDOUT_FILENO, TCSANOW, &raw_stdout_attr);
+-        }
++                        f->saved_stdout = true;
+ 
+-        r = sd_event_add_io(f->event, &f->master_event_source, master, EPOLLIN|EPOLLOUT|EPOLLET, on_master_event, f);
+-        if (r < 0)
+-                return r;
++                        raw_stdout_attr = f->saved_stdout_attr;
++                        cfmakeraw(&raw_stdout_attr);
++                        raw_stdout_attr.c_iflag = f->saved_stdout_attr.c_iflag;
++                        raw_stdout_attr.c_lflag = f->saved_stdout_attr.c_lflag;
++                        tcsetattr(STDOUT_FILENO, TCSANOW, &raw_stdout_attr);
++                }
+ 
+-        r = sd_event_add_io(f->event, &f->stdin_event_source, STDIN_FILENO, EPOLLIN|EPOLLET, on_stdin_event, f);
+-        if (r < 0 && r != -EPERM)
+-                return r;
++                r = sd_event_add_io(f->event, &f->stdin_event_source, STDIN_FILENO, EPOLLIN|EPOLLET, on_stdin_event, f);
++                if (r < 0 && r != -EPERM)
++                        return r;
++        }
+ 
+         r = sd_event_add_io(f->event, &f->stdout_event_source, STDOUT_FILENO, EPOLLOUT|EPOLLET, on_stdout_event, f);
+         if (r == -EPERM)
+@@ -372,6 +381,10 @@ int pty_forward_new(sd_event *event, int master, bool ignore_vhangup, PTYForward
+         else if (r < 0)
+                 return r;
+ 
++        r = sd_event_add_io(f->event, &f->master_event_source, master, EPOLLIN|EPOLLOUT|EPOLLET, on_master_event, f);
++        if (r < 0)
++                return r;
++
+         r = sd_event_add_signal(f->event, &f->sigwinch_event_source, SIGWINCH, on_sigwinch_event, f);
+         if (r < 0)
+                 return r;
+diff --git a/src/shared/ptyfwd.h b/src/shared/ptyfwd.h
+index d3e229b..6208a54 100644
+--- a/src/shared/ptyfwd.h
++++ b/src/shared/ptyfwd.h
+@@ -30,7 +30,7 @@
+ 
+ typedef struct PTYForward PTYForward;
+ 
+-int pty_forward_new(sd_event *event, int master, bool ignore_vhangup, PTYForward **f);
++int pty_forward_new(sd_event *event, int master, bool ignore_vhangup, bool read_only, PTYForward **f);
+ PTYForward *pty_forward_free(PTYForward *f);
+ 
+ int pty_forward_get_last_char(PTYForward *f, char *ch);
diff --git a/SOURCES/0327-mount-remove-obsolete-n.patch b/SOURCES/0327-mount-remove-obsolete-n.patch
new file mode 100644
index 0000000..c919efc
--- /dev/null
+++ b/SOURCES/0327-mount-remove-obsolete-n.patch
@@ -0,0 +1,55 @@
+From 9592604df60795ad8b58aa11311a26f267385bae Mon Sep 17 00:00:00 2001
+From: Karel Zak <kzak@redhat.com>
+Date: Tue, 28 Jul 2015 11:31:45 +0200
+Subject: [PATCH] mount: remove obsolete -n
+
+It seems that systemd still uses legacy -n option. The option has been
+originally designed to avoid write to /etc/mtab during boot when root
+FS is not ready or read-only.
+
+This is not necessary for long time, because /etc/mtab is not a real
+file (it's symlink) and write to the file is impossible. All utils
+should be able to detect the symlink and ignore mtab. This concept is
+supported for very long time before systemd.
+
+The userspase mount options are currently maintained by libmount
+(mount(8) and mount.nfs) in /run/mount) which is tmpfs initialized
+during early boot.
+
+(cherry picked from commit 6f20f850f79df365c2533195214127142013d317)
+Resolves: #1339721
+---
+ src/core/mount.c | 6 ------
+ 1 file changed, 6 deletions(-)
+
+diff --git a/src/core/mount.c b/src/core/mount.c
+index 23f63ce..fe967bc 100644
+--- a/src/core/mount.c
++++ b/src/core/mount.c
+@@ -881,8 +881,6 @@ static void mount_enter_unmounting(Mount *m) {
+         m->control_command = m->exec_command + MOUNT_EXEC_UNMOUNT;
+ 
+         r = exec_command_set(m->control_command, "/bin/umount", m->where, NULL);
+-        if (r >= 0 && UNIT(m)->manager->running_as == SYSTEMD_SYSTEM)
+-                r = exec_command_append(m->control_command, "-n", NULL);
+         if (r < 0)
+                 goto fail;
+ 
+@@ -935,8 +933,6 @@ static void mount_enter_mounting(Mount *m) {
+ 
+                 r = exec_command_set(m->control_command, "/bin/mount",
+                                      m->parameters_fragment.what, m->where, NULL);
+-                if (r >= 0 && UNIT(m)->manager->running_as == SYSTEMD_SYSTEM)
+-                        r = exec_command_append(m->control_command, "-n", NULL);
+                 if (r >= 0 && m->sloppy_options)
+                         r = exec_command_append(m->control_command, "-s", NULL);
+                 if (r >= 0 && m->parameters_fragment.fstype)
+@@ -985,8 +981,6 @@ static void mount_enter_remounting(Mount *m) {
+                 r = exec_command_set(m->control_command, "/bin/mount",
+                                      m->parameters_fragment.what, m->where,
+                                      "-o", o, NULL);
+-                if (r >= 0 && UNIT(m)->manager->running_as == SYSTEMD_SYSTEM)
+-                        r = exec_command_append(m->control_command, "-n", NULL);
+                 if (r >= 0 && m->sloppy_options)
+                         r = exec_command_append(m->control_command, "-s", NULL);
+                 if (r >= 0 && m->parameters_fragment.fstype)
diff --git a/SOURCES/0328-core-don-t-log-job-status-message-in-case-job-was-ef.patch b/SOURCES/0328-core-don-t-log-job-status-message-in-case-job-was-ef.patch
new file mode 100644
index 0000000..7047551
--- /dev/null
+++ b/SOURCES/0328-core-don-t-log-job-status-message-in-case-job-was-ef.patch
@@ -0,0 +1,244 @@
+From a7ec486dede56ab2ec28132133becf11e5685884 Mon Sep 17 00:00:00 2001
+From: Michal Sekletar <msekletar@users.noreply.github.com>
+Date: Mon, 16 May 2016 17:24:51 +0200
+Subject: [PATCH] core: don't log job status message in case job was
+ effectively NOP (#3199)
+
+We currently generate log message about unit being started even when
+unit was started already and job didn't do anything. This is because job
+was requested explicitly and hence became anchor job of the transaction
+thus we could not eliminate it. That is fine but, let's not pollute
+journal with useless log messages.
+
+$ systemctl start systemd-resolved
+$ systemctl start systemd-resolved
+$ systemctl start systemd-resolved
+
+Current state:
+$ journalctl -u systemd-resolved | grep Started
+
+May 05 15:31:42 rawhide systemd[1]: Started Network Name Resolution.
+May 05 15:31:59 rawhide systemd[1]: Started Network Name Resolution.
+May 05 15:32:01 rawhide systemd[1]: Started Network Name Resolution.
+
+After patch applied:
+$ journalctl -u systemd-resolved | grep Started
+
+May 05 16:42:12 rawhide systemd[1]: Started Network Name Resolution.
+
+Fixes #1723
+
+Cherry-picked from: 833f92ad39beca0e954e91e5764ffc83f8d0c1cf
+Resolves: #1280014
+---
+ src/core/dbus-job.c    |  2 +-
+ src/core/job.c         | 33 ++++++++++++++++++---------------
+ src/core/job.h         |  2 +-
+ src/core/manager.c     |  2 +-
+ src/core/transaction.c |  2 +-
+ src/core/unit.c        | 12 ++++++------
+ 6 files changed, 28 insertions(+), 25 deletions(-)
+
+diff --git a/src/core/dbus-job.c b/src/core/dbus-job.c
+index 8b5ea25..7ce5d57 100644
+--- a/src/core/dbus-job.c
++++ b/src/core/dbus-job.c
+@@ -84,7 +84,7 @@ int bus_job_method_cancel(sd_bus *bus, sd_bus_message *message, void *userdata,
+         if (r < 0)
+                 return r;
+ 
+-        job_finish_and_invalidate(j, JOB_CANCELED, true);
++        job_finish_and_invalidate(j, JOB_CANCELED, true, false);
+ 
+         return sd_bus_reply_method_return(message, NULL);
+ }
+diff --git a/src/core/job.c b/src/core/job.c
+index 7416386..c2876de 100644
+--- a/src/core/job.c
++++ b/src/core/job.c
+@@ -190,7 +190,7 @@ Job* job_install(Job *j) {
+ 
+         if (uj) {
+                 if (job_type_is_conflicting(uj->type, j->type))
+-                        job_finish_and_invalidate(uj, JOB_CANCELED, false);
++                        job_finish_and_invalidate(uj, JOB_CANCELED, false, false);
+                 else {
+                         /* not conflicting, i.e. mergeable */
+ 
+@@ -571,19 +571,19 @@ int job_run_and_invalidate(Job *j) {
+         j = manager_get_job(m, id);
+         if (j) {
+                 if (r == -EALREADY)
+-                        r = job_finish_and_invalidate(j, JOB_DONE, true);
++                        r = job_finish_and_invalidate(j, JOB_DONE, true, true);
+                 else if (r == -EBADR)
+-                        r = job_finish_and_invalidate(j, JOB_SKIPPED, true);
++                        r = job_finish_and_invalidate(j, JOB_SKIPPED, true, false);
+                 else if (r == -ENOEXEC)
+-                        r = job_finish_and_invalidate(j, JOB_INVALID, true);
++                        r = job_finish_and_invalidate(j, JOB_INVALID, true, false);
+                 else if (r == -EPROTO)
+-                        r = job_finish_and_invalidate(j, JOB_ASSERT, true);
++                        r = job_finish_and_invalidate(j, JOB_ASSERT, true, false);
+                 else if (r == -ENOTSUP)
+-                        r = job_finish_and_invalidate(j, JOB_UNSUPPORTED, true);
++                        r = job_finish_and_invalidate(j, JOB_UNSUPPORTED, true, false);
+                 else if (r == -EAGAIN)
+                         job_set_state(j, JOB_WAITING);
+                 else if (r < 0)
+-                        r = job_finish_and_invalidate(j, JOB_FAILED, true);
++                        r = job_finish_and_invalidate(j, JOB_FAILED, true, false);
+         }
+ 
+         return r;
+@@ -792,7 +792,7 @@ static void job_log_status_message(Unit *u, JobType t, JobResult result) {
+                                 NULL);
+ }
+ 
+-int job_finish_and_invalidate(Job *j, JobResult result, bool recursive) {
++int job_finish_and_invalidate(Job *j, JobResult result, bool recursive, bool already) {
+         Unit *u;
+         Unit *other;
+         JobType t;
+@@ -810,8 +810,11 @@ int job_finish_and_invalidate(Job *j, JobResult result, bool recursive) {
+         log_unit_debug(u->id, "Job %s/%s finished, result=%s",
+                        u->id, job_type_to_string(t), job_result_to_string(result));
+ 
+-        job_print_status_message(u, t, result);
+-        job_log_status_message(u, t, result);
++        /* If this job did nothing to respective unit we don't log the status message */
++        if (!already) {
++                job_print_status_message(u, t, result);
++                job_log_status_message(u, t, result);
++        }
+ 
+         job_add_to_dbus_queue(j);
+ 
+@@ -842,20 +845,20 @@ int job_finish_and_invalidate(Job *j, JobResult result, bool recursive) {
+                                 if (other->job &&
+                                     (other->job->type == JOB_START ||
+                                      other->job->type == JOB_VERIFY_ACTIVE))
+-                                        job_finish_and_invalidate(other->job, JOB_DEPENDENCY, true);
++                                        job_finish_and_invalidate(other->job, JOB_DEPENDENCY, true, false);
+ 
+                         SET_FOREACH(other, u->dependencies[UNIT_BOUND_BY], i)
+                                 if (other->job &&
+                                     (other->job->type == JOB_START ||
+                                      other->job->type == JOB_VERIFY_ACTIVE))
+-                                        job_finish_and_invalidate(other->job, JOB_DEPENDENCY, true);
++                                        job_finish_and_invalidate(other->job, JOB_DEPENDENCY, true, false);
+ 
+                         SET_FOREACH(other, u->dependencies[UNIT_REQUIRED_BY_OVERRIDABLE], i)
+                                 if (other->job &&
+                                     !other->job->override &&
+                                     (other->job->type == JOB_START ||
+                                      other->job->type == JOB_VERIFY_ACTIVE))
+-                                        job_finish_and_invalidate(other->job, JOB_DEPENDENCY, true);
++                                        job_finish_and_invalidate(other->job, JOB_DEPENDENCY, true, false);
+ 
+                 } else if (t == JOB_STOP) {
+ 
+@@ -863,7 +866,7 @@ int job_finish_and_invalidate(Job *j, JobResult result, bool recursive) {
+                                 if (other->job &&
+                                     (other->job->type == JOB_START ||
+                                      other->job->type == JOB_VERIFY_ACTIVE))
+-                                        job_finish_and_invalidate(other->job, JOB_DEPENDENCY, true);
++                                        job_finish_and_invalidate(other->job, JOB_DEPENDENCY, true, false);
+                 }
+         }
+ 
+@@ -911,7 +914,7 @@ static int job_dispatch_timer(sd_event_source *s, uint64_t monotonic, void *user
+         log_unit_warning(j->unit->id, "Job %s/%s timed out.", j->unit->id, job_type_to_string(j->type));
+ 
+         u = j->unit;
+-        job_finish_and_invalidate(j, JOB_TIMEOUT, true);
++        job_finish_and_invalidate(j, JOB_TIMEOUT, true, false);
+ 
+         failure_action(u->manager, u->job_timeout_action, u->job_timeout_reboot_arg);
+ 
+diff --git a/src/core/job.h b/src/core/job.h
+index d967b68..e4191ee 100644
+--- a/src/core/job.h
++++ b/src/core/job.h
+@@ -220,7 +220,7 @@ void job_add_to_dbus_queue(Job *j);
+ int job_start_timer(Job *j);
+ 
+ int job_run_and_invalidate(Job *j);
+-int job_finish_and_invalidate(Job *j, JobResult result, bool recursive);
++int job_finish_and_invalidate(Job *j, JobResult result, bool recursive, bool already);
+ 
+ char *job_dbus_path(Job *j);
+ 
+diff --git a/src/core/manager.c b/src/core/manager.c
+index a1504bf..ee456fb 100644
+--- a/src/core/manager.c
++++ b/src/core/manager.c
+@@ -1426,7 +1426,7 @@ void manager_clear_jobs(Manager *m) {
+ 
+         while ((j = hashmap_first(m->jobs)))
+                 /* No need to recurse. We're cancelling all jobs. */
+-                job_finish_and_invalidate(j, JOB_CANCELED, false);
++                job_finish_and_invalidate(j, JOB_CANCELED, false, false);
+ }
+ 
+ static int manager_dispatch_run_queue(sd_event_source *source, void *userdata) {
+diff --git a/src/core/transaction.c b/src/core/transaction.c
+index b0b3d6b..aed64fa 100644
+--- a/src/core/transaction.c
++++ b/src/core/transaction.c
+@@ -592,7 +592,7 @@ static int transaction_apply(Transaction *tr, Manager *m, JobMode mode) {
+                         /* Not invalidating recursively. Avoids triggering
+                          * OnFailure= actions of dependent jobs. Also avoids
+                          * invalidating our iterator. */
+-                        job_finish_and_invalidate(j, JOB_CANCELED, false);
++                        job_finish_and_invalidate(j, JOB_CANCELED, false, false);
+                 }
+         }
+ 
+diff --git a/src/core/unit.c b/src/core/unit.c
+index db5aa98..d6ead7d 100644
+--- a/src/core/unit.c
++++ b/src/core/unit.c
+@@ -1851,12 +1851,12 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_su
+                 case JOB_VERIFY_ACTIVE:
+ 
+                         if (UNIT_IS_ACTIVE_OR_RELOADING(ns))
+-                                job_finish_and_invalidate(u->job, JOB_DONE, true);
++                                job_finish_and_invalidate(u->job, JOB_DONE, true, false);
+                         else if (u->job->state == JOB_RUNNING && ns != UNIT_ACTIVATING) {
+                                 unexpected = true;
+ 
+                                 if (UNIT_IS_INACTIVE_OR_FAILED(ns))
+-                                        job_finish_and_invalidate(u->job, ns == UNIT_FAILED ? JOB_FAILED : JOB_DONE, true);
++                                        job_finish_and_invalidate(u->job, ns == UNIT_FAILED ? JOB_FAILED : JOB_DONE, true, false);
+                         }
+ 
+                         break;
+@@ -1866,12 +1866,12 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_su
+ 
+                         if (u->job->state == JOB_RUNNING) {
+                                 if (ns == UNIT_ACTIVE)
+-                                        job_finish_and_invalidate(u->job, reload_success ? JOB_DONE : JOB_FAILED, true);
++                                        job_finish_and_invalidate(u->job, reload_success ? JOB_DONE : JOB_FAILED, true, false);
+                                 else if (ns != UNIT_ACTIVATING && ns != UNIT_RELOADING) {
+                                         unexpected = true;
+ 
+                                         if (UNIT_IS_INACTIVE_OR_FAILED(ns))
+-                                                job_finish_and_invalidate(u->job, ns == UNIT_FAILED ? JOB_FAILED : JOB_DONE, true);
++                                                job_finish_and_invalidate(u->job, ns == UNIT_FAILED ? JOB_FAILED : JOB_DONE, true, false);
+                                 }
+                         }
+ 
+@@ -1882,10 +1882,10 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_su
+                 case JOB_TRY_RESTART:
+ 
+                         if (UNIT_IS_INACTIVE_OR_FAILED(ns))
+-                                job_finish_and_invalidate(u->job, JOB_DONE, true);
++                                job_finish_and_invalidate(u->job, JOB_DONE, true, false);
+                         else if (u->job->state == JOB_RUNNING && ns != UNIT_DEACTIVATING) {
+                                 unexpected = true;
+-                                job_finish_and_invalidate(u->job, JOB_FAILED, true);
++                                job_finish_and_invalidate(u->job, JOB_FAILED, true, false);
+                         }
+ 
+                         break;
diff --git a/SOURCES/0329-core-use-an-AF_UNIX-SOCK_DGRAM-socket-for-cgroup-age.patch b/SOURCES/0329-core-use-an-AF_UNIX-SOCK_DGRAM-socket-for-cgroup-age.patch
new file mode 100644
index 0000000..fd0463f
--- /dev/null
+++ b/SOURCES/0329-core-use-an-AF_UNIX-SOCK_DGRAM-socket-for-cgroup-age.patch
@@ -0,0 +1,489 @@
+From 92b12c7dc013c95bd0d35bae99ff6df023ce0e1f Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Wed, 4 May 2016 20:43:23 +0200
+Subject: [PATCH] core: use an AF_UNIX/SOCK_DGRAM socket for cgroup agent
+ notification
+
+dbus-daemon currently uses a backlog of 30 on its D-bus system bus socket. On
+overloaded systems this means that only 30 connections may be queued without
+dbus-daemon processing them before further connection attempts fail. Our
+cgroups-agent binary so far used D-Bus for its messaging, and hitting this
+limit hence may result in us losing cgroup empty messages.
+
+This patch adds a seperate cgroup agent socket of type AF_UNIX/SOCK_DGRAM.
+Since sockets of these types need no connection set up, no listen() backlog
+applies. Our cgroup-agent binary will hence simply block as long as it can't
+enqueue its datagram message, so that we won't lose cgroup empty messages as
+likely anymore.
+
+This also rearranges the ordering of the processing of SIGCHLD signals, service
+notification messages (sd_notify()...) and the two types of cgroup
+notifications (inotify for the unified hierarchy support, and agent for the
+classic hierarchy support). We now always process events for these in the
+following order:
+
+  1. service notification messages  (SD_EVENT_PRIORITY_NORMAL-7)
+  2. SIGCHLD signals (SD_EVENT_PRIORITY_NORMAL-6)
+  3. cgroup inotify and cgroup agent (SD_EVENT_PRIORITY_NORMAL-5)
+
+This is because when receiving SIGCHLD we invalidate PID information, which we
+need to process the service notification messages which are bound to PIDs.
+Hence the order between the first two items. And we want to process SIGCHLD
+metadata to detect whether a service is gone, before using cgroup
+notifications, to decide when a service is gone, since the former carries more
+useful metadata.
+
+Related to this:
+https://bugs.freedesktop.org/show_bug.cgi?id=95264
+https://github.com/systemd/systemd/issues/1961
+
+Cherry-picked from: d8fdc62037b5b0a9fd603ad5efd6b49f956f86b5
+Resolves: #1305608
+---
+ src/cgroups-agent/cgroups-agent.c |  48 ++++++------
+ src/core/cgroup.c                 |   2 +
+ src/core/dbus.c                   |  56 +++++++-------
+ src/core/dbus.h                   |   2 +
+ src/core/manager.c                | 149 ++++++++++++++++++++++++++++++++++++--
+ src/core/manager.h                |   3 +
+ 6 files changed, 198 insertions(+), 62 deletions(-)
+
+diff --git a/src/cgroups-agent/cgroups-agent.c b/src/cgroups-agent/cgroups-agent.c
+index 529e843..2fe6583 100644
+--- a/src/cgroups-agent/cgroups-agent.c
++++ b/src/cgroups-agent/cgroups-agent.c
+@@ -1,5 +1,3 @@
+-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+-
+ /***
+   This file is part of systemd.
+ 
+@@ -20,14 +18,21 @@
+ ***/
+ 
+ #include <stdlib.h>
++#include <sys/socket.h>
+ 
+-#include "sd-bus.h"
+ #include "log.h"
+-#include "bus-util.h"
++#include "socket-util.h"
+ 
+ int main(int argc, char *argv[]) {
+-        _cleanup_bus_close_unref_ sd_bus *bus = NULL;
+-        int r;
++
++        static const union sockaddr_union sa = {
++                .un.sun_family = AF_UNIX,
++                .un.sun_path = "/run/systemd/cgroups-agent",
++        };
++
++        _cleanup_close_ int fd = -1;
++        ssize_t n;
++        size_t l;
+ 
+         if (argc != 2) {
+                 log_error("Incorrect number of arguments.");
+@@ -38,27 +43,22 @@ int main(int argc, char *argv[]) {
+         log_parse_environment();
+         log_open();
+ 
+-        /* We send this event to the private D-Bus socket and then the
+-         * system instance will forward this to the system bus. We do
+-         * this to avoid an activation loop when we start dbus when we
+-         * are called when the dbus service is shut down. */
+-
+-        r = bus_open_system_systemd(&bus);
+-        if (r < 0) {
+-                /* If we couldn't connect we assume this was triggered
+-                 * while systemd got restarted/transitioned from
+-                 * initrd to the system, so let's ignore this */
+-                log_debug_errno(r, "Failed to get D-Bus connection: %m");
++        fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
++        if (fd < 0) {
++                log_debug_errno(errno, "Failed to allocate socket: %m");
++                return EXIT_FAILURE;
++        }
++
++        l = strlen(argv[1]);
++
++        n = sendto(fd, argv[1], l, 0, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path));
++        if (n < 0) {
++                log_debug_errno(errno, "Failed to send cgroups agent message: %m");
+                 return EXIT_FAILURE;
+         }
+ 
+-        r = sd_bus_emit_signal(bus,
+-                               "/org/freedesktop/systemd1/agent",
+-                               "org.freedesktop.systemd1.Agent",
+-                               "Released",
+-                               "s", argv[1]);
+-        if (r < 0) {
+-                log_debug_errno(r, "Failed to send signal message on private connection: %m");
++        if ((size_t) n != l) {
++                log_debug("Datagram size mismatch");
+                 return EXIT_FAILURE;
+         }
+ 
+diff --git a/src/core/cgroup.c b/src/core/cgroup.c
+index 10fdcc9..b7f08fb 100644
+--- a/src/core/cgroup.c
++++ b/src/core/cgroup.c
+@@ -1028,6 +1028,8 @@ int manager_notify_cgroup_empty(Manager *m, const char *cgroup) {
+         assert(m);
+         assert(cgroup);
+ 
++        log_debug("Got cgroup empty notification for: %s", cgroup);
++
+         u = manager_get_unit_by_cgroup(m, cgroup);
+         if (u) {
+                 r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, true);
+diff --git a/src/core/dbus.c b/src/core/dbus.c
+index 85b5174..29524d4 100644
+--- a/src/core/dbus.c
++++ b/src/core/dbus.c
+@@ -72,12 +72,37 @@ int bus_send_queued_message(Manager *m) {
+         return 0;
+ }
+ 
++int bus_forward_agent_released(Manager *m, const char *path) {
++        int r;
++
++        assert(m);
++        assert(path);
++
++        if (!m->running_as == SYSTEMD_SYSTEM)
++                return 0;
++
++        if (!m->system_bus)
++                return 0;
++
++        /* If we are running a system instance we forward the agent message on the system bus, so that the user
++         * instances get notified about this, too */
++
++        r = sd_bus_emit_signal(m->system_bus,
++                               "/org/freedesktop/systemd1/agent",
++                               "org.freedesktop.systemd1.Agent",
++                               "Released",
++                               "s", path);
++        if (r < 0)
++                return log_warning_errno(r, "Failed to propagate agent release message: %m");
++
++        return 1;
++}
++
+ static int signal_agent_released(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+         Manager *m = userdata;
+         const char *cgroup;
+         int r;
+ 
+-        assert(bus);
+         assert(message);
+         assert(m);
+ 
+@@ -88,16 +113,6 @@ static int signal_agent_released(sd_bus *bus, sd_bus_message *message, void *use
+         }
+ 
+         manager_notify_cgroup_empty(m, cgroup);
+-
+-        if (m->running_as == SYSTEMD_SYSTEM && m->system_bus) {
+-                /* If we are running as system manager, forward the
+-                 * message to the system bus */
+-
+-                r = sd_bus_send(m->system_bus, message, NULL);
+-                if (r < 0)
+-                        log_warning_errno(r, "Failed to forward Released message: %m");
+-        }
+-
+         return 0;
+ }
+ 
+@@ -679,25 +694,6 @@ static int bus_on_connection(sd_event_source *s, int fd, uint32_t revents, void
+                 return 0;
+         }
+ 
+-        if (m->running_as == SYSTEMD_SYSTEM) {
+-                /* When we run as system instance we get the Released
+-                 * signal via a direct connection */
+-
+-                r = sd_bus_add_match(
+-                                bus,
+-                                NULL,
+-                                "type='signal',"
+-                                "interface='org.freedesktop.systemd1.Agent',"
+-                                "member='Released',"
+-                                "path='/org/freedesktop/systemd1/agent'",
+-                                signal_agent_released, m);
+-
+-                if (r < 0) {
+-                        log_warning_errno(r, "Failed to register Released match on new connection bus: %m");
+-                        return 0;
+-                }
+-        }
+-
+         r = bus_setup_disconnected_match(m, bus);
+         if (r < 0)
+                 return 0;
+diff --git a/src/core/dbus.h b/src/core/dbus.h
+index d04f532..c27d136 100644
+--- a/src/core/dbus.h
++++ b/src/core/dbus.h
+@@ -40,3 +40,5 @@ int bus_verify_manage_unit_async(Manager *m, sd_bus_message *call, sd_bus_error
+ int bus_verify_manage_unit_async_for_kill(Manager *m, sd_bus_message *call, sd_bus_error *error);
+ int bus_verify_manage_unit_files_async(Manager *m, sd_bus_message *call, sd_bus_error *error);
+ int bus_verify_reload_daemon_async(Manager *m, sd_bus_message *call, sd_bus_error *error);
++
++int bus_forward_agent_released(Manager *m, const char *path);
+diff --git a/src/core/manager.c b/src/core/manager.c
+index ee456fb..370c8cb 100644
+--- a/src/core/manager.c
++++ b/src/core/manager.c
+@@ -83,8 +83,10 @@
+ #define JOBS_IN_PROGRESS_WAIT_USEC (5*USEC_PER_SEC)
+ #define JOBS_IN_PROGRESS_PERIOD_USEC (USEC_PER_SEC / 3)
+ #define JOBS_IN_PROGRESS_PERIOD_DIVISOR 3
++#define CGROUPS_AGENT_RCVBUF_SIZE (8*1024*1024)
+ 
+ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata);
++static int manager_dispatch_cgroups_agent_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata);
+ static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata);
+ static int manager_dispatch_time_change_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata);
+ static int manager_dispatch_idle_pipe_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata);
+@@ -456,11 +458,11 @@ static int manager_setup_signals(Manager *m) {
+         if (r < 0)
+                 return r;
+ 
+-        /* Process signals a bit earlier than the rest of things, but
+-         * later than notify_fd processing, so that the notify
+-         * processing can still figure out to which process/service a
+-         * message belongs, before we reap the process. */
+-        r = sd_event_source_set_priority(m->signal_event_source, -5);
++        /* Process signals a bit earlier than the rest of things, but later than notify_fd processing, so that the
++         * notify processing can still figure out to which process/service a message belongs, before we reap the
++         * process. Also, process this before handling cgroup notifications, so that we always collect child exit
++         * status information before detecting that there's no process in a cgroup. */
++        r = sd_event_source_set_priority(m->signal_event_source, -6);
+         if (r < 0)
+                 return r;
+ 
+@@ -541,7 +543,7 @@ int manager_new(SystemdRunningAs running_as, bool test_run, Manager **_m) {
+ 
+         m->idle_pipe[0] = m->idle_pipe[1] = m->idle_pipe[2] = m->idle_pipe[3] = -1;
+ 
+-        m->pin_cgroupfs_fd = m->notify_fd = m->signal_fd = m->time_change_fd = m->dev_autofs_fd = m->private_listen_fd = m->kdbus_fd = m->utab_inotify_fd = -1;
++        m->pin_cgroupfs_fd = m->notify_fd = m->cgroups_agent_fd = m->signal_fd = m->time_change_fd = m->dev_autofs_fd = m->private_listen_fd = m->kdbus_fd = m->utab_inotify_fd = -1;
+         m->current_job_id = 1; /* start as id #1, so that we can leave #0 around as "null-like" value */
+ 
+         m->ask_password_inotify_fd = -1;
+@@ -689,8 +691,8 @@ static int manager_setup_notify(Manager *m) {
+                 if (r < 0)
+                         return log_error_errno(r, "Failed to allocate notify event source: %m");
+ 
+-                /* Process signals a bit earlier than SIGCHLD, so that we can
+-                 * still identify to which service an exit message belongs */
++                /* Process notification messages a bit earlier than SIGCHLD, so that we can still identify to which
++                 * service an exit message belongs. */
+                 r = sd_event_source_set_priority(m->notify_event_source, -7);
+                 if (r < 0)
+                         return log_error_errno(r, "Failed to set priority of notify event source: %m");
+@@ -699,6 +701,77 @@ static int manager_setup_notify(Manager *m) {
+         return 0;
+ }
+ 
++static int manager_setup_cgroups_agent(Manager *m) {
++
++        static const union sockaddr_union sa = {
++                .un.sun_family = AF_UNIX,
++                .un.sun_path = "/run/systemd/cgroups-agent",
++        };
++        int r;
++
++        /* This creates a listening socket we receive cgroups agent messages on. We do not use D-Bus for delivering
++         * these messages from the cgroups agent binary to PID 1, as the cgroups agent binary is very short-living, and
++         * each instance of it needs a new D-Bus connection. Since D-Bus connections are SOCK_STREAM/AF_UNIX, on
++         * overloaded systems the backlog of the D-Bus socket becomes relevant, as not more than the configured number
++         * of D-Bus connections may be queued until the kernel will start dropping further incoming connections,
++         * possibly resulting in lost cgroups agent messages. To avoid this, we'll use a private SOCK_DGRAM/AF_UNIX
++         * socket, where no backlog is relevant as communication may take place without an actual connect() cycle, and
++         * we thus won't lose messages.
++         *
++         * Note that PID 1 will forward the agent message to system bus, so that the user systemd instance may listen
++         * to it. The system instance hence listens on this special socket, but the user instances listen on the system
++         * bus for these messages. */
++
++        if (m->test_run)
++                return 0;
++
++        if (!m->running_as == SYSTEMD_SYSTEM)
++                return 0;
++
++        if (m->cgroups_agent_fd < 0) {
++                _cleanup_close_ int fd = -1;
++
++                /* First free all secondary fields */
++                m->cgroups_agent_event_source = sd_event_source_unref(m->cgroups_agent_event_source);
++
++                fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
++                if (fd < 0)
++                        return log_error_errno(errno, "Failed to allocate cgroups agent socket: %m");
++
++                fd_inc_rcvbuf(fd, CGROUPS_AGENT_RCVBUF_SIZE);
++
++                (void) unlink(sa.un.sun_path);
++
++                /* Only allow root to connect to this socket */
++                RUN_WITH_UMASK(0077)
++                        r = bind(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path));
++                if (r < 0)
++                        return log_error_errno(errno, "bind(%s) failed: %m", sa.un.sun_path);
++
++                m->cgroups_agent_fd = fd;
++                fd = -1;
++        }
++
++        if (!m->cgroups_agent_event_source) {
++                r = sd_event_add_io(m->event, &m->cgroups_agent_event_source, m->cgroups_agent_fd, EPOLLIN, manager_dispatch_cgroups_agent_fd, m);
++                if (r < 0)
++                        return log_error_errno(r, "Failed to allocate cgroups agent event source: %m");
++
++                /* Process cgroups notifications early, but after having processed service notification messages or
++                 * SIGCHLD signals, so that a cgroup running empty is always just the last safety net of notification,
++                 * and we collected the metadata the notification and SIGCHLD stuff offers first. Also see handling of
++                 * cgroup inotify for the unified cgroup stuff. */
++                r = sd_event_source_set_priority(m->cgroups_agent_event_source, SD_EVENT_PRIORITY_NORMAL-5);
++                if (r < 0)
++                        return log_error_errno(r, "Failed to set priority of cgroups agent event source: %m");
++
++                (void) sd_event_source_set_description(m->cgroups_agent_event_source, "manager-cgroups-agent");
++        }
++
++        return 0;
++}
++
++
+ static int manager_setup_kdbus(Manager *m) {
+ #ifdef ENABLE_KDBUS
+         _cleanup_free_ char *p = NULL;
+@@ -912,6 +985,7 @@ Manager* manager_free(Manager *m) {
+ 
+         sd_event_source_unref(m->signal_event_source);
+         sd_event_source_unref(m->notify_event_source);
++        sd_event_source_unref(m->cgroups_agent_event_source);
+         sd_event_source_unref(m->time_change_event_source);
+         sd_event_source_unref(m->jobs_in_progress_event_source);
+         sd_event_source_unref(m->idle_pipe_event_source);
+@@ -919,6 +993,7 @@ Manager* manager_free(Manager *m) {
+ 
+         safe_close(m->signal_fd);
+         safe_close(m->notify_fd);
++        safe_close(m->cgroups_agent_fd);
+         safe_close(m->time_change_fd);
+         safe_close(m->kdbus_fd);
+ 
+@@ -1167,6 +1242,10 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) {
+         if (q < 0 && r == 0)
+                 r = q;
+ 
++        q = manager_setup_cgroups_agent(m);
++        if (q < 0 && r == 0)
++                r = q;
++
+         /* We might have deserialized the kdbus control fd, but if we
+          * didn't, then let's create the bus now. */
+         manager_setup_kdbus(m);
+@@ -1492,6 +1571,35 @@ static unsigned manager_dispatch_dbus_queue(Manager *m) {
+         return n;
+ }
+ 
++static int manager_dispatch_cgroups_agent_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
++        Manager *m = userdata;
++        char buf[PATH_MAX+1];
++        ssize_t n;
++
++        n = recv(fd, buf, sizeof(buf), 0);
++        if (n < 0)
++                return log_error_errno(errno, "Failed to read cgroups agent message: %m");
++        if (n == 0) {
++                log_error("Got zero-length cgroups agent message, ignoring.");
++                return 0;
++        }
++        if ((size_t) n >= sizeof(buf)) {
++                log_error("Got overly long cgroups agent message, ignoring.");
++                return 0;
++        }
++
++        if (memchr(buf, 0, n)) {
++                log_error("Got cgroups agent message with embedded NUL byte, ignoring.");
++                return 0;
++        }
++        buf[n] = 0;
++
++        manager_notify_cgroup_empty(m, buf);
++        bus_forward_agent_released(m, buf);
++
++        return 0;
++}
++
+ static void manager_invoke_notify_message(Manager *m, Unit *u, pid_t pid, char *buf, size_t n, FDSet *fds) {
+         _cleanup_strv_free_ char **tags = NULL;
+ 
+@@ -2304,6 +2412,16 @@ int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool switching_root) {
+                 fprintf(f, "notify-socket=%s\n", m->notify_socket);
+         }
+ 
++        if (m->cgroups_agent_fd >= 0) {
++                int copy;
++
++                copy = fdset_put_dup(fds, m->cgroups_agent_fd);
++                if (copy < 0)
++                        return copy;
++
++                fprintf(f, "cgroups-agent-fd=%i\n", copy);
++        }
++
+         if (m->kdbus_fd >= 0) {
+                 int copy;
+ 
+@@ -2473,6 +2591,17 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
+                         free(m->notify_socket);
+                         m->notify_socket = n;
+ 
++                } else if (startswith(l, "cgroups-agent-fd=")) {
++                        int fd;
++
++                        if (safe_atoi(l + 17, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))
++                                log_debug("Failed to parse cgroups agent fd: %s", l + 10);
++                        else {
++                                m->cgroups_agent_event_source = sd_event_source_unref(m->cgroups_agent_event_source);
++                                safe_close(m->cgroups_agent_fd);
++                                m->cgroups_agent_fd = fdset_remove(fds, fd);
++                        }
++
+                 } else if (startswith(l, "kdbus-fd=")) {
+                         int fd;
+ 
+@@ -2599,6 +2728,10 @@ int manager_reload(Manager *m) {
+         if (q < 0 && r >= 0)
+                 r = q;
+ 
++        q = manager_setup_cgroups_agent(m);
++        if (q < 0 && r >= 0)
++                r = q;
++
+         /* Third, fire things up! */
+         q = manager_coldplug(m);
+         if (q < 0 && r >= 0)
+diff --git a/src/core/manager.h b/src/core/manager.h
+index d3971f1..3e855db 100644
+--- a/src/core/manager.h
++++ b/src/core/manager.h
+@@ -137,6 +137,9 @@ struct Manager {
+         int notify_fd;
+         sd_event_source *notify_event_source;
+ 
++        int cgroups_agent_fd;
++        sd_event_source *cgroups_agent_event_source;
++
+         int signal_fd;
+         sd_event_source *signal_event_source;
+ 
diff --git a/SOURCES/0330-logind-process-session-inhibitor-fds-at-higher-prior.patch b/SOURCES/0330-logind-process-session-inhibitor-fds-at-higher-prior.patch
new file mode 100644
index 0000000..74225fe
--- /dev/null
+++ b/SOURCES/0330-logind-process-session-inhibitor-fds-at-higher-prior.patch
@@ -0,0 +1,59 @@
+From caca204d23babbdb0c688f543f3ee8d66a1a2001 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Wed, 4 May 2016 19:01:56 +0200
+Subject: [PATCH] logind: process session/inhibitor fds at higher priority
+
+Let's make sure we process session and inhibitor pipe fds (that signal
+sessions/inhibtors going away) at a higher priority
+than new bus calls that might create new sessions or inhibitors. This helps
+ensuring that the number of open sessions stays minimal.
+
+Cherry-picked from: e11544a8305ab9dea097c74bb16e296150c9cc10
+Resolves: #1305608
+---
+ src/login/logind-inhibit.c | 2 +-
+ src/login/logind-session.c | 4 +++-
+ src/login/logind.c         | 2 +-
+ 3 files changed, 5 insertions(+), 3 deletions(-)
+
+diff --git a/src/login/logind-inhibit.c b/src/login/logind-inhibit.c
+index 84fee0e..bf96898 100644
+--- a/src/login/logind-inhibit.c
++++ b/src/login/logind-inhibit.c
+@@ -303,7 +303,7 @@ int inhibitor_create_fifo(Inhibitor *i) {
+                 if (r < 0)
+                         return r;
+ 
+-                r = sd_event_source_set_priority(i->event_source, SD_EVENT_PRIORITY_IDLE);
++                r = sd_event_source_set_priority(i->event_source, SD_EVENT_PRIORITY_IDLE-10);
+                 if (r < 0)
+                         return r;
+         }
+diff --git a/src/login/logind-session.c b/src/login/logind-session.c
+index dc24539..59f5a7a 100644
+--- a/src/login/logind-session.c
++++ b/src/login/logind-session.c
+@@ -905,7 +905,9 @@ int session_create_fifo(Session *s) {
+                 if (r < 0)
+                         return r;
+ 
+-                r = sd_event_source_set_priority(s->fifo_event_source, SD_EVENT_PRIORITY_IDLE);
++                /* Let's make sure we noticed dead sessions before we process new bus requests (which might create new
++                 * sessions). */
++                r = sd_event_source_set_priority(s->fifo_event_source, SD_EVENT_PRIORITY_NORMAL-10);
+                 if (r < 0)
+                         return r;
+         }
+diff --git a/src/login/logind.c b/src/login/logind.c
+index 3afbf34..e8d0669 100644
+--- a/src/login/logind.c
++++ b/src/login/logind.c
+@@ -685,7 +685,7 @@ static int manager_connect_bus(Manager *m) {
+         if (r < 0)
+                 return log_error_errno(r, "Failed to register name: %m");
+ 
+-        r = sd_bus_attach_event(m->bus, m->event, 0);
++        r = sd_bus_attach_event(m->bus, m->event, SD_EVENT_PRIORITY_NORMAL);
+         if (r < 0)
+                 return log_error_errno(r, "Failed to attach bus to event loop: %m");
+ 
diff --git a/SOURCES/0331-Teach-bus_append_unit_property_assignment-about-Dele.patch b/SOURCES/0331-Teach-bus_append_unit_property_assignment-about-Dele.patch
new file mode 100644
index 0000000..39ce2f4
--- /dev/null
+++ b/SOURCES/0331-Teach-bus_append_unit_property_assignment-about-Dele.patch
@@ -0,0 +1,27 @@
+From f44296a5324dc84ff1b2a82bd1dd2d47160762b5 Mon Sep 17 00:00:00 2001
+From: Jan Synacek <jsynacek@redhat.com>
+Date: Mon, 23 May 2016 14:51:12 +0200
+Subject: [PATCH] Teach bus_append_unit_property_assignment() about 'Delegate'
+ property
+
+"Cherry-picked" from ea1a971646d31b990190f473c5c7e3562f36d3c9.
+
+Resolves: #1337922
+---
+ src/libsystemd/sd-bus/bus-util.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/src/libsystemd/sd-bus/bus-util.c b/src/libsystemd/sd-bus/bus-util.c
+index 3a91836..9d70798 100644
+--- a/src/libsystemd/sd-bus/bus-util.c
++++ b/src/libsystemd/sd-bus/bus-util.c
+@@ -1388,7 +1388,8 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
+ 
+         if (STR_IN_SET(field,
+                        "CPUAccounting", "MemoryAccounting", "BlockIOAccounting",
+-                       "SendSIGHUP", "SendSIGKILL", "WakeSystem", "DefaultDependencies")) {
++                       "SendSIGHUP", "SendSIGKILL", "WakeSystem", "DefaultDependencies",
++                       "Delegate")) {
+ 
+                 r = parse_boolean(eq);
+                 if (r < 0) {
diff --git a/SOURCES/0332-sd-netlink-fix-deep-recursion-in-message-destruction.patch b/SOURCES/0332-sd-netlink-fix-deep-recursion-in-message-destruction.patch
new file mode 100644
index 0000000..633bb16
--- /dev/null
+++ b/SOURCES/0332-sd-netlink-fix-deep-recursion-in-message-destruction.patch
@@ -0,0 +1,47 @@
+From 164a98ea6b24fea3433516dcc0df496929674cdd Mon Sep 17 00:00:00 2001
+From: Jan Synacek <jsynacek@redhat.com>
+Date: Tue, 7 Jun 2016 12:43:38 +0200
+Subject: [PATCH] sd-netlink: fix deep recursion in message destruction
+
+On larger systems we might very well see messages with thousands of parts.
+When we free them, we must avoid recursing into each part, otherwise we
+very likely get stack overflows.
+
+Fix sd_netlink_message_unref() to use an iterative approach rather than
+recursion (also avoid tail-recursion in case it is not optimized by the
+compiler).
+
+(cherry picked from commit 82e4eda664d40ef60829e27d84b1610c2f4070cd)
+Resolves: #1330593
+---
+ src/libsystemd/sd-rtnl/rtnl-message.c | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+diff --git a/src/libsystemd/sd-rtnl/rtnl-message.c b/src/libsystemd/sd-rtnl/rtnl-message.c
+index 276591f..9276bbd 100644
+--- a/src/libsystemd/sd-rtnl/rtnl-message.c
++++ b/src/libsystemd/sd-rtnl/rtnl-message.c
+@@ -584,7 +584,9 @@ sd_rtnl_message *sd_rtnl_message_ref(sd_rtnl_message *m) {
+ }
+ 
+ sd_rtnl_message *sd_rtnl_message_unref(sd_rtnl_message *m) {
+-        if (m && REFCNT_DEC(m->n_ref) == 0) {
++        sd_rtnl_message *t;
++
++        while (m && REFCNT_DEC(m->n_ref) == 0) {
+                 unsigned i;
+ 
+                 free(m->hdr);
+@@ -592,9 +594,9 @@ sd_rtnl_message *sd_rtnl_message_unref(sd_rtnl_message *m) {
+                 for (i = 0; i <= m->n_containers; i++)
+                         free(m->rta_offset_tb[i]);
+ 
+-                sd_rtnl_message_unref(m->next);
+-
+-                free(m);
++                t = m;
++                m = m->next;
++                free(t);
+         }
+ 
+         return NULL;
diff --git a/SOURCES/0333-add-REMOTE_ADDR-and-REMOTE_PORT-for-Accept-yes.patch b/SOURCES/0333-add-REMOTE_ADDR-and-REMOTE_PORT-for-Accept-yes.patch
new file mode 100644
index 0000000..11a75b3
--- /dev/null
+++ b/SOURCES/0333-add-REMOTE_ADDR-and-REMOTE_PORT-for-Accept-yes.patch
@@ -0,0 +1,281 @@
+From afa96dafde9d50f2b53ccf8136ead9ed79544877 Mon Sep 17 00:00:00 2001
+From: Shawn Landden <shawn@churchofgit.com>
+Date: Tue, 10 Mar 2015 04:41:59 -0700
+Subject: [PATCH] add REMOTE_ADDR and REMOTE_PORT for Accept=yes
+
+Cherry-picked from: 3b1c524154c876aecebc98787975cc2943100210
+Resolves: #1341154
+---
+ TODO                                     |  2 -
+ man/systemd.socket.xml                   |  7 ++-
+ src/core/service.c                       | 42 +++++++++++++++++-
+ src/libsystemd/sd-resolve/test-resolve.c |  2 +-
+ src/shared/socket-util.c                 | 76 +++++++++++++++++++++++---------
+ src/shared/socket-util.h                 |  4 +-
+ src/timesync/timesyncd-server.h          |  2 +-
+ 7 files changed, 107 insertions(+), 28 deletions(-)
+
+diff --git a/TODO b/TODO
+index d96d2bf..498d82c 100644
+--- a/TODO
++++ b/TODO
+@@ -185,8 +185,6 @@ Features:
+ * as soon as we have kdbus, and sender timestamps, revisit coalescing multiple parallel daemon reloads:
+   http://lists.freedesktop.org/archives/systemd-devel/2014-December/025862.html
+ 
+-* set $REMOTE_IP (or $REMOTE_ADDR/$REMOTE_PORT) environment variable when doing per-connection socket activation. use format introduced by xinetd or CGI for this
+-
+ * the install state probably shouldn't get confused by generated units, think dbus1/kdbus compat!
+ 
+ * in systemctl list-unit-files: show the install value the presets would suggest for a service in a third column
+diff --git a/man/systemd.socket.xml b/man/systemd.socket.xml
+index 2f54193..350a956 100644
+--- a/man/systemd.socket.xml
++++ b/man/systemd.socket.xml
+@@ -357,7 +357,12 @@
+         daemons designed for usage with
+         <citerefentry><refentrytitle>inetd</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+         to work unmodified with systemd socket
+-        activation.</para></listitem>
++        activation.</para>
++
++        <para>For IPv4 and IPv6 connections the <varname>REMOTE_ADDR</varname>
++        environment variable will contain the remote IP, and <varname>REMOTE_PORT</varname>
++        will contain the remote port. This is the same as the format used by CGI.
++        For SOCK_RAW the port is the IP protocol.</para></listitem>
+       </varlistentry>
+ 
+       <varlistentry>
+diff --git a/src/core/service.c b/src/core/service.c
+index ae5e610..c76713b 100644
+--- a/src/core/service.c
++++ b/src/core/service.c
+@@ -1094,7 +1094,7 @@ static int service_spawn(
+         if (r < 0)
+                 goto fail;
+ 
+-        our_env = new0(char*, 4);
++        our_env = new0(char*, 6);
+         if (!our_env) {
+                 r = -ENOMEM;
+                 goto fail;
+@@ -1118,6 +1118,46 @@ static int service_spawn(
+                         goto fail;
+                 }
+ 
++        if (UNIT_DEREF(s->accept_socket)) {
++                union sockaddr_union sa;
++                socklen_t salen = sizeof(sa);
++
++                r = getpeername(s->socket_fd, &sa.sa, &salen);
++                if (r < 0) {
++                        r = -errno;
++                        goto fail;
++                }
++
++                if (IN_SET(sa.sa.sa_family, AF_INET, AF_INET6)) {
++                        _cleanup_free_ char *addr = NULL;
++                        char *t;
++                        int port;
++
++                        r = sockaddr_pretty(&sa.sa, salen, true, false, &addr);
++                        if (r < 0)
++                                goto fail;
++
++                        t = strappend("REMOTE_ADDR=", addr);
++                        if (!t) {
++                                r = -ENOMEM;
++                                goto fail;
++                        }
++                        our_env[n_env++] = t;
++
++                        port = sockaddr_port(&sa.sa);
++                        if (port < 0) {
++                                r = port;
++                                goto fail;
++                        }
++
++                        if (asprintf(&t, "REMOTE_PORT=%u", port) < 0) {
++                                r = -ENOMEM;
++                                goto fail;
++                        }
++                        our_env[n_env++] = t;
++                }
++        }
++
+         final_env = strv_env_merge(2, UNIT(s)->manager->environment, our_env, NULL);
+         if (!final_env) {
+                 r = -ENOMEM;
+diff --git a/src/libsystemd/sd-resolve/test-resolve.c b/src/libsystemd/sd-resolve/test-resolve.c
+index d08e1b5..a14b6de 100644
+--- a/src/libsystemd/sd-resolve/test-resolve.c
++++ b/src/libsystemd/sd-resolve/test-resolve.c
+@@ -49,7 +49,7 @@ static int getaddrinfo_handler(sd_resolve_query *q, int ret, const struct addrin
+         for (i = ai; i; i = i->ai_next) {
+                 _cleanup_free_ char *addr = NULL;
+ 
+-                assert_se(sockaddr_pretty(i->ai_addr, i->ai_addrlen, false, &addr) == 0);
++                assert_se(sockaddr_pretty(i->ai_addr, i->ai_addrlen, false, true, &addr) == 0);
+                 puts(addr);
+         }
+ 
+diff --git a/src/shared/socket-util.c b/src/shared/socket-util.c
+index 407d0af..a212510 100644
+--- a/src/shared/socket-util.c
++++ b/src/shared/socket-util.c
+@@ -302,7 +302,7 @@ int socket_address_print(const SocketAddress *a, char **ret) {
+                 return 0;
+         }
+ 
+-        return sockaddr_pretty(&a->sockaddr.sa, a->size, false, ret);
++        return sockaddr_pretty(&a->sockaddr.sa, a->size, false, true, ret);
+ }
+ 
+ bool socket_address_can_accept(const SocketAddress *a) {
+@@ -471,7 +471,20 @@ bool socket_address_matches_fd(const SocketAddress *a, int fd) {
+         return socket_address_equal(a, &b);
+ }
+ 
+-int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_ipv6, char **ret) {
++int sockaddr_port(const struct sockaddr *_sa) {
++        union sockaddr_union *sa = (union sockaddr_union*) _sa;
++
++        assert(sa);
++
++        if (!IN_SET(sa->sa.sa_family, AF_INET, AF_INET6))
++                return -EAFNOSUPPORT;
++
++        return ntohs(sa->sa.sa_family == AF_INET6 ?
++                       sa->in6.sin6_port :
++                       sa->in.sin_port);
++}
++
++int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_ipv6, bool include_port, char **ret) {
+         union sockaddr_union *sa = (union sockaddr_union*) _sa;
+         char *p;
+ 
+@@ -485,11 +498,18 @@ int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_
+ 
+                 a = ntohl(sa->in.sin_addr.s_addr);
+ 
+-                if (asprintf(&p,
+-                             "%u.%u.%u.%u:%u",
+-                             a >> 24, (a >> 16) & 0xFF, (a >> 8) & 0xFF, a & 0xFF,
+-                             ntohs(sa->in.sin_port)) < 0)
+-                        return -ENOMEM;
++                if (include_port) {
++                        if (asprintf(&p,
++                                     "%u.%u.%u.%u:%u",
++                                     a >> 24, (a >> 16) & 0xFF, (a >> 8) & 0xFF, a & 0xFF,
++                                     ntohs(sa->in.sin_port)) < 0)
++                                return -ENOMEM;
++                } else {
++                        if (asprintf(&p,
++                                     "%u.%u.%u.%u",
++                                     a >> 24, (a >> 16) & 0xFF, (a >> 8) & 0xFF, a & 0xFF) < 0)
++                                return -ENOMEM;
++                }
+ 
+                 break;
+         }
+@@ -501,20 +521,34 @@ int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_
+ 
+                 if (translate_ipv6 && memcmp(&sa->in6.sin6_addr, ipv4_prefix, sizeof(ipv4_prefix)) == 0) {
+                         const uint8_t *a = sa->in6.sin6_addr.s6_addr+12;
+-
+-                        if (asprintf(&p,
+-                                     "%u.%u.%u.%u:%u",
+-                                     a[0], a[1], a[2], a[3],
+-                                     ntohs(sa->in6.sin6_port)) < 0)
+-                                return -ENOMEM;
++                        if (include_port) {
++                                if (asprintf(&p,
++                                             "%u.%u.%u.%u:%u",
++                                             a[0], a[1], a[2], a[3],
++                                             ntohs(sa->in6.sin6_port)) < 0)
++                                        return -ENOMEM;
++                        } else {
++                                if (asprintf(&p,
++                                             "%u.%u.%u.%u",
++                                             a[0], a[1], a[2], a[3]) < 0)
++                                        return -ENOMEM;
++                        }
+                 } else {
+                         char a[INET6_ADDRSTRLEN];
+ 
+-                        if (asprintf(&p,
+-                                     "[%s]:%u",
+-                                     inet_ntop(AF_INET6, &sa->in6.sin6_addr, a, sizeof(a)),
+-                                     ntohs(sa->in6.sin6_port)) < 0)
+-                                return -ENOMEM;
++                        inet_ntop(AF_INET6, &sa->in6.sin6_addr, a, sizeof(a));
++
++                        if (include_port) {
++                                if (asprintf(&p,
++                                             "[%s]:%u",
++                                             a,
++                                             ntohs(sa->in6.sin6_port)) < 0)
++                                        return -ENOMEM;
++                        } else {
++                                p = strdup(a);
++                                if (!p)
++                                        return -ENOMEM;
++                        }
+                 }
+ 
+                 break;
+@@ -589,7 +623,7 @@ int getpeername_pretty(int fd, char **ret) {
+         /* For remote sockets we translate IPv6 addresses back to IPv4
+          * if applicable, since that's nicer. */
+ 
+-        return sockaddr_pretty(&sa.sa, salen, true, ret);
++        return sockaddr_pretty(&sa.sa, salen, true, true, ret);
+ }
+ 
+ int getsockname_pretty(int fd, char **ret) {
+@@ -607,7 +641,7 @@ int getsockname_pretty(int fd, char **ret) {
+          * listening sockets where the difference between IPv4 and
+          * IPv6 matters. */
+ 
+-        return sockaddr_pretty(&sa.sa, salen, false, ret);
++        return sockaddr_pretty(&sa.sa, salen, false, true, ret);
+ }
+ 
+ int socknameinfo_pretty(union sockaddr_union *sa, socklen_t salen, char **_ret) {
+@@ -621,7 +655,7 @@ int socknameinfo_pretty(union sockaddr_union *sa, socklen_t salen, char **_ret)
+         if (r != 0) {
+                 int saved_errno = errno;
+ 
+-                r = sockaddr_pretty(&sa->sa, salen, true, &ret);
++                r = sockaddr_pretty(&sa->sa, salen, true, true, &ret);
+                 if (r < 0)
+                         return log_error_errno(r, "sockadd_pretty() failed: %m");
+ 
+diff --git a/src/shared/socket-util.h b/src/shared/socket-util.h
+index 07d0aff..6bfb677 100644
+--- a/src/shared/socket-util.h
++++ b/src/shared/socket-util.h
+@@ -98,7 +98,9 @@ const char* socket_address_get_path(const SocketAddress *a);
+ 
+ bool socket_ipv6_is_supported(void);
+ 
+-int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_ipv6, char **ret);
++int sockaddr_port(const struct sockaddr *_sa) _pure_;
++
++int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_ipv6, bool include_port, char **ret);
+ int getpeername_pretty(int fd, char **ret);
+ int getsockname_pretty(int fd, char **ret);
+ 
+diff --git a/src/timesync/timesyncd-server.h b/src/timesync/timesyncd-server.h
+index 243b44a..18c4444 100644
+--- a/src/timesync/timesyncd-server.h
++++ b/src/timesync/timesyncd-server.h
+@@ -59,7 +59,7 @@ struct ServerName {
+ int server_address_new(ServerName *n, ServerAddress **ret, const union sockaddr_union *sockaddr, socklen_t socklen);
+ ServerAddress* server_address_free(ServerAddress *a);
+ static inline int server_address_pretty(ServerAddress *a, char **pretty) {
+-        return sockaddr_pretty(&a->sockaddr.sa, a->socklen, true, pretty);
++        return sockaddr_pretty(&a->sockaddr.sa, a->socklen, true, true, pretty);
+ }
+ 
+ int server_name_new(Manager *m, ServerName **ret, ServerType type,const char *string);
diff --git a/SOURCES/0334-core-don-t-dispatch-load-queue-when-setting-Slice-fo.patch b/SOURCES/0334-core-don-t-dispatch-load-queue-when-setting-Slice-fo.patch
new file mode 100644
index 0000000..005f4a8
--- /dev/null
+++ b/SOURCES/0334-core-don-t-dispatch-load-queue-when-setting-Slice-fo.patch
@@ -0,0 +1,37 @@
+From b3207925388c6423a7665b9363eea90f41a30576 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Fri, 22 Apr 2016 17:30:08 +0200
+Subject: [PATCH] core: don't dispatch load queue when setting Slice= for
+ transient units
+
+Let's be more careful when setting up the Slice= property of transient units:
+let's use manager_load_unit_prepare() instead of manager_load_unit(), so that
+the load queue isn't dispatched right away, because our own transient unit is
+in it, and we don#t want to have it loaded until we finished initializing it.
+
+(cherry picked from commit aea529e5b2c864d536941ee18220abcc1a9015a0)
+Resolves: #1343904
+---
+ src/core/dbus-unit.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c
+index 227915e..49770bf 100644
+--- a/src/core/dbus-unit.c
++++ b/src/core/dbus-unit.c
+@@ -930,10 +930,14 @@ static int bus_unit_set_transient_property(
+                 } else {
+                         Unit *slice;
+ 
+-                        r = manager_load_unit(u->manager, s, NULL, error, &slice);
++                        /* Note that we do not dispatch the load queue here yet, as we don't want our own transient unit to be
++                         * loaded while we are still setting it up. Or in other words, we use manager_load_unit_prepare()
++                         * instead of manager_load_unit() on purpose, here. */
++                        r = manager_load_unit_prepare(u->manager, s, NULL, error, &slice);
+                         if (r < 0)
+                                 return r;
+ 
++
+                         if (slice->type != UNIT_SLICE)
+                                 return -EINVAL;
+ 
diff --git a/SOURCES/0335-run-make-slice-work-in-conjunction-with-scope.patch b/SOURCES/0335-run-make-slice-work-in-conjunction-with-scope.patch
new file mode 100644
index 0000000..a9b279e
--- /dev/null
+++ b/SOURCES/0335-run-make-slice-work-in-conjunction-with-scope.patch
@@ -0,0 +1,27 @@
+From 735f6a0d81b4bbefd0cb57bbfd51f0f86e4a703e Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Fri, 22 Apr 2016 17:31:40 +0200
+Subject: [PATCH] run: make --slice= work in conjunction with --scope
+
+Fixes: #2991
+(cherry picked from commit 37e605f934892bf7458eecaeb01fc682e33cc2ad)
+Resolves: #1343904
+---
+ src/run/run.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/src/run/run.c b/src/run/run.c
+index 4680342..bbb542b 100644
+--- a/src/run/run.c
++++ b/src/run/run.c
+@@ -595,6 +595,10 @@ static int transient_scope_set_properties(sd_bus_message *m) {
+         if (r < 0)
+                 return r;
+ 
++        r = transient_cgroup_set_properties(m);
++        if (r < 0)
++                return r;
++
+         r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, (uint32_t) getpid());
+         if (r < 0)
+                 return r;
diff --git a/SOURCES/0336-myhostname-fix-timeout-if-ipv6-is-disabled.patch b/SOURCES/0336-myhostname-fix-timeout-if-ipv6-is-disabled.patch
new file mode 100644
index 0000000..e1d7450
--- /dev/null
+++ b/SOURCES/0336-myhostname-fix-timeout-if-ipv6-is-disabled.patch
@@ -0,0 +1,61 @@
+From 6e5117b83af5998359916f276a9b32f755c0e6f4 Mon Sep 17 00:00:00 2001
+From: Jan Synacek <jsynacek@redhat.com>
+Date: Fri, 20 May 2016 12:33:48 +0200
+Subject: [PATCH] myhostname: fix timeout if ipv6 is disabled
+
+rhel-only
+Resolves: #1330973
+---
+ src/nss-myhostname/nss-myhostname.c |  9 +++++++--
+ src/shared/socket-util.c            | 10 ++++++++++
+ 2 files changed, 17 insertions(+), 2 deletions(-)
+
+diff --git a/src/nss-myhostname/nss-myhostname.c b/src/nss-myhostname/nss-myhostname.c
+index a939bb2..e197cc7 100644
+--- a/src/nss-myhostname/nss-myhostname.c
++++ b/src/nss-myhostname/nss-myhostname.c
+@@ -33,6 +33,7 @@
+ #include "local-addresses.h"
+ #include "macro.h"
+ #include "nss-util.h"
++#include "socket-util.h"
+ #include "util.h"
+ 
+ /* We use 127.0.0.2 as IPv4 address. This has the advantage over
+@@ -380,9 +381,13 @@ enum nss_status _nss_myhostname_gethostbyname3_r(
+                         return NSS_STATUS_NOTFOUND;
+                 }
+ 
+-                n_addresses = local_addresses(NULL, 0, af, &addresses);
+-                if (n_addresses < 0)
++                if (af == AF_INET6 && !socket_ipv6_is_supported()) {
+                         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/src/shared/socket-util.c b/src/shared/socket-util.c
+index a212510..79d1582 100644
+--- a/src/shared/socket-util.c
++++ b/src/shared/socket-util.c
+@@ -435,6 +435,16 @@ bool socket_ipv6_is_supported(void) {
+                 return true;
+ 
+         /* If module was loaded with disable=1 no IPv6 available */
++        if (l[0] == '1')
++                return false;
++
++        free(l);
++        l = NULL;
++
++        if (read_one_line_file("/proc/sys/net/ipv6/conf/all/disable_ipv6", &l) < 0)
++                return true;
++
++        /* If IPv6 was disabled via sysctl during runtime */
+         return l[0] == '0';
+ }
+ 
diff --git a/SOURCES/0337-readahead-do-not-increase-nr_requests-for-root-fs-bl.patch b/SOURCES/0337-readahead-do-not-increase-nr_requests-for-root-fs-bl.patch
new file mode 100644
index 0000000..1bca28f
--- /dev/null
+++ b/SOURCES/0337-readahead-do-not-increase-nr_requests-for-root-fs-bl.patch
@@ -0,0 +1,124 @@
+From 997778e332e9f6d3d1c42e9a222fcab8d4732c40 Mon Sep 17 00:00:00 2001
+From: Michal Sekletar <msekleta@redhat.com>
+Date: Fri, 27 May 2016 14:29:17 +0200
+Subject: [PATCH] readahead: do not increase nr_requests for root fs block
+ device
+
+Having nr_requests can cause system lockups. Arguably, this should get
+fixed somehow in kernel. For now we just stop changing the
+value.
+
+Note that not bumping a value may cause that posix_fadvise call
+will block in case there is no room in a request queue.
+
+See: http://article.gmane.org/gmane.linux.kernel/1072356
+
+RHEL-only
+Resolves: #1314559
+---
+ src/readahead/readahead-common.c | 64 ----------------------------------------
+ src/readahead/readahead-common.h |  2 --
+ src/readahead/readahead-replay.c |  2 --
+ 3 files changed, 68 deletions(-)
+
+diff --git a/src/readahead/readahead-common.c b/src/readahead/readahead-common.c
+index 3ca48a7..6cf33f7 100644
+--- a/src/readahead/readahead-common.c
++++ b/src/readahead/readahead-common.c
+@@ -253,70 +253,6 @@ ReadaheadShared *shared_get(void) {
+         return m;
+ }
+ 
+-/* We use 20K instead of the more human digestable 16K here. Why?
+-   Simply so that it is more unlikely that users end up picking this
+-   value too so that we can recognize better whether the user changed
+-   the value while we had it temporarily bumped. */
+-#define BUMP_REQUEST_NR (20*1024u)
+-
+-int block_bump_request_nr(const char *p) {
+-        struct stat st;
+-        uint64_t u;
+-        char *ap = NULL, *line = NULL;
+-        int r;
+-        dev_t d;
+-
+-        assert(p);
+-
+-        if (stat(p, &st) < 0)
+-                return -errno;
+-
+-        if (major(st.st_dev) == 0)
+-                return 0;
+-
+-        d = st.st_dev;
+-        block_get_whole_disk(d, &d);
+-
+-        if (asprintf(&ap, "/sys/dev/block/%u:%u/queue/nr_requests", major(d), minor(d)) < 0) {
+-                r= -ENOMEM;
+-                goto finish;
+-        }
+-
+-        r = read_one_line_file(ap, &line);
+-        if (r < 0) {
+-                if (r == -ENOENT)
+-                        r = 0;
+-                goto finish;
+-        }
+-
+-        r = safe_atou64(line, &u);
+-        if (r >= 0 && u >= BUMP_REQUEST_NR) {
+-                r = 0;
+-                goto finish;
+-        }
+-
+-        free(line);
+-        line = NULL;
+-
+-        if (asprintf(&line, "%u", BUMP_REQUEST_NR) < 0) {
+-                r = -ENOMEM;
+-                goto finish;
+-        }
+-
+-        r = write_string_file(ap, line);
+-        if (r < 0)
+-                goto finish;
+-
+-        log_info("Bumped block_nr parameter of %u:%u to %u. This is a temporary hack and should be removed one day.", major(d), minor(d), BUMP_REQUEST_NR);
+-        r = 1;
+-
+-finish:
+-        free(ap);
+-        free(line);
+-
+-        return r;
+-}
+-
+ int block_get_readahead(const char *p, uint64_t *bytes) {
+         struct stat st;
+         char *ap = NULL, *line = NULL;
+diff --git a/src/readahead/readahead-common.h b/src/readahead/readahead-common.h
+index b34f3aa..cc2ea81 100644
+--- a/src/readahead/readahead-common.h
++++ b/src/readahead/readahead-common.h
+@@ -51,8 +51,6 @@ typedef struct ReadaheadShared {
+ 
+ ReadaheadShared *shared_get(void);
+ 
+-int block_bump_request_nr(const char *p);
+-
+ int block_get_readahead(const char *p, uint64_t *bytes);
+ int block_set_readahead(const char *p, uint64_t bytes);
+ 
+diff --git a/src/readahead/readahead-replay.c b/src/readahead/readahead-replay.c
+index f81e0fe..c2e2816 100644
+--- a/src/readahead/readahead-replay.c
++++ b/src/readahead/readahead-replay.c
+@@ -134,8 +134,6 @@ static int replay(const char *root) {
+ 
+         assert(root);
+ 
+-        block_bump_request_nr(root);
+-
+         if (asprintf(&pack_fn, "%s/.readahead", root) < 0)
+                 return log_oom();
+ 
diff --git a/SOURCES/0338-manager-reduce-complexity-of-unit_gc_sweep-3507.patch b/SOURCES/0338-manager-reduce-complexity-of-unit_gc_sweep-3507.patch
new file mode 100644
index 0000000..24530fd
--- /dev/null
+++ b/SOURCES/0338-manager-reduce-complexity-of-unit_gc_sweep-3507.patch
@@ -0,0 +1,62 @@
+From 33ca0f1f0d4b9a91588c84067d2fb30968e41235 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Nykr=C3=BDn?= <lnykryn@redhat.com>
+Date: Tue, 14 Jun 2016 14:20:56 +0200
+Subject: [PATCH] manager: reduce complexity of unit_gc_sweep (#3507)
+
+When unit is marked as UNSURE, we are trying to find if it state was
+changed over and over again. So lets not go through the UNSURE states
+again. Also when we find a GOOD unit lets propagate the GOOD state to
+all units that this unit reference.
+
+This is a problem on machines with a lot of initscripts with different
+starting priority, since those units will reference each other and the
+original algorithm might get to n! complexity.
+
+Thanks HATAYAMA Daisuke for the expand_good_state code.
+Cherry-picked from: 4892084f096c19da0e83f28f250ca187b58c22b2
+Resolves: #1344556
+---
+ src/core/manager.c | 16 +++++++++++++++-
+ 1 file changed, 15 insertions(+), 1 deletion(-)
+
+diff --git a/src/core/manager.c b/src/core/manager.c
+index 370c8cb..e5226a8 100644
+--- a/src/core/manager.c
++++ b/src/core/manager.c
+@@ -838,6 +838,19 @@ enum {
+         _GC_OFFSET_MAX
+ };
+ 
++static void unit_gc_mark_good(Unit *u, unsigned gc_marker)
++{
++        Iterator i;
++        Unit *other;
++
++        u->gc_marker = gc_marker + GC_OFFSET_GOOD;
++
++        /* Recursively mark referenced units as GOOD as well */
++        SET_FOREACH(other, u->dependencies[UNIT_REFERENCES], i)
++                if (other->gc_marker == gc_marker + GC_OFFSET_UNSURE)
++                        unit_gc_mark_good(other, gc_marker);
++}
++
+ static void unit_gc_sweep(Unit *u, unsigned gc_marker) {
+         Iterator i;
+         Unit *other;
+@@ -847,6 +860,7 @@ static void unit_gc_sweep(Unit *u, unsigned gc_marker) {
+ 
+         if (u->gc_marker == gc_marker + GC_OFFSET_GOOD ||
+             u->gc_marker == gc_marker + GC_OFFSET_BAD ||
++            u->gc_marker == gc_marker + GC_OFFSET_UNSURE ||
+             u->gc_marker == gc_marker + GC_OFFSET_IN_PATH)
+                 return;
+ 
+@@ -887,7 +901,7 @@ bad:
+         return;
+ 
+ good:
+-        u->gc_marker = gc_marker + GC_OFFSET_GOOD;
++        unit_gc_mark_good(u, gc_marker);
+ }
+ 
+ static unsigned manager_dispatch_gc_queue(Manager *m) {
diff --git a/SOURCES/0339-hwdb-selinuxify-a-bit-3460.patch b/SOURCES/0339-hwdb-selinuxify-a-bit-3460.patch
new file mode 100644
index 0000000..c98059d
--- /dev/null
+++ b/SOURCES/0339-hwdb-selinuxify-a-bit-3460.patch
@@ -0,0 +1,68 @@
+From ca82178b166ae5fb8efe4b09aadae802534cf6e3 Mon Sep 17 00:00:00 2001
+From: Evgeny Vereshchagin <evvers@ya.ru>
+Date: Tue, 7 Jun 2016 20:47:41 +0300
+Subject: [PATCH] hwdb: selinuxify a bit (#3460)
+
+-bash-4.3# rm /etc/udev/hwdb.bin
+-bash-4.3# systemd-hwdb update
+-bash-4.3# ls -Z /etc/udev/hwdb.bin
+system_u:object_r:systemd_hwdb_etc_t:s0 /etc/udev/hwdb.bin
+
+Fixes: #3458
+
+(cherry picked from commit ea683512f9b82f2257770f0ed56d819eea230fc2)
+Resolves: #1343648
+---
+ Makefile.am     | 1 +
+ src/hwdb/hwdb.c | 8 ++++++--
+ 2 files changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/Makefile.am b/Makefile.am
+index b0a34b2..3848338 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -3752,6 +3752,7 @@ systemd_hwdb_SOURCES = \
+ 	src/hwdb/hwdb.c
+ 
+ systemd_hwdb_LDADD = \
++	libsystemd-label.la \
+ 	libsystemd-shared.la \
+ 	libsystemd-internal.la \
+ 	libudev-internal.la
+diff --git a/src/hwdb/hwdb.c b/src/hwdb/hwdb.c
+index 4539673..8e5d6cc 100644
+--- a/src/hwdb/hwdb.c
++++ b/src/hwdb/hwdb.c
+@@ -34,6 +34,8 @@
+ 
+ #include "hwdb-internal.h"
+ #include "hwdb-util.h"
++#include "label.h"
++#include "selinux-util.h"
+ 
+ /*
+  * Generic udev properties, key/value database based on modalias strings.
+@@ -642,12 +644,12 @@ static int hwdb_update(int argc, char *argv[], void *userdata) {
+         if (!hwdb_bin)
+                 return -ENOMEM;
+ 
+-        mkdir_parents(hwdb_bin, 0755);
++        mkdir_parents_label(hwdb_bin, 0755);
+         r = trie_store(trie, hwdb_bin);
+         if (r < 0)
+                 return log_error_errno(r, "Failure writing database %s: %m", hwdb_bin);
+ 
+-        return 0;
++        return label_fix(hwdb_bin, false, false);
+ }
+ 
+ static void help(void) {
+@@ -733,6 +735,8 @@ int main (int argc, char *argv[]) {
+         if (r <= 0)
+                 goto finish;
+ 
++        mac_selinux_init(NULL);
++
+         r = hwdb_main(argc, argv);
+ 
+ finish:
diff --git a/SOURCES/0340-udevadm-explicitly-relabel-etc-udev-hwdb.bin-after-r.patch b/SOURCES/0340-udevadm-explicitly-relabel-etc-udev-hwdb.bin-after-r.patch
new file mode 100644
index 0000000..6374256
--- /dev/null
+++ b/SOURCES/0340-udevadm-explicitly-relabel-etc-udev-hwdb.bin-after-r.patch
@@ -0,0 +1,55 @@
+From 0860805a09ce6c2c2136306bdf64d58621368291 Mon Sep 17 00:00:00 2001
+From: Michal Sekletar <msekleta@redhat.com>
+Date: Fri, 8 Jul 2016 15:54:55 +0200
+Subject: [PATCH] udevadm: explicitly relabel /etc/udev/hwdb.bin after rename
+
+This is basically the same change as ea68351.
+
+Cherry-picked from: 4f43161e909cb420aafbc4bebce4361b17b80fdd
+Related: #1350756
+---
+ src/udev/udevadm-hwdb.c | 5 ++++-
+ src/udev/udevadm.c      | 2 +-
+ 2 files changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/src/udev/udevadm-hwdb.c b/src/udev/udevadm-hwdb.c
+index d65e40c..201e2a0 100644
+--- a/src/udev/udevadm-hwdb.c
++++ b/src/udev/udevadm-hwdb.c
+@@ -26,6 +26,8 @@
+ #include "util.h"
+ #include "strbuf.h"
+ #include "conf-files.h"
++#include "label.h"
++#include "mkdir.h"
+ 
+ #include "udev.h"
+ #include "hwdb-internal.h"
+@@ -654,12 +656,13 @@ static int adm_hwdb(struct udev *udev, int argc, char *argv[]) {
+                         rc = EXIT_FAILURE;
+                         goto out;
+                 }
+-                mkdir_parents(hwdb_bin, 0755);
++                mkdir_parents_label(hwdb_bin, 0755);
+                 err = trie_store(trie, hwdb_bin);
+                 if (err < 0) {
+                         log_error_errno(err, "Failure writing database %s: %m", hwdb_bin);
+                         rc = EXIT_FAILURE;
+                 }
++                label_fix(hwdb_bin, false, false);
+         }
+ 
+         if (test) {
+diff --git a/src/udev/udevadm.c b/src/udev/udevadm.c
+index 56cd0cd..d05a26e 100644
+--- a/src/udev/udevadm.c
++++ b/src/udev/udevadm.c
+@@ -96,7 +96,7 @@ int main(int argc, char *argv[]) {
+ 
+         log_parse_environment();
+         log_open();
+-        mac_selinux_init("/dev");
++        mac_selinux_init(NULL);
+ 
+         while ((c = getopt_long(argc, argv, "+dhV", options, NULL)) >= 0)
+                 switch (c) {
diff --git a/SOURCES/0341-systemctl-return-diffrent-error-code-if-service-exis.patch b/SOURCES/0341-systemctl-return-diffrent-error-code-if-service-exis.patch
new file mode 100644
index 0000000..84b59cb
--- /dev/null
+++ b/SOURCES/0341-systemctl-return-diffrent-error-code-if-service-exis.patch
@@ -0,0 +1,82 @@
+From 2eb2ddac8eaa258dd1ac0b2d4c1aefef9b66a989 Mon Sep 17 00:00:00 2001
+From: Susant Sahani <ssahani@users.noreply.github.com>
+Date: Mon, 30 May 2016 20:23:15 +0530
+Subject: [PATCH] systemctl: return diffrent error code if service exist or not
+ (#3385)
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Before:
+[sus@maximus bz-1256858]$ systemctl status rsyslog.service;echo $?
+● rsyslog.service - System Logging Service
+   Loaded: loaded (/usr/lib/systemd/system/rsyslog.service; enabled; vendor
+preset: enabled)
+  Drop-In: /etc/systemd/system/rsyslog.service.d
+           └─50-CPUShares.conf
+   Active: inactive (dead) since Mon 2016-05-30 11:54:25 IST; 2h 26min ago
+     Docs: man:rsyslogd(8)
+           http://www.rsyslog.com/doc/
+  Process: 1159 ExecStart=/usr/sbin/rsyslogd -n $SYSLOGD_OPTIONS (code=exited,
+status=0/SUCCESS)
+ Main PID: 1159 (code=exited, status=0/SUCCESS)
+
+May 30 11:07:50 maximus systemd[1]: Starting System Logging Service...
+May 30 11:07:50 maximus systemd[1]: Started System Logging Service.
+May 30 11:54:25 maximus systemd[1]: Stopping System Logging Service...
+May 30 11:54:25 maximus systemd[1]: Stopped System Logging Service.
+3
+[sus@maximus bz-1256858]$ systemctl status hello.service;echo $?
+● hello.service
+   Loaded: not-found (Reason: No such file or directory)
+   Active: inactive (dead)
+3
+
+After:
+$ ./systemctl status hello.service;echo $?
+Failed to dump process list, ignoring: Access denied
+● hello.service
+   Loaded: not-found (Reason: No such file or directory)
+   Active: inactive (dead)
+4
+[sus@maximus bz-1256858]$  ./systemctl status rsyslog.service;echo $?
+Failed to dump process list, ignoring: Access denied
+● rsyslog.service - System Logging Service
+   Loaded: loaded (/usr/lib/systemd/system/rsyslog.service; enabled; vendor
+preset: enabled)
+  Drop-In: /etc/systemd/system/rsyslog.service.d
+           └─50-CPUShares.conf
+   Active: inactive (dead) since Mon 2016-05-30 11:54:25 IST; 2h 24min ago
+     Docs: man:rsyslogd(8)
+           http://www.rsyslog.com/doc/
+  Process: 1159 ExecStart=/usr/sbin/rsyslogd -n $SYSLOGD_OPTIONS (code=exited,
+status=0/SUCCESS)
+ Main PID: 1159 (code=exited, status=0/SUCCESS)
+
+May 30 11:07:50 maximus systemd[1]: Starting System Logging Service...
+May 30 11:07:50 maximus systemd[1]: Started System Logging Service.
+May 30 11:54:25 maximus systemd[1]: Stopping System Logging Service...
+May 30 11:54:25 maximus systemd[1]: Stopped System Logging Service.
+3
+
+Fixes: 1092
+
+(cherry picked from commit ca473d572f0d2d8f547ff787ae67afd489a3f15e)
+Resolves: #1047466
+---
+ src/systemctl/systemctl.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
+index 95ddf3b..6079d60 100644
+--- a/src/systemctl/systemctl.c
++++ b/src/systemctl/systemctl.c
+@@ -4295,6 +4295,8 @@ static int show_one(
+                  */
+                 if (info.pid_file && access(info.pid_file, F_OK) == 0)
+                         r = 1;
++                else if (streq_ptr(info.load_state, "not-found") && streq_ptr(info.active_state, "inactive"))
++                        r = 4;
+                 else
+                         r = 3;
+         }
diff --git a/SOURCES/0342-systemctl-Replace-init-script-error-codes-with-enum-.patch b/SOURCES/0342-systemctl-Replace-init-script-error-codes-with-enum-.patch
new file mode 100644
index 0000000..8696946
--- /dev/null
+++ b/SOURCES/0342-systemctl-Replace-init-script-error-codes-with-enum-.patch
@@ -0,0 +1,74 @@
+From 20a914f752898aae11708d7bf901e7dc1e81a28e Mon Sep 17 00:00:00 2001
+From: Susant Sahani <ssahani@users.noreply.github.com>
+Date: Tue, 31 May 2016 19:06:58 +0530
+Subject: [PATCH] systemctl: Replace init script error codes with enum (#3400)
+
+Now we just using constants for the init script exit status codes.
+Replace those error codes with enum so that it's more meaningful
+and readable.
+
+(cherry picked from commit b613907ea988e2994c68be686b5e92cdc7d3fb68)
+Related: #1047466
+---
+ src/systemctl/systemctl.c | 29 ++++++++++++++++++++++++-----
+ 1 file changed, 24 insertions(+), 5 deletions(-)
+
+diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
+index 6079d60..fdda174 100644
+--- a/src/systemctl/systemctl.c
++++ b/src/systemctl/systemctl.c
+@@ -75,6 +75,25 @@
+ #include "mkdir.h"
+ #include "dropin.h"
+ 
++/* The init script exit status codes
++   0       program is running or service is OK
++   1       program is dead and /var/run pid file exists
++   2       program is dead and /var/lock lock file exists
++   3       program is not running
++   4       program or service status is unknown
++   5-99    reserved for future LSB use
++   100-149 reserved for distribution use
++   150-199 reserved for application use
++   200-254 reserved
++*/
++enum {
++        EXIT_PROGRAM_RUNNING_OR_SERVICE_OK        = 0,
++        EXIT_PROGRAM_DEAD_AND_PID_EXISTS          = 1,
++        EXIT_PROGRAM_DEAD_AND_LOCK_FILE_EXISTS    = 2,
++        EXIT_PROGRAM_NOT_RUNNING                  = 3,
++        EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN   = 4,
++};
++
+ static char **arg_types = NULL;
+ static char **arg_states = NULL;
+ static char **arg_properties = NULL;
+@@ -3028,11 +3047,11 @@ static int check_unit_generic(sd_bus *bus, int code, const char *good_states, ch
+ 
+ static int check_unit_active(sd_bus *bus, char **args) {
+         /* According to LSB: 3, "program is not running" */
+-        return check_unit_generic(bus, 3, "active\0reloading\0", args + 1);
++        return check_unit_generic(bus, EXIT_PROGRAM_NOT_RUNNING, "active\0reloading\0", args + 1);
+ }
+ 
+ static int check_unit_failed(sd_bus *bus, char **args) {
+-        return check_unit_generic(bus, 1, "failed\0", args + 1);
++        return check_unit_generic(bus, EXIT_PROGRAM_DEAD_AND_PID_EXISTS, "failed\0", args + 1);
+ }
+ 
+ static int kill_unit(sd_bus *bus, char **args) {
+@@ -4294,11 +4313,11 @@ static int show_one(
+                  * 4: program or service status is unknown
+                  */
+                 if (info.pid_file && access(info.pid_file, F_OK) == 0)
+-                        r = 1;
++                        r = EXIT_PROGRAM_DEAD_AND_PID_EXISTS;
+                 else if (streq_ptr(info.load_state, "not-found") && streq_ptr(info.active_state, "inactive"))
+-                        r = 4;
++                        r = EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN;
+                 else
+-                        r = 3;
++                        r = EXIT_PROGRAM_NOT_RUNNING;
+         }
+ 
+         while ((p = info.exec)) {
diff --git a/SOURCES/0343-systemctl-rework-systemctl-status-a-bit.patch b/SOURCES/0343-systemctl-rework-systemctl-status-a-bit.patch
new file mode 100644
index 0000000..21a9c9f
--- /dev/null
+++ b/SOURCES/0343-systemctl-rework-systemctl-status-a-bit.patch
@@ -0,0 +1,234 @@
+From 41bb37959c96b8fddc13b37384b3453393517f4f Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Mon, 13 Jun 2016 19:11:26 +0200
+Subject: [PATCH] systemctl: rework "systemctl status" a bit
+
+This reworks "systemctl status" and "systemctl show" a bit. It removes the
+definition of the `property_info` structure, because we can simply reuse the
+existing UnitStatusInfo type for that.
+
+The "could not be found" message is now printed by show_one() itself (and not
+its caller), so that it is shown regardless by who the function is called.
+(This makes it necessary to pass the unit name to the function.)
+
+This also adds all properties found to a set, and then checks if any of the
+properties passed via "--property=" is mising in it, if so, a proper error is
+generated.
+
+Support for checking the PID file of a unit is removed, as this cannot be done
+reasonably client side (since the systemd instance we are talking to might sit
+on another host)
+
+Replaces: #3411
+Fixes: #3425
+Also see: #3504
+
+(cherry picked from commit 3dced37b7c2c9a5c733817569d2bbbaa397adaf7)
+Related: #1047466
+---
+ src/systemctl/systemctl.c | 106 +++++++++++++++++++++++++++++-----------------
+ 1 file changed, 68 insertions(+), 38 deletions(-)
+
+diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
+index fdda174..93b7a19 100644
+--- a/src/systemctl/systemctl.c
++++ b/src/systemctl/systemctl.c
+@@ -4211,12 +4211,19 @@ static int show_one(
+                 const char *verb,
+                 sd_bus *bus,
+                 const char *path,
++                const char *unit,
+                 bool show_properties,
+                 bool *new_line,
+                 bool *ellipsized) {
+ 
+         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
++        _cleanup_set_free_ Set *found_properties = NULL;
++        static const struct bus_properties_map property_map[] = {
++                { "LoadState",   "s", NULL, offsetof(UnitStatusInfo, load_state)   },
++                { "ActiveState", "s", NULL, offsetof(UnitStatusInfo, active_state) },
++                {}
++        };
+         UnitStatusInfo info = {
+                 .memory_current = (uint64_t) -1,
+                 .memory_limit = (uint64_t) -1,
+@@ -4243,6 +4250,25 @@ static int show_one(
+                 return r;
+         }
+ 
++        if (unit) {
++                r = bus_message_map_all_properties(bus, reply, property_map, &info);
++                if (r < 0)
++                        return log_error_errno(r, "Failed to map properties: %s", bus_error_message(&error, r));
++
++                if (streq_ptr(info.load_state, "not-found") && streq_ptr(info.active_state, "inactive")) {
++                        log_error("Unit %s could not be found.", unit);
++
++                        if (streq(verb, "status"))
++                                return EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN;
++
++                        return -ENOENT;
++                }
++
++                r = sd_bus_message_rewind(reply, true);
++                if (r < 0)
++                        return log_error_errno(r, "Failed to rewind: %s", bus_error_message(&error, r));
++        }
++
+         r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
+         if (r < 0)
+                 return bus_log_parse_error(r);
+@@ -4267,9 +4293,17 @@ static int show_one(
+                 if (r < 0)
+                         return bus_log_parse_error(r);
+ 
+-                if (show_properties)
++                if (show_properties) {
++                        r = set_ensure_allocated(&found_properties, &string_hash_ops);
++                        if (r < 0)
++                                return log_oom();
++
++                        r = set_put(found_properties, name);
++                        if (r < 0 && r != EEXIST)
++                                return log_oom();
++
+                         r = print_property(name, reply, contents);
+-                else
++                } else
+                         r = status_property(name, reply, &info, contents);
+                 if (r < 0)
+                         return r;
+@@ -4291,35 +4325,30 @@ static int show_one(
+ 
+         r = 0;
+ 
+-        if (!show_properties) {
+-                if (streq(verb, "help"))
+-                        show_unit_help(&info);
++        if (show_properties) {
++                char **pp;
++
++                STRV_FOREACH(pp, arg_properties) {
++                        if (!set_contains(found_properties, *pp)) {
++                                log_warning("Property %s does not exist.", *pp);
++                                r = -ENXIO;
++                        }
++                }
++        } else if (streq(verb, "help"))
++                show_unit_help(&info);
++        else if (streq(verb, "status")) {
++                print_status_info(&info, ellipsized);
++
++                if (info.active_state && STR_IN_SET(info.active_state, "inactive", "failed"))
++                        r = EXIT_PROGRAM_NOT_RUNNING;
+                 else
+-                        print_status_info(&info, ellipsized);
++                        r = EXIT_PROGRAM_RUNNING_OR_SERVICE_OK;
+         }
+ 
+         strv_free(info.documentation);
+         strv_free(info.dropin_paths);
+         strv_free(info.listen);
+ 
+-        if (!streq_ptr(info.active_state, "active") &&
+-            !streq_ptr(info.active_state, "reloading") &&
+-            streq(verb, "status")) {
+-                /* According to LSB: "program not running" */
+-                /* 0: program is running or service is OK
+-                 * 1: program is dead and /run PID file exists
+-                 * 2: program is dead and /run/lock lock file exists
+-                 * 3: program is not running
+-                 * 4: program or service status is unknown
+-                 */
+-                if (info.pid_file && access(info.pid_file, F_OK) == 0)
+-                        r = EXIT_PROGRAM_DEAD_AND_PID_EXISTS;
+-                else if (streq_ptr(info.load_state, "not-found") && streq_ptr(info.active_state, "inactive"))
+-                        r = EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN;
+-                else
+-                        r = EXIT_PROGRAM_NOT_RUNNING;
+-        }
+-
+         while ((p = info.exec)) {
+                 LIST_REMOVE(exec, info.exec, p);
+                 exec_status_info_free(p);
+@@ -4394,7 +4423,7 @@ static int show_all(
+                 if (!p)
+                         return log_oom();
+ 
+-                r = show_one(verb, bus, p, show_properties, new_line, ellipsized);
++                r = show_one(verb, bus, p, u->id, show_properties, new_line, ellipsized);
+                 if (r < 0)
+                         return r;
+                 else if (r > 0 && ret == 0)
+@@ -4481,9 +4510,8 @@ static int show(sd_bus *bus, char **args) {
+                 setrlimit_closest(RLIMIT_NOFILE, &RLIMIT_MAKE_CONST(16384));
+ 
+         /* If no argument is specified inspect the manager itself */
+-
+         if (show_properties && strv_length(args) <= 1)
+-                return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line, &ellipsized);
++                return show_one(args[0], bus, "/org/freedesktop/systemd1", NULL, show_properties, &new_line, &ellipsized);
+ 
+         if (show_status && strv_length(args) <= 1) {
+ 
+@@ -4498,7 +4526,7 @@ static int show(sd_bus *bus, char **args) {
+                 char **name;
+ 
+                 STRV_FOREACH(name, args + 1) {
+-                        _cleanup_free_ char *unit = NULL;
++                        _cleanup_free_ char *path = NULL, *unit = NULL;
+                         uint32_t id;
+ 
+                         if (safe_atou32(*name, &id) < 0) {
+@@ -4508,20 +4536,23 @@ static int show(sd_bus *bus, char **args) {
+                                 continue;
+                         } else if (show_properties) {
+                                 /* Interpret as job id */
+-                                if (asprintf(&unit, "/org/freedesktop/systemd1/job/%u", id) < 0)
++                                if (asprintf(&path, "/org/freedesktop/systemd1/job/%u", id) < 0)
+                                         return log_oom();
+ 
+                         } else {
+                                 /* Interpret as PID */
+-                                r = get_unit_dbus_path_by_pid(bus, id, &unit);
++                                r = get_unit_dbus_path_by_pid(bus, id, &path);
+                                 if (r < 0) {
+                                         ret = r;
+                                         continue;
+                                 }
++
++                                r = unit_name_from_dbus_path(path, &unit);
++                                if (r < 0)
++                                        return log_oom();
+                         }
+ 
+-                        r = show_one(args[0], bus, unit, show_properties,
+-                                     &new_line, &ellipsized);
++                        r = show_one(args[0], bus, path, unit, show_properties, &new_line, &ellipsized);
+                         if (r < 0)
+                                 return r;
+                         else if (r > 0 && ret == 0)
+@@ -4536,17 +4567,16 @@ static int show(sd_bus *bus, char **args) {
+                                 log_error_errno(r, "Failed to expand names: %m");
+ 
+                         STRV_FOREACH(name, names) {
+-                                _cleanup_free_ char *unit;
++                                _cleanup_free_ char *path;
+ 
+-                                unit = unit_dbus_path_from_name(*name);
+-                                if (!unit)
++                                path = unit_dbus_path_from_name(*name);
++                                if (!path)
+                                         return log_oom();
+ 
+-                                r = show_one(args[0], bus, unit, show_properties,
+-                                             &new_line, &ellipsized);
++                                r = show_one(args[0], bus, path, *name, show_properties, &new_line, &ellipsized);
+                                 if (r < 0)
+                                         return r;
+-                                else if (r > 0 && ret == 0)
++                                if (r > 0 && ret == 0)
+                                         ret = r;
+                         }
+                 }
diff --git a/SOURCES/0344-journal-verify-don-t-hit-SIGFPE-when-determining-pro.patch b/SOURCES/0344-journal-verify-don-t-hit-SIGFPE-when-determining-pro.patch
new file mode 100644
index 0000000..3bcc69f
--- /dev/null
+++ b/SOURCES/0344-journal-verify-don-t-hit-SIGFPE-when-determining-pro.patch
@@ -0,0 +1,62 @@
+From 1466d84c159c1a9d1839c1b346906b722e6311a3 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Fri, 24 Jul 2015 01:40:44 +0200
+Subject: [PATCH] journal-verify: don't hit SIGFPE when determining progress
+
+If we determine the progress based on a number of objects available,
+don't blindly devide by the number of objects, given that it might be 0.
+
+Cherry-picked from: 45c047b227d96e98e7076c15ae774ff6390dc403
+Related: #1350232
+---
+ src/journal/journal-verify.c | 16 +++++++++++++---
+ 1 file changed, 13 insertions(+), 3 deletions(-)
+
+diff --git a/src/journal/journal-verify.c b/src/journal/journal-verify.c
+index b03335e..983217c 100644
+--- a/src/journal/journal-verify.c
++++ b/src/journal/journal-verify.c
+@@ -69,6 +69,16 @@ static void draw_progress(uint64_t p, usec_t *last_usec) {
+         fflush(stdout);
+ }
+ 
++static uint64_t scale_progress(uint64_t scale, uint64_t p, uint64_t m) {
++
++        /* Calculates scale * p / m, but handles m == 0 safely, and saturates */
++
++        if (p >= m || m == 0)
++                return scale;
++
++        return scale * p / m;
++}
++
+ static void flush_progress(void) {
+         unsigned n, i;
+ 
+@@ -584,7 +594,7 @@ static int verify_hash_table(
+                 uint64_t last = 0, p;
+ 
+                 if (show_progress)
+-                        draw_progress(0xC000 + (0x3FFF * i / n), last_usec);
++                        draw_progress(0xC000 + scale_progress(0x3FFF, i, n), last_usec);
+ 
+                 p = le64toh(f->data_hash_table[i].head_hash_offset);
+                 while (p != 0) {
+@@ -726,7 +736,7 @@ static int verify_entry_array(
+                 Object *o;
+ 
+                 if (show_progress)
+-                        draw_progress(0x8000 + (0x3FFF * i / n), last_usec);
++                        draw_progress(0x8000 + scale_progress(0x3FFF, i, n), last_usec);
+ 
+                 if (a == 0) {
+                         error(a, "array chain too short at %"PRIu64" of %"PRIu64, i, n);
+@@ -863,7 +873,7 @@ int journal_file_verify(
+         p = le64toh(f->header->header_size);
+         while (p != 0) {
+                 if (show_progress)
+-                        draw_progress(0x7FFF * p / le64toh(f->header->tail_object_offset), &last_usec);
++                        draw_progress(scale_progress(0x7FFF, p, le64toh(f->header->tail_object_offset)), &last_usec);
+ 
+                 r = journal_file_move_to_object(f, OBJECT_UNUSED, p, &o);
+                 if (r < 0) {
diff --git a/SOURCES/0345-journal-avoid-mapping-empty-data-and-field-hash-tabl.patch b/SOURCES/0345-journal-avoid-mapping-empty-data-and-field-hash-tabl.patch
new file mode 100644
index 0000000..476804d
--- /dev/null
+++ b/SOURCES/0345-journal-avoid-mapping-empty-data-and-field-hash-tabl.patch
@@ -0,0 +1,162 @@
+From 283df68dbc1d90cad21beec6563215c26c69ec2c Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Fri, 24 Jul 2015 01:55:45 +0200
+Subject: [PATCH] journal: avoid mapping empty data and field hash tables
+
+When a new journal file is created we write the header first, then sync
+and only then create the data and field hash tables in them. That means
+to other processes it might appear that the files have a valid header
+but not data and field hash tables. Our reader code should be able to
+deal with this.
+
+With this change we'll not map the two hash tables right-away after
+opening a file for reading anymore (because that will of course fail if
+the objects are missing), but delay this until the first time we access
+them. On top of that, when we want to look something up in the hash
+tables and we notice they aren't initialized yet, we consider them
+empty.
+
+This improves handling of some journal files reported in #487.
+
+Cherry-picked from: dade37d403f1b8c1d7bb2efbe2361f2a3e999613
+Related: #1350232
+---
+ src/journal/journal-file.c   | 37 ++++++++++++++++++++++++++-----------
+ src/journal/journal-file.h   |  3 +++
+ src/journal/journal-verify.c | 14 ++++++++++++++
+ 3 files changed, 43 insertions(+), 11 deletions(-)
+
+diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c
+index 892fe47..ef18497 100644
+--- a/src/journal/journal-file.c
++++ b/src/journal/journal-file.c
+@@ -656,13 +656,16 @@ static int journal_file_setup_field_hash_table(JournalFile *f) {
+         return 0;
+ }
+ 
+-static int journal_file_map_data_hash_table(JournalFile *f) {
++int journal_file_map_data_hash_table(JournalFile *f) {
+         uint64_t s, p;
+         void *t;
+         int r;
+ 
+         assert(f);
+ 
++        if (f->data_hash_table)
++                return 0;
++
+         p = le64toh(f->header->data_hash_table_offset);
+         s = le64toh(f->header->data_hash_table_size);
+ 
+@@ -678,13 +681,16 @@ static int journal_file_map_data_hash_table(JournalFile *f) {
+         return 0;
+ }
+ 
+-static int journal_file_map_field_hash_table(JournalFile *f) {
++int journal_file_map_field_hash_table(JournalFile *f) {
+         uint64_t s, p;
+         void *t;
+         int r;
+ 
+         assert(f);
+ 
++        if (f->field_hash_table)
++                return 0;
++
+         p = le64toh(f->header->field_hash_table_offset);
+         s = le64toh(f->header->field_hash_table_size);
+ 
+@@ -803,10 +809,18 @@ int journal_file_find_field_object_with_hash(
+         assert(f);
+         assert(field && size > 0);
+ 
++        /* If the field hash table is empty, we can't find anything */
++        if (le64toh(f->header->field_hash_table_size) <= 0)
++                return 0;
++
++        /* Map the field hash table, if it isn't mapped yet. */
++        r = journal_file_map_field_hash_table(f);
++        if (r < 0)
++                return r;
++
+         osize = offsetof(Object, field.payload) + size;
+ 
+         m = le64toh(f->header->field_hash_table_size) / sizeof(HashItem);
+-
+         if (m <= 0)
+                 return -EBADMSG;
+ 
+@@ -866,6 +880,15 @@ int journal_file_find_data_object_with_hash(
+         assert(f);
+         assert(data || size == 0);
+ 
++        /* If there's no data hash table, then there's no entry. */
++        if (le64toh(f->header->data_hash_table_size) <= 0)
++                return 0;
++
++        /* Map the data hash table, if it isn't mapped yet. */
++        r = journal_file_map_data_hash_table(f);
++        if (r < 0)
++                return r;
++
+         osize = offsetof(Object, data.payload) + size;
+ 
+         m = le64toh(f->header->data_hash_table_size) / sizeof(HashItem);
+@@ -2707,14 +2730,6 @@ int journal_file_open(
+ #endif
+         }
+ 
+-        r = journal_file_map_field_hash_table(f);
+-        if (r < 0)
+-                goto fail;
+-
+-        r = journal_file_map_data_hash_table(f);
+-        if (r < 0)
+-                goto fail;
+-
+         if (mmap_cache_got_sigbus(f->mmap, f->fd)) {
+                 r = -EIO;
+                 goto fail;
+diff --git a/src/journal/journal-file.h b/src/journal/journal-file.h
+index 0f29b09..c74ad5f 100644
+--- a/src/journal/journal-file.h
++++ b/src/journal/journal-file.h
+@@ -234,3 +234,6 @@ static inline bool JOURNAL_FILE_COMPRESS(JournalFile *f) {
+         assert(f);
+         return f->compress_xz || f->compress_lz4;
+ }
++
++int journal_file_map_data_hash_table(JournalFile *f);
++int journal_file_map_field_hash_table(JournalFile *f);
+diff --git a/src/journal/journal-verify.c b/src/journal/journal-verify.c
+index 983217c..d2d5c40 100644
+--- a/src/journal/journal-verify.c
++++ b/src/journal/journal-verify.c
+@@ -590,6 +590,13 @@ static int verify_hash_table(
+         assert(last_usec);
+ 
+         n = le64toh(f->header->data_hash_table_size) / sizeof(HashItem);
++        if (n <= 0)
++                return 0;
++
++        r = journal_file_map_data_hash_table(f);
++        if (r < 0)
++                return log_error_errno(r, "Failed to map data hash table: %m");
++
+         for (i = 0; i < n; i++) {
+                 uint64_t last = 0, p;
+ 
+@@ -647,6 +654,13 @@ static int data_object_in_hash_table(JournalFile *f, uint64_t hash, uint64_t p)
+         assert(f);
+ 
+         n = le64toh(f->header->data_hash_table_size) / sizeof(HashItem);
++        if (n <= 0)
++                return 0;
++
++        r = journal_file_map_data_hash_table(f);
++        if (r < 0)
++                return log_error_errno(r, "Failed to map data hash table: %m");
++
+         h = hash % n;
+ 
+         q = le64toh(f->data_hash_table[h].head_hash_offset);
diff --git a/SOURCES/0346-journal-when-verifying-journal-files-handle-empty-on.patch b/SOURCES/0346-journal-when-verifying-journal-files-handle-empty-on.patch
new file mode 100644
index 0000000..96a659b
--- /dev/null
+++ b/SOURCES/0346-journal-when-verifying-journal-files-handle-empty-on.patch
@@ -0,0 +1,84 @@
+From 0c2f52bb9b0bce392f14a38d6477e396d6fc987e Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Fri, 24 Jul 2015 02:00:43 +0200
+Subject: [PATCH] journal: when verifying journal files, handle empty ones
+ nicely
+
+A journal file that carries no objects should be considered valid.
+
+Cherry-picked from: 8dc37a85255f68d62f7af66696cbf6a66401fb2a
+Resolves: #1350232
+---
+ src/journal/journal-verify.c | 37 ++++++++++++++-----------------------
+ 1 file changed, 14 insertions(+), 23 deletions(-)
+
+diff --git a/src/journal/journal-verify.c b/src/journal/journal-verify.c
+index d2d5c40..53f0550 100644
+--- a/src/journal/journal-verify.c
++++ b/src/journal/journal-verify.c
+@@ -885,7 +885,11 @@ int journal_file_verify(
+          * superficial structure, headers, hashes. */
+ 
+         p = le64toh(f->header->header_size);
+-        while (p != 0) {
++        for (;;) {
++                /* Early exit if there are no objects in the file, at all */
++                if (le64toh(f->header->tail_object_offset) == 0)
++                        break;
++
+                 if (show_progress)
+                         draw_progress(scale_progress(0x7FFF, p, le64toh(f->header->tail_object_offset)), &last_usec);
+ 
+@@ -901,9 +905,6 @@ int journal_file_verify(
+                         goto fail;
+                 }
+ 
+-                if (p == le64toh(f->header->tail_object_offset))
+-                        found_last = true;
+-
+                 n_objects ++;
+ 
+                 r = journal_file_object_verify(f, p, o);
+@@ -1148,13 +1149,15 @@ int journal_file_verify(
+                         n_weird ++;
+                 }
+ 
+-                if (p == le64toh(f->header->tail_object_offset))
+-                        p = 0;
+-                else
+-                        p = p + ALIGN64(le64toh(o->object.size));
+-        }
++                if (p == le64toh(f->header->tail_object_offset)) {
++                        found_last = true;
++                        break;
++                }
+ 
+-        if (!found_last) {
++                p = p + ALIGN64(le64toh(o->object.size));
++        };
++
++        if (!found_last && le64toh(f->header->tail_object_offset) != 0) {
+                 error(le64toh(f->header->tail_object_offset), "tail object pointer dead");
+                 r = -EBADMSG;
+                 goto fail;
+@@ -1200,19 +1203,7 @@ int journal_file_verify(
+                 goto fail;
+         }
+ 
+-        if (n_data_hash_tables != 1) {
+-                error(0, "missing data hash table");
+-                r = -EBADMSG;
+-                goto fail;
+-        }
+-
+-        if (n_field_hash_tables != 1) {
+-                error(0, "missing field hash table");
+-                r = -EBADMSG;
+-                goto fail;
+-        }
+-
+-        if (!found_main_entry_array) {
++        if (!found_main_entry_array && le64toh(f->header->entry_array_offset) != 0) {
+                 error(0, "missing entry array");
+                 r = -EBADMSG;
+                 goto fail;
diff --git a/SOURCES/0347-journal-explain-the-error-when-we-find-a-non-DATA-ob.patch b/SOURCES/0347-journal-explain-the-error-when-we-find-a-non-DATA-ob.patch
new file mode 100644
index 0000000..3f0242f
--- /dev/null
+++ b/SOURCES/0347-journal-explain-the-error-when-we-find-a-non-DATA-ob.patch
@@ -0,0 +1,31 @@
+From 8cfa250db93688a0796475cb911215e4edb252aa Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Fri, 24 Jul 2015 02:02:07 +0200
+Subject: [PATCH] journal: explain the error when we find a non-DATA object
+ that is compressed
+
+Only objects of type DATA may be compressed, generate a message about
+that, like we do for all other errros.
+
+Cherry-picked from: bca9e39dfadaefc4b02c0dd378adc3d6221071de
+Related: #1350232
+---
+ src/journal/journal-verify.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/src/journal/journal-verify.c b/src/journal/journal-verify.c
+index 53f0550..77fb409 100644
+--- a/src/journal/journal-verify.c
++++ b/src/journal/journal-verify.c
+@@ -123,8 +123,10 @@ static int journal_file_object_verify(JournalFile *f, uint64_t offset, Object *o
+          * other objects. */
+ 
+         if ((o->object.flags & OBJECT_COMPRESSED_XZ) &&
+-            o->object.type != OBJECT_DATA)
++            o->object.type != OBJECT_DATA) {
++                error(offset, "Found compressed object that isn't of type DATA, which is not allowed.");
+                 return -EBADMSG;
++        }
+ 
+         switch (o->object.type) {
+ 
diff --git a/SOURCES/0348-journalctl-properly-detect-empty-journal-files.patch b/SOURCES/0348-journalctl-properly-detect-empty-journal-files.patch
new file mode 100644
index 0000000..c4d242c
--- /dev/null
+++ b/SOURCES/0348-journalctl-properly-detect-empty-journal-files.patch
@@ -0,0 +1,31 @@
+From 8290b73eeb8da4f8f0076f3bb7e23990af734de0 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Fri, 24 Jul 2015 02:10:32 +0200
+Subject: [PATCH] journalctl: properly detect empty journal files
+
+When we encounter a journal file with exactly zero entries, print a nice
+message and exit, and don't print a weird error message.
+
+Cherry-picked from: 02ab86c732576a71179ce12e97d44c289833236d
+Related: #1350232
+---
+ src/journal/journalctl.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
+index 6948ed6..904aae9 100644
+--- a/src/journal/journalctl.c
++++ b/src/journal/journalctl.c
+@@ -2141,6 +2141,12 @@ int main(int argc, char *argv[]) {
+                 return EXIT_FAILURE;
+         }
+ 
++        if (r == 0) {
++                printf("-- No entries --\n");
++                return EXIT_SUCCESS;
++        }
++
++
+         if (!arg_follow)
+                 pager_open_if_enabled();
+ 
diff --git a/SOURCES/0349-journal-uppercase-first-character-in-verify-error-me.patch b/SOURCES/0349-journal-uppercase-first-character-in-verify-error-me.patch
new file mode 100644
index 0000000..d679d33
--- /dev/null
+++ b/SOURCES/0349-journal-uppercase-first-character-in-verify-error-me.patch
@@ -0,0 +1,642 @@
+From 2a9dd5375b4f35a101d6ef3deb035d901d7a2392 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Fri, 24 Jul 2015 02:18:13 +0200
+Subject: [PATCH] journal: uppercase first character in verify error messages
+
+In the english language the first character of a sentence is supposed to
+be uppercase. Let's make sure this also applies to the journal
+verification error messages.
+
+Cherry-picked from: e80acc51aeaf2d74cb4d6cecbcb6e18f74c22c05
+Related: #1350232
+---
+ src/journal/journal-verify.c | 162 ++++++++++++++++++++-----------------------
+ 1 file changed, 75 insertions(+), 87 deletions(-)
+
+diff --git a/src/journal/journal-verify.c b/src/journal/journal-verify.c
+index 77fb409..8a66ac7 100644
+--- a/src/journal/journal-verify.c
++++ b/src/journal/journal-verify.c
+@@ -135,15 +135,15 @@ static int journal_file_object_verify(JournalFile *f, uint64_t offset, Object *o
+                 int compression, r;
+ 
+                 if (le64toh(o->data.entry_offset) == 0)
+-                        warning(offset, "unused data (entry_offset==0)");
++                        warning(offset, "Unused data (entry_offset==0)");
+ 
+                 if ((le64toh(o->data.entry_offset) == 0) ^ (le64toh(o->data.n_entries) == 0)) {
+-                        error(offset, "bad n_entries: %"PRIu64, o->data.n_entries);
++                        error(offset, "Bad n_entries: %"PRIu64, o->data.n_entries);
+                         return -EBADMSG;
+                 }
+ 
+                 if (le64toh(o->object.size) - offsetof(DataObject, payload) <= 0) {
+-                        error(offset, "bad object size (<= %zu): %"PRIu64,
++                        error(offset, "Bad object size (<= %zu): %"PRIu64,
+                               offsetof(DataObject, payload),
+                               le64toh(o->object.size));
+                         return -EBADMSG;
+@@ -171,7 +171,7 @@ static int journal_file_object_verify(JournalFile *f, uint64_t offset, Object *o
+                         h2 = hash64(o->data.payload, le64toh(o->object.size) - offsetof(Object, data.payload));
+ 
+                 if (h1 != h2) {
+-                        error(offset, "invalid hash (%08"PRIx64" vs. %08"PRIx64, h1, h2);
++                        error(offset, "Invalid hash (%08"PRIx64" vs. %08"PRIx64, h1, h2);
+                         return -EBADMSG;
+                 }
+ 
+@@ -179,7 +179,7 @@ static int journal_file_object_verify(JournalFile *f, uint64_t offset, Object *o
+                     !VALID64(o->data.next_field_offset) ||
+                     !VALID64(o->data.entry_offset) ||
+                     !VALID64(o->data.entry_array_offset)) {
+-                        error(offset, "invalid offset (next_hash_offset="OFSfmt", next_field_offset="OFSfmt", entry_offset="OFSfmt", entry_array_offset="OFSfmt,
++                        error(offset, "Invalid offset (next_hash_offset="OFSfmt", next_field_offset="OFSfmt", entry_offset="OFSfmt", entry_array_offset="OFSfmt,
+                               o->data.next_hash_offset,
+                               o->data.next_field_offset,
+                               o->data.entry_offset,
+@@ -193,7 +193,7 @@ static int journal_file_object_verify(JournalFile *f, uint64_t offset, Object *o
+         case OBJECT_FIELD:
+                 if (le64toh(o->object.size) - offsetof(FieldObject, payload) <= 0) {
+                         error(offset,
+-                              "bad field size (<= %zu): %"PRIu64,
++                              "Bad field size (<= %zu): %"PRIu64,
+                               offsetof(FieldObject, payload),
+                               le64toh(o->object.size));
+                         return -EBADMSG;
+@@ -202,7 +202,7 @@ static int journal_file_object_verify(JournalFile *f, uint64_t offset, Object *o
+                 if (!VALID64(o->field.next_hash_offset) ||
+                     !VALID64(o->field.head_data_offset)) {
+                         error(offset,
+-                              "invalid offset (next_hash_offset="OFSfmt", head_data_offset="OFSfmt,
++                              "Invalid offset (next_hash_offset="OFSfmt", head_data_offset="OFSfmt,
+                               o->field.next_hash_offset,
+                               o->field.head_data_offset);
+                         return -EBADMSG;
+@@ -212,7 +212,7 @@ static int journal_file_object_verify(JournalFile *f, uint64_t offset, Object *o
+         case OBJECT_ENTRY:
+                 if ((le64toh(o->object.size) - offsetof(EntryObject, items)) % sizeof(EntryItem) != 0) {
+                         error(offset,
+-                              "bad entry size (<= %zu): %"PRIu64,
++                              "Bad entry size (<= %zu): %"PRIu64,
+                               offsetof(EntryObject, items),
+                               le64toh(o->object.size));
+                         return -EBADMSG;
+@@ -220,28 +220,28 @@ static int journal_file_object_verify(JournalFile *f, uint64_t offset, Object *o
+ 
+                 if ((le64toh(o->object.size) - offsetof(EntryObject, items)) / sizeof(EntryItem) <= 0) {
+                         error(offset,
+-                              "invalid number items in entry: %"PRIu64,
++                              "Invalid number items in entry: %"PRIu64,
+                               (le64toh(o->object.size) - offsetof(EntryObject, items)) / sizeof(EntryItem));
+                         return -EBADMSG;
+                 }
+ 
+                 if (le64toh(o->entry.seqnum) <= 0) {
+                         error(offset,
+-                              "invalid entry seqnum: %"PRIx64,
++                              "Invalid entry seqnum: %"PRIx64,
+                               le64toh(o->entry.seqnum));
+                         return -EBADMSG;
+                 }
+ 
+                 if (!VALID_REALTIME(le64toh(o->entry.realtime))) {
+                         error(offset,
+-                              "invalid entry realtime timestamp: %"PRIu64,
++                              "Invalid entry realtime timestamp: %"PRIu64,
+                               le64toh(o->entry.realtime));
+                         return -EBADMSG;
+                 }
+ 
+                 if (!VALID_MONOTONIC(le64toh(o->entry.monotonic))) {
+                         error(offset,
+-                              "invalid entry monotonic timestamp: %"PRIu64,
++                              "Invalid entry monotonic timestamp: %"PRIu64,
+                               le64toh(o->entry.monotonic));
+                         return -EBADMSG;
+                 }
+@@ -250,7 +250,7 @@ static int journal_file_object_verify(JournalFile *f, uint64_t offset, Object *o
+                         if (o->entry.items[i].object_offset == 0 ||
+                             !VALID64(o->entry.items[i].object_offset)) {
+                                 error(offset,
+-                                      "invalid entry item (%"PRIu64"/%"PRIu64" offset: "OFSfmt,
++                                      "Invalid entry item (%"PRIu64"/%"PRIu64" offset: "OFSfmt,
+                                       i, journal_file_entry_n_items(o),
+                                       o->entry.items[i].object_offset);
+                                 return -EBADMSG;
+@@ -264,7 +264,7 @@ static int journal_file_object_verify(JournalFile *f, uint64_t offset, Object *o
+                 if ((le64toh(o->object.size) - offsetof(HashTableObject, items)) % sizeof(HashItem) != 0 ||
+                     (le64toh(o->object.size) - offsetof(HashTableObject, items)) / sizeof(HashItem) <= 0) {
+                         error(offset,
+-                              "invalid %s hash table size: %"PRIu64,
++                              "Invalid %s hash table size: %"PRIu64,
+                               o->object.type == OBJECT_DATA_HASH_TABLE ? "data" : "field",
+                               le64toh(o->object.size));
+                         return -EBADMSG;
+@@ -274,7 +274,7 @@ static int journal_file_object_verify(JournalFile *f, uint64_t offset, Object *o
+                         if (o->hash_table.items[i].head_hash_offset != 0 &&
+                             !VALID64(le64toh(o->hash_table.items[i].head_hash_offset))) {
+                                 error(offset,
+-                                      "invalid %s hash table item (%"PRIu64"/%"PRIu64") head_hash_offset: "OFSfmt,
++                                      "Invalid %s hash table item (%"PRIu64"/%"PRIu64") head_hash_offset: "OFSfmt,
+                                       o->object.type == OBJECT_DATA_HASH_TABLE ? "data" : "field",
+                                       i, journal_file_hash_table_n_items(o),
+                                       le64toh(o->hash_table.items[i].head_hash_offset));
+@@ -283,7 +283,7 @@ static int journal_file_object_verify(JournalFile *f, uint64_t offset, Object *o
+                         if (o->hash_table.items[i].tail_hash_offset != 0 &&
+                             !VALID64(le64toh(o->hash_table.items[i].tail_hash_offset))) {
+                                 error(offset,
+-                                      "invalid %s hash table item (%"PRIu64"/%"PRIu64") tail_hash_offset: "OFSfmt,
++                                      "Invalid %s hash table item (%"PRIu64"/%"PRIu64") tail_hash_offset: "OFSfmt,
+                                       o->object.type == OBJECT_DATA_HASH_TABLE ? "data" : "field",
+                                       i, journal_file_hash_table_n_items(o),
+                                       le64toh(o->hash_table.items[i].tail_hash_offset));
+@@ -293,7 +293,7 @@ static int journal_file_object_verify(JournalFile *f, uint64_t offset, Object *o
+                         if ((o->hash_table.items[i].head_hash_offset != 0) !=
+                             (o->hash_table.items[i].tail_hash_offset != 0)) {
+                                 error(offset,
+-                                      "invalid %s hash table item (%"PRIu64"/%"PRIu64"): head_hash_offset="OFSfmt" tail_hash_offset="OFSfmt,
++                                      "Invalid %s hash table item (%"PRIu64"/%"PRIu64"): head_hash_offset="OFSfmt" tail_hash_offset="OFSfmt,
+                                       o->object.type == OBJECT_DATA_HASH_TABLE ? "data" : "field",
+                                       i, journal_file_hash_table_n_items(o),
+                                       le64toh(o->hash_table.items[i].head_hash_offset),
+@@ -308,14 +308,14 @@ static int journal_file_object_verify(JournalFile *f, uint64_t offset, Object *o
+                 if ((le64toh(o->object.size) - offsetof(EntryArrayObject, items)) % sizeof(le64_t) != 0 ||
+                     (le64toh(o->object.size) - offsetof(EntryArrayObject, items)) / sizeof(le64_t) <= 0) {
+                         error(offset,
+-                              "invalid object entry array size: %"PRIu64,
++                              "Invalid object entry array size: %"PRIu64,
+                               le64toh(o->object.size));
+                         return -EBADMSG;
+                 }
+ 
+                 if (!VALID64(o->entry_array.next_entry_array_offset)) {
+                         error(offset,
+-                              "invalid object entry array next_entry_array_offset: "OFSfmt,
++                              "Invalid object entry array next_entry_array_offset: "OFSfmt,
+                               o->entry_array.next_entry_array_offset);
+                         return -EBADMSG;
+                 }
+@@ -324,7 +324,7 @@ static int journal_file_object_verify(JournalFile *f, uint64_t offset, Object *o
+                         if (le64toh(o->entry_array.items[i]) != 0 &&
+                             !VALID64(le64toh(o->entry_array.items[i]))) {
+                                 error(offset,
+-                                      "invalid object entry array item (%"PRIu64"/%"PRIu64"): "OFSfmt,
++                                      "Invalid object entry array item (%"PRIu64"/%"PRIu64"): "OFSfmt,
+                                       i, journal_file_entry_array_n_items(o),
+                                       le64toh(o->entry_array.items[i]));
+                                 return -EBADMSG;
+@@ -335,14 +335,14 @@ static int journal_file_object_verify(JournalFile *f, uint64_t offset, Object *o
+         case OBJECT_TAG:
+                 if (le64toh(o->object.size) != sizeof(TagObject)) {
+                         error(offset,
+-                              "invalid object tag size: %"PRIu64,
++                              "Invalid object tag size: %"PRIu64,
+                               le64toh(o->object.size));
+                         return -EBADMSG;
+                 }
+ 
+                 if (!VALID_EPOCH(o->tag.epoch)) {
+                         error(offset,
+-                              "invalid object tag epoch: %"PRIu64,
++                              "Invalid object tag epoch: %"PRIu64,
+                               o->tag.epoch);
+                         return -EBADMSG;
+                 }
+@@ -415,8 +415,7 @@ static int entry_points_to_data(
+         assert(entry_fd >= 0);
+ 
+         if (!contains_uint64(f->mmap, entry_fd, n_entries, entry_p)) {
+-                error(data_p,
+-                      "data object references invalid entry at "OFSfmt, entry_p);
++                error(data_p, "Data object references invalid entry at "OFSfmt, entry_p);
+                 return -EBADMSG;
+         }
+ 
+@@ -432,8 +431,7 @@ static int entry_points_to_data(
+                 }
+ 
+         if (!found) {
+-                error(entry_p,
+-                      "data object at "OFSfmt" not referenced by linked entry", data_p);
++                error(entry_p, "Data object at "OFSfmt" not referenced by linked entry", data_p);
+                 return -EBADMSG;
+         }
+ 
+@@ -476,7 +474,7 @@ static int entry_points_to_data(
+                                         x = z;
+                         }
+ 
+-                        error(entry_p, "entry object doesn't exist in main entry array");
++                        error(entry_p, "Entry object doesn't exist in main entry array");
+                         return -EBADMSG;
+                 }
+ 
+@@ -506,9 +504,7 @@ static int verify_data(
+ 
+         /* Entry array means at least two objects */
+         if (a && n < 2) {
+-                error(p,
+-                      "entry array present (entry_array_offset="OFSfmt", but n_entries=%"PRIu64")",
+-                      a, n);
++                error(p, "Entry array present (entry_array_offset="OFSfmt", but n_entries=%"PRIu64")", a, n);
+                 return -EBADMSG;
+         }
+ 
+@@ -528,12 +524,12 @@ static int verify_data(
+                 uint64_t next, m, j;
+ 
+                 if (a == 0) {
+-                        error(p, "array chain too short");
++                        error(p, "Array chain too short");
+                         return -EBADMSG;
+                 }
+ 
+                 if (!contains_uint64(f->mmap, entry_array_fd, n_entry_arrays, a)) {
+-                        error(p, "invalid array offset "OFSfmt, a);
++                        error(p, "Invalid array offset "OFSfmt, a);
+                         return -EBADMSG;
+                 }
+ 
+@@ -543,8 +539,7 @@ static int verify_data(
+ 
+                 next = le64toh(o->entry_array.next_entry_array_offset);
+                 if (next != 0 && next <= a) {
+-                        error(p, "array chain has cycle (jumps back from "OFSfmt" to "OFSfmt")",
+-                              a, next);
++                        error(p, "Array chain has cycle (jumps back from "OFSfmt" to "OFSfmt")", a, next);
+                         return -EBADMSG;
+                 }
+ 
+@@ -553,7 +548,7 @@ static int verify_data(
+ 
+                         q = le64toh(o->entry_array.items[j]);
+                         if (q <= last) {
+-                                error(p, "data object's entry array not sorted");
++                                error(p, "Data object's entry array not sorted");
+                                 return -EBADMSG;
+                         }
+                         last = q;
+@@ -611,8 +606,7 @@ static int verify_hash_table(
+                         uint64_t next;
+ 
+                         if (!contains_uint64(f->mmap, data_fd, n_data, p)) {
+-                                error(p, "invalid data object at hash entry %"PRIu64" of %"PRIu64,
+-                                      i, n);
++                                error(p, "Invalid data object at hash entry %"PRIu64" of %"PRIu64, i, n);
+                                 return -EBADMSG;
+                         }
+ 
+@@ -622,14 +616,12 @@ static int verify_hash_table(
+ 
+                         next = le64toh(o->data.next_hash_offset);
+                         if (next != 0 && next <= p) {
+-                                error(p, "hash chain has a cycle in hash entry %"PRIu64" of %"PRIu64,
+-                                      i, n);
++                                error(p, "Hash chain has a cycle in hash entry %"PRIu64" of %"PRIu64, i, n);
+                                 return -EBADMSG;
+                         }
+ 
+                         if (le64toh(o->data.hash) % n != i) {
+-                                error(p, "hash value mismatch in hash entry %"PRIu64" of %"PRIu64,
+-                                      i, n);
++                                error(p, "Hash value mismatch in hash entry %"PRIu64" of %"PRIu64, i, n);
+                                 return -EBADMSG;
+                         }
+ 
+@@ -642,7 +634,7 @@ static int verify_hash_table(
+                 }
+ 
+                 if (last != le64toh(f->data_hash_table[i].tail_hash_offset)) {
+-                        error(p, "tail hash pointer mismatch in hash table");
++                        error(p, "Tail hash pointer mismatch in hash table");
+                         return -EBADMSG;
+                 }
+         }
+@@ -703,16 +695,16 @@ static int verify_entry(
+                 h = le64toh(o->entry.items[i].hash);
+ 
+                 if (!contains_uint64(f->mmap, data_fd, n_data, q)) {
+-                        error(p, "invalid data object of entry");
+-                                return -EBADMSG;
+-                        }
++                        error(p, "Invalid data object of entry");
++                        return -EBADMSG;
++                }
+ 
+                 r = journal_file_move_to_object(f, OBJECT_DATA, q, &u);
+                 if (r < 0)
+                         return r;
+ 
+                 if (le64toh(u->data.hash) != h) {
+-                        error(p, "hash mismatch for data object of entry");
++                        error(p, "Hash mismatch for data object of entry");
+                         return -EBADMSG;
+                 }
+ 
+@@ -720,7 +712,7 @@ static int verify_entry(
+                 if (r < 0)
+                         return r;
+                 if (r == 0) {
+-                        error(p, "data object missing from hash table");
++                        error(p, "Data object missing from hash table");
+                         return -EBADMSG;
+                 }
+         }
+@@ -755,12 +747,12 @@ static int verify_entry_array(
+                         draw_progress(0x8000 + scale_progress(0x3FFF, i, n), last_usec);
+ 
+                 if (a == 0) {
+-                        error(a, "array chain too short at %"PRIu64" of %"PRIu64, i, n);
++                        error(a, "Array chain too short at %"PRIu64" of %"PRIu64, i, n);
+                         return -EBADMSG;
+                 }
+ 
+                 if (!contains_uint64(f->mmap, entry_array_fd, n_entry_arrays, a)) {
+-                        error(a, "invalid array %"PRIu64" of %"PRIu64, i, n);
++                        error(a, "Invalid array %"PRIu64" of %"PRIu64, i, n);
+                         return -EBADMSG;
+                 }
+ 
+@@ -770,9 +762,7 @@ static int verify_entry_array(
+ 
+                 next = le64toh(o->entry_array.next_entry_array_offset);
+                 if (next != 0 && next <= a) {
+-                        error(a,
+-                              "array chain has cycle at %"PRIu64" of %"PRIu64" (jumps back from to "OFSfmt")",
+-                              i, n, next);
++                        error(a, "Array chain has cycle at %"PRIu64" of %"PRIu64" (jumps back from to "OFSfmt")", i, n, next);
+                         return -EBADMSG;
+                 }
+ 
+@@ -782,15 +772,13 @@ static int verify_entry_array(
+ 
+                         p = le64toh(o->entry_array.items[j]);
+                         if (p <= last) {
+-                                error(a, "entry array not sorted at %"PRIu64" of %"PRIu64,
+-                                      i, n);
++                                error(a, "Entry array not sorted at %"PRIu64" of %"PRIu64, i, n);
+                                 return -EBADMSG;
+                         }
+                         last = p;
+ 
+                         if (!contains_uint64(f->mmap, entry_fd, n_entries, p)) {
+-                                error(a, "invalid array entry at %"PRIu64" of %"PRIu64,
+-                                      i, n);
++                                error(a, "Invalid array entry at %"PRIu64" of %"PRIu64, i, n);
+                                 return -EBADMSG;
+                         }
+ 
+@@ -878,7 +866,7 @@ int journal_file_verify(
+ 
+         for (i = 0; i < sizeof(f->header->reserved); i++)
+                 if (f->header->reserved[i] != 0) {
+-                        error(offsetof(Header, reserved[i]), "reserved field is non-zero");
++                        error(offsetof(Header, reserved[i]), "Reserved field is non-zero");
+                         r = -EBADMSG;
+                         goto fail;
+                 }
+@@ -897,12 +885,12 @@ int journal_file_verify(
+ 
+                 r = journal_file_move_to_object(f, OBJECT_UNUSED, p, &o);
+                 if (r < 0) {
+-                        error(p, "invalid object");
++                        error(p, "Invalid object");
+                         goto fail;
+                 }
+ 
+                 if (p > le64toh(f->header->tail_object_offset)) {
+-                        error(offsetof(Header, tail_object_offset), "invalid tail object pointer");
++                        error(offsetof(Header, tail_object_offset), "Invalid tail object pointer");
+                         r = -EBADMSG;
+                         goto fail;
+                 }
+@@ -911,13 +899,13 @@ int journal_file_verify(
+ 
+                 r = journal_file_object_verify(f, p, o);
+                 if (r < 0) {
+-                        error(p, "invalid object contents: %s", strerror(-r));
++                        error(p, "Envalid object contents: %s", strerror(-r));
+                         goto fail;
+                 }
+ 
+                 if ((o->object.flags & OBJECT_COMPRESSED_XZ) &&
+                     (o->object.flags & OBJECT_COMPRESSED_LZ4)) {
+-                        error(p, "objected with double compression");
++                        error(p, "Objected with double compression");
+                         r = -EINVAL;
+                         goto fail;
+                 }
+@@ -950,7 +938,7 @@ int journal_file_verify(
+ 
+                 case OBJECT_ENTRY:
+                         if (JOURNAL_HEADER_SEALED(f->header) && n_tags <= 0) {
+-                                error(p, "first entry before first tag");
++                                error(p, "First entry before first tag");
+                                 r = -EBADMSG;
+                                 goto fail;
+                         }
+@@ -960,21 +948,21 @@ int journal_file_verify(
+                                 goto fail;
+ 
+                         if (le64toh(o->entry.realtime) < last_tag_realtime) {
+-                                error(p, "older entry after newer tag");
++                                error(p, "Older entry after newer tag");
+                                 r = -EBADMSG;
+                                 goto fail;
+                         }
+ 
+                         if (!entry_seqnum_set &&
+                             le64toh(o->entry.seqnum) != le64toh(f->header->head_entry_seqnum)) {
+-                                error(p, "head entry sequence number incorrect");
++                                error(p, "Head entry sequence number incorrect");
+                                 r = -EBADMSG;
+                                 goto fail;
+                         }
+ 
+                         if (entry_seqnum_set &&
+                             entry_seqnum >= le64toh(o->entry.seqnum)) {
+-                                error(p, "entry sequence number out of synchronization");
++                                error(p, "Entry sequence number out of synchronization");
+                                 r = -EBADMSG;
+                                 goto fail;
+                         }
+@@ -985,7 +973,7 @@ int journal_file_verify(
+                         if (entry_monotonic_set &&
+                             sd_id128_equal(entry_boot_id, o->entry.boot_id) &&
+                             entry_monotonic > le64toh(o->entry.monotonic)) {
+-                                error(p, "entry timestamp out of synchronization");
++                                error(p, "Entry timestamp out of synchronization");
+                                 r = -EBADMSG;
+                                 goto fail;
+                         }
+@@ -996,7 +984,7 @@ int journal_file_verify(
+ 
+                         if (!entry_realtime_set &&
+                             le64toh(o->entry.realtime) != le64toh(f->header->head_entry_realtime)) {
+-                                error(p, "head entry realtime timestamp incorrect");
++                                error(p, "Head entry realtime timestamp incorrect");
+                                 r = -EBADMSG;
+                                 goto fail;
+                         }
+@@ -1009,7 +997,7 @@ int journal_file_verify(
+ 
+                 case OBJECT_DATA_HASH_TABLE:
+                         if (n_data_hash_tables > 1) {
+-                                error(p, "more than one data hash table");
++                                error(p, "More than one data hash table");
+                                 r = -EBADMSG;
+                                 goto fail;
+                         }
+@@ -1026,14 +1014,14 @@ int journal_file_verify(
+ 
+                 case OBJECT_FIELD_HASH_TABLE:
+                         if (n_field_hash_tables > 1) {
+-                                error(p, "more than one field hash table");
++                                error(p, "More than one field hash table");
+                                 r = -EBADMSG;
+                                 goto fail;
+                         }
+ 
+                         if (le64toh(f->header->field_hash_table_offset) != p + offsetof(HashTableObject, items) ||
+                             le64toh(f->header->field_hash_table_size) != le64toh(o->object.size) - offsetof(HashTableObject, items)) {
+-                                error(p, "header fields for field hash table invalid");
++                                error(p, "Header fields for field hash table invalid");
+                                 r = -EBADMSG;
+                                 goto fail;
+                         }
+@@ -1048,7 +1036,7 @@ int journal_file_verify(
+ 
+                         if (p == le64toh(f->header->entry_array_offset)) {
+                                 if (found_main_entry_array) {
+-                                        error(p, "more than one main entry array");
++                                        error(p, "More than one main entry array");
+                                         r = -EBADMSG;
+                                         goto fail;
+                                 }
+@@ -1061,19 +1049,19 @@ int journal_file_verify(
+ 
+                 case OBJECT_TAG:
+                         if (!JOURNAL_HEADER_SEALED(f->header)) {
+-                                error(p, "tag object in file without sealing");
++                                error(p, "Tag object in file without sealing");
+                                 r = -EBADMSG;
+                                 goto fail;
+                         }
+ 
+                         if (le64toh(o->tag.seqnum) != n_tags + 1) {
+-                                error(p, "tag sequence number out of synchronization");
++                                error(p, "Tag sequence number out of synchronization");
+                                 r = -EBADMSG;
+                                 goto fail;
+                         }
+ 
+                         if (le64toh(o->tag.epoch) < last_epoch) {
+-                                error(p, "epoch sequence out of synchronization");
++                                error(p, "Epoch sequence out of synchronization");
+                                 r = -EBADMSG;
+                                 goto fail;
+                         }
+@@ -1082,7 +1070,7 @@ int journal_file_verify(
+                         if (f->seal) {
+                                 uint64_t q, rt;
+ 
+-                                debug(p, "checking tag %"PRIu64"...", le64toh(o->tag.seqnum));
++                                debug(p, "Checking tag %"PRIu64"...", le64toh(o->tag.seqnum));
+ 
+                                 rt = f->fss_start_usec + o->tag.epoch * f->fss_interval_usec;
+                                 if (entry_realtime_set && entry_realtime >= rt + f->fss_interval_usec) {
+@@ -1129,7 +1117,7 @@ int journal_file_verify(
+                                         goto fail;
+ 
+                                 if (memcmp(o->tag.tag, gcry_md_read(f->hmac, 0), TAG_LENGTH) != 0) {
+-                                        error(p, "tag failed verification");
++                                        error(p, "Tag failed verification");
+                                         r = -EBADMSG;
+                                         goto fail;
+                                 }
+@@ -1160,60 +1148,60 @@ int journal_file_verify(
+         };
+ 
+         if (!found_last && le64toh(f->header->tail_object_offset) != 0) {
+-                error(le64toh(f->header->tail_object_offset), "tail object pointer dead");
++                error(le64toh(f->header->tail_object_offset), "Tail object pointer dead");
+                 r = -EBADMSG;
+                 goto fail;
+         }
+ 
+         if (n_objects != le64toh(f->header->n_objects)) {
+-                error(offsetof(Header, n_objects), "object number mismatch");
++                error(offsetof(Header, n_objects), "Object number mismatch");
+                 r = -EBADMSG;
+                 goto fail;
+         }
+ 
+         if (n_entries != le64toh(f->header->n_entries)) {
+-                error(offsetof(Header, n_entries), "entry number mismatch");
++                error(offsetof(Header, n_entries), "Entry number mismatch");
+                 r = -EBADMSG;
+                 goto fail;
+         }
+ 
+         if (JOURNAL_HEADER_CONTAINS(f->header, n_data) &&
+             n_data != le64toh(f->header->n_data)) {
+-                error(offsetof(Header, n_data), "data number mismatch");
++                error(offsetof(Header, n_data), "Data number mismatch");
+                 r = -EBADMSG;
+                 goto fail;
+         }
+ 
+         if (JOURNAL_HEADER_CONTAINS(f->header, n_fields) &&
+             n_fields != le64toh(f->header->n_fields)) {
+-                error(offsetof(Header, n_fields), "field number mismatch");
++                error(offsetof(Header, n_fields), "Field number mismatch");
+                 r = -EBADMSG;
+                 goto fail;
+         }
+ 
+         if (JOURNAL_HEADER_CONTAINS(f->header, n_tags) &&
+             n_tags != le64toh(f->header->n_tags)) {
+-                error(offsetof(Header, n_tags), "tag number mismatch");
++                error(offsetof(Header, n_tags), "Tag number mismatch");
+                 r = -EBADMSG;
+                 goto fail;
+         }
+ 
+         if (JOURNAL_HEADER_CONTAINS(f->header, n_entry_arrays) &&
+             n_entry_arrays != le64toh(f->header->n_entry_arrays)) {
+-                error(offsetof(Header, n_entry_arrays), "entry array number mismatch");
++                error(offsetof(Header, n_entry_arrays), "Entry array number mismatch");
+                 r = -EBADMSG;
+                 goto fail;
+         }
+ 
+         if (!found_main_entry_array && le64toh(f->header->entry_array_offset) != 0) {
+-                error(0, "missing entry array");
++                error(0, "Missing entry array");
+                 r = -EBADMSG;
+                 goto fail;
+         }
+ 
+         if (entry_seqnum_set &&
+             entry_seqnum != le64toh(f->header->tail_entry_seqnum)) {
+-                error(offsetof(Header, tail_entry_seqnum), "invalid tail seqnum");
++                error(offsetof(Header, tail_entry_seqnum), "Invalid tail seqnum");
+                 r = -EBADMSG;
+                 goto fail;
+         }
+@@ -1221,13 +1209,13 @@ int journal_file_verify(
+         if (entry_monotonic_set &&
+             (!sd_id128_equal(entry_boot_id, f->header->boot_id) ||
+              entry_monotonic != le64toh(f->header->tail_entry_monotonic))) {
+-                error(0, "invalid tail monotonic timestamp");
++                error(0, "Invalid tail monotonic timestamp");
+                 r = -EBADMSG;
+                 goto fail;
+         }
+ 
+         if (entry_realtime_set && entry_realtime != le64toh(f->header->tail_entry_realtime)) {
+-                error(0, "invalid tail realtime timestamp");
++                error(0, "Invalid tail realtime timestamp");
+                 r = -EBADMSG;
+                 goto fail;
+         }
diff --git a/SOURCES/0350-journalctl-make-sure-journalctl-f-t-unmatched-blocks.patch b/SOURCES/0350-journalctl-make-sure-journalctl-f-t-unmatched-blocks.patch
new file mode 100644
index 0000000..7de0a54
--- /dev/null
+++ b/SOURCES/0350-journalctl-make-sure-journalctl-f-t-unmatched-blocks.patch
@@ -0,0 +1,48 @@
+From 3045db86f9185f6de78f85099159330dfc1a0e9e Mon Sep 17 00:00:00 2001
+From: Stef Walter <stefw@redhat.com>
+Date: Fri, 14 Aug 2015 16:38:41 +0200
+Subject: [PATCH] journalctl: make sure 'journalctl -f -t unmatched' blocks
+
+Previously the following command:
+
+$ journalctl -f -t unmatchedtag12345
+
+... would block when called with criteria that did not match any
+journal lines. Once log lines appeared that matched the criteria
+they were displayed.
+
+Commit 02ab86c732576a71179ce12e97d44c289833236d broke this
+behavior and the journal was not followed, but the command
+exits with '-- No entries --' displayed.
+
+This commit fixes the issue.
+
+More information downstream:
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1253649
+
+Cherry-picked from: c51e1a96359b3f4d374345593b11273df2132b93
+Related: #1350232
+---
+ src/journal/journalctl.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
+index 904aae9..2688d8b 100644
+--- a/src/journal/journalctl.c
++++ b/src/journal/journalctl.c
+@@ -2142,8 +2142,12 @@ int main(int argc, char *argv[]) {
+         }
+ 
+         if (r == 0) {
+-                printf("-- No entries --\n");
+-                return EXIT_SUCCESS;
++                if (arg_follow)
++                        need_seek = true;
++                else {
++                        printf("-- No entries --\n");
++                        return EXIT_SUCCESS;
++                }
+         }
+ 
+ 
diff --git a/SOURCES/0351-journalctl-don-t-print-No-entries-in-quiet-mode.patch b/SOURCES/0351-journalctl-don-t-print-No-entries-in-quiet-mode.patch
new file mode 100644
index 0000000..2478c48
--- /dev/null
+++ b/SOURCES/0351-journalctl-don-t-print-No-entries-in-quiet-mode.patch
@@ -0,0 +1,25 @@
+From 13f24902c7c1ba91d41bf4e8dd694cf01f876938 Mon Sep 17 00:00:00 2001
+From: Evgeny Vereshchagin <evvers@ya.ru>
+Date: Tue, 17 Nov 2015 06:06:52 +0000
+Subject: [PATCH] journalctl: don't print -- No entries -- in quiet mode
+
+Cherry-picked from: bfcb7c5f5333f9c3523b7027c2ad4c99e4494fb5
+Related: #1350232
+---
+ src/journal/journalctl.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
+index 2688d8b..a38ce4b 100644
+--- a/src/journal/journalctl.c
++++ b/src/journal/journalctl.c
+@@ -2145,7 +2145,8 @@ int main(int argc, char *argv[]) {
+                 if (arg_follow)
+                         need_seek = true;
+                 else {
+-                        printf("-- No entries --\n");
++                        if (!arg_quiet)
++                                printf("-- No entries --\n");
+                         return EXIT_SUCCESS;
+                 }
+         }
diff --git a/SOURCES/0352-sd-event-expose-the-event-loop-iteration-counter-via.patch b/SOURCES/0352-sd-event-expose-the-event-loop-iteration-counter-via.patch
new file mode 100644
index 0000000..79865b4
--- /dev/null
+++ b/SOURCES/0352-sd-event-expose-the-event-loop-iteration-counter-via.patch
@@ -0,0 +1,69 @@
+From 8fe5d9138039aafd314340b12d6d586d657d53a7 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Wed, 29 Jun 2016 19:03:26 -0700
+Subject: [PATCH] sd-event: expose the event loop iteration counter via
+ sd_event_get_iteration()
+
+This extends the existing event loop iteration counter to 64bit, and exposes it
+via a new function sd_event_get_iteration(). This is helpful for cases like
+issue #3612. After all, since we maintain the counter anyway, we might as well
+expose it.
+
+(This also fixes an unrelated issue in the man page for sd_event_wait() where
+micro and milliseconds got mixed up)
+
+Cherry-picked from: 7486322b99da5b4d2d00d35b310b035f936f7964
+Related: #1342173
+---
+ src/libsystemd/sd-event/sd-event.c | 14 +++++++++++---
+ src/systemd/sd-event.h             |  1 +
+ 2 files changed, 12 insertions(+), 3 deletions(-)
+
+diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c
+index 1f1e6fe..9d48e5a 100644
+--- a/src/libsystemd/sd-event/sd-event.c
++++ b/src/libsystemd/sd-event/sd-event.c
+@@ -76,8 +76,8 @@ struct sd_event_source {
+         int64_t priority;
+         unsigned pending_index;
+         unsigned prepare_index;
+-        unsigned pending_iteration;
+-        unsigned prepare_iteration;
++        uint64_t pending_iteration;
++        uint64_t prepare_iteration;
+ 
+         LIST_FIELDS(sd_event_source, sources);
+ 
+@@ -169,7 +169,7 @@ struct sd_event {
+ 
+         pid_t original_pid;
+ 
+-        unsigned iteration;
++        uint64_t iteration;
+         dual_timestamp timestamp;
+         usec_t timestamp_boottime;
+         int state;
+@@ -2689,3 +2689,11 @@ _public_ int sd_event_get_watchdog(sd_event *e) {
+ 
+         return e->watchdog;
+ }
++
++_public_ int sd_event_get_iteration(sd_event *e, uint64_t *ret) {
++        assert_return(e, -EINVAL);
++        assert_return(!event_pid_changed(e), -ECHILD);
++
++        *ret = e->iteration;
++        return 0;
++}
+diff --git a/src/systemd/sd-event.h b/src/systemd/sd-event.h
+index 25a10f9..4957f3a 100644
+--- a/src/systemd/sd-event.h
++++ b/src/systemd/sd-event.h
+@@ -101,6 +101,7 @@ int sd_event_get_tid(sd_event *e, pid_t *tid);
+ int sd_event_get_exit_code(sd_event *e, int *code);
+ int sd_event_set_watchdog(sd_event *e, int b);
+ int sd_event_get_watchdog(sd_event *e);
++int sd_event_get_iteration(sd_event *e, uint64_t *ret);
+ 
+ sd_event_source* sd_event_source_ref(sd_event_source *s);
+ sd_event_source* sd_event_source_unref(sd_event_source *s);
diff --git a/SOURCES/0353-manager-Only-invoke-a-single-sigchld-per-unit-within.patch b/SOURCES/0353-manager-Only-invoke-a-single-sigchld-per-unit-within.patch
new file mode 100644
index 0000000..962c65f
--- /dev/null
+++ b/SOURCES/0353-manager-Only-invoke-a-single-sigchld-per-unit-within.patch
@@ -0,0 +1,85 @@
+From 2a0feeb4252cbf1207f45e978fe7eb02bb0182ec Mon Sep 17 00:00:00 2001
+From: Kyle Walker <walker.kyle.t@gmail.com>
+Date: Thu, 30 Jun 2016 15:12:18 -0400
+Subject: [PATCH] manager: Only invoke a single sigchld per unit within a
+ cleanup cycle
+
+By default, each iteration of manager_dispatch_sigchld() results in a unit level
+sigchld event being invoked. For scope units, this results in a scope_sigchld_event()
+which can seemingly stall for workloads that have a large number of PIDs within the
+scope. The stall exhibits itself as a SIG_0 being initiated for each u->pids entry
+as a result of pid_is_unwaited().
+
+v2:
+This patch resolves this condition by only paying to cost of a sigchld in the underlying
+scope unit once per sigchld iteration. A new "sigchldgen" member resides within the
+Unit struct. The Manager is incremented via the sd event loop, accessed via
+sd_event_get_iteration, and the Unit member is set to the same value as the manager each
+time that a sigchld event is invoked. If the Manager iteration value and Unit member
+match, the sigchld event is not invoked for that iteration.
+
+Cherry-picked from: 36f20ae3b2975e44b6ef17e453ae06a289e9a122
+Resolves: #1342173
+---
+ src/core/manager.c | 13 ++++++++++++-
+ src/core/unit.c    |  1 +
+ src/core/unit.h    |  3 +++
+ 3 files changed, 16 insertions(+), 1 deletion(-)
+
+diff --git a/src/core/manager.c b/src/core/manager.c
+index e5226a8..63693b9 100644
+--- a/src/core/manager.c
++++ b/src/core/manager.c
+@@ -1747,14 +1747,25 @@ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t
+ }
+ 
+ static void invoke_sigchld_event(Manager *m, Unit *u, siginfo_t *si) {
++        uint64_t iteration;
++        
+         assert(m);
+         assert(u);
+         assert(si);
+ 
++        sd_event_get_iteration(m->event, &iteration);
++
+         log_unit_debug(u->id, "Child "PID_FMT" belongs to %s", si->si_pid, u->id);
+ 
+         unit_unwatch_pid(u, si->si_pid);
+-        UNIT_VTABLE(u)->sigchld_event(u, si->si_pid, si->si_code, si->si_status);
++
++        if (UNIT_VTABLE(u)->sigchld_event) {
++                if (set_size(u->pids) <= 1 || iteration != u->sigchldgen) {
++                        UNIT_VTABLE(u)->sigchld_event(u, si->si_pid, si->si_code, si->si_status);
++                        u->sigchldgen = iteration;
++                } else
++                        log_debug("%s already issued a sigchld this iteration %llu, skipping. Pids still being watched %d", u->id, iteration, set_size(u->pids));
++        }
+ }
+ 
+ static int manager_dispatch_sigchld(Manager *m) {
+diff --git a/src/core/unit.c b/src/core/unit.c
+index d6ead7d..d62135d 100644
+--- a/src/core/unit.c
++++ b/src/core/unit.c
+@@ -94,6 +94,7 @@ Unit *unit_new(Manager *m, size_t size) {
+         u->unit_file_state = _UNIT_FILE_STATE_INVALID;
+         u->unit_file_preset = -1;
+         u->on_failure_job_mode = JOB_REPLACE;
++        u->sigchldgen = 0;
+ 
+         return u;
+ }
+diff --git a/src/core/unit.h b/src/core/unit.h
+index 0eebc0b..d936457 100644
+--- a/src/core/unit.h
++++ b/src/core/unit.h
+@@ -167,6 +167,9 @@ struct Unit {
+          * process SIGCHLD for */
+         Set *pids;
+ 
++        /* Used in sigchld event invocation to avoid repeat events being invoked */
++        uint64_t sigchldgen;
++
+         /* Used during GC sweeps */
+         unsigned gc_marker;
+ 
diff --git a/SOURCES/0354-manager-Fixing-a-debug-printf-formatting-mistake.patch b/SOURCES/0354-manager-Fixing-a-debug-printf-formatting-mistake.patch
new file mode 100644
index 0000000..7d91382
--- /dev/null
+++ b/SOURCES/0354-manager-Fixing-a-debug-printf-formatting-mistake.patch
@@ -0,0 +1,28 @@
+From 1a6aae42bb3c4e524ded2da53afa303dd479b877 Mon Sep 17 00:00:00 2001
+From: Kyle Walker <walker.kyle.t@gmail.com>
+Date: Fri, 1 Jul 2016 10:04:40 -0400
+Subject: [PATCH] manager: Fixing a debug printf formatting mistake
+
+A 'llu' formatting statement was used in a debugging printf statement
+instead of a 'PRIu64'. Correcting that mistake here.
+
+Cherry-picked from: 72b0c3f59695239c51b719576f625e789bd00a66
+Related: #1342173
+---
+ src/core/manager.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/src/core/manager.c b/src/core/manager.c
+index 63693b9..d168777 100644
+--- a/src/core/manager.c
++++ b/src/core/manager.c
+@@ -1764,7 +1764,8 @@ static void invoke_sigchld_event(Manager *m, Unit *u, siginfo_t *si) {
+                         UNIT_VTABLE(u)->sigchld_event(u, si->si_pid, si->si_code, si->si_status);
+                         u->sigchldgen = iteration;
+                 } else
+-                        log_debug("%s already issued a sigchld this iteration %llu, skipping. Pids still being watched %d", u->id, iteration, set_size(u->pids));
++                        log_debug("%s already issued a sigchld this iteration %" PRIu64 ", skipping. Pids still being watched %d", u->id, iteration, set_size(u->pids));
++
+         }
+ }
+ 
diff --git a/SOURCES/0355-core-support-IEC-suffixes-for-RLIMIT-stuff.patch b/SOURCES/0355-core-support-IEC-suffixes-for-RLIMIT-stuff.patch
new file mode 100644
index 0000000..7791eba
--- /dev/null
+++ b/SOURCES/0355-core-support-IEC-suffixes-for-RLIMIT-stuff.patch
@@ -0,0 +1,191 @@
+From 99074eebc911728a41167c1962231e11b5e3cddd Mon Sep 17 00:00:00 2001
+From: Karel Zak <kzak@redhat.com>
+Date: Fri, 6 Nov 2015 11:06:52 +0100
+Subject: [PATCH] core: support IEC suffixes for RLIMIT stuff
+
+Let's make things more user-friendly and support for example
+
+  LimitAS=16G
+
+rather than force users to always use LimitAS=16106127360.
+
+The change is relevant for options:
+
+  [Default]Limit{FSIZE,DATA,STACK,CORE,RSS,AS,MEMLOCK,MSGQUEUE}
+
+The patch introduces config_parse_bytes_limit(), it's the same as
+config_parse_limit() but uses parse_size() tu support the suffixes.
+
+Addresses: https://github.com/systemd/systemd/issues/1772
+
+Cherry-picked from: 412ea7a936ebaa5342a4c2abf48b9e408e6ba5dc
+Related: #1351415
+---
+ man/systemd-system.conf.xml           |  6 +++--
+ man/systemd.exec.xml                  |  4 +++-
+ src/core/load-fragment-gperf.gperf.m4 | 16 ++++++-------
+ src/core/load-fragment.c              | 43 +++++++++++++++++++++++++++++++++++
+ src/core/load-fragment.h              |  1 +
+ src/core/main.c                       | 16 ++++++-------
+ 6 files changed, 67 insertions(+), 19 deletions(-)
+
+diff --git a/man/systemd-system.conf.xml b/man/systemd-system.conf.xml
+index ca25c93..b7d9cde 100644
+--- a/man/systemd-system.conf.xml
++++ b/man/systemd-system.conf.xml
+@@ -327,8 +327,10 @@
+         resource limits for units. See
+         <citerefentry><refentrytitle>setrlimit</refentrytitle><manvolnum>2</manvolnum></citerefentry>
+         for details. Use the string <varname>infinity</varname> to
+-        configure no limit on a specific resource. These settings may
+-        be overridden in individual units using the corresponding
++        configure no limit on a specific resource. The multiplicative suffixes
++        K (=1024), M (=1024*1024) and so on for G, T, P and E may be used for
++        resource limits measured in bytes (e.g. DefaultLimitAS=16G). These
++        settings may be overridden in individual units using the corresponding
+         LimitXXX= directives. Note that these resource limits are only
+         defaults for units, they are not applied to PID 1
+         itself.</para></listitem>
+diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml
+index 6af7c7a..25aea16 100644
+--- a/man/systemd.exec.xml
++++ b/man/systemd.exec.xml
+@@ -559,7 +559,9 @@
+         of various resources for executed processes. See
+         <citerefentry><refentrytitle>setrlimit</refentrytitle><manvolnum>2</manvolnum></citerefentry>
+         for details. Use the string <varname>infinity</varname> to
+-        configure no limit on a specific resource.</para></listitem>
++        configure no limit on a specific resource. The multiplicative suffixes
++        K (=1024), M (=1024*1024) and so on for G, T, P and E may be used for
++        resource limits measured in bytes (e.g. LimitAS=16G).</para></listitem>
+ 
+         <table>
+           <title>Limit directives and their equivalent with ulimit</title>
+diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
+index 85d9797..c3461a0 100644
+--- a/src/core/load-fragment-gperf.gperf.m4
++++ b/src/core/load-fragment-gperf.gperf.m4
+@@ -59,18 +59,18 @@ $1.SystemCallArchitectures,      config_parse_warn_compat,           DISABLED_CO
+ $1.SystemCallErrorNumber,        config_parse_warn_compat,           DISABLED_CONFIGURATION,        0
+ $1.RestrictAddressFamilies,      config_parse_warn_compat,           DISABLED_CONFIGURATION,        0')
+ $1.LimitCPU,                     config_parse_limit,                 RLIMIT_CPU,                    offsetof($1, exec_context.rlimit)
+-$1.LimitFSIZE,                   config_parse_limit,                 RLIMIT_FSIZE,                  offsetof($1, exec_context.rlimit)
+-$1.LimitDATA,                    config_parse_limit,                 RLIMIT_DATA,                   offsetof($1, exec_context.rlimit)
+-$1.LimitSTACK,                   config_parse_limit,                 RLIMIT_STACK,                  offsetof($1, exec_context.rlimit)
+-$1.LimitCORE,                    config_parse_limit,                 RLIMIT_CORE,                   offsetof($1, exec_context.rlimit)
+-$1.LimitRSS,                     config_parse_limit,                 RLIMIT_RSS,                    offsetof($1, exec_context.rlimit)
++$1.LimitFSIZE,                   config_parse_bytes_limit,           RLIMIT_FSIZE,                  offsetof($1, exec_context.rlimit)
++$1.LimitDATA,                    config_parse_bytes_limit,           RLIMIT_DATA,                   offsetof($1, exec_context.rlimit)
++$1.LimitSTACK,                   config_parse_bytes_limit,           RLIMIT_STACK,                  offsetof($1, exec_context.rlimit)
++$1.LimitCORE,                    config_parse_bytes_limit,           RLIMIT_CORE,                   offsetof($1, exec_context.rlimit)
++$1.LimitRSS,                     config_parse_bytes_limit,           RLIMIT_RSS,                    offsetof($1, exec_context.rlimit)
+ $1.LimitNOFILE,                  config_parse_limit,                 RLIMIT_NOFILE,                 offsetof($1, exec_context.rlimit)
+-$1.LimitAS,                      config_parse_limit,                 RLIMIT_AS,                     offsetof($1, exec_context.rlimit)
++$1.LimitAS,                      config_parse_bytes_limit,           RLIMIT_AS,                     offsetof($1, exec_context.rlimit)
+ $1.LimitNPROC,                   config_parse_limit,                 RLIMIT_NPROC,                  offsetof($1, exec_context.rlimit)
+-$1.LimitMEMLOCK,                 config_parse_limit,                 RLIMIT_MEMLOCK,                offsetof($1, exec_context.rlimit)
++$1.LimitMEMLOCK,                 config_parse_bytes_limit,           RLIMIT_MEMLOCK,                offsetof($1, exec_context.rlimit)
+ $1.LimitLOCKS,                   config_parse_limit,                 RLIMIT_LOCKS,                  offsetof($1, exec_context.rlimit)
+ $1.LimitSIGPENDING,              config_parse_limit,                 RLIMIT_SIGPENDING,             offsetof($1, exec_context.rlimit)
+-$1.LimitMSGQUEUE,                config_parse_limit,                 RLIMIT_MSGQUEUE,               offsetof($1, exec_context.rlimit)
++$1.LimitMSGQUEUE,                config_parse_bytes_limit,           RLIMIT_MSGQUEUE,               offsetof($1, exec_context.rlimit)
+ $1.LimitNICE,                    config_parse_limit,                 RLIMIT_NICE,                   offsetof($1, exec_context.rlimit)
+ $1.LimitRTPRIO,                  config_parse_limit,                 RLIMIT_RTPRIO,                 offsetof($1, exec_context.rlimit)
+ $1.LimitRTTIME,                  config_parse_limit,                 RLIMIT_RTTIME,                 offsetof($1, exec_context.rlimit)
+diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
+index b188ec9..dbb45b2 100644
+--- a/src/core/load-fragment.c
++++ b/src/core/load-fragment.c
+@@ -1119,6 +1119,49 @@ int config_parse_limit(const char *unit,
+         return 0;
+ }
+ 
++int config_parse_bytes_limit(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) {
++
++        struct rlimit **rl = data;
++        uint64_t bytes;
++
++        assert(filename);
++        assert(lvalue);
++        assert(rvalue);
++        assert(data);
++
++        rl += ltype;
++
++        if (streq(rvalue, "infinity"))
++                bytes = (uint64_t) RLIM_INFINITY;
++        else {
++                int r;
++
++                r = parse_size(rvalue, 1024, &bytes);
++                if (r < 0) {
++                        log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse resource value, ignoring: %s", rvalue);
++                        return 0;
++                }
++        }
++
++        if (!*rl) {
++                *rl = new(struct rlimit, 1);
++                if (!*rl)
++                        return log_oom();
++        }
++
++        (*rl)->rlim_cur = (*rl)->rlim_max = (rlim_t) bytes;
++        return 0;
++}
++
+ #ifdef HAVE_SYSV_COMPAT
+ int config_parse_sysv_priority(const char *unit,
+                                const char *filename,
+diff --git a/src/core/load-fragment.h b/src/core/load-fragment.h
+index ce10d03..2d509d0 100644
+--- a/src/core/load-fragment.h
++++ b/src/core/load-fragment.h
+@@ -56,6 +56,7 @@ int config_parse_exec_capabilities(const char *unit, const char *filename, unsig
+ int config_parse_exec_secure_bits(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_bounding_set(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_limit(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_bytes_limit(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_sysv_priority(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_kill_signal(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_exec_mount_flags(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);
+diff --git a/src/core/main.c b/src/core/main.c
+index 2aec40b..60ea36c 100644
+--- a/src/core/main.c
++++ b/src/core/main.c
+@@ -655,18 +655,18 @@ static int parse_config_file(void) {
+                 { "Manager", "DefaultStartLimitBurst",    config_parse_unsigned,         0, &arg_default_start_limit_burst         },
+                 { "Manager", "DefaultEnvironment",        config_parse_environ,          0, &arg_default_environment               },
+                 { "Manager", "DefaultLimitCPU",           config_parse_limit,            0, &arg_default_rlimit[RLIMIT_CPU]        },
+-                { "Manager", "DefaultLimitFSIZE",         config_parse_limit,            0, &arg_default_rlimit[RLIMIT_FSIZE]      },
+-                { "Manager", "DefaultLimitDATA",          config_parse_limit,            0, &arg_default_rlimit[RLIMIT_DATA]       },
+-                { "Manager", "DefaultLimitSTACK",         config_parse_limit,            0, &arg_default_rlimit[RLIMIT_STACK]      },
+-                { "Manager", "DefaultLimitCORE",          config_parse_limit,            0, &arg_default_rlimit[RLIMIT_CORE]       },
+-                { "Manager", "DefaultLimitRSS",           config_parse_limit,            0, &arg_default_rlimit[RLIMIT_RSS]        },
++                { "Manager", "DefaultLimitFSIZE",         config_parse_bytes_limit,      0, &arg_default_rlimit[RLIMIT_FSIZE]      },
++                { "Manager", "DefaultLimitDATA",          config_parse_bytes_limit,      0, &arg_default_rlimit[RLIMIT_DATA]       },
++                { "Manager", "DefaultLimitSTACK",         config_parse_bytes_limit,      0, &arg_default_rlimit[RLIMIT_STACK]      },
++                { "Manager", "DefaultLimitCORE",          config_parse_bytes_limit,      0, &arg_default_rlimit[RLIMIT_CORE]       },
++                { "Manager", "DefaultLimitRSS",           config_parse_bytes_limit,      0, &arg_default_rlimit[RLIMIT_RSS]        },
+                 { "Manager", "DefaultLimitNOFILE",        config_parse_limit,            0, &arg_default_rlimit[RLIMIT_NOFILE]     },
+-                { "Manager", "DefaultLimitAS",            config_parse_limit,            0, &arg_default_rlimit[RLIMIT_AS]         },
++                { "Manager", "DefaultLimitAS",            config_parse_bytes_limit,      0, &arg_default_rlimit[RLIMIT_AS]         },
+                 { "Manager", "DefaultLimitNPROC",         config_parse_limit,            0, &arg_default_rlimit[RLIMIT_NPROC]      },
+-                { "Manager", "DefaultLimitMEMLOCK",       config_parse_limit,            0, &arg_default_rlimit[RLIMIT_MEMLOCK]    },
++                { "Manager", "DefaultLimitMEMLOCK",       config_parse_bytes_limit,      0, &arg_default_rlimit[RLIMIT_MEMLOCK]    },
+                 { "Manager", "DefaultLimitLOCKS",         config_parse_limit,            0, &arg_default_rlimit[RLIMIT_LOCKS]      },
+                 { "Manager", "DefaultLimitSIGPENDING",    config_parse_limit,            0, &arg_default_rlimit[RLIMIT_SIGPENDING] },
+-                { "Manager", "DefaultLimitMSGQUEUE",      config_parse_limit,            0, &arg_default_rlimit[RLIMIT_MSGQUEUE]   },
++                { "Manager", "DefaultLimitMSGQUEUE",      config_parse_bytes_limit,      0, &arg_default_rlimit[RLIMIT_MSGQUEUE]   },
+                 { "Manager", "DefaultLimitNICE",          config_parse_limit,            0, &arg_default_rlimit[RLIMIT_NICE]       },
+                 { "Manager", "DefaultLimitRTPRIO",        config_parse_limit,            0, &arg_default_rlimit[RLIMIT_RTPRIO]     },
+                 { "Manager", "DefaultLimitRTTIME",        config_parse_limit,            0, &arg_default_rlimit[RLIMIT_RTTIME]     },
diff --git a/SOURCES/0356-core-accept-time-units-for-time-based-resource-limit.patch b/SOURCES/0356-core-accept-time-units-for-time-based-resource-limit.patch
new file mode 100644
index 0000000..a0ce023
--- /dev/null
+++ b/SOURCES/0356-core-accept-time-units-for-time-based-resource-limit.patch
@@ -0,0 +1,416 @@
+From 128ef85392f68fa32650deab12d6cd2e01ad52cf Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Tue, 10 Nov 2015 16:52:52 +0100
+Subject: [PATCH] core: accept time units for time-based resource limits
+
+Let's make sure "LimitCPU=30min" can be parsed properly, following the
+usual logic how we parse time values. Similar for LimitRTTIME=.
+
+While we are at it, extend a bit on the man page section about resource
+limits.
+
+Fixes: #1772
+
+Cherry-picked from: a4c1800284e3546bbfab2dc19eb59bcb91c4a2ca
+Related: #1351415
+---
+ man/systemd.exec.xml                  |  86 ++++++++++++++++++++++-------
+ src/core/load-fragment-gperf.gperf.m4 |   4 +-
+ src/core/load-fragment.c              | 101 ++++++++++++++++++++++++++++++++++
+ src/core/load-fragment.h              |   2 +
+ src/test/test-unit-file.c             |  61 ++++++++++++++++++++
+ 5 files changed, 231 insertions(+), 23 deletions(-)
+
+diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml
+index 25aea16..cfdcc3d 100644
+--- a/man/systemd.exec.xml
++++ b/man/systemd.exec.xml
+@@ -559,90 +559,133 @@
+         of various resources for executed processes. See
+         <citerefentry><refentrytitle>setrlimit</refentrytitle><manvolnum>2</manvolnum></citerefentry>
+         for details. Use the string <varname>infinity</varname> to
+-        configure no limit on a specific resource. The multiplicative suffixes
+-        K (=1024), M (=1024*1024) and so on for G, T, P and E may be used for
+-        resource limits measured in bytes (e.g. LimitAS=16G).</para></listitem>
++        configure no limit on a specific resource. The multiplicative
++        suffixes K (=1024), M (=1024*1024) and so on for G, T, P and E
++        may be used for resource limits measured in bytes
++        (e.g. LimitAS=16G). For the limits referring to time values,
++        the usual time units ms, s, min, h and so on may be used (see
++        <citerefentry><refentrytitle>systemd.time</refentrytitle><manvolnum>7</manvolnum></citerefentry>
++        for details). Note that if no time unit is specified for
++        <varname>LimitCPU=</varname> the default unit of seconds is
++        implied, while for <varname>LimitRTTIME=</varname> the default
++        unit of microseconds is implied. Also, note that the effective
++        granularity of the limits might influence their
++        enforcement. For example, time limits specified for
++        <varname>LimitCPU=</varname> will be rounded up implicitly to
++        multiples of 1s.</para>
++
++        <para>Note that most process resource limits configured with
++        these options are per-process, and processes may fork in order
++        to acquire a new set of resources that are accounted
++        independently of the original process, and may thus escape
++        limits set. Also note that <varname>LimitRSS=</varname> is not
++        implemented on Linux, and setting it has no effect. Often it
++        is advisable to prefer the resource controls listed in
++        <citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>
++        over these per-process limits, as they apply to services as a
++        whole, may be altered dynamically at runtime, and are
++        generally more expressive. For example,
++        <varname>MemoryLimit=</varname> is a more powerful (and
++        working) replacement for <varname>LimitRSS=</varname>.</para>
+ 
+         <table>
+           <title>Limit directives and their equivalent with ulimit</title>
+ 
+-          <tgroup cols='2'>
++          <tgroup cols='3'>
+             <colspec colname='directive' />
+             <colspec colname='equivalent' />
++            <colspec colname='unit' />
+             <thead>
+               <row>
+                 <entry>Directive</entry>
+                 <entry>ulimit equivalent</entry>
++                <entry>Unit</entry>
+               </row>
+             </thead>
+             <tbody>
+               <row>
+-                <entry>LimitCPU</entry>
++                <entry>LimitCPU=</entry>
+                 <entry>ulimit -t</entry>
++                <entry>Seconds</entry>
+               </row>
+               <row>
+-                <entry>LimitFSIZE</entry>
++                <entry>LimitFSIZE=</entry>
+                 <entry>ulimit -f</entry>
++                <entry>Bytes</entry>
+               </row>
+               <row>
+-                <entry>LimitDATA</entry>
++                <entry>LimitDATA=</entry>
+                 <entry>ulimit -d</entry>
++                <entry>Bytes</entry>
+               </row>
+               <row>
+-                <entry>LimitSTACK</entry>
++                <entry>LimitSTACK=</entry>
+                 <entry>ulimit -s</entry>
++                <entry>Bytes</entry>
+               </row>
+               <row>
+-                <entry>LimitCORE</entry>
++                <entry>LimitCORE=</entry>
+                 <entry>ulimit -c</entry>
++                <entry>Bytes</entry>
+               </row>
+               <row>
+-                <entry>LimitRSS</entry>
++                <entry>LimitRSS=</entry>
+                 <entry>ulimit -m</entry>
++                <entry>Bytes</entry>
+               </row>
+               <row>
+-                <entry>LimitNOFILE</entry>
++                <entry>LimitNOFILE=</entry>
+                 <entry>ulimit -n</entry>
++                <entry>Number of File Descriptors</entry>
+               </row>
+               <row>
+-                <entry>LimitAS</entry>
++                <entry>LimitAS=</entry>
+                 <entry>ulimit -v</entry>
++                <entry>Bytes</entry>
+               </row>
+               <row>
+-                <entry>LimitNPROC</entry>
++                <entry>LimitNPROC=</entry>
+                 <entry>ulimit -u</entry>
++                <entry>Number of Processes</entry>
+               </row>
+               <row>
+-                <entry>LimitMEMLOCK</entry>
++                <entry>LimitMEMLOCK=</entry>
+                 <entry>ulimit -l</entry>
++                <entry>Bytes</entry>
+               </row>
+               <row>
+-                <entry>LimitLOCKS</entry>
++                <entry>LimitLOCKS=</entry>
+                 <entry>ulimit -x</entry>
++                <entry>Number of Locks</entry>
+               </row>
+               <row>
+-                <entry>LimitSIGPENDING</entry>
++                <entry>LimitSIGPENDING=</entry>
+                 <entry>ulimit -i</entry>
++                <entry>Number of Queued Signals</entry>
+               </row>
+               <row>
+-                <entry>LimitMSGQUEUE</entry>
++                <entry>LimitMSGQUEUE=</entry>
+                 <entry>ulimit -q</entry>
++                <entry>Bytes</entry>
+               </row>
+               <row>
+-                <entry>LimitNICE</entry>
++                <entry>LimitNICE=</entry>
+                 <entry>ulimit -e</entry>
++                <entry>Nice Level</entry>
+               </row>
+               <row>
+-                <entry>LimitRTPRIO</entry>
++                <entry>LimitRTPRIO=</entry>
+                 <entry>ulimit -r</entry>
++                <entry>Realtime Priority</entry>
+               </row>
+               <row>
+-                <entry>LimitRTTIME</entry>
++                <entry>LimitRTTIME=</entry>
+                 <entry>No equivalent</entry>
++                <entry>Microseconds</entry>
+               </row>
+             </tbody>
+           </tgroup>
+-        </table>
++        </table></listitem>
+       </varlistentry>
+ 
+       <varlistentry>
+@@ -1266,6 +1309,7 @@
+         <citerefentry><refentrytitle>systemd.mount</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+         <citerefentry><refentrytitle>systemd.kill</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+         <citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
++        <citerefentry><refentrytitle>systemd.time</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
+         <citerefentry><refentrytitle>systemd.directives</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
+         <citerefentry><refentrytitle>tmpfiles.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+         <citerefentry project='man-pages'><refentrytitle>exec</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
+index c3461a0..ce1397c 100644
+--- a/src/core/load-fragment-gperf.gperf.m4
++++ b/src/core/load-fragment-gperf.gperf.m4
+@@ -58,7 +58,7 @@ $1.RestrictAddressFamilies,      config_parse_address_families,      0,
+ $1.SystemCallArchitectures,      config_parse_warn_compat,           DISABLED_CONFIGURATION,        0
+ $1.SystemCallErrorNumber,        config_parse_warn_compat,           DISABLED_CONFIGURATION,        0
+ $1.RestrictAddressFamilies,      config_parse_warn_compat,           DISABLED_CONFIGURATION,        0')
+-$1.LimitCPU,                     config_parse_limit,                 RLIMIT_CPU,                    offsetof($1, exec_context.rlimit)
++$1.LimitCPU,                     config_parse_sec_limit,             RLIMIT_CPU,                    offsetof($1, exec_context.rlimit)
+ $1.LimitFSIZE,                   config_parse_bytes_limit,           RLIMIT_FSIZE,                  offsetof($1, exec_context.rlimit)
+ $1.LimitDATA,                    config_parse_bytes_limit,           RLIMIT_DATA,                   offsetof($1, exec_context.rlimit)
+ $1.LimitSTACK,                   config_parse_bytes_limit,           RLIMIT_STACK,                  offsetof($1, exec_context.rlimit)
+@@ -73,7 +73,7 @@ $1.LimitSIGPENDING,              config_parse_limit,                 RLIMIT_SIGP
+ $1.LimitMSGQUEUE,                config_parse_bytes_limit,           RLIMIT_MSGQUEUE,               offsetof($1, exec_context.rlimit)
+ $1.LimitNICE,                    config_parse_limit,                 RLIMIT_NICE,                   offsetof($1, exec_context.rlimit)
+ $1.LimitRTPRIO,                  config_parse_limit,                 RLIMIT_RTPRIO,                 offsetof($1, exec_context.rlimit)
+-$1.LimitRTTIME,                  config_parse_limit,                 RLIMIT_RTTIME,                 offsetof($1, exec_context.rlimit)
++$1.LimitRTTIME,                  config_parse_usec_limit,            RLIMIT_RTTIME,                 offsetof($1, exec_context.rlimit)
+ $1.ReadWriteDirectories,         config_parse_namespace_path_strv,   0,                             offsetof($1, exec_context.read_write_dirs)
+ $1.ReadOnlyDirectories,          config_parse_namespace_path_strv,   0,                             offsetof($1, exec_context.read_only_dirs)
+ $1.InaccessibleDirectories,      config_parse_namespace_path_strv,   0,                             offsetof($1, exec_context.inaccessible_dirs)
+diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
+index dbb45b2..8afe9d7 100644
+--- a/src/core/load-fragment.c
++++ b/src/core/load-fragment.c
+@@ -1162,6 +1162,107 @@ int config_parse_bytes_limit(const char *unit,
+         return 0;
+ }
+ 
++int config_parse_sec_limit(
++                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) {
++
++        struct rlimit **rl = data;
++        rlim_t seconds;
++        int r;
++
++        assert(filename);
++        assert(lvalue);
++        assert(rvalue);
++        assert(data);
++
++        rl += ltype;
++
++        if (streq(rvalue, "infinity"))
++                seconds = RLIM_INFINITY;
++        else {
++                usec_t t;
++
++                r = parse_sec(rvalue, &t);
++                if (r < 0) {
++                        log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse resource value, ignoring: %s", rvalue);
++                        return 0;
++                }
++
++                if (t == USEC_INFINITY)
++                        seconds = RLIM_INFINITY;
++                else
++                        seconds = (rlim_t) (DIV_ROUND_UP(t, USEC_PER_SEC));
++        }
++
++        if (!*rl) {
++                *rl = new(struct rlimit, 1);
++                if (!*rl)
++                        return log_oom();
++        }
++
++        (*rl)->rlim_cur = (*rl)->rlim_max = seconds;
++        return 0;
++}
++
++
++int config_parse_usec_limit(
++                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) {
++
++        struct rlimit **rl = data;
++        rlim_t useconds;
++        int r;
++
++        assert(filename);
++        assert(lvalue);
++        assert(rvalue);
++        assert(data);
++
++        rl += ltype;
++
++        if (streq(rvalue, "infinity"))
++                useconds = RLIM_INFINITY;
++        else {
++                usec_t t;
++
++                r = parse_time(rvalue, &t, 1);
++                if (r < 0) {
++                        log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse resource value, ignoring: %s", rvalue);
++                        return 0;
++                }
++
++                if (t == USEC_INFINITY)
++                        useconds = RLIM_INFINITY;
++                else
++                        useconds = (rlim_t) t;
++        }
++
++        if (!*rl) {
++                *rl = new(struct rlimit, 1);
++                if (!*rl)
++                        return log_oom();
++        }
++
++        (*rl)->rlim_cur = (*rl)->rlim_max = useconds;
++        return 0;
++}
++
+ #ifdef HAVE_SYSV_COMPAT
+ int config_parse_sysv_priority(const char *unit,
+                                const char *filename,
+diff --git a/src/core/load-fragment.h b/src/core/load-fragment.h
+index 2d509d0..359794d 100644
+--- a/src/core/load-fragment.h
++++ b/src/core/load-fragment.h
+@@ -57,6 +57,8 @@ int config_parse_exec_secure_bits(const char *unit, const char *filename, unsign
+ int config_parse_bounding_set(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_limit(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_bytes_limit(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_sec_limit(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_usec_limit(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_sysv_priority(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_kill_signal(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_exec_mount_flags(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);
+diff --git a/src/test/test-unit-file.c b/src/test/test-unit-file.c
+index 5500983..d151737 100644
+--- a/src/test/test-unit-file.c
++++ b/src/test/test-unit-file.c
+@@ -545,6 +545,66 @@ static void test_install_printf(void) {
+         expect(i4, "%U", "0");
+ }
+ 
++
++static void test_config_parse_rlimit(void) {
++        struct rlimit * rl[_RLIMIT_MAX] = {};
++
++        assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "55", rl, NULL) >= 0);
++        assert_se(rl[RLIMIT_NOFILE]);
++        assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 55);
++        assert_se(rl[RLIMIT_NOFILE]->rlim_cur == rl[RLIMIT_NOFILE]->rlim_max);
++
++        assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "infinity", rl, NULL) >= 0);
++        assert_se(rl[RLIMIT_NOFILE]);
++        assert_se(rl[RLIMIT_NOFILE]->rlim_cur == RLIM_INFINITY);
++        assert_se(rl[RLIMIT_NOFILE]->rlim_cur == rl[RLIMIT_NOFILE]->rlim_max);
++
++        rl[RLIMIT_NOFILE] = free(rl[RLIMIT_NOFILE]);
++        assert_se(config_parse_sec_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "56", rl, NULL) >= 0);
++        assert_se(rl[RLIMIT_CPU]);
++        assert_se(rl[RLIMIT_CPU]->rlim_cur == 56);
++        assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max);
++
++        assert_se(config_parse_sec_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "57s", rl, NULL) >= 0);
++        assert_se(rl[RLIMIT_CPU]);
++        assert_se(rl[RLIMIT_CPU]->rlim_cur == 57);
++        assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max);
++
++        assert_se(config_parse_sec_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "infinity", rl, NULL) >= 0);
++        assert_se(rl[RLIMIT_CPU]);
++        assert_se(rl[RLIMIT_CPU]->rlim_cur == RLIM_INFINITY);
++        assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max);
++
++        assert_se(config_parse_sec_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "1234ms", rl, NULL) >= 0);
++        assert_se(rl[RLIMIT_CPU]);
++        assert_se(rl[RLIMIT_CPU]->rlim_cur == 2);
++        assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max);
++
++        rl[RLIMIT_CPU] = free(rl[RLIMIT_CPU]);
++
++        assert_se(config_parse_usec_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "58", rl, NULL) >= 0);
++        assert_se(rl[RLIMIT_RTTIME]);
++        assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 58);
++        assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
++
++        assert_se(config_parse_usec_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "59s", rl, NULL) >= 0);
++        assert_se(rl[RLIMIT_RTTIME]);
++        assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 59 * USEC_PER_SEC);
++        assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
++
++        assert_se(config_parse_usec_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "infinity", rl, NULL) >= 0);
++        assert_se(rl[RLIMIT_RTTIME]);
++        assert_se(rl[RLIMIT_RTTIME]->rlim_cur == RLIM_INFINITY);
++        assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
++
++        assert_se(config_parse_usec_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "2345ms", rl, NULL) >= 0);
++        assert_se(rl[RLIMIT_RTTIME]);
++        assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 2345 * USEC_PER_MSEC);
++        assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
++
++        rl[RLIMIT_RTTIME] = free(rl[RLIMIT_RTTIME]);
++}
++
+ int main(int argc, char *argv[]) {
+         int r;
+ 
+@@ -553,6 +613,7 @@ int main(int argc, char *argv[]) {
+ 
+         r = test_unit_file_get_set();
+         test_config_parse_exec();
++        test_config_parse_rlimit();
+         test_load_env_file_1();
+         test_load_env_file_2();
+         test_load_env_file_3();
diff --git a/SOURCES/0357-time-util-add-parse_time-which-is-like-parse_sec-but.patch b/SOURCES/0357-time-util-add-parse_time-which-is-like-parse_sec-but.patch
new file mode 100644
index 0000000..6ef4d42
--- /dev/null
+++ b/SOURCES/0357-time-util-add-parse_time-which-is-like-parse_sec-but.patch
@@ -0,0 +1,214 @@
+From 8afe4259a8add0d042950015d34afc95a221ad96 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Wed, 6 Jul 2016 13:47:07 +0200
+Subject: [PATCH] time-util: add parse_time(), which is like parse_sec() but
+ allows specification of default time unit if none is specified
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This is useful if we want to parse RLIMIT_RTTIME values where the common
+UNIX syntax is without any units but refers to a non-second unit (µs in
+this case), but where we want to allow specification of units.
+
+Cherry-picked from: 519cffec890510f817740d07355e911b10c203b7
+Related: #1351415
+---
+ src/shared/calendarspec.c |  4 ++--
+ src/shared/time-util.c    | 34 ++++++++++++++++++++++------------
+ src/shared/time-util.h    |  1 +
+ src/test/test-time.c      | 23 +++++++++++++++++++++++
+ src/test/test-unit-file.c |  6 +++---
+ 5 files changed, 51 insertions(+), 17 deletions(-)
+
+diff --git a/src/shared/calendarspec.c b/src/shared/calendarspec.c
+index 2fde3e1..abbf026 100644
+--- a/src/shared/calendarspec.c
++++ b/src/shared/calendarspec.c
+@@ -556,7 +556,7 @@ static int parse_date(const char **p, CalendarSpec *c) {
+         return -EINVAL;
+ }
+ 
+-static int parse_time(const char **p, CalendarSpec *c) {
++static int parse_calendar_time(const char **p, CalendarSpec *c) {
+         CalendarComponent *h = NULL, *m = NULL, *s = NULL;
+         const char *t;
+         int r;
+@@ -789,7 +789,7 @@ int calendar_spec_from_string(const char *p, CalendarSpec **spec) {
+                 if (r < 0)
+                         goto fail;
+ 
+-                r = parse_time(&p, c);
++                r = parse_calendar_time(&p, c);
+                 if (r < 0)
+                         goto fail;
+ 
+diff --git a/src/shared/time-util.c b/src/shared/time-util.c
+index 1c36c57..c001f52 100644
+--- a/src/shared/time-util.c
++++ b/src/shared/time-util.c
+@@ -613,7 +613,8 @@ finish:
+         return 0;
+ }
+ 
+-int parse_sec(const char *t, usec_t *usec) {
++int parse_time(const char *t, usec_t *usec, usec_t default_unit) {
++
+         static const struct {
+                 const char *suffix;
+                 usec_t usec;
+@@ -645,7 +646,6 @@ int parse_sec(const char *t, usec_t *usec) {
+                 { "y", USEC_PER_YEAR },
+                 { "usec", 1ULL },
+                 { "us", 1ULL },
+-                { "", USEC_PER_SEC }, /* default is sec */
+         };
+ 
+         const char *p, *s;
+@@ -654,6 +654,7 @@ int parse_sec(const char *t, usec_t *usec) {
+ 
+         assert(t);
+         assert(usec);
++        assert(default_unit > 0);
+ 
+         p = t;
+ 
+@@ -672,6 +673,7 @@ int parse_sec(const char *t, usec_t *usec) {
+                 long long l, z = 0;
+                 char *e;
+                 unsigned i, n = 0;
++                usec_t multiplier, k;
+ 
+                 p += strspn(p, WHITESPACE);
+ 
+@@ -714,21 +716,24 @@ int parse_sec(const char *t, usec_t *usec) {
+ 
+                 for (i = 0; i < ELEMENTSOF(table); i++)
+                         if (startswith(e, table[i].suffix)) {
+-                                usec_t k = (usec_t) z * table[i].usec;
+-
+-                                for (; n > 0; n--)
+-                                        k /= 10;
+-
+-                                r += (usec_t) l * table[i].usec + k;
++                                multiplier = table[i].usec;
+                                 p = e + strlen(table[i].suffix);
+-
+-                                something = true;
+                                 break;
+                         }
+ 
+-                if (i >= ELEMENTSOF(table))
+-                        return -EINVAL;
++                if (i >= ELEMENTSOF(table)) {
++                        multiplier = default_unit;
++                        p = e;
++                }
++
++                something = true;
++
++                k = (usec_t) z * multiplier;
++
++                for (; n > 0; n--)
++                        k /= 10;
+ 
++                r += (usec_t) l * multiplier + k;
+         }
+ 
+         *usec = r;
+@@ -736,6 +741,11 @@ int parse_sec(const char *t, usec_t *usec) {
+         return 0;
+ }
+ 
++
++int parse_sec(const char *t, usec_t *usec) {
++        return parse_time(t, usec, USEC_PER_SEC);
++}
++
+ int parse_nsec(const char *t, nsec_t *nsec) {
+         static const struct {
+                 const char *suffix;
+diff --git a/src/shared/time-util.h b/src/shared/time-util.h
+index fca8a4d..f278914 100644
+--- a/src/shared/time-util.h
++++ b/src/shared/time-util.h
+@@ -99,6 +99,7 @@ void dual_timestamp_deserialize(const char *value, dual_timestamp *t);
+ int parse_timestamp(const char *t, usec_t *usec);
+ 
+ int parse_sec(const char *t, usec_t *usec);
++int parse_time(const char *t, usec_t *usec, usec_t default_unit);
+ int parse_nsec(const char *t, nsec_t *nsec);
+ 
+ bool ntp_synced(void);
+diff --git a/src/test/test-time.c b/src/test/test-time.c
+index 3840fff..820e4aa 100644
+--- a/src/test/test-time.c
++++ b/src/test/test-time.c
+@@ -57,6 +57,28 @@ static void test_parse_sec(void) {
+         assert_se(parse_sec(".3 infinity", &u) < 0);
+ }
+ 
++static void test_parse_time(void) {
++        usec_t u;
++
++        assert_se(parse_time("5", &u, 1) >= 0);
++        assert_se(u == 5);
++
++        assert_se(parse_time("5", &u, USEC_PER_MSEC) >= 0);
++        assert_se(u == 5 * USEC_PER_MSEC);
++
++        assert_se(parse_time("5", &u, USEC_PER_SEC) >= 0);
++        assert_se(u == 5 * USEC_PER_SEC);
++
++        assert_se(parse_time("5s", &u, 1) >= 0);
++        assert_se(u == 5 * USEC_PER_SEC);
++
++        assert_se(parse_time("5s", &u, USEC_PER_SEC) >= 0);
++        assert_se(u == 5 * USEC_PER_SEC);
++
++        assert_se(parse_time("5s", &u, USEC_PER_MSEC) >= 0);
++        assert_se(u == 5 * USEC_PER_SEC);
++}
++
+ static void test_parse_nsec(void) {
+         nsec_t u;
+ 
+@@ -161,6 +183,7 @@ static void test_get_timezones(void) {
+ 
+ int main(int argc, char *argv[]) {
+         test_parse_sec();
++        test_parse_time();
+         test_parse_nsec();
+         test_format_timespan(1);
+         test_format_timespan(USEC_PER_MSEC);
+diff --git a/src/test/test-unit-file.c b/src/test/test-unit-file.c
+index d151737..87c81cc 100644
+--- a/src/test/test-unit-file.c
++++ b/src/test/test-unit-file.c
+@@ -559,7 +559,7 @@ static void test_config_parse_rlimit(void) {
+         assert_se(rl[RLIMIT_NOFILE]->rlim_cur == RLIM_INFINITY);
+         assert_se(rl[RLIMIT_NOFILE]->rlim_cur == rl[RLIMIT_NOFILE]->rlim_max);
+ 
+-        rl[RLIMIT_NOFILE] = free(rl[RLIMIT_NOFILE]);
++        free(rl[RLIMIT_NOFILE]);
+         assert_se(config_parse_sec_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "56", rl, NULL) >= 0);
+         assert_se(rl[RLIMIT_CPU]);
+         assert_se(rl[RLIMIT_CPU]->rlim_cur == 56);
+@@ -580,7 +580,7 @@ static void test_config_parse_rlimit(void) {
+         assert_se(rl[RLIMIT_CPU]->rlim_cur == 2);
+         assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max);
+ 
+-        rl[RLIMIT_CPU] = free(rl[RLIMIT_CPU]);
++        free(rl[RLIMIT_CPU]);
+ 
+         assert_se(config_parse_usec_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "58", rl, NULL) >= 0);
+         assert_se(rl[RLIMIT_RTTIME]);
+@@ -602,7 +602,7 @@ static void test_config_parse_rlimit(void) {
+         assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 2345 * USEC_PER_MSEC);
+         assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
+ 
+-        rl[RLIMIT_RTTIME] = free(rl[RLIMIT_RTTIME]);
++        free(rl[RLIMIT_RTTIME]);
+ }
+ 
+ int main(int argc, char *argv[]) {
diff --git a/SOURCES/0358-core-support-soft-hard-ranges-for-RLIMIT-options.patch b/SOURCES/0358-core-support-soft-hard-ranges-for-RLIMIT-options.patch
new file mode 100644
index 0000000..fafaafe
--- /dev/null
+++ b/SOURCES/0358-core-support-soft-hard-ranges-for-RLIMIT-options.patch
@@ -0,0 +1,1003 @@
+From 81a95ec724b7b874f850cb0f32f1981ccc4fb062 Mon Sep 17 00:00:00 2001
+From: Karel Zak <kzak@redhat.com>
+Date: Fri, 20 Nov 2015 12:54:10 +0100
+Subject: [PATCH] core: support <soft:hard> ranges for RLIMIT options
+
+The new parser supports:
+
+ <value>       - specify both limits to the same value
+ <soft:hard>   - specify both limits
+
+the size or time specific suffixes are supported, for example
+
+  LimitRTTIME=1sec
+  LimitAS=4G:16G
+
+The patch introduces parse_rlimit_range() and rlim type (size, sec,
+usec, etc.) specific parsers. No code is duplicated now.
+
+The patch also sync docs for DefaultLimitXXX= and LimitXXX=.
+
+References: https://github.com/systemd/systemd/issues/1769
+
+Cherry-picked from: 91518d20ddf0376808544576d0ef0883cedc67d4
+Resolves: #1351415
+---
+ man/systemd-system.conf.xml |  27 ++-
+ man/systemd.exec.xml        |   5 +-
+ src/core/load-fragment.c    | 243 ++++++++++++-----------
+ src/shared/util.c           | 467 ++++++++++++++++++++++++++++++++++++++++++++
+ src/shared/util.h           |  14 ++
+ src/test/test-unit-file.c   |  31 +++
+ 6 files changed, 667 insertions(+), 120 deletions(-)
+
+diff --git a/man/systemd-system.conf.xml b/man/systemd-system.conf.xml
+index b7d9cde..39d19bc 100644
+--- a/man/systemd-system.conf.xml
++++ b/man/systemd-system.conf.xml
+@@ -326,13 +326,26 @@
+         <listitem><para>These settings control various default
+         resource limits for units. See
+         <citerefentry><refentrytitle>setrlimit</refentrytitle><manvolnum>2</manvolnum></citerefentry>
+-        for details. Use the string <varname>infinity</varname> to
+-        configure no limit on a specific resource. The multiplicative suffixes
+-        K (=1024), M (=1024*1024) and so on for G, T, P and E may be used for
+-        resource limits measured in bytes (e.g. DefaultLimitAS=16G). These
+-        settings may be overridden in individual units using the corresponding
+-        LimitXXX= directives. Note that these resource limits are only
+-        defaults for units, they are not applied to PID 1
++        for details. The resource limit is possible to specify in two formats,
++        <option>value</option> to set soft and hard limits to the same value,
++        or <option>soft:hard</option> to set both limits individually (e.g. DefaultLimitAS=4G:16G).
++        Use the string <varname>infinity</varname> to
++        configure no limit on a specific resource. The multiplicative
++        suffixes K (=1024), M (=1024*1024) and so on for G, T, P and E
++        may be used for resource limits measured in bytes
++        (e.g. DefaultLimitAS=16G). For the limits referring to time values,
++        the usual time units ms, s, min, h and so on may be used (see
++        <citerefentry><refentrytitle>systemd.time</refentrytitle><manvolnum>7</manvolnum></citerefentry>
++        for details). Note that if no time unit is specified for
++        <varname>DefaultLimitCPU=</varname> the default unit of seconds is
++        implied, while for <varname>DefaultLimitRTTIME=</varname> the default
++        unit of microseconds is implied. Also, note that the effective
++        granularity of the limits might influence their
++        enforcement. For example, time limits specified for
++        <varname>DefaultLimitCPU=</varname> will be rounded up implicitly to
++        multiples of 1s. These  settings may be overridden in individual units
++        using the corresponding LimitXXX= directives. Note that these resource
++        limits are only defaults for units, they are not applied to PID 1
+         itself.</para></listitem>
+       </varlistentry>
+     </variablelist>
+diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml
+index cfdcc3d..0cd469c 100644
+--- a/man/systemd.exec.xml
++++ b/man/systemd.exec.xml
+@@ -558,7 +558,10 @@
+         <listitem><para>These settings set both soft and hard limits
+         of various resources for executed processes. See
+         <citerefentry><refentrytitle>setrlimit</refentrytitle><manvolnum>2</manvolnum></citerefentry>
+-        for details. Use the string <varname>infinity</varname> to
++        for details. The resource limit is possible to specify in two formats,
++        <option>value</option> to set soft and hard limits to the same value,
++        or <option>soft:hard</option> to set both limits individually (e.g. LimitAS=4G:16G).
++        Use the string <varname>infinity</varname> to
+         configure no limit on a specific resource. The multiplicative
+         suffixes K (=1024), M (=1024*1024) and so on for G, T, P and E
+         may be used for resource limits measured in bytes
+diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
+index 8afe9d7..d307f1c 100644
+--- a/src/core/load-fragment.c
++++ b/src/core/load-fragment.c
+@@ -1075,81 +1075,108 @@ int config_parse_bounding_set(const char *unit,
+         return 0;
+ }
+ 
+-int config_parse_limit(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) {
+ 
+-        struct rlimit **rl = data;
+-        unsigned long long u;
++static int rlim_parse_u64(const char *val, rlim_t *res) {
++        int r = 0;
+ 
+-        assert(filename);
+-        assert(lvalue);
+-        assert(rvalue);
+-        assert(data);
++        if (streq(val, "infinity"))
++                *res = RLIM_INFINITY;
++        else {
++                uint64_t u;
+ 
+-        rl += ltype;
++                /* setrlimit(2) suggests rlim_t is always 64bit on Linux. */
++                assert_cc(sizeof(rlim_t) == sizeof(uint64_t));
++
++                r = safe_atou64(val, &u);
++                if (r >= 0 && u >= (uint64_t) RLIM_INFINITY)
++                        r = -ERANGE;
++                if (r == 0)
++                        *res = (rlim_t) u;
++        }
++        return r;
++}
+ 
+-        if (streq(rvalue, "infinity"))
+-                u = (unsigned long long) RLIM_INFINITY;
++static int rlim_parse_size(const char *val, rlim_t *res) {
++        int r = 0;
++
++        if (streq(val, "infinity"))
++                *res = RLIM_INFINITY;
+         else {
+-                int r;
++                off_t u;
+ 
+-                r = safe_atollu(rvalue, &u);
+-                if (r < 0) {
+-                        log_syntax(unit, LOG_ERR, filename, line, -r,
+-                                   "Failed to parse resource value, ignoring: %s", rvalue);
+-                        return 0;
+-                }
++                r = parse_size(val, 1024, &u);
++                if (r >= 0 && u >= (off_t) RLIM_INFINITY)
++                        r = -ERANGE;
++                if (r == 0)
++                        *res = (rlim_t) u;
+         }
++        return r;
++}
+ 
+-        if (!*rl) {
+-                *rl = new(struct rlimit, 1);
+-                if (!*rl)
+-                        return log_oom();
+-        }
++static int rlim_parse_sec(const char *val, rlim_t *res) {
++        int r = 0;
+ 
+-        (*rl)->rlim_cur = (*rl)->rlim_max = (rlim_t) u;
+-        return 0;
++        if (streq(val, "infinity"))
++                *res = RLIM_INFINITY;
++        else {
++                usec_t t;
++
++                r = parse_sec(val, &t);
++                if (r < 0)
++                        return r;
++                if (t == USEC_INFINITY)
++                        *res = RLIM_INFINITY;
++                else
++                        *res = (rlim_t) (DIV_ROUND_UP(t, USEC_PER_SEC));
++
++        }
++        return r;
+ }
+ 
+-int config_parse_bytes_limit(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) {
++static int rlim_parse_usec(const char *val, rlim_t *res) {
++        int r = 0;
+ 
+-        struct rlimit **rl = data;
+-        uint64_t bytes;
++        if (streq(val, "infinity"))
++                *res = RLIM_INFINITY;
++        else {
++                usec_t t;
+ 
+-        assert(filename);
+-        assert(lvalue);
+-        assert(rvalue);
+-        assert(data);
++                r = parse_time(val, &t, 1);
++                if (r < 0)
++                        return r;
++                if (t == USEC_INFINITY)
++                        *res = RLIM_INFINITY;
++                else
++                        *res = (rlim_t) t;
++        }
++        return r;
++}
+ 
+-        rl += ltype;
++static int parse_rlimit_range(
++                const char *unit,
++                const char *filename,
++                unsigned line,
++                const char *value,
++                struct rlimit **rl,
++                int (*rlim_parser)(const char *, rlim_t *)) {
+ 
+-        if (streq(rvalue, "infinity"))
+-                bytes = (uint64_t) RLIM_INFINITY;
+-        else {
+-                int r;
++        rlim_t soft, hard;
++        _cleanup_free_ char *sword = NULL, *hword = NULL;
++        int nwords, r;
+ 
+-                r = parse_size(rvalue, 1024, &bytes);
+-                if (r < 0) {
+-                        log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse resource value, ignoring: %s", rvalue);
+-                        return 0;
+-                }
++        assert(value);
++
++        /* <value> or <soft:hard> */
++        nwords = extract_many_words(&value, ":", EXTRACT_DONT_COALESCE_SEPARATORS, &sword, &hword, NULL);
++        r = nwords < 0 ? nwords : nwords == 0 ? -EINVAL : 0;
++
++        if (r == 0)
++                r = rlim_parser(sword, &soft);
++        if (r == 0 && nwords == 2)
++                r = rlim_parser(hword, &hard);
++        if (r < 0) {
++                log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse resource value, ignoring: %s", value);
++                return 0;
+         }
+ 
+         if (!*rl) {
+@@ -1157,12 +1184,12 @@ int config_parse_bytes_limit(const char *unit,
+                 if (!*rl)
+                         return log_oom();
+         }
+-
+-        (*rl)->rlim_cur = (*rl)->rlim_max = (rlim_t) bytes;
++        (*rl)->rlim_cur = soft;
++        (*rl)->rlim_max = nwords == 2 ? hard : soft;
+         return 0;
+ }
+ 
+-int config_parse_sec_limit(
++int config_parse_limit(
+                 const char *unit,
+                 const char *filename,
+                 unsigned line,
+@@ -1175,8 +1202,6 @@ int config_parse_sec_limit(
+                 void *userdata) {
+ 
+         struct rlimit **rl = data;
+-        rlim_t seconds;
+-        int r;
+ 
+         assert(filename);
+         assert(lvalue);
+@@ -1184,36 +1209,33 @@ int config_parse_sec_limit(
+         assert(data);
+ 
+         rl += ltype;
++        return parse_rlimit_range(unit, filename, line, rvalue, rl, rlim_parse_u64);
++}
+ 
+-        if (streq(rvalue, "infinity"))
+-                seconds = RLIM_INFINITY;
+-        else {
+-                usec_t t;
+-
+-                r = parse_sec(rvalue, &t);
+-                if (r < 0) {
+-                        log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse resource value, ignoring: %s", rvalue);
+-                        return 0;
+-                }
++int config_parse_bytes_limit(
++                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) {
+ 
+-                if (t == USEC_INFINITY)
+-                        seconds = RLIM_INFINITY;
+-                else
+-                        seconds = (rlim_t) (DIV_ROUND_UP(t, USEC_PER_SEC));
+-        }
++        struct rlimit **rl = data;
+ 
+-        if (!*rl) {
+-                *rl = new(struct rlimit, 1);
+-                if (!*rl)
+-                        return log_oom();
+-        }
++        assert(filename);
++        assert(lvalue);
++        assert(rvalue);
++        assert(data);
+ 
+-        (*rl)->rlim_cur = (*rl)->rlim_max = seconds;
+-        return 0;
++        rl += ltype;
++        return parse_rlimit_range(unit, filename, line, rvalue, rl, rlim_parse_size);
+ }
+ 
+-
+-int config_parse_usec_limit(
++int config_parse_sec_limit(
+                 const char *unit,
+                 const char *filename,
+                 unsigned line,
+@@ -1226,8 +1248,6 @@ int config_parse_usec_limit(
+                 void *userdata) {
+ 
+         struct rlimit **rl = data;
+-        rlim_t useconds;
+-        int r;
+ 
+         assert(filename);
+         assert(lvalue);
+@@ -1235,34 +1255,33 @@ int config_parse_usec_limit(
+         assert(data);
+ 
+         rl += ltype;
++        return parse_rlimit_range(unit, filename, line, rvalue, rl, rlim_parse_sec);
++}
+ 
+-        if (streq(rvalue, "infinity"))
+-                useconds = RLIM_INFINITY;
+-        else {
+-                usec_t t;
+-
+-                r = parse_time(rvalue, &t, 1);
+-                if (r < 0) {
+-                        log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse resource value, ignoring: %s", rvalue);
+-                        return 0;
+-                }
++int config_parse_usec_limit(
++                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) {
+ 
+-                if (t == USEC_INFINITY)
+-                        useconds = RLIM_INFINITY;
+-                else
+-                        useconds = (rlim_t) t;
+-        }
++        struct rlimit **rl = data;
+ 
+-        if (!*rl) {
+-                *rl = new(struct rlimit, 1);
+-                if (!*rl)
+-                        return log_oom();
+-        }
++        assert(filename);
++        assert(lvalue);
++        assert(rvalue);
++        assert(data);
+ 
+-        (*rl)->rlim_cur = (*rl)->rlim_max = useconds;
+-        return 0;
++        rl += ltype;
++        return parse_rlimit_range(unit, filename, line, rvalue, rl, rlim_parse_usec);
+ }
+ 
++
+ #ifdef HAVE_SYSV_COMPAT
+ int config_parse_sysv_priority(const char *unit,
+                                const char *filename,
+diff --git a/src/shared/util.c b/src/shared/util.c
+index 036677e..f75ed9d 100644
+--- a/src/shared/util.c
++++ b/src/shared/util.c
+@@ -93,6 +93,7 @@
+ #include "virt.h"
+ #include "def.h"
+ #include "sparse-endian.h"
++#include "conf-parser.h"
+ 
+ int saved_argc = 0;
+ char **saved_argv = NULL;
+@@ -100,6 +101,8 @@ char **saved_argv = NULL;
+ static volatile unsigned cached_columns = 0;
+ static volatile unsigned cached_lines = 0;
+ 
++bool unichar_is_valid(int32_t ch);
++
+ size_t page_size(void) {
+         static thread_local size_t pgsz = 0;
+         long r;
+@@ -1365,6 +1368,207 @@ char *cescape(const char *s) {
+         return r;
+ }
+ 
++bool unichar_is_valid(int32_t ch) {
++
++        if (ch >= 0x110000) /* End of unicode space */
++                return false;
++        if ((ch & 0xFFFFF800) == 0xD800) /* Reserved area for UTF-16 */
++                return false;
++        if ((ch >= 0xFDD0) && (ch <= 0xFDEF)) /* Reserved */
++                return false;
++        if ((ch & 0xFFFE) == 0xFFFE) /* BOM (Byte Order Mark) */
++                return false;
++
++        return true;
++}
++
++int cunescape_one(const char *p, size_t length, int32_t *ret, bool *eight_bit) {
++        int r = 1;
++
++        assert(p);
++        assert(*p);
++        assert(ret);
++
++        /* Unescapes C style. Returns the unescaped character in ret.
++         * Sets *eight_bit to true if the escaped sequence either fits in
++         * one byte in UTF-8 or is a non-unicode literal byte and should
++         * instead be copied directly.
++         */
++
++        if (length != (size_t) -1 && length < 1)
++                return -EINVAL;
++
++        switch (p[0]) {
++
++        case 'a':
++                *ret = '\a';
++                break;
++        case 'b':
++                *ret = '\b';
++                break;
++        case 'f':
++                *ret = '\f';
++                break;
++        case 'n':
++                *ret = '\n';
++                break;
++        case 'r':
++                *ret = '\r';
++                break;
++        case 't':
++                *ret = '\t';
++                break;
++        case 'v':
++                *ret = '\v';
++                break;
++        case '\\':
++                *ret = '\\';
++                break;
++        case '"':
++                *ret = '"';
++                break;
++        case '\'':
++                *ret = '\'';
++                break;
++
++        case 's':
++                /* This is an extension of the XDG syntax files */
++                *ret = ' ';
++                break;
++
++        case 'x': {
++                /* hexadecimal encoding */
++                int a, b;
++
++                if (length != (size_t) -1 && length < 3)
++                        return -EINVAL;
++
++                a = unhexchar(p[1]);
++                if (a < 0)
++                        return -EINVAL;
++
++                b = unhexchar(p[2]);
++                if (b < 0)
++                        return -EINVAL;
++
++                /* Don't allow NUL bytes */
++                if (a == 0 && b == 0)
++                        return -EINVAL;
++
++                *ret = (a << 4U) | b;
++                *eight_bit = true;
++                r = 3;
++                break;
++        }
++
++        case 'u': {
++                /* C++11 style 16bit unicode */
++
++                int a[4];
++                unsigned i;
++                uint32_t c;
++
++                if (length != (size_t) -1 && length < 5)
++                        return -EINVAL;
++
++                for (i = 0; i < 4; i++) {
++                        a[i] = unhexchar(p[1 + i]);
++                        if (a[i] < 0)
++                                return a[i];
++                }
++
++                c = ((uint32_t) a[0] << 12U) | ((uint32_t) a[1] << 8U) | ((uint32_t) a[2] << 4U) | (uint32_t) a[3];
++
++                /* Don't allow 0 chars */
++                if (c == 0)
++                        return -EINVAL;
++
++                *ret = c;
++                r = 5;
++                break;
++        }
++
++        case 'U': {
++                /* C++11 style 32bit unicode */
++
++                int a[8];
++                unsigned i;
++                int32_t c;
++
++                if (length != (size_t) -1 && length < 9)
++                        return -EINVAL;
++
++                for (i = 0; i < 8; i++) {
++                        a[i] = unhexchar(p[1 + i]);
++                        if (a[i] < 0)
++                                return a[i];
++                }
++
++                c = ((uint32_t) a[0] << 28U) | ((uint32_t) a[1] << 24U) | ((uint32_t) a[2] << 20U) | ((uint32_t) a[3] << 16U) |
++                    ((uint32_t) a[4] << 12U) | ((uint32_t) a[5] <<  8U) | ((uint32_t) a[6] <<  4U) |  (uint32_t) a[7];
++
++                /* Don't allow 0 chars */
++                if (c == 0)
++                        return -EINVAL;
++
++                /* Don't allow invalid code points */
++                if (!unichar_is_valid(c))
++                        return -EINVAL;
++
++                *ret = c;
++                r = 9;
++                break;
++        }
++
++        case '0':
++        case '1':
++        case '2':
++        case '3':
++        case '4':
++        case '5':
++        case '6':
++        case '7': {
++                /* octal encoding */
++                int a, b, c;
++                int32_t m;
++
++                if (length != (size_t) -1 && length < 3)
++                        return -EINVAL;
++
++                a = unoctchar(p[0]);
++                if (a < 0)
++                        return -EINVAL;
++
++                b = unoctchar(p[1]);
++                if (b < 0)
++                        return -EINVAL;
++
++                c = unoctchar(p[2]);
++                if (c < 0)
++                        return -EINVAL;
++
++                /* don't allow NUL bytes */
++                if (a == 0 && b == 0 && c == 0)
++                        return -EINVAL;
++
++                /* Don't allow bytes above 255 */
++                m = ((uint32_t) a << 6U) | ((uint32_t) b << 3U) | (uint32_t) c;
++                if (m > 255)
++                        return -EINVAL;
++
++                *ret = m;
++                *eight_bit = true;
++                r = 3;
++                break;
++        }
++
++        default:
++                return -EINVAL;
++        }
++
++        return r;
++}
++
+ char *cunescape_length_with_prefix(const char *s, size_t length, const char *prefix) {
+         char *r, *t;
+         const char *f;
+@@ -8207,3 +8411,266 @@ bool colors_enabled(void) {
+ 
+         return parse_boolean(colors) != 0;
+ }
++
++int extract_first_word(const char **p, char **ret, const char *separators, ExtractFlags flags) {
++        _cleanup_free_ char *s = NULL;
++        size_t allocated = 0, sz = 0;
++        char c;
++        int r;
++
++        char quote = 0;                 /* 0 or ' or " */
++        bool backslash = false;         /* whether we've just seen a backslash */
++
++        assert(p);
++        assert(ret);
++
++        /* Bail early if called after last value or with no input */
++        if (!*p)
++                goto finish_force_terminate;
++        c = **p;
++
++        if (!separators)
++                separators = WHITESPACE;
++
++        /* Parses the first word of a string, and returns it in
++         * *ret. Removes all quotes in the process. When parsing fails
++         * (because of an uneven number of quotes or similar), leaves
++         * the pointer *p at the first invalid character. */
++
++        if (flags & EXTRACT_DONT_COALESCE_SEPARATORS)
++                if (!GREEDY_REALLOC(s, allocated, sz+1))
++                        return -ENOMEM;
++
++        for (;; (*p)++, c = **p) {
++                if (c == 0)
++                        goto finish_force_terminate;
++                else if (strchr(separators, c)) {
++                        if (flags & EXTRACT_DONT_COALESCE_SEPARATORS) {
++                                (*p)++;
++                                goto finish_force_next;
++                        }
++                } else {
++                        /* We found a non-blank character, so we will always
++                         * want to return a string (even if it is empty),
++                         * allocate it here. */
++                        if (!GREEDY_REALLOC(s, allocated, sz+1))
++                                return -ENOMEM;
++                        break;
++                }
++        }
++
++        for (;; (*p)++, c = **p) {
++                if (backslash) {
++                        if (!GREEDY_REALLOC(s, allocated, sz+7))
++                                return -ENOMEM;
++
++                        if (c == 0) {
++                                if ((flags & EXTRACT_CUNESCAPE_RELAX) &&
++                                    (!quote || flags & EXTRACT_RELAX)) {
++                                        /* If we find an unquoted trailing backslash and we're in
++                                         * EXTRACT_CUNESCAPE_RELAX mode, keep it verbatim in the
++                                         * output.
++                                         *
++                                         * Unbalanced quotes will only be allowed in EXTRACT_RELAX
++                                         * mode, EXTRACT_CUNESCAPE_RELAX mode does not allow them.
++                                         */
++                                        s[sz++] = '\\';
++                                        goto finish_force_terminate;
++                                }
++                                if (flags & EXTRACT_RELAX)
++                                        goto finish_force_terminate;
++                                return -EINVAL;
++                        }
++
++                        if (flags & EXTRACT_CUNESCAPE) {
++                                bool eight_bit = false;
++                                int32_t u;
++
++                                r = cunescape_one(*p, (size_t) -1, &u, &eight_bit);
++                                if (r < 0) {
++                                        if (flags & EXTRACT_CUNESCAPE_RELAX) {
++                                                s[sz++] = '\\';
++                                                s[sz++] = c;
++                                        } else
++                                                return -EINVAL;
++                                } else {
++                                        (*p) += r - 1;
++
++                                        if (eight_bit)
++                                                s[sz++] = u;
++                                        else
++                                                sz += utf8_encode_unichar(s + sz, u);
++                                }
++                        } else
++                                s[sz++] = c;
++
++                        backslash = false;
++
++                } else if (quote) {     /* inside either single or double quotes */
++                        for (;; (*p)++, c = **p) {
++                                if (c == 0) {
++                                        if (flags & EXTRACT_RELAX)
++                                                goto finish_force_terminate;
++                                        return -EINVAL;
++                                } else if (c == quote) {        /* found the end quote */
++                                        quote = 0;
++                                        break;
++                                } else if (c == '\\' && !(flags & EXTRACT_RETAIN_ESCAPE)) {
++                                        backslash = true;
++                                        break;
++                                } else {
++                                        if (!GREEDY_REALLOC(s, allocated, sz+2))
++                                                return -ENOMEM;
++
++                                        s[sz++] = c;
++                                }
++                        }
++
++                } else {
++                        for (;; (*p)++, c = **p) {
++                                if (c == 0)
++                                        goto finish_force_terminate;
++                                else if ((c == '\'' || c == '"') && (flags & EXTRACT_QUOTES)) {
++                                        quote = c;
++                                        break;
++                                } else if (c == '\\' && !(flags & EXTRACT_RETAIN_ESCAPE)) {
++                                        backslash = true;
++                                        break;
++                                } else if (strchr(separators, c)) {
++                                        if (flags & EXTRACT_DONT_COALESCE_SEPARATORS) {
++                                                (*p)++;
++                                                goto finish_force_next;
++                                        }
++                                        /* Skip additional coalesced separators. */
++                                        for (;; (*p)++, c = **p) {
++                                                if (c == 0)
++                                                        goto finish_force_terminate;
++                                                if (!strchr(separators, c))
++                                                        break;
++                                        }
++                                        goto finish;
++
++                                } else {
++                                        if (!GREEDY_REALLOC(s, allocated, sz+2))
++                                                return -ENOMEM;
++
++                                        s[sz++] = c;
++                                }
++                        }
++                }
++        }
++
++finish_force_terminate:
++        *p = NULL;
++finish:
++        if (!s) {
++                *p = NULL;
++                *ret = NULL;
++                return 0;
++        }
++
++finish_force_next:
++        s[sz] = 0;
++        *ret = s;
++        s = NULL;
++
++        return 1;
++}
++
++int extract_first_word_and_warn(
++                const char **p,
++                char **ret,
++                const char *separators,
++                ExtractFlags flags,
++                const char *unit,
++                const char *filename,
++                unsigned line,
++                const char *rvalue) {
++
++        /* Try to unquote it, if it fails, warn about it and try again
++         * but this time using EXTRACT_CUNESCAPE_RELAX to keep the
++         * backslashes verbatim in invalid escape sequences. */
++
++        const char *save;
++        int r;
++
++        save = *p;
++        r = extract_first_word(p, ret, separators, flags);
++        if (r >= 0)
++                return r;
++
++        if (r == -EINVAL && !(flags & EXTRACT_CUNESCAPE_RELAX)) {
++
++                /* Retry it with EXTRACT_CUNESCAPE_RELAX. */
++                *p = save;
++                r = extract_first_word(p, ret, separators, flags|EXTRACT_CUNESCAPE_RELAX);
++                if (r >= 0) {
++                        /* It worked this time, hence it must have been an invalid escape sequence we could correct. */
++                        log_syntax(unit, LOG_WARNING, filename, line, EINVAL, "Invalid escape sequences in line, correcting: \"%s\"", rvalue);
++                        return r;
++                }
++
++                /* If it's still EINVAL; then it must be unbalanced quoting, report this. */
++                if (r == -EINVAL)
++                        return log_syntax(unit, LOG_ERR, filename, line, r, "Unbalanced quoting, ignoring: \"%s\"", rvalue);
++        }
++
++        /* Can be any error, report it */
++        return log_syntax(unit, LOG_ERR, filename, line, r, "Unable to decode word \"%s\", ignoring: %m", rvalue);
++}
++
++int extract_many_words(const char **p, const char *separators, ExtractFlags flags, ...) {
++        va_list ap;
++        char **l;
++        int n = 0, i, c, r;
++
++        /* Parses a number of words from a string, stripping any
++         * quotes if necessary. */
++
++        assert(p);
++
++        /* Count how many words are expected */
++        va_start(ap, flags);
++        for (;;) {
++                if (!va_arg(ap, char **))
++                        break;
++                n++;
++        }
++        va_end(ap);
++
++        if (n <= 0)
++                return 0;
++
++        /* Read all words into a temporary array */
++        l = newa0(char*, n);
++        for (c = 0; c < n; c++) {
++
++                r = extract_first_word(p, &l[c], separators, flags);
++                if (r < 0) {
++                        int j;
++
++                        for (j = 0; j < c; j++)
++                                free(l[j]);
++
++                        return r;
++                }
++
++                if (r == 0)
++                        break;
++        }
++
++        /* If we managed to parse all words, return them in the passed
++         * in parameters */
++        va_start(ap, flags);
++        for (i = 0; i < n; i++) {
++                char **v;
++
++                v = va_arg(ap, char **);
++                assert(v);
++
++                *v = l[i];
++        }
++        va_end(ap);
++
++        return c;
++}
+diff --git a/src/shared/util.h b/src/shared/util.h
+index a441e44..be04524 100644
+--- a/src/shared/util.h
++++ b/src/shared/util.h
+@@ -315,6 +315,7 @@ int undecchar(char c) _const_;
+ char *cescape(const char *s);
+ char *cunescape(const char *s);
+ char *cunescape_length(const char *s, size_t length);
++int cunescape_one(const char *p, size_t length, int32_t *ret, bool *eight_bit);
+ char *cunescape_length_with_prefix(const char *s, size_t length, const char *prefix);
+ 
+ char *xescape(const char *s, const char *bad);
+@@ -1082,3 +1083,16 @@ void sigkill_wait(pid_t *pid);
+ int syslog_parse_priority(const char **p, int *priority, bool with_facility);
+ 
+ char *shell_maybe_quote(const char *s);
++
++typedef enum ExtractFlags {
++        EXTRACT_RELAX                    = 1,
++        EXTRACT_CUNESCAPE                = 2,
++        EXTRACT_CUNESCAPE_RELAX          = 4,
++        EXTRACT_QUOTES                   = 8,
++        EXTRACT_DONT_COALESCE_SEPARATORS = 16,
++        EXTRACT_RETAIN_ESCAPE            = 32,
++} ExtractFlags;
++
++int extract_first_word(const char **p, char **ret, const char *separators, ExtractFlags flags);
++int extract_first_word_and_warn(const char **p, char **ret, const char *separators, ExtractFlags flags, const char *unit, const char *filename, unsigned line, const char *rvalue);
++int extract_many_words(const char **p, const char *separators, ExtractFlags flags, ...) _sentinel_;
+diff --git a/src/test/test-unit-file.c b/src/test/test-unit-file.c
+index 87c81cc..931dfed 100644
+--- a/src/test/test-unit-file.c
++++ b/src/test/test-unit-file.c
+@@ -554,11 +554,22 @@ static void test_config_parse_rlimit(void) {
+         assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 55);
+         assert_se(rl[RLIMIT_NOFILE]->rlim_cur == rl[RLIMIT_NOFILE]->rlim_max);
+ 
++
++        assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "55:66", rl, NULL) >= 0);
++        assert_se(rl[RLIMIT_NOFILE]);
++        assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 55);
++        assert_se(rl[RLIMIT_NOFILE]->rlim_max == 66);
++
+         assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "infinity", rl, NULL) >= 0);
+         assert_se(rl[RLIMIT_NOFILE]);
+         assert_se(rl[RLIMIT_NOFILE]->rlim_cur == RLIM_INFINITY);
+         assert_se(rl[RLIMIT_NOFILE]->rlim_cur == rl[RLIMIT_NOFILE]->rlim_max);
+ 
++        assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "infinity:infinity", rl, NULL) >= 0);
++        assert_se(rl[RLIMIT_NOFILE]);
++        assert_se(rl[RLIMIT_NOFILE]->rlim_cur == RLIM_INFINITY);
++        assert_se(rl[RLIMIT_NOFILE]->rlim_cur == rl[RLIMIT_NOFILE]->rlim_max);
++
+         free(rl[RLIMIT_NOFILE]);
+         assert_se(config_parse_sec_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "56", rl, NULL) >= 0);
+         assert_se(rl[RLIMIT_CPU]);
+@@ -570,6 +581,11 @@ static void test_config_parse_rlimit(void) {
+         assert_se(rl[RLIMIT_CPU]->rlim_cur == 57);
+         assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max);
+ 
++        assert_se(config_parse_sec_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "40s:1m", rl, NULL) >= 0);
++        assert_se(rl[RLIMIT_CPU]);
++        assert_se(rl[RLIMIT_CPU]->rlim_cur == 40);
++        assert_se(rl[RLIMIT_CPU]->rlim_max == 60);
++
+         assert_se(config_parse_sec_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "infinity", rl, NULL) >= 0);
+         assert_se(rl[RLIMIT_CPU]);
+         assert_se(rl[RLIMIT_CPU]->rlim_cur == RLIM_INFINITY);
+@@ -587,16 +603,31 @@ static void test_config_parse_rlimit(void) {
+         assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 58);
+         assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
+ 
++        assert_se(config_parse_usec_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "58:60", rl, NULL) >= 0);
++        assert_se(rl[RLIMIT_RTTIME]);
++        assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 58);
++        assert_se(rl[RLIMIT_RTTIME]->rlim_max == 60);
++
+         assert_se(config_parse_usec_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "59s", rl, NULL) >= 0);
+         assert_se(rl[RLIMIT_RTTIME]);
+         assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 59 * USEC_PER_SEC);
+         assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
+ 
++        assert_se(config_parse_usec_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "59s:123s", rl, NULL) >= 0);
++        assert_se(rl[RLIMIT_RTTIME]);
++        assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 59 * USEC_PER_SEC);
++        assert_se(rl[RLIMIT_RTTIME]->rlim_max == 123 * USEC_PER_SEC);
++
+         assert_se(config_parse_usec_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "infinity", rl, NULL) >= 0);
+         assert_se(rl[RLIMIT_RTTIME]);
+         assert_se(rl[RLIMIT_RTTIME]->rlim_cur == RLIM_INFINITY);
+         assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
+ 
++        assert_se(config_parse_usec_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "infinity:infinity", rl, NULL) >= 0);
++        assert_se(rl[RLIMIT_RTTIME]);
++        assert_se(rl[RLIMIT_RTTIME]->rlim_cur == RLIM_INFINITY);
++        assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
++
+         assert_se(config_parse_usec_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "2345ms", rl, NULL) >= 0);
+         assert_se(rl[RLIMIT_RTTIME]);
+         assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 2345 * USEC_PER_MSEC);
diff --git a/SOURCES/0359-core-fix-rlimit-parsing.patch b/SOURCES/0359-core-fix-rlimit-parsing.patch
new file mode 100644
index 0000000..42fe56a
--- /dev/null
+++ b/SOURCES/0359-core-fix-rlimit-parsing.patch
@@ -0,0 +1,74 @@
+From b53ec8d7dca8eba189c45ae29e4d5ff03e5e5556 Mon Sep 17 00:00:00 2001
+From: Evgeny Vereshchagin <evvers@ya.ru>
+Date: Fri, 27 Nov 2015 08:54:42 +0000
+Subject: [PATCH] core: fix rlimit parsing
+
+* refuse limits if soft > hard
+* print an actual value instead of (null)
+
+see https://github.com/systemd/systemd/pull/1994#issuecomment-159999123
+
+Cherry-picked from: 0316f2aeebde7569d24a93ab788ac4bc1657b11b
+Related: #1351415
+---
+ src/core/load-fragment.c  |  5 ++++-
+ src/test/test-unit-file.c | 21 +++++++++++++++++++++
+ 2 files changed, 25 insertions(+), 1 deletion(-)
+
+diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
+index d307f1c..2f6209e 100644
+--- a/src/core/load-fragment.c
++++ b/src/core/load-fragment.c
+@@ -1160,6 +1160,7 @@ static int parse_rlimit_range(
+                 struct rlimit **rl,
+                 int (*rlim_parser)(const char *, rlim_t *)) {
+ 
++        const char *whole_value = value;
+         rlim_t soft, hard;
+         _cleanup_free_ char *sword = NULL, *hword = NULL;
+         int nwords, r;
+@@ -1175,9 +1176,11 @@ static int parse_rlimit_range(
+         if (r == 0 && nwords == 2)
+                 r = rlim_parser(hword, &hard);
+         if (r < 0) {
+-                log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse resource value, ignoring: %s", value);
++                log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse resource value, ignoring: %s", whole_value);
+                 return 0;
+         }
++        if (nwords == 2 && soft > hard)
++                return log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid resource value ("RLIM_FMT" > "RLIM_FMT"), ignoring: %s", soft, hard, whole_value);
+ 
+         if (!*rl) {
+                 *rl = new(struct rlimit, 1);
+diff --git a/src/test/test-unit-file.c b/src/test/test-unit-file.c
+index 931dfed..8acf071 100644
+--- a/src/test/test-unit-file.c
++++ b/src/test/test-unit-file.c
+@@ -570,6 +570,27 @@ static void test_config_parse_rlimit(void) {
+         assert_se(rl[RLIMIT_NOFILE]->rlim_cur == RLIM_INFINITY);
+         assert_se(rl[RLIMIT_NOFILE]->rlim_cur == rl[RLIMIT_NOFILE]->rlim_max);
+ 
++        assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "10:20:30", rl, NULL) >= 0);
++        assert_se(rl[RLIMIT_NOFILE]);
++        assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10);
++        assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20);
++
++        /* Invalid values don't change rl */
++        assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "wat:wat", rl, NULL) >= 0);
++        assert_se(rl[RLIMIT_NOFILE]);
++        assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10);
++        assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20);
++
++        assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "66:wat", rl, NULL) >= 0);
++        assert_se(rl[RLIMIT_NOFILE]);
++        assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10);
++        assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20);
++
++        assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "200:100", rl, NULL) >= 0);
++        assert_se(rl[RLIMIT_NOFILE]);
++        assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10);
++        assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20);
++
+         free(rl[RLIMIT_NOFILE]);
+         assert_se(config_parse_sec_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "56", rl, NULL) >= 0);
+         assert_se(rl[RLIMIT_CPU]);
diff --git a/SOURCES/0360-core-dump-rlim_cur-too.patch b/SOURCES/0360-core-dump-rlim_cur-too.patch
new file mode 100644
index 0000000..e9a5db3
--- /dev/null
+++ b/SOURCES/0360-core-dump-rlim_cur-too.patch
@@ -0,0 +1,26 @@
+From 0c4a5153b14701ffdbff2f768548d4a657b1ca9f Mon Sep 17 00:00:00 2001
+From: Evgeny Vereshchagin <evvers@ya.ru>
+Date: Fri, 27 Nov 2015 09:13:35 +0000
+Subject: [PATCH] core: dump rlim_cur too
+
+Cherry-picked from: fdbbadbd0d13d3296b9aa4273aaeecd9ba6b82d1
+Related: #1351415
+---
+ src/core/execute.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/src/core/execute.c b/src/core/execute.c
+index 8172c8b..e9b4359 100644
+--- a/src/core/execute.c
++++ b/src/core/execute.c
+@@ -2254,8 +2254,8 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) {
+ 
+         for (i = 0; i < RLIM_NLIMITS; i++)
+                 if (c->rlimit[i])
+-                        fprintf(f, "%s%s: "RLIM_FMT"\n",
+-                                prefix, rlimit_to_string(i), c->rlimit[i]->rlim_max);
++                        fprintf(f, "%s%s: " RLIM_FMT " " RLIM_FMT "\n",
++                                prefix, rlimit_to_string(i), c->rlimit[i]->rlim_cur, c->rlimit[i]->rlim_max);
+ 
+         if (c->ioprio_set) {
+                 _cleanup_free_ char *class_str = NULL;
diff --git a/SOURCES/0361-install-fix-disable-via-unit-file-path.patch b/SOURCES/0361-install-fix-disable-via-unit-file-path.patch
new file mode 100644
index 0000000..ae0acdf
--- /dev/null
+++ b/SOURCES/0361-install-fix-disable-via-unit-file-path.patch
@@ -0,0 +1,39 @@
+From 96df052a6a9d09cde2d437861727bf37fe6446b4 Mon Sep 17 00:00:00 2001
+From: Michal Sekletar <msekleta@redhat.com>
+Date: Tue, 12 Jul 2016 09:40:02 +0200
+Subject: [PATCH] install: fix disable via unit file path
+
+Drop the check for unit file name validity. install_info_add does that
+anyway. Also pass NULL in place of name argument to install_info_add if
+we are dealing with path to a unit file. install_info_add will figure
+out a name from a path and it will correctly populate
+UnitFileInstallInfo with both name and path. Then in
+unit_file_search called from install_info_traverse we can take a
+shortcut and attempt to load unit file directly.
+
+Cherry-picked from: 4dfbf0b176ff0e8a352617eba5e79065ee477969
+Resolves: #1348208
+---
+ src/shared/install.c | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+diff --git a/src/shared/install.c b/src/shared/install.c
+index 5288bb4..f190dbf 100644
+--- a/src/shared/install.c
++++ b/src/shared/install.c
+@@ -1910,10 +1910,12 @@ int unit_file_disable(
+                 return r;
+ 
+         STRV_FOREACH(i, files) {
+-                if (!unit_name_is_valid(*i, UNIT_NAME_ANY))
+-                        return -EINVAL;
+ 
+-                r = install_info_add(&c, *i, NULL, NULL);
++                if (!is_path(*i))
++                        r = install_info_add(&c, *i, NULL, NULL);
++                else
++                        r = install_info_add(&c, NULL, *i, NULL);
++
+                 if (r < 0)
+                         return r;
+         }
diff --git a/SOURCES/0362-manager-don-t-skip-sigchld-handler-for-main-and-cont.patch b/SOURCES/0362-manager-don-t-skip-sigchld-handler-for-main-and-cont.patch
new file mode 100644
index 0000000..0eb22d0
--- /dev/null
+++ b/SOURCES/0362-manager-don-t-skip-sigchld-handler-for-main-and-cont.patch
@@ -0,0 +1,248 @@
+From fd8580a8f42b1e10d75f43229b203fb889260b71 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Nykr=C3=BDn?= <lnykryn@redhat.com>
+Date: Sat, 16 Jul 2016 21:04:13 +0200
+Subject: [PATCH] manager: don't skip sigchld handler for main and control pid
+ for services (#3738)
+
+During stop when service has one "regular" pid one main pid and one
+control pid and the sighld for the regular one is processed first the
+unit_tidy_watch_pids will skip the main and control pid and does not
+remove them from u->pids(). But then we skip the sigchld event because we
+already did one in the iteration and there are two pids in u->pids.
+
+v2: Use general unit_main_pid() and unit_control_pid() instead of
+reaching directly to service structure.
+Cherry-picked from: ccc2c98e1b0c06861577632440b996ca16cefd53
+Resolves: #1342173
+---
+ src/core/busname.c | 10 ++++++++++
+ src/core/manager.c |  5 ++++-
+ src/core/mount.c   | 10 ++++++++++
+ src/core/service.c | 19 +++++++++++++++++++
+ src/core/socket.c  | 10 ++++++++++
+ src/core/swap.c    | 10 ++++++++++
+ src/core/unit.c    | 18 ++++++++++++++++++
+ src/core/unit.h    |  9 +++++++++
+ 8 files changed, 90 insertions(+), 1 deletion(-)
+
+diff --git a/src/core/busname.c b/src/core/busname.c
+index 43d7607..f626ba9 100644
+--- a/src/core/busname.c
++++ b/src/core/busname.c
+@@ -997,6 +997,14 @@ static const char* const busname_state_table[_BUSNAME_STATE_MAX] = {
+ 
+ DEFINE_STRING_TABLE_LOOKUP(busname_state, BusNameState);
+ 
++static int busname_control_pid(Unit *u) {
++        BusName *n = BUSNAME(u);
++
++        assert(n);
++
++        return n->control_pid;
++}
++
+ static const char* const busname_result_table[_BUSNAME_RESULT_MAX] = {
+         [BUSNAME_SUCCESS] = "success",
+         [BUSNAME_FAILURE_RESOURCES] = "resources",
+@@ -1047,6 +1055,8 @@ const UnitVTable busname_vtable = {
+ 
+         .supported = busname_supported,
+ 
++        .control_pid = busname_control_pid,
++
+         .bus_interface = "org.freedesktop.systemd1.BusName",
+         .bus_vtable = bus_busname_vtable,
+ 
+diff --git a/src/core/manager.c b/src/core/manager.c
+index d168777..5da8365 100644
+--- a/src/core/manager.c
++++ b/src/core/manager.c
+@@ -1760,7 +1760,10 @@ static void invoke_sigchld_event(Manager *m, Unit *u, siginfo_t *si) {
+         unit_unwatch_pid(u, si->si_pid);
+ 
+         if (UNIT_VTABLE(u)->sigchld_event) {
+-                if (set_size(u->pids) <= 1 || iteration != u->sigchldgen) {
++                if (set_size(u->pids) <= 1 ||
++                    iteration != u->sigchldgen ||
++                    unit_main_pid(u) == si->si_pid ||
++                    unit_control_pid(u) == si->si_pid) {
+                         UNIT_VTABLE(u)->sigchld_event(u, si->si_pid, si->si_code, si->si_status);
+                         u->sigchldgen = iteration;
+                 } else
+diff --git a/src/core/mount.c b/src/core/mount.c
+index fe967bc..3fbdb7d 100644
+--- a/src/core/mount.c
++++ b/src/core/mount.c
+@@ -1877,6 +1877,14 @@ static const char* const mount_state_table[_MOUNT_STATE_MAX] = {
+ 
+ DEFINE_STRING_TABLE_LOOKUP(mount_state, MountState);
+ 
++static int mount_control_pid(Unit *u) {
++        Mount *m = MOUNT(u);
++
++        assert(m);
++
++        return m->control_pid;
++}
++
+ static const char* const mount_exec_command_table[_MOUNT_EXEC_COMMAND_MAX] = {
+         [MOUNT_EXEC_MOUNT] = "ExecMount",
+         [MOUNT_EXEC_UNMOUNT] = "ExecUnmount",
+@@ -1938,6 +1946,8 @@ const UnitVTable mount_vtable = {
+ 
+         .reset_failed = mount_reset_failed,
+ 
++        .control_pid = mount_control_pid,
++
+         .bus_interface = "org.freedesktop.systemd1.Mount",
+         .bus_vtable = bus_mount_vtable,
+         .bus_set_property = bus_mount_set_property,
+diff --git a/src/core/service.c b/src/core/service.c
+index c76713b..babd3c5 100644
+--- a/src/core/service.c
++++ b/src/core/service.c
+@@ -3068,6 +3068,22 @@ static const char* const service_state_table[_SERVICE_STATE_MAX] = {
+ 
+ DEFINE_STRING_TABLE_LOOKUP(service_state, ServiceState);
+ 
++static int service_main_pid(Unit *u) {
++        Service *s = SERVICE(u);
++
++        assert(s);
++
++        return s->main_pid;
++}
++
++static int service_control_pid(Unit *u) {
++        Service *s = SERVICE(u);
++
++        assert(s);
++
++        return s->control_pid;
++}
++
+ static const char* const service_restart_table[_SERVICE_RESTART_MAX] = {
+         [SERVICE_RESTART_NO] = "no",
+         [SERVICE_RESTART_ON_SUCCESS] = "on-success",
+@@ -3178,6 +3194,9 @@ const UnitVTable service_vtable = {
+         .notify_cgroup_empty = service_notify_cgroup_empty_event,
+         .notify_message = service_notify_message,
+ 
++        .main_pid = service_main_pid,
++        .control_pid = service_control_pid,
++
+         .bus_name_owner_change = service_bus_name_owner_change,
+ 
+         .bus_interface = "org.freedesktop.systemd1.Service",
+diff --git a/src/core/socket.c b/src/core/socket.c
+index bc677a2..771af0d 100644
+--- a/src/core/socket.c
++++ b/src/core/socket.c
+@@ -2648,6 +2648,14 @@ static const char* const socket_state_table[_SOCKET_STATE_MAX] = {
+ 
+ DEFINE_STRING_TABLE_LOOKUP(socket_state, SocketState);
+ 
++static int socket_control_pid(Unit *u) {
++        Socket *s = SOCKET(u);
++
++        assert(s);
++
++        return s->control_pid;
++}
++
+ static const char* const socket_exec_command_table[_SOCKET_EXEC_COMMAND_MAX] = {
+         [SOCKET_EXEC_START_PRE] = "StartPre",
+         [SOCKET_EXEC_START_CHOWN] = "StartChown",
+@@ -2713,6 +2721,8 @@ const UnitVTable socket_vtable = {
+ 
+         .reset_failed = socket_reset_failed,
+ 
++        .control_pid = socket_control_pid,
++
+         .bus_interface = "org.freedesktop.systemd1.Socket",
+         .bus_vtable = bus_socket_vtable,
+         .bus_set_property = bus_socket_set_property,
+diff --git a/src/core/swap.c b/src/core/swap.c
+index 34a2c40..42f9959 100644
+--- a/src/core/swap.c
++++ b/src/core/swap.c
+@@ -1426,6 +1426,14 @@ static const char* const swap_state_table[_SWAP_STATE_MAX] = {
+ 
+ DEFINE_STRING_TABLE_LOOKUP(swap_state, SwapState);
+ 
++static int swap_control_pid(Unit *u) {
++        Swap *s = SWAP(u);
++
++        assert(s);
++
++        return s->control_pid;
++}
++
+ static const char* const swap_exec_command_table[_SWAP_EXEC_COMMAND_MAX] = {
+         [SWAP_EXEC_ACTIVATE] = "ExecActivate",
+         [SWAP_EXEC_DEACTIVATE] = "ExecDeactivate",
+@@ -1487,6 +1495,8 @@ const UnitVTable swap_vtable = {
+ 
+         .reset_failed = swap_reset_failed,
+ 
++        .control_pid = swap_control_pid,
++
+         .bus_interface = "org.freedesktop.systemd1.Swap",
+         .bus_vtable = bus_swap_vtable,
+         .bus_set_property = bus_swap_set_property,
+diff --git a/src/core/unit.c b/src/core/unit.c
+index d62135d..0e90d13 100644
+--- a/src/core/unit.c
++++ b/src/core/unit.c
+@@ -3674,6 +3674,24 @@ int unit_setup_exec_runtime(Unit *u) {
+         return exec_runtime_make(rt, unit_get_exec_context(u), u->id);
+ }
+ 
++pid_t unit_control_pid(Unit *u) {
++        assert(u);
++
++        if (UNIT_VTABLE(u)->control_pid)
++                return UNIT_VTABLE(u)->control_pid(u);
++
++        return 0;
++}
++
++pid_t unit_main_pid(Unit *u) {
++        assert(u);
++
++        if (UNIT_VTABLE(u)->main_pid)
++                return UNIT_VTABLE(u)->main_pid(u);
++
++        return 0;
++}
++
+ static const char* const unit_active_state_table[_UNIT_ACTIVE_STATE_MAX] = {
+         [UNIT_ACTIVE] = "active",
+         [UNIT_RELOADING] = "reloading",
+diff --git a/src/core/unit.h b/src/core/unit.h
+index d936457..35287a5 100644
+--- a/src/core/unit.h
++++ b/src/core/unit.h
+@@ -399,6 +399,12 @@ struct UnitVTable {
+ 
+         int (*get_timeout)(Unit *u, uint64_t *timeout);
+ 
++        /* Returns the main PID if there is any defined, or 0. */
++        pid_t (*main_pid)(Unit *u);
++
++        /* Returns the main PID if there is any defined, or 0. */
++        pid_t (*control_pid)(Unit *u);
++
+         /* This is called for each unit type and should be used to
+          * enumerate existing devices and load them. However,
+          * everything that is loaded here should still stay in
+@@ -610,6 +616,9 @@ int unit_make_transient(Unit *u);
+ 
+ int unit_require_mounts_for(Unit *u, const char *path);
+ 
++pid_t unit_control_pid(Unit *u);
++pid_t unit_main_pid(Unit *u);
++
+ const char *unit_active_state_to_string(UnitActiveState i) _const_;
+ UnitActiveState unit_active_state_from_string(const char *s) _pure_;
+ 
diff --git a/SOURCES/0363-units-increase-watchdog-timeout-to-3min-for-all-our-.patch b/SOURCES/0363-units-increase-watchdog-timeout-to-3min-for-all-our-.patch
new file mode 100644
index 0000000..5c97603
--- /dev/null
+++ b/SOURCES/0363-units-increase-watchdog-timeout-to-3min-for-all-our-.patch
@@ -0,0 +1,156 @@
+From 5be84b3ae46c0fd35c3e80d4f457bf5aedc8af8f Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Wed, 23 Sep 2015 17:27:39 +0200
+Subject: [PATCH] units: increase watchdog timeout to 3min for all our services
+
+Apparently, disk IO issues are more frequent than we hope, and 1min
+waiting for disk IO happens, so let's increase the watchdog timeout a
+bit, for all our services.
+
+See #1353 for an example where this triggers.
+
+(cherry picked from commit c2fc2c2560f0ca0fab383753c065e45d76f465e5)
+Resolves: #1267707
+---
+ units/systemd-hostnamed.service.in   | 2 +-
+ units/systemd-importd.service.in     | 2 +-
+ units/systemd-journald.service.in    | 2 +-
+ units/systemd-localed.service.in     | 2 +-
+ units/systemd-logind.service.in      | 2 +-
+ units/systemd-machined.service.in    | 2 +-
+ units/systemd-networkd.service.in    | 2 +-
+ units/systemd-resolved.service.m4.in | 2 +-
+ units/systemd-timedated.service.in   | 2 +-
+ units/systemd-timesyncd.service.in   | 2 +-
+ 10 files changed, 10 insertions(+), 10 deletions(-)
+
+diff --git a/units/systemd-hostnamed.service.in b/units/systemd-hostnamed.service.in
+index cc88ecd..b7079e4 100644
+--- a/units/systemd-hostnamed.service.in
++++ b/units/systemd-hostnamed.service.in
+@@ -14,7 +14,7 @@ Documentation=http://www.freedesktop.org/wiki/Software/systemd/hostnamed
+ ExecStart=@rootlibexecdir@/systemd-hostnamed
+ BusName=org.freedesktop.hostname1
+ CapabilityBoundingSet=CAP_SYS_ADMIN
+-WatchdogSec=1min
++WatchdogSec=3min
+ PrivateTmp=yes
+ PrivateDevices=yes
+ PrivateNetwork=yes
+diff --git a/units/systemd-importd.service.in b/units/systemd-importd.service.in
+index 5534a49..60e8e9c 100644
+--- a/units/systemd-importd.service.in
++++ b/units/systemd-importd.service.in
+@@ -14,7 +14,7 @@ ExecStart=@rootlibexecdir@/systemd-importd
+ BusName=org.freedesktop.import1
+ CapabilityBoundingSet=CAP_CHOWN CAP_FOWNER CAP_FSETID CAP_MKNOD CAP_SETFCAP CAP_SYS_ADMIN CAP_SETPCAP
+ NoNewPrivileges=yes
+-WatchdogSec=1min
++WatchdogSec=3min
+ PrivateTmp=yes
+ ProtectSystem=full
+ ProtectHome=yes
+diff --git a/units/systemd-journald.service.in b/units/systemd-journald.service.in
+index 9d44622..8575912 100644
+--- a/units/systemd-journald.service.in
++++ b/units/systemd-journald.service.in
+@@ -22,7 +22,7 @@ RestartSec=0
+ NotifyAccess=all
+ StandardOutput=null
+ 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=1min
++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/units/systemd-localed.service.in b/units/systemd-localed.service.in
+index bfa0978..9b13f90 100644
+--- a/units/systemd-localed.service.in
++++ b/units/systemd-localed.service.in
+@@ -14,7 +14,7 @@ Documentation=http://www.freedesktop.org/wiki/Software/systemd/localed
+ ExecStart=@rootlibexecdir@/systemd-localed
+ BusName=org.freedesktop.locale1
+ CapabilityBoundingSet=
+-WatchdogSec=1min
++WatchdogSec=3min
+ PrivateTmp=yes
+ PrivateDevices=yes
+ PrivateNetwork=yes
+diff --git a/units/systemd-logind.service.in b/units/systemd-logind.service.in
+index f087e99..ff04913 100644
+--- a/units/systemd-logind.service.in
++++ b/units/systemd-logind.service.in
+@@ -24,7 +24,7 @@ Restart=always
+ RestartSec=0
+ BusName=org.freedesktop.login1
+ CapabilityBoundingSet=CAP_SYS_ADMIN CAP_MAC_ADMIN CAP_AUDIT_CONTROL CAP_CHOWN CAP_KILL CAP_DAC_READ_SEARCH CAP_DAC_OVERRIDE CAP_FOWNER CAP_SYS_TTY_CONFIG
+-WatchdogSec=1min
++WatchdogSec=3min
+ 
+ # Increase the default a bit in order to allow many simultaneous
+ # logins since we keep one fd open per session.
+diff --git a/units/systemd-machined.service.in b/units/systemd-machined.service.in
+index 15f34d9..35cde98 100644
+--- a/units/systemd-machined.service.in
++++ b/units/systemd-machined.service.in
+@@ -16,7 +16,7 @@ After=machine.slice
+ ExecStart=@rootlibexecdir@/systemd-machined
+ BusName=org.freedesktop.machine1
+ CapabilityBoundingSet=CAP_KILL CAP_SYS_PTRACE CAP_SYS_ADMIN CAP_SETGID CAP_SYS_CHROOT CAP_DAC_READ_SEARCH
+-WatchdogSec=1min
++WatchdogSec=3min
+ PrivateTmp=yes
+ PrivateDevices=yes
+ PrivateNetwork=yes
+diff --git a/units/systemd-networkd.service.in b/units/systemd-networkd.service.in
+index 5a91b8e..d3808c4 100644
+--- a/units/systemd-networkd.service.in
++++ b/units/systemd-networkd.service.in
+@@ -25,7 +25,7 @@ ExecStart=@rootlibexecdir@/systemd-networkd
+ CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_BROADCAST CAP_NET_RAW CAP_SETUID CAP_SETGID CAP_SETPCAP CAP_CHOWN CAP_DAC_OVERRIDE CAP_FOWNER
+ ProtectSystem=full
+ ProtectHome=yes
+-WatchdogSec=1min
++WatchdogSec=3min
+ 
+ [Install]
+ WantedBy=multi-user.target
+diff --git a/units/systemd-resolved.service.m4.in b/units/systemd-resolved.service.m4.in
+index 98ae564..46864e6 100644
+--- a/units/systemd-resolved.service.m4.in
++++ b/units/systemd-resolved.service.m4.in
+@@ -25,7 +25,7 @@ ExecStart=@rootlibexecdir@/systemd-resolved
+ CapabilityBoundingSet=CAP_SETUID CAP_SETGID CAP_SETPCAP CAP_CHOWN CAP_DAC_OVERRIDE CAP_FOWNER
+ ProtectSystem=full
+ ProtectHome=yes
+-WatchdogSec=1min
++WatchdogSec=3min
+ 
+ [Install]
+ WantedBy=multi-user.target
+diff --git a/units/systemd-timedated.service.in b/units/systemd-timedated.service.in
+index fe5ccb4..0c9599d 100644
+--- a/units/systemd-timedated.service.in
++++ b/units/systemd-timedated.service.in
+@@ -14,7 +14,7 @@ Documentation=http://www.freedesktop.org/wiki/Software/systemd/timedated
+ ExecStart=@rootlibexecdir@/systemd-timedated
+ BusName=org.freedesktop.timedate1
+ CapabilityBoundingSet=CAP_SYS_TIME
+-WatchdogSec=1min
++WatchdogSec=3min
+ PrivateTmp=yes
+ ProtectSystem=yes
+ ProtectHome=yes
+diff --git a/units/systemd-timesyncd.service.in b/units/systemd-timesyncd.service.in
+index 39edafc..c7d1d2b 100644
+--- a/units/systemd-timesyncd.service.in
++++ b/units/systemd-timesyncd.service.in
+@@ -27,7 +27,7 @@ PrivateTmp=yes
+ PrivateDevices=yes
+ ProtectSystem=full
+ ProtectHome=yes
+-WatchdogSec=1min
++WatchdogSec=3min
+ 
+ [Install]
+ WantedBy=sysinit.target
diff --git a/SOURCES/0364-core-bump-net.unix.max_dgram_qlen-really-early-durin.patch b/SOURCES/0364-core-bump-net.unix.max_dgram_qlen-really-early-durin.patch
new file mode 100644
index 0000000..4a0081b
--- /dev/null
+++ b/SOURCES/0364-core-bump-net.unix.max_dgram_qlen-really-early-durin.patch
@@ -0,0 +1,90 @@
+From a3b8feb9320f745f960fe8f7006183137f4969b1 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Mon, 2 Nov 2015 09:34:05 +0100
+Subject: [PATCH] core: bump net.unix.max_dgram_qlen really early during boot
+
+Only that way it actually has an effect on all our sockets, including
+$NOTIFY_SOCKET.
+
+(cherry picked from commit 19854865a877a3a4fa3d04550c15a99c0e1187ff)
+Related: #1267707
+---
+ src/core/main.c  | 36 ++++++++++++++++++++++++++++++++++++
+ src/shared/def.h |  3 +++
+ 2 files changed, 39 insertions(+)
+
+diff --git a/src/core/main.c b/src/core/main.c
+index 60ea36c..c9d8ce4 100644
+--- a/src/core/main.c
++++ b/src/core/main.c
+@@ -1198,6 +1198,7 @@ static int status_welcome(void) {
+ 
+ static int write_container_id(void) {
+         const char *c;
++        int r;
+ 
+         c = getenv("container");
+         if (isempty(c))
+@@ -1206,6 +1207,40 @@ static int write_container_id(void) {
+         return write_string_file("/run/systemd/container", c);
+ }
+ 
++static int bump_unix_max_dgram_qlen(void) {
++        _cleanup_free_ char *qlen = NULL;
++        unsigned long v;
++        int r;
++
++        /* Let's bump the net.unix.max_dgram_qlen sysctl. The kernel
++         * default of 16 is simply too low. We set the value really
++         * really early during boot, so that it is actually applied to
++         * all our sockets, including the $NOTIFY_SOCKET one. */
++
++        r = read_one_line_file("/proc/sys/net/unix/max_dgram_qlen", &qlen);
++        if (r < 0)
++                return log_warning_errno(r, "Failed to read AF_UNIX datagram queue length, ignoring: %m");
++
++        r = safe_atolu(qlen, &v);
++        if (r < 0)
++                return log_warning_errno(r, "Failed to parse AF_UNIX datagram queue length, ignoring: %m");
++
++        if (v >= DEFAULT_UNIX_MAX_DGRAM_QLEN)
++                return 0;
++
++        free(qlen);
++        qlen = NULL;
++        if (asprintf(&qlen, "%lu\n", DEFAULT_UNIX_MAX_DGRAM_QLEN) < 0)
++                return log_oom();
++
++        r = write_string_file("/proc/sys/net/unix/max_dgram_qlen", qlen);
++        if (r < 0)
++                return log_full_errno(IN_SET(r, -EROFS, -EPERM, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
++                                      "Failed to bump AF_UNIX datagram queue length, ignoring: %m");
++
++        return 1;
++}
++
+ int main(int argc, char *argv[]) {
+         Manager *m = NULL;
+         int r, retval = EXIT_FAILURE;
+@@ -1571,6 +1606,7 @@ int main(int argc, char *argv[]) {
+                 hostname_setup();
+                 machine_id_setup(NULL);
+                 loopback_setup();
++                bump_unix_max_dgram_qlen();
+ 
+                 test_mtab();
+                 test_usr();
+diff --git a/src/shared/def.h b/src/shared/def.h
+index a3d9fcf..76daf01 100644
+--- a/src/shared/def.h
++++ b/src/shared/def.h
+@@ -35,6 +35,9 @@
+  * the watchdog pings will keep the loop busy. */
+ #define DEFAULT_EXIT_USEC (30*USEC_PER_SEC)
+ 
++/* The default value for the net.unix.max_dgram_qlen sysctl */
++#define DEFAULT_UNIX_MAX_DGRAM_QLEN 512UL
++
+ #define SYSTEMD_CGROUP_CONTROLLER "name=systemd"
+ 
+ #define SIGNALS_CRASH_HANDLER SIGSEGV,SIGILL,SIGFPE,SIGBUS,SIGQUIT,SIGABRT
diff --git a/SOURCES/0365-core-fix-priority-ordering-in-notify-handling.patch b/SOURCES/0365-core-fix-priority-ordering-in-notify-handling.patch
new file mode 100644
index 0000000..bc8efb1
--- /dev/null
+++ b/SOURCES/0365-core-fix-priority-ordering-in-notify-handling.patch
@@ -0,0 +1,228 @@
+From 64e21697bdefe0a37edc8557fd110daea2667771 Mon Sep 17 00:00:00 2001
+From: David Herrmann <dh.herrmann@gmail.com>
+Date: Wed, 28 Oct 2015 19:11:36 +0100
+Subject: [PATCH] core: fix priority ordering in notify-handling
+
+Currently, we dispatch NOTIFY messages in a tight loop. Regardless how
+much data is incoming, we always dispatch everything that is queued.
+This, however, completely breaks priority event-handling of sd-event.
+When dispatching one NOTIFY event, another completely different event
+might fire, or might be queued by the NOTIFY handling. However, this
+event will not get dispatched until all other further NOTIFY messages are
+handled. Those might even arrive _after_ the other event fired, and as
+such completely break priority ordering of sd-event (which several code
+paths rely on).
+
+Break this by never dispatching multiple messages. Just return after each
+message that was read and let sd-event handle everything else.
+
+(The patch looks scarier that it is. It basically just drops the for(;;)
+ loop and re-indents the loop-content.)
+
+(cherry picked from commit b215b0ede11c0dda90009c8412609d2416150075)
+Related: #1267707
+---
+ src/core/manager.c | 158 ++++++++++++++++++++++++++---------------------------
+ 1 file changed, 78 insertions(+), 80 deletions(-)
+
+diff --git a/src/core/manager.c b/src/core/manager.c
+index 5da8365..c502199 100644
+--- a/src/core/manager.c
++++ b/src/core/manager.c
+@@ -1635,9 +1635,33 @@ static void manager_invoke_notify_message(Manager *m, Unit *u, pid_t pid, char *
+ }
+ 
+ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
++        _cleanup_fdset_free_ FDSet *fds = NULL;
+         Manager *m = userdata;
++
++        char buf[NOTIFY_BUFFER_MAX+1];
++        struct iovec iovec = {
++                .iov_base = buf,
++                .iov_len = sizeof(buf)-1,
++        };
++        union {
++                struct cmsghdr cmsghdr;
++                uint8_t buf[CMSG_SPACE(sizeof(struct ucred)) +
++                            CMSG_SPACE(sizeof(int) * NOTIFY_FD_MAX)];
++        } control = {};
++        struct msghdr msghdr = {
++                .msg_iov = &iovec,
++                .msg_iovlen = 1,
++                .msg_control = &control,
++                .msg_controllen = sizeof(control),
++        };
++
++        struct cmsghdr *cmsg;
++        struct ucred *ucred = NULL;
++        bool found = false;
++        Unit *u1, *u2, *u3;
++        int r, *fd_array = NULL;
++        unsigned n_fds = 0;
+         ssize_t n;
+-        int r;
+ 
+         assert(m);
+         assert(m->notify_fd == fd);
+@@ -1647,108 +1671,82 @@ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t
+                 return 0;
+         }
+ 
+-        for (;;) {
+-                _cleanup_fdset_free_ FDSet *fds = NULL;
+-                char buf[NOTIFY_BUFFER_MAX+1];
+-                struct iovec iovec = {
+-                        .iov_base = buf,
+-                        .iov_len = sizeof(buf)-1,
+-                };
+-                union {
+-                        struct cmsghdr cmsghdr;
+-                        uint8_t buf[CMSG_SPACE(sizeof(struct ucred)) +
+-                                    CMSG_SPACE(sizeof(int) * NOTIFY_FD_MAX)];
+-                } control = {};
+-                struct msghdr msghdr = {
+-                        .msg_iov = &iovec,
+-                        .msg_iovlen = 1,
+-                        .msg_control = &control,
+-                        .msg_controllen = sizeof(control),
+-                };
+-                struct cmsghdr *cmsg;
+-                struct ucred *ucred = NULL;
+-                bool found = false;
+-                Unit *u1, *u2, *u3;
+-                int *fd_array = NULL;
+-                unsigned n_fds = 0;
+-
+-                n = recvmsg(m->notify_fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
+-                if (n < 0) {
+-                        if (errno == EAGAIN || errno == EINTR)
+-                                break;
++        n = recvmsg(m->notify_fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
++        if (n < 0) {
++                if (errno == EAGAIN || errno == EINTR)
++                        return 0;
+ 
+-                        return -errno;
+-                }
++                return -errno;
++        }
+ 
+-                for (cmsg = CMSG_FIRSTHDR(&msghdr); cmsg; cmsg = CMSG_NXTHDR(&msghdr, cmsg)) {
+-                        if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
++        for (cmsg = CMSG_FIRSTHDR(&msghdr); cmsg; cmsg = CMSG_NXTHDR(&msghdr, cmsg)) {
++                if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
+ 
+-                                fd_array = (int*) CMSG_DATA(cmsg);
+-                                n_fds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
++                        fd_array = (int*) CMSG_DATA(cmsg);
++                        n_fds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
+ 
+-                        } else if (cmsg->cmsg_level == SOL_SOCKET &&
+-                                   cmsg->cmsg_type == SCM_CREDENTIALS &&
+-                                   cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
++                } else if (cmsg->cmsg_level == SOL_SOCKET &&
++                           cmsg->cmsg_type == SCM_CREDENTIALS &&
++                           cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
+ 
+-                                ucred = (struct ucred*) CMSG_DATA(cmsg);
+-                        }
++                        ucred = (struct ucred*) CMSG_DATA(cmsg);
+                 }
++        }
+ 
+-                if (n_fds > 0) {
+-                        assert(fd_array);
++        if (n_fds > 0) {
++                assert(fd_array);
+ 
+-                        r = fdset_new_array(&fds, fd_array, n_fds);
+-                        if (r < 0) {
+-                                close_many(fd_array, n_fds);
+-                                return log_oom();
+-                        }
++                r = fdset_new_array(&fds, fd_array, n_fds);
++                if (r < 0) {
++                        close_many(fd_array, n_fds);
++                        return log_oom();
+                 }
++        }
+ 
+-                if (!ucred || ucred->pid <= 0) {
+-                        log_warning("Received notify message without valid credentials. Ignoring.");
+-                        continue;
+-                }
++        if (!ucred || ucred->pid <= 0) {
++                log_warning("Received notify message without valid credentials. Ignoring.");
++                return 0;
++        }
+ 
+-                if ((size_t) n >= sizeof(buf)) {
+-                        log_warning("Received notify message exceeded maximum size. Ignoring.");
+-                        continue;
+-                }
++        if ((size_t) n >= sizeof(buf)) {
++                log_warning("Received notify message exceeded maximum size. Ignoring.");
++                return 0;
++        }
+ 
+-                buf[n] = 0;
++        buf[n] = 0;
+ 
+-                /* Notify every unit that might be interested, but try
+-                 * to avoid notifying the same one multiple times. */
+-                u1 = manager_get_unit_by_pid(m, ucred->pid);
+-                if (u1) {
+-                        manager_invoke_notify_message(m, u1, ucred->pid, buf, n, fds);
+-                        found = true;
+-                }
++        /* Notify every unit that might be interested, but try
++         * to avoid notifying the same one multiple times. */
++        u1 = manager_get_unit_by_pid(m, ucred->pid);
++        if (u1) {
++                manager_invoke_notify_message(m, u1, ucred->pid, buf, n, fds);
++                found = true;
++        }
+ 
+-                u2 = hashmap_get(m->watch_pids1, LONG_TO_PTR(ucred->pid));
+-                if (u2 && u2 != u1) {
+-                        manager_invoke_notify_message(m, u2, ucred->pid, buf, n, fds);
+-                        found = true;
+-                }
++        u2 = hashmap_get(m->watch_pids1, LONG_TO_PTR(ucred->pid));
++        if (u2 && u2 != u1) {
++                manager_invoke_notify_message(m, u2, ucred->pid, buf, n, fds);
++                found = true;
++        }
+ 
+-                u3 = hashmap_get(m->watch_pids2, LONG_TO_PTR(ucred->pid));
+-                if (u3 && u3 != u2 && u3 != u1) {
+-                        manager_invoke_notify_message(m, u3, ucred->pid, buf, n, fds);
+-                        found = true;
+-                }
++        u3 = hashmap_get(m->watch_pids2, LONG_TO_PTR(ucred->pid));
++        if (u3 && u3 != u2 && u3 != u1) {
++                manager_invoke_notify_message(m, u3, ucred->pid, buf, n, fds);
++                found = true;
++        }
+ 
+-                if (!found)
+-                        log_warning("Cannot find unit for notify message of PID "PID_FMT".", ucred->pid);
++        if (!found)
++                log_warning("Cannot find unit for notify message of PID "PID_FMT".", ucred->pid);
+ 
+-                if (fdset_size(fds) > 0)
+-                        log_warning("Got auxiliary fds with notification message, closing all.");
+-        }
++        if (fdset_size(fds) > 0)
++                log_warning("Got auxiliary fds with notification message, closing all.");
+ 
+         return 0;
+ }
+ 
+ static void invoke_sigchld_event(Manager *m, Unit *u, siginfo_t *si) {
+         uint64_t iteration;
+-        
++
+         assert(m);
+         assert(u);
+         assert(si);
diff --git a/SOURCES/0366-tests-fix-personality-tests-on-ppc64-and-aarch64.patch b/SOURCES/0366-tests-fix-personality-tests-on-ppc64-and-aarch64.patch
new file mode 100644
index 0000000..96ae2f1
--- /dev/null
+++ b/SOURCES/0366-tests-fix-personality-tests-on-ppc64-and-aarch64.patch
@@ -0,0 +1,85 @@
+From 89a7c7e55af18c4f18c0d83c244dbe20ddb85515 Mon Sep 17 00:00:00 2001
+From: Jan Synacek <jsynacek@redhat.com>
+Date: Fri, 29 Jul 2016 15:03:02 +0200
+Subject: [PATCH] tests: fix personality tests on ppc64 and aarch64
+
+Resolves: #1361049
+---
+ src/shared/util.c                     | 16 ++++++++++++++++
+ src/test/test-execute.c               |  6 ++++++
+ test/exec-personality-aarch64.service |  7 +++++++
+ test/exec-personality-ppc64.service   |  7 +++++++
+ 4 files changed, 36 insertions(+)
+ create mode 100644 test/exec-personality-aarch64.service
+ create mode 100644 test/exec-personality-ppc64.service
+
+diff --git a/src/shared/util.c b/src/shared/util.c
+index f75ed9d..3030261 100644
+--- a/src/shared/util.c
++++ b/src/shared/util.c
+@@ -6986,6 +6986,22 @@ unsigned long personality_from_string(const char *p) {
+ 
+         if (streq(p, "s390"))
+                 return PER_LINUX;
++
++#elif defined(__powerpc64__)
++
++#  if defined(__BIG_ENDIAN__)
++        if (streq(p, "ppc64"))
++                return PER_LINUX;
++#  else
++        if (streq(p, "ppc64le"))
++                return PER_LINUX;
++#  endif
++
++#elif defined(__aarch64__)
++
++        if (streq(p, "aarch64"))
++                return PER_LINUX;
++
+ #endif
+ 
+         /* personality(7) documents that 0xffffffffUL is used for
+diff --git a/src/test/test-execute.c b/src/test/test-execute.c
+index 38522a1..5a02960 100644
+--- a/src/test/test-execute.c
++++ b/src/test/test-execute.c
+@@ -83,6 +83,12 @@ static void test_exec_personality(Manager *m) {
+ #elif defined(__s390__)
+         test(m, "exec-personality-s390.service", 0, CLD_EXITED);
+ 
++#elif defined(__powerpc64__)
++        test(m, "exec-personality-ppc64.service", 0, CLD_EXITED);
++
++#elif defined(__aarch64__)
++        test(m, "exec-personality-aarch64.service", 0, CLD_EXITED);
++
+ #else
+         test(m, "exec-personality-x86.service", 0, CLD_EXITED);
+ #endif
+diff --git a/test/exec-personality-aarch64.service b/test/exec-personality-aarch64.service
+new file mode 100644
+index 0000000..8511174
+--- /dev/null
++++ b/test/exec-personality-aarch64.service
+@@ -0,0 +1,7 @@
++[Unit]
++Description=Test for Personality=aarch64
++
++[Service]
++ExecStart=/bin/sh -c 'echo $(uname -m); exit $(test $(uname -m) = "aarch64")'
++Type=oneshot
++Personality=aarch64
+diff --git a/test/exec-personality-ppc64.service b/test/exec-personality-ppc64.service
+new file mode 100644
+index 0000000..4432074
+--- /dev/null
++++ b/test/exec-personality-ppc64.service
+@@ -0,0 +1,7 @@
++[Unit]
++Description=Test for Personality=ppc64
++
++[Service]
++ExecStart=/bin/sh -c 'echo $(uname -m); exit $(test $(uname -m) = "ppc64" -o $(uname -m) = "ppc64le")'
++Type=oneshot
++Personality=ppc64
diff --git a/SOURCES/0367-systemctl-consider-service-running-only-when-it-is-i.patch b/SOURCES/0367-systemctl-consider-service-running-only-when-it-is-i.patch
new file mode 100644
index 0000000..2197d54
--- /dev/null
+++ b/SOURCES/0367-systemctl-consider-service-running-only-when-it-is-i.patch
@@ -0,0 +1,29 @@
+From 94fec84897ab40bf2bc92f0d395a93ecac1b45be Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Nykr=C3=BDn?= <lnykryn@redhat.com>
+Date: Wed, 3 Aug 2016 17:08:37 +0200
+Subject: [PATCH] systemctl: consider service running only when it is in active
+ or reloading state (#3874)
+
+Otherwise for example services that are failing on start and have Restart=on-failure
+and bigger RestartSec systemctl status will return 0.
+
+Fixes: #3864
+Cherry-picked from: 7f5da8bd4fb1ba49ba40195a74ca76bb5d4d1f81
+Resolves: #1362461
+---
+ src/systemctl/systemctl.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
+index 93b7a19..b7496c0 100644
+--- a/src/systemctl/systemctl.c
++++ b/src/systemctl/systemctl.c
+@@ -4339,7 +4339,7 @@ static int show_one(
+         else if (streq(verb, "status")) {
+                 print_status_info(&info, ellipsized);
+ 
+-                if (info.active_state && STR_IN_SET(info.active_state, "inactive", "failed"))
++                if (info.active_state && !STR_IN_SET(info.active_state, "active", "reloading"))
+                         r = EXIT_PROGRAM_NOT_RUNNING;
+                 else
+                         r = EXIT_PROGRAM_RUNNING_OR_SERVICE_OK;
diff --git a/SOURCES/0368-install-do-not-crash-when-processing-empty-masked-un.patch b/SOURCES/0368-install-do-not-crash-when-processing-empty-masked-un.patch
new file mode 100644
index 0000000..874819d
--- /dev/null
+++ b/SOURCES/0368-install-do-not-crash-when-processing-empty-masked-un.patch
@@ -0,0 +1,24 @@
+From 7d6f53ece9b0a397ee2f8bdaa1a52ef2f03bd81f Mon Sep 17 00:00:00 2001
+From: Michal Sekletar <msekleta@redhat.com>
+Date: Tue, 9 Aug 2016 13:02:37 +0200
+Subject: [PATCH] install: do not crash when processing empty (masked) unit
+ file
+
+Related: #1159308
+---
+ src/shared/install.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/shared/install.c b/src/shared/install.c
+index f190dbf..f7f9866 100644
+--- a/src/shared/install.c
++++ b/src/shared/install.c
+@@ -996,7 +996,7 @@ static int unit_file_load(
+         if (fstat(fd, &st) < 0)
+                 return -errno;
+         if (null_or_empty(&st)) {
+-               info->type = UNIT_FILE_MASKED;
++               info->type = UNIT_FILE_TYPE_MASKED;
+                 return 0;
+         }
+         if (S_ISDIR(st.st_mode))
diff --git a/SOURCES/0369-Revert-install-fix-disable-via-unit-file-path.patch b/SOURCES/0369-Revert-install-fix-disable-via-unit-file-path.patch
new file mode 100644
index 0000000..0cb195e
--- /dev/null
+++ b/SOURCES/0369-Revert-install-fix-disable-via-unit-file-path.patch
@@ -0,0 +1,32 @@
+From f79f65a2957cca23e0347eb2c9dfbd53be5c8dba Mon Sep 17 00:00:00 2001
+From: Michal Sekletar <msekleta@redhat.com>
+Date: Mon, 8 Aug 2016 15:15:14 +0200
+Subject: [PATCH] Revert "install: fix disable via unit file path"
+
+This reverts commit 96df052a6a9d09cde2d437861727bf37fe6446b4.
+
+Related: #1348208
+---
+ src/shared/install.c | 8 +++-----
+ 1 file changed, 3 insertions(+), 5 deletions(-)
+
+diff --git a/src/shared/install.c b/src/shared/install.c
+index f7f9866..9962508 100644
+--- a/src/shared/install.c
++++ b/src/shared/install.c
+@@ -1910,12 +1910,10 @@ int unit_file_disable(
+                 return r;
+ 
+         STRV_FOREACH(i, files) {
++                if (!unit_name_is_valid(*i, UNIT_NAME_ANY))
++                        return -EINVAL;
+ 
+-                if (!is_path(*i))
+-                        r = install_info_add(&c, *i, NULL, NULL);
+-                else
+-                        r = install_info_add(&c, NULL, *i, NULL);
+-
++                r = install_info_add(&c, *i, NULL, NULL);
+                 if (r < 0)
+                         return r;
+         }
diff --git a/SOURCES/0370-systemctl-allow-disable-on-the-unit-file-path-but-wa.patch b/SOURCES/0370-systemctl-allow-disable-on-the-unit-file-path-but-wa.patch
new file mode 100644
index 0000000..03a19ba
--- /dev/null
+++ b/SOURCES/0370-systemctl-allow-disable-on-the-unit-file-path-but-wa.patch
@@ -0,0 +1,82 @@
+From 1f8b1e35e3ec80c50201403171b7375ff14c808c Mon Sep 17 00:00:00 2001
+From: Michal Sekletar <msekletar@users.noreply.github.com>
+Date: Tue, 26 Jul 2016 14:25:52 +0200
+Subject: [PATCH] systemctl: allow disable on the unit file path, but warn
+ about it (#3806)
+
+systemd now returns an error when it is asked to perform disable on the
+unit file path. In the past this was allowed, but systemd never really
+considered an actual content of the [Install] section of the unit
+file. Instead it performed disable on the unit name, i.e. purged all
+symlinks pointing to the given unit file (undo of implicit link action
+done by systemd when enable is called on the unit file path) and all
+symlinks that have the same basename as the given unit file.
+
+However, to notice that [Install] info of the file is not consulted one
+must create additional symlinks manually. I argue that in most cases
+users do not create such links. Let's be nice to our users and don't
+break existing scripts that expect disable to work with the unit file
+path.
+
+Fixes #3706.
+
+IMPORTANT
+=========
+Note that in this downstream backport we actually pass false to
+normalize_names(), hence it will not produce any warning when full path
+is passed in. This is because we need to preserve behavior compatible
+with prior systemd versions shipped in RHEL.
+
+Cherry-picked from: 1d3c86c06fca8311923fcf81af0ab0bbb66e1edd
+Resolves: #1348208
+---
+ src/systemctl/systemctl.c | 29 +++++++++++++++++++++++++++++
+ 1 file changed, 29 insertions(+)
+
+diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
+index b7496c0..5899818 100644
+--- a/src/systemctl/systemctl.c
++++ b/src/systemctl/systemctl.c
+@@ -5333,6 +5333,29 @@ static int mangle_names(char **original_names, char ***mangled_names) {
+         return 0;
+ }
+ 
++static int normalize_names(char **names, bool warn_if_path) {
++        char **u;
++        bool was_path = false;
++
++        STRV_FOREACH(u, names) {
++                int r;
++
++                if (!is_path(*u))
++                        continue;
++
++                r = free_and_strdup(u, basename(*u));
++                if (r < 0)
++                        return log_error_errno(r, "Failed to normalize unit file path: %m");
++
++                was_path = true;
++        }
++
++        if (warn_if_path && was_path)
++                log_warning("Warning: Can't execute disable on the unit file path. Proceeding with the unit name.");
++
++        return 0;
++}
++
+ static int enable_unit(sd_bus *bus, char **args) {
+         _cleanup_strv_free_ char **names = NULL;
+         const char *verb = args[0];
+@@ -5357,6 +5380,12 @@ static int enable_unit(sd_bus *bus, char **args) {
+         if (strv_isempty(names))
+                 return 0;
+ 
++        if (streq(verb, "disable")) {
++                r = normalize_names(names, false);
++                if (r < 0)
++                        return r;
++        }
++
+         if (!bus || avoid_bus()) {
+                 if (streq(verb, "enable")) {
+                         r = unit_file_enable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
diff --git a/SOURCES/0371-tmpfiles-enforce-ordering-when-executing-lines.patch b/SOURCES/0371-tmpfiles-enforce-ordering-when-executing-lines.patch
new file mode 100644
index 0000000..193b35c
--- /dev/null
+++ b/SOURCES/0371-tmpfiles-enforce-ordering-when-executing-lines.patch
@@ -0,0 +1,102 @@
+From fd09d69b1bca2b4b602f4ee98d4749a39af04bb4 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Fri, 10 Apr 2015 16:22:22 +0200
+Subject: [PATCH] tmpfiles: enforce ordering when executing lines
+
+Always create files first, and then adjust their ACLs, xattrs, file
+attributes, never the opposite. Previously the order was not
+deterministic, thus possibly first adjusting ACLs/xattrs/file
+attributes before actually creating the items.
+
+Cherry-picked from: 17493fa5d17cadce3b773692d3eeab137de7d323
+Resolves: #1365870
+---
+ src/tmpfiles/tmpfiles.c | 39 +++++++++++++++++++++++++++++++++++----
+ 1 file changed, 35 insertions(+), 4 deletions(-)
+
+diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
+index 64c733a..bda89df 100644
+--- a/src/tmpfiles/tmpfiles.c
++++ b/src/tmpfiles/tmpfiles.c
+@@ -78,18 +78,18 @@ typedef enum ItemType {
+         COPY_FILES = 'C',
+ 
+         /* These ones take globs */
++        WRITE_FILE = 'w',
+         SET_XATTR = 't',
+         RECURSIVE_SET_XATTR = 'T',
+         SET_ACL = 'a',
+         RECURSIVE_SET_ACL = 'A',
+-        WRITE_FILE = 'w',
+         IGNORE_PATH = 'x',
+         IGNORE_DIRECTORY_PATH = 'X',
+         REMOVE_PATH = 'r',
+         RECURSIVE_REMOVE_PATH = 'R',
+-        ADJUST_MODE = 'm', /* legacy, 'z' is identical to this */
+         RELABEL_PATH = 'z',
+         RECURSIVE_RELABEL_PATH = 'Z',
++        ADJUST_MODE = 'm', /* legacy, 'z' is identical to this */
+ } ItemType;
+ 
+ typedef struct Item {
+@@ -1480,6 +1480,31 @@ static void item_array_free(ItemArray *a) {
+         free(a);
+ }
+ 
++static int item_compare(const void *a, const void *b) {
++        const Item *x = a, *y = b;
++
++        /* Make sure that the ownership taking item is put first, so
++         * that we first create the node, and then can adjust it */
++
++        if (takes_ownership(x->type) && !takes_ownership(y->type))
++                return -1;
++        if (!takes_ownership(x->type) && takes_ownership(y->type))
++                return 1;
++
++        return (int) x->type - (int) y->type;
++}
++
++static void item_array_sort(ItemArray *a) {
++
++        /* Sort an item array, to enforce stable ordering in which we
++         * apply things. */
++
++        if (a->count <= 1)
++                return;
++
++        qsort(a->items, a->count, sizeof(Item), item_compare);
++}
++
+ static bool item_compatible(Item *a, Item *b) {
+         assert(a);
+         assert(b);
+@@ -1806,6 +1831,8 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
+                 return log_oom();
+ 
+         memcpy(existing->items + existing->count++, &i, sizeof(i));
++        item_array_sort(existing);
++
+         zero(i);
+         return 0;
+ }
+@@ -2045,13 +2072,17 @@ int main(int argc, char *argv[]) {
+                 }
+         }
+ 
+-        HASHMAP_FOREACH(a, globs, iterator) {
++        /* The non-globbing ones usually create things, hence we apply
++         * them first */
++        HASHMAP_FOREACH(a, items, iterator) {
+                 k = process_item_array(a);
+                 if (k < 0 && r == 0)
+                         r = k;
+         }
+ 
+-        HASHMAP_FOREACH(a, items, iterator) {
++        /* The globbing ones usually alter things, hence we apply them
++         * second. */
++        HASHMAP_FOREACH(a, globs, iterator) {
+                 k = process_item_array(a);
+                 if (k < 0 && r == 0)
+                         r = k;
diff --git a/SOURCES/0372-Introduce-bus_unit_check_load_state-helper.patch b/SOURCES/0372-Introduce-bus_unit_check_load_state-helper.patch
new file mode 100644
index 0000000..ed25b0f
--- /dev/null
+++ b/SOURCES/0372-Introduce-bus_unit_check_load_state-helper.patch
@@ -0,0 +1,53 @@
+From c55a7f9448378c10a7e8074db908502ae5ff60aa Mon Sep 17 00:00:00 2001
+From: Franck Bui <fbui@suse.com>
+Date: Fri, 13 Nov 2015 14:12:19 +0100
+Subject: [PATCH] Introduce bus_unit_check_load_state() helper
+
+This function is used to check that a previous unit load succeed and
+returns 0 in this case.
+
+In the case the load failed, the function setup a bus error
+accordingly and returns -errno.
+
+(cherry picked from commit 000a996dc46c187f803b67b0b0d51ad4d0bc1658)
+Related: #1256858
+---
+ src/core/dbus-unit.c | 17 +++++++++++++++++
+ src/core/dbus-unit.h |  2 ++
+ 2 files changed, 19 insertions(+)
+
+diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c
+index 49770bf..c3654db 100644
+--- a/src/core/dbus-unit.c
++++ b/src/core/dbus-unit.c
+@@ -1083,3 +1083,20 @@ int bus_unit_set_properties(
+ 
+         return n;
+ }
++
++int bus_unit_check_load_state(Unit *u, sd_bus_error *error) {
++
++        if (u->load_state == UNIT_LOADED)
++                return 0;
++
++        /* Give a better description of the unit error when
++         * possible. Note that in the case of UNIT_MASKED, load_error
++         * is not set. */
++        if (u->load_state == UNIT_MASKED)
++                return sd_bus_error_setf(error, BUS_ERROR_UNIT_MASKED, "Unit is masked.");
++
++        if (u->load_state == UNIT_NOT_FOUND)
++                return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit not found.");
++
++        return sd_bus_error_set_errnof(error, u->load_error, "Unit is not loaded properly: %m.");
++}
+diff --git a/src/core/dbus-unit.h b/src/core/dbus-unit.h
+index 57a5e19..4338496 100644
+--- a/src/core/dbus-unit.h
++++ b/src/core/dbus-unit.h
+@@ -37,3 +37,5 @@ int bus_unit_method_reset_failed(sd_bus *bus, sd_bus_message *message, void *use
+ int bus_unit_queue_job(sd_bus *bus, sd_bus_message *message, Unit *u, JobType type, JobMode mode, bool reload_if_possible, sd_bus_error *error);
+ int bus_unit_set_properties(Unit *u, sd_bus_message *message, UnitSetPropertiesMode mode, bool commit, sd_bus_error *error);
+ int bus_unit_method_set_properties(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error);
++
++int bus_unit_check_load_state(Unit *u, sd_bus_error *error);
diff --git a/SOURCES/0373-core-use-bus_unit_check_load_state-in-transaction_ad.patch b/SOURCES/0373-core-use-bus_unit_check_load_state-in-transaction_ad.patch
new file mode 100644
index 0000000..3962654
--- /dev/null
+++ b/SOURCES/0373-core-use-bus_unit_check_load_state-in-transaction_ad.patch
@@ -0,0 +1,76 @@
+From a47b58110f92415fcb69441031e4d04fec48b852 Mon Sep 17 00:00:00 2001
+From: Franck Bui <fbui@suse.com>
+Date: Wed, 2 Dec 2015 17:03:28 +0100
+Subject: [PATCH] core: use bus_unit_check_load_state() in
+ transaction_add_job_and_dependencies()
+
+(cherry picked from commit ee87525c5eeacf3ce8fb730bcd3658e8da085046)
+Related: #1256858
+---
+ src/core/transaction.c    | 27 +++++----------------------
+ src/systemctl/systemctl.c |  5 +++++
+ 2 files changed, 10 insertions(+), 22 deletions(-)
+
+diff --git a/src/core/transaction.c b/src/core/transaction.c
+index aed64fa..57e9cb3 100644
+--- a/src/core/transaction.c
++++ b/src/core/transaction.c
+@@ -26,6 +26,7 @@
+ #include "bus-util.h"
+ #include "bus-error.h"
+ #include "transaction.h"
++#include "dbus-unit.h"
+ 
+ static void transaction_unlink_job(Transaction *tr, Job *j, bool delete_dependencies);
+ 
+@@ -857,30 +858,12 @@ int transaction_add_job_and_dependencies(
+                 return sd_bus_error_setf(e, BUS_ERROR_LOAD_FAILED,
+                                          "Unit %s is not loaded properly.", unit->id);
+ 
+-        if (type != JOB_STOP && unit->load_state == UNIT_ERROR) {
+-                if (unit->load_error == -ENOENT || unit->manager->test_run)
+-                        return sd_bus_error_setf(e, BUS_ERROR_LOAD_FAILED,
+-                                                 "Unit %s failed to load: %s.",
+-                                                 unit->id,
+-                                                 strerror(-unit->load_error));
+-                else
+-                        return sd_bus_error_setf(e, BUS_ERROR_LOAD_FAILED,
+-                                                 "Unit %s failed to load: %s. "
+-                                                 "See system logs and 'systemctl status %s' for details.",
+-                                                 unit->id,
+-                                                 strerror(-unit->load_error),
+-                                                 unit->id);
++        if (type != JOB_STOP) {
++                r = bus_unit_check_load_state(unit, e);
++                if (r < 0)
++                        return r;
+         }
+ 
+-        if (type != JOB_STOP && unit->load_state == UNIT_NOT_FOUND)
+-                return sd_bus_error_setf(e, BUS_ERROR_LOAD_FAILED,
+-                                         "Unit %s failed to load: %s.",
+-                                         unit->id, strerror(-unit->load_error));
+-
+-        if (type != JOB_STOP && unit->load_state == UNIT_MASKED)
+-                return sd_bus_error_setf(e, BUS_ERROR_UNIT_MASKED,
+-                                         "Unit %s is masked.", unit->id);
+-
+         if (!unit_job_is_applicable(unit, type))
+                 return sd_bus_error_setf(e, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE,
+                                          "Job type %s is not applicable for unit %s.",
+diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
+index 5899818..e4b404a 100644
+--- a/src/systemctl/systemctl.c
++++ b/src/systemctl/systemctl.c
+@@ -2617,6 +2617,11 @@ static int start_unit_one(
+                 verb = method_to_verb(method);
+ 
+                 log_error("Failed to %s %s: %s", verb, name, bus_error_message(error, r));
++
++                if (!sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) &&
++                    !sd_bus_error_has_name(error, BUS_ERROR_UNIT_MASKED))
++                        log_error("See system logs and 'systemctl status %s' for details.", name);
++
+                 return r;
+         }
+ 
diff --git a/SOURCES/0374-udev-path_id-correct-segmentation-fault-due-to-missi.patch b/SOURCES/0374-udev-path_id-correct-segmentation-fault-due-to-missi.patch
new file mode 100644
index 0000000..a0b2982
--- /dev/null
+++ b/SOURCES/0374-udev-path_id-correct-segmentation-fault-due-to-missi.patch
@@ -0,0 +1,31 @@
+From fb9a50a0ad64f28c00c7d0bbc4ee8908d4233593 Mon Sep 17 00:00:00 2001
+From: Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
+Date: Fri, 19 Feb 2016 15:21:18 +0100
+Subject: [PATCH] udev/path_id: correct segmentation fault due to missing NULL
+ check
+
+Running "udevadm test-builtin path_id /sys/devices/platform/" results
+in a segmentation fault.
+
+The problem is that udev_device_get_subsystem(dev) might return NULL
+in a streq() call.  Solve this problem by using streq_ptr() instead.
+
+Cherry-picked from: 5181ab917d6407cb57043e98955f0de1614366ea
+Resolves: #1365556
+---
+ src/udev/udev-builtin-path_id.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/udev/udev-builtin-path_id.c b/src/udev/udev-builtin-path_id.c
+index 8359e23..a3b019b 100644
+--- a/src/udev/udev-builtin-path_id.c
++++ b/src/udev/udev-builtin-path_id.c
+@@ -729,7 +729,7 @@ restart:
+          * devices do not expose their buses and do not provide a unique
+          * and predictable name that way.
+          */
+-        if (streq(udev_device_get_subsystem(dev), "block") && !supported_transport) {
++        if (streq_ptr(udev_device_get_subsystem(dev), "block") && !supported_transport) {
+                 free(path);
+                 path = NULL;
+         }
diff --git a/SOURCES/0375-rules-load-sg-driver-also-when-scsi_target-appears-4.patch b/SOURCES/0375-rules-load-sg-driver-also-when-scsi_target-appears-4.patch
new file mode 100644
index 0000000..8b12005
--- /dev/null
+++ b/SOURCES/0375-rules-load-sg-driver-also-when-scsi_target-appears-4.patch
@@ -0,0 +1,22 @@
+From 3724d66bec53bf53e5378269e6ddf68c99da7f0c Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Nykr=C3=BDn?= <lnykryn@redhat.com>
+Date: Thu, 18 Aug 2016 14:51:19 +0200
+Subject: [PATCH] rules: load sg driver also when scsi_target appears (#45)
+
+Resolves: #1322773
+---
+ rules/40-redhat.rules | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/rules/40-redhat.rules b/rules/40-redhat.rules
+index 9a48add..3335fe5 100644
+--- a/rules/40-redhat.rules
++++ b/rules/40-redhat.rules
+@@ -11,6 +11,7 @@ ACTION=="add", SUBSYSTEM=="module", KERNEL=="bridge", RUN+="/usr/lib/systemd/sys
+ 
+ # load SCSI generic (sg) driver
+ SUBSYSTEM=="scsi", ENV{DEVTYPE}=="scsi_device", TEST!="[module/sg]", RUN+="/sbin/modprobe -bv sg"
++SUBSYSTEM=="scsi", ENV{DEVTYPE}=="scsi_target", TEST!="[module/sg]", RUN+="/sbin/modprobe -bv sg"
+ 
+ # Rule for prandom character device node permissions
+ KERNEL=="prandom", MODE="0644"
diff --git a/SOURCES/0376-fix-gcc-warnings-about-uninitialized-variables.patch b/SOURCES/0376-fix-gcc-warnings-about-uninitialized-variables.patch
new file mode 100644
index 0000000..d7e92ab
--- /dev/null
+++ b/SOURCES/0376-fix-gcc-warnings-about-uninitialized-variables.patch
@@ -0,0 +1,483 @@
+From c815acfb5863d9562a3f1e9cbd6204da3364860c Mon Sep 17 00:00:00 2001
+From: Harald Hoyer <harald@redhat.com>
+Date: Fri, 27 Mar 2015 12:02:49 +0100
+Subject: [PATCH] fix gcc warnings about uninitialized variables
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+like:
+
+src/shared/install.c: In function ‘unit_file_lookup_state’:
+src/shared/install.c:1861:16: warning: ‘r’ may be used uninitialized in
+this function [-Wmaybe-uninitialized]
+         return r < 0 ? r : state;
+                ^
+src/shared/install.c:1796:13: note: ‘r’ was declared here
+         int r;
+             ^
+
+Conflicts:
+	src/journal/journal-file.c
+	src/shared/btrfs-util.c
+        src/shared/install.c
+
+Cherry-picked from: a7f7d1bde43fc825c49afea3f946f5b4b3d563e0
+Related: #1318994
+---
+ src/import/import-job.c                   | 2 +-
+ src/journal-remote/journal-gatewayd.c     | 2 +-
+ src/journal-remote/journal-remote-parse.c | 2 +-
+ src/journal-remote/journal-remote.c       | 4 ++--
+ src/journal/catalog.c                     | 2 +-
+ src/journal/coredump.c                    | 4 ++--
+ src/journal/journal-file.c                | 6 +++---
+ src/journal/journal-vacuum.c              | 2 +-
+ src/journal/journalctl.c                  | 2 +-
+ src/journal/test-journal-stream.c         | 2 +-
+ src/libsystemd-network/lldp-tlv.c         | 8 ++++----
+ src/libsystemd-network/sd-dhcp-server.c   | 2 +-
+ src/libsystemd-network/sd-pppoe.c         | 2 +-
+ src/libsystemd/sd-login/sd-login.c        | 2 +-
+ src/network/networkctl.c                  | 2 +-
+ src/resolve/resolved-dns-transaction.c    | 2 +-
+ src/resolve/test-dns-domain.c             | 2 +-
+ src/shared/base-filesystem.c              | 2 +-
+ src/shared/capability.c                   | 2 +-
+ src/shared/copy.c                         | 6 +++---
+ src/shared/install.c                      | 2 +-
+ src/shared/logs-show.c                    | 2 +-
+ src/shared/util.c                         | 4 ++--
+ src/test/test-path.c                      | 2 +-
+ src/test/test-pty.c                       | 2 +-
+ src/udev/net/link-config.c                | 2 +-
+ 26 files changed, 36 insertions(+), 36 deletions(-)
+
+diff --git a/src/import/import-job.c b/src/import/import-job.c
+index 5f9cfd3..d826f49 100644
+--- a/src/import/import-job.c
++++ b/src/import/import-job.c
+@@ -80,7 +80,7 @@ void import_job_curl_on_finished(CurlGlue *g, CURL *curl, CURLcode result) {
+         long status;
+         int r;
+ 
+-        if (curl_easy_getinfo(curl, CURLINFO_PRIVATE, &j) != CURLE_OK)
++        if (curl_easy_getinfo(curl, CURLINFO_PRIVATE, (char **)&j) != CURLE_OK)
+                 return;
+ 
+         if (!j || j->state == IMPORT_JOB_DONE || j->state == IMPORT_JOB_FAILED)
+diff --git a/src/journal-remote/journal-gatewayd.c b/src/journal-remote/journal-gatewayd.c
+index 576f7ca..d1f0ce3 100644
+--- a/src/journal-remote/journal-gatewayd.c
++++ b/src/journal-remote/journal-gatewayd.c
+@@ -736,7 +736,7 @@ static int request_handler_machine(
+         RequestMeta *m = connection_cls;
+         int r;
+         _cleanup_free_ char* hostname = NULL, *os_name = NULL;
+-        uint64_t cutoff_from = 0, cutoff_to = 0, usage;
++        uint64_t cutoff_from = 0, cutoff_to = 0, usage = 0;
+         char *json;
+         sd_id128_t mid, bid;
+         _cleanup_free_ char *v = NULL;
+diff --git a/src/journal-remote/journal-remote-parse.c b/src/journal-remote/journal-remote-parse.c
+index 7e62954..64089da 100644
+--- a/src/journal-remote/journal-remote-parse.c
++++ b/src/journal-remote/journal-remote-parse.c
+@@ -316,7 +316,7 @@ int process_data(RemoteSource *source) {
+         switch(source->state) {
+         case STATE_LINE: {
+                 char *line, *sep;
+-                size_t n;
++                size_t n = 0;
+ 
+                 assert(source->data_size == 0);
+ 
+diff --git a/src/journal-remote/journal-remote.c b/src/journal-remote/journal-remote.c
+index 9c515f9..4fac55c 100644
+--- a/src/journal-remote/journal-remote.c
++++ b/src/journal-remote/journal-remote.c
+@@ -353,7 +353,7 @@ static int remove_source(RemoteServer *s, int fd) {
+ 
+ static int add_source(RemoteServer *s, int fd, char* name, bool own_name) {
+ 
+-        RemoteSource *source;
++        RemoteSource *source = NULL;
+         int r;
+ 
+         /* This takes ownership of name, even on failure, if own_name is true. */
+@@ -1148,7 +1148,7 @@ static int dispatch_raw_connection_event(sd_event_source *event,
+                 .size = sizeof(union sockaddr_union),
+                 .type = SOCK_STREAM,
+         };
+-        char *hostname;
++        char *hostname = NULL;
+ 
+         fd2 = accept_connection("raw", fd, &addr, &hostname);
+         if (fd2 < 0)
+diff --git a/src/journal/catalog.c b/src/journal/catalog.c
+index f170232..a9c40c6 100644
+--- a/src/journal/catalog.c
++++ b/src/journal/catalog.c
+@@ -559,7 +559,7 @@ static const char *find_id(void *p, sd_id128_t id) {
+ int catalog_get(const char* database, sd_id128_t id, char **_text) {
+         _cleanup_close_ int fd = -1;
+         void *p = NULL;
+-        struct stat st;
++        struct stat st = {};
+         char *text = NULL;
+         int r;
+         const char *s;
+diff --git a/src/journal/coredump.c b/src/journal/coredump.c
+index f7ba019..59ccd46 100644
+--- a/src/journal/coredump.c
++++ b/src/journal/coredump.c
+@@ -244,7 +244,7 @@ static int maybe_remove_external_coredump(const char *filename, off_t size) {
+ 
+ static int make_filename(const char *info[_INFO_LEN], char **ret) {
+         _cleanup_free_ char *c = NULL, *u = NULL, *p = NULL, *t = NULL;
+-        sd_id128_t boot;
++        sd_id128_t boot = {};
+         int r;
+ 
+         assert(info);
+@@ -843,7 +843,7 @@ log:
+         /* Optionally store the entire coredump in the journal */
+         if (IN_SET(arg_storage, COREDUMP_STORAGE_JOURNAL, COREDUMP_STORAGE_BOTH) &&
+             coredump_size <= (off_t) arg_journal_size_max) {
+-                size_t sz;
++                size_t sz = 0;
+ 
+                 /* Store the coredump itself in the journal */
+ 
+diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c
+index ef18497..2a93460 100644
+--- a/src/journal/journal-file.c
++++ b/src/journal/journal-file.c
+@@ -911,7 +911,7 @@ int journal_file_find_data_object_with_hash(
+                 if (o->object.flags & OBJECT_COMPRESSION_MASK) {
+ #if defined(HAVE_XZ) || defined(HAVE_LZ4)
+                         uint64_t l;
+-                        size_t rsize;
++                        size_t rsize = 0;
+ 
+                         l = le64toh(o->object.size);
+                         if (l <= offsetof(Object, data.payload))
+@@ -1075,7 +1075,7 @@ static int journal_file_append_data(
+ 
+ #if defined(HAVE_XZ) || defined(HAVE_LZ4)
+         if (JOURNAL_FILE_COMPRESS(f) && size >= COMPRESSION_SIZE_THRESHOLD) {
+-                size_t rsize;
++                size_t rsize = 0;
+ 
+                 compression = compress_blob(data, size, o->data.payload, &rsize);
+ 
+@@ -2903,7 +2903,7 @@ int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint6
+ 
+                 if (o->object.flags & OBJECT_COMPRESSION_MASK) {
+ #if defined(HAVE_XZ) || defined(HAVE_LZ4)
+-                        size_t rsize;
++                        size_t rsize = 0;
+ 
+                         r = decompress_blob(o->object.flags & OBJECT_COMPRESSION_MASK,
+                                             o->data.payload, l, &from->compress_buffer, &from->compress_buffer_size, &rsize, 0);
+diff --git a/src/journal/journal-vacuum.c b/src/journal/journal-vacuum.c
+index 832c327..856d11e 100644
+--- a/src/journal/journal-vacuum.c
++++ b/src/journal/journal-vacuum.c
+@@ -76,7 +76,7 @@ static void patch_realtime(
+                 unsigned long long *realtime) {
+ 
+         _cleanup_free_ const char *path = NULL;
+-        usec_t x, crtime;
++        usec_t x, crtime = 0;
+ 
+         /* The timestamp was determined by the file name, but let's
+          * see if the file might actually be older than the file name
+diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
+index a38ce4b..6ba8847 100644
+--- a/src/journal/journalctl.c
++++ b/src/journal/journalctl.c
+@@ -1644,7 +1644,7 @@ static int verify(sd_journal *j) {
+ 
+         ORDERED_HASHMAP_FOREACH(f, j->files, i) {
+                 int k;
+-                usec_t first, validated, last;
++                usec_t first = 0, validated = 0, last = 0;
+ 
+ #ifdef HAVE_GCRYPT
+                 if (!arg_verify_key && JOURNAL_HEADER_SEALED(f->header))
+diff --git a/src/journal/test-journal-stream.c b/src/journal/test-journal-stream.c
+index 3996e77..b8caeb3 100644
+--- a/src/journal/test-journal-stream.c
++++ b/src/journal/test-journal-stream.c
+@@ -42,7 +42,7 @@ static void verify_contents(sd_journal *j, unsigned skip) {
+                 const void *d;
+                 char *k, *c;
+                 size_t l;
+-                unsigned u;
++                unsigned u = 0;
+ 
+                 assert_se(sd_journal_get_cursor(j, &k) >= 0);
+                 printf("cursor: %s\n", k);
+diff --git a/src/libsystemd-network/lldp-tlv.c b/src/libsystemd-network/lldp-tlv.c
+index e43d70d..e32783f 100644
+--- a/src/libsystemd-network/lldp-tlv.c
++++ b/src/libsystemd-network/lldp-tlv.c
+@@ -156,7 +156,7 @@ static inline int tlv_packet_read_internal(tlv_section *m, void **data) {
+ }
+ 
+ int tlv_packet_read_u8(tlv_packet *m, uint8_t *data) {
+-        void *val;
++        void *val = NULL;
+         int r;
+ 
+         assert_return(m, -EINVAL);
+@@ -174,7 +174,7 @@ int tlv_packet_read_u8(tlv_packet *m, uint8_t *data) {
+ 
+ int tlv_packet_read_u16(tlv_packet *m, uint16_t *data) {
+         uint16_t t;
+-        void *val;
++        void *val = NULL;
+         int r;
+ 
+         assert_return(m, -EINVAL);
+@@ -211,7 +211,7 @@ int tlv_packet_read_u32(tlv_packet *m, uint32_t *data) {
+ }
+ 
+ int tlv_packet_read_string(tlv_packet *m, char **data, uint16_t *data_length) {
+-        void *val;
++        void *val = NULL;
+         int r;
+ 
+         assert_return(m, -EINVAL);
+@@ -229,7 +229,7 @@ int tlv_packet_read_string(tlv_packet *m, char **data, uint16_t *data_length) {
+ }
+ 
+ int tlv_packet_read_bytes(tlv_packet *m, uint8_t **data, uint16_t *data_length) {
+-        void *val;
++        void *val = NULL;
+         int r;
+ 
+         assert_return(m, -EINVAL);
+diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c
+index 3f89f34..0f284eb 100644
+--- a/src/libsystemd-network/sd-dhcp-server.c
++++ b/src/libsystemd-network/sd-dhcp-server.c
+@@ -776,7 +776,7 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message,
+                 if (pool_offset >= 0 &&
+                     server->bound_leases[pool_offset] == existing_lease) {
+                         DHCPLease *lease;
+-                        usec_t time_now;
++                        usec_t time_now = 0;
+ 
+                         if (!existing_lease) {
+                                 lease = new0(DHCPLease, 1);
+diff --git a/src/libsystemd-network/sd-pppoe.c b/src/libsystemd-network/sd-pppoe.c
+index 4f49b79..83e58a3 100644
+--- a/src/libsystemd-network/sd-pppoe.c
++++ b/src/libsystemd-network/sd-pppoe.c
+@@ -340,7 +340,7 @@ static int pppoe_timeout(sd_event_source *s, uint64_t usec, void *userdata);
+ 
+ static int pppoe_arm_timeout(sd_pppoe *ppp) {
+         _cleanup_event_source_unref_ sd_event_source *timeout = NULL;
+-        usec_t next_timeout;
++        usec_t next_timeout = 0;
+         int r;
+ 
+         assert(ppp);
+diff --git a/src/libsystemd/sd-login/sd-login.c b/src/libsystemd/sd-login/sd-login.c
+index f71749f..cc0677b 100644
+--- a/src/libsystemd/sd-login/sd-login.c
++++ b/src/libsystemd/sd-login/sd-login.c
+@@ -82,7 +82,7 @@ _public_ int sd_pid_get_owner_uid(pid_t pid, uid_t *uid) {
+ }
+ 
+ _public_ int sd_peer_get_session(int fd, char **session) {
+-        struct ucred ucred;
++        struct ucred ucred = {};
+         int r;
+ 
+         assert_return(fd >= 0, -EINVAL);
+diff --git a/src/network/networkctl.c b/src/network/networkctl.c
+index aa83f32..778670b 100644
+--- a/src/network/networkctl.c
++++ b/src/network/networkctl.c
+@@ -964,7 +964,7 @@ static int link_lldp_status(int argc, char *argv[], void *userdata) {
+                                                 return -ENOMEM;
+ 
+                                 } else if (streq(a, "_TTL")) {
+-                                        long long unsigned x;
++                                        long long unsigned x = 0;
+                                         usec_t time;
+ 
+                                         r = safe_atollu(b, &x);
+diff --git a/src/resolve/resolved-dns-transaction.c b/src/resolve/resolved-dns-transaction.c
+index 74b0634..bc1a90d 100644
+--- a/src/resolve/resolved-dns-transaction.c
++++ b/src/resolve/resolved-dns-transaction.c
+@@ -252,7 +252,7 @@ static int dns_transaction_open_tcp(DnsTransaction *t) {
+                         fd = dns_scope_tcp_socket(t->scope, t->received->family, &t->received->sender, t->received->sender_port);
+                 else {
+                         union in_addr_union address;
+-                        int family;
++                        int family = AF_UNSPEC;
+ 
+                         /* Otherwise, try to talk to the owner of a
+                          * the IP address, in case this is a reverse
+diff --git a/src/resolve/test-dns-domain.c b/src/resolve/test-dns-domain.c
+index ebc8d98..4963a9c 100644
+--- a/src/resolve/test-dns-domain.c
++++ b/src/resolve/test-dns-domain.c
+@@ -162,7 +162,7 @@ static void test_dns_name_single_label(void) {
+ 
+ static void test_dns_name_reverse_one(const char *address, const char *name) {
+         _cleanup_free_ char *p = NULL;
+-        union in_addr_union a, b;
++        union in_addr_union a, b = {};
+         int familya, familyb;
+ 
+         assert_se(in_addr_from_string_auto(address, &familya, &a) >= 0);
+diff --git a/src/shared/base-filesystem.c b/src/shared/base-filesystem.c
+index 73907c6..20a69bd 100644
+--- a/src/shared/base-filesystem.c
++++ b/src/shared/base-filesystem.c
+@@ -55,7 +55,7 @@ static const BaseFilesystem table[] = {
+ int base_filesystem_create(const char *root) {
+         _cleanup_close_ int fd = -1;
+         unsigned i;
+-        int r;
++        int r = 0;
+ 
+         fd = open(root, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
+         if (fd < 0)
+diff --git a/src/shared/capability.c b/src/shared/capability.c
+index 915ceb9..2b963fd 100644
+--- a/src/shared/capability.c
++++ b/src/shared/capability.c
+@@ -55,7 +55,7 @@ unsigned long cap_last_cap(void) {
+         static thread_local unsigned long saved;
+         static thread_local bool valid = false;
+         _cleanup_free_ char *content = NULL;
+-        unsigned long p;
++        unsigned long p = 0;
+         int r;
+ 
+         if (valid)
+diff --git a/src/shared/copy.c b/src/shared/copy.c
+index 0239a58..2a0cb28 100644
+--- a/src/shared/copy.c
++++ b/src/shared/copy.c
+@@ -360,7 +360,7 @@ int copy_file_fd(const char *from, int fdt, bool try_reflink) {
+ }
+ 
+ int copy_file(const char *from, const char *to, int flags, mode_t mode, unsigned chattr_flags) {
+-        int fdt, r;
++        int fdt = -1, r;
+ 
+         assert(from);
+         assert(to);
+@@ -390,7 +390,7 @@ int copy_file(const char *from, const char *to, int flags, mode_t mode, unsigned
+ }
+ 
+ int copy_file_atomic(const char *from, const char *to, mode_t mode, bool replace, unsigned chattr_flags) {
+-        _cleanup_free_ char *t;
++        _cleanup_free_ char *t = NULL;
+         int r;
+ 
+         assert(from);
+@@ -415,7 +415,7 @@ int copy_file_atomic(const char *from, const char *to, mode_t mode, bool replace
+ int copy_times(int fdf, int fdt) {
+         struct timespec ut[2];
+         struct stat st;
+-        usec_t crtime;
++        usec_t crtime = 0;
+ 
+         assert(fdf >= 0);
+         assert(fdt >= 0);
+diff --git a/src/shared/install.c b/src/shared/install.c
+index 9962508..61aaafe 100644
+--- a/src/shared/install.c
++++ b/src/shared/install.c
+@@ -2046,7 +2046,7 @@ UnitFileState unit_file_lookup_state(
+         _cleanup_(install_context_done) InstallContext c = {};
+         InstallInfo *i;
+         UnitFileState state;
+-        int r;
++        int r = 0;
+ 
+         assert(paths);
+         assert(name);
+diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c
+index 8c37411..a572be9 100644
+--- a/src/shared/logs-show.c
++++ b/src/shared/logs-show.c
+@@ -993,7 +993,7 @@ static int show_journal(FILE *f,
+ 
+                 if (warn_cutoff && line < how_many && not_before > 0) {
+                         sd_id128_t boot_id;
+-                        usec_t cutoff;
++                        usec_t cutoff = 0;
+ 
+                         /* Check whether the cutoff line is too early */
+ 
+diff --git a/src/shared/util.c b/src/shared/util.c
+index 3030261..4c441a5 100644
+--- a/src/shared/util.c
++++ b/src/shared/util.c
+@@ -3073,7 +3073,7 @@ int getttyname_malloc(int fd, char **ret) {
+ 
+ int getttyname_harder(int fd, char **r) {
+         int k;
+-        char *s;
++        char *s = NULL;
+ 
+         k = getttyname_malloc(fd, &s);
+         if (k < 0)
+@@ -3627,7 +3627,7 @@ char **replace_env_argv(char **argv, char **env) {
+                 /* If $FOO appears as single word, replace it by the split up variable */
+                 if ((*i)[0] == '$' && (*i)[1] != '{') {
+                         char *e;
+-                        char **w, **m;
++                        char **w, **m = NULL;
+                         unsigned q;
+ 
+                         e = strv_env_get(env, *i+1);
+diff --git a/src/test/test-path.c b/src/test/test-path.c
+index 4f9f5c1..a3295aa 100644
+--- a/src/test/test-path.c
++++ b/src/test/test-path.c
+@@ -33,7 +33,7 @@ static int setup_test(Manager **m) {
+         char **tests_path = STRV_MAKE("exists", "existsglobFOOBAR", "changed", "modified", "unit",
+                                       "directorynotempty", "makedirectory");
+         char **test_path;
+-        Manager *tmp;
++        Manager *tmp = NULL;
+         int r;
+ 
+         assert_se(m);
+diff --git a/src/test/test-pty.c b/src/test/test-pty.c
+index cab569a..67c125a 100644
+--- a/src/test/test-pty.c
++++ b/src/test/test-pty.c
+@@ -97,7 +97,7 @@ static void run_parent(Pty *pty) {
+ 
+ static void test_pty(void) {
+         pid_t pid;
+-        Pty *pty;
++        Pty *pty = NULL;
+ 
+         rcvsiz = 0;
+         zero(rcvbuf);
+diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c
+index 489593f..ad6a82e 100644
+--- a/src/udev/net/link-config.c
++++ b/src/udev/net/link-config.c
+@@ -474,7 +474,7 @@ int link_config_apply(link_config_ctx *ctx, link_config *config,
+ 
+ int link_get_driver(link_config_ctx *ctx, struct udev_device *device, char **ret) {
+         const char *name;
+-        char *driver;
++        char *driver = NULL;
+         int r;
+ 
+         name = udev_device_get_sysname(device);
diff --git a/SOURCES/0377-journalctl-rework-code-that-checks-whether-we-have-a.patch b/SOURCES/0377-journalctl-rework-code-that-checks-whether-we-have-a.patch
new file mode 100644
index 0000000..f2389ba
--- /dev/null
+++ b/SOURCES/0377-journalctl-rework-code-that-checks-whether-we-have-a.patch
@@ -0,0 +1,339 @@
+From e9bef2f8146ccf152459248775eec8e8ce123865 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Wed, 22 Apr 2015 22:54:23 +0200
+Subject: [PATCH] journalctl: rework code that checks whether we have access to
+ /var/log/journal
+
+- fix some memory leaks on error conditions
+
+- handle all error cases properly, and log about failures
+
+- move HAVE_ACL and no-HAVE_ACL code closer to each other
+
+Cherry-picked from: e346512c684e9efae84c6442f7e6a5781564ecde
+Related: #1318994
+---
+ src/journal/journalctl.c | 120 ++++++++++++++++++++++++-----------------------
+ src/shared/acl-util.c    | 102 ++++++++++++++++++++++------------------
+ src/shared/acl-util.h    |   2 +-
+ 3 files changed, 119 insertions(+), 105 deletions(-)
+
+diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
+index 6ba8847..f60e641 100644
+--- a/src/journal/journalctl.c
++++ b/src/journal/journalctl.c
+@@ -1680,61 +1680,76 @@ static int verify(sd_journal *j) {
+         return r;
+ }
+ 
+-#ifdef HAVE_ACL
+ static int access_check_var_log_journal(sd_journal *j) {
++#ifdef HAVE_ACL
+         _cleanup_strv_free_ char **g = NULL;
+-        bool have_access;
++        const char* dir;
++#endif
+         int r;
+ 
+         assert(j);
+ 
+-        have_access = in_group("systemd-journal") > 0;
++        if (arg_quiet)
++                return 0;
+ 
+-        if (!have_access) {
+-                const char* dir;
++        /* If we are root, we should have access, don't warn. */
++        if (getuid() == 0)
++                return 0;
+ 
+-                if (access("/run/log/journal", F_OK) >= 0)
+-                        dir = "/run/log/journal";
+-                else
+-                        dir = "/var/log/journal";
++        /* If we are in the 'systemd-journal' group, we should have
++         * access too. */
++        r = in_group("systemd-journal");
++        if (r < 0)
++                return log_error_errno(r, "Failed to check if we are in the 'systemd-journal' group: %m");
++        if (r > 0)
++                return 0;
+ 
+-                /* Let's enumerate all groups from the default ACL of
+-                 * the directory, which generally should allow access
+-                 * to most journal files too */
+-                r = search_acl_groups(&g, dir, &have_access);
+-                if (r < 0)
+-                        return r;
+-        }
++#ifdef HAVE_ACL
++        if (laccess("/run/log/journal", F_OK) >= 0)
++                dir = "/run/log/journal";
++        else
++                dir = "/var/log/journal";
+ 
+-        if (!have_access) {
++        /* If we are in any of the groups listed in the journal ACLs,
++         * then all is good, too. Let's enumerate all groups from the
++         * default ACL of the directory, which generally should allow
++         * access to most journal files too. */
++        r = acl_search_groups(dir, &g);
++        if (r < 0)
++                return log_error_errno(r, "Failed to search journal ACL: %m");
++        if (r > 0)
++                return 0;
+ 
+-                if (strv_isempty(g))
+-                        log_notice("Hint: You are currently not seeing messages from other users and the system.\n"
+-                                   "      Users in the 'systemd-journal' group can see all messages. Pass -q to\n"
+-                                   "      turn off this notice.");
+-                else {
+-                        _cleanup_free_ char *s = NULL;
++        /* Print a pretty list, if there were ACLs set. */
++        if (!strv_isempty(g)) {
++                _cleanup_free_ char *s = NULL;
+ 
+-                        r = strv_extend(&g, "systemd-journal");
+-                        if (r < 0)
+-                                return log_oom();
++                /* Thre are groups in the ACL, let's list them */
++                r = strv_extend(&g, "systemd-journal");
++                if (r < 0)
++                        return log_oom();
+ 
+-                        strv_sort(g);
+-                        strv_uniq(g);
++                strv_sort(g);
++                strv_uniq(g);
+ 
+-                        s = strv_join(g, "', '");
+-                        if (!s)
+-                                return log_oom();
++                s = strv_join(g, "', '");
++                if (!s)
++                        return log_oom();
+ 
+-                        log_notice("Hint: You are currently not seeing messages from other users and the system.\n"
+-                                   "      Users in groups '%s' can see all messages.\n"
+-                                   "      Pass -q to turn off this notice.", s);
+-                }
++                log_notice("Hint: You are currently not seeing messages from other users and the system.\n"
++                           "      Users in groups '%s' can see all messages.\n"
++                           "      Pass -q to turn off this notice.", s);
++                return 1;
+         }
++#endif
+ 
+-        return 0;
++        /* If no ACLs were found, print a short version of the message. */
++        log_notice("Hint: You are currently not seeing messages from other users and the system.\n"
++                   "      Users in the 'systemd-journal' group can see all messages. Pass -q to\n"
++                   "      turn off this notice.");
++
++        return 1;
+ }
+-#endif
+ 
+ static int access_check(sd_journal *j) {
+         Iterator it;
+@@ -1746,30 +1761,15 @@ static int access_check(sd_journal *j) {
+         if (set_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))) {
+-#ifdef HAVE_ACL
+-                /* If /run/log/journal or /var/log/journal exist, try
+-                   to pring a nice notice if the user lacks access to it. */
+-                if (!arg_quiet && geteuid() != 0) {
+-                        r = access_check_var_log_journal(j);
+-                        if (r < 0)
+-                                return r;
+-                }
+-#else
+-                if (geteuid() != 0 && in_group("systemd-journal") <= 0) {
+-                        log_error("Unprivileged users cannot access messages. Users in the 'systemd-journal' group\n"
+-                                  "group may access messages.");
+-                        return -EACCES;
+-                }
+-#endif
++                (void) access_check_var_log_journal(j);
+ 
+-                if (ordered_hashmap_isempty(j->files)) {
+-                        log_error("No journal files were opened due to insufficient permissions.");
+-                        r = -EACCES;
+-                }
++                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) {
+@@ -1778,8 +1778,12 @@ static int access_check(sd_journal *j) {
+                 err = -PTR_TO_INT(code);
+                 assert(err > 0);
+ 
+-                if (err != EACCES)
+-                        log_warning_errno(err, "Error was encountered while opening journal files: %m");
++                if (err == EACCES)
++                        continue;
++
++                log_warning_errno(err, "Error was encountered while opening journal files: %m");
++                if (r == 0)
++                        r = -err;
+         }
+ 
+         return r;
+diff --git a/src/shared/acl-util.c b/src/shared/acl-util.c
+index e67e9ac..d18a02f 100644
+--- a/src/shared/acl-util.c
++++ b/src/shared/acl-util.c
+@@ -82,17 +82,18 @@ int calc_acl_mask_if_needed(acl_t *acl_p) {
+ 
+                 if (tag == ACL_MASK)
+                         return 0;
+-                if (IN_SET(tag, ACL_USER, ACL_GROUP))
+-                        goto calc;
++
++                if (IN_SET(tag, ACL_USER, ACL_GROUP)) {
++                        if (acl_calc_mask(acl_p) < 0)
++                                return -errno;
++
++                        return 1;
++                }
+         }
+         if (r < 0)
+                 return -errno;
+-        return 0;
+ 
+-calc:
+-        if (acl_calc_mask(acl_p) < 0)
+-                return -errno;
+-        return 1;
++        return 0;
+ }
+ 
+ int add_base_acls_if_needed(acl_t *acl_p, const char *path) {
+@@ -159,59 +160,68 @@ int add_base_acls_if_needed(acl_t *acl_p, const char *path) {
+         return 0;
+ }
+ 
+-int search_acl_groups(char*** dst, const char* path, bool* belong) {
+-        acl_t acl;
++int acl_search_groups(const char *path, char ***ret_groups) {
++        _cleanup_strv_free_ char **g = NULL;
++        _cleanup_(acl_free) acl_t acl = NULL;
++        bool ret = false;
++        acl_entry_t entry;
++        int r;
+ 
+         assert(path);
+-        assert(belong);
+ 
+         acl = acl_get_file(path, ACL_TYPE_DEFAULT);
+-        if (acl) {
+-                acl_entry_t entry;
+-                int r;
+-
+-                r = acl_get_entry(acl, ACL_FIRST_ENTRY, &entry);
+-                while (r > 0) {
+-                        acl_tag_t tag;
+-                        gid_t *gid;
+-                        char *name;
++        if (!acl)
++                return -errno;
+ 
+-                        r = acl_get_tag_type(entry, &tag);
+-                        if (r < 0)
+-                                break;
++        r = acl_get_entry(acl, ACL_FIRST_ENTRY, &entry);
++        for (;;) {
++                _cleanup_(acl_free_gid_tpp) gid_t *gid = NULL;
++                acl_tag_t tag;
++
++                if (r < 0)
++                        return -errno;
++                if (r == 0)
++                        break;
++
++                if (acl_get_tag_type(entry, &tag) < 0)
++                        return -errno;
+ 
+-                        if (tag != ACL_GROUP)
+-                                goto next;
++                if (tag != ACL_GROUP)
++                        goto next;
+ 
+-                        gid = acl_get_qualifier(entry);
+-                        if (!gid)
+-                                break;
++                gid = acl_get_qualifier(entry);
++                if (!gid)
++                        return -errno;
++
++                if (in_gid(*gid) > 0) {
++                        if (!ret_groups)
++                                return true;
+ 
+-                        if (in_gid(*gid) > 0) {
+-                                *belong = true;
+-                                break;
+-                        }
++                        ret = true;
++                }
++
++                if (ret_groups) {
++                        char *name;
+ 
+                         name = gid_to_name(*gid);
+-                        if (!name) {
+-                                acl_free(acl);
+-                                return log_oom();
+-                        }
+-
+-                        r = strv_consume(dst, name);
+-                        if (r < 0) {
+-                                acl_free(acl);
+-                                return log_oom();
+-                        }
+-
+-                next:
+-                        r = acl_get_entry(acl, ACL_NEXT_ENTRY, &entry);
++                        if (!name)
++                                return -ENOMEM;
++
++                        r = strv_consume(&g, name);
++                        if (r < 0)
++                                return r;
+                 }
+ 
+-                acl_free(acl);
++        next:
++                r = acl_get_entry(acl, ACL_NEXT_ENTRY, &entry);
+         }
+ 
+-        return 0;
++        if (ret_groups) {
++                *ret_groups = g;
++                g = NULL;
++        }
++
++        return ret;
+ }
+ 
+ int parse_acl(char *text, acl_t *acl_access, acl_t *acl_default, bool want_mask) {
+diff --git a/src/shared/acl-util.h b/src/shared/acl-util.h
+index fdb9006..c8bcc26 100644
+--- a/src/shared/acl-util.h
++++ b/src/shared/acl-util.h
+@@ -32,7 +32,7 @@
+ int acl_find_uid(acl_t acl, uid_t uid, acl_entry_t *entry);
+ int calc_acl_mask_if_needed(acl_t *acl_p);
+ int add_base_acls_if_needed(acl_t *acl_p, const char *path);
+-int search_acl_groups(char*** dst, const char* path, bool* belong);
++int acl_search_groups(const char* path, char ***ret_groups);
+ int parse_acl(char *text, acl_t *acl_access, acl_t *acl_default, bool want_mask);
+ int acls_for_file(const char *path, acl_type_t type, acl_t new, acl_t *acl);
+ 
diff --git a/SOURCES/0378-journalctl-Improve-boot-ID-lookup.patch b/SOURCES/0378-journalctl-Improve-boot-ID-lookup.patch
new file mode 100644
index 0000000..4aab7e3
--- /dev/null
+++ b/SOURCES/0378-journalctl-Improve-boot-ID-lookup.patch
@@ -0,0 +1,55 @@
+From a6db5931947acb807b37cac9c832d68cd66fbc2a Mon Sep 17 00:00:00 2001
+From: Jan Janssen <medhefgo@web.de>
+Date: Fri, 1 May 2015 15:15:16 +0200
+Subject: [PATCH] journalctl: Improve boot ID lookup
+
+This method should greatly improve offset based lookup, by simply jumping
+from one boot to the next boot. It starts at the journal head to get the
+a boot ID, makes a _BOOT_ID match and then comes from the opposite
+journal direction (tail) to get to the end that boot. After flushing the matches
+and advancing the journal from that exact position, we arrive at the start
+of next boot. Rinse and repeat.
+
+This is faster than the old method of aggregating the full boot listing just
+so we can jump to a specific boot, which can be a real pain on big journals
+just for a mere "-b -1" case.
+
+As an additional benefit --list-boots should improve slightly too, because
+it does less seeking.
+
+Note that there can be a change in boot order with this lookup method
+because it will use the order of boots in the journal, not the realtime stamp
+stored in them. That's arguably better, though.
+Another deficiency is that it will get confused with boots interleaving in the
+journal, therefore, it will refuse operation in --merge, --file and --directory mode.
+
+https://bugs.freedesktop.org/show_bug.cgi?id=72601
+
+Conflicts:
+	src/journal/journalctl.c
+
+Cherry-picked from: 596a23293d28f93843aef86721b90043e74d3081
+Related: #1318994
+---
+ src/journal/journalctl.c | 7 +++----
+ 1 file changed, 3 insertions(+), 4 deletions(-)
+
+diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
+index f60e641..c7a19f2 100644
+--- a/src/journal/journalctl.c
++++ b/src/journal/journalctl.c
+@@ -1166,11 +1166,10 @@ static int add_boot(sd_journal *j) {
+                 const char *reason = (r == 0) ? "No such boot ID in journal" : strerror(-r);
+ 
+                 if (sd_id128_is_null(arg_boot_id))
+-                        log_error("Data from the specified boot (%+i) is not available: %s",
+-                                  arg_boot_offset, reason);
++                        log_error("Failed to look up boot %+i: %s", arg_boot_offset, reason);
+                 else
+-                        log_error("Data from the specified boot ("SD_ID128_FORMAT_STR") is not available: %s",
+-                                  SD_ID128_FORMAT_VAL(arg_boot_id), reason);
++                        log_error("Failed to look up boot ID "SD_ID128_FORMAT_STR"%+i: %s",
++                                  SD_ID128_FORMAT_VAL(arg_boot_id), arg_boot_offset, reason);
+ 
+                 return r == 0 ? -ENODATA : r;
+         }
diff --git a/SOURCES/0379-journalctl-only-have-a-single-exit-path-from-main.patch b/SOURCES/0379-journalctl-only-have-a-single-exit-path-from-main.patch
new file mode 100644
index 0000000..0e5da0f
--- /dev/null
+++ b/SOURCES/0379-journalctl-only-have-a-single-exit-path-from-main.patch
@@ -0,0 +1,217 @@
+From 134a85fc4fa6d1c3209e11415b2610147e2e1aac Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Mon, 18 May 2015 23:50:34 +0200
+Subject: [PATCH] journalctl: only have a single exit path from main()
+
+That way we can be sure we execute the destructors properly, and can be
+valgrind-clean.
+
+Cherry-picked from: 909dea0c7ced0042fa3acd8cd05f5007a2cf2cea
+Related: #1318994
+---
+ src/journal/journalctl.c | 51 +++++++++++++++++++++++++-----------------------
+ 1 file changed, 27 insertions(+), 24 deletions(-)
+
+diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
+index c7a19f2..31da357 100644
+--- a/src/journal/journalctl.c
++++ b/src/journal/journalctl.c
+@@ -532,7 +532,7 @@ static int parse_argv(int argc, char *argv[]) {
+                         arg_boot = true;
+ 
+                         if (optarg) {
+-                                r =  parse_boot_descriptor(optarg, &arg_boot_id, &arg_boot_offset);
++                                r = parse_boot_descriptor(optarg, &arg_boot_id, &arg_boot_offset);
+                                 if (r < 0) {
+                                         log_error("Failed to parse boot descriptor '%s'", optarg);
+                                         return -EINVAL;
+@@ -1929,12 +1929,12 @@ int main(int argc, char *argv[]) {
+         if (r < 0) {
+                 log_error_errno(r, "Failed to open %s: %m",
+                                 arg_directory ? arg_directory : arg_file ? "files" : "journal");
+-                return EXIT_FAILURE;
++                goto finish;
+         }
+ 
+         r = access_check(j);
+         if (r < 0)
+-                return EXIT_FAILURE;
++                goto finish;
+ 
+         if (arg_action == ACTION_VERIFY) {
+                 r = verify(j);
+@@ -1943,7 +1943,8 @@ int main(int argc, char *argv[]) {
+ 
+         if (arg_action == ACTION_PRINT_HEADER) {
+                 journal_print_header(j);
+-                return EXIT_SUCCESS;
++                r = 0;
++                goto finish;
+         }
+ 
+         if (arg_action == ACTION_DISK_USAGE) {
+@@ -1952,11 +1953,11 @@ int main(int argc, char *argv[]) {
+ 
+                 r = sd_journal_get_usage(j, &bytes);
+                 if (r < 0)
+-                        return EXIT_FAILURE;
++                        goto finish;
+ 
+                 printf("Archived and active journals take up %s on disk.\n",
+                        format_bytes(sbytes, sizeof(sbytes), bytes));
+-                return EXIT_SUCCESS;
++                goto finish;
+         }
+ 
+         if (arg_action == ACTION_VACUUM) {
+@@ -1976,7 +1977,7 @@ int main(int argc, char *argv[]) {
+                         }
+                 }
+ 
+-                return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
++                goto finish;
+         }
+ 
+         if (arg_action == ACTION_LIST_BOOTS) {
+@@ -1995,11 +1996,11 @@ int main(int argc, char *argv[]) {
+          * It may need to seek the journal to find parent boot IDs. */
+         r = add_boot(j);
+         if (r < 0)
+-                return EXIT_FAILURE;
++                goto finish;
+ 
+         r = add_dmesg(j);
+         if (r < 0)
+-                return EXIT_FAILURE;
++                goto finish;
+ 
+         r = add_units(j);
+         strv_free(arg_system_units);
+@@ -2007,25 +2008,25 @@ int main(int argc, char *argv[]) {
+ 
+         if (r < 0) {
+                 log_error_errno(r, "Failed to add filter for units: %m");
+-                return EXIT_FAILURE;
++                goto finish;
+         }
+ 
+         r = add_syslog_identifier(j);
+         if (r < 0) {
+                 log_error_errno(r, "Failed to add filter for syslog identifiers: %m");
+-                return EXIT_FAILURE;
++                goto finish;
+         }
+ 
+         r = add_priorities(j);
+         if (r < 0) {
+                 log_error_errno(r, "Failed to add filter for priorities: %m");
+-                return EXIT_FAILURE;
++                goto finish;
+         }
+ 
+         r = add_matches(j, argv + optind);
+         if (r < 0) {
+                 log_error_errno(r, "Failed to add filters: %m");
+-                return EXIT_FAILURE;
++                goto finish;
+         }
+ 
+         if (_unlikely_(log_get_max_level() >= LOG_DEBUG)) {
+@@ -2042,13 +2043,13 @@ int main(int argc, char *argv[]) {
+                 r = sd_journal_set_data_threshold(j, 0);
+                 if (r < 0) {
+                         log_error("Failed to unset data size threshold");
+-                        return EXIT_FAILURE;
++                        goto finish;
+                 }
+ 
+                 r = sd_journal_query_unique(j, arg_field);
+                 if (r < 0) {
+                         log_error_errno(r, "Failed to query unique data objects: %m");
+-                        return EXIT_FAILURE;
++                        goto finish;
+                 }
+ 
+                 SD_JOURNAL_FOREACH_UNIQUE(j, data, size) {
+@@ -2066,22 +2067,24 @@ int main(int argc, char *argv[]) {
+                         n_shown ++;
+                 }
+ 
+-                return EXIT_SUCCESS;
++                r = 0;
++                goto finish;
+         }
+ 
+         /* Opening the fd now means the first sd_journal_wait() will actually wait */
+         if (arg_follow) {
+                 r = sd_journal_get_fd(j);
+                 if (r < 0)
+-                        return EXIT_FAILURE;
++                        goto finish;
+         }
+ 
+         if (arg_cursor || arg_after_cursor) {
+                 r = sd_journal_seek_cursor(j, arg_cursor ?: arg_after_cursor);
+                 if (r < 0) {
+                         log_error_errno(r, "Failed to seek to cursor: %m");
+-                        return EXIT_FAILURE;
++                        goto finish;
+                 }
++
+                 if (!arg_reverse)
+                         r = sd_journal_next_skip(j, 1 + !!arg_after_cursor);
+                 else
+@@ -2099,7 +2102,7 @@ int main(int argc, char *argv[]) {
+                 r = sd_journal_seek_realtime_usec(j, arg_since);
+                 if (r < 0) {
+                         log_error_errno(r, "Failed to seek to date: %m");
+-                        return EXIT_FAILURE;
++                        goto finish;
+                 }
+                 r = sd_journal_next(j);
+ 
+@@ -2107,7 +2110,7 @@ int main(int argc, char *argv[]) {
+                 r = sd_journal_seek_realtime_usec(j, arg_until);
+                 if (r < 0) {
+                         log_error_errno(r, "Failed to seek to date: %m");
+-                        return EXIT_FAILURE;
++                        goto finish;
+                 }
+                 r = sd_journal_previous(j);
+ 
+@@ -2115,7 +2118,7 @@ int main(int argc, char *argv[]) {
+                 r = sd_journal_seek_tail(j);
+                 if (r < 0) {
+                         log_error_errno(r, "Failed to seek to tail: %m");
+-                        return EXIT_FAILURE;
++                        goto finish;
+                 }
+ 
+                 r = sd_journal_previous_skip(j, arg_lines);
+@@ -2124,7 +2127,7 @@ int main(int argc, char *argv[]) {
+                 r = sd_journal_seek_tail(j);
+                 if (r < 0) {
+                         log_error_errno(r, "Failed to seek to tail: %m");
+-                        return EXIT_FAILURE;
++                        goto finish;
+                 }
+ 
+                 r = sd_journal_previous(j);
+@@ -2133,7 +2136,7 @@ int main(int argc, char *argv[]) {
+                 r = sd_journal_seek_head(j);
+                 if (r < 0) {
+                         log_error_errno(r, "Failed to seek to head: %m");
+-                        return EXIT_FAILURE;
++                        goto finish;
+                 }
+ 
+                 r = sd_journal_next(j);
+@@ -2141,7 +2144,7 @@ int main(int argc, char *argv[]) {
+ 
+         if (r < 0) {
+                 log_error_errno(r, "Failed to iterate through journal: %m");
+-                return EXIT_FAILURE;
++                goto finish;
+         }
+ 
+         if (r == 0) {
diff --git a/SOURCES/0380-journalctl-free-all-command-line-argument-objects.patch b/SOURCES/0380-journalctl-free-all-command-line-argument-objects.patch
new file mode 100644
index 0000000..3e53a70
--- /dev/null
+++ b/SOURCES/0380-journalctl-free-all-command-line-argument-objects.patch
@@ -0,0 +1,45 @@
+From 4cbe0933587385ed0d811ce11264d65d15b05cfd Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Mon, 18 May 2015 23:54:05 +0200
+Subject: [PATCH] journalctl: free all command line argument objects
+
+let's try to be valgrind clean
+
+Cherry-picked from: d52da2057f06c49d50ed99300dc407c0227b1a32
+Related: #1318994
+---
+ src/journal/journalctl.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
+index 31da357..92ee3fb 100644
+--- a/src/journal/journalctl.c
++++ b/src/journal/journalctl.c
+@@ -39,7 +39,6 @@
+ 
+ #include "sd-journal.h"
+ #include "sd-bus.h"
+-
+ #include "log.h"
+ #include "logs-show.h"
+ #include "util.h"
+@@ -2003,9 +2002,6 @@ int main(int argc, char *argv[]) {
+                 goto finish;
+ 
+         r = add_units(j);
+-        strv_free(arg_system_units);
+-        strv_free(arg_user_units);
+-
+         if (r < 0) {
+                 log_error_errno(r, "Failed to add filter for units: %m");
+                 goto finish;
+@@ -2283,5 +2279,9 @@ finish:
+ 
+         strv_free(arg_file);
+ 
++        strv_free(arg_syslog_identifier);
++        strv_free(arg_system_units);
++        strv_free(arg_user_units);
++
+         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+ }
diff --git a/SOURCES/0381-journalctl-rename-boot_id_t-to-BootId.patch b/SOURCES/0381-journalctl-rename-boot_id_t-to-BootId.patch
new file mode 100644
index 0000000..32478bf
--- /dev/null
+++ b/SOURCES/0381-journalctl-rename-boot_id_t-to-BootId.patch
@@ -0,0 +1,120 @@
+From 1b84db099fc619719026679236a9db0199fd129a Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Tue, 19 May 2015 00:24:27 +0200
+Subject: [PATCH] journalctl: rename boot_id_t to BootId
+
+So far we tried to reserve the _t suffix to types we use like a value in
+contrast to types we use as objects, hence let's do this in journalctl
+too.
+
+Cherry-picked from: 45bc27b621c51b9d0e0229835deb6d188bcd417b
+Related: #1318994
+---
+ src/journal/journalctl.c | 42 +++++++++++++++++++++++-------------------
+ 1 file changed, 23 insertions(+), 19 deletions(-)
+
+diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
+index 92ee3fb..e84dd4c 100644
+--- a/src/journal/journalctl.c
++++ b/src/journal/journalctl.c
+@@ -128,12 +128,12 @@ static enum {
+         ACTION_VACUUM,
+ } arg_action = ACTION_SHOW;
+ 
+-typedef struct boot_id_t {
++typedef struct BootId {
+         sd_id128_t id;
+         uint64_t first;
+         uint64_t last;
+-        LIST_FIELDS(struct boot_id_t, boot_list);
+-} boot_id_t;
++        LIST_FIELDS(struct BootId, boot_list);
++} BootId;
+ 
+ static int add_matches_for_device(sd_journal *j, const char *devpath) {
+         int r;
+@@ -934,13 +934,15 @@ static int add_matches(sd_journal *j, char **args) {
+         return 0;
+ }
+ 
+-static int discover_next_boot(sd_journal *j,
+-                              boot_id_t **boot,
+-                              bool advance_older,
+-                              bool read_realtime) {
++static int discover_next_boot(
++                sd_journal *j,
++                BootId **boot,
++                bool advance_older,
++                bool read_realtime) {
++
+         int r;
+         char match[9+32+1] = "_BOOT_ID=";
+-        _cleanup_free_ boot_id_t *next_boot = NULL;
++        _cleanup_free_ BootId *next_boot = NULL;
+ 
+         assert(j);
+         assert(boot);
+@@ -965,7 +967,7 @@ static int discover_next_boot(sd_journal *j,
+         else if (r == 0)
+                 return 0; /* End of journal, yay. */
+ 
+-        next_boot = new0(boot_id_t, 1);
++        next_boot = new0(BootId, 1);
+         if (!next_boot)
+                 return log_oom();
+ 
+@@ -1012,13 +1014,15 @@ static int discover_next_boot(sd_journal *j,
+         return 0;
+ }
+ 
+-static int get_boots(sd_journal *j,
+-                     boot_id_t **boots,
+-                     boot_id_t *query_ref_boot,
+-                     int ref_boot_offset) {
++static int get_boots(
++                sd_journal *j,
++                BootId **boots,
++                BootId *query_ref_boot,
++                int ref_boot_offset) {
++
+         bool skip_once;
+         int r, count = 0;
+-        boot_id_t *head = NULL, *tail = NULL;
++        BootId *head = NULL, *tail = NULL;
+         const bool advance_older = query_ref_boot && ref_boot_offset <= 0;
+ 
+         assert(j);
+@@ -1073,12 +1077,12 @@ static int get_boots(sd_journal *j,
+                 /* No sd_journal_next/previous here. */
+         }
+ 
+-        while (true) {
+-                _cleanup_free_ boot_id_t *current = NULL;
++        for (;;) {
++                _cleanup_free_ BootId *current = NULL;
+ 
+                 r = discover_next_boot(j, &current, advance_older, !query_ref_boot);
+                 if (r < 0) {
+-                        boot_id_t *id, *id_next;
++                        BootId *id, *id_next;
+                         LIST_FOREACH_SAFE(boot_list, id, id_next, head)
+                                 free(id);
+                         return r;
+@@ -1116,7 +1120,7 @@ finish:
+ 
+ static int list_boots(sd_journal *j) {
+         int w, i, count;
+-        boot_id_t *id, *id_next, *all_ids;
++        BootId *id, *id_next, *all_ids;
+ 
+         assert(j);
+ 
+@@ -1148,7 +1152,7 @@ static int list_boots(sd_journal *j) {
+ static int add_boot(sd_journal *j) {
+         char match[9+32+1] = "_BOOT_ID=";
+         int r;
+-        boot_id_t ref_boot_id = {};
++        BootId ref_boot_id = {};
+ 
+         assert(j);
+ 
diff --git a/SOURCES/0382-util-introduce-CMSG_FOREACH-macro-and-make-use-of-it.patch b/SOURCES/0382-util-introduce-CMSG_FOREACH-macro-and-make-use-of-it.patch
new file mode 100644
index 0000000..864ec1e
--- /dev/null
+++ b/SOURCES/0382-util-introduce-CMSG_FOREACH-macro-and-make-use-of-it.patch
@@ -0,0 +1,301 @@
+From 603edc22d0516044b72b09ed94a696edd2de7f37 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Wed, 10 Jun 2015 19:10:47 +0200
+Subject: [PATCH] util: introduce CMSG_FOREACH() macro and make use of it
+ everywhere
+
+It's only marginally shorter then the usual for() loop, but certainly
+more readable.
+
+Cherry-picked from: 2a1288ff89322a2f49c79f6d1832c8164c14a05c
+Related: #1318994
+---
+ src/core/manager.c                      |  2 +-
+ src/core/namespace.c                    |  3 +--
+ src/import/importd.c                    |  8 ++------
+ src/journal/journald-server.c           |  2 +-
+ src/libsystemd-network/sd-dhcp-client.c |  2 +-
+ src/libsystemd-network/sd-dhcp-server.c |  2 +-
+ src/libsystemd/sd-bus/bus-container.c   |  2 +-
+ src/libsystemd/sd-bus/bus-socket.c      | 16 ++++++++++------
+ src/libsystemd/sd-rtnl/rtnl-message.c   |  2 +-
+ src/resolve/resolved-dns-stream.c       |  3 ++-
+ src/resolve/resolved-manager.c          |  2 +-
+ src/shared/macro.h                      |  3 +++
+ src/shared/util.c                       | 12 +++++++++++-
+ src/shared/util.h                       |  2 ++
+ src/timesync/timesyncd-manager.c        |  2 +-
+ 15 files changed, 39 insertions(+), 24 deletions(-)
+
+diff --git a/src/core/manager.c b/src/core/manager.c
+index c502199..71dd70c 100644
+--- a/src/core/manager.c
++++ b/src/core/manager.c
+@@ -1679,7 +1679,7 @@ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t
+                 return -errno;
+         }
+ 
+-        for (cmsg = CMSG_FIRSTHDR(&msghdr); cmsg; cmsg = CMSG_NXTHDR(&msghdr, cmsg)) {
++        CMSG_FOREACH(cmsg, &msghdr) {
+                 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
+ 
+                         fd_array = (int*) CMSG_DATA(cmsg);
+diff --git a/src/core/namespace.c b/src/core/namespace.c
+index ebd5fb3..00495c1 100644
+--- a/src/core/namespace.c
++++ b/src/core/namespace.c
+@@ -658,12 +658,11 @@ int setup_netns(int netns_storage_socket[2]) {
+         } else {
+                 /* Yay, found something, so let's join the namespace */
+ 
+-                for (cmsg = CMSG_FIRSTHDR(&mh); cmsg; cmsg = CMSG_NXTHDR(&mh, cmsg)) {
++                CMSG_FOREACH(cmsg, &mh)
+                         if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
+                                 assert(cmsg->cmsg_len == CMSG_LEN(sizeof(int)));
+                                 netns = *(int*) CMSG_DATA(cmsg);
+                         }
+-                }
+ 
+                 if (setns(netns, CLONE_NEWNET) < 0) {
+                         r = -errno;
+diff --git a/src/import/importd.c b/src/import/importd.c
+index 9aaf991..a29630b 100644
+--- a/src/import/importd.c
++++ b/src/import/importd.c
+@@ -507,12 +507,8 @@ static int manager_on_notify(sd_event_source *s, int fd, uint32_t revents, void
+                 return -errno;
+         }
+ 
+-        for (cmsg = CMSG_FIRSTHDR(&msghdr); cmsg; cmsg = CMSG_NXTHDR(&msghdr, cmsg)) {
+-                if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
+-                        close_many((int*) CMSG_DATA(cmsg), (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int));
+-                        log_warning("Somebody sent us unexpected fds, ignoring.");
+-                        return 0;
+-                } else if (cmsg->cmsg_level == SOL_SOCKET &&
++        CMSG_FOREACH(cmsg, &msghdr) {
++                if (cmsg->cmsg_level == SOL_SOCKET &&
+                            cmsg->cmsg_type == SCM_CREDENTIALS &&
+                            cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
+ 
+diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c
+index 6a35ebb..1eb1394 100644
+--- a/src/journal/journald-server.c
++++ b/src/journal/journald-server.c
+@@ -1176,7 +1176,7 @@ int server_process_datagram(sd_event_source *es, int fd, uint32_t revents, void
+                         return -errno;
+                 }
+ 
+-                for (cmsg = CMSG_FIRSTHDR(&msghdr); cmsg; cmsg = CMSG_NXTHDR(&msghdr, cmsg)) {
++                CMSG_FOREACH(cmsg, &msghdr) {
+ 
+                         if (cmsg->cmsg_level == SOL_SOCKET &&
+                             cmsg->cmsg_type == SCM_CREDENTIALS &&
+diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c
+index 5f90617..870850e 100644
+--- a/src/libsystemd-network/sd-dhcp-client.c
++++ b/src/libsystemd-network/sd-dhcp-client.c
+@@ -1590,7 +1590,7 @@ static int client_receive_message_raw(sd_event_source *s, int fd,
+         } else if ((size_t)len < sizeof(DHCPPacket))
+                 return 0;
+ 
+-        for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
++        CMSG_FOREACH(cmsg, &msg) {
+                 if (cmsg->cmsg_level == SOL_PACKET &&
+                     cmsg->cmsg_type == PACKET_AUXDATA &&
+                     cmsg->cmsg_len == CMSG_LEN(sizeof(struct tpacket_auxdata))) {
+diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c
+index 0f284eb..c9d0ace 100644
+--- a/src/libsystemd-network/sd-dhcp-server.c
++++ b/src/libsystemd-network/sd-dhcp-server.c
+@@ -903,7 +903,7 @@ static int server_receive_message(sd_event_source *s, int fd,
+         else if ((size_t)len < sizeof(DHCPMessage))
+                 return 0;
+ 
+-        for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
++        CMSG_FOREACH(cmsg, &msg) {
+                 if (cmsg->cmsg_level == IPPROTO_IP &&
+                     cmsg->cmsg_type == IP_PKTINFO &&
+                     cmsg->cmsg_len == CMSG_LEN(sizeof(struct in_pktinfo))) {
+diff --git a/src/libsystemd/sd-bus/bus-container.c b/src/libsystemd/sd-bus/bus-container.c
+index d29b98a..10ab714 100644
+--- a/src/libsystemd/sd-bus/bus-container.c
++++ b/src/libsystemd/sd-bus/bus-container.c
+@@ -222,7 +222,7 @@ int bus_container_connect_kernel(sd_bus *b) {
+         if (recvmsg(pair[0], &mh, MSG_NOSIGNAL|MSG_CMSG_CLOEXEC) < 0)
+                 return -errno;
+ 
+-        for (cmsg = CMSG_FIRSTHDR(&mh); cmsg; cmsg = CMSG_NXTHDR(&mh, cmsg))
++        CMSG_FOREACH(cmsg, &mh)
+                 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
+                         int *fds;
+                         unsigned n_fds;
+diff --git a/src/libsystemd/sd-bus/bus-socket.c b/src/libsystemd/sd-bus/bus-socket.c
+index a3c3a45..ab56ef4 100644
+--- a/src/libsystemd/sd-bus/bus-socket.c
++++ b/src/libsystemd/sd-bus/bus-socket.c
+@@ -503,7 +503,6 @@ static int bus_socket_read_auth(sd_bus *b) {
+                 struct cmsghdr cmsghdr;
+                 uint8_t buf[CMSG_SPACE(sizeof(int) * BUS_FDS_MAX)];
+         } control;
+-        struct cmsghdr *cmsg;
+         bool handle_cmsg = false;
+ 
+         assert(b);
+@@ -554,8 +553,10 @@ static int bus_socket_read_auth(sd_bus *b) {
+ 
+         b->rbuffer_size += k;
+ 
+-        if (handle_cmsg)
+-                for (cmsg = CMSG_FIRSTHDR(&mh); cmsg; cmsg = CMSG_NXTHDR(&mh, cmsg))
++        if (handle_cmsg) {
++                struct cmsghdr *cmsg;
++
++                CMSG_FOREACH(cmsg, &mh)
+                         if (cmsg->cmsg_level == SOL_SOCKET &&
+                             cmsg->cmsg_type == SCM_RIGHTS) {
+                                 int j;
+@@ -569,6 +570,7 @@ static int bus_socket_read_auth(sd_bus *b) {
+                         } else
+                                 log_debug("Got unexpected auxiliary data with level=%d and type=%d",
+                                           cmsg->cmsg_level, cmsg->cmsg_type);
++        }
+ 
+         r = bus_socket_auth_verify(b);
+         if (r != 0)
+@@ -930,7 +932,6 @@ int bus_socket_read_message(sd_bus *bus) {
+                 struct cmsghdr cmsghdr;
+                 uint8_t buf[CMSG_SPACE(sizeof(int) * BUS_FDS_MAX)];
+         } control;
+-        struct cmsghdr *cmsg;
+         bool handle_cmsg = false;
+ 
+         assert(bus);
+@@ -976,8 +977,10 @@ int bus_socket_read_message(sd_bus *bus) {
+ 
+         bus->rbuffer_size += k;
+ 
+-        if (handle_cmsg)
+-                for (cmsg = CMSG_FIRSTHDR(&mh); cmsg; cmsg = CMSG_NXTHDR(&mh, cmsg))
++        if (handle_cmsg) {
++                struct cmsghdr *cmsg;
++
++                CMSG_FOREACH(cmsg, &mh)
+                         if (cmsg->cmsg_level == SOL_SOCKET &&
+                             cmsg->cmsg_type == SCM_RIGHTS) {
+                                 int n, *f;
+@@ -1005,6 +1008,7 @@ int bus_socket_read_message(sd_bus *bus) {
+                         } else
+                                 log_debug("Got unexpected auxiliary data with level=%d and type=%d",
+                                           cmsg->cmsg_level, cmsg->cmsg_type);
++        }
+ 
+         r = bus_socket_read_message_need(bus, &need);
+         if (r < 0)
+diff --git a/src/libsystemd/sd-rtnl/rtnl-message.c b/src/libsystemd/sd-rtnl/rtnl-message.c
+index 9276bbd..cc84253 100644
+--- a/src/libsystemd/sd-rtnl/rtnl-message.c
++++ b/src/libsystemd/sd-rtnl/rtnl-message.c
+@@ -1444,7 +1444,7 @@ static int socket_recv_message(int fd, struct iovec *iov, uint32_t *_group, bool
+                 return (errno == EAGAIN || errno == EINTR) ? 0 : -errno;
+         }
+ 
+-        for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
++        CMSG_FOREACH(cmsg, &msg) {
+                 if (cmsg->cmsg_level == SOL_SOCKET &&
+                     cmsg->cmsg_type == SCM_CREDENTIALS &&
+                     cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
+diff --git a/src/resolve/resolved-dns-stream.c b/src/resolve/resolved-dns-stream.c
+index 4c0b557..7f47e72 100644
+--- a/src/resolve/resolved-dns-stream.c
++++ b/src/resolve/resolved-dns-stream.c
+@@ -113,7 +113,8 @@ static int dns_stream_identify(DnsStream *s) {
+ 
+         mh.msg_control = &control;
+         mh.msg_controllen = sl;
+-        for (cmsg = CMSG_FIRSTHDR(&mh); cmsg; cmsg = CMSG_NXTHDR(&mh, cmsg)) {
++
++        CMSG_FOREACH(cmsg, &mh) {
+ 
+                 if (cmsg->cmsg_level == IPPROTO_IPV6) {
+                         assert(s->peer.sa.sa_family == AF_INET6);
+diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c
+index 7c253aa..173ab8a 100644
+--- a/src/resolve/resolved-manager.c
++++ b/src/resolve/resolved-manager.c
+@@ -920,7 +920,7 @@ int manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret) {
+         } else
+                 return -EAFNOSUPPORT;
+ 
+-        for (cmsg = CMSG_FIRSTHDR(&mh); cmsg; cmsg = CMSG_NXTHDR(&mh, cmsg)) {
++        CMSG_FOREACH(cmsg, &mh) {
+ 
+                 if (cmsg->cmsg_level == IPPROTO_IPV6) {
+                         assert(p->family == AF_INET6);
+diff --git a/src/shared/macro.h b/src/shared/macro.h
+index 9d857dc..7a57f4e 100644
+--- a/src/shared/macro.h
++++ b/src/shared/macro.h
+@@ -471,4 +471,7 @@ static inline bool GID_IS_INVALID(gid_t gid) {
+         }                                                       \
+         struct __useless_struct_to_allow_trailing_semicolon__
+ 
++#define CMSG_FOREACH(cmsg, mh)                                          \
++        for ((cmsg) = CMSG_FIRSTHDR(mh); (cmsg); (cmsg) = CMSG_NXTHDR((mh), (cmsg)))
++
+ #include "log.h"
+diff --git a/src/shared/util.c b/src/shared/util.c
+index 4c441a5..357fbfe 100644
+--- a/src/shared/util.c
++++ b/src/shared/util.c
+@@ -7887,7 +7887,7 @@ int openpt_in_namespace(pid_t pid, int flags) {
+         if (recvmsg(pair[0], &mh, MSG_NOSIGNAL|MSG_CMSG_CLOEXEC) < 0)
+                 return -errno;
+ 
+-        for (cmsg = CMSG_FIRSTHDR(&mh); cmsg; cmsg = CMSG_NXTHDR(&mh, cmsg))
++        CMSG_FOREACH(cmsg, &mh)
+                 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
+                         int *fds;
+                         unsigned n_fds;
+@@ -8375,6 +8375,16 @@ ssize_t string_table_lookup(const char * const *table, size_t len, const char *k
+         return -1;
+ }
+ 
++void cmsg_close_all(struct msghdr *mh) {
++        struct cmsghdr *cmsg;
++
++        assert(mh);
++
++        CMSG_FOREACH(cmsg, mh)
++                if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS)
++                        close_many((int*) CMSG_DATA(cmsg), (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int));
++}
++
+ char *shell_maybe_quote(const char *s) {
+         const char *p;
+         char *r, *t;
+diff --git a/src/shared/util.h b/src/shared/util.h
+index be04524..12afcc3 100644
+--- a/src/shared/util.h
++++ b/src/shared/util.h
+@@ -1082,6 +1082,8 @@ void sigkill_wait(pid_t *pid);
+ 
+ int syslog_parse_priority(const char **p, int *priority, bool with_facility);
+ 
++void cmsg_close_all(struct msghdr *mh);
++
+ char *shell_maybe_quote(const char *s);
+ 
+ typedef enum ExtractFlags {
+diff --git a/src/timesync/timesyncd-manager.c b/src/timesync/timesyncd-manager.c
+index 73ac7ee..5cc1968 100644
+--- a/src/timesync/timesyncd-manager.c
++++ b/src/timesync/timesyncd-manager.c
+@@ -539,7 +539,7 @@ static int manager_receive_response(sd_event_source *source, int fd, uint32_t re
+         }
+ 
+         recv_time = NULL;
+-        for (cmsg = CMSG_FIRSTHDR(&msghdr); cmsg; cmsg = CMSG_NXTHDR(&msghdr, cmsg)) {
++        CMSG_FOREACH(cmsg, &msghdr) {
+                 if (cmsg->cmsg_level != SOL_SOCKET)
+                         continue;
+ 
diff --git a/SOURCES/0383-journald-don-t-employ-inner-loop-for-reading-from-in.patch b/SOURCES/0383-journald-don-t-employ-inner-loop-for-reading-from-in.patch
new file mode 100644
index 0000000..1811890
--- /dev/null
+++ b/SOURCES/0383-journald-don-t-employ-inner-loop-for-reading-from-in.patch
@@ -0,0 +1,251 @@
+From 6d1ef1fb841a0b3b4c53b560892f3570b3379dc9 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Wed, 10 Jun 2015 19:24:58 +0200
+Subject: [PATCH] journald: don't employ inner loop for reading from incoming
+ sockets
+
+Otherwise, if the socket is constantly busy we will never return to the
+event loop, but we really need to to dispatch other (possibly more
+high-priority) events too. Hence, return after dispatching one message
+to the event handler, and rely on the event loop calling us back
+right-away.
+
+Fixes #125
+
+Related: #1318994
+Cherry-picked from: a315ac4e076c4ce7ce3e5c95792cf916d5e918c5
+---
+ src/journal/journald-server.c | 204 +++++++++++++++++++++---------------------
+ 1 file changed, 100 insertions(+), 104 deletions(-)
+
+diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c
+index 1eb1394..275224d 100644
+--- a/src/journal/journald-server.c
++++ b/src/journal/journald-server.c
+@@ -1103,6 +1103,42 @@ finish:
+ 
+ int server_process_datagram(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
+         Server *s = userdata;
++        struct ucred *ucred = NULL;
++        struct timeval *tv = NULL;
++        struct cmsghdr *cmsg;
++        char *label = NULL;
++        size_t label_len = 0, m;
++        struct iovec iovec;
++        ssize_t n;
++        int *fds = NULL, v = 0;
++        unsigned n_fds = 0;
++
++        union {
++                struct cmsghdr cmsghdr;
++
++                /* We use NAME_MAX space for the SELinux label
++                 * here. The kernel currently enforces no
++                 * limit, but according to suggestions from
++                 * the SELinux people this will change and it
++                 * will probably be identical to NAME_MAX. For
++                 * now we use that, but this should be updated
++                 * one day when the final limit is known. */
++                uint8_t buf[CMSG_SPACE(sizeof(struct ucred)) +
++                            CMSG_SPACE(sizeof(struct timeval)) +
++                            CMSG_SPACE(sizeof(int)) + /* fd */
++                            CMSG_SPACE(NAME_MAX)]; /* selinux label */
++        } control = {};
++
++        union sockaddr_union sa = {};
++
++        struct msghdr msghdr = {
++                .msg_iov = &iovec,
++                .msg_iovlen = 1,
++                .msg_control = &control,
++                .msg_controllen = sizeof(control),
++                .msg_name = &sa,
++                .msg_namelen = sizeof(sa),
++        };
+ 
+         assert(s);
+         assert(fd == s->native_fd || fd == s->syslog_fd || fd == s->audit_fd);
+@@ -1112,119 +1148,79 @@ int server_process_datagram(sd_event_source *es, int fd, uint32_t revents, void
+                 return -EIO;
+         }
+ 
+-        for (;;) {
+-                struct ucred *ucred = NULL;
+-                struct timeval *tv = NULL;
+-                struct cmsghdr *cmsg;
+-                char *label = NULL;
+-                size_t label_len = 0;
+-                struct iovec iovec;
+-
+-                union {
+-                        struct cmsghdr cmsghdr;
+-
+-                        /* We use NAME_MAX space for the SELinux label
+-                         * here. The kernel currently enforces no
+-                         * limit, but according to suggestions from
+-                         * the SELinux people this will change and it
+-                         * will probably be identical to NAME_MAX. For
+-                         * now we use that, but this should be updated
+-                         * one day when the final limit is known. */
+-                        uint8_t buf[CMSG_SPACE(sizeof(struct ucred)) +
+-                                    CMSG_SPACE(sizeof(struct timeval)) +
+-                                    CMSG_SPACE(sizeof(int)) + /* fd */
+-                                    CMSG_SPACE(NAME_MAX)]; /* selinux label */
+-                } control = {};
+-                union sockaddr_union sa = {};
+-                struct msghdr msghdr = {
+-                        .msg_iov = &iovec,
+-                        .msg_iovlen = 1,
+-                        .msg_control = &control,
+-                        .msg_controllen = sizeof(control),
+-                        .msg_name = &sa,
+-                        .msg_namelen = sizeof(sa),
+-                };
+-
+-                ssize_t n;
+-                int *fds = NULL;
+-                unsigned n_fds = 0;
+-                int v = 0;
+-                size_t m;
+-
+-                /* Try to get the right size, if we can. (Not all
+-                 * sockets support SIOCINQ, hence we just try, but
+-                 * don't rely on it. */
+-                (void) ioctl(fd, SIOCINQ, &v);
+-
+-                /* Fix it up, if it is too small. We use the same fixed value as auditd here. Awful! */
+-                m = PAGE_ALIGN(MAX3((size_t) v + 1,
+-                                    (size_t) LINE_MAX,
+-                                    ALIGN(sizeof(struct nlmsghdr)) + ALIGN((size_t) MAX_AUDIT_MESSAGE_LENGTH)) + 1);
+-
+-                if (!GREEDY_REALLOC(s->buffer, s->buffer_size, m))
+-                        return log_oom();
+-
+-                iovec.iov_base = s->buffer;
+-                iovec.iov_len = s->buffer_size - 1; /* Leave room for trailing NUL we add later */
+-
+-                n = recvmsg(fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
+-                if (n < 0) {
+-                        if (errno == EINTR || errno == EAGAIN)
+-                                return 0;
+-
+-                        log_error_errno(errno, "recvmsg() failed: %m");
+-                        return -errno;
+-                }
++        /* Try to get the right size, if we can. (Not all
++         * sockets support SIOCINQ, hence we just try, but
++         * don't rely on it. */
++        (void) ioctl(fd, SIOCINQ, &v);
+ 
+-                CMSG_FOREACH(cmsg, &msghdr) {
+-
+-                        if (cmsg->cmsg_level == SOL_SOCKET &&
+-                            cmsg->cmsg_type == SCM_CREDENTIALS &&
+-                            cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred)))
+-                                ucred = (struct ucred*) CMSG_DATA(cmsg);
+-                        else if (cmsg->cmsg_level == SOL_SOCKET &&
+-                                 cmsg->cmsg_type == SCM_SECURITY) {
+-                                label = (char*) CMSG_DATA(cmsg);
+-                                label_len = cmsg->cmsg_len - CMSG_LEN(0);
+-                        } else if (cmsg->cmsg_level == SOL_SOCKET &&
+-                                   cmsg->cmsg_type == SO_TIMESTAMP &&
+-                                   cmsg->cmsg_len == CMSG_LEN(sizeof(struct timeval)))
+-                                tv = (struct timeval*) CMSG_DATA(cmsg);
+-                        else if (cmsg->cmsg_level == SOL_SOCKET &&
+-                                 cmsg->cmsg_type == SCM_RIGHTS) {
+-                                fds = (int*) CMSG_DATA(cmsg);
+-                                n_fds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
+-                        }
+-                }
++        /* Fix it up, if it is too small. We use the same fixed value as auditd here. Awful! */
++        m = PAGE_ALIGN(MAX3((size_t) v + 1,
++                            (size_t) LINE_MAX,
++                            ALIGN(sizeof(struct nlmsghdr)) + ALIGN((size_t) MAX_AUDIT_MESSAGE_LENGTH)) + 1);
+ 
+-                /* And a trailing NUL, just in case */
+-                s->buffer[n] = 0;
++        if (!GREEDY_REALLOC(s->buffer, s->buffer_size, m))
++                return log_oom();
+ 
+-                if (fd == s->syslog_fd) {
+-                        if (n > 0 && n_fds == 0)
+-                                server_process_syslog_message(s, strstrip(s->buffer), ucred, tv, label, label_len);
+-                        else if (n_fds > 0)
+-                                log_warning("Got file descriptors via syslog socket. Ignoring.");
++        iovec.iov_base = s->buffer;
++        iovec.iov_len = s->buffer_size - 1; /* Leave room for trailing NUL we add later */
+ 
+-                } else if (fd == s->native_fd) {
+-                        if (n > 0 && n_fds == 0)
+-                                server_process_native_message(s, s->buffer, n, ucred, tv, label, label_len);
+-                        else if (n == 0 && n_fds == 1)
+-                                server_process_native_file(s, fds[0], ucred, tv, label, label_len);
+-                        else if (n_fds > 0)
+-                                log_warning("Got too many file descriptors via native socket. Ignoring.");
++        n = recvmsg(fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
++        if (n < 0) {
++                if (errno == EINTR || errno == EAGAIN)
++                        return 0;
+ 
+-                } else {
+-                        assert(fd == s->audit_fd);
++                return log_error_errno(errno, "recvmsg() failed: %m");
++        }
+ 
+-                        if (n > 0 && n_fds == 0)
+-                                server_process_audit_message(s, s->buffer, n, ucred, &sa, msghdr.msg_namelen);
+-                        else if (n_fds > 0)
+-                                log_warning("Got file descriptors via audit socket. Ignoring.");
++        CMSG_FOREACH(cmsg, &msghdr) {
++
++                if (cmsg->cmsg_level == SOL_SOCKET &&
++                    cmsg->cmsg_type == SCM_CREDENTIALS &&
++                    cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred)))
++                        ucred = (struct ucred*) CMSG_DATA(cmsg);
++                else if (cmsg->cmsg_level == SOL_SOCKET &&
++                         cmsg->cmsg_type == SCM_SECURITY) {
++                        label = (char*) CMSG_DATA(cmsg);
++                        label_len = cmsg->cmsg_len - CMSG_LEN(0);
++                } else if (cmsg->cmsg_level == SOL_SOCKET &&
++                           cmsg->cmsg_type == SO_TIMESTAMP &&
++                           cmsg->cmsg_len == CMSG_LEN(sizeof(struct timeval)))
++                        tv = (struct timeval*) CMSG_DATA(cmsg);
++                else if (cmsg->cmsg_level == SOL_SOCKET &&
++                         cmsg->cmsg_type == SCM_RIGHTS) {
++                        fds = (int*) CMSG_DATA(cmsg);
++                        n_fds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
+                 }
++        }
++
++        /* And a trailing NUL, just in case */
++        s->buffer[n] = 0;
++
++        if (fd == s->syslog_fd) {
++                if (n > 0 && n_fds == 0)
++                        server_process_syslog_message(s, strstrip(s->buffer), ucred, tv, label, label_len);
++                else if (n_fds > 0)
++                        log_warning("Got file descriptors via syslog socket. Ignoring.");
++
++        } else if (fd == s->native_fd) {
++                if (n > 0 && n_fds == 0)
++                        server_process_native_message(s, s->buffer, n, ucred, tv, label, label_len);
++                else if (n == 0 && n_fds == 1)
++                        server_process_native_file(s, fds[0], ucred, tv, label, label_len);
++                else if (n_fds > 0)
++                        log_warning("Got too many file descriptors via native socket. Ignoring.");
+ 
+-                close_many(fds, n_fds);
++        } else {
++                assert(fd == s->audit_fd);
++
++                if (n > 0 && n_fds == 0)
++                        server_process_audit_message(s, s->buffer, n, ucred, &sa, msghdr.msg_namelen);
++                else if (n_fds > 0)
++                        log_warning("Got file descriptors via audit socket. Ignoring.");
+         }
++
++        close_many(fds, n_fds);
++        return 0;
+ }
+ 
+ static int dispatch_sigusr1(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) {
diff --git a/SOURCES/0384-journald-fix-count-of-object-meta-fields.patch b/SOURCES/0384-journald-fix-count-of-object-meta-fields.patch
new file mode 100644
index 0000000..c41559a
--- /dev/null
+++ b/SOURCES/0384-journald-fix-count-of-object-meta-fields.patch
@@ -0,0 +1,29 @@
+From 7eee42f5d268084171d435de2b16333d2a0f79ab Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Wed, 5 Aug 2015 11:31:52 +0300
+Subject: [PATCH] journald: fix count of object meta fields
+
+There are 12 object meta fields created in dispatch_message_real(), but
+we only allocated space for 11. Fix this.
+
+Fixes #866.
+
+Cherry-picked from: 704e4fe7a18a13a8651c0064ef3eda91027baffc
+Related: #1318994
+---
+ src/journal/journald-server.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/journal/journald-server.h b/src/journal/journald-server.h
+index c96877c..b1263a7 100644
+--- a/src/journal/journald-server.h
++++ b/src/journal/journald-server.h
+@@ -148,7 +148,7 @@ typedef struct Server {
+ #define N_IOVEC_META_FIELDS 20
+ #define N_IOVEC_KERNEL_FIELDS 64
+ #define N_IOVEC_UDEV_FIELDS 32
+-#define N_IOVEC_OBJECT_FIELDS 11
++#define N_IOVEC_OBJECT_FIELDS 12
+ 
+ void server_dispatch_message(Server *s, struct iovec *iovec, unsigned n, unsigned m, const struct ucred *ucred, const struct timeval *tv, const char *label, size_t label_len, const char *unit_id, int priority, pid_t object_pid);
+ void server_driver_message(Server *s, sd_id128_t message_id, const char *format, ...) _printf_(3,4);
diff --git a/SOURCES/0385-journal-cat-return-a-correct-error-not-1.patch b/SOURCES/0385-journal-cat-return-a-correct-error-not-1.patch
new file mode 100644
index 0000000..30d010b
--- /dev/null
+++ b/SOURCES/0385-journal-cat-return-a-correct-error-not-1.patch
@@ -0,0 +1,24 @@
+From ced1149f5af28ce2ad6174a2df9483b483d5e1cf Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Wed, 23 Sep 2015 19:39:30 +0200
+Subject: [PATCH] journal-cat: return a correct error, not -1
+
+Cherry-picked from: e4603df5cf80bbd7a7d51fc66fa6c60e042423bc
+Related: #1318994
+---
+ src/journal/cat.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/journal/cat.c b/src/journal/cat.c
+index 79706b6..ed467b0 100644
+--- a/src/journal/cat.c
++++ b/src/journal/cat.c
+@@ -96,7 +96,7 @@ static int parse_argv(int argc, char *argv[]) {
+                         arg_priority = log_level_from_string(optarg);
+                         if (arg_priority < 0) {
+                                 log_error("Failed to parse priority value.");
+-                                return arg_priority;
++                                return -EINVAL;
+                         }
+                         break;
+ 
diff --git a/SOURCES/0386-journalctl-introduce-short-options-for-since-and-unt.patch b/SOURCES/0386-journalctl-introduce-short-options-for-since-and-unt.patch
new file mode 100644
index 0000000..ec754dc
--- /dev/null
+++ b/SOURCES/0386-journalctl-introduce-short-options-for-since-and-unt.patch
@@ -0,0 +1,90 @@
+From f6cf4e14409d25868caccc3606a928a610465405 Mon Sep 17 00:00:00 2001
+From: Jan Synacek <jsynacek@redhat.com>
+Date: Tue, 13 Oct 2015 10:50:49 +0200
+Subject: [PATCH] journalctl: introduce short options for --since and --until
+
+Fixes #1514.
+
+Cherry-picked from: 66f529249a6b3c3391e732cba44482a498153e16
+Related: #1318994
+---
+ man/journalctl.xml       |  2 ++
+ src/journal/journalctl.c | 16 +++++++---------
+ 2 files changed, 9 insertions(+), 9 deletions(-)
+
+diff --git a/man/journalctl.xml b/man/journalctl.xml
+index 0981fba..dedcf19 100644
+--- a/man/journalctl.xml
++++ b/man/journalctl.xml
+@@ -528,7 +528,9 @@
+       </varlistentry>
+ 
+       <varlistentry>
++        <term><option>-S</option></term>
+         <term><option>--since=</option></term>
++        <term><option>-U</option></term>
+         <term><option>--until=</option></term>
+ 
+         <listitem><para>Start showing entries on or newer than the
+diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
+index e84dd4c..ba9ae05 100644
+--- a/src/journal/journalctl.c
++++ b/src/journal/journalctl.c
+@@ -274,8 +274,8 @@ static void help(void) {
+                "     --system              Show the system journal\n"
+                "     --user                Show the user journal for the current user\n"
+                "  -M --machine=CONTAINER   Operate on local container\n"
+-               "     --since=DATE          Show entries not older than the specified date\n"
+-               "     --until=DATE          Show entries not newer than the specified date\n"
++               "  -S --since=DATE          Show entries not older than the specified date\n"
++               "  -U --until=DATE          Show entries not newer than the specified date\n"
+                "  -c --cursor=CURSOR       Show entries starting at the specified cursor\n"
+                "     --after-cursor=CURSOR Show entries after the specified cursor\n"
+                "     --show-cursor         Print the cursor after all the entries\n"
+@@ -347,8 +347,6 @@ static int parse_argv(int argc, char *argv[]) {
+                 ARG_VERIFY,
+                 ARG_VERIFY_KEY,
+                 ARG_DISK_USAGE,
+-                ARG_SINCE,
+-                ARG_UNTIL,
+                 ARG_AFTER_CURSOR,
+                 ARG_SHOW_CURSOR,
+                 ARG_USER_UNIT,
+@@ -398,8 +396,8 @@ static int parse_argv(int argc, char *argv[]) {
+                 { "cursor",         required_argument, NULL, 'c'                },
+                 { "after-cursor",   required_argument, NULL, ARG_AFTER_CURSOR   },
+                 { "show-cursor",    no_argument,       NULL, ARG_SHOW_CURSOR    },
+-                { "since",          required_argument, NULL, ARG_SINCE          },
+-                { "until",          required_argument, NULL, ARG_UNTIL          },
++                { "since",          required_argument, NULL, 'S'                },
++                { "until",          required_argument, NULL, 'U'                },
+                 { "unit",           required_argument, NULL, 'u'                },
+                 { "user-unit",      required_argument, NULL, ARG_USER_UNIT      },
+                 { "field",          required_argument, NULL, 'F'                },
+@@ -421,7 +419,7 @@ static int parse_argv(int argc, char *argv[]) {
+         assert(argc >= 0);
+         assert(argv);
+ 
+-        while ((c = getopt_long(argc, argv, "hefo:aln::qmb::kD:p:c:t:u:F:xrM:", options, NULL)) >= 0)
++        while ((c = getopt_long(argc, argv, "hefo:aln::qmb::kD:p:c:S:U:t:u:F:xrM:", options, NULL)) >= 0)
+ 
+                 switch (c) {
+ 
+@@ -711,7 +709,7 @@ static int parse_argv(int argc, char *argv[]) {
+                         break;
+                 }
+ 
+-                case ARG_SINCE:
++                case 'S':
+                         r = parse_timestamp(optarg, &arg_since);
+                         if (r < 0) {
+                                 log_error("Failed to parse timestamp: %s", optarg);
+@@ -720,7 +718,7 @@ static int parse_argv(int argc, char *argv[]) {
+                         arg_since_set = true;
+                         break;
+ 
+-                case ARG_UNTIL:
++                case 'U':
+                         r = parse_timestamp(optarg, &arg_until);
+                         if (r < 0) {
+                                 log_error("Failed to parse timestamp: %s", optarg);
diff --git a/SOURCES/0387-journal-s-Envalid-Invalid.patch b/SOURCES/0387-journal-s-Envalid-Invalid.patch
new file mode 100644
index 0000000..f1cae03
--- /dev/null
+++ b/SOURCES/0387-journal-s-Envalid-Invalid.patch
@@ -0,0 +1,24 @@
+From 80476a1b99601168536e4543124d0532c895c498 Mon Sep 17 00:00:00 2001
+From: Vito Caputo <vito.caputo@coreos.com>
+Date: Fri, 23 Oct 2015 16:12:31 -0700
+Subject: [PATCH] journal: s/Envalid/Invalid/
+
+Cherry-picked from: 0c4a83a259c2ff87df83f48cd7ceef37b8746f4f
+Related: #1318994
+---
+ src/journal/journal-verify.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/journal/journal-verify.c b/src/journal/journal-verify.c
+index 8a66ac7..250d4c7 100644
+--- a/src/journal/journal-verify.c
++++ b/src/journal/journal-verify.c
+@@ -899,7 +899,7 @@ int journal_file_verify(
+ 
+                 r = journal_file_object_verify(f, p, o);
+                 if (r < 0) {
+-                        error(p, "Envalid object contents: %s", strerror(-r));
++                        error(p, "Invalid object contents: %s", strerror(-r));
+                         goto fail;
+                 }
+ 
diff --git a/SOURCES/0388-journald-dispatch-SIGTERM-SIGINT-with-a-low-priority.patch b/SOURCES/0388-journald-dispatch-SIGTERM-SIGINT-with-a-low-priority.patch
new file mode 100644
index 0000000..fefb1b5
--- /dev/null
+++ b/SOURCES/0388-journald-dispatch-SIGTERM-SIGINT-with-a-low-priority.patch
@@ -0,0 +1,43 @@
+From be21e10cf30e66215e986ab900637b32e502a29a Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Tue, 10 Nov 2015 16:53:00 +0100
+Subject: [PATCH] journald: dispatch SIGTERM/SIGINT with a low priority
+
+Let's make sure to process all queued log data before exiting, so that
+we don't unnecessary lose messages when shutting down.
+
+https://github.com/systemd/systemd/pull/1812#issuecomment-155149871
+
+Cherry-picked from: b374689c02c681671a3c3c0b0fd3add32386b442
+Related: #1318994
+---
+ src/journal/journald-server.c | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c
+index 275224d..2b7ecd0 100644
+--- a/src/journal/journald-server.c
++++ b/src/journal/journald-server.c
+@@ -1284,10 +1284,22 @@ static int setup_signals(Server *s) {
+         if (r < 0)
+                 return r;
+ 
++        /* Let's process SIGTERM late, so that we flush all queued
++         * messages to disk before we exit */
++        r = sd_event_source_set_priority(s->sigterm_event_source, SD_EVENT_PRIORITY_NORMAL+20);
++        if (r < 0)
++                return r;
++
++        /* When journald is invoked on the terminal (when debugging),
++         * it's useful if C-c is handled equivalent to SIGTERM. */
+         r = sd_event_add_signal(s->event, &s->sigint_event_source, SIGINT, dispatch_sigterm, s);
+         if (r < 0)
+                 return r;
+ 
++        r = sd_event_source_set_priority(s->sigint_event_source, SD_EVENT_PRIORITY_NORMAL+20);
++        if (r < 0)
++                return r;
++
+         return 0;
+ }
+ 
diff --git a/SOURCES/0389-lz4-fix-size-check-which-had-no-chance-of-working-on.patch b/SOURCES/0389-lz4-fix-size-check-which-had-no-chance-of-working-on.patch
new file mode 100644
index 0000000..2dd758d
--- /dev/null
+++ b/SOURCES/0389-lz4-fix-size-check-which-had-no-chance-of-working-on.patch
@@ -0,0 +1,25 @@
+From 942cfd50b5c03f19cfe1b03040c54b7a460b5593 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
+Date: Tue, 1 Dec 2015 22:53:23 -0500
+Subject: [PATCH] lz4: fix size check which had no chance of working on
+ big-endian
+
+Cherry-picked from: b3aa622929f81b44974d182636b1fde8b2a506e5
+Related: #1318994
+---
+ src/journal/compress.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/journal/compress.c b/src/journal/compress.c
+index c9a3399..4fb09f5 100644
+--- a/src/journal/compress.c
++++ b/src/journal/compress.c
+@@ -190,7 +190,7 @@ int decompress_blob_lz4(const void *src, uint64_t src_size,
+                 return -EBADMSG;
+ 
+         size = le64toh( *(le64_t*)src );
+-        if (size < 0 || (le64_t) size != *(le64_t*)src)
++        if (size < 0 || (unsigned) size != le64toh(*(le64_t*)src))
+                 return -EFBIG;
+         if ((size_t) size > *dst_alloc_size) {
+                 out = realloc(*dst, size);
diff --git a/SOURCES/0390-journal-normalize-priority-of-logging-sources.patch b/SOURCES/0390-journal-normalize-priority-of-logging-sources.patch
new file mode 100644
index 0000000..bbdc47e
--- /dev/null
+++ b/SOURCES/0390-journal-normalize-priority-of-logging-sources.patch
@@ -0,0 +1,70 @@
+From c87355bc80da9e2cba7f7723d7c6568dfa56f1a1 Mon Sep 17 00:00:00 2001
+From: Vito Caputo <vito.caputo@coreos.com>
+Date: Fri, 8 Jan 2016 12:11:44 -0800
+Subject: [PATCH] journal: normalize priority of logging sources
+
+The stream event source has a priority of SD_EVENT_PRIORITY_NORMAL+5,
+and stdout source +10, but the native and syslog event sources are left
+at the default of 0.
+
+As a result, any heavy native or syslog logger can cause starvation of
+the other loggers.  This is trivially demonstrated by running:
+
+ dd if=/dev/urandom bs=8k | od | systemd-cat & # native spammer
+ systemd-run echo hello & # stream logger
+ journalctl --follow --output=verbose --no-pager --identifier=echo &
+
+... and wait, and wait, the "hello" never comes.
+
+Now kill %1, "hello" arrives finally.
+
+Cherry-picked from: 48cef29504b1ffc0df9929f2d8b2af2ad74d2b4a
+Related: #1318994
+---
+ src/journal/journald-native.c | 4 ++++
+ src/journal/journald-stream.c | 2 +-
+ src/journal/journald-syslog.c | 4 ++++
+ 3 files changed, 9 insertions(+), 1 deletion(-)
+
+diff --git a/src/journal/journald-native.c b/src/journal/journald-native.c
+index 851625d..2c9cf6e 100644
+--- a/src/journal/journald-native.c
++++ b/src/journal/journald-native.c
+@@ -457,5 +457,9 @@ int server_open_native_socket(Server*s) {
+         if (r < 0)
+                 return log_error_errno(r, "Failed to add native server fd to event loop: %m");
+ 
++        r = sd_event_source_set_priority(s->native_event_source, SD_EVENT_PRIORITY_NORMAL+5);
++        if (r < 0)
++                return log_error_errno(r, "Failed to adjust native event source priority: %m");
++
+         return 0;
+ }
+diff --git a/src/journal/journald-stream.c b/src/journal/journald-stream.c
+index 15a554c..b860714 100644
+--- a/src/journal/journald-stream.c
++++ b/src/journal/journald-stream.c
+@@ -448,7 +448,7 @@ int server_open_stdout_socket(Server *s) {
+         if (r < 0)
+                 return log_error_errno(r, "Failed to add stdout server fd to event source: %m");
+ 
+-        r = sd_event_source_set_priority(s->stdout_event_source, SD_EVENT_PRIORITY_NORMAL+10);
++        r = sd_event_source_set_priority(s->stdout_event_source, SD_EVENT_PRIORITY_NORMAL+5);
+         if (r < 0)
+                 return log_error_errno(r, "Failed to adjust priority of stdout server event source: %m");
+ 
+diff --git a/src/journal/journald-syslog.c b/src/journal/journald-syslog.c
+index 4e118aa..8602b4a 100644
+--- a/src/journal/journald-syslog.c
++++ b/src/journal/journald-syslog.c
+@@ -421,6 +421,10 @@ int server_open_syslog_socket(Server *s) {
+         if (r < 0)
+                 return log_error_errno(r, "Failed to add syslog server fd to event loop: %m");
+ 
++        r = sd_event_source_set_priority(s->syslog_event_source, SD_EVENT_PRIORITY_NORMAL+5);
++        if (r < 0)
++                return log_error_errno(r, "Failed to adjust syslog event source priority: %m");
++
+         return 0;
+ }
+ 
diff --git a/SOURCES/0391-Fix-miscalculated-buffer-size-and-uses-of-size-unlim.patch b/SOURCES/0391-Fix-miscalculated-buffer-size-and-uses-of-size-unlim.patch
new file mode 100644
index 0000000..c381989
--- /dev/null
+++ b/SOURCES/0391-Fix-miscalculated-buffer-size-and-uses-of-size-unlim.patch
@@ -0,0 +1,43 @@
+From 573e86d7e9f0038044d5cba2a1a543e24b063a79 Mon Sep 17 00:00:00 2001
+From: Aleksander Adamowski <olo@fb.com>
+Date: Mon, 11 Jan 2016 15:26:41 -0800
+Subject: [PATCH] Fix miscalculated buffer size and uses of size-unlimited
+ sprintf() function.
+
+Not sure if this results in an exploitable buffer overflow, probably not
+since the the int value is likely sanitized somewhere earlier and it's
+being put through a bit mask shortly before being used.
+
+Cherry-picked from: 13f5402c6b734ed4c2b3e8b7c3d3bf6d815e7661
+Related: #1318994
+---
+ src/journal/journald-syslog.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/src/journal/journald-syslog.c b/src/journal/journald-syslog.c
+index 8602b4a..b499a0d 100644
+--- a/src/journal/journald-syslog.c
++++ b/src/journal/journald-syslog.c
+@@ -317,7 +317,7 @@ void server_process_syslog_message(
+         size_t label_len) {
+ 
+         char syslog_priority[sizeof("PRIORITY=") + DECIMAL_STR_MAX(int)],
+-             syslog_facility[sizeof("SYSLOG_FACILITY") + DECIMAL_STR_MAX(int)];
++             syslog_facility[sizeof("SYSLOG_FACILITY=") + DECIMAL_STR_MAX(int)];
+         const char *message = NULL, *syslog_identifier = NULL, *syslog_pid = NULL;
+         struct iovec iovec[N_IOVEC_META_FIELDS + 6];
+         unsigned n = 0;
+@@ -348,11 +348,11 @@ void server_process_syslog_message(
+ 
+         IOVEC_SET_STRING(iovec[n++], "_TRANSPORT=syslog");
+ 
+-        sprintf(syslog_priority, "PRIORITY=%i", priority & LOG_PRIMASK);
++        snprintf(syslog_priority, sizeof(syslog_priority), "PRIORITY=%i", priority & LOG_PRIMASK);
+         IOVEC_SET_STRING(iovec[n++], syslog_priority);
+ 
+         if (priority & LOG_FACMASK) {
+-                sprintf(syslog_facility, "SYSLOG_FACILITY=%i", LOG_FAC(priority));
++                snprintf(syslog_facility, sizeof(syslog_facility), "SYSLOG_FACILITY=%i", LOG_FAC(priority));
+                 IOVEC_SET_STRING(iovec[n++], syslog_facility);
+         }
+ 
diff --git a/SOURCES/0392-journal-Drop-monotonicity-check-when-appending-to-jo.patch b/SOURCES/0392-journal-Drop-monotonicity-check-when-appending-to-jo.patch
new file mode 100644
index 0000000..d1c3c5b
--- /dev/null
+++ b/SOURCES/0392-journal-Drop-monotonicity-check-when-appending-to-jo.patch
@@ -0,0 +1,34 @@
+From e1d77a906fef76c1c8db2132e1d3a407f913444c Mon Sep 17 00:00:00 2001
+From: Klearchos Chaloulos <klearchos.chaloulos@nokia.com>
+Date: Tue, 9 Feb 2016 12:14:54 +0200
+Subject: [PATCH] journal: Drop monotonicity check when appending to journal
+ file
+
+Remove the check that triggers rotation of the journal file when the
+arriving log entry had a monotonic timestamp smaller that the previous
+log entry. This check causes unnecessary rotations when journal-remote
+was receiving from multiple senders, therefore monotonicity can not be
+guaranteed. Also, it does not offer any useful functionality for
+systemd-journald.
+
+Cherry-picked from: ecb6105a1bd8445a123343827d46bb527bcca92f
+Related: #1318994
+---
+ src/journal/journal-file.c | 4 ----
+ 1 file changed, 4 deletions(-)
+
+diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c
+index 2a93460..8034b77 100644
+--- a/src/journal/journal-file.c
++++ b/src/journal/journal-file.c
+@@ -1419,10 +1419,6 @@ int journal_file_append_entry(JournalFile *f, const dual_timestamp *ts, const st
+                 ts = &_ts;
+         }
+ 
+-        if (f->tail_entry_monotonic_valid &&
+-            ts->monotonic < le64toh(f->header->tail_entry_monotonic))
+-                return -EINVAL;
+-
+ #ifdef HAVE_GCRYPT
+         r = journal_file_maybe_append_tag(f, ts->realtime);
+         if (r < 0)
diff --git a/SOURCES/0393-journalctl-unify-how-we-free-boot-id-lists-a-bit.patch b/SOURCES/0393-journalctl-unify-how-we-free-boot-id-lists-a-bit.patch
new file mode 100644
index 0000000..93b9348
--- /dev/null
+++ b/SOURCES/0393-journalctl-unify-how-we-free-boot-id-lists-a-bit.patch
@@ -0,0 +1,83 @@
+From 76d6062ebf93614a45f1f74be7a93a9a662c5812 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Tue, 19 May 2015 00:35:02 +0200
+Subject: [PATCH] journalctl: unify how we free boot id lists a bit
+
+Instead of use LIST_FOREACH_SAFE, just use the same, seperate destructor
+everywhere.
+
+Cherry-picked from: 9530e0d023b0e9308f19eadf6e42cdc25bc30793
+Related: #1318994
+---
+ src/journal/journalctl.c | 21 +++++++++++++++------
+ 1 file changed, 15 insertions(+), 6 deletions(-)
+
+diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
+index ba9ae05..5864ff5 100644
+--- a/src/journal/journalctl.c
++++ b/src/journal/journalctl.c
+@@ -932,6 +932,15 @@ static int add_matches(sd_journal *j, char **args) {
+         return 0;
+ }
+ 
++static void boot_id_free_all(BootId *l) {
++
++        while (l) {
++                BootId *i = l;
++                LIST_REMOVE(boot_list, l, i);
++                free(i);
++        }
++}
++
+ static int discover_next_boot(
+                 sd_journal *j,
+                 BootId **boot,
+@@ -1009,6 +1018,7 @@ static int discover_next_boot(
+ 
+         *boot = next_boot;
+         next_boot = NULL;
++
+         return 0;
+ }
+ 
+@@ -1080,9 +1090,7 @@ static int get_boots(
+ 
+                 r = discover_next_boot(j, &current, advance_older, !query_ref_boot);
+                 if (r < 0) {
+-                        BootId *id, *id_next;
+-                        LIST_FOREACH_SAFE(boot_list, id, id_next, head)
+-                                free(id);
++                        boot_id_free_all(head);
+                         return r;
+                 }
+ 
+@@ -1118,7 +1126,7 @@ finish:
+ 
+ static int list_boots(sd_journal *j) {
+         int w, i, count;
+-        BootId *id, *id_next, *all_ids;
++        BootId *id, *all_ids;
+ 
+         assert(j);
+ 
+@@ -1132,7 +1140,7 @@ static int list_boots(sd_journal *j) {
+         w = DECIMAL_STR_WIDTH(count - 1) + 1;
+ 
+         i = 0;
+-        LIST_FOREACH_SAFE(boot_list, id, id_next, all_ids) {
++        LIST_FOREACH(boot_list, id, all_ids) {
+                 char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX];
+ 
+                 printf("% *i " SD_ID128_FORMAT_STR " %s—%s\n",
+@@ -1141,9 +1149,10 @@ static int list_boots(sd_journal *j) {
+                        format_timestamp_maybe_utc(a, sizeof(a), id->first),
+                        format_timestamp_maybe_utc(b, sizeof(b), id->last));
+                 i++;
+-                free(id);
+         }
+ 
++        boot_id_free_all(all_ids);
++
+         return 0;
+ }
+ 
diff --git a/SOURCES/0394-journalctl-don-t-trust-the-per-field-entry-tables-wh.patch b/SOURCES/0394-journalctl-don-t-trust-the-per-field-entry-tables-wh.patch
new file mode 100644
index 0000000..1aa83fb
--- /dev/null
+++ b/SOURCES/0394-journalctl-don-t-trust-the-per-field-entry-tables-wh.patch
@@ -0,0 +1,187 @@
+From cc5710c3ad0ff51fa84b736d66d5f70aa0ade2b3 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Mon, 25 Apr 2016 18:08:42 +0200
+Subject: [PATCH] journalctl: don't trust the per-field entry tables when
+ looking for boot IDs
+
+When appending to a journal file, journald will:
+
+a) first, append the actual entry to the end of the journal file
+b) second, add an offset reference to it to the global entry array stored at
+   the beginning of the file
+c) third, add offset references to it to the per-field entry array stored at
+   various places of the file
+
+The global entry array, maintained by b) is used when iterating through the
+journal without matches applied.
+
+The per-field entry array maintained by c) is used when iterating through the
+journal with a match for that specific field applied.
+
+In the wild, there are journal files where a) and b) were completed, but c)
+was not before the files were abandoned. This means, that in some cases log
+entries are at the end of these files that appear in the global entry array,
+but not in the per-field entry array of the _BOOT_ID= field. Now, the
+"journalctl --list-boots" command alternatingly uses the global entry array
+and the per-field entry array of the _BOOT_ID= field. It seeks to the last
+entry of a specific _BOOT_ID=field by having the right match installed, and
+then jumps to the next following entry with no match installed anymore, under
+the assumption this would bring it to the next boot ID. However, if the
+per-field entry wasn't written fully, it might actually turn out that the
+global entry array might know one more entry with the same _BOOT_ID, thus
+resulting in a indefinite loop around the same _BOOT_ID.
+
+This patch fixes that, by updating the boot search logic to always continue
+reading entries until the boot ID actually changed from the previous. Thus, the
+per-field entry array is used as quick jump index (i.e. as an optimization),
+but not trusted otherwise.  Only the global entry array is trusted.
+
+This replaces PR #1904, which is actually very similar to this one. However,
+this one actually reads the boot ID directly from the entry header, and doesn't
+try to read it at all until the read pointer is actually really located on the
+first item to read.
+
+Fixes: #617
+
+Replaces: #1904
+
+Cherry-picked from: dc00966228ff90c554fd034e588ea55eb605ec52
+Related: #1318994
+---
+ src/journal/journalctl.c | 71 ++++++++++++++++++++++++++++--------------------
+ 1 file changed, 42 insertions(+), 29 deletions(-)
+
+diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
+index 5864ff5..723854a 100644
+--- a/src/journal/journalctl.c
++++ b/src/journal/journalctl.c
+@@ -941,18 +941,18 @@ static void boot_id_free_all(BootId *l) {
+         }
+ }
+ 
+-static int discover_next_boot(
+-                sd_journal *j,
+-                BootId **boot,
++static int discover_next_boot(sd_journal *j,
++                sd_id128_t previous_boot_id,
+                 bool advance_older,
+-                bool read_realtime) {
++                BootId **ret) {
+ 
+-        int r;
+-        char match[9+32+1] = "_BOOT_ID=";
+         _cleanup_free_ BootId *next_boot = NULL;
++        char match[9+32+1] = "_BOOT_ID=";
++        sd_id128_t boot_id;
++        int r;
+ 
+         assert(j);
+-        assert(boot);
++        assert(ret);
+ 
+         /* We expect the journal to be on the last position of a boot
+          * (in relation to the direction we are going), so that the next
+@@ -965,29 +965,40 @@ static int discover_next_boot(
+          * we can actually advance to a *different* boot. */
+         sd_journal_flush_matches(j);
+ 
+-        if (advance_older)
+-                r = sd_journal_previous(j);
+-        else
+-                r = sd_journal_next(j);
+-        if (r < 0)
+-                return r;
+-        else if (r == 0)
+-                return 0; /* End of journal, yay. */
++        do {
++                if (advance_older)
++                        r = sd_journal_previous(j);
++                else
++                        r = sd_journal_next(j);
++                if (r < 0)
++                        return r;
++                else if (r == 0)
++                        return 0; /* End of journal, yay. */
++
++                r = sd_journal_get_monotonic_usec(j, NULL, &boot_id);
++                if (r < 0)
++                        return r;
++
++                /* We iterate through this in a loop, until the boot ID differs from the previous one. Note that
++                 * normally, this will only require a single iteration, as we seeked to the last entry of the previous
++                 * boot entry already. However, it might happen that the per-journal-field entry arrays are less
++                 * complete than the main entry array, and hence might reference an entry that's not actually the last
++                 * one of the boot ID as last one. Let's hence use the per-field array is initial seek position to
++                 * speed things up, but let's not trust that it is complete, and hence, manually advance as
++                 * necessary. */
++
++        } while (sd_id128_equal(boot_id, previous_boot_id));
+ 
+         next_boot = new0(BootId, 1);
+         if (!next_boot)
+                 return log_oom();
+ 
+-        r = sd_journal_get_monotonic_usec(j, NULL, &next_boot->id);
++        next_boot->id = boot_id;
++
++        r = sd_journal_get_realtime_usec(j, &next_boot->first);
+         if (r < 0)
+                 return r;
+ 
+-        if (read_realtime) {
+-                r = sd_journal_get_realtime_usec(j, &next_boot->first);
+-                if (r < 0)
+-                        return r;
+-        }
+-
+         /* Now seek to the last occurrence of this boot ID. */
+         sd_id128_to_string(next_boot->id, match + 9);
+         r = sd_journal_add_match(j, match, sizeof(match) - 1);
+@@ -1010,13 +1021,11 @@ static int discover_next_boot(
+         else if (r == 0)
+                 return -ENODATA; /* This shouldn't happen. We just came from this very boot ID. */
+ 
+-        if (read_realtime) {
+-                r = sd_journal_get_realtime_usec(j, &next_boot->last);
+-                if (r < 0)
+-                        return r;
+-        }
++        r = sd_journal_get_realtime_usec(j, &next_boot->last);
++        if (r < 0)
++                return r;
+ 
+-        *boot = next_boot;
++        *ret = next_boot;
+         next_boot = NULL;
+ 
+         return 0;
+@@ -1032,6 +1041,7 @@ static int get_boots(
+         int r, count = 0;
+         BootId *head = NULL, *tail = NULL;
+         const bool advance_older = query_ref_boot && ref_boot_offset <= 0;
++        sd_id128_t previous_boot_id;
+ 
+         assert(j);
+ 
+@@ -1085,10 +1095,11 @@ static int get_boots(
+                 /* No sd_journal_next/previous here. */
+         }
+ 
++        previous_boot_id = SD_ID128_NULL;
+         for (;;) {
+                 _cleanup_free_ BootId *current = NULL;
+ 
+-                r = discover_next_boot(j, &current, advance_older, !query_ref_boot);
++                r = discover_next_boot(j, previous_boot_id, advance_older, &current);
+                 if (r < 0) {
+                         boot_id_free_all(head);
+                         return r;
+@@ -1097,6 +1108,8 @@ static int get_boots(
+                 if (!current)
+                         break;
+ 
++                previous_boot_id = current->id;
++
+                 if (query_ref_boot) {
+                         if (!skip_once)
+                                 ref_boot_offset += advance_older ? 1 : -1;
diff --git a/SOURCES/0395-units-remove-udev-control-socket-when-systemd-stops-.patch b/SOURCES/0395-units-remove-udev-control-socket-when-systemd-stops-.patch
new file mode 100644
index 0000000..cca08e1
--- /dev/null
+++ b/SOURCES/0395-units-remove-udev-control-socket-when-systemd-stops-.patch
@@ -0,0 +1,33 @@
+From f77d58374ccd2e3d9c886e59020f1b32e97f2bdc Mon Sep 17 00:00:00 2001
+From: Michal Sekletar <msekletar@users.noreply.github.com>
+Date: Mon, 29 Aug 2016 14:49:20 +0200
+Subject: [PATCH] units: remove udev control socket when systemd stops the
+ socket unit (#49)
+
+Mere presence of the socket in the filesystem makes
+udev_queue_get_udev_is_active() return that udev is running. Note that,
+udev on exit doesn't unlink control socket nor does systemd. Thus socket
+stays around even when both daemon and socket are stopped. This causes
+problems for cryptsetup because when it detects running udev it launches
+synchronous operations that *really* require udev. This in turn may
+cause blocking and subsequent timeout in systemd-cryptsetup on reboot
+while machine is in a state that udev and its control socket units are
+stopped, e.g. emergency mode.
+
+Fixes #2477
+
+Cherry-picked from: a2de10775194edec51b1e88d20a380724a3dc716
+Resolves: #1370133
+---
+ units/systemd-udevd-control.socket | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/units/systemd-udevd-control.socket b/units/systemd-udevd-control.socket
+index 8330a1c..46f704e 100644
+--- a/units/systemd-udevd-control.socket
++++ b/units/systemd-udevd-control.socket
+@@ -17,3 +17,4 @@ Service=systemd-udevd.service
+ ListenSequentialPacket=/run/udev/control
+ SocketMode=0600
+ PassCredentials=yes
++RemoveOnStop=yes
diff --git a/SOURCES/0396-logind-don-t-assert-if-the-slice-is-missing.patch b/SOURCES/0396-logind-don-t-assert-if-the-slice-is-missing.patch
new file mode 100644
index 0000000..75055f3
--- /dev/null
+++ b/SOURCES/0396-logind-don-t-assert-if-the-slice-is-missing.patch
@@ -0,0 +1,26 @@
+From 7f681673fa2af8f1898447ee336763f2eeb00d57 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Fri, 13 Nov 2015 18:47:02 +0100
+Subject: [PATCH] logind: don't assert if the slice is missing
+
+After all, we don't actually really need the slice to work, it's just
+nice to have it.
+
+Cherry-picked from: 38599489e49e840291516488a3ef1b4a56198c58
+Resolves: #1371437
+---
+ src/login/logind-session.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/src/login/logind-session.c b/src/login/logind-session.c
+index 59f5a7a..746e50a 100644
+--- a/src/login/logind-session.c
++++ b/src/login/logind-session.c
+@@ -507,7 +507,6 @@ static int session_start_scope(Session *s) {
+ 
+         assert(s);
+         assert(s->user);
+-        assert(s->user->slice);
+ 
+         if (!s->scope) {
+                 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
diff --git a/SOURCES/0397-core-enable-transient-unit-support-for-slice-units.patch b/SOURCES/0397-core-enable-transient-unit-support-for-slice-units.patch
new file mode 100644
index 0000000..48f6860
--- /dev/null
+++ b/SOURCES/0397-core-enable-transient-unit-support-for-slice-units.patch
@@ -0,0 +1,48 @@
+From e360c720533dccac39d8b88510b15c21a944b042 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Fri, 13 Nov 2015 18:46:50 +0100
+Subject: [PATCH] core: enable transient unit support for slice units
+
+Cherry-picked from: 17f62e9bd00f5fefd486475861b06d3ec6b7ee10
+Resolves: #1370299
+---
+ src/core/dbus-manager.c | 13 ++++++++++++-
+ src/core/slice.c        |  1 +
+ 2 files changed, 13 insertions(+), 1 deletion(-)
+
+diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
+index 9eef290..8d3758a 100644
+--- a/src/core/dbus-manager.c
++++ b/src/core/dbus-manager.c
+@@ -633,7 +633,18 @@ static int transient_unit_from_message(
+         if (r < 0)
+                 return r;
+ 
+-        if (u->load_state != UNIT_NOT_FOUND ||
++        /* Check if the unit already exists or is already referenced,
++         * in a number of different ways. Note that to cater for unit
++         * types such as slice, we are generally fine with units that
++         * are marked UNIT_LOADED even even though nothing was
++         * actually loaded, as those unit types don't require a file
++         * on disk to validly load. */
++
++        if (!IN_SET(u->load_state, UNIT_NOT_FOUND, UNIT_LOADED) ||
++            u->fragment_path ||
++            u->source_path ||
++            !strv_isempty(u->dropin_paths) ||
++            u->refs ||
+             set_size(u->dependencies[UNIT_REFERENCED_BY]) > 0)
+                 return sd_bus_error_setf(error, BUS_ERROR_UNIT_EXISTS, "Unit %s already exists.", name);
+ 
+diff --git a/src/core/slice.c b/src/core/slice.c
+index 61ff9d3..9154558 100644
+--- a/src/core/slice.c
++++ b/src/core/slice.c
+@@ -272,6 +272,7 @@ const UnitVTable slice_vtable = {
+ 
+         .no_alias = true,
+         .no_instances = true,
++        .can_transient = true,
+ 
+         .load = slice_load,
+ 
diff --git a/SOURCES/0398-sd-bus-bump-message-queue-size.patch b/SOURCES/0398-sd-bus-bump-message-queue-size.patch
new file mode 100644
index 0000000..12ac5b5
--- /dev/null
+++ b/SOURCES/0398-sd-bus-bump-message-queue-size.patch
@@ -0,0 +1,31 @@
+From aff078e9ce3c43410de9bc3a2e9cf7042ac799aa Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Wed, 31 Aug 2016 20:09:31 +0200
+Subject: [PATCH] sd-bus: bump message queue size
+
+Let's bump it further, as this the current limit turns out to be problematic
+IRL. Let's bump it to more than twice what we know of is needed.
+
+Fixes: #4068
+
+Cherry-picked from: 5ddda46
+Resolves: #1371205
+---
+ src/libsystemd/sd-bus/bus-internal.h | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/src/libsystemd/sd-bus/bus-internal.h b/src/libsystemd/sd-bus/bus-internal.h
+index 071b3da..6a10686 100644
+--- a/src/libsystemd/sd-bus/bus-internal.h
++++ b/src/libsystemd/sd-bus/bus-internal.h
+@@ -326,8 +326,8 @@ struct sd_bus {
+ 
+ #define BUS_DEFAULT_TIMEOUT ((usec_t) (25 * USEC_PER_SEC))
+ 
+-#define BUS_WQUEUE_MAX 1024
+-#define BUS_RQUEUE_MAX 64*1024
++#define BUS_WQUEUE_MAX (192*1024)
++#define BUS_RQUEUE_MAX (192*1024)
+ 
+ #define BUS_MESSAGE_SIZE_MAX (64*1024*1024)
+ #define BUS_AUTH_SIZE_MAX (64*1024)
diff --git a/SOURCES/0399-install-fix-disable-when-etc-systemd-system-is-a-sym.patch b/SOURCES/0399-install-fix-disable-when-etc-systemd-system-is-a-sym.patch
new file mode 100644
index 0000000..fc0079d
--- /dev/null
+++ b/SOURCES/0399-install-fix-disable-when-etc-systemd-system-is-a-sym.patch
@@ -0,0 +1,24 @@
+From 30c5299e91db30f07b64c6c47ac7417bd4e6988c Mon Sep 17 00:00:00 2001
+From: Lukas Nykryn <lnykryn@redhat.com>
+Date: Tue, 30 Aug 2016 15:04:07 +0200
+Subject: [PATCH] install: fix disable when /etc/systemd/system is a symlink
+
+Cherry-picked from: 67852d08e6a35d34b428e8be64efdb3f003f4697
+Resolves: #1285996
+---
+ src/shared/install.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/shared/install.c b/src/shared/install.c
+index 61aaafe..ab86cd1 100644
+--- a/src/shared/install.c
++++ b/src/shared/install.c
+@@ -476,7 +476,7 @@ static int remove_marked_symlinks(
+         if (set_size(remove_symlinks_to) <= 0)
+                 return 0;
+ 
+-        fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
++        fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC);
+         if (fd < 0)
+                 return -errno;
+ 
diff --git a/SOURCES/0400-rules-add-NVMe-rules-3136.patch b/SOURCES/0400-rules-add-NVMe-rules-3136.patch
new file mode 100644
index 0000000..ba874de
--- /dev/null
+++ b/SOURCES/0400-rules-add-NVMe-rules-3136.patch
@@ -0,0 +1,36 @@
+From d913c83db4d3271a400173dfee55078335055e86 Mon Sep 17 00:00:00 2001
+From: Ming Lin <minggr@gmail.com>
+Date: Fri, 29 Apr 2016 04:02:57 -0700
+Subject: [PATCH] rules: add NVMe rules (#3136)
+
+Add NVMe rules using the "wwid" attribute.
+
+root@target:~# cat /sys/block/nvme0n1/wwid
+eui.3825004235000591
+
+root@target:~# ls /dev/disk/by-id/ -l |grep nvme
+lrwxrwxrwx 1 root root 13 Apr 27 16:08 nvme-eui.3825004235000591 -> ../../nvme0n1
+lrwxrwxrwx 1 root root 15 Apr 27 16:08 nvme-eui.3825004235000591-part1 -> ../../nvme0n1p1
+lrwxrwxrwx 1 root root 15 Apr 27 16:08 nvme-eui.3825004235000591-part2 -> ../../nvme0n1p2
+
+Cherry-picked from: 427a28ecbe0eb170e651e0530ab58d6e6f6c498c
+Resolves: #1274651
+---
+ rules/60-persistent-storage.rules | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/rules/60-persistent-storage.rules b/rules/60-persistent-storage.rules
+index 71ab974..cc01acb 100644
+--- a/rules/60-persistent-storage.rules
++++ b/rules/60-persistent-storage.rules
+@@ -22,6 +22,10 @@ TEST=="whole_disk", GOTO="persistent_storage_end"
+ # for partitions import parent information
+ ENV{DEVTYPE}=="partition", IMPORT{parent}="ID_*"
+ 
++# NVMe
++KERNEL=="nvme*[0-9]n*[0-9]", ATTR{wwid}=="?*", SYMLINK+="disk/by-id/nvme-$attr{wwid}"
++KERNEL=="nvme*[0-9]n*[0-9]p*[0-9]", ENV{DEVTYPE}=="partition", ATTRS{wwid}=="?*", SYMLINK+="disk/by-id/nvme-$attr{wwid}-part%n"
++
+ # virtio-blk
+ KERNEL=="vd*[!0-9]", ATTRS{serial}=="?*", ENV{ID_SERIAL}="$attr{serial}", SYMLINK+="disk/by-id/virtio-$env{ID_SERIAL}"
+ KERNEL=="vd*[0-9]", ATTRS{serial}=="?*", ENV{ID_SERIAL}="$attr{serial}", SYMLINK+="disk/by-id/virtio-$env{ID_SERIAL}-part%n"
diff --git a/SOURCES/0401-rules-introduce-disk-by-id-model_serial-symlinks-for.patch b/SOURCES/0401-rules-introduce-disk-by-id-model_serial-symlinks-for.patch
new file mode 100644
index 0000000..a6d5133
--- /dev/null
+++ b/SOURCES/0401-rules-introduce-disk-by-id-model_serial-symlinks-for.patch
@@ -0,0 +1,36 @@
+From 1e61121501f79e654a36bf2efb6a987f6a11c262 Mon Sep 17 00:00:00 2001
+From: Michal Sekletar <msekletar@users.noreply.github.com>
+Date: Wed, 17 Aug 2016 14:10:28 +0200
+Subject: [PATCH] rules: introduce disk/by-id (model_serial) symlinks for NVMe
+ drives (#3974)
+
+$ ls -l /dev/disk/by-id/nvme*
+lrwxrwxrwx. 1 root root 13 Aug 17 04:25 /dev/disk/by-id/nvme-HUSPR3216AHP301_STM0001B6780 -> ../../nvme0n1
+lrwxrwxrwx. 1 root root 15 Aug 17 04:25 /dev/disk/by-id/nvme-HUSPR3216AHP301_STM0001B6780-part1 -> ../../nvme0n1p1
+
+https://github.com/systemd/systemd/issues/1453
+https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=779ff75617099f4defe14e20443b95019a4c5ae8
+
+Cherry-picked from: a5110c90303cf455db5062faef34d5724d12e2e9
+Related: #1274651
+---
+ rules/60-persistent-storage.rules | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/rules/60-persistent-storage.rules b/rules/60-persistent-storage.rules
+index cc01acb..74f8f21 100644
+--- a/rules/60-persistent-storage.rules
++++ b/rules/60-persistent-storage.rules
+@@ -26,6 +26,12 @@ ENV{DEVTYPE}=="partition", IMPORT{parent}="ID_*"
+ KERNEL=="nvme*[0-9]n*[0-9]", ATTR{wwid}=="?*", SYMLINK+="disk/by-id/nvme-$attr{wwid}"
+ 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{model}=="?*", ENV{ID_SERIAL_SHORT}=="?*", ENV{ID_SERIAL}="$attr{model}_$env{ID_SERIAL_SHORT}", SYMLINK+="disk/by-id/nvme-$env{ID_SERIAL}"
++
++KERNEL=="nvme*[0-9]n*[0-9]p*[0-9]", ENV{DEVTYPE}=="partition", ATTRS{serial}=="?*", ENV{ID_SERIAL_SHORT}="$attr{serial}"
++KERNEL=="nvme*[0-9]n*[0-9]p*[0-9]", ENV{DEVTYPE}=="partition", ATTRS{model}=="?*", ENV{ID_SERIAL_SHORT}=="?*", ENV{ID_SERIAL}="$attr{model}_$env{ID_SERIAL_SHORT}", SYMLINK+="disk/by-id/nvme-$env{ID_SERIAL}-part%n"
++
+ # virtio-blk
+ KERNEL=="vd*[!0-9]", ATTRS{serial}=="?*", ENV{ID_SERIAL}="$attr{serial}", SYMLINK+="disk/by-id/virtio-$env{ID_SERIAL}"
+ KERNEL=="vd*[0-9]", ATTRS{serial}=="?*", ENV{ID_SERIAL}="$attr{serial}", SYMLINK+="disk/by-id/virtio-$env{ID_SERIAL}-part%n"
diff --git a/SOURCES/0402-rules-fix-for-possible-whitespace-in-the-model-attri.patch b/SOURCES/0402-rules-fix-for-possible-whitespace-in-the-model-attri.patch
new file mode 100644
index 0000000..504b0e8
--- /dev/null
+++ b/SOURCES/0402-rules-fix-for-possible-whitespace-in-the-model-attri.patch
@@ -0,0 +1,33 @@
+From 8ed606212fb3e82c12b1fcea8500a5dfe4f89393 Mon Sep 17 00:00:00 2001
+From: Michal Sekletar <msekleta@redhat.com>
+Date: Thu, 1 Sep 2016 12:42:05 +0200
+Subject: [PATCH] rules: fix for possible whitespace in the "model" attribute
+
+Without this the rules would create multiple wrong symlinks, because
+SYMLINK treats strings with spaces as a list of links to create.
+
+Suggested-by: Artur Paszkiewicz <artur.paszkiewicz@intel.com>
+
+Cherry-picked from: f41c12825db7460429c857ccc0e545bd631a62a0
+Related: #1274651
+---
+ rules/60-persistent-storage.rules | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/rules/60-persistent-storage.rules b/rules/60-persistent-storage.rules
+index 74f8f21..06e3329 100644
+--- a/rules/60-persistent-storage.rules
++++ b/rules/60-persistent-storage.rules
+@@ -27,10 +27,10 @@ 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{model}=="?*", ENV{ID_SERIAL_SHORT}=="?*", ENV{ID_SERIAL}="$attr{model}_$env{ID_SERIAL_SHORT}", SYMLINK+="disk/by-id/nvme-$env{ID_SERIAL}"
++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}"
+-KERNEL=="nvme*[0-9]n*[0-9]p*[0-9]", ENV{DEVTYPE}=="partition", ATTRS{model}=="?*", ENV{ID_SERIAL_SHORT}=="?*", ENV{ID_SERIAL}="$attr{model}_$env{ID_SERIAL_SHORT}", SYMLINK+="disk/by-id/nvme-$env{ID_SERIAL}-part%n"
++KERNEL=="nvme*[0-9]n*[0-9]p*[0-9]", ENV{DEVTYPE}=="partition", ATTRS{model}=="?*", ENV{ID_SERIAL_SHORT}=="?*", ENV{ID_SERIAL}="$attr{model}_$env{ID_SERIAL_SHORT}", SYMLINK+="disk/by-id/nvme-$env{ID_SERIAL}-part%n", OPTIONS="string_escape=replace"
+ 
+ # virtio-blk
+ KERNEL=="vd*[!0-9]", ATTRS{serial}=="?*", ENV{ID_SERIAL}="$attr{serial}", SYMLINK+="disk/by-id/virtio-$env{ID_SERIAL}"
diff --git a/SOURCES/0403-systemctl-pid1-do-not-warn-about-missing-install-inf.patch b/SOURCES/0403-systemctl-pid1-do-not-warn-about-missing-install-inf.patch
new file mode 100644
index 0000000..95a1cef
--- /dev/null
+++ b/SOURCES/0403-systemctl-pid1-do-not-warn-about-missing-install-inf.patch
@@ -0,0 +1,111 @@
+From 5f273838f41f27e0045395c1677272d9dd12496c Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
+Date: Thu, 21 Apr 2016 20:04:21 -0400
+Subject: [PATCH] systemctl,pid1: do not warn about missing install info with
+ "preset"
+
+When "preset" was executed for a unit without install info, we'd warn similarly
+as for "enable" and "disable". But "preset" is usually called for all units,
+because the preset files are provided by the distribution, and the units are under
+control of individual programs, and it's reasonable to call "preset" for all units
+rather then try to do it only for the ones that can be installed.
+We also don't warn about missing info for "preset-all". Thus it seems reasonable
+to silently ignore units w/o install info when presetting.
+
+(In addition, when more than one unit was specified, we'd issue the warning
+only if none of them had install info. But this is probably something to fix
+for enable/disable too.)
+
+Cherry-picked from: 39207373dd638e548019ddb49929f15795b8b404
+Resolves: #1373950
+---
+ man/systemctl.xml         | 26 +++++++++++++-------------
+ src/systemctl/systemctl.c |  7 ++++---
+ 2 files changed, 17 insertions(+), 16 deletions(-)
+
+diff --git a/man/systemctl.xml b/man/systemctl.xml
+index 2d0678d..bb21f3a 100644
+--- a/man/systemctl.xml
++++ b/man/systemctl.xml
+@@ -1012,22 +1012,22 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
+           <term><command>preset <replaceable>NAME</replaceable>...</command></term>
+ 
+           <listitem>
+-            <para>Reset one or more unit files, as specified on the
+-            command line, to the defaults configured in the preset
+-            policy files. This has the same effect as
+-            <command>disable</command> or <command>enable</command>,
+-            depending how the unit is listed in the preset files.</para>
++            <para>Reset the enable/disable status one or more unit files, as specified on
++            the command line, to the defaults configured in the preset policy files. This
++            has the same effect as <command>disable</command> or
++            <command>enable</command>, depending how the unit is listed in the preset
++            files.</para>
+ 
+-            <para>Use <option>--preset-mode=</option> to control
+-            whether units shall be enabled and disabled, or only
+-            enabled, or only disabled.</para>
++            <para>Use <option>--preset-mode=</option> to control whether units shall be
++            enabled and disabled, or only enabled, or only disabled.</para>
++
++            <para>If the unit carries no install information, it will be silently ignored
++            by this command.</para>
+ 
+-            <para>For more information on the preset policy format,
+-            see
++            <para>For more information on the preset policy format, see
+             <citerefentry><refentrytitle>systemd.preset</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+-            For more information on the concept of presets, please
+-            consult the <ulink
+-            url="http://freedesktop.org/wiki/Software/systemd/Preset">Preset</ulink>
++            For more information on the concept of presets, please consult the
++            <ulink url="http://freedesktop.org/wiki/Software/systemd/Preset">Preset</ulink>
+             document.</para>
+           </listitem>
+         </varlistentry>
+diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
+index e4b404a..e854508 100644
+--- a/src/systemctl/systemctl.c
++++ b/src/systemctl/systemctl.c
+@@ -5367,6 +5367,7 @@ static int enable_unit(sd_bus *bus, char **args) {
+         UnitFileChange *changes = NULL;
+         unsigned n_changes = 0;
+         int carries_install_info = -1;
++        bool ignore_carries_install_info = false;
+         int r;
+ 
+         if (!args[1])
+@@ -5404,7 +5405,6 @@ static int enable_unit(sd_bus *bus, char **args) {
+                         r = unit_file_link(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
+                 else if (streq(verb, "preset")) {
+                         r = unit_file_preset(arg_scope, arg_runtime, arg_root, names, arg_preset_mode, arg_force, &changes, &n_changes);
+-                        carries_install_info = r;
+                 } else if (streq(verb, "mask"))
+                         r = unit_file_mask(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
+                 else if (streq(verb, "unmask"))
+@@ -5424,7 +5424,7 @@ static int enable_unit(sd_bus *bus, char **args) {
+         } else {
+                 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
+                 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+-                int expect_carries_install_info = false;
++                bool expect_carries_install_info = false;
+                 bool send_force = true, send_preset_mode = false;
+                 const char *method;
+ 
+@@ -5450,6 +5450,7 @@ static int enable_unit(sd_bus *bus, char **args) {
+                                 method = "PresetUnitFiles";
+ 
+                         expect_carries_install_info = true;
++                        ignore_carries_install_info = true;
+                 } else if (streq(verb, "mask"))
+                         method = "MaskUnitFiles";
+                 else if (streq(verb, "unmask")) {
+@@ -5515,7 +5516,7 @@ static int enable_unit(sd_bus *bus, char **args) {
+                         r = 0;
+         }
+ 
+-        if (carries_install_info == 0)
++        if (carries_install_info == 0 && !ignore_carries_install_info)
+                 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
+                             "using systemctl.\n"
+                             "Possible reasons for having this kind of units are:\n"
diff --git a/SOURCES/0404-systemctl-core-ignore-masked-units-in-preset-all.patch b/SOURCES/0404-systemctl-core-ignore-masked-units-in-preset-all.patch
new file mode 100644
index 0000000..f3c6446
--- /dev/null
+++ b/SOURCES/0404-systemctl-core-ignore-masked-units-in-preset-all.patch
@@ -0,0 +1,148 @@
+From c9a4b1688552a23867d3d9db18620501d57d33da Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
+Date: Sat, 16 Apr 2016 19:31:53 -0400
+Subject: [PATCH] systemctl/core: ignore masked units in preset-all
+
+With any masked unit that would that would be enabled by presets, we'd get:
+
+test@rawhide $ sudo systemctl preset-all
+Failed to execute operation: Unit file is masked.
+
+test@rawhide $ sudo systemctl --root=/ preset-all
+Operation failed: Cannot send after transport endpoint shutdown
+
+Simply ignore those units:
+
+test@rawhide $ sudo systemctl preset-all
+Unit xxx.service is masked, ignoring.
+
+Cherry-picked from: 9a0a413a195a21888cf926be5595d0efc1eef0fe
+Related: #1375097
+---
+ src/core/dbus-manager.c          | 12 +++++++-----
+ src/libsystemd/sd-bus/bus-util.c | 10 ++++++++--
+ src/shared/install.c             |  4 ++++
+ src/shared/install.h             |  5 +++++
+ src/systemctl/systemctl.c        | 20 ++++++++++++++------
+ 5 files changed, 38 insertions(+), 13 deletions(-)
+
+diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
+index 8d3758a..c2067c0 100644
+--- a/src/core/dbus-manager.c
++++ b/src/core/dbus-manager.c
+@@ -1598,11 +1598,13 @@ static int reply_unit_file_changes_and_free(
+         unsigned i;
+         int r;
+ 
+-        if (n_changes > 0) {
+-                r = bus_foreach_bus(m, NULL, send_unit_files_changed, NULL);
+-                if (r < 0)
+-                        log_debug_errno(r, "Failed to send UnitFilesChanged signal: %m");
+-        }
++        for (i = 0; i < n_changes; i++)
++                if (unit_file_change_is_modification(changes[i].type)) {
++                        r = bus_foreach_bus(m, NULL, send_unit_files_changed, NULL);
++                        if (r < 0)
++                                log_debug_errno(r, "Failed to send UnitFilesChanged signal: %m");
++                        break;
++                }
+ 
+         r = sd_bus_message_new_method_return(message, &reply);
+         if (r < 0)
+diff --git a/src/libsystemd/sd-bus/bus-util.c b/src/libsystemd/sd-bus/bus-util.c
+index 9d70798..75d0370 100644
+--- a/src/libsystemd/sd-bus/bus-util.c
++++ b/src/libsystemd/sd-bus/bus-util.c
+@@ -1893,11 +1893,17 @@ int bus_deserialize_and_dump_unit_file_changes(sd_bus_message *m, bool quiet, Un
+                 if (!quiet) {
+                         if (streq(type, "symlink"))
+                                 log_info("Created symlink from %s to %s.", path, source);
+-                        else
++                        else if (streq(type, "unlink"))
+                                 log_info("Removed symlink %s.", path);
++                        else if (streq(type, "masked"))
++                                log_info("Unit %s is masked, ignoring.", path);
++                        else
++                                log_notice("Manager reported unknown change type \"%s\" for %s.", type, path);
+                 }
+ 
+-                r = unit_file_changes_add(changes, n_changes, streq(type, "symlink") ? UNIT_FILE_SYMLINK : UNIT_FILE_UNLINK, path, source);
++                r = unit_file_changes_add(changes, n_changes,
++                                          unit_file_change_type_from_string(type),
++                                          path, source);
+                 if (r < 0)
+                         return r;
+         }
+diff --git a/src/shared/install.c b/src/shared/install.c
+index ab86cd1..62da52d 100644
+--- a/src/shared/install.c
++++ b/src/shared/install.c
+@@ -2402,6 +2402,9 @@ int unit_file_preset_all(
+                                 continue;
+ 
+                         r = preset_prepare_one(scope, &plus, &minus, &paths, root_dir, mode, de->d_name);
++                        if (r == -ESHUTDOWN)
++                                r = unit_file_changes_add(changes, n_changes,
++                                                          UNIT_FILE_IS_MASKED, de->d_name, NULL);
+                         if (r < 0)
+                                 return r;
+                 }
+@@ -2535,6 +2538,7 @@ DEFINE_STRING_TABLE_LOOKUP(unit_file_state, UnitFileState);
+ static const char* const unit_file_change_type_table[_UNIT_FILE_CHANGE_TYPE_MAX] = {
+         [UNIT_FILE_SYMLINK] = "symlink",
+         [UNIT_FILE_UNLINK] = "unlink",
++        [UNIT_FILE_IS_MASKED] = "masked",
+ };
+ 
+ DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type, UnitFileChangeType);
+diff --git a/src/shared/install.h b/src/shared/install.h
+index 87a40b6..f0e3666 100644
+--- a/src/shared/install.h
++++ b/src/shared/install.h
+@@ -60,10 +60,15 @@ typedef enum UnitFilePresetMode {
+ typedef enum UnitFileChangeType {
+         UNIT_FILE_SYMLINK,
+         UNIT_FILE_UNLINK,
++        UNIT_FILE_IS_MASKED,
+         _UNIT_FILE_CHANGE_TYPE_MAX,
+         _UNIT_FILE_CHANGE_TYPE_INVALID = -1
+ } UnitFileChangeType;
+ 
++static inline bool unit_file_change_is_modification(UnitFileChangeType type) {
++        return IN_SET(type, UNIT_FILE_SYMLINK, UNIT_FILE_UNLINK);
++}
++
+ typedef struct UnitFileChange {
+         UnitFileChangeType type;
+         char *path;
+diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
+index e4b404a..a688d69 100644
+--- a/src/systemctl/systemctl.c
++++ b/src/systemctl/systemctl.c
+@@ -1944,12 +1944,20 @@ static void dump_unit_file_changes(const UnitFileChange *changes, unsigned n_cha
+ 
+         assert(changes || n_changes == 0);
+ 
+-        for (i = 0; i < n_changes; i++) {
+-                if (changes[i].type == UNIT_FILE_SYMLINK)
+-                        log_info("Created symlink from %s to %s.", changes[i].path, changes[i].source);
+-                else
+-                        log_info("Removed symlink %s.", changes[i].path);
+-        }
++        for (i = 0; i < n_changes; i++)
++                switch(changes[i].type) {
++                case UNIT_FILE_SYMLINK:
++                        log_info("Created symlink %s, pointing to %s.", changes[i].path, changes[i].source);
++                        break;
++                case UNIT_FILE_UNLINK:
++                        log_info("Removed %s.", changes[i].path);
++                        break;
++                case UNIT_FILE_IS_MASKED:
++                        log_info("Unit %s is masked, ignoring.", changes[i].path);
++                        break;
++                default:
++                        assert_not_reached("bad change type");
++                }
+ }
+ 
+ static int set_default(sd_bus *bus, char **args) {
diff --git a/SOURCES/0405-shared-install-handle-dangling-aliases-as-an-explici.patch b/SOURCES/0405-shared-install-handle-dangling-aliases-as-an-explici.patch
new file mode 100644
index 0000000..abdb752
--- /dev/null
+++ b/SOURCES/0405-shared-install-handle-dangling-aliases-as-an-explici.patch
@@ -0,0 +1,113 @@
+From 2047b2d0db643a168144b708cf58091ca47acb21 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
+Date: Wed, 4 May 2016 10:10:57 -0400
+Subject: [PATCH] shared/install: handle dangling aliases as an explicit case,
+ report nicely
+
+This fixes 'preset-all' with a unit that is a dangling symlink.
+
+$ systemctl --root=/ preset-all
+Unit syslog.service is an alias to a unit that is not present, ignoring.
+Unit auditd.service is masked, ignoring.
+Unit NetworkManager.service is masked, ignoring.
+
+Cherry-picked from: 893275df36c8c358d3c0b851ca255a6169dac138
+Resolves: #1375097
+---
+ src/libsystemd/sd-bus/bus-util.c |  2 ++
+ src/shared/install.c             | 17 +++++++++++++----
+ src/shared/install.h             |  1 +
+ src/systemctl/systemctl.c        |  3 +++
+ 4 files changed, 19 insertions(+), 4 deletions(-)
+
+diff --git a/src/libsystemd/sd-bus/bus-util.c b/src/libsystemd/sd-bus/bus-util.c
+index 75d0370..d357760 100644
+--- a/src/libsystemd/sd-bus/bus-util.c
++++ b/src/libsystemd/sd-bus/bus-util.c
+@@ -1897,6 +1897,8 @@ int bus_deserialize_and_dump_unit_file_changes(sd_bus_message *m, bool quiet, Un
+                                 log_info("Removed symlink %s.", path);
+                         else if (streq(type, "masked"))
+                                 log_info("Unit %s is masked, ignoring.", path);
++                        else if (streq(type, "dangling"))
++                                log_info("Unit %s is an alias to a unit that is not present, ignoring.", path);
+                         else
+                                 log_notice("Manager reported unknown change type \"%s\" for %s.", type, path);
+                 }
+diff --git a/src/shared/install.c b/src/shared/install.c
+index 62da52d..b0a29dd 100644
+--- a/src/shared/install.c
++++ b/src/shared/install.c
+@@ -1253,12 +1253,15 @@ static int install_info_traverse(
+                         if (r < 0)
+                                 return r;
+ 
++                        /* Try again, with the new target we found. */
+                         r = unit_file_search(c, i, paths, root_dir, flags);
+-                        if (r < 0)
+-                                return r;
++                        if (r == -ENOENT)
++                                /* Translate error code to highlight this specific case */
++                                return -ENOLINK;
+                 }
+ 
+-                /* Try again, with the new target we found. */
++                if (r < 0)
++                        return r;
+         }
+ 
+         if (ret)
+@@ -1528,7 +1531,9 @@ static int install_context_mark_for_removal(
+                         return r;
+ 
+                 r = install_info_traverse(scope, c, root_dir, paths, i, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS, NULL);
+-                if (r < 0)
++                if (r == -ENOLINK)
++                        return 0;
++                else if (r < 0)
+                         return r;
+ 
+                 if (i->type != UNIT_FILE_TYPE_REGULAR)
+@@ -2405,6 +2410,9 @@ int unit_file_preset_all(
+                         if (r == -ESHUTDOWN)
+                                 r = unit_file_changes_add(changes, n_changes,
+                                                           UNIT_FILE_IS_MASKED, de->d_name, NULL);
++                        else if (r == -ENOLINK)
++                                r = unit_file_changes_add(changes, n_changes,
++                                                          UNIT_FILE_IS_DANGLING, de->d_name, NULL);
+                         if (r < 0)
+                                 return r;
+                 }
+@@ -2539,6 +2547,7 @@ static const char* const unit_file_change_type_table[_UNIT_FILE_CHANGE_TYPE_MAX]
+         [UNIT_FILE_SYMLINK] = "symlink",
+         [UNIT_FILE_UNLINK] = "unlink",
+         [UNIT_FILE_IS_MASKED] = "masked",
++        [UNIT_FILE_IS_DANGLING] = "dangling",
+ };
+ 
+ DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type, UnitFileChangeType);
+diff --git a/src/shared/install.h b/src/shared/install.h
+index f0e3666..7e40445 100644
+--- a/src/shared/install.h
++++ b/src/shared/install.h
+@@ -61,6 +61,7 @@ typedef enum UnitFileChangeType {
+         UNIT_FILE_SYMLINK,
+         UNIT_FILE_UNLINK,
+         UNIT_FILE_IS_MASKED,
++        UNIT_FILE_IS_DANGLING,
+         _UNIT_FILE_CHANGE_TYPE_MAX,
+         _UNIT_FILE_CHANGE_TYPE_INVALID = -1
+ } UnitFileChangeType;
+diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
+index a688d69..39f0150 100644
+--- a/src/systemctl/systemctl.c
++++ b/src/systemctl/systemctl.c
+@@ -1955,6 +1955,9 @@ static void dump_unit_file_changes(const UnitFileChange *changes, unsigned n_cha
+                 case UNIT_FILE_IS_MASKED:
+                         log_info("Unit %s is masked, ignoring.", changes[i].path);
+                         break;
++                case UNIT_FILE_IS_DANGLING:
++                        log_info("Unit %s is an alias to a unit that is not present, ignoring.", changes[i].path);
++                        break;
+                 default:
+                         assert_not_reached("bad change type");
+                 }
diff --git a/SOURCES/0406-shared-install-ignore-unit-symlinks-when-doing-prese.patch b/SOURCES/0406-shared-install-ignore-unit-symlinks-when-doing-prese.patch
new file mode 100644
index 0000000..025a8ca
--- /dev/null
+++ b/SOURCES/0406-shared-install-ignore-unit-symlinks-when-doing-prese.patch
@@ -0,0 +1,75 @@
+From 412044ee341c574e5163bf2be32e5da9618f2640 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
+Date: Sat, 13 Aug 2016 01:20:29 -0400
+Subject: [PATCH] shared/install: ignore unit symlinks when doing preset-all
+
+Before, when interating over unit files during preset-all, behaviour was the
+following:
+
+- if we hit the real unit name first, presets were queried for that name, and
+  that unit was enabled or disabled accordingly,
+
+- if we hit an alias first (one of the symlinks chaining to the real unit), we
+  checked the presets using the symlink name, and then proceeded to enable or
+  disable the real unit.
+
+E.g. for systemd-networkd.service we have the alias dbus-org.freedesktop.network1.service
+(/usr/lib/systemd/system/dbus-org.freedesktop.network1.service), but the preset
+is only for the systemd-networkd.service name. The service would be enabled or
+disabled pseudorandomly depending on the order of iteration.
+
+For "preset", behaviour was analogous: preset on the alias name disabled the
+service (following the default disable policy), preset on the "real" name
+applied the presets.
+
+With the patch, for "preset" and "preset-all" we silently skip symlinks. This
+gives mostly the right behaviour, with the limitation that presets on aliases
+are ignored.  I think that presets on aliases are not that common (at least my
+preset files on Fedora don't exhibit any such usage), and should not be
+necessary, since whoever installs the preset can just refer to the real unit
+file. It would be possible to overcome this limitation by gathering a list of
+names of a unit first, and then checking whether *any* of the names matches the
+presets list. That would require a significant redesign of the code, and be
+a lot slower (since we would have to fully read all unit directories to preset
+one unit) to so I'm not doing that for now.
+
+With this patch, two properties are satisfied:
+- preset-all and preset are idempotent, and the second and subsequent invocations
+  do not produce any changes,
+- preset-all and preset for a specific name produce the same state for that unit.
+
+Fixes #3616.
+
+Cherry-picked from: 11e11fd57a837ea1cb142009c3048882392f3ed3
+Related: #1375097
+---
+ src/shared/install.c | 12 ++++++++++--
+ 1 file changed, 10 insertions(+), 2 deletions(-)
+
+diff --git a/src/shared/install.c b/src/shared/install.c
+index b0a29dd..f01a212 100644
+--- a/src/shared/install.c
++++ b/src/shared/install.c
+@@ -2270,12 +2270,20 @@ static int preset_prepare_one(
+                 const char *name) {
+ 
+         InstallInfo *i;
++        _cleanup_(install_context_done) InstallContext tmp = {};
+         int r;
+ 
+-        if (install_info_find(plus, name) ||
+-            install_info_find(minus, name))
++        if (install_info_find(plus, name) || install_info_find(minus, name))
+                 return 0;
+ 
++        r = install_info_discover(scope, &tmp, root_dir, paths, name, SEARCH_FOLLOW_CONFIG_SYMLINKS, &i);
++        if (r < 0)
++                return r;
++        if (!streq(name, i->name)) {
++                log_debug("Skipping %s because is an alias for %s", name, i->name);
++                return 0;
++        }
++
+         r = unit_file_query_preset(scope, root_dir, name);
+         if (r < 0)
+                 return r;
diff --git a/SOURCES/0407-40-redhat.rules-don-t-hoplug-memory-on-s390x.patch b/SOURCES/0407-40-redhat.rules-don-t-hoplug-memory-on-s390x.patch
new file mode 100644
index 0000000..a9e060c
--- /dev/null
+++ b/SOURCES/0407-40-redhat.rules-don-t-hoplug-memory-on-s390x.patch
@@ -0,0 +1,23 @@
+From 195083a33b4204d513787e7f4b6c63f19a0fe1c7 Mon Sep 17 00:00:00 2001
+From: Lukas Nykryn <lnykryn@redhat.com>
+Date: Tue, 13 Sep 2016 13:18:38 +0200
+Subject: [PATCH] 40-redhat.rules: don't hoplug memory on s390x
+
+Resolves: #1370161
+---
+ rules/40-redhat.rules | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/rules/40-redhat.rules b/rules/40-redhat.rules
+index 3335fe5..4c56950 100644
+--- a/rules/40-redhat.rules
++++ b/rules/40-redhat.rules
+@@ -4,7 +4,7 @@
+ SUBSYSTEM=="cpu", ACTION=="add", TEST=="online", ATTR{online}=="0", ATTR{online}="1"
+ 
+ # Memory hotadd request
+-SUBSYSTEM=="memory", ACTION=="add", ATTR{state}=="offline", ATTR{state}="online"
++SUBSYSTEM=="memory", ACTION=="add", PROGRAM="/usr/bin/systemd-detect-virt", RESULT!="zvm", ATTR{state}=="offline", ATTR{state}="online"
+ 
+ # reload sysctl.conf / sysctl.conf.d settings when the bridge module is loaded
+ ACTION=="add", SUBSYSTEM=="module", KERNEL=="bridge", RUN+="/usr/lib/systemd/systemd-sysctl --prefix=/proc/sys/net/bridge"
diff --git a/SOURCES/org.freedesktop.hostname1.policy b/SOURCES/org.freedesktop.hostname1.policy
new file mode 100644
index 0000000..0014156
--- /dev/null
+++ b/SOURCES/org.freedesktop.hostname1.policy
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE policyconfig PUBLIC "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
+        "http://www.freedesktop.org/standards/PolicyKit/1/policyconfig.dtd">
+<policyconfig>
+
+        <vendor>The systemd Project</vendor>
+        <vendor_url>http://www.freedesktop.org/wiki/Software/systemd</vendor_url>
+
+        <action id="org.freedesktop.hostname1.set-hostname">
+                <description>Set host name</description>
+                <description xml:lang="de">Rechnername festlegen</description>
+                <description xml:lang="el">Ορισμός ονόματος οικοδεσπότη</description>
+                <description xml:lang="fr">Définir le nom d'hôte</description>
+                <description xml:lang="hu">Gépnév beállítása</description>
+                <description xml:lang="it">Configura il nome host</description>
+                <description xml:lang="pl">Ustawienie nazwy komputera</description>
+                <description xml:lang="pt_BR">Definir nome de máquina</description>
+                <description xml:lang="ru">Настроить имя компьютера</description>
+                <description xml:lang="sv">Ange värdnamn</description>
+                <description xml:lang="uk">Встановити назву вузла</description>
+                <message>Authentication is required to set the local host name.</message>
+                <message xml:lang="de">Legitimierung ist zum Festlegen des lokalen Rechnernamens notwendig</message>
+                <message xml:lang="el">Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη.</message>
+                <message xml:lang="fr">Authentification requise pour définir le nom d'hôte local.</message>
+                <message xml:lang="hu">Hitelesítés szükséges a helyi gépnév beállításához.</message>
+                <message xml:lang="it">Autenticazione richiesta per configurare il nome host locale.</message>
+                <message xml:lang="pl">Wymagane jest uwierzytelnienie, aby ustawić nazwę lokalnego komputera.</message>
+                <message xml:lang="pt_BR">É necessária autenticação para definir nome de máquina local.</message>
+                <message xml:lang="ru">Чтобы настроить имя компьютера, необходимо пройти аутентификацию.</message>
+                <message xml:lang="sv">Autentisering krävs för att ange lokalt värdnamn.</message>
+                <message xml:lang="uk">Засвідчення потрібне, щоб встановити назву локального вузла.</message>
+                <defaults>
+                        <allow_any>auth_admin_keep</allow_any>
+                        <allow_inactive>auth_admin_keep</allow_inactive>
+                        <allow_active>auth_admin_keep</allow_active>
+                </defaults>
+        </action>
+
+        <action id="org.freedesktop.hostname1.set-static-hostname">
+                <description>Set static host name</description>
+                <description xml:lang="de">Statischen Rechnernamen festlegen</description>
+                <description xml:lang="el">Ορισμός στατικού ονόματος οικοδεσπότη</description>
+                <description xml:lang="fr">Définir le nom d'hôte statique</description>
+                <description xml:lang="hu">Statikus gépnév beállítása</description>
+                <description xml:lang="it">Configura il nome host statico</description>
+                <description xml:lang="pl">Ustawienie statycznej nazwy komputera</description>
+                <description xml:lang="pt_BR">Definir nome estático de máquina</description>
+                <description xml:lang="ru">Настроить статическое имя компьютера</description>
+                <description xml:lang="sv">Ange statiskt värdnamn</description>
+                <description xml:lang="uk">Встановити статичну назву вузла</description>
+                <message>Authentication is required to set the statically configured local host name, as well as the pretty host name.</message>
+                <message xml:lang="de">Authentifizierung ist erforderlich, um den statisch geänderten, lokalen Rechnernamen, sowie den beschönigten Rechnernamen festzulegen.</message>
+                <message xml:lang="el">Απαιτείται πιστοποίηση για να ορίσετε το στατικά ρυθμισμένο όνομα τοπικού οικοδεσπότη, καθώς και το pretty όνομα οικοδεσπότη.</message>
+                <message xml:lang="fr">Authentification requise pour définir le nom d'hôte local de manière statique, tout comme le nom d'hôte familier.</message>
+                <message xml:lang="hu">Hitelesítés szükséges a statikusan megadott helyi gépnév, valamint a szép gépnév beállításához.</message>
+                <message xml:lang="it">Autenticazione richiesta per configurare staticamente il nome host locale e il nome host descrittivo.</message>
+                <message xml:lang="pl">Wymagane jest uwierzytelnienie, aby ustawić statycznie skonfigurowaną nazwę lokalnego komputera, a także jego ładną nazwę.</message>
+                <message xml:lang="pt_BR">É necessária autenticação para definir o nome de máquina local configurado estaticamente, assim como o nome apresentável de máquina.</message>
+                <message xml:lang="ru">Чтобы настроить статическое имя компьютера, а также его «красивое» имя, необходимо пройти аутентификацию.</message>
+                <message xml:lang="sv">Autentisering krävs för att ange det statiskt konfigurerade lokala värdnamnet såväl som det stiliga värdnamnet.</message>
+                <message xml:lang="uk">Засвідчення потрібне, щоб вказати статично налаштовану назву локального вузла, так само й форматовану.</message>
+                <defaults>
+                        <allow_any>auth_admin_keep</allow_any>
+                        <allow_inactive>auth_admin_keep</allow_inactive>
+                        <allow_active>auth_admin_keep</allow_active>
+                </defaults>
+                <annotate key="org.freedesktop.policykit.imply">org.freedesktop.hostname1.set-hostname org.freedesktop.hostname1.set-machine-info</annotate>
+        </action>
+
+        <action id="org.freedesktop.hostname1.set-machine-info">
+                <description>Set machine information</description>
+                <description xml:lang="de">Maschinen-Information festlegen</description>
+                <description xml:lang="el">Ορισμός πληροφοριών μηχανής</description>
+                <description xml:lang="fr">Définir les informations sur la machine</description>
+                <description xml:lang="hu">Gépinformációk beállítása</description>
+                <description xml:lang="it">Configura le informazioni sulla macchina</description>
+                <description xml:lang="pl">Ustawienie informacji o komputerze</description>
+                <description xml:lang="pt_BR">Definir informações da máquina</description>
+                <description xml:lang="ru">Настроить информацию о компьютере</description>
+                <description xml:lang="sv">Ange datorinformation</description>
+                <description xml:lang="uk">Встановити інформацію про машину</description>
+                <message>Authentication is required to set local machine information.</message>
+                <message xml:lang="de">Legitimierung ist zum Festlegen der lokalen Maschinen-Information erforderlich.</message>
+                <message xml:lang="el">Απαιτείται πιστοποίηση για να ορίσετε πληροφορίες τοπικής μηχανής.</message>
+                <message xml:lang="fr">Authentification requise pour définir les informations sur la machine locale.</message>
+                <message xml:lang="hu">Hitelesítés szükséges a helyi gép információinak beállításához.</message>
+                <message xml:lang="it">Autenticazione richiesta per configurare le informazioni sulla macchina locale.</message>
+                <message xml:lang="pl">Wymagane jest uwierzytelnienie, aby ustawić informacje o lokalnym komputerze.</message>
+                <message xml:lang="pt_BR">É necessária autenticação para definir informações de máquina local.</message>
+                <message xml:lang="ru">Чтобы настроить информацию о компьютере, необходимо пройти аутентификацию.</message>
+                <message xml:lang="sv">Autentisering krävs för att ange lokal datorinformation.</message>
+                <message xml:lang="uk">Засвідчення потрібно, щоб вказати локальну інформацію про машини.</message>
+                <defaults>
+                        <allow_any>auth_admin_keep</allow_any>
+                        <allow_inactive>auth_admin_keep</allow_inactive>
+                        <allow_active>auth_admin_keep</allow_active>
+                </defaults>
+        </action>
+
+</policyconfig>
\ No newline at end of file
diff --git a/SOURCES/org.freedesktop.import1.policy b/SOURCES/org.freedesktop.import1.policy
new file mode 100644
index 0000000..e05e4bb
--- /dev/null
+++ b/SOURCES/org.freedesktop.import1.policy
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE policyconfig PUBLIC "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
+        "http://www.freedesktop.org/standards/PolicyKit/1/policyconfig.dtd">
+<policyconfig>
+
+        <vendor>The systemd Project</vendor>
+        <vendor_url>http://www.freedesktop.org/wiki/Software/systemd</vendor_url>
+
+        <action id="org.freedesktop.import1.pull">
+                <description>Download a VM or container image</description>
+                <description xml:lang="de">Abbild einer VM oder eines Containers herunterladen</description>
+                <description xml:lang="fr">Télécharger une image de machine virtuelle (VM) ou de conteneur</description>
+                <description xml:lang="pl">Pobranie obrazu maszyny wirtualnej lub kontenera</description>
+                <description xml:lang="ru">Загрузить образ виртуальной машины или контейнера</description>
+                <message>Authentication is required to download a VM or container image</message>
+                <message xml:lang="de">Legitimierung ist zum Herunterladen eines VM- oder Containerabbilds erforderlich</message>
+                <message xml:lang="fr">Authentification requise pour télécharger une image de machine virtuelle (VM) ou de conteneur.</message>
+                <message xml:lang="pl">Wymagane jest uwierzytelnienie, aby pobrać obraz maszyny wirtualnej lub kontenera</message>
+                <message xml:lang="ru">Чтобы загрузить образ виртуальной машины или контейнера, необходимо пройти аутентификацию.</message>
+                <defaults>
+                        <allow_any>auth_admin</allow_any>
+                        <allow_inactive>auth_admin</allow_inactive>
+                        <allow_active>auth_admin_keep</allow_active>
+                </defaults>
+        </action>
+
+</policyconfig>
\ No newline at end of file
diff --git a/SOURCES/org.freedesktop.locale1.policy b/SOURCES/org.freedesktop.locale1.policy
new file mode 100644
index 0000000..5f9b571
--- /dev/null
+++ b/SOURCES/org.freedesktop.locale1.policy
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE policyconfig PUBLIC "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
+        "http://www.freedesktop.org/standards/PolicyKit/1/policyconfig.dtd">
+<policyconfig>
+
+        <vendor>The systemd Project</vendor>
+        <vendor_url>http://www.freedesktop.org/wiki/Software/systemd</vendor_url>
+
+        <action id="org.freedesktop.locale1.set-locale">
+                <description>Set system locale</description>
+                <description xml:lang="de">Die lokale Sprachumgebung festlegen</description>
+                <description xml:lang="el">Ορισμός τοπικών ρυθμίσεων συστήματος</description>
+                <description xml:lang="fr">Définir la langue du système</description>
+                <description xml:lang="hu">Területi beállítás megadása</description>
+                <description xml:lang="it">Configura le impostazioni regionali di sistema</description>
+                <description xml:lang="pl">Ustawienie lokalizacji systemu</description>
+                <description xml:lang="pt_BR">Definir configurações regionais do sistema</description>
+                <description xml:lang="ru">Настроить системную локаль</description>
+                <description xml:lang="sv">Ange systemlokal</description>
+                <description xml:lang="uk">Вказати системну локаль</description>
+                <message>Authentication is required to set the system locale.</message>
+                <message xml:lang="de">Legitimierung ist zum Festlegen der systemweiten Spracheinstellungen erforderlich.</message>
+                <message xml:lang="el">Απαιτείται πιστοποίηση για να ορίσετε τις τοπικές ρυθμίσεις του συστήματος.</message>
+                <message xml:lang="fr">Authentification requise pour définir la langue du système.</message>
+                <message xml:lang="hu">Hitelesítés szükséges a rendszer területi beállításainak megadásához.</message>
+                <message xml:lang="it">Autenticazione richiesta per configurare le impostazioni regionali di sistema.</message>
+                <message xml:lang="pl">Wymagane jest uwierzytelnienie, aby ustawić lokalizację systemu.</message>
+                <message xml:lang="pt_BR">É necessária autenticação para definir as configurações regionais do sistema.</message>
+                <message xml:lang="ru">Чтобы настроить системную локаль, необходимо пройти аутентификацию.</message>
+                <message xml:lang="sv">Autentisering krävs för att ange systemlokal.</message>
+                <message xml:lang="uk">Засвідчення потрібно, щоб встановити системну локаль.</message>
+                <defaults>
+                        <allow_any>auth_admin_keep</allow_any>
+                        <allow_inactive>auth_admin_keep</allow_inactive>
+                        <allow_active>auth_admin_keep</allow_active>
+                </defaults>
+                <annotate key="org.freedesktop.policykit.imply">org.freedesktop.locale1.set-keyboard</annotate>
+        </action>
+
+        <action id="org.freedesktop.locale1.set-keyboard">
+                <description>Set system keyboard settings</description>
+                <description xml:lang="de">Tastatureinstellungen des Systems festlegen</description>
+                <description xml:lang="el">Ορισμός ρυθμίσεων πληκτρολογίου συστήματος</description>
+                <description xml:lang="fr">Définir les paramètres de clavier du système</description>
+                <description xml:lang="hu">Rendszer billentyűzetbeállítások megadása</description>
+                <description xml:lang="it">Configura la tastiera di sistema</description>
+                <description xml:lang="pl">Ustawienie klawiatury systemu</description>
+                <description xml:lang="pt_BR">Definir configurações de teclado do sistema</description>
+                <description xml:lang="ru">Настроить параметры клавиатуры</description>
+                <description xml:lang="sv">Ange systeminställningar för tangentbord</description>
+                <description xml:lang="uk">Вказати налаштування системної клавіатури</description>
+                <message>Authentication is required to set the system keyboard settings.</message>
+                <message xml:lang="de">Legitimierung ist zum Festlegen der Tastatureinstellungen des Systems erforderlich.</message>
+                <message xml:lang="el">Απαιτείται πιστοποίηση για να ορίσετε τις ρυθμίσεις πληκτρολογίου του συστήματος.</message>
+                <message xml:lang="fr">Authentification requise pour définir les paramètres de clavier du système.</message>
+                <message xml:lang="hu">Hitelesítés szükséges a rendszer billentyűzetbeállításainak megadásához.</message>
+                <message xml:lang="it">Autenticazione richiesta per configurare la tastiera di sistema.</message>
+                <message xml:lang="pl">Wymagane jest uwierzytelnienie, aby ustawić klawiaturę systemu.</message>
+                <message xml:lang="pt_BR">É necessária autenticação para definir as configurações de teclado do sistema.</message>
+                <message xml:lang="ru">Чтобы настроить параметры клавиатуры, необходимо пройти аутентификацию.</message>
+                <message xml:lang="sv">Autentisering krävs för att ange systeminställningar för tangentbord.</message>
+                <message xml:lang="uk">Засвідчення потрібно, щоб вказати налаштування системної клавіатури.</message>
+                <defaults>
+                        <allow_any>auth_admin_keep</allow_any>
+                        <allow_inactive>auth_admin_keep</allow_inactive>
+                        <allow_active>auth_admin_keep</allow_active>
+                </defaults>
+        </action>
+
+</policyconfig>
\ No newline at end of file
diff --git a/SOURCES/org.freedesktop.login1.policy b/SOURCES/org.freedesktop.login1.policy
new file mode 100644
index 0000000..0a19273
--- /dev/null
+++ b/SOURCES/org.freedesktop.login1.policy
@@ -0,0 +1,743 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE policyconfig PUBLIC "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
+        "http://www.freedesktop.org/standards/PolicyKit/1/policyconfig.dtd">
+<policyconfig>
+
+        <vendor>The systemd Project</vendor>
+        <vendor_url>http://www.freedesktop.org/wiki/Software/systemd</vendor_url>
+
+        <action id="org.freedesktop.login1.inhibit-block-shutdown">
+                <description>Allow applications to inhibit system shutdown</description>
+                <description xml:lang="de">Anwendungen dürfen das Herunterfahren des Systems unterbinden</description>
+                <description xml:lang="el">Να επιτρέπεται στις εφαρμογές να αποτρέπουν τον τερματισμό του συστήματος</description>
+                <description xml:lang="fr">Permet aux applications d'empêcher l'arrêt du système</description>
+                <description xml:lang="hu">Alkalmazások meggátolhatják a rendszer leállítását</description>
+                <description xml:lang="it">Consenti alle applicazioni di inibire lo spegnimento del sistema</description>
+                <description xml:lang="pl">Zezwolenie programom na wstrzymywanie wyłączenia systemu</description>
+                <description xml:lang="pt_BR">Permitir que aplicativos inibam o desligamento do sistema</description>
+                <description xml:lang="ru">Разрешить приложениям устанавливать блокировку на выключение системы</description>
+                <description xml:lang="sv">Tillåt program att hindra systemavstängning</description>
+                <description xml:lang="uk">Дозволити програмам перешкоджати вимкненню системи</description>
+                <message>Authentication is required for an application to inhibit system shutdown.</message>
+                <message xml:lang="de">Legitimierung ist notwendig, um Anwendungen das Herunterfahren des Systems zu erlauben.</message>
+                <message xml:lang="el">Απαιτείται πιστοποίηση για να επιτρέπεται σε μια εφαρμογή να αποτρέψει τον τερματισμό του συστήματος.</message>
+                <message xml:lang="fr">Authentification requise pour permettre à une application d'empêcher l'arrêt du système.</message>
+                <message xml:lang="hu">Hitelesítés szükséges egy alkalmazás számára a rendszerleállítás meggátlásához.</message>
+                <message xml:lang="it">Autenticazione richiesta per un'applicazione per inibire lo spegnimento del sistema.</message>
+                <message xml:lang="pl">Program wymaga uwierzytelnienia, aby wstrzymać wyłączenie systemu.</message>
+                <message xml:lang="pt_BR">É necessária autenticação para que um aplicativo iniba o desligamento do sistema.</message>
+                <message xml:lang="ru">Чтобы разрешить приложениям устанавливать блокировку на выключение системы, необходимо пройти аутентификацию.</message>
+                <message xml:lang="sv">Autentisering krävs för att tillåta ett program att hindra systemavstängning.</message>
+                <message xml:lang="uk">Засвідчення потрібно, щоб дозволити програмам перешкоджати вимкненню системи.</message>
+                <defaults>
+                        <allow_any>no</allow_any>
+                        <allow_inactive>yes</allow_inactive>
+                        <allow_active>yes</allow_active>
+                </defaults>
+                <annotate key="org.freedesktop.policykit.imply">org.freedesktop.login1.inhibit-delay-shutdown org.freedesktop.login1.inhibit-block-sleep org.freedesktop.login1.inhibit-delay-sleep org.freedesktop.login1.inhibit-block-idle</annotate>
+        </action>
+
+        <action id="org.freedesktop.login1.inhibit-delay-shutdown">
+                <description>Allow applications to delay system shutdown</description>
+                <description xml:lang="de">Anwendungen dürfen das Herunterfahren des Systems verzögern</description>
+                <description xml:lang="el">Να επιτρέπεται στις εφαρμογές να καθυστερούν τον τερματισμό του συστήματος</description>
+                <description xml:lang="fr">Permet aux applications de retarder l'arrêt du système</description>
+                <description xml:lang="hu">Alkalmazások késleltethetik a rendszer leállítását</description>
+                <description xml:lang="it">Consenti alle applicazioni di ritardare lo spegnimento del sistema</description>
+                <description xml:lang="pl">Zezwolenie programom na opóźnienie wyłączenia systemu</description>
+                <description xml:lang="pt_BR">Permitir que aplicativos atrasem o desligamento do sistema</description>
+                <description xml:lang="ru">Разрешить приложениям устанавливать задержку на выключение системы</description>
+                <description xml:lang="sv">Tillåt program att fördröja systemavstängning</description>
+                <description xml:lang="uk">Дозволити програмам затримувати вимкнення системи</description>
+                <message>Authentication is required for an application to delay system shutdown.</message>
+                <message xml:lang="de">Legitimierung ist notwendig, um Anwendungen das Verzögern des Herunterfahren des Systems zu erlauben.</message>
+                <message xml:lang="el">Απαιτείται πιστοποίηση για να επιτρέπεται σε μια εφαρμογή να καθυστερήσει τον τερματισμό του συστήματος.</message>
+                <message xml:lang="fr">Authentification requise pour permettre à une application de retarder l'arrêt du système.</message>
+                <message xml:lang="hu">Hitelesítés szükséges egy alkalmazás számára a rendszerleállítás késleltetéséhez.</message>
+                <message xml:lang="it">Autenticazione richiesta per un'applicazione per ritardare lo spegnimento del sistema.</message>
+                <message xml:lang="pl">Program wymaga uwierzytelnienia, aby opóźnić wyłączenie systemu.</message>
+                <message xml:lang="pt_BR">É necessária autenticação para que um aplicativo atrase o desligamento do sistema.</message>
+                <message xml:lang="ru">Чтобы разрешить приложениям устанавливать задержку на выключение системы, необходимо пройти аутентификацию.</message>
+                <message xml:lang="sv">Autentisering krävs för att tillåta ett program att fördröja systemavstängning.</message>
+                <message xml:lang="uk">Засвідчення потрібно, щоб дозволити програмам затримувати вимкнення системи.</message>
+                <defaults>
+                        <allow_any>yes</allow_any>
+                        <allow_inactive>yes</allow_inactive>
+                        <allow_active>yes</allow_active>
+                </defaults>
+                <annotate key="org.freedesktop.policykit.imply">org.freedesktop.login1.inhibit-delay-sleep</annotate>
+        </action>
+
+        <action id="org.freedesktop.login1.inhibit-block-sleep">
+                <description>Allow applications to inhibit system sleep</description>
+                <description xml:lang="de">Anwendungen dürfen den Bereitschaftsmodus unterbinden</description>
+                <description xml:lang="el">Να επιτρέπεται στις εφαρμογές να αποτρέπουν την ύπνωση του συστήματος</description>
+                <description xml:lang="fr">Permet aux applications d'empêcher la mise en veille du système</description>
+                <description xml:lang="hu">Alkalmazások meggátolhatják a rendszer altatását</description>
+                <description xml:lang="it">Consenti alle applicazioni di inibire il sistema in pausa</description>
+                <description xml:lang="pl">Zezwolenie programom na wstrzymanie uśpienia systemu</description>
+                <description xml:lang="pt_BR">Permitir que aplicativos inibam a suspensão do sistema</description>
+                <description xml:lang="ru">Разрешить приложениям устанавливать блокировку на засыпание системы</description>
+                <description xml:lang="sv">Tillåt program att hindra system att försättas i viloläge</description>
+                <description xml:lang="uk">Дозволити програмам перешкоджати засинанню системи</description>
+                <message>Authentication is required for an application to inhibit system sleep.</message>
+                <message xml:lang="de">Legitimierung ist erforderlich, um Anwendungen das Unterbinden des Bereitschaftsmodus zu erlauben.</message>
+                <message xml:lang="el">Απαιτείται πιστοποίηση για να επιτρέπεται σε μια εφαρμογή να αποτρέψει την ύπνωση του συστήματος.</message>
+                <message xml:lang="fr">Authentification requise pour permettre à une application d'empêcher la mise en veille du système.</message>
+                <message xml:lang="hu">Hitelesítés szükséges egy alkalmazás számára a rendszeraltatás meggátlásához.</message>
+                <message xml:lang="it">Autenticazione richiesta per un'applicazione per inibire il sistema in pausa.</message>
+                <message xml:lang="pl">Program wymaga uwierzytelnienia, aby wstrzymać uśpienie systemu.</message>
+                <message xml:lang="pt_BR">É necessária autenticação para que um aplicativo iniba a suspensão do sistema.</message>
+                <message xml:lang="ru">Чтобы разрешить приложениям устанавливать блокировку на засыпание системы, необходимо пройти аутентификацию.</message>
+                <message xml:lang="sv">Autentisering krävs för att tillåta ett program att hindra ett system att försättas i viloläge.</message>
+                <message xml:lang="uk">Засвідчення потрібно, щоб дозволити програмам перешкоджати засинанню системи.</message>
+                <defaults>
+                        <allow_any>no</allow_any>
+                        <allow_inactive>yes</allow_inactive>
+                        <allow_active>yes</allow_active>
+                </defaults>
+                <annotate key="org.freedesktop.policykit.imply">org.freedesktop.login1.inhibit-delay-sleep org.freedesktop.login1.inhibit-block-idle</annotate>
+        </action>
+
+        <action id="org.freedesktop.login1.inhibit-delay-sleep">
+                <description>Allow applications to delay system sleep</description>
+                <description xml:lang="de">Anwendungen dürfen den Bereitschaftsmodus verzögern</description>
+                <description xml:lang="el">Να επιτρέπεται στις εφαρμογές να καθυστερούν την ύπνωση του συστήματος</description>
+                <description xml:lang="fr">Permet aux applications de retarder la mise en veille du système</description>
+                <description xml:lang="hu">Alkalmazások késleltethetik a rendszer altatását</description>
+                <description xml:lang="it">Consenti alle applicazioni di ritardare il sistema in pausa</description>
+                <description xml:lang="pl">Zezwolenie programom na opóźnienie uśpienia systemu</description>
+                <description xml:lang="pt_BR">Permite que aplicativos atrasem a suspensão do sistema</description>
+                <description xml:lang="ru">Разрешить приложениям устанавливать задержку на засыпание системы</description>
+                <description xml:lang="sv">Tillåt program att fördröja att system försätts i viloläge</description>
+                <description xml:lang="uk">Дозволити програмами затримувати засинання системи</description>
+                <message>Authentication is required for an application to delay system sleep.</message>
+                <message xml:lang="de">Legitimierung ist erforderlich, um Anwendungen das Verzögern des Bereitschaftsmodus zu erlauben.</message>
+                <message xml:lang="el">Απαιτείται πιστοποίηση για να επιτρέπεται σε μια εφαρμογή να καθυστερήσει την ύπνωση του συστήματος.</message>
+                <message xml:lang="fr">Authentification requise pour permettre à une application de retarder la mise en veille du système.</message>
+                <message xml:lang="hu">Hitelesítés szükséges egy alkalmazás számára a rendszeraltatás késleltetéséhez.</message>
+                <message xml:lang="it">Autenticazione richiesta per un'applicazione per ritardare il sistema in pausa.</message>
+                <message xml:lang="pl">Program wymaga uwierzytelnienia, aby opóźnić uśpienie systemu.</message>
+                <message xml:lang="pt_BR">É necessária autenticação para que um aplicativo atrase a suspensão do sistema.</message>
+                <message xml:lang="ru">Чтобы разрешить приложениям устанавливать задержку на засыпание системы, необходимо пройти аутентификацию.</message>
+                <message xml:lang="sv">Autentisering krävs för att tillåta ett program att fördröja ett system att försättas i viloläge.</message>
+                <message xml:lang="uk">Засвідчення потрібно, щоб дозволити програмам затримувати засинання системи.</message>
+                <defaults>
+                        <allow_any>yes</allow_any>
+                        <allow_inactive>yes</allow_inactive>
+                        <allow_active>yes</allow_active>
+                </defaults>
+        </action>
+
+        <action id="org.freedesktop.login1.inhibit-block-idle">
+                <description>Allow applications to inhibit automatic system suspend</description>
+                <description xml:lang="de">Anwendungen dürfen den automatischen Bereitschaftsmodus unterbinden</description>
+                <description xml:lang="el">Να επιτρέπεται στις εφαρμογές να αποτρέπουν την αυτόματη αναστολή του συστήματος</description>
+                <description xml:lang="fr">Permet aux applications d'empêcher l'hibernation automatique du système</description>
+                <description xml:lang="hu">Alkalmazások meggátolhatják a rendszer automatikus felfüggesztését</description>
+                <description xml:lang="it">Consenti alle applicazioni di inibire la sospesione automatica del sistema</description>
+                <description xml:lang="pl">Zezwolenie programom na wstrzymanie automatycznego uśpienia systemu</description>
+                <description xml:lang="pt_BR">Permitir que aplicativos inibam a suspensão automática do sistema</description>
+                <description xml:lang="ru">Разрешить приложениям устанавливать блокировку на автоматический переход системы в ждущий режим</description>
+                <description xml:lang="sv">Tillåt program att hindra automatiskt systemvänteläge</description>
+                <description xml:lang="uk">Дозволити програмам перешкоджати автоматичному призупиненню системи</description>
+                <message>Authentication is required for an application to inhibit automatic system suspend.</message>
+                <message xml:lang="de">Legitimierung ist notwendig, um Anwendungen das Unterbinden des automatischen Bereitschaftsmodus zu erlauben.</message>
+                <message xml:lang="el">Απαιτείται πιστοποίηση για να επιτρέπεται σε μια εφαρμογή να αποτρέψει την αυτόματη αναστολή του συστήματος.</message>
+                <message xml:lang="fr">Authentification requise pour permettre à une application d'empêcher l'hibernation automatique du système.</message>
+                <message xml:lang="hu">Hitelesítés szükséges egy alkalmazás számára az automatikus rendszerfelfüggesztés meggátlásához.</message>
+                <message xml:lang="it">Autenticazione richiesta per un'applicazione per inibire la sospensione automatica del sistema.</message>
+                <message xml:lang="pl">Program wymaga uwierzytelnienia, aby wstrzymać automatyczne uśpienie systemu.</message>
+                <message xml:lang="pt_BR">É necessária autenticação para que um aplicativo iniba a suspensão automática do sistema.</message>
+                <message xml:lang="ru">Чтобы разрешить приложениям устанавливать блокировку на автоматический переход системы в ждущий режим, необходимо пройти аутентификацию.</message>
+                <message xml:lang="sv">Autentisering krävs för att tillåta ett program att hindra automatiskt systemvänteläge.</message>
+                <message xml:lang="uk">Засвідчення потрібно, щоб дозволити програмам перешкоджати автоматичному призупиненню системи.</message>
+                <defaults>
+                        <allow_any>yes</allow_any>
+                        <allow_inactive>yes</allow_inactive>
+                        <allow_active>yes</allow_active>
+                </defaults>
+        </action>
+
+        <action id="org.freedesktop.login1.inhibit-handle-power-key">
+                <description>Allow applications to inhibit system handling of the power key</description>
+                <description xml:lang="de">Anwendungen dürfen das Auswerten des Ein-/Ausschaltknopfs des Systems unterbinden</description>
+                <description xml:lang="el">Να επιτρέπεται στις εφαρμογές να αποτρέπουν τη διαχείριση του πλήκτρου ενεργοποίησης του συστήματος</description>
+                <description xml:lang="fr">Permet aux applications d'empêcher la gestion du bouton d'alimentation  du système</description>
+                <description xml:lang="hu">Alkalmazások meggátolhatják a bekapcsoló gomb rendszer általi kezelését</description>
+                <description xml:lang="it">Consenti alle applicazioni di inibire la gestione di sistema del tasto di accensione</description>
+                <description xml:lang="pl">Zezwolenie programom na wstrzymanie obsługi klawisza zasilania przez system</description>
+                <description xml:lang="pt_BR">Permitir que aplicativos inibam o sistema de gerenciar o botão de energia</description>
+                <description xml:lang="ru">Разрешить приложениям устанавливать блокировку обработки нажатий на кнопку выключения</description>
+                <description xml:lang="sv">Tillåt program att hindra systemhantering av strömknappen</description>
+                <description xml:lang="uk">Дозволити програмам перешкоджати обробленню системою клавіші живлення</description>
+                <message>Authentication is required for an application to inhibit system handling of the power key.</message>
+                <message xml:lang="de">Legitmierung ist erforderlich, um Anwendungen das Unterbinden der Auswertung der Ein-/Ausschaltknopfs des Systems zu erlauben.</message>
+                <message xml:lang="el">Απαιτείται πιστοποίηση για να επιτρέπεται σε μια εφαρμογή να αποτρέψει την διαχείριση του πλήκτρου ενεργοποίησης του συστήματος.</message>
+                <message xml:lang="fr">Authentification requise pour permettre à une application d'empêcher la gestion du bouton d'alimentation du système.</message>
+                <message xml:lang="hu">Hitelesítés szükséges egy alkalmazás számára a bekapcsoló gomb rendszer általi kezelésének meggátlásához.</message>
+                <message xml:lang="it">Autenticazione richiesta per un'applicazione per inibire la gestione di sistema del tasto di accensione.</message>
+                <message xml:lang="pl">Program wymaga uwierzytelnienia, aby wstrzymać obsługę klawisza zasilania przez system.</message>
+                <message xml:lang="pt_BR">É necessária autenticação para que um aplicativo iniba a manipulação do sistema sobre a chave de ligar/desligar.</message>
+                <message xml:lang="ru">Чтобы разрешить приложениям устанавливать блокировку обработки нажатий на кнопку выключения, необходимо пройти аутентификацию.</message>
+                <message xml:lang="sv">Autentisering krävs för att tillåta ett program att hindra systemhantering av strömknappen.</message>
+                <message xml:lang="uk">Засвідчення потрібно, щоб дозволити програмам перешкоджати обробленню системою клавіші живлення.</message>
+                <defaults>
+                        <allow_any>no</allow_any>
+                        <allow_inactive>yes</allow_inactive>
+                        <allow_active>yes</allow_active>
+                </defaults>
+                <annotate key="org.freedesktop.policykit.imply">org.freedesktop.login1.inhibit-handle-suspend-key org.freedesktop.login1.inhibit-handle-hibernate-key org.freedesktop.login1.inhibit-handle-lid-switch</annotate>
+        </action>
+
+        <action id="org.freedesktop.login1.inhibit-handle-suspend-key">
+                <description>Allow applications to inhibit system handling of the suspend key</description>
+                <description xml:lang="de">Anwendungen dürfen das Auswerten des Bereitschaftsknopfs des Systems unterbinden</description>
+                <description xml:lang="el">Να επιτρέπεται στις εφαρμογές να αποτρέπουν τη διαχείριση του πλήκτρου αναστολής του συστήματος.</description>
+                <description xml:lang="fr">Permet aux applications d'empêcher la gestion du bouton de mise en veille du système</description>
+                <description xml:lang="hu">Alkalmazások meggátolhatják a felfüggesztés gomb rendszer általi kezelését</description>
+                <description xml:lang="it">Consenti alle applicazioni di inibire la gestione di sistema del tasto di sospensione</description>
+                <description xml:lang="pl">Zezwolenie programom na wstrzymanie obsługi klawisza uśpienia przez system</description>
+                <description xml:lang="pt_BR">Permitir que aplicativos inibam o sistema de gerenciar o botão de suspensão</description>
+                <description xml:lang="ru">Разрешить приложениям устанавливать блокировку обработки нажатий на кнопку перехода в ждущий режим</description>
+                <description xml:lang="sv">Tillåt program att hindra systemhantering av väntelägesknappen</description>
+                <description xml:lang="uk">Дозволити програмам перешкоджати обробленню системою клавіші призупинення</description>
+                <message>Authentication is required for an application to inhibit system handling of the suspend key.</message>
+                <message xml:lang="de">Legitimierung ist erforderlich, um Anwendungen das Unterbinden der Auswertung des Bereitschaftsknopfes des Systems zu erlauben.</message>
+                <message xml:lang="el">Απαιτείται πιστοποίηση για να επιτρέπεται σε μια εφαρμογή να αποτρέψει την διαχείριση του πλήκτρου αναστολής του συστήματος.</message>
+                <message xml:lang="fr">Authentification requise pour permettre à une application d'empêcher la gestion du bouton de mise en veille du système.</message>
+                <message xml:lang="hu">Hitelesítés szükséges egy alkalmazás számára a felfüggesztés gomb rendszer általi kezelésének meggátlásához.</message>
+                <message xml:lang="it">Autenticazione richiesta per un'applicazione per inibire la gestione di sistema del tasto di sospensione.</message>
+                <message xml:lang="pl">Program wymaga uwierzytelnienia, aby wstrzymać obsługę klawisza uśpienia przez system.</message>
+                <message xml:lang="pt_BR">É necessária autenticação para que um aplicativo iniba a manipulação do sistema sobre a chave de suspensão.</message>
+                <message xml:lang="ru">Чтобы разрешить приложениям устанавливать блокировку обработки нажатий на кнопку перехода в ждущий режим, необходимо пройти аутентификацию.</message>
+                <message xml:lang="sv">Autentisering krävs för att tillåta ett program att hindra systemhantering av väntelägesknappen.</message>
+                <message xml:lang="uk">Засвідчення потрібно, щоб дозволити програмам перешкоджати обробленню системою клавіші призупинення.</message>
+                <defaults>
+                        <allow_any>no</allow_any>
+                        <allow_inactive>yes</allow_inactive>
+                        <allow_active>yes</allow_active>
+                </defaults>
+                <annotate key="org.freedesktop.policykit.imply">org.freedesktop.login1.inhibit-handle-hibernate-key org.freedesktop.login1.inhibit-handle-lid-switch</annotate>
+        </action>
+
+        <action id="org.freedesktop.login1.inhibit-handle-hibernate-key">
+                <description>Allow applications to inhibit system handling of the hibernate key</description>
+                <description xml:lang="de">Anwendungen dürfen das Auswerten des Knopfs für den Ruhezustand unterbinden</description>
+                <description xml:lang="el">Να επιτρέπεται στις εφαρμογές να αποτρέπουν τη διαχείριση του πλήκτρου αδρανοποίησης του συστήματος</description>
+                <description xml:lang="fr">Permet aux applications d'empêcher la gestion du bouton d'hibernation du système</description>
+                <description xml:lang="hu">Alkalmazások meggátolhatják a hibernálás gomb rendszer általi kezelését</description>
+                <description xml:lang="it">Consenti alle applicazioni di inibire la gestione di sistema del tasto di ibernazione</description>
+                <description xml:lang="pl">Zezwolenie programom na wstrzymanie obsługi klawisza hibernacji przez system</description>
+                <description xml:lang="pt_BR">Permitir que aplicativos inibam o sistema de gerenciar o botão de hibernação</description>
+                <description xml:lang="ru">Разрешить приложениям устанавливать блокировку обработки нажатий на кнопку перехода в спящий режим</description>
+                <description xml:lang="sv">Tillåt program att hindra systemhantering av vilolägesknappen</description>
+                <description xml:lang="uk">Дозволити програмам перешкоджати обробленню системою клавіші присипання</description>
+                <message>Authentication is required for an application to inhibit system handling of the hibernate key.</message>
+                <message xml:lang="de">Legitimierung ist erforderlich, um Anwendungen das Unterbinden der Auswertung des Knopfs für den Ruhezustand zu erlauben.</message>
+                <message xml:lang="el">Απαιτείται πιστοποίηση για να επιτρέπεται σε μια εφαρμογή να αποτρέψει την διαχείριση του πλήκτρου αδρανοποίησης του συστήματος.</message>
+                <message xml:lang="fr">Authentification requise pour permettre à une application d'empêcher la gestion du bouton d'hibernation du système.</message>
+                <message xml:lang="hu">Hitelesítés szükséges egy alkalmazás számára a hibernálás gomb rendszer általi kezelésének meggátlásához.</message>
+                <message xml:lang="it">Autenticazione richiesta per un'applicazione per inibire la gestione di sistema del tasto di ibernazione.</message>
+                <message xml:lang="pl">Program wymaga uwierzytelnienia, aby wstrzymać obsługę klawisza hibernacji przez system.</message>
+                <message xml:lang="pt_BR">É necessária autenticação para que um aplicativo iniba a manipulação do sistema sobre a chave de hibernar.</message>
+                <message xml:lang="ru">Чтобы разрешить приложениям устанавливать блокировку обработки нажатий на кнопку перехода в спящий режим, необходимо пройти аутентификацию.</message>
+                <message xml:lang="sv">Autentisering krävs för att tillåta ett program att hindra systemhantering av vilolägesknappen.</message>
+                <message xml:lang="uk">Засвідчення потрібно, щоб дозволити програмам перешкоджати обробленню системою клавіші присипання.</message>
+                <defaults>
+                        <allow_any>no</allow_any>
+                        <allow_inactive>yes</allow_inactive>
+                        <allow_active>yes</allow_active>
+                </defaults>
+        </action>
+
+        <action id="org.freedesktop.login1.inhibit-handle-lid-switch">
+                <description>Allow applications to inhibit system handling of the lid switch</description>
+                <description xml:lang="de">Anwendungen dürfen das Auswerten des Notebookdeckelschalters unterbinden</description>
+                <description xml:lang="el">Να επιτρέπεται στις εφαρμογές να αποτρέπουν τη διαχείριση του διακόπτη καλύμματος του συστήματος</description>
+                <description xml:lang="fr">Permet aux applications d'empêcher la gestion par le système du rabat de l'écran</description>
+                <description xml:lang="hu">Alkalmazások meggátolhatják a fedélkapcsoló rendszer általi kezelését</description>
+                <description xml:lang="it">Consenti alle applicazioni di inibire la gestione di sistema alla apertura/chiusura del portatile</description>
+                <description xml:lang="pl">Zezwolenie programom na wstrzymanie obsługi przełącznika pokrywy przez system</description>
+                <description xml:lang="pt_BR">Permitir que aplicativos inibam o sistema de gerenciar a abertura/fechamento da tampa do dispositivo portátil</description>
+                <description xml:lang="ru">Разрешить приложениям устанавливать блокировку на обработку закрытия крышки ноутбука</description>
+                <description xml:lang="sv">Tillåt program att hindra systemhantering av växel för datorhölje</description>
+                <description xml:lang="uk">Дозволити програмам перешкоджати обробленню системою клавіші перемикання кришки</description>
+                <message>Authentication is required for an application to inhibit system handling of the lid switch.</message>
+                <message xml:lang="de">Legitimierung ist erforderlich, um Anwendungen das Unterbinden der Auswertung des Notebookdeckelschalters des Systems zu erlauben.</message>
+                <message xml:lang="el">Απαιτείται πιστοποίηση για να επιτρέπεται σε μια εφαρμογή να αποτρέψει την διαχείριση του διακόπτη καλύμματος του συστήματος.</message>
+                <message xml:lang="fr">Authentification requise pour permettre à une application d'empêcher la gestion par le système du rabat de l'écran.</message>
+                <message xml:lang="hu">Hitelesítés szükséges egy alkalmazás számára a fedélkapcsoló rendszer általi kezelésének meggátlásához.</message>
+                <message xml:lang="it">Autenticazione richiesta per consentire ad un'applicazione di inibire la gestione di sistema alla apertura/chiusura del portatile.</message>
+                <message xml:lang="pl">Program wymaga uwierzytelnienia, aby wstrzymać obsługę przełącznika pokrywy przez system.</message>
+                <message xml:lang="pt_BR">É necessária autenticação para que um aplicativo iniba a manipulação do sistema sobre o interruptor da tela.</message>
+                <message xml:lang="ru">Чтобы разрешить приложениям устанавливать блокировку на обработку закрытия крышки ноутбука, необходимо пройти аутентификацию.</message>
+                <message xml:lang="sv">Autentisering krävs för att tillåta ett program att hindra systemhantering av brytaren för datorhöljet.</message>
+                <message xml:lang="uk">Засвідчення потрібно, щоб дозволити програмам перешкоджати обробленню системою клавіші перемикання кришки.</message>
+                <defaults>
+                        <allow_any>no</allow_any>
+                        <allow_inactive>yes</allow_inactive>
+                        <allow_active>yes</allow_active>
+                </defaults>
+        </action>
+
+        <action id="org.freedesktop.login1.set-user-linger">
+                <description>Allow non-logged-in users to run programs</description>
+                <description xml:lang="de">Nicht angemeldete Benutzer dürfen Programme ausführen</description>
+                <description xml:lang="el">Να επιτρέπεται σε μη συνδεμένους χρήστες να εκτελούν προγράμματα</description>
+                <description xml:lang="fr">Permet aux utilisateurs non connectés d'exécuter des programmes</description>
+                <description xml:lang="hu">Programfuttatás engedélyezése be nem jelentkezett felhasználók számára</description>
+                <description xml:lang="it">Consenti agli utenti non connessi di eseguire programmi</description>
+                <description xml:lang="pl">Zezwolenie niezalogowanym użytkownikom na uruchamianie programów</description>
+                <description xml:lang="pt_BR">Permitir que programas sejam executados por usuários que não possuem sessão</description>
+                <description xml:lang="ru">Разрешить пользователям оставлять программы в фоновом режиме после завершения сеанса</description>
+                <description xml:lang="sv">Tillåt ej inloggade användare att köra program</description>
+                <description xml:lang="uk">Дозволити незареєстрованим користувачам запускати програми</description>
+                <message>Authentication is required to run programs as a non-logged-in user.</message>
+                <message xml:lang="de">Legitimierung ist erforderlich, damit nicht angemeldete Benutzer Programme ausführen dürfen.</message>
+                <message xml:lang="el">Απαιτείται πιστοποίηση για να επιτρέπεται σε μη συνδεμένους χρήστες να εκτελούν προγράμματα.</message>
+                <message xml:lang="fr">Authentification requise pour permettre aux utilisateurs non connectés d'exécuter des programmes.</message>
+                <message xml:lang="hu">Hitelesítés szükséges a programfuttatáshoz be nem jelentkezett felhasználóként.</message>
+                <message xml:lang="it">Autenticazione richiesta per consentire agli utenti non connessi di eseguire programmi.</message>
+                <message xml:lang="pl">Wymagane jest uwierzytelnienie, aby uruchamiać programy jako niezalogowany użytkownik.</message>
+                <message xml:lang="pt_BR">É necessária autenticação para executar programas como usuário sem sessão aberta.</message>
+                <message xml:lang="ru">Чтобы разрешить пользователям оставлять программы в фоновом режиме после завершения сеанса, необходимо пройти аутентификацию.</message>
+                <message xml:lang="sv">Autentisering krävs för att köra program som en icke inloggad användare.</message>
+                <message xml:lang="uk">Засвідчення потрібно, щоб дозволити незареєстрованим користувачам запускати програми.</message>
+                <defaults>
+                        <allow_any>auth_admin_keep</allow_any>
+                        <allow_inactive>auth_admin_keep</allow_inactive>
+                        <allow_active>auth_admin_keep</allow_active>
+                </defaults>
+        </action>
+
+        <action id="org.freedesktop.login1.attach-device">
+                <description>Allow attaching devices to seats</description>
+                <description xml:lang="de">Das Anschließen von Geräten an Arbeitsstationen erlauben</description>
+                <description xml:lang="el">Να επιτρέπεται η προσάρτηση συσκευών στους σταθμούς εργασίας</description>
+                <description xml:lang="fr">Permet d'associer des périphériques à des postes (seats)</description>
+                <description xml:lang="hu">Eszközök csatolásának engedélyezése munkaállomásokhoz</description>
+                <description xml:lang="it">Consenti di collegare dispositivi alle postazioni</description>
+                <description xml:lang="pl">Zezwolenie na podłączanie urządzeń do stanowisk</description>
+                <description xml:lang="pt_BR">Permitir conectar dispositivos em estações</description>
+                <description xml:lang="ru">Разрешить подключение устройств к рабочим местам</description>
+                <description xml:lang="sv">Tillåt att binda enheter till platser</description>
+                <description xml:lang="uk">Дозволити під'єднання пристроїв до місць</description>
+                <message>Authentication is required for attaching a device to a seat.</message>
+                <message xml:lang="de">Legitimierung ist zum Anschließen eines Geräts an eine Arbeitsstation notwendig.</message>
+                <message xml:lang="el">Απαιτείται πιστοποίηση για προσάρτηση μιας συσκευής σε έναν σταθμό εργασίας.</message>
+                <message xml:lang="fr">Authentification requise pour associer un périphérique à un poste (seat).</message>
+                <message xml:lang="hu">Hitelesítés szükséges eszköz csatolásának engedélyezéséhez egy munkaállomáshoz</message>
+                <message xml:lang="it">Autenticazione richiesta per collegare un dispositivo ad una postazione.</message>
+                <message xml:lang="pl">Wymagane jest uwierzytelnienie, aby podłączyć urządzenie do stanowiska.</message>
+                <message xml:lang="pt_BR">É necessária autenticação para conectar um dispositivo em uma estação.</message>
+                <message xml:lang="ru">Чтобы разрешить подключение устройств к рабочим местам, необходимо пройти аутентификацию.</message>
+                <message xml:lang="sv">Autentisering krävs för att binda en enhet till en plats.</message>
+                <message xml:lang="uk">Засвідчення потрібно, щоб під'єднувати пристрої до місць.</message>
+                <defaults>
+                        <allow_any>auth_admin_keep</allow_any>
+                        <allow_inactive>auth_admin_keep</allow_inactive>
+                        <allow_active>auth_admin_keep</allow_active>
+                </defaults>
+                <annotate key="org.freedesktop.policykit.imply">org.freedesktop.login1.flush-devices</annotate>
+        </action>
+
+        <action id="org.freedesktop.login1.flush-devices">
+                <description>Flush device to seat attachments</description>
+                <description xml:lang="de">Zurücksetzen der an eine Arbeitsstation angeschlossenen Geräte</description>
+                <description xml:lang="el">Αφαίρεση συσκευής από προσαρτήσεις σταθμού εργασίας</description>
+                <description xml:lang="fr">Révoquer les associations de périphériques aux postes (seats)</description>
+                <description xml:lang="hu">Eszközök és munkaállomások csatolásainak törlése</description>
+                <description xml:lang="it">Scollega i dispositivi dalla postazione</description>
+                <description xml:lang="pl">Usunięcie podłączenia urządzeń do stanowisk</description>
+                <description xml:lang="pt_BR">Liberar dispositivo para conexões da estação</description>
+                <description xml:lang="ru">Сбросить привязки устройств к рабочим местам</description>
+                <description xml:lang="sv">Töm bindningar för enhet-till-plats</description>
+                <description xml:lang="uk">Очисний пристрій для під'єднань до місця</description>
+                <message>Authentication is required for resetting how devices are attached to seats.</message>
+                <message xml:lang="de">Legitimierung ist zum Zurücksetzen notwendig, wie Geräte an eine Arbeitsstation angeschlossen werden.</message>
+                <message xml:lang="el">Απαιτείται πιστοποίηση για επαναφορά του τρόπου που οι συσκευές προσαρτώνται στους σταθμούς εργασίας.</message>
+                <message xml:lang="fr">Authentification requise pour révoquer les associations de périphériques aux postes (seats).</message>
+                <message xml:lang="hu">Hitelesítés szükséges az eszközök munkaállomásokhoz csatolásainak alaphelyzetbe állításához.</message>
+                <message xml:lang="it">Autenticazione richiesta per ripristinare come i dispositivi sono collegati alle postazioni.</message>
+                <message xml:lang="pl">Wymagane jest uwierzytelnienie, aby ponownie ustawić sposób podłączenia urządzeń do stanowisk.</message>
+                <message xml:lang="pt_BR">É necessária autenticação para redefinir a quantidade de dispositivos conectados na estação.</message>
+                <message xml:lang="ru">Чтобы сбросить привязки устройств к рабочим местам, необходимо пройти аутентификацию.</message>
+                <message xml:lang="sv">Autentisering krävs för att återställa hur enheter är bundna till platser.</message>
+                <message xml:lang="uk">Засвідчення потрібно, щоб перезапустити спосіб під'єднання до місць.</message>
+                <defaults>
+                        <allow_any>auth_admin_keep</allow_any>
+                        <allow_inactive>auth_admin_keep</allow_inactive>
+                        <allow_active>auth_admin_keep</allow_active>
+                </defaults>
+        </action>
+
+        <action id="org.freedesktop.login1.power-off">
+                <description>Power off the system</description>
+                <description xml:lang="de">Das System ausschalten</description>
+                <description xml:lang="el">Σβήσιμο του συστήματος</description>
+                <description xml:lang="fr">Éteindre le système</description>
+                <description xml:lang="hu">A rendszer kikapcsolása</description>
+                <description xml:lang="it">Spegnere il sistema</description>
+                <description xml:lang="pl">Wyłączenie systemu</description>
+                <description xml:lang="pt_BR">Desligar o sistema</description>
+                <description xml:lang="ru">Выключить систему</description>
+                <description xml:lang="sv">Stäng av systemet</description>
+                <description xml:lang="uk">Вимкнути систему</description>
+                <message>Authentication is required for powering off the system.</message>
+                <message xml:lang="de">Legitimierung ist zum Ausschalten des Systems notwendig.</message>
+                <message xml:lang="el">Απαιτείται πιστοποίηση για την σβήσιμο του συστήματος.</message>
+                <message xml:lang="fr">Authentification requise pour éteindre le système.</message>
+                <message xml:lang="hu">Hitelesítés szükséges a rendszer kikapcsolásához.</message>
+                <message xml:lang="it">Autenticazione richiesta per spegnere il sistema.</message>
+                <message xml:lang="pl">Wymagane jest uwierzytelnienie, aby wyłączyć system.</message>
+                <message xml:lang="pt_BR">É necessária autenticação para desligar o sistema.</message>
+                <message xml:lang="ru">Чтобы выключить систему, необходимо пройти аутентификацию.</message>
+                <message xml:lang="sv">Autentisering krävs för att stänga av systemet.</message>
+                <message xml:lang="uk">Засвідчення потрібно, щоб вимкнути систему.</message>
+                <defaults>
+                        <allow_any>auth_admin_keep</allow_any>
+                        <allow_inactive>auth_admin_keep</allow_inactive>
+                        <allow_active>yes</allow_active>
+                </defaults>
+        </action>
+
+        <action id="org.freedesktop.login1.power-off-multiple-sessions">
+                <description>Power off the system while other users are logged in</description>
+                <description xml:lang="de">Das System herunter fahren, während andere Benutzer angemeldet sind</description>
+                <description xml:lang="el">Σβήσιμο του συστήματος ενώ άλλοι χρήστες είναι συνδεμένοι</description>
+                <description xml:lang="fr">Éteindre le système alors que d'autres utilisateurs sont connectés</description>
+                <description xml:lang="hu">A rendszer kikapcsolása miközben be vannak jelentkezve más felhasználók</description>
+                <description xml:lang="it">Spegnere il sistema mentre altri utenti sono connessi</description>
+                <description xml:lang="pl">Wyłączenie systemu, kiedy są zalogowani inni użytkownicy</description>
+                <description xml:lang="pt_BR">Desligar o sistema enquanto outros usuários estão conectados</description>
+                <description xml:lang="ru">Выключить систему, несмотря на то, что в ней работают другие пользователи</description>
+                <description xml:lang="sv">Stäng av systemet medan andra användare är inloggade</description>
+                <description xml:lang="uk">Вимикнути систему, коли інші користувачі ще в ній</description>
+                <message>Authentication is required for powering off the system while other users are logged in.</message>
+                <message xml:lang="de">Legitimierung ist zum Herunterfahren des Systems notwendig, während andere Benutzer angemeldet sind.</message>
+                <message xml:lang="el">Απαιτείται πιστοποίηση για σβήσιμο του συστήματος ενώ άλλοι χρήστες είναι συνδεμένοι.</message>
+                <message xml:lang="fr">Authentification requise pour éteindre le système alors que d'autres utilisateurs sont connectés.</message>
+                <message xml:lang="hu">Hitelesítés szükséges a rendszer kikapcsolásához miközben be vannak jelentkezve más felhasználók.</message>
+                <message xml:lang="it">Autenticazione richiesta per spegnere il sistema mentre altri utenti sono connessi.</message>
+                <message xml:lang="pl">Wymagane jest uwierzytelnienie, aby wyłączyć system, kiedy są zalogowani inni użytkownicy.</message>
+                <message xml:lang="pt_BR">É necessária autenticação para desligar o sistema enquanto outros usuários estão conectados.</message>
+                <message xml:lang="ru">Чтобы выключить систему, несмотря на то, что в ней работают другие пользователи, необходимо пройти аутентификацию.</message>
+                <message xml:lang="sv">Autentisering krävs för att stänga av systemet medan andra användare är inloggade.</message>
+                <message xml:lang="uk">Засвідчення потрібно, щоб вимкнути систему, коли інші користувачі в ній.</message>
+                <defaults>
+                        <allow_any>auth_admin_keep</allow_any>
+                        <allow_inactive>auth_admin_keep</allow_inactive>
+                        <allow_active>yes</allow_active>
+                </defaults>
+                <annotate key="org.freedesktop.policykit.imply">org.freedesktop.login1.power-off</annotate>
+        </action>
+
+        <action id="org.freedesktop.login1.power-off-ignore-inhibit">
+                <description>Power off the system while an application asked to inhibit it</description>
+                <description xml:lang="de">Das System ausschalten, während eine Anwendung anfordert es zu unterbinden</description>
+                <description xml:lang="el">Απενεργοποίηση του συστήματος ενώ μια εφαρμογή ζήτησε να αποτραπεί.</description>
+                <description xml:lang="fr">Éteindre le système alors qu'une application a demandé de l'empêcher</description>
+                <description xml:lang="hu">A rendszer kikapcsolása miközben egy alkalmazás ennek meggátlását kérte</description>
+                <description xml:lang="it">Spegnere il sistema mentre un'applicazione chiede di inibirne l'azione</description>
+                <description xml:lang="pl">Wyłączenie systemu, kiedy program zażądał jego wstrzymania</description>
+                <description xml:lang="pt_BR">Desligar o sistema enquanto um aplicativo solicitou inibição</description>
+                <description xml:lang="ru">Выключить систему, несмотря на то, что приложение запросило блокировку выключения</description>
+                <description xml:lang="sv">Stäng av systemet även då ett program hindrar det</description>
+                <description xml:lang="uk">Вимкнути систему, коли програми намагаються першкодити цьому</description>
+                <message>Authentication is required for powering off the system while an application asked to inhibit it.</message>
+                <message xml:lang="de">Legitimierung ist zum Ausschalten des Systems notwendig, während eine Anwendung anfordert es zu unterbinden.</message>
+                <message xml:lang="el">Απαιτείται πιστοποίηση για απενεργοποίηση του συστήματος ενώ μια εφαρμογή ζήτησε να αποτραπεί.</message>
+                <message xml:lang="fr">Authentification requise pour éteindre le système alors qu'une application a demandé de l'empêcher.</message>
+                <message xml:lang="hu">Hitelesítés szükséges a rendszer kikapcsolásához miközben egy alkalmazás ennek meggátlását kérte.</message>
+                <message xml:lang="it">Autenticazione richiesta per spegnere il sistema mentre un'applicazione chiede di inibirne l'azione.</message>
+                <message xml:lang="pl">Wymagane jest uwierzytelnienie, aby wyłączyć system, kiedy program zażądał jego wstrzymania.</message>
+                <message xml:lang="pt_BR">É necessária autenticação para desligar o sistema enquanto um aplicativo solicitou inibição.</message>
+                <message xml:lang="ru">Чтобы выключить систему, несмотря на то, что приложение запросило блокировку выключения, необходимо пройти аутентификацию.</message>
+                <message xml:lang="sv">Autentisering krävs för att stänga av systemet även då ett program hindrar det.</message>
+                <message xml:lang="uk">Засвідчення потрібно, щоб вимкнути систему, коли програми намагаються першкодити цьому.</message>
+                <defaults>
+                        <allow_any>auth_admin_keep</allow_any>
+                        <allow_inactive>auth_admin_keep</allow_inactive>
+                        <allow_active>auth_admin_keep</allow_active>
+                </defaults>
+                <annotate key="org.freedesktop.policykit.imply">org.freedesktop.login1.power-off</annotate>
+        </action>
+
+        <action id="org.freedesktop.login1.reboot">
+                <description>Reboot the system</description>
+                <description xml:lang="de">Das System neu starten</description>
+                <description xml:lang="el">Επανεκκίνηση του συστήματος</description>
+                <description xml:lang="fr">Redémarrer le système</description>
+                <description xml:lang="hu">A rendszer újraindítása</description>
+                <description xml:lang="it">Riavviare il sistema</description>
+                <description xml:lang="pl">Ponowne uruchomienie systemu</description>
+                <description xml:lang="pt_BR">Reiniciar o sistema</description>
+                <description xml:lang="ru">Перезагрузить систему</description>
+                <description xml:lang="sv">Starta om systemet</description>
+                <description xml:lang="uk">Перезавантажити систему</description>
+                <message>Authentication is required for rebooting the system.</message>
+                <message xml:lang="de">Legitimierung ist zum Neustart des Systems notwendig.</message>
+                <message xml:lang="el">Απαιτείται πιστοποίηση για επανεκκίνηση του συστήματος.</message>
+                <message xml:lang="fr">Authentification requise pour redémarrer le système.</message>
+                <message xml:lang="hu">Hitelesítés szükséges a rendszer újraindításához.</message>
+                <message xml:lang="it">Autenticazione richiesta per riavviare il sistema.</message>
+                <message xml:lang="pl">Wymagane jest uwierzytelnienie, aby ponownie uruchomić system.</message>
+                <message xml:lang="pt_BR">É necessária autenticação para reiniciar o sistema.</message>
+                <message xml:lang="ru">Чтобы перезагрузить систему, необходимо пройти аутентификацию.</message>
+                <message xml:lang="sv">Autentisering krävs för att starta om systemet.</message>
+                <message xml:lang="uk">Для перезавантаження системи необхідна ідентифікація.</message>
+                <defaults>
+                        <allow_any>auth_admin_keep</allow_any>
+                        <allow_inactive>auth_admin_keep</allow_inactive>
+                        <allow_active>yes</allow_active>
+                </defaults>
+        </action>
+
+        <action id="org.freedesktop.login1.reboot-multiple-sessions">
+                <description>Reboot the system while other users are logged in</description>
+                <description xml:lang="de">Das Systems neu starten, während andere Benutzer angemeldet sind</description>
+                <description xml:lang="el">Επανεκκίνηση του συστήματος ενώ άλλοι χρήστες είναι συνδεμένοι</description>
+                <description xml:lang="fr">Redémarrer le système alors que d'autres utilisateurs sont connectés</description>
+                <description xml:lang="hu">A rendszer újraindítása mialatt be vannak jelentkezve más felhasználók</description>
+                <description xml:lang="it">Riavviare il sistema mentre altri utenti sono connessi</description>
+                <description xml:lang="pl">Ponowne uruchomienie systemu, kiedy są zalogowani inni użytkownicy</description>
+                <description xml:lang="pt_BR">Reiniciar o sistema enquanto outros usuários estiverem conectados</description>
+                <description xml:lang="ru">Перезагрузить систему, несмотря на то, что в ней работают другие пользователи</description>
+                <description xml:lang="sv">Starta om systemet medan andra användare är inloggade</description>
+                <description xml:lang="uk">Перезавантажити, якщо інщі користувачі в системі</description>
+                <message>Authentication is required for rebooting the system while other users are logged in.</message>
+                <message xml:lang="de">Legitimierung ist zum Neustart des Systems notwendig, während andere Benutzer angemeldet sind.</message>
+                <message xml:lang="el">Απαιτείται πιστοποίηση για επανεκκίνηση του συστήματος ενώ άλλοι χρήστες είναι συνδεμένοι.</message>
+                <message xml:lang="fr">Authentification requise pour redémarrer le système alors que d'autres utilisateurs sont connectés.</message>
+                <message xml:lang="hu">Hitelesítés szükséges a rendszer újraindításához miközben be vannak jelentkezve más felhasználók.</message>
+                <message xml:lang="it">Autenticazione richiesta per riavviare il sistema mentre altri utenti sono connessi.</message>
+                <message xml:lang="pl">Wymagane jest uwierzytelnienie, aby ponownie uruchomić system, kiedy są zalogowani inni użytkownicy.</message>
+                <message xml:lang="pt_BR">É necessária autenticação para reiniciar o sistema enquanto outros usuários estiverem conectados.</message>
+                <message xml:lang="ru">Чтобы перезагрузить систему, несмотря на то, что в ней работают другие пользователи, необходимо пройти аутентификацию.</message>
+                <message xml:lang="sv">Autentisering krävs för att starta om systemet medan andra användare är inloggade.</message>
+                <message xml:lang="uk">Засвідчення потрібно, щоб перезапустити систему, коли інші користувачі в ній.</message>
+                <defaults>
+                        <allow_any>auth_admin_keep</allow_any>
+                        <allow_inactive>auth_admin_keep</allow_inactive>
+                        <allow_active>yes</allow_active>
+                </defaults>
+                <annotate key="org.freedesktop.policykit.imply">org.freedesktop.login1.reboot</annotate>
+        </action>
+
+        <action id="org.freedesktop.login1.reboot-ignore-inhibit">
+                <description>Reboot the system while an application asked to inhibit it</description>
+                <description xml:lang="de">Das System neu starten, während eine Anwendung anfordert es zu unterbinden</description>
+                <description xml:lang="el">Επανεκκίνηση του συστήματος ενώ μια εφαρμογή ζήτησε να αποτραπεί</description>
+                <description xml:lang="fr">Redémarrer le système alors qu'une application a demandé de l'empêcher</description>
+                <description xml:lang="hu">A rendszer újraindítása miközben egy alkalmazás ennek meggátlását kérte</description>
+                <description xml:lang="it">Riavviare il sistema mentre un'applicazione chiede di inibirne l'azione</description>
+                <description xml:lang="pl">Ponowne uruchomienie systemu, kiedy program zażądał jego wstrzymania</description>
+                <description xml:lang="pt_BR">Reiniciar o sistema enquanto um aplicativo solicitou inibição</description>
+                <description xml:lang="ru">Перезагрузить систему, несмотря на то, что приложение запросило блокировку выключения</description>
+                <description xml:lang="sv">Starta om systemet även då ett program hindrar det.</description>
+                <description xml:lang="uk">Перезапустити систему, коли програми намагаються першкодити цьому</description>
+                <message>Authentication is required for rebooting the system while an application asked to inhibit it.</message>
+                <message xml:lang="de">Legitimierung ist zum Neustart des Systems notwendig, während eine Anwendung anforderte es zu unterbinden.</message>
+                <message xml:lang="el">Απαιτείται πιστοποίηση για επανεκκίνηση του συστήματος ενώ μια εφαρμογή ζήτησε να αποτραπεί.</message>
+                <message xml:lang="fr">Authentification requise pour redémarrer le système alors qu'une application  a demandé de l'empêcher.</message>
+                <message xml:lang="hu">Hitelesítés szükséges a rendszer újraindításához miközben egy alkalmazás ennek meggátlását kérte.</message>
+                <message xml:lang="it">Autenticazione richiesta per riavviare il sistema mentre un'applicazione chiede di inibirne l'azione.</message>
+                <message xml:lang="pl">Wymagane jest uwierzytelnienie, aby ponownie uruchomić system, kiedy program zażądał jego wstrzymania.</message>
+                <message xml:lang="pt_BR">É necessária autenticação para reiniciar o sistema enquanto um aplicativo solicitou inibição.</message>
+                <message xml:lang="ru">Чтобы перезагрузить систему, несмотря на то, что приложение запросило блокировку выключения, необходимо пройти аутентификацию.</message>
+                <message xml:lang="sv">Autentisering krävs för att starta om systemet även då ett program hindrar det.</message>
+                <message xml:lang="uk">Засвідчення потрібно, щоб перезапустити систему, коли програми намагаються першкодити цьому.</message>
+                <defaults>
+                        <allow_any>auth_admin_keep</allow_any>
+                        <allow_inactive>auth_admin_keep</allow_inactive>
+                        <allow_active>auth_admin_keep</allow_active>
+                </defaults>
+                <annotate key="org.freedesktop.policykit.imply">org.freedesktop.login1.reboot</annotate>
+        </action>
+
+        <action id="org.freedesktop.login1.suspend">
+                <description>Suspend the system</description>
+                <description xml:lang="de">Das System in Bereitschaft versetzen</description>
+                <description xml:lang="el">Αναστολή του συστήματος</description>
+                <description xml:lang="fr">Mettre le système en veille</description>
+                <description xml:lang="hu">A rendszer felfüggesztése</description>
+                <description xml:lang="it">Sospendere il sistema</description>
+                <description xml:lang="pl">Uśpienie systemu</description>
+                <description xml:lang="pt_BR">Suspender o sistema</description>
+                <description xml:lang="ru">Перевести систему в ждущий режим</description>
+                <description xml:lang="sv">Försätt system i vänteläge</description>
+                <description xml:lang="uk">Призупинити систему</description>
+                <message>Authentication is required for suspending the system.</message>
+                <message xml:lang="de">Legitimierung ist zum Versetzen des Systems in Bereitschaft notwendig.</message>
+                <message xml:lang="el">Απαιτείται πιστοποίηση για την αναστολή του συστήματος.</message>
+                <message xml:lang="fr">Authentification requise pour mettre le système en veille.</message>
+                <message xml:lang="hu">Hitelesítés szükséges a rendszer felfüggesztéséhez.</message>
+                <message xml:lang="it">Autenticazione richiesta per sospendere il sistema.</message>
+                <message xml:lang="pl">Wymagane jest uwierzytelnienie, aby uśpić system.</message>
+                <message xml:lang="pt_BR">É necessária autenticação para suspender o sistema.</message>
+                <message xml:lang="ru">Чтобы перевести систему в ждущий режим, необходимо пройти аутентификацию.</message>
+                <message xml:lang="sv">Autentisering krävs för att försätta system i vänteläge.</message>
+                <message xml:lang="uk">Засвідчення потрібно, щоб призупинити систему.</message>
+                <defaults>
+                        <allow_any>auth_admin_keep</allow_any>
+                        <allow_inactive>auth_admin_keep</allow_inactive>
+                        <allow_active>yes</allow_active>
+                </defaults>
+        </action>
+
+        <action id="org.freedesktop.login1.suspend-multiple-sessions">
+                <description>Suspend the system while other users are logged in</description>
+                <description xml:lang="de">Das System in Bereitschaft versetzen, während andere Benutzer angemeldet sind.</description>
+                <description xml:lang="el">Αναστολή του συστήματος ενώ άλλοι χρήστες είναι συνδεμένοι</description>
+                <description xml:lang="fr">Mettre le système en veille alors que d'autres utilisateurs sont connectés</description>
+                <description xml:lang="hu">A rendszer felfüggesztése mialatt be vannak jelentkezve más felhasználók</description>
+                <description xml:lang="it">Sospendere il sistema mentre altri utenti sono connessi</description>
+                <description xml:lang="pl">Uśpienie systemu, kiedy są zalogowani inni użytkownicy</description>
+                <description xml:lang="pt_BR">Suspender o sistema enquanto outros usuários estiverem conectados</description>
+                <description xml:lang="ru">Перевести систему в ждущий режим, несмотря на то, что в ней работают другие пользователи</description>
+                <description xml:lang="sv">Försätt systemet i vänteläge medan andra användare är inloggade</description>
+                <description xml:lang="uk">Призупинити систему, коли інші користувачі в ній</description>
+                <message>Authentication is required for suspending the system while other users are logged in.</message>
+                <message xml:lang="de">Legitimierung ist zum Versetzen des Systems in Bereitschaft notwendig, während andere Benutzer angemeldet sind.</message>
+                <message xml:lang="el">Απαιτείται πιστοποίηση για αναστολή του συστήματος ενώ άλλοι χρήστες είναι συνδεμένοι.</message>
+                <message xml:lang="fr">Authentification requise pour mettre le système en veille alors que d'autres utilisateurs sont connectés.</message>
+                <message xml:lang="hu">Hitelesítés szükséges a rendszer felfüggesztéséhez miközben be vannak jelentkezve más felhasználók.</message>
+                <message xml:lang="it">Autenticazione richiesta per sospendere il sistema mentre altri utenti sono connessi.</message>
+                <message xml:lang="pl">Wymagane jest uwierzytelnienie, aby uśpić system, kiedy są zalogowani inni użytkownicy.</message>
+                <message xml:lang="pt_BR">É necessária autenticação para suspender o sistema enquanto outros usuários estiverem conectados.</message>
+                <message xml:lang="ru">Чтобы перевести систему в ждущий режим, несмотря на то, что в ней работают другие пользователи, необходимо пройти аутентификацию.</message>
+                <message xml:lang="sv">Autentisering krävs för att försätta systemet i vänteläge medan andra användare är inloggade.</message>
+                <message xml:lang="uk">Засвідчення потрібно, щоб призупинити систему, коли інші користувачі в ній.</message>
+                <defaults>
+                        <allow_any>auth_admin_keep</allow_any>
+                        <allow_inactive>auth_admin_keep</allow_inactive>
+                        <allow_active>yes</allow_active>
+                </defaults>
+                <annotate key="org.freedesktop.policykit.imply">org.freedesktop.login1.suspend</annotate>
+        </action>
+
+        <action id="org.freedesktop.login1.suspend-ignore-inhibit">
+                <description>Suspend the system while an application asked to inhibit it</description>
+                <description xml:lang="de">Das System in Bereitschaft versetzen, während eine Anwendung anfordert dies zu unterbinden</description>
+                <description xml:lang="el">Αναστολή του συστήματος ενώ μια εφαρμογή ζήτησε να αποτραπεί</description>
+                <description xml:lang="fr">Mettre le système en veille alors qu'une application a demandé de l'empêcher</description>
+                <description xml:lang="hu">A rendszer felfüggesztése miközben egy alkalmazás ennek meggátlását kérte</description>
+                <description xml:lang="it">Sospendere il sistema mentre un'applicazione chiede di inibirne l'azione</description>
+                <description xml:lang="pl">Uśpienie systemu, kiedy program zażądał jego wstrzymania</description>
+                <description xml:lang="pt_BR">Suspender o sistema enquanto um aplicativo solicitou inibição</description>
+                <description xml:lang="ru">Перевести систему в ждущий режим, несмотря на то, что приложение запросило блокировку</description>
+                <description xml:lang="sv">Försätt systemet i vänteläge även då ett program hindrar det</description>
+                <description xml:lang="uk">Призупинити систему, коли програми намагаються першкодити цьому</description>
+                <message>Authentication is required for suspending the system while an application asked to inhibit it.</message>
+                <message xml:lang="de">Legitimierung ist zum Versetzen des Systems in Bereitschaft notwendig, während eine Anwendung anfordert dies zu unterbinden.</message>
+                <message xml:lang="el">Απαιτείται πιστοποίηση για αναστολή του συστήματος ενώ μια εφαρμογή ζήτησε να αποτραπεί.</message>
+                <message xml:lang="fr">Authentification requise pour mettre le système en veille alors qu'une application a demandé de l'empêcher.</message>
+                <message xml:lang="hu">Hitelesítés szükséges a rendszer felfüggesztéséhez miközben egy alkalmazás ennek meggátlását kérte.</message>
+                <message xml:lang="it">Autenticazione richiesta per sospendere il sistema mentre un'applicazione chiede di inibirne l'azione.</message>
+                <message xml:lang="pl">Wymagane jest uwierzytelnienie, aby uśpić system, kiedy program zażądał jego wstrzymania.</message>
+                <message xml:lang="pt_BR">É necessária autenticação para suspender o sistema enquanto um aplicativo solicitou inibição.</message>
+                <message xml:lang="ru">Чтобы перевести систему в ждущий режим, несмотря на то, что приложение запросило блокировку, необходимо пройти аутентификацию.</message>
+                <message xml:lang="sv">Autentisering krävs för att försätta ett program i vänteläge även då ett program hindrar det.</message>
+                <message xml:lang="uk">Засвідчення потрібно, щоб призупнити систему, коли програми намагаються першкодити цьому.</message>
+                <defaults>
+                        <allow_any>auth_admin_keep</allow_any>
+                        <allow_inactive>auth_admin_keep</allow_inactive>
+                        <allow_active>auth_admin_keep</allow_active>
+                </defaults>
+                <annotate key="org.freedesktop.policykit.imply">org.freedesktop.login1.suspend</annotate>
+        </action>
+
+        <action id="org.freedesktop.login1.hibernate">
+                <description>Hibernate the system</description>
+                <description xml:lang="de">Den Ruhezustand des Systems aktivieren</description>
+                <description xml:lang="el">Αδρανοποίηση του συτήματος</description>
+                <description xml:lang="fr">Mettre le système en hibernation</description>
+                <description xml:lang="hu">A rendszer hibernálása</description>
+                <description xml:lang="it">Ibernare il sistema</description>
+                <description xml:lang="pl">Hibernacja systemu</description>
+                <description xml:lang="pt_BR">Hibernar o sistema</description>
+                <description xml:lang="ru">Перевести систему в спящий режим</description>
+                <description xml:lang="sv">Försätt systemet i viloläge</description>
+                <description xml:lang="uk">Приспати систему</description>
+                <message>Authentication is required for hibernating the system.</message>
+                <message xml:lang="de">Legitimierung ist zum Aktivieren des Ruhezustands des Systems notwendig.</message>
+                <message xml:lang="el">Απαιτείται πιστοποίηση για αδρανοποίηση του συστήματος.</message>
+                <message xml:lang="fr">Authentification requise pour mettre le système en hibernation.</message>
+                <message xml:lang="hu">Hitelesítés szükséges a rendszer hibernálásához.</message>
+                <message xml:lang="it">Autenticazione richiesta per ibernare il sistema.</message>
+                <message xml:lang="pl">Wymagane jest uwierzytelnienie, aby zahibernować system.</message>
+                <message xml:lang="pt_BR">É necessária autenticação para hibernar o sistema.</message>
+                <message xml:lang="ru">Чтобы перевести систему в спящий режим, необходимо пройти аутентификацию.</message>
+                <message xml:lang="sv">Autentisering krävs för att försätta systemet i viloläge.</message>
+                <message xml:lang="uk">Засвідчення потрібно, щоб приспати систему.</message>
+                <defaults>
+                        <allow_any>auth_admin_keep</allow_any>
+                        <allow_inactive>auth_admin_keep</allow_inactive>
+                        <allow_active>yes</allow_active>
+                </defaults>
+        </action>
+
+        <action id="org.freedesktop.login1.hibernate-multiple-sessions">
+                <description>Hibernate the system while other users are logged in</description>
+                <description xml:lang="de">Den Ruhezustand des Systems aktivieren, während andere Benutzer angemeldet sind</description>
+                <description xml:lang="el">Αδρανοποίηση του συστήματος ενώ άλλοι χρήστες είναι συνδεμένοι</description>
+                <description xml:lang="fr">Mettre le système en hibernation alors que d'autres utilisateurs sont connectés</description>
+                <description xml:lang="hu">A rendszer hibernálása mialatt be vannak jelentkezve más felhasználók</description>
+                <description xml:lang="it">Ibernare il sistema mentre altri utenti sono connessi</description>
+                <description xml:lang="pl">Hibernacja systemu, kiedy są zalogowani inni użytkownicy</description>
+                <description xml:lang="pt_BR">Hibernar o sistema enquanto outros usuários estiverem conectados</description>
+                <description xml:lang="ru">Перевести систему в спящий режим, несмотря на то, что в ней работают другие пользователи</description>
+                <description xml:lang="sv">Försätt systemet i viloläge medan andra användare är inloggade</description>
+                <description xml:lang="uk">Приспати систему, коли інші користувачі в ній</description>
+                <message>Authentication is required for hibernating the system while other users are logged in.</message>
+                <message xml:lang="de">Legitimierung ist zum Aktivieren des Ruhezustands des Systems notwendig, während andere Benutzer angemeldet sind.</message>
+                <message xml:lang="el">Απαιτείται πιστοποίηση για αδρανοποίηση του συστήματος ενώ άλλοι χρήστες είναι συνδεμένοι.</message>
+                <message xml:lang="fr">Authentification requise pour mettre le système en hibernation alors que d'autres utilisateurs sont connectés.</message>
+                <message xml:lang="hu">Hitelesítés szükséges a rendszer hibernálásához miközben be vannak jelentkezve más felhasználók.</message>
+                <message xml:lang="it">Autenticazione richiesta per ibernare il sistema mentre altri utenti sono connessi.</message>
+                <message xml:lang="pl">Wymagane jest uwierzytelnienie, aby zahibernować system, kiedy są zalogowani inni użytkownicy.</message>
+                <message xml:lang="pt_BR">É necessária autenticação para hibernar o sistema enquanto outros usuários estiverem conectados.</message>
+                <message xml:lang="ru">Чтобы перевести систему в спящий режим, несмотря на то, что в ней работают другие пользователи, необходимо пройти аутентификацию.</message>
+                <message xml:lang="sv">Autentisering krävs för att försätta systemet i viloläge medan andra användare är inloggade.</message>
+                <message xml:lang="uk">Засвідчення потрібно, щоб присипання систему, коли інші користувачі в ній.</message>
+                <defaults>
+                        <allow_any>auth_admin_keep</allow_any>
+                        <allow_inactive>auth_admin_keep</allow_inactive>
+                        <allow_active>yes</allow_active>
+                </defaults>
+                <annotate key="org.freedesktop.policykit.imply">org.freedesktop.login1.hibernate</annotate>
+        </action>
+
+        <action id="org.freedesktop.login1.hibernate-ignore-inhibit">
+                <description>Hibernate the system while an application asked to inhibit it</description>
+                <description xml:lang="de">Das System in den Ruhezustand versetzen, während eine Anwendung wünscht dies zu verhindern</description>
+                <description xml:lang="el">Αδρανοποίηση του συστήματος ενώ μια εφαρμογή ζήτησε να αποτραπεί</description>
+                <description xml:lang="fr">Mettre le système en hibernation alors qu'une application a demandé de l'empêcher</description>
+                <description xml:lang="hu">A rendszer hibernálása miközben egy alkalmazás ennek meggátlását kérte</description>
+                <description xml:lang="it">Ibernare il sistema mentre un'applicazione chiede di inibirne l'azione</description>
+                <description xml:lang="pl">Hibernacja systemu, kiedy program zażądał jej wstrzymania</description>
+                <description xml:lang="pt_BR">Hibernar o sistema enquanto um aplicativo solicitou inibição</description>
+                <description xml:lang="ru">Перевести систему в спящий режим, несмотря на то, что приложение запросило блокировку</description>
+                <description xml:lang="sv">Försätt systemet i viloläge även då ett program hindrar det</description>
+                <description xml:lang="uk">Приспати систему, коли програми намагаються першкодити цьому</description>
+                <message>Authentication is required for hibernating the system while an application asked to inhibit it.</message>
+                <message xml:lang="de">Legitimierung ist zum Versetzen des System in den Ruhezustand notwendig, während eine Anwendung wünscht dies zu verhindern.</message>
+                <message xml:lang="el">Απαιτείται πιστοποίηση για αδρανοποίηση του συστήματος ενώ μια εφαρμογή ζήτησε να αποτραπεί.</message>
+                <message xml:lang="fr">Authentification requise pour mettre le système en hibernation alors qu'une application a demandé de l'empêcher.</message>
+                <message xml:lang="hu">Hitelesítés szükséges a rendszer hibernálásához miközben egy alkalmazás ennek meggátlását kérte.</message>
+                <message xml:lang="it">Autenticazione richiesta per ibernare il sistema mentre un'applicazione chiede di inibirne l'azione.</message>
+                <message xml:lang="pl">Wymagane jest uwierzytelnienie, aby zahibernować system, kiedy program zażądał jej wstrzymania.</message>
+                <message xml:lang="pt_BR">É necessária autenticação para hibernar o sistema enquanto um aplicativo solicitou inibição.</message>
+                <message xml:lang="ru">Чтобы перевести систему в спящий режим, несмотря на то, что приложение запросило блокировку, необходимо пройти аутентификацию.</message>
+                <message xml:lang="sv">Autentisering krävs för att försätta ett program i viloläge även då ett program hindrar det.</message>
+                <message xml:lang="uk">Засвідчення потрібно, щоб приспати систему, коли програми намагаються першкодити цьому.</message>
+                <defaults>
+                        <allow_any>auth_admin_keep</allow_any>
+                        <allow_inactive>auth_admin_keep</allow_inactive>
+                        <allow_active>auth_admin_keep</allow_active>
+                </defaults>
+                <annotate key="org.freedesktop.policykit.imply">org.freedesktop.login1.hibernate</annotate>
+        </action>
+
+</policyconfig>
\ No newline at end of file
diff --git a/SOURCES/org.freedesktop.machine1.policy b/SOURCES/org.freedesktop.machine1.policy
new file mode 100644
index 0000000..d7998b8
--- /dev/null
+++ b/SOURCES/org.freedesktop.machine1.policy
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE policyconfig PUBLIC "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
+        "http://www.freedesktop.org/standards/PolicyKit/1/policyconfig.dtd">
+<policyconfig>
+
+        <vendor>The systemd Project</vendor>
+        <vendor_url>http://www.freedesktop.org/wiki/Software/systemd</vendor_url>
+
+        <action id="org.freedesktop.machine1.login">
+                <description>Log into a local container</description>
+                <description xml:lang="de">In einem lokalen Container anmelden</description>
+                <description xml:lang="fr">Connexion dans un conteneur local</description>
+                <description xml:lang="hu">Bejelentkezés helyi konténerbe</description>
+                <description xml:lang="it">Accedi in un container locale</description>
+                <description xml:lang="pl">Logowanie do lokalnego kontenera</description>
+                <description xml:lang="pt_BR">Conectar a um contêiner local</description>
+                <description xml:lang="ru">Зайти в локальный контейнер</description>
+                <description xml:lang="sv">Logga till en lokal behållare</description>
+                <message>Authentication is required to log into a local container</message>
+                <message xml:lang="de">Legitimierung ist zum Anmelden in einem lokalen Container notwendig</message>
+                <message xml:lang="fr">Authentification requise pour permettre la connexion dans un conteneur local.</message>
+                <message xml:lang="hu">Hitelesítés szükséges a bejelentkezéshez egy helyi konténerbe.</message>
+                <message xml:lang="it">Autenticazione richiesta per accedere in un container locale</message>
+                <message xml:lang="pl">Wymagane jest uwierzytelnienie, aby zalogować się do lokalnego kontenera</message>
+                <message xml:lang="pt_BR">É necessária autenticação para se conectar a um contêiner local.</message>
+                <message xml:lang="sv">Autentisering krävs för att tillåta loggning till en lokal behållare.</message>
+                <defaults>
+                        <allow_any>auth_admin</allow_any>
+                        <allow_inactive>auth_admin</allow_inactive>
+                        <allow_active>auth_admin_keep</allow_active>
+                </defaults>
+        </action>
+
+</policyconfig>
\ No newline at end of file
diff --git a/SOURCES/org.freedesktop.systemd1.policy b/SOURCES/org.freedesktop.systemd1.policy
new file mode 100644
index 0000000..f7e013c
--- /dev/null
+++ b/SOURCES/org.freedesktop.systemd1.policy
@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE policyconfig PUBLIC "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
+        "http://www.freedesktop.org/standards/PolicyKit/1/policyconfig.dtd">
+<policyconfig>
+
+        <vendor>The systemd Project</vendor>
+        <vendor_url>http://www.freedesktop.org/wiki/Software/systemd</vendor_url>
+
+        <action id="org.freedesktop.systemd1.reply-password">
+                <description>Send passphrase back to system</description>
+                <description xml:lang="de">Passphrase zurück an das System senden</description>
+                <description xml:lang="el">Αποστολή του συνθηματικού πίσω στο σύστημα</description>
+                <description xml:lang="fr">Renvoyer la phrase secrète au système</description>
+                <description xml:lang="hu">Jelmondat visszaküldése a rendszernek</description>
+                <description xml:lang="it">Inviare la frase segreta (passphrase) al sistema</description>
+                <description xml:lang="pl">Wysłanie hasła z powrotem do systemu</description>
+                <description xml:lang="pt_BR">Enviar frase secreta de volta ao sistema</description>
+                <description xml:lang="ru">Отправить пароль системе</description>
+                <description xml:lang="sv">Skicka tillbaka lösenfras till system</description>
+                <description xml:lang="uk">Надіслати пароль назад у систему</description>
+                <message>Authentication is required to send the entered passphrase back to the system.</message>
+                <message xml:lang="de">Legitimierung ist zum Senden des eingegebenen Kennworts zurück an das System notwendig.</message>
+                <message xml:lang="el">Απαιτείται πιστοποίηση για αποστολή του εισερχόμενου συνθηματικού πίσω στο σύστημα.</message>
+                <message xml:lang="fr">Authentification requise pour renvoyer la phrase secrète au système.</message>
+                <message xml:lang="hu">Hitelesítés szükséges a bevitt jelmondat visszaküldéséhez a rendszernek.</message>
+                <message xml:lang="it">Autenticazione richiesta per inviare la frase segreta (passphrase) al sistema.</message>
+                <message xml:lang="pl">Wymagane jest uwierzytelnienie, aby wysłać podane hasło z powrotem do systemu.</message>
+                <message xml:lang="pt_BR">É necessária autenticação para enviar a frase secreta informada de volta ao sistema.</message>
+                <message xml:lang="ru">Чтобы отправить пароль системе, необходимо пройти аутентификацию.</message>
+                <message xml:lang="sv">Autentisering krävs för att skicka tillbaka den angivna lösenfrasen till systemet.</message>
+                <message xml:lang="uk">Засвідчення потрібно, щоб надіслати введений пароль назад у систему.</message>
+                <defaults>
+                        <allow_any>no</allow_any>
+                        <allow_inactive>no</allow_inactive>
+                        <allow_active>auth_admin_keep</allow_active>
+                </defaults>
+                <annotate key="org.freedesktop.policykit.exec.path">/usr/lib/systemd/systemd-reply-password</annotate>
+        </action>
+
+        <action id="org.freedesktop.systemd1.manage-units">
+                <description>Manage system services or units</description>
+                <description xml:lang="de">Systemdienste und Einheiten verwalten</description>
+                <description xml:lang="fr">Gérer les services système ou les unités</description>
+                <description xml:lang="hu">Rendszerszolgáltatások vagy -egységek kezelése</description>
+                <description xml:lang="it">Gestisci i servizi o le unità di sistema</description>
+                <description xml:lang="pl">Zarządzanie usługami lub jednostkami systemu</description>
+                <description xml:lang="pt_BR">Gerenciar unidades e serviços do sistema</description>
+                <description xml:lang="ru">Управление системными службами и юнитами</description>
+                <description xml:lang="sv">Hantera systemtjänster eller enheter</description>
+                <message>Authentication is required to manage system services or units.</message>
+                <message xml:lang="de">Legitimierung ist notwendig für die Verwaltung von Systemdiensten und Einheiten</message>
+                <message xml:lang="fr">Authentification requise pour gérer les services système ou les unités.</message>
+                <message xml:lang="hu">Hitelesítés szükséges a rendszerszolgáltatások vagy -egységek kezeléséhez.</message>
+                <message xml:lang="it">Autenticazione richiesta per gestire servizi e unità di sistema.</message>
+                <message xml:lang="pl">Wymagane jest uwierzytelnienie, aby zarządzać usługami lub jednostkami systemu.</message>
+                <message xml:lang="pt_BR">É necessária autenticação para gerenciar unidades e serviços do sistema.</message>
+                <message xml:lang="ru">Для управления системными службами и юнитами, необходимо пройти аутентификацию.</message>
+                <message xml:lang="sv">Autentisering krävs för att hantera systemtjänster eller enheter.</message>
+                <defaults>
+                        <allow_any>auth_admin</allow_any>
+                        <allow_inactive>auth_admin</allow_inactive>
+                        <allow_active>auth_admin_keep</allow_active>
+                </defaults>
+        </action>
+
+        <action id="org.freedesktop.systemd1.manage-unit-files">
+                <description>Manage system service or unit files</description>
+                <description xml:lang="de">Systemdienste und Einheitendateien verwalten</description>
+                <description xml:lang="fr">Gérer le service système ou ses fichiers unités</description>
+                <description xml:lang="hu">Rendszerszolgáltatás- vagy egységfájlok kezelése</description>
+                <description xml:lang="it">Gestisci i file dei servizi o delle unità di sistema</description>
+                <description xml:lang="pl">Zarządzanie plikami usług lub jednostek systemu</description>
+                <description xml:lang="pt_BR">Gerenciar arquivos de unidades e serviços do sistema</description>
+                <description xml:lang="ru">Управление файлами конфигурации системных служб и юнитов</description>
+                <description xml:lang="sv">Hantera systemtjänster eller enhetsfiler</description>
+                <message>Authentication is required to manage system service or unit files.</message>
+                <message xml:lang="de">Legitimierung ist notwendig für die Verwaltung von Systemdiensten und Einheitendateien.</message>
+                <message xml:lang="fr">Authentification requise pour gérer le service système ou ses fichiers unités.</message>
+                <message xml:lang="hu">Hitelesítés szükséges a rendszerszolgáltatás- vagy egységfájlok kezeléséhez.</message>
+                <message xml:lang="it">Autenticazione richiesta per gestire i file dei servizi o delle unità di sistema.</message>
+                <message xml:lang="pl">Wymagane jest uwierzytelnienie, aby zarządzać plikami usług lub jednostek systemu.</message>
+                <message xml:lang="pt_BR">É necessária autenticação para gerenciar arquivos "unit" e "service" do sistema.</message>
+                <message xml:lang="ru">Для управления файлами конфигурации системных служб и юнитов, необходимо пройти аутентификацию.</message>
+                <message xml:lang="sv">Autentisering krävs för att hantera systemtjänster eller enhetsfiler.</message>
+                <defaults>
+                        <allow_any>auth_admin</allow_any>
+                        <allow_inactive>auth_admin</allow_inactive>
+                        <allow_active>auth_admin_keep</allow_active>
+                </defaults>
+        </action>
+
+        <action id="org.freedesktop.systemd1.reload-daemon">
+                <description>Reload the systemd state</description>
+                <description xml:lang="de">Den systemd-Zustand neu laden</description>
+                <description xml:lang="fr">Recharger l'état de systemd</description>
+                <description xml:lang="hu">A systemd állapotának újratöltése</description>
+                <description xml:lang="it">Riavviare lo stato di systemd</description>
+                <description xml:lang="pl">Ponowne wczytanie stanu systemd</description>
+                <description xml:lang="pt_BR">Recarregar o estado do sistema</description>
+                <description xml:lang="ru">Перечитать конфигурацию systemd</description>
+                <description xml:lang="sv">Läs om tillståndet för systemd</description>
+                <message>Authentication is required to reload the systemd state.</message>
+                <message xml:lang="de">Legitimierung ist zum erneuten Laden des systemd-Zustands notwendig.</message>
+                <message xml:lang="fr">Authentification requise pour recharger l'état de systemd</message>
+                <message xml:lang="hu">Hitelesítés szükséges a systemd állapotának újratöltéséhez.</message>
+                <message xml:lang="it">Autenticazione richiesta per riavviare lo stato di sistemd.</message>
+                <message xml:lang="pl">Wymagane jest uwierzytelnienie, aby ponownie wczytać stan systemd.</message>
+                <message xml:lang="pt_BR">É necessária autenticação para recarregar o estado do sistema.</message>
+                <message xml:lang="ru">Чтобы заставить systemd перечитать конфигурацию, необходимо пройти аутентификацию.</message>
+                <message xml:lang="sv">Autentisering krävs för att läsa om tillståndet för systemd.</message>
+                <defaults>
+                        <allow_any>auth_admin</allow_any>
+                        <allow_inactive>auth_admin</allow_inactive>
+                        <allow_active>auth_admin_keep</allow_active>
+                </defaults>
+        </action>
+
+</policyconfig>
\ No newline at end of file
diff --git a/SOURCES/org.freedesktop.timedate1.policy b/SOURCES/org.freedesktop.timedate1.policy
new file mode 100644
index 0000000..e9f4c96
--- /dev/null
+++ b/SOURCES/org.freedesktop.timedate1.policy
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE policyconfig PUBLIC "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
+        "http://www.freedesktop.org/standards/PolicyKit/1/policyconfig.dtd">
+<policyconfig>
+
+        <vendor>The systemd Project</vendor>
+        <vendor_url>http://www.freedesktop.org/wiki/Software/systemd</vendor_url>
+
+        <action id="org.freedesktop.timedate1.set-time">
+                <description>Set system time</description>
+                <description xml:lang="de">Die Systemzeit festlegen</description>
+                <description xml:lang="el">Ορισμός ώρας συστήματος</description>
+                <description xml:lang="fr">Définir l'heure du système</description>
+                <description xml:lang="hu">Rendszeridő beállítása</description>
+                <description xml:lang="it">Configura l'orario di sistema</description>
+                <description xml:lang="pl">Ustawienie czasu systemu</description>
+                <description xml:lang="pt_BR">Definir horário do sistema</description>
+                <description xml:lang="ru">Настроить системное время</description>
+                <description xml:lang="sv">Ange systemtid</description>
+                <description xml:lang="uk">Вказати системний час</description>
+                <message>Authentication is required to set the system time.</message>
+                <message xml:lang="de">Legitimierung ist zum Festlegen der Systemzeit notwendig.</message>
+                <message xml:lang="el">Απαιτείται πιστοποίηση για να ορίσετε την ώρα του συστήματος.</message>
+                <message xml:lang="fr">Authentification requise pour définir l'heure du système.</message>
+                <message xml:lang="hu">Hitelesítés szükséges a rendszeridő beállításához.</message>
+                <message xml:lang="it">Autenticazione richiesta per configurare l'orario di sistema.</message>
+                <message xml:lang="pl">Wymagane jest uwierzytelnienie, aby ustawić czas systemu.</message>
+                <message xml:lang="pt_BR">É necessária autenticação para definir o horário do sistema.</message>
+                <message xml:lang="ru">Чтобы настроить системное время, необходимо пройти аутентификацию.</message>
+                <message xml:lang="sv">Autentisering krävs för ange systemtiden.</message>
+                <message xml:lang="uk">Засвідчення потрібно, щоб вказати системний час.</message>
+                <defaults>
+                        <allow_any>auth_admin_keep</allow_any>
+                        <allow_inactive>auth_admin_keep</allow_inactive>
+                        <allow_active>auth_admin_keep</allow_active>
+                </defaults>
+                <annotate key="org.freedesktop.policykit.imply">org.freedesktop.timedate1.set-timezone org.freedesktop.timedate1.set-ntp</annotate>
+        </action>
+
+        <action id="org.freedesktop.timedate1.set-timezone">
+                <description>Set system timezone</description>
+                <description xml:lang="de">Die Systemzeitzone festlegen</description>
+                <description xml:lang="el">Ορισμός ζώνης ώρας συστήματος</description>
+                <description xml:lang="fr">Définir le fuseau horaire du système</description>
+                <description xml:lang="hu">Rendszer időzónájának beállítása</description>
+                <description xml:lang="it">Configura il fuso orario di sistema</description>
+                <description xml:lang="pl">Ustawienie strefy czasowej systemu</description>
+                <description xml:lang="pt_BR">Definir fuso horário do sistema</description>
+                <description xml:lang="ru">Настроить часовой пояс</description>
+                <description xml:lang="sv">Ange systemets tidszon</description>
+                <description xml:lang="uk">Вказати системний часовий пояс</description>
+                <message>Authentication is required to set the system timezone.</message>
+                <message xml:lang="de">Legitimierung ist zum Festlegen der Systemzeitzone notwendig.</message>
+                <message xml:lang="el">Απαιτείται πιστοποίηση για να ορίσετε την ώρα ζώνης του συστήματος.</message>
+                <message xml:lang="fr">Authentification requise pour définir le fuseau horaire du système.</message>
+                <message xml:lang="hu">Hitelesítés szükséges a rendszer időzónájának beállításához.</message>
+                <message xml:lang="it">Autenticazione richiesta per configurare il fuso orario di sistema.</message>
+                <message xml:lang="pl">Wymagane jest uwierzytelnienie, aby ustawić strefę czasową systemu.</message>
+                <message xml:lang="pt_BR">É necessária autenticação para definir o fuso horário do sistema.</message>
+                <message xml:lang="ru">Чтобы настроить часовой пояс, необходимо пройти аутентификацию.</message>
+                <message xml:lang="sv">Autentisering krävs för att ange systemets tidszon.</message>
+                <message xml:lang="uk">Засвідчення потрібно, щоб вказати системний часовий пояс.</message>
+                <defaults>
+                        <allow_any>auth_admin_keep</allow_any>
+                        <allow_inactive>auth_admin_keep</allow_inactive>
+                        <allow_active>auth_admin_keep</allow_active>
+                </defaults>
+        </action>
+
+        <action id="org.freedesktop.timedate1.set-local-rtc">
+                <description>Set RTC to local timezone or UTC</description>
+                <description xml:lang="de">Echtzeituhr auf lokale Zeitzone oder UTC setzen</description>
+                <description xml:lang="el">Ορισμός RTC στην τοπική ζώνη ώρας ή UTC</description>
+                <description xml:lang="fr">Positionner l'horloge matérielle à l'heure locale ou sur le temps universel coordonné (UTC)</description>
+                <description xml:lang="hu">Az RTC beállítása helyi időzónára vagy UTC-re</description>
+                <description xml:lang="it">Configura l'orologio di sistema (RTC) al fuso orario locale o al tempo civile (UTC)</description>
+                <description xml:lang="pl">Ustawienie RTC na lokalną strefę czasową lub strefę UTC</description>
+                <description xml:lang="pt_BR">Definir o relógio do sistema (RTC) para fuso horário local ou UTC</description>
+                <description xml:lang="ru">Установить аппаратные часы по местному времени или по Гринвичу</description>
+                <description xml:lang="sv">Sätt realtidsklocka (RTC) till lokal tidszon eller koordinerad universell tid (UTC)</description>
+                <description xml:lang="uk">Вкажіть RTC для локального часового поясу або UTC</description>
+                <message>Authentication is required to control whether the RTC stores the local or UTC time.</message>
+                <message xml:lang="de">Legitimierung ist notwendig zum Festlegen, ob die Echtzeituhr auf lokale Zeitzone oder UTC eingestellt ist.</message>
+                <message xml:lang="el">Απαιτείται πιστοποίηση για να ελέγξετε αν το RTC αποθηκεύει την τοπική ή την ώρα UTC.</message>
+                <message xml:lang="fr">Authentification requise pour positionner l'horloge matérielle à l'heure locale ou sur le temps universel coordonné (UTC).</message>
+                <message xml:lang="hu">Hitelesítés szükséges az RTC beállításához a helyi időzóna vagy UTC tárolására.</message>
+                <message xml:lang="it">Autenticazione richiesta per verificare se l'orologio di sistema (RTC) è configurato all'orario locale o al tempo civile (UTC).</message>
+                <message xml:lang="pl">Wymagane jest uwierzytelnienie, aby kontrolować, czy RTC przechowuje czas lokalny lub czas UTC.</message>
+                <message xml:lang="pt_BR">É necessária autenticação para controlar se o RTC deve, ou não, armazenar o horário local ou de UTC.</message>
+                <message xml:lang="ru">Чтобы контролировать, установлены аппаратные часы по местному времени или по Гринвичу, необходимо пройти аутентификацию.</message>
+                <message xml:lang="sv">Autentisering krävs för att kunna kontrollera huruvida realtidsklockan (RTC) lagrar den lokala eller koordinerade universella tiden (UTC).</message>
+                <message xml:lang="uk">Засвідчення потрібно, щоб контролювати, чи RTC зберігає час, чи UTC.</message>
+                <defaults>
+                        <allow_any>auth_admin_keep</allow_any>
+                        <allow_inactive>auth_admin_keep</allow_inactive>
+                        <allow_active>auth_admin_keep</allow_active>
+                </defaults>
+        </action>
+
+        <action id="org.freedesktop.timedate1.set-ntp">
+                <description>Turn network time synchronization on or off</description>
+                <description xml:lang="de">Netzwerkzeitabgeich ein- oder ausschalten</description>
+                <description xml:lang="el">Ενεργοποίηση/Απενεργοποίηση συγχρονισμού ώρας δικτύου</description>
+                <description xml:lang="fr">Activer ou désactiver la synchronisation de l'heure avec le réseau</description>
+                <description xml:lang="hu">Hálózati időszinkronizáció be- vagy kikapcsolása</description>
+                <description xml:lang="it">Abilita o meno la sincronizzazione dell'orario in rete</description>
+                <description xml:lang="pl">Włączenie lub wyłączenie synchronizacji czasu przez sieć</description>
+                <description xml:lang="pt_BR">Ligar/desligar a sincronização do horário em rede</description>
+                <description xml:lang="ru">Включить или выключить синхронизацию времени по сети</description>
+                <description xml:lang="sv">Växla synkronisering av nätverkstid på och av</description>
+                <description xml:lang="uk">Увімкнути або вимкнути синхронізування через мережу</description>
+                <message>Authentication is required to control whether network time synchronization shall be enabled.</message>
+                <message xml:lang="de">Legitimierung ist zum Festlegen, ob Netzwerkzeitabgeich eingeschaltet sein soll, erforderlich.</message>
+                <message xml:lang="el">Απαιτείται πιστοποίηση για να ελέγξετε αν ο συγχρονισμός ώρας δικτύου θα ενεργοποιηθεί.</message>
+                <message xml:lang="fr">Authentification requise pour activer ou désactiver la synchronisation de l'heure avec le réseau.</message>
+                <message xml:lang="hu">Hitelesítés szükséges a hálózati időszinkronizáció engedélyezéséhez.</message>
+                <message xml:lang="it">Autenticazione richiesta per verificare se la sincronizzazione dell'orario in rete possa essere attivata.</message>
+                <message xml:lang="pl">Wymagane jest uwierzytelnienie, aby kontrolować, czy włączyć synchronizację czasu przez sieć.</message>
+                <message xml:lang="pt_BR">É necessária autenticação para controlar se deve ser habilitada, ou não, a sincronização de horário através de rede.</message>
+                <message xml:lang="ru">Чтобы включить или выключить синхронизацию времени по сети, необходимо пройти аутентификацию.</message>
+                <message xml:lang="sv">Autentisering krävs för att kontrollera huruvida synkronisering av nätverkstid ska vara aktiverat.</message>
+                <message xml:lang="uk">Засвідчення потрібно, щоб контролювати, чи синхронізування часу через мережу запущено.</message>
+                <defaults>
+                        <allow_any>auth_admin_keep</allow_any>
+                        <allow_inactive>auth_admin_keep</allow_inactive>
+                        <allow_active>auth_admin_keep</allow_active>
+                </defaults>
+        </action>
+
+</policyconfig>
\ No newline at end of file
diff --git a/SPECS/systemd.spec b/SPECS/systemd.spec
index debe9b3..95d164a 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:        19%{?dist}.13
+Release:        30%{?dist}
 # For a breakdown of the licensing, see README
 License:        LGPLv2+ and MIT and GPLv2+
 Summary:        A System and Service Manager
@@ -26,6 +26,13 @@ Source4:        rc.local
 Source5:        60-alias-kmsg.rules
 # Stop-gap, just to ensure things work fine with rsyslog without having to change the package right-away
 Source6:        listen.conf
+Source7:        org.freedesktop.hostname1.policy
+Source8:        org.freedesktop.import1.policy
+Source9:        org.freedesktop.locale1.policy
+Source10:       org.freedesktop.login1.policy
+Source11:       org.freedesktop.machine1.policy
+Source12:       org.freedesktop.systemd1.policy
+Source13:       org.freedesktop.timedate1.policy
 
 # RHEL-specific
 Patch0001: 0001-kernel-install-add-fedora-specific-callouts-to-new-k.patch
@@ -290,28 +297,151 @@ Patch0259: 0259-device-rework-how-we-enter-tentative-state.patch
 Patch0260: 0260-core-Do-not-bind-a-mount-unit-to-a-device-if-it-was-.patch
 Patch0261: 0261-logind-set-RemoveIPC-no-by-default.patch
 Patch0262: 0262-sysv-generator-follow-symlinks-in-etc-rc.d-init.d.patch
-Patch0263: 0263-man-RemoveIPC-is-set-to-no-on-rhel.patch
-Patch0264: 0264-makefile-disable-udev-tests.patch
-Patch0265: 0265-sysv-generator-test-always-log-to-console.patch
+Patch0263: 0263-sysv-generator-test-always-log-to-console.patch
+Patch0264: 0264-man-RemoveIPC-is-set-to-no-on-rhel.patch
+Patch0265: 0265-Avoid-tmp-being-mounted-as-tmpfs-without-the-user-s-.patch
 Patch0266: 0266-test-sysv-generator-Check-for-network-online.target.patch
-Patch0267: 0267-Avoid-tmp-being-mounted-as-tmpfs-without-the-user-s-.patch
-Patch0268: 0268-udev-fibre-channel-fix-NPIV-support.patch
-Patch0269: 0269-ata_id-unreverse-WWN-identifier.patch
-Patch0270: 0270-Fixup-WWN-bytes-for-big-endian-systems.patch
-Patch0271: 0271-Revert-udev-fibre-channel-fix-NPIV-support.patch
-Patch0272: 0272-udev-path-id-fibre-channel-NPIV-use-fc_vport-s-port_.patch
-Patch0273: 0273-rules-set-SYSTEMD_READY-0-on-DM_UDEV_DISABLE_OTHER_R.patch
-Patch0274: 0274-Revert-journald-turn-ForwardToSyslog-off-by-default.patch
-Patch0275: 0275-journal-fix-error-handling-when-compressing-journal-.patch
-Patch0276: 0276-journal-irrelevant-coding-style-fixes.patch
-Patch0277: 0277-fstab-generator-cescape-device-name-in-root-fsck-ser.patch
-Patch0278: 0278-manager-reduce-complexity-of-unit_gc_sweep-3507.patch
-Patch0279: 0279-core-use-an-AF_UNIX-SOCK_DGRAM-socket-for-cgroup-age.patch
-Patch0280: 0280-logind-process-session-inhibitor-fds-at-higher-prior.patch
-Patch0281: 0281-sd-event-expose-the-event-loop-iteration-counter-via.patch
-Patch0282: 0282-manager-Only-invoke-a-single-sigchld-per-unit-within.patch
-Patch0283: 0283-manager-Fixing-a-debug-printf-formatting-mistake.patch
-Patch0284: 0284-manager-don-t-skip-sigchld-handler-for-main-and-cont.patch
+Patch0267: 0267-makefile-disable-udev-tests.patch
+Patch0268: 0268-arm-aarch64-detect-virt-check-dmi.patch
+Patch0269: 0269-detect-virt-dmi-look-for-KVM.patch
+Patch0270: 0270-Revert-journald-turn-ForwardToSyslog-off-by-default.patch
+Patch0271: 0271-terminal-util-when-resetting-terminals-don-t-wait-fo.patch
+Patch0272: 0272-basic-terminal-util-introduce-SYSTEMD_COLORS-environ.patch
+Patch0273: 0273-ask-password-don-t-abort-when-message-is-missing.patch
+Patch0274: 0274-sysv-generator-do-not-join-dependencies-on-one-line-.patch
+Patch0275: 0275-udev-fibre-channel-fix-NPIV-support.patch
+Patch0276: 0276-ata_id-unreverse-WWN-identifier.patch
+Patch0277: 0277-Fixup-WWN-bytes-for-big-endian-systems.patch
+Patch0278: 0278-sd-journal-introduce-has_runtime_files-and-has_persi.patch
+Patch0279: 0279-journalctl-improve-error-messages-when-the-specified.patch
+Patch0280: 0280-journalctl-show-friendly-info-when-using-b-on-runtim.patch
+Patch0281: 0281-journalctl-make-journalctl-dev-sda-work.patch
+Patch0282: 0282-journalctl-add-match-for-the-current-boot-when-calle.patch
+Patch0283: 0283-man-clarify-what-happens-when-journalctl-is-called-w.patch
+Patch0284: 0284-core-downgrade-warning-about-duplicate-device-names.patch
+Patch0285: 0285-udev-downgrade-a-few-warnings-to-debug-messages.patch
+Patch0286: 0286-man-LEVEL-in-systemd-analyze-set-log-level-is-not-op.patch
+Patch0287: 0287-Revert-udev-fibre-channel-fix-NPIV-support.patch
+Patch0288: 0288-udev-path-id-fibre-channel-NPIV-use-fc_vport-s-port_.patch
+Patch0289: 0289-systemctl-is-active-failed-should-return-0-if-at-lea.patch
+Patch0290: 0290-rules-set-SYSTEMD_READY-0-on-DM_UDEV_DISABLE_OTHER_R.patch
+Patch0291: 0291-s390-add-personality-support.patch
+Patch0292: 0292-socket_address_listen-do-not-rely-on-errno.patch
+Patch0293: 0293-path_id-reintroduce-by-path-links-for-virtio-block-d.patch
+Patch0294: 0294-journal-fix-error-handling-when-compressing-journal-.patch
+Patch0295: 0295-journal-irrelevant-coding-style-fixes.patch
+Patch0296: 0296-install-follow-unit-file-symlinks-in-usr-but-not-etc.patch
+Patch0297: 0297-core-look-for-instance-when-processing-template-name.patch
+Patch0298: 0298-core-improve-error-message-when-starting-template-wi.patch
+Patch0299: 0299-man-tmpfiles.d-add-note-about-permissions-and-owners.patch
+Patch0300: 0300-tmpfiles-don-t-follow-symlinks-when-adjusting-ACLs-f.patch
+Patch0301: 0301-udev-filter-out-non-sensically-high-onboard-indexes-.patch
+Patch0302: 0302-test-execute-add-tests-for-RuntimeDirectory.patch
+Patch0303: 0303-core-fix-group-ownership-when-Group-is-set.patch
+Patch0304: 0304-fstab-generator-cescape-device-name-in-root-fsck-ser.patch
+Patch0305: 0305-core-add-new-RandomSec-setting-for-time-units.patch
+Patch0306: 0306-core-rename-Random-to-RandomizedDelay.patch
+Patch0307: 0307-journal-remote-change-owner-of-var-log-journal-remot.patch
+Patch0308: 0308-Add-Seal-option-in-the-configuration-file-for-journa.patch
+Patch0309: 0309-tests-fix-make-check-failure.patch
+Patch0310: 0310-device-make-sure-to-not-ignore-re-plugged-device.patch
+Patch0311: 0311-device-Ensure-we-have-sysfs-path-before-comparing.patch
+Patch0312: 0312-core-fix-memory-leak-on-set-default-enable-disable-e.patch
+Patch0313: 0313-nspawn-fix-minor-memory-leak.patch
+Patch0314: 0314-basic-fix-error-memleak-in-socket-util.patch
+Patch0315: 0315-core-fix-memory-leak-in-manager_run_generators.patch
+Patch0316: 0316-modules-load-fix-memory-leak.patch
+Patch0317: 0317-core-fix-memory-leak-on-failed-preset-all.patch
+Patch0318: 0318-sd-bus-fix-memory-leak-in-test-bus-chat.patch
+Patch0319: 0319-core-fix-memory-leak-in-transient-units.patch
+Patch0320: 0320-bus-fix-leak-in-error-path.patch
+Patch0321: 0321-shared-logs-show-fix-memleak-in-add_matches_for_unit.patch
+Patch0322: 0322-logind-introduce-LockedHint-and-SetLockedHint-3238.patch
+Patch0323: 0323-import-use-the-old-curl-api.patch
+Patch0324: 0324-importd-drop-dkr-support.patch
+Patch0325: 0325-import-add-support-for-gpg2-for-verifying-imported-i.patch
+Patch0326: 0326-nspawn-when-connected-to-pipes-for-stdin-stdout-pass.patch
+Patch0327: 0327-mount-remove-obsolete-n.patch
+Patch0328: 0328-core-don-t-log-job-status-message-in-case-job-was-ef.patch
+Patch0329: 0329-core-use-an-AF_UNIX-SOCK_DGRAM-socket-for-cgroup-age.patch
+Patch0330: 0330-logind-process-session-inhibitor-fds-at-higher-prior.patch
+Patch0331: 0331-Teach-bus_append_unit_property_assignment-about-Dele.patch
+Patch0332: 0332-sd-netlink-fix-deep-recursion-in-message-destruction.patch
+Patch0333: 0333-add-REMOTE_ADDR-and-REMOTE_PORT-for-Accept-yes.patch
+Patch0334: 0334-core-don-t-dispatch-load-queue-when-setting-Slice-fo.patch
+Patch0335: 0335-run-make-slice-work-in-conjunction-with-scope.patch
+Patch0336: 0336-myhostname-fix-timeout-if-ipv6-is-disabled.patch
+Patch0337: 0337-readahead-do-not-increase-nr_requests-for-root-fs-bl.patch
+Patch0338: 0338-manager-reduce-complexity-of-unit_gc_sweep-3507.patch
+Patch0339: 0339-hwdb-selinuxify-a-bit-3460.patch
+Patch0340: 0340-udevadm-explicitly-relabel-etc-udev-hwdb.bin-after-r.patch
+Patch0341: 0341-systemctl-return-diffrent-error-code-if-service-exis.patch
+Patch0342: 0342-systemctl-Replace-init-script-error-codes-with-enum-.patch
+Patch0343: 0343-systemctl-rework-systemctl-status-a-bit.patch
+Patch0344: 0344-journal-verify-don-t-hit-SIGFPE-when-determining-pro.patch
+Patch0345: 0345-journal-avoid-mapping-empty-data-and-field-hash-tabl.patch
+Patch0346: 0346-journal-when-verifying-journal-files-handle-empty-on.patch
+Patch0347: 0347-journal-explain-the-error-when-we-find-a-non-DATA-ob.patch
+Patch0348: 0348-journalctl-properly-detect-empty-journal-files.patch
+Patch0349: 0349-journal-uppercase-first-character-in-verify-error-me.patch
+Patch0350: 0350-journalctl-make-sure-journalctl-f-t-unmatched-blocks.patch
+Patch0351: 0351-journalctl-don-t-print-No-entries-in-quiet-mode.patch
+Patch0352: 0352-sd-event-expose-the-event-loop-iteration-counter-via.patch
+Patch0353: 0353-manager-Only-invoke-a-single-sigchld-per-unit-within.patch
+Patch0354: 0354-manager-Fixing-a-debug-printf-formatting-mistake.patch
+Patch0355: 0355-core-support-IEC-suffixes-for-RLIMIT-stuff.patch
+Patch0356: 0356-core-accept-time-units-for-time-based-resource-limit.patch
+Patch0357: 0357-time-util-add-parse_time-which-is-like-parse_sec-but.patch
+Patch0358: 0358-core-support-soft-hard-ranges-for-RLIMIT-options.patch
+Patch0359: 0359-core-fix-rlimit-parsing.patch
+Patch0360: 0360-core-dump-rlim_cur-too.patch
+Patch0361: 0361-install-fix-disable-via-unit-file-path.patch
+Patch0362: 0362-manager-don-t-skip-sigchld-handler-for-main-and-cont.patch
+Patch0363: 0363-units-increase-watchdog-timeout-to-3min-for-all-our-.patch
+Patch0364: 0364-core-bump-net.unix.max_dgram_qlen-really-early-durin.patch
+Patch0365: 0365-core-fix-priority-ordering-in-notify-handling.patch
+Patch0366: 0366-tests-fix-personality-tests-on-ppc64-and-aarch64.patch
+Patch0367: 0367-systemctl-consider-service-running-only-when-it-is-i.patch
+Patch0368: 0368-install-do-not-crash-when-processing-empty-masked-un.patch
+Patch0369: 0369-Revert-install-fix-disable-via-unit-file-path.patch
+Patch0370: 0370-systemctl-allow-disable-on-the-unit-file-path-but-wa.patch
+Patch0371: 0371-tmpfiles-enforce-ordering-when-executing-lines.patch
+Patch0372: 0372-Introduce-bus_unit_check_load_state-helper.patch
+Patch0373: 0373-core-use-bus_unit_check_load_state-in-transaction_ad.patch
+Patch0374: 0374-udev-path_id-correct-segmentation-fault-due-to-missi.patch
+Patch0375: 0375-rules-load-sg-driver-also-when-scsi_target-appears-4.patch
+Patch0376: 0376-fix-gcc-warnings-about-uninitialized-variables.patch
+Patch0377: 0377-journalctl-rework-code-that-checks-whether-we-have-a.patch
+Patch0378: 0378-journalctl-Improve-boot-ID-lookup.patch
+Patch0379: 0379-journalctl-only-have-a-single-exit-path-from-main.patch
+Patch0380: 0380-journalctl-free-all-command-line-argument-objects.patch
+Patch0381: 0381-journalctl-rename-boot_id_t-to-BootId.patch
+Patch0382: 0382-util-introduce-CMSG_FOREACH-macro-and-make-use-of-it.patch
+Patch0383: 0383-journald-don-t-employ-inner-loop-for-reading-from-in.patch
+Patch0384: 0384-journald-fix-count-of-object-meta-fields.patch
+Patch0385: 0385-journal-cat-return-a-correct-error-not-1.patch
+Patch0386: 0386-journalctl-introduce-short-options-for-since-and-unt.patch
+Patch0387: 0387-journal-s-Envalid-Invalid.patch
+Patch0388: 0388-journald-dispatch-SIGTERM-SIGINT-with-a-low-priority.patch
+Patch0389: 0389-lz4-fix-size-check-which-had-no-chance-of-working-on.patch
+Patch0390: 0390-journal-normalize-priority-of-logging-sources.patch
+Patch0391: 0391-Fix-miscalculated-buffer-size-and-uses-of-size-unlim.patch
+Patch0392: 0392-journal-Drop-monotonicity-check-when-appending-to-jo.patch
+Patch0393: 0393-journalctl-unify-how-we-free-boot-id-lists-a-bit.patch
+Patch0394: 0394-journalctl-don-t-trust-the-per-field-entry-tables-wh.patch
+Patch0395: 0395-units-remove-udev-control-socket-when-systemd-stops-.patch
+Patch0396: 0396-logind-don-t-assert-if-the-slice-is-missing.patch
+Patch0397: 0397-core-enable-transient-unit-support-for-slice-units.patch
+Patch0398: 0398-sd-bus-bump-message-queue-size.patch
+Patch0399: 0399-install-fix-disable-when-etc-systemd-system-is-a-sym.patch
+Patch0400: 0400-rules-add-NVMe-rules-3136.patch
+Patch0401: 0401-rules-introduce-disk-by-id-model_serial-symlinks-for.patch
+Patch0402: 0402-rules-fix-for-possible-whitespace-in-the-model-attri.patch
+Patch0403: 0403-systemctl-pid1-do-not-warn-about-missing-install-inf.patch
+Patch0404: 0404-systemctl-core-ignore-masked-units-in-preset-all.patch
+Patch0405: 0405-shared-install-handle-dangling-aliases-as-an-explici.patch
+Patch0406: 0406-shared-install-ignore-unit-symlinks-when-doing-prese.patch
+Patch0407: 0407-40-redhat.rules-don-t-hoplug-memory-on-s390x.patch
 
 
 %global num_patches %{lua: c=0; for i,p in ipairs(patches) do c=c+1; end; print(c);}
@@ -329,6 +459,8 @@ BuildRequires:  glib2-devel
 BuildRequires:  gobject-introspection-devel
 BuildRequires:  libblkid-devel
 BuildRequires:  xz-devel
+BuildRequires:  zlib-devel
+BuildRequires:  bzip2-devel
 BuildRequires:  libidn-devel
 BuildRequires:  libcurl-devel
 BuildRequires:  kmod-devel
@@ -354,7 +486,6 @@ BuildRequires:  autoconf
 BuildRequires:  libtool
 BuildRequires:  git
 BuildRequires:  libmount-devel
-BuildRequires:  tree
 
 Requires(post): coreutils
 Requires(post): gawk
@@ -415,6 +546,7 @@ License:        LGPLv2+ and MIT
 Requires:       %{name} = %{version}-%{release}
 Provides:       libudev-devel = %{version}
 Obsoletes:      libudev-devel < 183
+Requires:       %{name}-libs = %{version}-%{release}
 
 %description devel
 Development headers and auxiliary files for developing applications for systemd.
@@ -431,6 +563,7 @@ SysV compatibility tools for systemd
 Summary:        Python 2 bindings for systemd
 License:        LGPLv2+
 Requires:       %{name} = %{version}-%{release}
+Requires:       %{name}-libs = %{version}-%{release}
 
 %description python
 This package contains bindings which allow Python 2 programs to use
@@ -441,6 +574,7 @@ Summary:        Libraries for adding libudev support to applications that use gl
 Conflicts:      filesystem < 3
 License:        LGPLv2+
 Requires:       %{name}-libs = %{version}-%{release}
+Requires:       glib2 >= 2.42
 
 %description -n libgudev1
 This package contains the libraries that make it easier to use libudev
@@ -555,7 +689,6 @@ CONFIGURE_OPTS=(
 --disable-timesyncd
 --disable-kdbus
 --disable-terminal
---disable-importd
 --enable-gtk-doc
 --enable-compat-libs
 --disable-sysusers
@@ -566,6 +699,7 @@ CONFIGURE_OPTS=(
 )
 
 
+RPM_OPT_FLAGS="$RPM_OPT_FLAGS -O0"
 %configure "${CONFIGURE_OPTS[@]}"
 make %{?_smp_mflags} GCC_COLORS="" V=1
 
@@ -575,6 +709,15 @@ make %{?_smp_mflags} GCC_COLORS="" V=1
 find %{buildroot} \( -name '*.a' -o -name '*.la' \) -delete
 sed -i 's/L+/#/' %{buildroot}/usr/lib/tmpfiles.d/etc.conf
 
+rm -f %{buildroot}%{_datadir}/polkit-1/actions/org.freedesktop.*.policy
+install -m 0644 %{SOURCE7} %{buildroot}%{_datadir}/polkit-1/actions/
+install -m 0644 %{SOURCE8} %{buildroot}%{_datadir}/polkit-1/actions/
+install -m 0644 %{SOURCE9} %{buildroot}%{_datadir}/polkit-1/actions/
+install -m 0644 %{SOURCE10} %{buildroot}%{_datadir}/polkit-1/actions/
+install -m 0644 %{SOURCE11} %{buildroot}%{_datadir}/polkit-1/actions/
+install -m 0644 %{SOURCE12} %{buildroot}%{_datadir}/polkit-1/actions/
+install -m 0644 %{SOURCE13} %{buildroot}%{_datadir}/polkit-1/actions/
+
 # udev links
 mkdir -p %{buildroot}/%{_sbindir}
 ln -sf ../bin/udevadm %{buildroot}%{_sbindir}/udevadm
@@ -718,8 +861,8 @@ getent group floppy >/dev/null 2>&1 || groupadd -r -g 19 floppy >/dev/null 2>&1 
 getent group systemd-journal >/dev/null 2>&1 || groupadd -r -g 190 systemd-journal 2>&1 || :
 getent group systemd-bus-proxy >/dev/null 2>&1 || groupadd -r systemd-bus-proxy 2>&1 || :
 getent passwd systemd-bus-proxy >/dev/null 2>&1 || useradd -r -l -g systemd-bus-proxy -d / -s /sbin/nologin -c "systemd Bus Proxy" systemd-bus-proxy >/dev/null 2>&1 || :
-getent group systemd-network >/dev/null 2>&1 || groupadd -r systemd-network 2>&1 || :
-getent passwd systemd-network >/dev/null 2>&1 || useradd -r -l -g systemd-network -d / -s /sbin/nologin -c "systemd Network Management" systemd-network >/dev/null 2>&1 || :
+getent group systemd-network >/dev/null 2>&1 || groupadd -r -g 192 systemd-network 2>&1 || :
+getent passwd systemd-network >/dev/null 2>&1 || useradd -r -u 192 -l -g systemd-network -d / -s /sbin/nologin -c "systemd Network Management" systemd-network >/dev/null 2>&1 || :
 
 systemctl stop systemd-udevd-control.socket systemd-udevd-kernel.socket systemd-udevd.service >/dev/null 2>&1 || :
 
@@ -929,8 +1072,9 @@ getent group systemd-journal-gateway >/dev/null 2>&1 || groupadd -r -g 191 syste
 getent passwd systemd-journal-gateway >/dev/null 2>&1 || useradd -r -l -u 191 -g systemd-journal-gateway -d %{_localstatedir}/log/journal -s /sbin/nologin -c "Journal Gateway" systemd-journal-gateway >/dev/null 2>&1 || :
 getent group systemd-journal-remote >/dev/null 2>&1 || groupadd -r systemd-journal-remote 2>&1 || :
 getent passwd systemd-journal-remote >/dev/null 2>&1 || useradd -r -l -g systemd-journal-remote -d /%{_localstatedir}/log/journal/remote -s /sbin/nologin -c "Journal Remote" systemd-journal-remote >/dev/null 2>&1 || :
+getent group systemd-journal >/dev/null 2>&1 || groupadd -r -g 190 systemd-journal 2>&1 || :
 getent group systemd-journal-upload >/dev/null 2>&1 || groupadd -r systemd-journal-upload 2>&1 || :
-getent passwd systemd-journal-upload >/dev/null 2>&1 || useradd -r -l -g systemd-journal-upload -d /%{_localstatedir}/log/journal/upload -s /sbin/nologin -c "Journal Upload" systemd-journal-upload >/dev/null 2>&1 || :
+getent passwd systemd-journal-upload >/dev/null 2>&1 || useradd -r -l -g systemd-journal-upload -G systemd-journal -d /%{_localstatedir}/log/journal/upload -s /sbin/nologin -c "Journal Upload" systemd-journal-upload >/dev/null 2>&1 || :
 
 %post journal-gateway
 %systemd_post systemd-journal-gatewayd.socket systemd-journal-gatewayd.service
@@ -957,8 +1101,8 @@ getent passwd systemd-journal-upload >/dev/null 2>&1 || useradd -r -l -g systemd
 %systemd_postun_with_restart systemd-networkd.service systemd-networkd-wait-online.service
 
 %pre resolved
-getent group systemd-resolve >/dev/null 2>&1 || groupadd -r systemd-resolve 2>&1 || :
-getent passwd systemd-resolve >/dev/null 2>&1 || useradd -r -l -g systemd-resolve -d / -s /sbin/nologin -c "systemd Resolver" systemd-resolve >/dev/null 2>&1 || :
+getent group systemd-resolve >/dev/null 2>&1 || groupadd -r -g 193 systemd-resolve 2>&1 || :
+getent passwd systemd-resolve >/dev/null 2>&1 || useradd -r -u 193 -l -g systemd-resolve -d / -s /sbin/nologin -c "systemd Resolver" systemd-resolve >/dev/null 2>&1 || :
 
 %post resolved
 %systemd_post systemd-resolved.service
@@ -1020,6 +1164,7 @@ getent passwd systemd-resolve >/dev/null 2>&1 || useradd -r -l -g systemd-resolv
 %config(noreplace) %{_sysconfdir}/dbus-1/system.d/org.freedesktop.locale1.conf
 %config(noreplace) %{_sysconfdir}/dbus-1/system.d/org.freedesktop.timedate1.conf
 %config(noreplace) %{_sysconfdir}/dbus-1/system.d/org.freedesktop.machine1.conf
+%config(noreplace) %{_sysconfdir}/dbus-1/system.d/org.freedesktop.import1.conf
 %config(noreplace) %{_sysconfdir}/systemd/system.conf
 %config(noreplace) %{_sysconfdir}/systemd/user.conf
 %config(noreplace) %{_sysconfdir}/systemd/logind.conf
@@ -1094,6 +1239,7 @@ getent passwd systemd-resolve >/dev/null 2>&1 || useradd -r -l -g systemd-resolv
 %exclude %{_prefix}/lib/systemd/systemd-resolve-host
 %exclude %{_prefix}/lib/systemd/systemd-journal-upload
 %{_prefix}/lib/systemd/systemd-*
+%{_prefix}/lib/systemd/import-pubring.gpg
 %{_prefix}/lib/udev
 %exclude  %{_sysconfdir}/udev/rules.d/80-net-setup-link.rules
 %{_prefix}/lib/tmpfiles.d/systemd.conf
@@ -1143,6 +1289,7 @@ getent passwd systemd-resolve >/dev/null 2>&1 || useradd -r -l -g systemd-resolv
 %{_datadir}/dbus-1/system-services/org.freedesktop.locale1.service
 %{_datadir}/dbus-1/system-services/org.freedesktop.timedate1.service
 %{_datadir}/dbus-1/system-services/org.freedesktop.machine1.service
+%{_datadir}/dbus-1/system-services/org.freedesktop.import1.service
 %dir %{_datadir}/polkit-1
 %dir %{_datadir}/polkit-1/actions
 %{_datadir}/polkit-1/actions/org.freedesktop.systemd1.policy
@@ -1151,6 +1298,7 @@ getent passwd systemd-resolve >/dev/null 2>&1 || useradd -r -l -g systemd-resolv
 %{_datadir}/polkit-1/actions/org.freedesktop.locale1.policy
 %{_datadir}/polkit-1/actions/org.freedesktop.timedate1.policy
 %{_datadir}/polkit-1/actions/org.freedesktop.machine1.policy
+%{_datadir}/polkit-1/actions/org.freedesktop.import1.policy
 %{_libdir}/pkgconfig/systemd.pc
 %{_datadir}/pkgconfig/udev.pc
 %{_datadir}/bash-completion/completions/*
@@ -1272,56 +1420,174 @@ getent passwd systemd-resolve >/dev/null 2>&1 || useradd -r -l -g systemd-resolv
 %{_mandir}/man8/systemd-resolved.*
 
 %changelog
-* Wed Jul 27 2016 Lukas Nykryn <lnykryn@redhat.com> - 219-19.13
-- core: use an AF_UNIX/SOCK_DGRAM socket for cgroup agent notification (#1305608)
-- logind: process session/inhibitor fds at higher priority (#1305608)
+* Tue Sep 13 2016 Lukas Nykryn <lnykryn@redhat.com> - 219-30
+- systemctl,pid1: do not warn about missing install info with "preset" (#1373950)
+- systemctl/core: ignore masked units in preset-all (#1375097)
+- shared/install: handle dangling aliases as an explicit case, report nicely (#1375097)
+- shared/install: ignore unit symlinks when doing preset-all (#1375097)
+- 40-redhat.rules: don't hoplug memory on s390x (#1370161)
+
+* Mon Sep 05 2016 Lukas Nykryn <lnykryn@redhat.com> - 219-29
+- fix gcc warnings about uninitialized variables (#1318994)
+- journalctl: rework code that checks whether we have access to /var/log/journal (#1318994)
+- journalctl: Improve boot ID lookup (#1318994)
+- journalctl: only have a single exit path from main() (#1318994)
+- journalctl: free all command line argument objects (#1318994)
+- journalctl: rename boot_id_t to BootId (#1318994)
+- util: introduce CMSG_FOREACH() macro and make use of it everywhere (#1318994)
+- journald: don't employ inner loop for reading from incoming sockets (#1318994)
+- journald: fix count of object meta fields (#1318994)
+- journal-cat: return a correct error, not -1 (#1318994)
+- journalctl: introduce short options for --since and --until (#1318994)
+- journal: s/Envalid/Invalid/ (#1318994)
+- journald: dispatch SIGTERM/SIGINT with a low priority (#1318994)
+- lz4: fix size check which had no chance of working on big-endian (#1318994)
+- journal: normalize priority of logging sources (#1318994)
+- Fix miscalculated buffer size and uses of size-unlimited sprintf() function. (#1318994)
+- journal: Drop monotonicity check when appending to journal file (#1318994)
+- journalctl: unify how we free boot id lists a bit (#1318994)
+- journalctl: don't trust the per-field entry tables when looking for boot IDs (#1318994)
+- units: remove udev control socket when systemd stops the socket unit (#49) (#1370133)
+- logind: don't assert if the slice is missing (#1371437)
+- core: enable transient unit support for slice units (#1370299)
+- sd-bus: bump message queue size (#1371205)
+- install: fix disable when /etc/systemd/system is a symlink (#1285996)
+- rules: add NVMe rules (#3136) (#1274651)
+- rules: introduce disk/by-id (model_serial) symlinks for NVMe drives (#3974) (#1274651)
+- rules: fix for possible whitespace in the "model" attribute (#1274651)
+
+* Fri Aug 19 2016 Lukas Nykryn <lnykryn@redhat.com> - 219-27
+- tmpfiles: enforce ordering when executing lines (#1365870)
+- Introduce bus_unit_check_load_state() helper (#1256858)
+- core: use bus_unit_check_load_state() in transaction_add_job_and_dependencies() (#1256858)
+- udev/path_id: correct segmentation fault due to missing NULL check (#1365556)
+- rules: load sg driver also when scsi_target appears (#45) (#1322773)
+
+* Tue Aug 09 2016 Lukas Nykryn <lnykryn@redhat.com> - 219-26
+- install: do not crash when processing empty (masked) unit file (#1159308)
+- Revert "install: fix disable via unit file path" (#1348208)
+- systemctl: allow disable on the unit file path, but warn about it (#3806) (#1348208)
+
+* Thu Aug 04 2016 Lukas Nykryn <lnykryn@redhat.com> - 219-25
+- units: increase watchdog timeout to 3min for all our services (#1267707)
+- core: bump net.unix.max_dgram_qlen really early during boot (#1267707)
+- core: fix priority ordering in notify-handling (#1267707)
+- tests: fix personality tests on ppc64 and aarch64 (#1361049)
+- systemctl: consider service running only when it is in active or reloading state (#3874) (#1362461)
+
+* Mon Jul 18 2016 Lukas Nykryn <lnykryn@redhat.com> - 219-24
+- manager: don't skip sigchld handler for main and control pid for services (#3738) (#1342173)
+
+* Tue Jul 12 2016 Lukas Nykryn <lnykryn@redhat.com> - 219-23
+- udevadm: explicitly relabel /etc/udev/hwdb.bin after rename (#1350756)
+- systemctl: return diffrent error code if service exist or not (#3385) (#1047466)
+- systemctl: Replace init script error codes with enum (#3400) (#1047466)
+- systemctl: rework "systemctl status" a bit (#1047466)
+- journal-verify: don't hit SIGFPE when determining progress (#1350232)
+- journal: avoid mapping empty data and field hash tables (#1350232)
+- journal: when verifying journal files, handle empty ones nicely (#1350232)
+- journal: explain the error when we find a non-DATA object that is compressed (#1350232)
+- journalctl: properly detect empty journal files (#1350232)
+- journal: uppercase first character in verify error messages (#1350232)
+- journalctl: make sure 'journalctl -f -t unmatched' blocks (#1350232)
+- journalctl: don't print -- No entries -- in quiet mode (#1350232)
 - sd-event: expose the event loop iteration counter via sd_event_get_iteration() (#1342173)
 - manager: Only invoke a single sigchld per unit within a cleanup cycle (#1342173)
 - manager: Fixing a debug printf formatting mistake (#1342173)
-- manager: don't skip sigchld handler for main and control pid for services (#3738) (#1342173)
-
-* Tue Jun 14 2016 Lukas Nykryn <lnykryn@redhat.com> - 219-19.12
+- core: support IEC suffixes for RLIMIT stuff (#1351415)
+- core: accept time units for time-based resource limits (#1351415)
+- time-util: add parse_time(), which is like parse_sec() but allows specification of default time unit if none is specified (#1351415)
+- core: support <soft:hard> ranges for RLIMIT options (#1351415)
+- core: fix rlimit parsing (#1351415)
+- core: dump rlim_cur too (#1351415)
+- install: fix disable via unit file path (#1348208)
+
+* Wed Jun 22 2016 Lukas Nykryn <lnykryn@redhat.com> - 219-22
+- nspawn: when connected to pipes for stdin/stdout, pass them as-is to PID 1 (#1307080)
+- mount: remove obsolete -n (#1339721)
+- core: don't log job status message in case job was effectively NOP (#3199) (#1280014)
+- core: use an AF_UNIX/SOCK_DGRAM socket for cgroup agent notification (#1305608)
+- logind: process session/inhibitor fds at higher priority (#1305608)
+- Teach bus_append_unit_property_assignment() about 'Delegate' property (#1337922)
+- sd-netlink: fix deep recursion in message destruction (#1330593)
+- add REMOTE_ADDR and REMOTE_PORT for Accept=yes (#1341154)
+- core: don't dispatch load queue when setting Slice= for transient units (#1343904)
+- run: make --slice= work in conjunction with --scope (#1343904)
+- myhostname: fix timeout if ipv6 is disabled (#1330973)
+- readahead: do not increase nr_requests for root fs block device (#1314559)
 - manager: reduce complexity of unit_gc_sweep (#3507) (#1344556)
+- hwdb: selinuxify a bit (#3460) (#1343648)
 
-* Thu May 26 2016 Lukas Nykryn <lnykryn@redhat.com> - 219-19.11
-- fstab-generator: cescape device name in root-fsck service (#1306126)
-
-* Tue May 24 2016 Lukáš Nykrýn <lnykryn@redhat.com> - 219-19.10
-- get rid of ldconfig.service (#1338892)
-
-* Thu Apr 28 2016 Lukas Nykryn <lnykryn@redhat.com> - 219-19.9
+* Mon May 23 2016 Lukas Nykryn <lnykryn@redhat.com> - 219-21
+- path_id: reintroduce by-path links for virtio block devices (#952567)
 - journal: fix error handling when compressing journal objects (#1292447)
 - journal: irrelevant coding style fixes (#1292447)
-
-* Wed Apr 20 2016 Lukas Nykryn <lnykryn@redhat.com> - 219-19.8
+- install: follow unit file symlinks in /usr, but not /etc when looking for [Install] data (#1159308)
+- core: look for instance when processing template name (#1159308)
+- core: improve error message when starting template without instance (#1142369)
+- man/tmpfiles.d: add note about permissions and ownership of symlinks (#1296288)
+- tmpfiles: don't follow symlinks when adjusting ACLs, fille attributes, access modes or ownership (#1296288)
+- udev: filter out non-sensically high onboard indexes reported by the kernel (#1230210)
+- test-execute: add tests for RuntimeDirectory (#1324826)
+- core: fix group ownership when Group is set (#1324826)
+- fstab-generator: cescape device name in root-fsck service (#1306126)
+- core: add new RandomSec= setting for time units (#1305279)
+- core: rename Random* to RandomizedDelay* (#1305279)
+- journal-remote: change owner of /var/log/journal/remote and create /var/lib/systemd/journal-upload (#1327303)
+- Add Seal option in the configuration file for journald-remote (#1329233)
+- tests: fix make check failure (#1159308)
+- device: make sure to not ignore re-plugged device (#1332606)
+- device: Ensure we have sysfs path before comparing. (#1332606)
+- core: fix memory leak on set-default, enable, disable etc (#1331667)
+- nspawn: fix minor memory leak (#1331667)
+- basic: fix error/memleak in socket-util (#1331667)
+- core: fix memory leak in manager_run_generators() (#1331667)
+- modules-load: fix memory leak (#1331667)
+- core: fix memory leak on failed preset-all (#1331667)
+- sd-bus: fix memory leak in test-bus-chat (#1331667)
+- core: fix memory leak in transient units (#1331667)
+- bus: fix leak in error path (#1331667)
+- shared/logs-show: fix memleak in add_matches_for_unit (#1331667)
+- logind: introduce LockedHint and SetLockedHint (#3238) (#1335499)
+- import: use the old curl api (#1284974)
+- importd: drop dkr support (#1284974)
+- import: add support for gpg2 for verifying imported images (#1284974)
+
+* Thu Mar 10 2016 Lukas Nykryn <lnykryn@redhat.com> - 219-20
+- run: synchronously wait until the scope unit we create is started (#1272368)
+- device: rework how we enter tentative state (#1283579)
+- core: Do not bind a mount unit to a device, if it was from mountinfo (#1283579)
+- logind: set RemoveIPC=no by default (#1284588)
+- sysv-generator: follow symlinks in /etc/rc.d/init.d (#1285492)
+- sysv-generator test: always log to console (#1279034)
+- man: RemoveIPC is set to no on rhel (#1284588)
+- Avoid /tmp being mounted as tmpfs without the user's will (#1298109)
+- test sysv-generator: Check for network-online.target. (#1279034)
+- arm/aarch64: detect-virt: check dmi (#1278165)
+- detect-virt: dmi: look for KVM (#1278165)
 - Revert "journald: turn ForwardToSyslog= off by default" (#1285642)
-
-* Fri Mar 04 2016 Lukas Nykryn <lnykryn@redhat.com> - 219-19.7
+- terminal-util: when resetting terminals, don't wait for carrier (#1266745)
+- basic/terminal-util: introduce SYSTEMD_COLORS environment variable (#1247963)
+- ask-password: don't abort when message is missing (#1261136)
+- sysv-generator: do not join dependencies on one line, split them (#1288600)
+- udev: fibre channel: fix NPIV support (#1266934)
+- ata_id: unreverse WWN identifier (#1273306)
+- Fixup WWN bytes for big-endian systems (#1273306)
+- sd-journal: introduce has_runtime_files and has_persistent_files (#1082179)
+- journalctl: improve error messages when the specified boot is not found (#1082179)
+- journalctl: show friendly info when using -b on runtime journal only (#1082179)
+- journalctl: make "journalctl /dev/sda" work (#947636)
+- journalctl: add match for the current boot when called with devpath (#947636)
+- man: clarify what happens when journalctl is called with devpath (#947636)
+- core: downgrade warning about duplicate device names (#1296249)
+- udev: downgrade a few warnings to debug messages (#1289461)
+- man: LEVEL in systemd-analyze set-log level is not optional (#1268336)
 - Revert "udev: fibre channel: fix NPIV support" (#1266934)
 - udev: path-id: fibre channel NPIV - use fc_vport's port_name (#1266934)
+- systemctl: is-active/failed should return 0 if at least one unit is in given state (#1254650)
 - rules: set SYSTEMD_READY=0 on DM_UDEV_DISABLE_OTHER_RULES_FLAG=1 only with ADD event (#1312011)
-
-* Thu Feb 25 2016 Lukas Nykryn <lnykryn@redhat.com> - 219-19.6
-- ata_id: unreverse WWN identifier (#1308795)
-- Fixup WWN bytes for big-endian systems (#1308795)
-
-* Wed Feb 03 2016 Lukas Nykryn <lnykryn@redhat.com> - 219-19.5
-- udev: fibre channel: fix NPIV support (#1266934)
-
-* Wed Jan 13 2016 Lukas Nykryn <lnykryn@redhat.com> - 219-19.4
-- Avoid /tmp being mounted as tmpfs without the user's will (#1298109)
-
-* Thu Dec 10 2015 Lukas Nykryn <lnykryn@redhat.com> - 219-19.3
-- sysv-generator: follow symlinks in /etc/rc.d/init.d (#1288005)
-- man: RemoveIPC is set to no on rhel (#1284588)
-
-* Fri Nov 27 2015 Lukas Nykryn <lnykryn@redhat.com> - 219-19.2
-- device: rework how we enter tentative state (#1283579)
-- core: Do not bind a mount unit to a device, if it was from mountinfo (#1283579)
-- logind: set RemoveIPC=no by default (#1284588)
-
-* Wed Nov 18 2015 Lukas Nykryn <lnykryn@redhat.com> - 219-19.1
-- run: synchronously wait until the scope unit we create is started (#1283192)
+- s390: add personality support (#1300344)
+- socket_address_listen - do not rely on errno (#1316452)
 
 * Mon Oct 12 2015 Lukas Nykryn <lnykryn@redhat.com> - 219-19
 - udev: make naming for virtio devices opt-in (#1269216)