A System and Service Manager
CentOS Buildsys
2013-11-19 a4b143cb65ba5767d993a3b041001c1172e2396d
import systemd-207-8.el7.src.rpm
104 files added
1 files deleted
11726 ■■■■■ changed files
.systemd.metadata 1 ●●●● patch | view | raw | blame | history
README.md 5 ●●●●● patch | view | raw | blame | history
SOURCES/0001-RHEL-units-add-Install-section-to-tmp.mount.patch 24 ●●●●● patch | view | raw | blame | history
SOURCES/0002-kernel-install-add-fedora-specific-callouts-to-new-k.patch 42 ●●●●● patch | view | raw | blame | history
SOURCES/0003-core-cgroup-first-print-then-free.patch 23 ●●●●● patch | view | raw | blame | history
SOURCES/0004-swap-fix-reverse-dependencies.patch 27 ●●●●● patch | view | raw | blame | history
SOURCES/0005-update-TODO.patch 22 ●●●●● patch | view | raw | blame | history
SOURCES/0006-cryptsetup-generator-don-t-create-tmp-swap-units.patch 50 ●●●●● patch | view | raw | blame | history
SOURCES/0007-cryptsetup-generator-allow-specifying-options-in-pro.patch 185 ●●●●● patch | view | raw | blame | history
SOURCES/0008-automount-rename-repeat_unmont-to-repeat_unmount.patch 41 ●●●●● patch | view | raw | blame | history
SOURCES/0009-cgroup-add-the-missing-setting-of-variable-s-value.patch 24 ●●●●● patch | view | raw | blame | history
SOURCES/0010-cgroup-correct-the-log-information.patch 23 ●●●●● patch | view | raw | blame | history
SOURCES/0011-cgroup-fix-incorrectly-setting-memory-cgroup.patch 43 ●●●●● patch | view | raw | blame | history
SOURCES/0012-random-seed-we-should-return-errno-of-failed-loop_wr.patch 22 ●●●●● patch | view | raw | blame | history
SOURCES/0013-update-TODO.patch 24 ●●●●● patch | view | raw | blame | history
SOURCES/0014-libudev-fix-move_later-comparison.patch 24 ●●●●● patch | view | raw | blame | history
SOURCES/0015-man-document-luks.options-kernel-commandline.patch 23 ●●●●● patch | view | raw | blame | history
SOURCES/0016-keymap-remove-some-commented-out-lines.patch 33 ●●●●● patch | view | raw | blame | history
SOURCES/0017-Advertise-hibernation-only-if-there-s-enough-free-sw.patch 259 ●●●●● patch | view | raw | blame | history
SOURCES/0018-README-add-SCSI-BSG-option.patch 24 ●●●●● patch | view | raw | blame | history
SOURCES/0019-swap-create-.wants-symlink-to-auto-swap-devices.patch 87 ●●●●● patch | view | raw | blame | history
SOURCES/0020-cgroup-add-missing-equals-for-BlockIOWeight.patch 22 ●●●●● patch | view | raw | blame | history
SOURCES/0021-Assume-that-proc-meminfo-can-be-missing.patch 50 ●●●●● patch | view | raw | blame | history
SOURCES/0022-transaction.c-do-not-point-users-to-logs-when-unit-n.patch 63 ●●●●● patch | view | raw | blame | history
SOURCES/0023-Verify-validity-of-session-name-when-received-from-o.patch 283 ●●●●● patch | view | raw | blame | history
SOURCES/0024-udev-rules-avoid-erroring-on-trailing-whitespace.patch 27 ●●●●● patch | view | raw | blame | history
SOURCES/0025-keymap-Add-Samsung-Series-5-Ultra.patch 65 ●●●●● patch | view | raw | blame | history
SOURCES/0026-login-fix-login_is_valid-test.patch 149 ●●●●● patch | view | raw | blame | history
SOURCES/0027-polkit-Avoid-race-condition-in-scraping-proc.patch 74 ●●●●● patch | view | raw | blame | history
SOURCES/0028-core-whenever-a-new-PID-is-passed-to-us-make-sure-we.patch 71 ●●●●● patch | view | raw | blame | history
SOURCES/0029-remove-user-.service.patch 91 ●●●●● patch | view | raw | blame | history
SOURCES/0030-cgroup-always-enable-memory.use_hierarchy-for-all-cg.patch 27 ●●●●● patch | view | raw | blame | history
SOURCES/0031-logind-return-EINVAL-when-PID-is-wrong.patch 45 ●●●●● patch | view | raw | blame | history
SOURCES/0032-core-drop-some-out-of-date-references-to-cgroup-sett.patch 197 ●●●●● patch | view | raw | blame | history
SOURCES/0033-man-explain-NAME-in-systemctl-man-page.patch 33 ●●●●● patch | view | raw | blame | history
SOURCES/0034-journald-accept-EPOLLERR-from-dev-kmsg.patch 69 ●●●●● patch | view | raw | blame | history
SOURCES/0035-journald-avoid-NSS-in-journald.patch 89 ●●●●● patch | view | raw | blame | history
SOURCES/0036-libudev-add-missing-global-to-symbol-export.patch 20 ●●●●● patch | view | raw | blame | history
SOURCES/0037-gpt-auto-generator-do-not-assume-that-dev-block-u-u-.patch 206 ●●●●● patch | view | raw | blame | history
SOURCES/0038-logind-put-correct-user-object-paths-in-introspectio.patch 23 ●●●●● patch | view | raw | blame | history
SOURCES/0039-Fix-obsolete-references-to-systemd-random-seed-load..patch 38 ●●●●● patch | view | raw | blame | history
SOURCES/0040-cgroup-always-enable-memory.use_hierarchy-for-all-cg.patch 28 ●●●●● patch | view | raw | blame | history
SOURCES/0041-journalctl-1-s-adm-systemd-journal.patch 22 ●●●●● patch | view | raw | blame | history
SOURCES/0042-cgroup-if-we-do-a-cgroup-operation-then-do-something.patch 422 ●●●●● patch | view | raw | blame | history
SOURCES/0043-core-rework-how-we-match-mount-units-against-each-ot.patch 1156 ●●●●● patch | view | raw | blame | history
SOURCES/0044-logind-never-consider-a-closing-session-relevant-for.patch 23 ●●●●● patch | view | raw | blame | history
SOURCES/0045-man-drop-references-to-cgroup-wher-appropriate.patch 436 ●●●●● patch | view | raw | blame | history
SOURCES/0046-systemctl-make-sure-set-property-mangles-unit-names.patch 36 ●●●●● patch | view | raw | blame | history
SOURCES/0047-dbus-fix-introspection-for-TimerSlackNSec.patch 22 ●●●●● patch | view | raw | blame | history
SOURCES/0048-swap-properly-expose-timeout-property-on-the-bus.patch 21 ●●●●● patch | view | raw | blame | history
SOURCES/0049-build-sys-restore-detection-of-sphinx.patch 29 ●●●●● patch | view | raw | blame | history
SOURCES/0050-util-add-macro-for-iterating-through-all-prefixes-of.patch 119 ●●●●● patch | view | raw | blame | history
SOURCES/0051-util-properly-handle-the-root-dir-in-PATH_FOREACH_PR.patch 94 ●●●●● patch | view | raw | blame | history
SOURCES/0052-cgroup-get-rid-of-MemorySoftLimit.patch 245 ●●●●● patch | view | raw | blame | history
SOURCES/0053-set-IgnoreOnIsolate-true-for-systemd-cryptsetup-.ser.patch 27 ●●●●● patch | view | raw | blame | history
SOURCES/0054-main-don-t-free-fds-array-twice.patch 21 ●●●●● patch | view | raw | blame | history
SOURCES/0055-local-fix-memory-leak-when-putting-together-locale-s.patch 147 ●●●●● patch | view | raw | blame | history
SOURCES/0056-hashmap-size-hashmap-bucket-array-dynamically.patch 470 ●●●●● patch | view | raw | blame | history
SOURCES/0057-smack-setup-fix-path-to-Smack-CIPSO-mappings.patch 25 ●●●●● patch | view | raw | blame | history
SOURCES/0058-fix-lingering-references-to-var-lib-backlight-random.patch 51 ●●●●● patch | view | raw | blame | history
SOURCES/0059-cryptsetup-fix-OOM-handling-when-parsing-mount-optio.patch 45 ●●●●● patch | view | raw | blame | history
SOURCES/0060-journald-add-missing-error-check.patch 22 ●●●●● patch | view | raw | blame | history
SOURCES/0061-bus-fix-potentially-uninitialized-memory-access.patch 31 ●●●●● patch | view | raw | blame | history
SOURCES/0062-dbus-fix-return-value-of-dispatch_rqueue.patch 27 ●●●●● patch | view | raw | blame | history
SOURCES/0063-modules-load-fix-error-handling.patch 24 ●●●●● patch | view | raw | blame | history
SOURCES/0064-efi-never-call-qsort-on-potentially-NULL-arrays.patch 23 ●●●●● patch | view | raw | blame | history
SOURCES/0065-strv-don-t-access-potentially-NULL-string-arrays.patch 24 ●●●●● patch | view | raw | blame | history
SOURCES/0066-mkdir-pass-a-proper-function-pointer-to-mkdir_safe_i.patch 22 ●●●●● patch | view | raw | blame | history
SOURCES/0067-tmpfiles.d-include-setgid-perms-for-run-log-journal.patch 23 ●●●●● patch | view | raw | blame | history
SOURCES/0068-gpt-auto-generator-exit-immediately-if-in-container.patch 37 ●●●●● patch | view | raw | blame | history
SOURCES/0069-systemd-order-remote-mounts-from-mountinfo-before-re.patch 38 ●●●●● patch | view | raw | blame | history
SOURCES/0070-manager-when-verifying-whether-clients-may-change-en.patch 42 ●●●●● patch | view | raw | blame | history
SOURCES/0071-mount-check-for-NULL-before-reading-pm-what.patch 26 ●●●●● patch | view | raw | blame | history
SOURCES/0072-core-do-not-add-what-to-RequiresMountsFor-for-networ.patch 178 ●●●●● patch | view | raw | blame | history
SOURCES/0073-systemd-serialize-deserialize-forbid_restart-value.patch 48 ●●●●● patch | view | raw | blame | history
SOURCES/0074-core-unify-the-way-we-denote-serialization-attribute.patch 37 ●●●●● patch | view | raw | blame | history
SOURCES/0075-journald-fix-minor-memory-leak.patch 22 ●●●●● patch | view | raw | blame | history
SOURCES/0076-journald-remove-rotated-file-from-hashmap-when-rotat.patch 36 ●●●●● patch | view | raw | blame | history
SOURCES/0077-udevadm.xml-document-resolve-names-option-for-test.patch 31 ●●●●● patch | view | raw | blame | history
SOURCES/0078-dbus-common-avoid-leak-in-error-path.patch 68 ●●●●● patch | view | raw | blame | history
SOURCES/0079-drop-ins-check-return-value.patch 26 ●●●●● patch | view | raw | blame | history
SOURCES/0080-shared-util-Fix-glob_extend-argument.patch 25 ●●●●● patch | view | raw | blame | history
SOURCES/0081-Fix-for-SIGSEGV-in-systemd-bootchart-on-short-living.patch 31 ●●●●● patch | view | raw | blame | history
SOURCES/0082-man-document-the-b-special-boot-option.patch 34 ●●●●● patch | view | raw | blame | history
SOURCES/0083-tmpfiles-log-unaccessible-FUSE-mount-points-only-as-.patch 34 ●●●●● patch | view | raw | blame | history
SOURCES/0084-move-utf8-functions-from-libudev-private.h-to-utf8.h.patch 514 ●●●●● patch | view | raw | blame | history
SOURCES/0085-Use-udev_encode_string-in-fstab_node_to_udev_node.patch 113 ●●●●● patch | view | raw | blame | history
SOURCES/0086-Fix-buffer-overrun-when-enumerating-files.patch 173 ●●●●● patch | view | raw | blame | history
SOURCES/0087-shared-utf8-merge-implementations-remove-cruft.patch 401 ●●●●● patch | view | raw | blame | history
SOURCES/0088-device-nodes-move-device-node-specific-code-to-own-f.patch 418 ●●●●● patch | view | raw | blame | history
SOURCES/0089-shared-util-fix-off-by-one-error-in-tag_to_udev_node.patch 47 ●●●●● patch | view | raw | blame | history
SOURCES/0090-udev-path_id-fix-by-path-link-generation-for-scm-dev.patch 25 ●●●●● patch | view | raw | blame | history
SOURCES/0091-hashmap-randomize-hash-functions-a-bit.patch 374 ●●●●● patch | view | raw | blame | history
SOURCES/0092-Configurable-Timeouts-Restarts-default-values.patch 293 ●●●●● patch | view | raw | blame | history
SOURCES/0093-manager-configurable-StartLimit-default-values.patch 161 ●●●●● patch | view | raw | blame | history
SOURCES/0094-sysctl-bring-back-etc-sysctl.conf.patch 25 ●●●●● patch | view | raw | blame | history
SOURCES/0095-tmpfiles-add-a-new-m-line-type-that-adjusts-user-gro.patch 158 ●●●●● patch | view | raw | blame | history
SOURCES/85-display-manager.preset 10 ●●●●● patch | view | raw | blame | history
SOURCES/90-default.preset 106 ●●●●● patch | view | raw | blame | history
SOURCES/99-default-disable.preset 1 ●●●● patch | view | raw | blame | history
SOURCES/listen.conf 1 ●●●● patch | view | raw | blame | history
SOURCES/rc.local 13 ●●●●● patch | view | raw | blame | history
SOURCES/systemd-sysv-convert 148 ●●●●● patch | view | raw | blame | history
SOURCES/yum-protect-systemd.conf 1 ●●●● patch | view | raw | blame | history
SPECS/systemd.spec 1748 ●●●●● patch | view | raw | blame | history
.systemd.metadata
New file
@@ -0,0 +1 @@
ea1a538bc3d29f7c6f7f0a0aa5c070b9018c5527 SOURCES/systemd-207.tar.xz
README.md
File was deleted
SOURCES/0001-RHEL-units-add-Install-section-to-tmp.mount.patch
New file
@@ -0,0 +1,24 @@
From 2e987a0ac284a1cd1ab4f8e335abcae91c976f15 Mon Sep 17 00:00:00 2001
From: Michal Schmidt <mschmidt@redhat.com>
Date: Fri, 15 Feb 2013 09:07:57 +0100
Subject: [PATCH] RHEL: units: add [Install] section to tmp.mount
Related: #908253
---
 units/tmp.mount | 6 ++++++
 1 file changed, 6 insertions(+)
diff --git a/units/tmp.mount b/units/tmp.mount
index 99a3ba3..79e1c76 100644
--- a/units/tmp.mount
+++ b/units/tmp.mount
@@ -18,3 +18,9 @@ What=tmpfs
 Where=/tmp
 Type=tmpfs
 Options=mode=1777,strictatime
+
+# tmp.mount is statically enabled in upstream. In RHEL tmp-on-tmpfs is not used
+# by default, but there are cases where it is necessary (anaconda, live images,
+# read-only root). Make 'systemctl enable tmp.mount' work:
+[Install]
+WantedBy=local-fs.target
SOURCES/0002-kernel-install-add-fedora-specific-callouts-to-new-k.patch
New file
@@ -0,0 +1,42 @@
From b81d902a8ec4e81c6ddda0208307ee77d4e0858b Mon Sep 17 00:00:00 2001
From: Harald Hoyer <harald@redhat.com>
Date: Wed, 13 Mar 2013 07:57:53 +0100
Subject: [PATCH] kernel-install: add fedora specific callouts to
 new-kernel-pkg
---
 src/kernel-install/kernel-install | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)
diff --git a/src/kernel-install/kernel-install b/src/kernel-install/kernel-install
index fb2ee57..f491947 100644
--- a/src/kernel-install/kernel-install
+++ b/src/kernel-install/kernel-install
@@ -19,6 +19,27 @@
 # You should have received a copy of the GNU Lesser General Public License
 # along with systemd; If not, see <http://www.gnu.org/licenses/>.
+if [[ -x /sbin/new-kernel-pkg ]]; then
+    [[ "$2" == *\+* ]] && flavor=-"${2##*+}"
+    case "$1" in
+        add)
+            /sbin/new-kernel-pkg --package "kernel${flavor}" --install "$2" || exit $?
+            /sbin/new-kernel-pkg --package "kernel${flavor}" --mkinitrd --dracut --depmod --update "$2" || exit $?
+            /sbin/new-kernel-pkg --package "kernel${flavor}" --rpmposttrans "$2" || exit $?
+            ;;
+        remove)
+            /sbin/new-kernel-pkg --package "kernel${flavor+-$flavor}" --rminitrd --rmmoddep --remove "$2" || exit $?
+            ;;
+        *)
+            ;;
+    esac
+
+    # exit, if we can't find a boot loader spec conforming setup
+    if ! [[ -d /boot/loader/entries || -L /boot/loader/entries ]]; then
+        exit 0
+    fi
+fi
+
 usage()
 {
     echo "Usage:" >&2
SOURCES/0003-core-cgroup-first-print-then-free.patch
New file
@@ -0,0 +1,23 @@
From 89ad78921a404dc82f22862f2354707199ea1616 Mon Sep 17 00:00:00 2001
From: Lukas Nykryn <lnykryn@redhat.com>
Date: Fri, 13 Sep 2013 14:31:17 +0200
Subject: [PATCH] core/cgroup: first print then free
---
 src/core/cgroup.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/core/cgroup.c b/src/core/cgroup.c
index 3eeb475..513450a 100644
--- a/src/core/cgroup.c
+++ b/src/core/cgroup.c
@@ -395,8 +395,8 @@ static int unit_create_cgroups(Unit *u, CGroupControllerMask mask) {
                 is_in_hash = true;
         if (r < 0) {
-                free(path);
                 log_error("cgroup %s exists already: %s", path, strerror(-r));
+                free(path);
                 return r;
         }
SOURCES/0004-swap-fix-reverse-dependencies.patch
New file
@@ -0,0 +1,27 @@
From 0f84fab56d31f53b2970bdee64e254c4518618a7 Mon Sep 17 00:00:00 2001
From: Tom Gundersen <teg@jklm.no>
Date: Fri, 13 Sep 2013 14:46:18 +0200
Subject: [PATCH] swap: fix reverse dependencies
Make sure swap.target correctly requires/wants the swap units.
This fixes https://bugs.freedesktop.org/show_bug.cgi?id=69291.
Reported-by: Hussam Al-Tayeb
---
 src/core/swap.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/core/swap.c b/src/core/swap.c
index 57d15eb..3950860 100644
--- a/src/core/swap.c
+++ b/src/core/swap.c
@@ -220,7 +220,7 @@ static int swap_add_default_dependencies(Swap *s) {
         }
         if (!noauto) {
-                r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_BEFORE, (nofail ? UNIT_WANTED_BY : UNIT_REQUIRED_BY),
+                r = unit_add_two_dependencies_by_name_inverse(UNIT(s), UNIT_AFTER, (nofail ? UNIT_WANTS : UNIT_REQUIRES),
                                                       SPECIAL_SWAP_TARGET, NULL, true);
                 if (r < 0)
                         return r;
SOURCES/0005-update-TODO.patch
New file
@@ -0,0 +1,22 @@
From d0746c1d17407a17c18f26876d9ca0f6f20b29b0 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Fri, 13 Sep 2013 04:13:47 +0200
Subject: [PATCH] update TODO
---
 TODO | 2 ++
 1 file changed, 2 insertions(+)
diff --git a/TODO b/TODO
index 08d4914..5354692 100644
--- a/TODO
+++ b/TODO
@@ -58,6 +58,8 @@ CGroup Rework Completion:
 Features:
+* Move backlight and random-seed into /var/lib/systemd
+
 * When a Type=forking service fails and needed another service that
   service is not cleaned up again when it has StopWhenUnneeded=yes
   http://lists.freedesktop.org/archives/systemd-devel/2013-July/012141.html
SOURCES/0006-cryptsetup-generator-don-t-create-tmp-swap-units.patch
New file
@@ -0,0 +1,50 @@
From d12ed80037b482f7da136abbd7abce9c9219ef8e Mon Sep 17 00:00:00 2001
From: Tom Gundersen <teg@jklm.no>
Date: Thu, 15 Aug 2013 08:47:59 +0800
Subject: [PATCH] cryptsetup-generator: don't create tmp+swap units
---
 src/cryptsetup/cryptsetup-generator.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c
index 81b7708..967c5e6 100644
--- a/src/cryptsetup/cryptsetup-generator.c
+++ b/src/cryptsetup/cryptsetup-generator.c
@@ -72,13 +72,20 @@ static int create_disk(
         _cleanup_free_ char *p = NULL, *n = NULL, *d = NULL, *u = NULL, *from = NULL, *to = NULL, *e = NULL;
         _cleanup_fclose_ FILE *f = NULL;
-        bool noauto, nofail;
+        bool noauto, nofail, tmp, swap;
         assert(name);
         assert(device);
         noauto = has_option(options, "noauto");
         nofail = has_option(options, "nofail");
+        tmp = has_option(options, "tmp");
+        swap = has_option(options, "swap");
+
+        if (tmp && swap) {
+                log_error("Device '%s' cannot be both 'tmp' and 'swap'. Ignoring.", name);
+                return -EINVAL;
+        }
         n = unit_name_from_path_instance("systemd-cryptsetup", name, ".service");
         if (!n)
@@ -151,12 +158,12 @@ static int create_disk(
                 name, u, strempty(password), strempty(options),
                 name);
-        if (has_option(options, "tmp"))
+        if (tmp)
                 fprintf(f,
                         "ExecStartPost=/sbin/mke2fs '/dev/mapper/%s'\n",
                         name);
-        if (has_option(options, "swap"))
+        if (swap)
                 fprintf(f,
                         "ExecStartPost=/sbin/mkswap '/dev/mapper/%s'\n",
                         name);
SOURCES/0007-cryptsetup-generator-allow-specifying-options-in-pro.patch
New file
@@ -0,0 +1,185 @@
From 61ca2800f3a1666478bdc01fc796d36c917a5032 Mon Sep 17 00:00:00 2001
From: Tom Gundersen <teg@jklm.no>
Date: Sun, 18 Aug 2013 14:59:00 +0800
Subject: [PATCH] cryptsetup-generator: allow specifying options in
 /proc/cmdline
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The main usecase for this is to make it possible to use cryptsetup in
the initrd without it having to include a host-specific /etc/crypttab.
Tested-by: Thomas Bächler <thomas@archlinux.org>
---
 man/systemd-cryptsetup-generator.xml  | 23 ++++++++++
 src/cryptsetup/cryptsetup-generator.c | 79 +++++++++++++++++++++++++++++++++--
 2 files changed, 98 insertions(+), 4 deletions(-)
diff --git a/man/systemd-cryptsetup-generator.xml b/man/systemd-cryptsetup-generator.xml
index 215ac2d..d6b7e49 100644
--- a/man/systemd-cryptsetup-generator.xml
+++ b/man/systemd-cryptsetup-generator.xml
@@ -137,6 +137,29 @@
                                 will be activated in the initrd or the real root.</para>
                                 </listitem>
                         </varlistentry>
+
+                        <varlistentry>
+                                <term><varname>luks.options=</varname></term>
+                                <term><varname>rd.luks.options=</varname></term>
+
+                                <listitem><para>Takes a LUKS super
+                                block UUID followed by an '=' and a string
+                                of options separated by commas as argument.
+                                This will override the options for the given
+                                UUID.</para>
+                                <para>If only a list of options, without an
+                                UUID, is specified, they apply to any UUIDs not
+                                specified elsewhere, and without an entry in
+                                /etc/crypttab.</para><para>
+                                <varname>rd.luks.options=</varname>
+                                is honored only by initial RAM disk
+                                (initrd) while
+                                <varname>luks.options=</varname> is
+                                honored by both the main system and
+                                the initrd.</para>
+                                </listitem>
+                        </varlistentry>
+
                         <varlistentry>
                                 <term><varname>luks.key=</varname></term>
                                 <term><varname>rd.luks.key=</varname></term>
diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c
index 967c5e6..ba6efa6 100644
--- a/src/cryptsetup/cryptsetup-generator.c
+++ b/src/cryptsetup/cryptsetup-generator.c
@@ -240,7 +240,7 @@ static int create_disk(
         return 0;
 }
-static int parse_proc_cmdline(char ***arg_proc_cmdline_disks, char **arg_proc_cmdline_keyfile) {
+static int parse_proc_cmdline(char ***arg_proc_cmdline_disks, char ***arg_proc_cmdline_options, char **arg_proc_cmdline_keyfile) {
         _cleanup_free_ char *line = NULL;
         char *w = NULL, *state = NULL;
         int r;
@@ -307,7 +307,20 @@ static int parse_proc_cmdline(char ***arg_proc_cmdline_disks, char **arg_proc_cm
                                         return log_oom();
                         }
+                } else if (startswith(word, "luks.options=")) {
+                        if (strv_extend(arg_proc_cmdline_options, word + 13) < 0)
+                                return log_oom();
+
+                } else if (startswith(word, "rd.luks.options=")) {
+
+                        if (in_initrd()) {
+                                if (strv_extend(arg_proc_cmdline_options, word + 16) < 0)
+                                        return log_oom();
+                        }
+
                 } else if (startswith(word, "luks.key=")) {
+                        if (*arg_proc_cmdline_keyfile)
+                                free(*arg_proc_cmdline_keyfile);
                         *arg_proc_cmdline_keyfile = strdup(word + 9);
                         if (!*arg_proc_cmdline_keyfile)
                                 return log_oom();
@@ -337,6 +350,7 @@ static int parse_proc_cmdline(char ***arg_proc_cmdline_disks, char **arg_proc_cm
 int main(int argc, char *argv[]) {
         _cleanup_strv_free_ char **arg_proc_cmdline_disks_done = NULL;
         _cleanup_strv_free_ char **arg_proc_cmdline_disks = NULL;
+        _cleanup_strv_free_ char **arg_proc_cmdline_options = NULL;
         _cleanup_free_ char *arg_proc_cmdline_keyfile = NULL;
         _cleanup_fclose_ FILE *f = NULL;
         unsigned n = 0;
@@ -357,7 +371,7 @@ int main(int argc, char *argv[]) {
         umask(0022);
-        if (parse_proc_cmdline(&arg_proc_cmdline_disks, &arg_proc_cmdline_keyfile) < 0)
+        if (parse_proc_cmdline(&arg_proc_cmdline_disks, &arg_proc_cmdline_options, &arg_proc_cmdline_keyfile) < 0)
                 return EXIT_FAILURE;
         if (!arg_enabled)
@@ -412,6 +426,26 @@ int main(int argc, char *argv[]) {
                                 continue;
                         }
+                        if (arg_proc_cmdline_options) {
+                                /*
+                                  If options are specified on the kernel commandline, let them override
+                                  the ones from crypttab.
+                                */
+                                STRV_FOREACH(i, arg_proc_cmdline_options) {
+                                        _cleanup_free_ char *proc_uuid = NULL, *proc_options = NULL;
+                                        const char *p = *i;
+
+                                        k = sscanf(p, "%m[0-9a-fA-F-]=%ms", &proc_uuid, &proc_options);
+                                        if (k == 2 && streq(proc_uuid, device + 5)) {
+                                                if (options)
+                                                        free(options);
+                                                options = strdup(p);
+                                                if (!proc_options)
+                                                        return log_oom();
+                                        }
+                                }
+                        }
+
                         if (arg_proc_cmdline_disks) {
                                 /*
                                   If luks UUIDs are specified on the kernel command line, use them as a filter
@@ -452,7 +486,7 @@ next:
                   on the kernel command line and not yet written.
                 */
-                _cleanup_free_ char *name = NULL, *device = NULL;
+                _cleanup_free_ char *name = NULL, *device = NULL, *options = NULL;
                 const char *p = *i;
                 if (startswith(p, "luks-"))
@@ -467,7 +501,44 @@ next:
                 if (!name || !device)
                         return log_oom();
-                if (create_disk(name, device, arg_proc_cmdline_keyfile, "timeout=0") < 0)
+                if (arg_proc_cmdline_options) {
+                        /*
+                          If options are specified on the kernel commandline, use them.
+                        */
+                        char **j;
+
+                        STRV_FOREACH(j, arg_proc_cmdline_options) {
+                                _cleanup_free_ char *proc_uuid = NULL, *proc_options = NULL;
+                                const char *s = *j;
+                                int k;
+
+                                k = sscanf(s, "%m[0-9a-fA-F-]=%ms", &proc_uuid, &proc_options);
+                                if (k == 2) {
+                                        if (streq(proc_uuid, device + 5)) {
+                                                if (options)
+                                                        free(options);
+                                                options = strdup(proc_options);
+                                                if (!options)
+                                                        return log_oom();
+                                        }
+                                } else if (!options) {
+                                        /*
+                                          Fall back to options without a specified UUID
+                                        */
+                                        options = strdup(s);
+                                        if (!options)
+                                                return log_oom();
+                                }
+                        }
+                }
+
+                if (!options) {
+                        options = strdup("timeout=0");
+                        if (!options)
+                                return log_oom();
+                }
+
+                if (create_disk(name, device, arg_proc_cmdline_keyfile, options) < 0)
                         r = EXIT_FAILURE;
         }
SOURCES/0008-automount-rename-repeat_unmont-to-repeat_unmount.patch
New file
@@ -0,0 +1,41 @@
From 091169fa11a366ab42fb6f71c22e8ed95868f804 Mon Sep 17 00:00:00 2001
From: David Mackey <tdmackey@booleanhaiku.com>
Date: Thu, 12 Sep 2013 19:45:49 -0700
Subject: [PATCH] automount: rename repeat_unmont to repeat_unmount
Trivial cleanup of repeat_unmount() spelling.
---
 src/core/automount.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/core/automount.c b/src/core/automount.c
index a20d534..6762392 100644
--- a/src/core/automount.c
+++ b/src/core/automount.c
@@ -66,7 +66,7 @@ static void automount_init(Unit *u) {
         UNIT(a)->ignore_on_isolate = true;
 }
-static void repeat_unmout(const char *path) {
+static void repeat_unmount(const char *path) {
         assert(path);
         for (;;) {
@@ -100,7 +100,7 @@ static void unmount_autofs(Automount *a) {
         if (a->where &&
             (UNIT(a)->manager->exit_code != MANAGER_RELOAD &&
              UNIT(a)->manager->exit_code != MANAGER_REEXECUTE))
-                repeat_unmout(a->where);
+                repeat_unmount(a->where);
 }
 static void automount_done(Unit *u) {
@@ -575,7 +575,7 @@ fail:
                 close_nointr_nofail(ioctl_fd);
         if (mounted)
-                repeat_unmout(a->where);
+                repeat_unmount(a->where);
         log_error_unit(UNIT(a)->id,
                        "Failed to initialize automounter: %s", strerror(-r));
SOURCES/0009-cgroup-add-the-missing-setting-of-variable-s-value.patch
New file
@@ -0,0 +1,24 @@
From 8799f0a37ef24fe2709b6e7fdb4ca2c1c9586718 Mon Sep 17 00:00:00 2001
From: Gao feng <gaofeng@cn.fujitsu.com>
Date: Fri, 13 Sep 2013 11:17:05 +0800
Subject: [PATCH] cgroup: add the missing setting of variable's value
set the value of variable "r" to the return value
of cg_set_attribute.
---
 src/core/cgroup.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/core/cgroup.c b/src/core/cgroup.c
index 513450a..9804227 100644
--- a/src/core/cgroup.c
+++ b/src/core/cgroup.c
@@ -264,7 +264,7 @@ void cgroup_context_apply(CGroupContext *c, CGroupControllerMask mask, const cha
                         log_error("Failed to set memory.limit_in_bytes on %s: %s", path, strerror(-r));
                 sprintf(buf, "%" PRIu64 "\n", c->memory_soft_limit);
-                cg_set_attribute("memory", path, "memory.soft_limit_in_bytes", buf);
+                r = cg_set_attribute("memory", path, "memory.soft_limit_in_bytes", buf);
                 if (r < 0)
                         log_error("Failed to set memory.limit_in_bytes on %s: %s", path, strerror(-r));
         }
SOURCES/0010-cgroup-correct-the-log-information.patch
New file
@@ -0,0 +1,23 @@
From 9b69c0d07b0db38c181e35e52bcea0eb0dd21818 Mon Sep 17 00:00:00 2001
From: Gao feng <gaofeng@cn.fujitsu.com>
Date: Fri, 13 Sep 2013 11:17:06 +0800
Subject: [PATCH] cgroup: correct the log information
it should be memory.soft_limit_in_bytes.
---
 src/core/cgroup.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/core/cgroup.c b/src/core/cgroup.c
index 9804227..08cb64b 100644
--- a/src/core/cgroup.c
+++ b/src/core/cgroup.c
@@ -266,7 +266,7 @@ void cgroup_context_apply(CGroupContext *c, CGroupControllerMask mask, const cha
                 sprintf(buf, "%" PRIu64 "\n", c->memory_soft_limit);
                 r = cg_set_attribute("memory", path, "memory.soft_limit_in_bytes", buf);
                 if (r < 0)
-                        log_error("Failed to set memory.limit_in_bytes on %s: %s", path, strerror(-r));
+                        log_error("Failed to set memory.soft_limit_in_bytes on %s: %s", path, strerror(-r));
         }
         if (mask & CGROUP_DEVICE) {
SOURCES/0011-cgroup-fix-incorrectly-setting-memory-cgroup.patch
New file
@@ -0,0 +1,43 @@
From c7e5130d5b3983986bfe95918c75e083fa90dd47 Mon Sep 17 00:00:00 2001
From: Gao feng <gaofeng@cn.fujitsu.com>
Date: Fri, 13 Sep 2013 14:43:04 +0800
Subject: [PATCH] cgroup: fix incorrectly setting memory cgroup
If the memory_limit of unit is -1, we should write "-1"
to the file memory.limit_in_bytes. not the (unit64_t) -1.
otherwise the memory.limit_in_bytes will be set to zero.
---
 src/core/cgroup.c | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/src/core/cgroup.c b/src/core/cgroup.c
index 08cb64b..1f41efc 100644
--- a/src/core/cgroup.c
+++ b/src/core/cgroup.c
@@ -257,14 +257,21 @@ void cgroup_context_apply(CGroupContext *c, CGroupControllerMask mask, const cha
         if (mask & CGROUP_MEMORY) {
                 char buf[DECIMAL_STR_MAX(uint64_t) + 1];
+                if (c->memory_limit != (uint64_t) -1) {
+                        sprintf(buf, "%" PRIu64 "\n", c->memory_limit);
+                        r = cg_set_attribute("memory", path, "memory.limit_in_bytes", buf);
+                } else
+                        r = cg_set_attribute("memory", path, "memory.limit_in_bytes", "-1");
-                sprintf(buf, "%" PRIu64 "\n", c->memory_limit);
-                r = cg_set_attribute("memory", path, "memory.limit_in_bytes", buf);
                 if (r < 0)
                         log_error("Failed to set memory.limit_in_bytes on %s: %s", path, strerror(-r));
-                sprintf(buf, "%" PRIu64 "\n", c->memory_soft_limit);
-                r = cg_set_attribute("memory", path, "memory.soft_limit_in_bytes", buf);
+                if (c->memory_soft_limit != (uint64_t) -1) {
+                        sprintf(buf, "%" PRIu64 "\n", c->memory_soft_limit);
+                        r = cg_set_attribute("memory", path, "memory.soft_limit_in_bytes", buf);
+                } else
+                        r = cg_set_attribute("memory", path, "memory.soft_limit_in_bytes", "-1");
+
                 if (r < 0)
                         log_error("Failed to set memory.soft_limit_in_bytes on %s: %s", path, strerror(-r));
         }
SOURCES/0012-random-seed-we-should-return-errno-of-failed-loop_wr.patch
New file
@@ -0,0 +1,22 @@
From 198884f22dc432a98e3d4423434b9e97d67f2da8 Mon Sep 17 00:00:00 2001
From: Lukas Nykryn <lnykryn@redhat.com>
Date: Fri, 13 Sep 2013 14:12:55 +0200
Subject: [PATCH] random-seed: we should return errno of failed loop_write
---
 src/random-seed/random-seed.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/random-seed/random-seed.c b/src/random-seed/random-seed.c
index 4776c07..afbd500 100644
--- a/src/random-seed/random-seed.c
+++ b/src/random-seed/random-seed.c
@@ -157,7 +157,7 @@ int main(int argc, char *argv[]) {
                 r = loop_write(seed_fd, buf, (size_t) k, false);
                 if (r <= 0) {
                         log_error("Failed to write new random seed file: %s", r < 0 ? strerror(-r) : "short write");
-                        r = k == 0 ? -EIO : (int) k;
+                        r = r == 0 ? -EIO : r;
                 }
         }
SOURCES/0013-update-TODO.patch
New file
@@ -0,0 +1,24 @@
From f11f72532fd9a05149714229cb7559b8e3fa802a Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Fri, 13 Sep 2013 14:28:17 +0200
Subject: [PATCH] update TODO
---
 TODO | 4 ++++
 1 file changed, 4 insertions(+)
diff --git a/TODO b/TODO
index 5354692..9943b3e 100644
--- a/TODO
+++ b/TODO
@@ -60,6 +60,10 @@ Features:
 * Move backlight and random-seed into /var/lib/systemd
+* If we try to find a unit via a danglign symlink generate a clean
+  error. Currently we just ignore it and read the unit from the search
+  path anyway.
+
 * When a Type=forking service fails and needed another service that
   service is not cleaned up again when it has StopWhenUnneeded=yes
   http://lists.freedesktop.org/archives/systemd-devel/2013-July/012141.html
SOURCES/0014-libudev-fix-move_later-comparison.patch
New file
@@ -0,0 +1,24 @@
From 3b93bf5a35b0bb7111754fbae75e7654b775506d Mon Sep 17 00:00:00 2001
From: Lukas Nykryn <lnykryn@redhat.com>
Date: Fri, 13 Sep 2013 14:12:54 +0200
Subject: [PATCH] libudev: fix move_later comparison
At the beginning move_later is set to -1, but it is set to different
value only if expression !move_later is true.
---
 src/libudev/libudev-enumerate.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/libudev/libudev-enumerate.c b/src/libudev/libudev-enumerate.c
index bc1e37d..8146f27 100644
--- a/src/libudev/libudev-enumerate.c
+++ b/src/libudev/libudev-enumerate.c
@@ -300,7 +300,7 @@ _public_ struct udev_list_entry *udev_enumerate_get_list_entry(struct udev_enume
                         /* skip to be delayed devices, and move the to
                          * the point where the prefix changes. We can
                          * only move one item at a time. */
-                        if (!move_later) {
+                        if (move_later == -1) {
                                 move_later_prefix = devices_delay_later(udev_enumerate->udev, entry->syspath);
                                 if (move_later_prefix > 0) {
SOURCES/0015-man-document-luks.options-kernel-commandline.patch
New file
@@ -0,0 +1,23 @@
From 583f4eb5d443bc09502d6973f08755173db43fd8 Mon Sep 17 00:00:00 2001
From: Tom Gundersen <teg@jklm.no>
Date: Fri, 13 Sep 2013 21:03:55 +0200
Subject: [PATCH] man: document luks.options kernel commandline
This should have been part of commit 7ab064a6d
---
 man/kernel-command-line.xml | 2 ++
 1 file changed, 2 insertions(+)
diff --git a/man/kernel-command-line.xml b/man/kernel-command-line.xml
index a4b7d13..cc267a3 100644
--- a/man/kernel-command-line.xml
+++ b/man/kernel-command-line.xml
@@ -250,6 +250,8 @@
                                 <term><varname>rd.luks.crypttab=</varname></term>
                                 <term><varname>luks.uuid=</varname></term>
                                 <term><varname>rd.luks.uuid=</varname></term>
+                                <term><varname>luks.options=</varname></term>
+                                <term><varname>rd.luks.options=</varname></term>
                                 <term><varname>luks.key=</varname></term>
                                 <term><varname>rd.luks.key=</varname></term>
SOURCES/0016-keymap-remove-some-commented-out-lines.patch
New file
@@ -0,0 +1,33 @@
From f559cb147ae336f62a9020fa909b70ea90e43886 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Wed, 28 Aug 2013 17:23:59 -0400
Subject: [PATCH] keymap: remove some commented out lines
---
 hwdb/60-keyboard.hwdb | 6 ------
 1 file changed, 6 deletions(-)
diff --git a/hwdb/60-keyboard.hwdb b/hwdb/60-keyboard.hwdb
index eca3f55..53e83ad 100644
--- a/hwdb/60-keyboard.hwdb
+++ b/hwdb/60-keyboard.hwdb
@@ -894,11 +894,6 @@ keyboard:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*200E[45]*:pvr*
 # Series 5
 keyboard:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*700Z*:pvr*
  KEYBOARD_KEY_ce=!prog1                                 # Fn+F1 launch settings
-#KEYBOARD_KEY_89=!brightnessdown                        # Fn+F2
-#KEYBOARD_KEY_88=!brightnessup                          # Fn+F3
-#KEYBOARD_KEY_82=!switchvideomode                       # Fn+F4 video output
-#KEYBOARD_KEY_f9=!f23                                   # Fn+F5 touchpad turn OFF
-#KEYBOARD_KEY_f7=!f22                                   # Fn+F5 touchpad turn ON
  KEYBOARD_KEY_a0=!mute                                  # Fn+F6 mute
  KEYBOARD_KEY_ae=!volumedown                            # Fn+F7
  KEYBOARD_KEY_b0=!volumeup                              # Fn+F8
@@ -906,7 +901,6 @@ keyboard:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*700Z*:pvr*
  KEYBOARD_KEY_96=!kbdillumup                            # Fn+F10 keyboard backlight up
  KEYBOARD_KEY_b3=!prog3                                 # Fn+F11 fan/cooling mode changer
  KEYBOARD_KEY_d5=!wlan                                  # Fn+F12 wlan/airplane switch
-# KEYBOARD_KEY_ba=!ejectcd                               # Fn+DEL eject cd
 # Series 9
 keyboard:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*90X3A*:pvr*
SOURCES/0017-Advertise-hibernation-only-if-there-s-enough-free-sw.patch
New file
@@ -0,0 +1,259 @@
From 3559039a97e1d3e28dd9b38202d3499652a58036 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Fri, 13 Sep 2013 19:41:52 -0400
Subject: [PATCH] Advertise hibernation only if there's enough free swap
Condition that is checked is taken from upower:
  active(anon) < free swap * 0.98
This is really stupid, because the kernel knows the situation better,
e.g. there could be two swap files, and then hibernation would be
impossible despite passing this check, or the kernel could start
supporting compressed swap and/or compressed hibernation images, and
then this this check would be too stringent. Nevertheless, until
we have something better, this should at least return a true negative
if there's no swap.
Logging of capabilities in the journal is changed to not strip leading
zeros. I consider this more readable anyway.
http://cgit.freedesktop.org/upower/tree/src/up-daemon.c#n613
https://bugzilla.redhat.com/show_bug.cgi?id=1007059
---
 src/shared/fileio.c       | 34 ++++++++++++++++++++++++++++++++++
 src/shared/fileio.h       |  2 ++
 src/shared/logs-show.c    |  2 +-
 src/shared/sleep-config.c | 45 ++++++++++++++++++++++++++++++++++++++++++++-
 src/shared/util.c         | 23 +----------------------
 src/test/test-fileio.c    | 20 ++++++++++++++++++++
 src/test/test-sleep.c     | 16 ++++++++--------
 7 files changed, 110 insertions(+), 32 deletions(-)
diff --git a/src/shared/fileio.c b/src/shared/fileio.c
index 77fd059..4e2b444 100644
--- a/src/shared/fileio.c
+++ b/src/shared/fileio.c
@@ -648,3 +648,37 @@ int executable_is_script(const char *path, char **interpreter) {
         *interpreter = ans;
         return 1;
 }
+
+/**
+ * Retrieve one field from a file like /proc/self/status.
+ * pattern should start with '\n' and end with ':'. Whitespace
+ * after ':' will be skipped. field must be freed afterwards.
+ */
+int get_status_field(const char *filename, const char *pattern, char **field) {
+        _cleanup_free_ char *status = NULL;
+        char *t;
+        size_t len;
+        int r;
+
+        assert(filename);
+        assert(field);
+
+        r = read_full_file(filename, &status, NULL);
+        if (r < 0)
+                return r;
+
+        t = strstr(status, pattern);
+        if (!t)
+                return -ENOENT;
+
+        t += strlen(pattern);
+        t += strspn(t, WHITESPACE);
+
+        len = strcspn(t, WHITESPACE);
+
+        *field = strndup(t, len);
+        if (!*field)
+                return -ENOMEM;
+
+        return 0;
+}
diff --git a/src/shared/fileio.h b/src/shared/fileio.h
index a0aae28..59e4150 100644
--- a/src/shared/fileio.h
+++ b/src/shared/fileio.h
@@ -37,3 +37,5 @@ int load_env_file(const char *fname, const char *separator, char ***l);
 int write_env_file(const char *fname, char **l);
 int executable_is_script(const char *path, char **interpreter);
+
+int get_status_field(const char *filename, const char *pattern, char **field);
diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c
index 87633e7..f50777c 100644
--- a/src/shared/logs-show.c
+++ b/src/shared/logs-show.c
@@ -201,7 +201,7 @@ static int output_short(
         assert(j);
         /* Set the threshold to one bigger than the actual print
-         * treshold, so that if the line is actually longer than what
+         * threshold, so that if the line is actually longer than what
          * we're willing to print, ellipsization will occur. This way
          * we won't output a misleading line without any indication of
          * truncation.
diff --git a/src/shared/sleep-config.c b/src/shared/sleep-config.c
index cd3238b..5ec7cce 100644
--- a/src/shared/sleep-config.c
+++ b/src/shared/sleep-config.c
@@ -163,6 +163,46 @@ int can_sleep_disk(char **types) {
         return false;
 }
+#define HIBERNATION_SWAP_THRESHOLD 0.98
+
+static bool enough_memory_for_hibernation(void) {
+        _cleanup_free_ char *active = NULL, *swapfree = NULL;
+        unsigned long long act, swap;
+        int r;
+
+        r = get_status_field("/proc/meminfo", "\nSwapFree:", &swapfree);
+        if (r < 0) {
+                log_error("Failed to retrieve SwapFree from /proc/meminfo: %s", strerror(-r));
+                return false;
+        }
+
+        r = safe_atollu(swapfree, &swap);
+        if (r < 0) {
+                log_error("Failed to parse SwapFree from /proc/meminfo: %s: %s",
+                          swapfree, strerror(-r));
+                return false;
+        }
+
+        r = get_status_field("/proc/meminfo", "\nActive(anon):", &active);
+        if (r < 0) {
+                log_error("Failed to retrieve Active(anon) from /proc/meminfo: %s", strerror(-r));
+                return false;
+        }
+
+        r = safe_atollu(active, &act);
+        if (r < 0) {
+                log_error("Failed to parse Active(anon) from /proc/meminfo: %s: %s",
+                          active, strerror(-r));
+                return false;
+        }
+
+        r = act <= swap * HIBERNATION_SWAP_THRESHOLD;
+        log_debug("Hibernation is %spossible, Active(anon)=%llu kB, SwapFree=%llu kB, threshold=%.2g%%",
+                  r ? "" : "im", act, swap, 100*HIBERNATION_SWAP_THRESHOLD);
+
+        return r;
+}
+
 int can_sleep(const char *verb) {
         _cleanup_strv_free_ char **modes = NULL, **states = NULL;
         int r;
@@ -175,5 +215,8 @@ int can_sleep(const char *verb) {
         if (r < 0)
                 return false;
-        return can_sleep_state(states) && can_sleep_disk(modes);
+        if (!can_sleep_state(states) || !can_sleep_disk(modes))
+                return false;
+
+        return streq(verb, "suspend") || enough_memory_for_hibernation();
 }
diff --git a/src/shared/util.c b/src/shared/util.c
index 9a075fa..f6f3b18 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -694,9 +694,6 @@ int is_kernel_thread(pid_t pid) {
 int get_process_capeff(pid_t pid, char **capeff) {
         const char *p;
-        _cleanup_free_ char *status = NULL;
-        char *t = NULL;
-        int r;
         assert(capeff);
         assert(pid >= 0);
@@ -706,25 +703,7 @@ int get_process_capeff(pid_t pid, char **capeff) {
         else
                 p = procfs_file_alloca(pid, "status");
-        r = read_full_file(p, &status, NULL);
-        if (r < 0)
-                return r;
-
-        t = strstr(status, "\nCapEff:\t");
-        if (!t)
-                return -ENOENT;
-
-        for (t += strlen("\nCapEff:\t"); t[0] == '0'; t++)
-                continue;
-
-        if (t[0] == '\n')
-                t--;
-
-        *capeff = strndup(t, strchr(t, '\n') - t);
-        if (!*capeff)
-                return -ENOMEM;
-
-        return 0;
+        return get_status_field(p, "\nCapEff:", capeff);
 }
 int get_process_exe(pid_t pid, char **name) {
diff --git a/src/test/test-fileio.c b/src/test/test-fileio.c
index 1184e7e..4a4ed79 100644
--- a/src/test/test-fileio.c
+++ b/src/test/test-fileio.c
@@ -229,9 +229,29 @@ static void test_executable_is_script(void) {
         unlink(t);
 }
+static void test_status_field(void) {
+        _cleanup_free_ char *t = NULL, *p = NULL, *s = NULL;
+        unsigned long long total, buffers;
+
+        assert_se(get_status_field("/proc/self/status", "\nThreads:", &t) == 0);
+        puts(t);
+        assert_se(streq(t, "1"));
+
+        assert_se(get_status_field("/proc/meminfo", "MemTotal:", &p) == 0);
+        puts(p);
+        assert_se(safe_atollu(p, &total) == 0);
+
+        assert_se(get_status_field("/proc/meminfo", "\nBuffers:", &s) == 0);
+        puts(s);
+        assert_se(safe_atollu(s, &buffers) == 0);
+
+        assert(buffers < total);
+}
+
 int main(int argc, char *argv[]) {
         test_parse_env_file();
         test_parse_multiline_env_file();
         test_executable_is_script();
+        test_status_field();
         return 0;
 }
diff --git a/src/test/test-sleep.c b/src/test/test-sleep.c
index c3cb9c5..545dfab 100644
--- a/src/test/test-sleep.c
+++ b/src/test/test-sleep.c
@@ -40,14 +40,14 @@ int main(int argc, char* argv[]) {
                 **shutdown = strv_new("shutdown", NULL),
                 **freez = strv_new("freeze", NULL);
-        log_info("Can Standby: %s", yes_no(can_sleep_state(standby) > 0));
-        log_info("Can Suspend: %s", yes_no(can_sleep_state(mem) > 0));
-        log_info("Can Hibernate: %s", yes_no(can_sleep_state(disk) > 0));
-        log_info("Can Hibernate+Suspend (Hybrid-Sleep): %s", yes_no(can_sleep_disk(suspend) > 0));
-        log_info("Can Hibernate+Reboot: %s", yes_no(can_sleep_disk(reboot) > 0));
-        log_info("Can Hibernate+Platform: %s", yes_no(can_sleep_disk(platform) > 0));
-        log_info("Can Hibernate+Shutdown: %s", yes_no(can_sleep_disk(shutdown) > 0));
-        log_info("Can Freeze: %s", yes_no(can_sleep_disk(freez) > 0));
+        log_info("Standby configured: %s", yes_no(can_sleep_state(standby) > 0));
+        log_info("Suspend configured: %s", yes_no(can_sleep_state(mem) > 0));
+        log_info("Hibernate configured: %s", yes_no(can_sleep_state(disk) > 0));
+        log_info("Hibernate+Suspend (Hybrid-Sleep) configured: %s", yes_no(can_sleep_disk(suspend) > 0));
+        log_info("Hibernate+Reboot configured: %s", yes_no(can_sleep_disk(reboot) > 0));
+        log_info("Hibernate+Platform configured: %s", yes_no(can_sleep_disk(platform) > 0));
+        log_info("Hibernate+Shutdown configured: %s", yes_no(can_sleep_disk(shutdown) > 0));
+        log_info("Freeze configured: %s", yes_no(can_sleep_state(freez) > 0));
         log_info("Suspend configured and possible: %s", yes_no(can_sleep("suspend") > 0));
         log_info("Hibernation configured and possible: %s", yes_no(can_sleep("hibernate") > 0));
SOURCES/0018-README-add-SCSI-BSG-option.patch
New file
@@ -0,0 +1,24 @@
From 64a94f1e45890eaeb5880dbd2044265e17023067 Mon Sep 17 00:00:00 2001
From: Kay Sievers <kay@vrfy.org>
Date: Sun, 15 Sep 2013 07:29:25 +0200
Subject: [PATCH] README: add SCSI BSG option
---
 README | 4 ++++
 1 file changed, 4 insertions(+)
diff --git a/README b/README
index a16f342..b39cd37 100644
--- a/README
+++ b/README
@@ -64,6 +64,10 @@ REQUIREMENTS:
         Mount and bind mount handling might require it:
           CONFIG_FHANDLE
+        Support for some SCSI devices serial number retrieval, to
+        create additional symlinks in /dev/disk/ and /dev/tape:
+          CONFIG_BLK_DEV_BSG
+
         Optional but strongly recommended:
           CONFIG_IPV6
           CONFIG_AUTOFS4_FS
SOURCES/0019-swap-create-.wants-symlink-to-auto-swap-devices.patch
New file
@@ -0,0 +1,87 @@
From c1f9c15f319f7dfb96bcbf2c3cf879f2b4457350 Mon Sep 17 00:00:00 2001
From: Tom Gundersen <teg@jklm.no>
Date: Mon, 16 Sep 2013 01:08:32 +0200
Subject: [PATCH] swap: create .wants symlink to 'auto' swap devices
As we load unit files lazily, we need to make sure something pulls in swap
units that should be started automatically, otherwise the default dependencies
will never be applied.
This partially reinstates code removed in
commit 64347fc2b983f33e7efb0fd2bb44e133fb9f30f4.
Also don't order swap devices after swap.target when they are 'nofail'.
---
 src/core/swap.c                       |  8 ++++++--
 src/fstab-generator/fstab-generator.c | 18 ++++++++++++++++--
 2 files changed, 22 insertions(+), 4 deletions(-)
diff --git a/src/core/swap.c b/src/core/swap.c
index 3950860..76c7d45 100644
--- a/src/core/swap.c
+++ b/src/core/swap.c
@@ -220,8 +220,12 @@ static int swap_add_default_dependencies(Swap *s) {
         }
         if (!noauto) {
-                r = unit_add_two_dependencies_by_name_inverse(UNIT(s), UNIT_AFTER, (nofail ? UNIT_WANTS : UNIT_REQUIRES),
-                                                      SPECIAL_SWAP_TARGET, NULL, true);
+                if (nofail)
+                        r = unit_add_dependency_by_name_inverse(UNIT(s),
+                                UNIT_WANTS, SPECIAL_SWAP_TARGET, NULL, true);
+                else
+                        r = unit_add_two_dependencies_by_name_inverse(UNIT(s),
+                                UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SWAP_TARGET, NULL, true);
                 if (r < 0)
                         return r;
         }
diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c
index 6ebe8aa..b73dfa4 100644
--- a/src/fstab-generator/fstab-generator.c
+++ b/src/fstab-generator/fstab-generator.c
@@ -66,6 +66,7 @@ static int mount_find_pri(struct mntent *me, int *ret) {
 static int add_swap(const char *what, struct mntent *me) {
         _cleanup_free_ char *name = NULL, *unit = NULL, *lnk = NULL, *device = NULL;
         _cleanup_fclose_ FILE *f = NULL;
+        bool noauto;
         int r, pri = -1;
         assert(what);
@@ -77,6 +78,8 @@ static int add_swap(const char *what, struct mntent *me) {
                 return pri;
         }
+        noauto = !!hasmntopt(me, "noauto");
+
         name = unit_name_from_path(what, ".swap");
         if (!name)
                 return log_oom();
@@ -97,8 +100,7 @@ static int add_swap(const char *what, struct mntent *me) {
         fprintf(f,
                 "# Automatically generated by systemd-fstab-generator\n\n"
                 "[Unit]\n"
-                "SourcePath=/etc/fstab\n"
-                "\n"
+                "SourcePath=/etc/fstab\n\n"
                 "[Swap]\n"
                 "What=%s\n",
                 what);
@@ -114,6 +116,18 @@ static int add_swap(const char *what, struct mntent *me) {
                 return -errno;
         }
+        if (!noauto) {
+                lnk = strjoin(arg_dest, "/" SPECIAL_SWAP_TARGET ".wants/", name, NULL);
+                if (!lnk)
+                        return log_oom();
+
+                mkdir_parents_label(lnk, 0755);
+                if (symlink(unit, lnk) < 0) {
+                        log_error("Failed to create symlink %s: %m", lnk);
+                        return -errno;
+                }
+        }
+
         return 0;
 }
SOURCES/0020-cgroup-add-missing-equals-for-BlockIOWeight.patch
New file
@@ -0,0 +1,22 @@
From f93999bbdbc9e16322d77bda2a4e44c20040808d Mon Sep 17 00:00:00 2001
From: Gao feng <gaofeng@cn.fujitsu.com>
Date: Mon, 16 Sep 2013 09:57:33 +0800
Subject: [PATCH] cgroup: add missing equals for BlockIOWeight
---
 src/core/cgroup.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/core/cgroup.c b/src/core/cgroup.c
index 1f41efc..9277dd6 100644
--- a/src/core/cgroup.c
+++ b/src/core/cgroup.c
@@ -92,7 +92,7 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
                 "%sBlockIOAccounting=%s\n"
                 "%sMemoryAccounting=%s\n"
                 "%sCPUShares=%lu\n"
-                "%sBlockIOWeight%lu\n"
+                "%sBlockIOWeight=%lu\n"
                 "%sMemoryLimit=%" PRIu64 "\n"
                 "%sMemorySoftLimit=%" PRIu64 "\n"
                 "%sDevicePolicy=%s\n",
SOURCES/0021-Assume-that-proc-meminfo-can-be-missing.patch
New file
@@ -0,0 +1,50 @@
From 0fdb6640bb9de89ca739676bbbb43d3a05a42f50 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Sun, 15 Sep 2013 08:40:16 -0400
Subject: [PATCH] Assume that /proc/meminfo can be missing
Travis tests are failing, probably because /proc/meminfo is not available
in the test environment. The same might be true in some virtualized systems,
so just treat missing /proc/meminfo as a sign that hibernation is not
possible.
---
 src/shared/sleep-config.c | 3 ++-
 src/test/test-fileio.c    | 6 +++++-
 2 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/src/shared/sleep-config.c b/src/shared/sleep-config.c
index 5ec7cce..148c4dc 100644
--- a/src/shared/sleep-config.c
+++ b/src/shared/sleep-config.c
@@ -172,7 +172,8 @@ static bool enough_memory_for_hibernation(void) {
         r = get_status_field("/proc/meminfo", "\nSwapFree:", &swapfree);
         if (r < 0) {
-                log_error("Failed to retrieve SwapFree from /proc/meminfo: %s", strerror(-r));
+                log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING,
+                         "Failed to retrieve SwapFree from /proc/meminfo: %s", strerror(-r));
                 return false;
         }
diff --git a/src/test/test-fileio.c b/src/test/test-fileio.c
index 4a4ed79..3511f3a 100644
--- a/src/test/test-fileio.c
+++ b/src/test/test-fileio.c
@@ -232,12 +232,16 @@ static void test_executable_is_script(void) {
 static void test_status_field(void) {
         _cleanup_free_ char *t = NULL, *p = NULL, *s = NULL;
         unsigned long long total, buffers;
+        int r;
         assert_se(get_status_field("/proc/self/status", "\nThreads:", &t) == 0);
         puts(t);
         assert_se(streq(t, "1"));
-        assert_se(get_status_field("/proc/meminfo", "MemTotal:", &p) == 0);
+        r = get_status_field("/proc/meminfo", "MemTotal:", &p);
+        if (r == -ENOENT)
+                return;
+        assert(r == 0);
         puts(p);
         assert_se(safe_atollu(p, &total) == 0);
SOURCES/0022-transaction.c-do-not-point-users-to-logs-when-unit-n.patch
New file
@@ -0,0 +1,63 @@
From a38c3d5d4e94c7e11db1ca22126bb11c6b029886 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Sun, 15 Sep 2013 12:15:38 -0400
Subject: [PATCH] transaction.c: do not point users to logs when unit not found
The logs are unlikely to contain any useful information in this case.
Also, change "walked on cycle path" to "found dependency on", which
is less technical and indicates the direction. With the old message,
I was never sure if prior units depended on later ones, or vice versa.
https://bugzilla.redhat.com/show_bug.cgi?id=996133
https://bugzilla.redhat.com/show_bug.cgi?id=997082
---
 src/core/transaction.c | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/src/core/transaction.c b/src/core/transaction.c
index 27efef7..203070f 100644
--- a/src/core/transaction.c
+++ b/src/core/transaction.c
@@ -344,7 +344,7 @@ static int transaction_verify_order_one(Transaction *tr, Job *j, Job *from, unsi
         assert(!j->transaction_prev);
         /* Does a recursive sweep through the ordering graph, looking
-         * for a cycle. If we find cycle we try to break it. */
+         * for a cycle. If we find a cycle we try to break it. */
         /* Have we seen this before? */
         if (j->generation == generation) {
@@ -371,7 +371,7 @@ static int transaction_verify_order_one(Transaction *tr, Job *j, Job *from, unsi
                         /* logging for j not k here here to provide consistent narrative */
                         log_info_unit(j->unit->id,
-                                      "Walked on cycle path to %s/%s",
+                                      "Found dependency on %s/%s",
                                       k->unit->id, job_type_to_string(k->type));
                         if (!delete &&
@@ -860,7 +860,7 @@ int transaction_add_job_and_dependencies(
                 return -EINVAL;
         }
-        if (type != JOB_STOP && (unit->load_state == UNIT_ERROR || unit->load_state == UNIT_NOT_FOUND)) {
+        if (type != JOB_STOP && unit->load_state == UNIT_ERROR) {
                 dbus_set_error(e, BUS_ERROR_LOAD_FAILED,
                                "Unit %s failed to load: %s. "
                                "See system logs and 'systemctl status %s' for details.",
@@ -870,6 +870,14 @@ int transaction_add_job_and_dependencies(
                 return -EINVAL;
         }
+        if (type != JOB_STOP && unit->load_state == UNIT_NOT_FOUND) {
+                dbus_set_error(e, BUS_ERROR_LOAD_FAILED,
+                               "Unit %s failed to load: %s.",
+                               unit->id,
+                               strerror(-unit->load_error));
+                return -EINVAL;
+        }
+
         if (type != JOB_STOP && unit->load_state == UNIT_MASKED) {
                 dbus_set_error(e, BUS_ERROR_MASKED, "Unit %s is masked.", unit->id);
                 return -EADDRNOTAVAIL;
SOURCES/0023-Verify-validity-of-session-name-when-received-from-o.patch
New file
@@ -0,0 +1,283 @@
From 45f0d8e103c57e9e5e9d92bba1dc2d50b49806de Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Sun, 15 Sep 2013 22:26:56 -0400
Subject: [PATCH] Verify validity of session name when received from outside
Only ASCII letters and digits are allowed.
---
 Makefile.am                | 14 +++++++++++---
 TODO                       |  3 ---
 src/login/login-shared.c   |  8 ++++++++
 src/login/login-shared.h   |  3 +++
 src/login/logind-dbus.c    |  1 +
 src/login/logind-session.c |  1 +
 src/login/logind-session.h |  1 +
 src/login/logind.c         |  6 ++++++
 src/login/sd-login.c       | 12 +++++++-----
 src/shared/cgroup-util.c   |  4 +---
 src/shared/def.h           |  5 +++++
 src/shared/env-util.c      |  5 ++---
 src/shared/replace-var.c   |  3 ++-
 src/shared/unit-name.c     |  5 ++---
 14 files changed, 50 insertions(+), 21 deletions(-)
 create mode 100644 src/login/login-shared.c
 create mode 100644 src/login/login-shared.h
diff --git a/Makefile.am b/Makefile.am
index 7b7539a..6014521 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -2324,7 +2324,10 @@ if HAVE_ACL
 libudev_core_la_SOURCES += \
     src/udev/udev-builtin-uaccess.c \
     src/login/logind-acl.c \
-    src/login/sd-login.c
+    src/login/sd-login.c \
+    src/systemd/sd-login.h \
+    src/login/login-shared.c \
+    src/login/login-shared.h
 libudev_core_la_LIBADD += \
     libsystemd-acl.la
@@ -3759,7 +3762,9 @@ libsystemd_logind_core_la_SOURCES = \
     src/login/logind-session-dbus.c \
     src/login/logind-seat-dbus.c \
     src/login/logind-user-dbus.c \
-    src/login/logind-acl.h
+    src/login/logind-acl.h \
+    src/login/login-shared.c \
+    src/login/login-shared.h
 libsystemd_logind_core_la_CFLAGS = \
     $(AM_CFLAGS) \
@@ -3860,7 +3865,10 @@ tests += \
     test-login-tables
 libsystemd_login_la_SOURCES = \
-    src/login/sd-login.c
+    src/login/sd-login.c \
+    src/systemd/sd-login.h \
+    src/login/login-shared.c \
+    src/login/login-shared.h
 libsystemd_login_la_CFLAGS = \
     $(AM_CFLAGS) \
diff --git a/TODO b/TODO
index 9943b3e..bfeaa81 100644
--- a/TODO
+++ b/TODO
@@ -142,9 +142,6 @@ Features:
 * journald: make sure ratelimit is actually really per-service with the new cgroup changes
-* libsystemd-logind: sd_session_is_active() and friends: verify
-  validity of session name before appending it to a path
-
 * gparted needs to disable auto-activation of mount units somehow, or
   maybe we should stop doing auto-activation of this after boot
   entirely. https://bugzilla.gnome.org/show_bug.cgi?id=701676
diff --git a/src/login/login-shared.c b/src/login/login-shared.c
new file mode 100644
index 0000000..ff13c28
--- /dev/null
+++ b/src/login/login-shared.c
@@ -0,0 +1,8 @@
+#include "login-shared.h"
+#include "def.h"
+
+bool session_id_valid(const char *id) {
+        assert(id);
+
+        return id + strspn(id, LETTERS DIGITS) == '\0';
+}
diff --git a/src/login/login-shared.h b/src/login/login-shared.h
new file mode 100644
index 0000000..728ef00
--- /dev/null
+++ b/src/login/login-shared.h
@@ -0,0 +1,3 @@
+#include <stdbool.h>
+
+bool session_id_valid(const char *id);
diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
index 345df9f..d052e74 100644
--- a/src/login/logind-dbus.c
+++ b/src/login/logind-dbus.c
@@ -554,6 +554,7 @@ static int bus_manager_create_session(Manager *m, DBusMessage *message) {
                  * the audit data and let's better register a new
                  * ID */
                 if (hashmap_get(m->sessions, id)) {
+                        log_warning("Existing logind session ID %s used by new audit session, ignoring", id);
                         audit_id = 0;
                         free(id);
diff --git a/src/login/logind-session.c b/src/login/logind-session.c
index a726fb1..2d22a68 100644
--- a/src/login/logind-session.c
+++ b/src/login/logind-session.c
@@ -41,6 +41,7 @@ Session* session_new(Manager *m, const char *id) {
         assert(m);
         assert(id);
+        assert(session_id_valid(id));
         s = new0(Session, 1);
         if (!s)
diff --git a/src/login/logind-session.h b/src/login/logind-session.h
index edaae8d..9cf6485 100644
--- a/src/login/logind-session.h
+++ b/src/login/logind-session.h
@@ -29,6 +29,7 @@ typedef enum KillWho KillWho;
 #include "logind.h"
 #include "logind-seat.h"
 #include "logind-user.h"
+#include "login-shared.h"
 typedef enum SessionState {
         SESSION_OPENING,  /* Session scope is being created */
diff --git a/src/login/logind.c b/src/login/logind.c
index 9094567..4ef92b8 100644
--- a/src/login/logind.c
+++ b/src/login/logind.c
@@ -684,6 +684,12 @@ int manager_enumerate_sessions(Manager *m) {
                 if (!dirent_is_file(de))
                         continue;
+                if (!session_id_valid(de->d_name)) {
+                        log_warning("Invalid session file name '%s', ignoring.", de->d_name);
+                        r = -EINVAL;
+                        continue;
+                }
+
                 k = manager_add_session(m, de->d_name, &s);
                 if (k < 0) {
                         log_error("Failed to add session by file name %s: %s", de->d_name, strerror(-k));
diff --git a/src/login/sd-login.c b/src/login/sd-login.c
index 8a7838d..71d8c29 100644
--- a/src/login/sd-login.c
+++ b/src/login/sd-login.c
@@ -31,6 +31,7 @@
 #include "sd-login.h"
 #include "strv.h"
 #include "fileio.h"
+#include "login-shared.h"
 _public_ int sd_pid_get_session(pid_t pid, char **session) {
         if (pid < 0)
@@ -226,17 +227,19 @@ static int file_of_session(const char *session, char **_p) {
         assert(_p);
-        if (session)
+        if (session) {
+                if (!session_id_valid(session))
+                        return -EINVAL;
+
                 p = strappend("/run/systemd/sessions/", session);
-        else {
-                char *buf;
+        } else {
+                _cleanup_free_ char *buf = NULL;
                 r = sd_pid_get_session(0, &buf);
                 if (r < 0)
                         return r;
                 p = strappend("/run/systemd/sessions/", buf);
-                free(buf);
         }
         if (!p)
@@ -255,7 +258,6 @@ _public_ int sd_session_is_active(const char *session) {
                 return r;
         r = parse_env_file(p, NEWLINE, "ACTIVE", &s, NULL);
-
         if (r < 0)
                 return r;
diff --git a/src/shared/cgroup-util.c b/src/shared/cgroup-util.c
index 1d545e0..0bffebd 100644
--- a/src/shared/cgroup-util.c
+++ b/src/shared/cgroup-util.c
@@ -1511,9 +1511,7 @@ char *cg_unescape(const char *p) {
 }
 #define CONTROLLER_VALID                        \
-        "0123456789"                            \
-        "abcdefghijklmnopqrstuvwxyz"            \
-        "ABCDEFGHIJKLMNOPQRSTUVWXYZ"            \
+        DIGITS LETTERS                          \
         "_"
 bool cg_controller_is_valid(const char *p, bool allow_named) {
diff --git a/src/shared/def.h b/src/shared/def.h
index 5abb544..edd0bcf 100644
--- a/src/shared/def.h
+++ b/src/shared/def.h
@@ -33,3 +33,8 @@
 #define SIGNALS_CRASH_HANDLER SIGSEGV,SIGILL,SIGFPE,SIGBUS,SIGQUIT,SIGABRT
 #define SIGNALS_IGNORE SIGPIPE
+
+#define DIGITS            "0123456789"
+#define LOWERCASE_LETTERS "abcdefghijklmnopqrstuvwxyz"
+#define UPPERCASE_LETTERS "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+#define LETTERS LOWERCASE_LETTERS UPPERCASE_LETTERS
diff --git a/src/shared/env-util.c b/src/shared/env-util.c
index 6a52fb9..5e29629 100644
--- a/src/shared/env-util.c
+++ b/src/shared/env-util.c
@@ -27,11 +27,10 @@
 #include "utf8.h"
 #include "util.h"
 #include "env-util.h"
+#include "def.h"
 #define VALID_CHARS_ENV_NAME                    \
-        "0123456789"                            \
-        "abcdefghijklmnopqrstuvwxyz"            \
-        "ABCDEFGHIJKLMNOPQRSTUVWXYZ"            \
+        DIGITS LETTERS                          \
         "_"
 #ifndef ARG_MAX
diff --git a/src/shared/replace-var.c b/src/shared/replace-var.c
index e11c57a..478fc43 100644
--- a/src/shared/replace-var.c
+++ b/src/shared/replace-var.c
@@ -24,6 +24,7 @@
 #include "macro.h"
 #include "util.h"
 #include "replace-var.h"
+#include "def.h"
 /*
  * Generic infrastructure for replacing @FOO@ style variables in
@@ -40,7 +41,7 @@ static int get_variable(const char *b, char **r) {
         if (*b != '@')
                 return 0;
-        k = strspn(b + 1, "ABCDEFGHIJKLMNOPQRSTUVWXYZ_");
+        k = strspn(b + 1, UPPERCASE_LETTERS "_");
         if (k <= 0 || b[k+1] != '@')
                 return 0;
diff --git a/src/shared/unit-name.c b/src/shared/unit-name.c
index 1baa6eb..8f6c28e 100644
--- a/src/shared/unit-name.c
+++ b/src/shared/unit-name.c
@@ -26,11 +26,10 @@
 #include "path-util.h"
 #include "util.h"
 #include "unit-name.h"
+#include "def.h"
 #define VALID_CHARS                             \
-        "0123456789"                            \
-        "abcdefghijklmnopqrstuvwxyz"            \
-        "ABCDEFGHIJKLMNOPQRSTUVWXYZ"            \
+        DIGITS LETTERS                          \
         ":-_.\\"
 static const char* const unit_type_table[_UNIT_TYPE_MAX] = {
SOURCES/0024-udev-rules-avoid-erroring-on-trailing-whitespace.patch
New file
@@ -0,0 +1,27 @@
From c4f1b97f45f1685c0a4bcba8c6724ce17bb6af19 Mon Sep 17 00:00:00 2001
From: Dave Reisner <dreisner@archlinux.org>
Date: Mon, 16 Sep 2013 11:22:35 -0400
Subject: [PATCH] udev-rules: avoid erroring on trailing whitespace
https://bugs.archlinux.org/task/36950
---
 src/udev/udev-rules.c | 6 ++++++
 1 file changed, 6 insertions(+)
diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c
index f14158b..6f8b127 100644
--- a/src/udev/udev-rules.c
+++ b/src/udev/udev-rules.c
@@ -1068,6 +1068,12 @@ static int add_rule(struct udev_rules *rules, char *line,
                 enum operation_type op;
                 if (get_key(rules->udev, &linepos, &key, &op, &value) != 0) {
+                        /* Avoid erroring on trailing whitespace. This is probably rare
+                         * so save the work for the error case instead of always trying
+                         * to strip the trailing whitespace with strstrip(). */
+                        while (isblank(*linepos))
+                                linepos++;
+
                         /* If we aren't at the end of the line, this is a parsing error.
                          * Make a best effort to describe where the problem is. */
                         if (*linepos != '\n') {
SOURCES/0025-keymap-Add-Samsung-Series-5-Ultra.patch
New file
@@ -0,0 +1,65 @@
From 3d2b4b62bfc73a38dce90be5cebdc924db42f63c Mon Sep 17 00:00:00 2001
From: Martin Pitt <martinpitt@gnome.org>
Date: Mon, 16 Sep 2013 14:25:44 -0500
Subject: [PATCH] keymap: Add Samsung Series 5 [Ultra]
Also consolidate the wlan key into the "all Samsung" rule to avoid repetition.
Thanks to Mauro Carvalho Chehab!
https://bugzilla.redhat.com/show_bug.cgi?id=989103
---
 hwdb/60-keyboard.hwdb | 17 ++++++++++++-----
 1 file changed, 12 insertions(+), 5 deletions(-)
diff --git a/hwdb/60-keyboard.hwdb b/hwdb/60-keyboard.hwdb
index 53e83ad..3862b4c 100644
--- a/hwdb/60-keyboard.hwdb
+++ b/hwdb/60-keyboard.hwdb
@@ -882,6 +882,8 @@ keyboard:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*
  KEYBOARD_KEY_b1=!prog2                                 # Fn+F7 run Samsung Magic Doctor (keypressed event is generated twice)
  KEYBOARD_KEY_b3=!prog3                                 # Fn+F8 switch power mode (battery/dynamic/performance)
  KEYBOARD_KEY_b4=!wlan                                  # Fn+F9 (X60P)
+ KEYBOARD_KEY_c5=!prog3                                 # Fn+F8 switch power mode (battery/dynamic/performance)
+ KEYBOARD_KEY_d5=!wlan                                  # Fn+F12 wlan/airplane switch
  KEYBOARD_KEY_f7=!f22                                   # Fn+F10 Touchpad on
  KEYBOARD_KEY_f9=!f23                                   # Fn+F10 Touchpad off
@@ -889,9 +891,18 @@ keyboard:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*
 keyboard:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*300E[457]*:pvr*
 keyboard:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*200E[45]*:pvr*
  KEYBOARD_KEY_ce=!                                      # Fn+F1  launch control setting
- KEYBOARD_KEY_d5=!                                      # Fn+F12 Wi-Fi toggle
 # Series 5
+keyboard:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*530U*:pvr*
+ KEYBOARD_KEY_ce=!prog1                                 # Fn+F1 launch settings
+ KEYBOARD_KEY_a8=!                                      # Fn Lock - Function lock on
+ KEYBOARD_KEY_a9=!                                      # Fn Lock - Function lock off
+
+keyboard:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*550P*:pvr*
+ KEYBOARD_KEY_ce=!prog1                                 # Fn+F1 launch settings
+ KEYBOARD_KEY_a8=!                                      # Fn Lock - Function lock on
+ KEYBOARD_KEY_a9=!                                      # Fn Lock - Function lock off
+
 keyboard:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*700Z*:pvr*
  KEYBOARD_KEY_ce=!prog1                                 # Fn+F1 launch settings
  KEYBOARD_KEY_a0=!mute                                  # Fn+F6 mute
@@ -900,7 +911,6 @@ keyboard:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*700Z*:pvr*
  KEYBOARD_KEY_97=!kbdillumdown                          # Fn+F9 keyboard backlight down
  KEYBOARD_KEY_96=!kbdillumup                            # Fn+F10 keyboard backlight up
  KEYBOARD_KEY_b3=!prog3                                 # Fn+F11 fan/cooling mode changer
- KEYBOARD_KEY_d5=!wlan                                  # Fn+F12 wlan/airplane switch
 # Series 9
 keyboard:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*90X3A*:pvr*
@@ -936,9 +946,6 @@ keyboard:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*700Z*:pvr*
 keyboard:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*700T*:pvr*
  KEYBOARD_KEY_ad=leftmeta
-keyboard:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn535U*:pvr*
- KEYBOARD_KEY_d5=!wlan
-
 ###########################################################
 # SONY
 ###########################################################
SOURCES/0026-login-fix-login_is_valid-test.patch
New file
@@ -0,0 +1,149 @@
From 87e08d21857b2b2e59f3480e6d0538b535a5897c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Mon, 16 Sep 2013 11:04:20 -0500
Subject: [PATCH] login: fix login_is_valid test
---
 Makefile.am                   | 10 +++++++++-
 src/login/login-shared.c      | 23 ++++++++++++++++++++++-
 src/login/login-shared.h      | 21 +++++++++++++++++++++
 src/login/test-login-shared.c | 38 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 90 insertions(+), 2 deletions(-)
 create mode 100644 src/login/test-login-shared.c
diff --git a/Makefile.am b/Makefile.am
index 6014521..eae001b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -3836,6 +3836,13 @@ test_login_LDADD = \
     libsystemd-login-internal.la \
     libsystemd-shared.la
+test_login_shared_SOURCES = \
+    src/login/test-login-shared.c
+
+test_login_shared_LDADD = \
+    libsystemd-login-internal.la \
+    libsystemd-shared.la
+
 test_inhibit_SOURCES = \
     src/login/test-inhibit.c
@@ -3862,7 +3869,8 @@ manual_tests += \
     test-inhibit
 tests += \
-    test-login-tables
+    test-login-tables \
+    test-login-shared
 libsystemd_login_la_SOURCES = \
     src/login/sd-login.c \
diff --git a/src/login/login-shared.c b/src/login/login-shared.c
index ff13c28..054c775 100644
--- a/src/login/login-shared.c
+++ b/src/login/login-shared.c
@@ -1,8 +1,29 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+  This file is part of systemd.
+
+  Copyright 2013 Zbigniew Jędrzejewski-Szmek
+
+  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 "login-shared.h"
 #include "def.h"
 bool session_id_valid(const char *id) {
         assert(id);
-        return id + strspn(id, LETTERS DIGITS) == '\0';
+        return id[0] && id[strspn(id, LETTERS DIGITS)] == '\0';
 }
diff --git a/src/login/login-shared.h b/src/login/login-shared.h
index 728ef00..b2787c9 100644
--- a/src/login/login-shared.h
+++ b/src/login/login-shared.h
@@ -1,3 +1,24 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+  This file is part of systemd.
+
+  Copyright 2013 Zbigniew Jędrzejewski-Szmek
+
+  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 <stdbool.h>
 bool session_id_valid(const char *id);
diff --git a/src/login/test-login-shared.c b/src/login/test-login-shared.c
new file mode 100644
index 0000000..2df6029
--- /dev/null
+++ b/src/login/test-login-shared.c
@@ -0,0 +1,38 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+  This file is part of systemd.
+
+  Copyright 2013 Zbigniew Jędrzejewski-Szmek
+
+  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 "macro.h"
+#include "login-shared.h"
+
+static void test_session_id_valid(void) {
+        assert_se(session_id_valid("c1"));
+        assert_se(session_id_valid("1234"));
+
+        assert_se(!session_id_valid("1-2"));
+        assert_se(!session_id_valid(""));
+        assert_se(!session_id_valid("\tid"));
+}
+
+int main(int argc, char* argv[]) {
+        test_session_id_valid();
+
+        return 0;
+}
SOURCES/0027-polkit-Avoid-race-condition-in-scraping-proc.patch
New file
@@ -0,0 +1,74 @@
From 88e8824997b26b821530384bb944e15a63e81301 Mon Sep 17 00:00:00 2001
From: Colin Walters <walters@verbum.org>
Date: Thu, 22 Aug 2013 13:55:21 -0400
Subject: [PATCH] polkit: Avoid race condition in scraping /proc
If a calling process execve()s a setuid program, it can appear to be
uid 0.  Since we're receiving requests over DBus, avoid this by simply
passing system-bus-name as a subject.
https://bugzilla.redhat.com/show_bug.cgi?id=1005142
---
 src/shared/polkit.c | 31 +++++--------------------------
 1 file changed, 5 insertions(+), 26 deletions(-)
diff --git a/src/shared/polkit.c b/src/shared/polkit.c
index cea7074..1c5e9e3 100644
--- a/src/shared/polkit.c
+++ b/src/shared/polkit.c
@@ -38,12 +38,8 @@ int verify_polkit(
 #ifdef ENABLE_POLKIT
         DBusMessage *m = NULL, *reply = NULL;
-        const char *unix_process = "unix-process", *pid = "pid", *starttime = "start-time", *cancel_id = "";
+        const char *system_bus_name = "system-bus-name", *name = "name", *cancel_id = "";
         uint32_t flags = interactive ? 1 : 0;
-        pid_t pid_raw;
-        uint32_t pid_u32;
-        unsigned long long starttime_raw;
-        uint64_t starttime_u64;
         DBusMessageIter iter_msg, iter_struct, iter_array, iter_dict, iter_variant;
         int r;
         dbus_bool_t authorized = FALSE, challenge = FALSE;
@@ -68,14 +64,6 @@ int verify_polkit(
 #ifdef ENABLE_POLKIT
-        pid_raw = bus_get_unix_process_id(c, sender, error);
-        if (pid_raw == 0)
-                return -EINVAL;
-
-        r = get_starttime_of_pid(pid_raw, &starttime_raw);
-        if (r < 0)
-                return r;
-
         m = dbus_message_new_method_call(
                         "org.freedesktop.PolicyKit1",
                         "/org/freedesktop/PolicyKit1/Authority",
@@ -86,22 +74,13 @@ int verify_polkit(
         dbus_message_iter_init_append(m, &iter_msg);
-        pid_u32 = (uint32_t) pid_raw;
-        starttime_u64 = (uint64_t) starttime_raw;
-
         if (!dbus_message_iter_open_container(&iter_msg, DBUS_TYPE_STRUCT, NULL, &iter_struct) ||
-            !dbus_message_iter_append_basic(&iter_struct, DBUS_TYPE_STRING, &unix_process) ||
+            !dbus_message_iter_append_basic(&iter_struct, DBUS_TYPE_STRING, &system_bus_name) ||
             !dbus_message_iter_open_container(&iter_struct, DBUS_TYPE_ARRAY, "{sv}", &iter_array) ||
             !dbus_message_iter_open_container(&iter_array, DBUS_TYPE_DICT_ENTRY, NULL, &iter_dict) ||
-            !dbus_message_iter_append_basic(&iter_dict, DBUS_TYPE_STRING, &pid) ||
-            !dbus_message_iter_open_container(&iter_dict, DBUS_TYPE_VARIANT, "u", &iter_variant) ||
-            !dbus_message_iter_append_basic(&iter_variant, DBUS_TYPE_UINT32, &pid_u32) ||
-            !dbus_message_iter_close_container(&iter_dict, &iter_variant) ||
-            !dbus_message_iter_close_container(&iter_array, &iter_dict) ||
-            !dbus_message_iter_open_container(&iter_array, DBUS_TYPE_DICT_ENTRY, NULL, &iter_dict) ||
-            !dbus_message_iter_append_basic(&iter_dict, DBUS_TYPE_STRING, &starttime) ||
-            !dbus_message_iter_open_container(&iter_dict, DBUS_TYPE_VARIANT, "t", &iter_variant) ||
-            !dbus_message_iter_append_basic(&iter_variant, DBUS_TYPE_UINT64, &starttime_u64) ||
+            !dbus_message_iter_append_basic(&iter_dict, DBUS_TYPE_STRING, &name) ||
+            !dbus_message_iter_open_container(&iter_dict, DBUS_TYPE_VARIANT, "s", &iter_variant) ||
+            !dbus_message_iter_append_basic(&iter_variant, DBUS_TYPE_STRING, &sender) ||
             !dbus_message_iter_close_container(&iter_dict, &iter_variant) ||
             !dbus_message_iter_close_container(&iter_array, &iter_dict) ||
             !dbus_message_iter_close_container(&iter_struct, &iter_array) ||
SOURCES/0028-core-whenever-a-new-PID-is-passed-to-us-make-sure-we.patch
New file
@@ -0,0 +1,71 @@
From f47d0b042f6d0a1661dff9816410162693d1daa2 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Tue, 1 Oct 2013 05:06:56 +0200
Subject: [PATCH] core: whenever a new PID is passed to us, make sure we watch
 it
---
 src/core/service.c | 21 +++++++++++++++------
 1 file changed, 15 insertions(+), 6 deletions(-)
diff --git a/src/core/service.c b/src/core/service.c
index 246a86e..5953f45 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -191,7 +191,13 @@ static int service_set_main_pid(Service *s, pid_t pid) {
         if (pid == getpid())
                 return -EINVAL;
-        service_unwatch_main_pid(s);
+        if (s->main_pid == pid && s->main_pid_known)
+                return 0;
+
+        if (s->main_pid != pid) {
+                service_unwatch_main_pid(s);
+                exec_status_start(&s->main_exec_status, pid);
+        }
         s->main_pid = pid;
         s->main_pid_known = true;
@@ -205,8 +211,6 @@ static int service_set_main_pid(Service *s, pid_t pid) {
         } else
                 s->main_pid_alien = false;
-        exec_status_start(&s->main_exec_status, pid);
-
         return 0;
 }
@@ -2698,8 +2702,10 @@ static int service_deserialize_item(Unit *u, const char *key, const char *value,
                 if (parse_pid(value, &pid) < 0)
                         log_debug_unit(u->id, "Failed to parse main-pid value %s", value);
-                else
-                        service_set_main_pid(s, (pid_t) pid);
+                else {
+                        service_set_main_pid(s, pid);
+                        unit_watch_pid(UNIT(s), pid);
+                }
         } else if (streq(key, "main-pid-known")) {
                 int b;
@@ -3391,6 +3397,7 @@ static void service_notify_message(Unit *u, pid_t pid, char **tags) {
                         log_debug_unit(u->id,
                                        "%s: got %s", u->id, e);
                         service_set_main_pid(s, pid);
+                        unit_watch_pid(UNIT(s), pid);
                 }
         }
@@ -3687,8 +3694,10 @@ static void service_bus_query_pid_done(
             (s->state == SERVICE_START ||
              s->state == SERVICE_START_POST ||
              s->state == SERVICE_RUNNING ||
-             s->state == SERVICE_RELOAD))
+             s->state == SERVICE_RELOAD)){
                 service_set_main_pid(s, pid);
+                unit_watch_pid(UNIT(s), pid);
+        }
 }
 int service_set_socket_fd(Service *s, int fd, Socket *sock) {
SOURCES/0029-remove-user-.service.patch
New file
@@ -0,0 +1,91 @@
From 40810e62f4df958b2465dcc1923b8b827fb778e8 Mon Sep 17 00:00:00 2001
From: Harald Hoyer <harald@redhat.com>
Date: Wed, 30 Oct 2013 18:22:49 +0100
Subject: [PATCH] remove user@.service
fixes rhbz#1019738
---
 Makefile.am             |  2 --
 src/login/logind-user.c | 42 ------------------------------------------
 2 files changed, 44 deletions(-)
diff --git a/Makefile.am b/Makefile.am
index eae001b..25bfd91 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -435,7 +435,6 @@ nodist_systemunit_DATA = \
     units/systemd-sysctl.service \
     units/emergency.service \
     units/rescue.service \
-    units/user@.service \
     units/systemd-hibernate.service \
     units/systemd-hybrid-sleep.service \
     units/systemd-suspend.service \
@@ -484,7 +483,6 @@ EXTRA_DIST += \
     units/user/systemd-exit.service.in \
     units/systemd-fsck@.service.in \
     units/systemd-fsck-root.service.in \
-    units/user@.service.in \
     units/systemd-udevd.service \
     units/systemd-udev-trigger.service \
     units/systemd-udev-settle.service \
diff --git a/src/login/logind-user.c b/src/login/logind-user.c
index adbe638..9cc186b 100644
--- a/src/login/logind-user.c
+++ b/src/login/logind-user.c
@@ -365,43 +365,6 @@ static int user_start_slice(User *u) {
         return 0;
 }
-static int user_start_service(User *u) {
-        DBusError error;
-        char *job;
-        int r;
-
-        assert(u);
-
-        dbus_error_init(&error);
-
-        if (!u->service) {
-                char lu[DECIMAL_STR_MAX(unsigned long) + 1], *service;
-                sprintf(lu, "%lu", (unsigned long) u->uid);
-
-                service = unit_name_build("user", lu, ".service");
-                if (!service)
-                        return log_oom();
-
-                r = manager_start_unit(u->manager, service, &error, &job);
-                if (r < 0) {
-                        log_error("Failed to start user service: %s", bus_error(&error, r));
-                        dbus_error_free(&error);
-
-                        free(service);
-                } else {
-                        u->service = service;
-
-                        free(u->service_job);
-                        u->service_job = job;
-                }
-        }
-
-        if (u->service)
-                hashmap_put(u->manager->user_units, u->service, u);
-
-        return 0;
-}
-
 int user_start(User *u) {
         int r;
@@ -422,11 +385,6 @@ int user_start(User *u) {
         if (r < 0)
                 return r;
-        /* Spawn user systemd */
-        r = user_start_service(u);
-        if (r < 0)
-                return r;
-
         if (!dual_timestamp_is_set(&u->timestamp))
                 dual_timestamp_get(&u->timestamp);
SOURCES/0030-cgroup-always-enable-memory.use_hierarchy-for-all-cg.patch
New file
@@ -0,0 +1,27 @@
From 8986b8ccd7ea39d75246b72f497a4131a278f3bb Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Mon, 23 Sep 2013 16:02:31 -0500
Subject: [PATCH] cgroup: always enable memory.use_hierarchy= for all cgroups
 in the memory hierarchy
The non-hierarchial mode contradicts the whole idea of a cgroup tree so
let's not support this. In the future the kernel will only support the
hierarchial logic anyway.
---
 src/core/cgroup.c | 3 +++
 1 file changed, 3 insertions(+)
diff --git a/src/core/cgroup.c b/src/core/cgroup.c
index 9277dd6..7f29afb 100644
--- a/src/core/cgroup.c
+++ b/src/core/cgroup.c
@@ -678,6 +678,9 @@ int manager_setup_cgroup(Manager *m) {
         /* 6. Figure out which controllers are supported */
         m->cgroup_supported = cg_mask_supported();
+        /* 7.  Always enable hierarchial support if it exists... */
+        cg_set_attribute("memory", "/", "memory.use_hierarchy", "1");
+
         return 0;
 }
SOURCES/0031-logind-return-EINVAL-when-PID-is-wrong.patch
New file
@@ -0,0 +1,45 @@
From 07c3b93b709a601398ce5e06d48f215d097ed959 Mon Sep 17 00:00:00 2001
From: Lukas Nykryn <lnykryn@redhat.com>
Date: Tue, 24 Sep 2013 16:27:20 +0200
Subject: [PATCH] logind: return -EINVAL when PID is wrong
dbus-send --print-reply --system --dest=org.freedesktop.login1
/org/freedesktop/login1 org.freedesktop.login1.Manager.GetUserByPID
uint32:0
causes
systemd-logind[29843]: Assertion 'pid >= 1' failed at
src/login/logind.c:938, function manager_get_user_by_pid(). Aborting.
---
 src/login/logind.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/src/login/logind.c b/src/login/logind.c
index 4ef92b8..afc737c 100644
--- a/src/login/logind.c
+++ b/src/login/logind.c
@@ -914,9 +914,11 @@ int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session) {
         int r;
         assert(m);
-        assert(pid >= 1);
         assert(session);
+        if (pid < 1)
+                return -EINVAL;
+
         r = cg_pid_get_unit(pid, &unit);
         if (r < 0)
                 return r;
@@ -935,9 +937,11 @@ int manager_get_user_by_pid(Manager *m, pid_t pid, User **user) {
         int r;
         assert(m);
-        assert(pid >= 1);
         assert(user);
+        if (pid < 1)
+                return -EINVAL;
+
         r = cg_pid_get_slice(pid, &unit);
         if (r < 0)
                 return r;
SOURCES/0032-core-drop-some-out-of-date-references-to-cgroup-sett.patch
New file
@@ -0,0 +1,197 @@
From 873b06ca6f97f7288c98647fa5e761847122a382 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Thu, 26 Sep 2013 22:49:44 +0200
Subject: [PATCH] core: drop some out-of-date references to cgroup settings
---
 man/systemd-cgtop.xml       | 36 +++++++++++++++---------------------
 man/systemd-system.conf.xml | 27 +--------------------------
 man/systemd.unit.xml        |  5 ++++-
 src/core/dbus-manager.c     | 27 ---------------------------
 src/core/system.conf        |  3 +--
 src/core/user.conf          |  1 -
 6 files changed, 21 insertions(+), 78 deletions(-)
diff --git a/man/systemd-cgtop.xml b/man/systemd-cgtop.xml
index 0e9e5e6..51549c4 100644
--- a/man/systemd-cgtop.xml
+++ b/man/systemd-cgtop.xml
@@ -73,30 +73,23 @@
                 only accounted for control groups in the
                 <literal>cpuacct</literal> hierarchy, memory usage
                 only for those in <literal>memory</literal> and disk
-                I/O usage for those in
-                <literal>blkio</literal>. <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>
-                by default places all services in their own control
-                group in the <literal>cpuacct</literal> hierarchy, but
-                not in <literal>memory</literal> nor
-                <literal>blkio</literal>. If resource monitoring for
-                these resources is required, it is recommended to add
-                <literal>blkio</literal> and <literal>memory</literal>
-                to the <varname>DefaultControllers=</varname> setting
-                in <filename>/etc/systemd/system.conf</filename> (see
-                <citerefentry><refentrytitle>systemd-system.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>
-                for details). Alternatively, it is possible to enable
-                resource accounting individually for services, by
-                making use of the <varname>ControlGroup=</varname>
-                option in the unit files (See
-                <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+                I/O usage for those in <literal>blkio</literal>. If
+                resource monitoring for these resources is required,
+                it is recommended to add the
+                <varname>CPUAccounting=1</varname>,
+                <varname>MemoryAccounting=1</varname> and
+                <varname>BlockIOAccounting=1</varname> settings in the
+                unit files in question (See
+                <citerefentry><refentrytitle>systemd.cgroup</refentrytitle><manvolnum>5</manvolnum></citerefentry>
                 for details).</para>
                 <para>To emphasize this: unless
-                <literal>blkio</literal> and <literal>memory</literal>
-                are enabled for the services in question with either
-                of the options suggested above no resource accounting
-                will be available for system services and the data shown
-                by <command>systemd-cgtop</command> will be
+                <literal>CPUAccounting=1</literal>,
+                <literal>MemoryAccounting=1</literal> and
+                <literal>BlockIOAccounting=1</literal> are enabled for
+                the services in question no resource accounting will
+                be available for system services and the data shown by
+                <command>systemd-cgtop</command> will be
                 incomplete.</para>
         </refsect1>
@@ -281,6 +274,7 @@
                         <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
                         <citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
                         <citerefentry><refentrytitle>systemd-cgls</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+                        <citerefentry><refentrytitle>systemd.cgroup</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
                         <citerefentry><refentrytitle>top</refentrytitle><manvolnum>1</manvolnum></citerefentry>
                 </para>
         </refsect1>
diff --git a/man/systemd-system.conf.xml b/man/systemd-system.conf.xml
index c52e590..e8cf8a9 100644
--- a/man/systemd-system.conf.xml
+++ b/man/systemd-system.conf.xml
@@ -104,32 +104,7 @@
                         </varlistentry>
                         <varlistentry>
-                                <term><varname>DefaultControllers=cpu</varname></term>
-
-                                <listitem><para>Configures in which
-                                control group hierarchies to create
-                                per-service cgroups automatically, in
-                                addition to the
-                                <literal>name=systemd</literal> named
-                                hierarchy. Defaults to
-                                <literal>cpu</literal>. Takes a
-                                space-separated list of controller
-                                names. Pass the empty string to ensure
-                                that systemd does not touch any
-                                hierarchies but its own.</para>
-
-                                <para>Note that the default value of
-                                'cpu' will make realtime scheduling
-                                unavailable to system services. See
-                                <ulink
-                                url="http://www.freedesktop.org/wiki/Software/systemd/MyServiceCantGetRealtime">My
-                                Service Can't Get Realtime!</ulink>
-                                for more
-                                information.</para></listitem>
-                        </varlistentry>
-
-                        <varlistentry>
-                                <term><varname>JoinControllers=cpu,cpuacct,cpuset net_cls,netprio</varname></term>
+                                <term><varname>JoinControllers=cpu,cpuacct net_cls,netprio</varname></term>
                                 <listitem><para>Configures controllers
                                 that shall be mounted in a single
diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml
index d61426a..5c8b8e8 100644
--- a/man/systemd.unit.xml
+++ b/man/systemd.unit.xml
@@ -1241,7 +1241,10 @@
                       <row>
                         <entry><literal>%R</literal></entry>
                         <entry>Parent directory of the control group path where units are placed.</entry>
-                        <entry>For system instances this usually resolves to <filename>/</filename>, except in containers, where this resolves to the container's root directory. This specifier is particularly useful in the <varname>ControlGroup=</varname> setting (see <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>).</entry>
+                        <entry>For system instances this usually
+                        resolves to <filename>/</filename>, except in
+                        containers, where this resolves to the
+                        container's root directory.</entry>
                       </row>
                       <row>
                         <entry><literal>%t</literal></entry>
diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
index 75e2e45..676a07f 100644
--- a/src/core/dbus-manager.c
+++ b/src/core/dbus-manager.c
@@ -103,32 +103,6 @@
         "  <method name=\"ResetFailedUnit\">\n"                         \
         "   <arg name=\"name\" type=\"s\" direction=\"in\"/>\n"         \
         "  </method>\n"                                                 \
-        "  <method name=\"SetUnitControlGroup\">\n"                     \
-        "   <arg name=\"name\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"group\" type=\"s\" direction=\"in\"/>\n"        \
-        "   <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n"         \
-        "  </method>\n"                                                 \
-        "  <method name=\"UnsetUnitControlGroup\">\n"                   \
-        "   <arg name=\"name\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"group\" type=\"s\" direction=\"in\"/>\n"        \
-        "   <arg name=\"mode\" type=\"s\" direction=\"in\"\n/>"         \
-        "  </method>\n"                                                 \
-        "  <method name=\"GetUnitControlGroupAttribute\">\n"            \
-        "   <arg name=\"name\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"attribute\" type=\"s\" direction=\"in\"/>\n"    \
-        "   <arg name=\"values\" type=\"as\" direction=\"out\"/>\n"     \
-        "  </method>\n"                                                 \
-        "  <method name=\"SetUnitControlGroupAttribute\">\n"            \
-        "   <arg name=\"name\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"attribute\" type=\"s\" direction=\"in\"/>\n"    \
-        "   <arg name=\"values\" type=\"as\" direction=\"in\"/>\n"      \
-        "   <arg name=\"mode\" type=\"s\" direction=\"in\"\n/>"         \
-        "  </method>\n"                                                 \
-        "  <method name=\"UnsetUnitControlGroupAttributes\">\n"         \
-        "   <arg name=\"name\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"attribute\" type=\"s\" direction=\"in\"/>\n"    \
-        "   <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n"         \
-        "  </method>\n"                                                 \
         "  <method name=\"GetJob\">\n"                                  \
         "   <arg name=\"id\" type=\"u\" direction=\"in\"/>\n"           \
         "   <arg name=\"job\" type=\"o\" direction=\"out\"/>\n"         \
@@ -316,7 +290,6 @@
         "  <property name=\"ConfirmSpawn\" type=\"b\" access=\"read\"/>\n" \
         "  <property name=\"ShowStatus\" type=\"b\" access=\"read\"/>\n" \
         "  <property name=\"UnitPath\" type=\"as\" access=\"read\"/>\n" \
-        "  <property name=\"DefaultControllers\" type=\"as\" access=\"read\"/>\n" \
         "  <property name=\"DefaultStandardOutput\" type=\"s\" access=\"read\"/>\n" \
         "  <property name=\"DefaultStandardError\" type=\"s\" access=\"read\"/>\n" \
         "  <property name=\"RuntimeWatchdogUSec\" type=\"t\" access=\"readwrite\"/>\n" \
diff --git a/src/core/system.conf b/src/core/system.conf
index f2817bc..7b03c87 100644
--- a/src/core/system.conf
+++ b/src/core/system.conf
@@ -17,10 +17,9 @@
 #ShowStatus=yes
 #CrashChVT=1
 #CPUAffinity=1 2
-#DefaultControllers=cpu
 #DefaultStandardOutput=journal
 #DefaultStandardError=inherit
-#JoinControllers=cpu,cpuacct,cpuset net_cls,net_prio
+#JoinControllers=cpu,cpuacct net_cls,net_prio
 #RuntimeWatchdogSec=0
 #ShutdownWatchdogSec=10min
 #CapabilityBoundingSet=
diff --git a/src/core/user.conf b/src/core/user.conf
index 4252451..4a0129a 100644
--- a/src/core/user.conf
+++ b/src/core/user.conf
@@ -12,6 +12,5 @@
 #LogTarget=console
 #LogColor=yes
 #LogLocation=no
-#DefaultControllers=cpu
 #DefaultStandardOutput=inherit
 #DefaultStandardError=inherit
SOURCES/0033-man-explain-NAME-in-systemctl-man-page.patch
New file
@@ -0,0 +1,33 @@
From 29acf51b6a3ea9305752c9c4dacf1289a1edacb5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?V=C3=A1clav=20Pavl=C3=ADn?= <vpavlin@redhat.com>
Date: Thu, 31 Oct 2013 14:36:41 +0100
Subject: [PATCH] man: explain NAME in systemctl man page
---
 man/systemctl.xml | 13 +++++++++++++
 1 file changed, 13 insertions(+)
diff --git a/man/systemctl.xml b/man/systemctl.xml
index b043581..51c34b7 100644
--- a/man/systemctl.xml
+++ b/man/systemctl.xml
@@ -63,6 +63,19 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>.
     introspect and control the state of the
     <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>
     system and service manager.</para>
+
+    <para>For Unit Commands the <replaceable>NAME</replaceable> represents full name of unit.
+    <programlisting>
+systemctl start foo.service
+    </programlisting>
+    For Unit File Commands the <replaceable>NAME</replaceable> represents full name of the unit file, or absolute path to the unit file.
+    <programlisting>
+systemctl start /path/to/foo.service
+    </programlisting>
+    While working with services/service files, <command>systemctl</command> is able to append .service suffix when it is missing.
+    <programlisting>
+systemctl start foo
+    </programlisting></para>
   </refsect1>
   <refsect1>
SOURCES/0034-journald-accept-EPOLLERR-from-dev-kmsg.patch
New file
@@ -0,0 +1,69 @@
From 21deaace3a2ce9531443279a7c36a0fc068bdea7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Thu, 19 Sep 2013 16:57:57 -0500
Subject: [PATCH] journald: accept EPOLLERR from /dev/kmsg
Also print out unexpected epoll events explictly.
---
 src/journal/journald-server.c | 20 +++++++++++++++-----
 1 file changed, 15 insertions(+), 5 deletions(-)
diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c
index ba211b3..c252710 100644
--- a/src/journal/journald-server.c
+++ b/src/journal/journald-server.c
@@ -1075,7 +1075,8 @@ int process_event(Server *s, struct epoll_event *ev) {
                 ssize_t n;
                 if (ev->events != EPOLLIN) {
-                        log_error("Got invalid event from epoll.");
+                        log_error("Got invalid event from epoll for %s: %"PRIx32,
+                                  "signal fd", ev->events);
                         return -EIO;
                 }
@@ -1128,8 +1129,12 @@ int process_event(Server *s, struct epoll_event *ev) {
         } else if (ev->data.fd == s->dev_kmsg_fd) {
                 int r;
-                if (ev->events != EPOLLIN) {
-                        log_error("Got invalid event from epoll.");
+                if (ev->events & EPOLLERR)
+                        log_warning("/dev/kmsg buffer overrun, some messages lost.");
+
+                if (!(ev->events & EPOLLIN)) {
+                        log_error("Got invalid event from epoll for %s: %"PRIx32,
+                                  "/dev/kmsg", ev->events);
                         return -EIO;
                 }
@@ -1143,7 +1148,9 @@ int process_event(Server *s, struct epoll_event *ev) {
                    ev->data.fd == s->syslog_fd) {
                 if (ev->events != EPOLLIN) {
-                        log_error("Got invalid event from epoll.");
+                        log_error("Got invalid event from epoll for %s: %"PRIx32,
+                                  ev->data.fd == s->native_fd ? "native fd" : "syslog fd",
+                                  ev->events);
                         return -EIO;
                 }
@@ -1264,7 +1271,8 @@ int process_event(Server *s, struct epoll_event *ev) {
         } else if (ev->data.fd == s->stdout_fd) {
                 if (ev->events != EPOLLIN) {
-                        log_error("Got invalid event from epoll.");
+                        log_error("Got invalid event from epoll for %s: %"PRIx32,
+                                  "stdout fd", ev->events);
                         return -EIO;
                 }
@@ -1275,6 +1283,8 @@ int process_event(Server *s, struct epoll_event *ev) {
                 StdoutStream *stream;
                 if ((ev->events|EPOLLIN|EPOLLHUP) != (EPOLLIN|EPOLLHUP)) {
+                        log_error("Got invalid event from epoll for %s: %"PRIx32,
+                                  "stdout stream", ev->events);
                         log_error("Got invalid event from epoll.");
                         return -EIO;
                 }
SOURCES/0035-journald-avoid-NSS-in-journald.patch
New file
@@ -0,0 +1,89 @@
From 6359b8041144a0571853b1dcad55ad60922af55d Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Tue, 17 Sep 2013 16:42:36 -0500
Subject: [PATCH] journald: avoid NSS in journald
In order to avoid a deadlock between journald looking up the
"systemd-journal" group name, and nscd (or anyother NSS backing daemon)
logging something back to the journal avoid all NSS in journald the same
way as we avoid it from PID 1.
With this change we rely on the kernel file system logic to adjust the
group of created journal files via the SETGID bit on the journal
directory. To ensure that it is always set, even after the user created
it with a simply "mkdir" on the shell we fix it up via tmpfiles on boot.
---
 src/journal/journald-server.c | 25 ++-----------------------
 src/journal/journald-server.h |  3 ---
 tmpfiles.d/systemd.conf       |  3 +++
 3 files changed, 5 insertions(+), 26 deletions(-)
diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c
index c252710..8007b05 100644
--- a/src/journal/journald-server.c
+++ b/src/journal/journald-server.c
@@ -180,25 +180,6 @@ static uint64_t available_space(Server *s, bool verbose) {
         return s->cached_available_space;
 }
-static void server_read_file_gid(Server *s) {
-        const char *g = "systemd-journal";
-        int r;
-
-        assert(s);
-
-        if (s->file_gid_valid)
-                return;
-
-        r = get_group_creds(&g, &s->file_gid);
-        if (r < 0)
-                log_warning("Failed to resolve '%s' group: %s", g, strerror(-r));
-
-        /* if we couldn't read the gid, then it will be 0, but that's
-         * fine and we shouldn't try to resolve the group again, so
-         * let's just pretend it worked right-away. */
-        s->file_gid_valid = true;
-}
-
 void server_fix_perms(Server *s, JournalFile *f, uid_t uid) {
         int r;
 #ifdef HAVE_ACL
@@ -209,11 +190,9 @@ void server_fix_perms(Server *s, JournalFile *f, uid_t uid) {
         assert(f);
-        server_read_file_gid(s);
-
-        r = fchmod_and_fchown(f->fd, 0640, 0, s->file_gid);
+        r = fchmod(f->fd, 0640);
         if (r < 0)
-                log_warning("Failed to fix access mode/rights on %s, ignoring: %s", f->path, strerror(-r));
+                log_warning("Failed to fix access mode on %s, ignoring: %s", f->path, strerror(-r));
 #ifdef HAVE_ACL
         if (uid <= 0)
diff --git a/src/journal/journald-server.h b/src/journal/journald-server.h
index e856ef2..0393e38 100644
--- a/src/journal/journald-server.h
+++ b/src/journal/journald-server.h
@@ -97,9 +97,6 @@ typedef struct Server {
         usec_t max_file_usec;
         usec_t oldest_file_usec;
-        gid_t file_gid;
-        bool file_gid_valid;
-
         LIST_HEAD(StdoutStream, stdout_streams);
         unsigned n_stdout_streams;
diff --git a/tmpfiles.d/systemd.conf b/tmpfiles.d/systemd.conf
index 4924b4e..c397c71 100644
--- a/tmpfiles.d/systemd.conf
+++ b/tmpfiles.d/systemd.conf
@@ -23,3 +23,6 @@ d /run/systemd/machines 0755 root root -
 d /run/systemd/shutdown 0755 root root -
 F /run/nologin 0644 - - - "System is booting up."
+
+m /var/log/journal 2755 root systemd-journal - -
+m /var/log/journal/%m 2755 root systemd-journal - -
SOURCES/0036-libudev-add-missing-global-to-symbol-export.patch
New file
@@ -0,0 +1,20 @@
From 23e9bb8dc174e2418c852361ee4ca7dc0474b879 Mon Sep 17 00:00:00 2001
From: Kay Sievers <kay@vrfy.org>
Date: Tue, 17 Sep 2013 16:37:42 -0500
Subject: [PATCH] libudev: add missing 'global' to symbol export
---
 src/libudev/libudev.sym | 1 +
 1 file changed, 1 insertion(+)
diff --git a/src/libudev/libudev.sym b/src/libudev/libudev.sym
index 8e09430..1e6f885 100644
--- a/src/libudev/libudev.sym
+++ b/src/libudev/libudev.sym
@@ -109,5 +109,6 @@ global:
 } LIBUDEV_189;
 LIBUDEV_199 {
+global:
         udev_device_set_sysattr_value;
 } LIBUDEV_196;
SOURCES/0037-gpt-auto-generator-do-not-assume-that-dev-block-u-u-.patch
New file
@@ -0,0 +1,206 @@
From cb6800ec93c7d49f5f43355fef44f6797759cc0a Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Tue, 17 Sep 2013 18:04:40 -0500
Subject: [PATCH] gpt-auto-generator: do not assume that /dev/block/%u:%u is
 useable
The generator might run before udev, and udev sets up the /dev/block/
symlinks, hence we cannot use them from the gpt generator. Instead,
manually translate a major/minor to a device node.
---
 src/gpt-auto-generator/gpt-auto-generator.c | 109 +++++++++++++++++++---------
 1 file changed, 74 insertions(+), 35 deletions(-)
diff --git a/src/gpt-auto-generator/gpt-auto-generator.c b/src/gpt-auto-generator/gpt-auto-generator.c
index 880661e..ca54925 100644
--- a/src/gpt-auto-generator/gpt-auto-generator.c
+++ b/src/gpt-auto-generator/gpt-auto-generator.c
@@ -55,18 +55,13 @@ static inline void blkid_free_probep(blkid_probe *b) {
 }
 #define _cleanup_blkid_freep_probe_ _cleanup_(blkid_free_probep)
-static int verify_gpt_partition(dev_t dev, sd_id128_t *type, unsigned *nr, char **fstype) {
-        _cleanup_free_ char *t = NULL;
+static int verify_gpt_partition(const char *node, sd_id128_t *type, unsigned *nr, char **fstype) {
         _cleanup_blkid_freep_probe_ blkid_probe b = NULL;
         const char *v;
         int r;
-        r = asprintf(&t, "/dev/block/%u:%u", major(dev), minor(dev));
-        if (r < 0)
-                return -ENOMEM;
-
         errno = 0;
-        b = blkid_new_probe_from_filename(t);
+        b = blkid_new_probe_from_filename(node);
         if (!b)
                 return errno != 0 ? -errno : -ENOMEM;
@@ -237,8 +232,7 @@ static int add_home(const char *path, const char *fstype) {
         return 0;
 }
-static int enumerate_partitions(dev_t dev) {
-        struct udev *udev;
+static int enumerate_partitions(struct udev *udev, dev_t dev) {
         struct udev_enumerate *e = NULL;
         struct udev_device *parent = NULL, *d = NULL;
         struct udev_list_entry *first, *item;
@@ -246,10 +240,6 @@ static int enumerate_partitions(dev_t dev) {
         _cleanup_free_ char *home = NULL, *home_fstype = NULL;
         int r;
-        udev = udev_new();
-        if (!udev)
-                return log_oom();
-
         e = udev_enumerate_new(udev);
         if (!e) {
                 r = log_oom();
@@ -294,7 +284,6 @@ static int enumerate_partitions(dev_t dev) {
                 struct udev_device *q;
                 sd_id128_t type_id;
                 unsigned nr;
-                dev_t sub;
                 q = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item));
                 if (!q) {
@@ -314,12 +303,10 @@ static int enumerate_partitions(dev_t dev) {
                         goto finish;
                 }
-                sub = udev_device_get_devnum(q);
-
-                r = verify_gpt_partition(sub, &type_id, &nr, &fstype);
+                r = verify_gpt_partition(node, &type_id, &nr, &fstype);
                 if (r < 0) {
-                        log_error("Failed to verify GPT partition /dev/block/%u:%u: %s",
-                                  major(sub), minor(sub), strerror(-r));
+                        log_error("Failed to verify GPT partition %s: %s",
+                                  node, strerror(-r));
                         udev_device_unref(q);
                         goto finish;
                 }
@@ -360,8 +347,6 @@ finish:
         if (e)
                 udev_enumerate_unref(e);
-        if (udev)
-                udev_unref(udev);
         return r;
 }
@@ -440,13 +425,50 @@ static int get_block_device(const char *path, dev_t *dev) {
         return 0;
 }
+static int devno_to_devnode(struct udev *udev, dev_t devno, char **ret) {
+        struct udev_device *d = NULL;
+        const char *t;
+        char *n;
+        int r;
+
+        d = udev_device_new_from_devnum(udev, 'b', devno);
+        if (!d) {
+                r = log_oom();
+                goto finish;
+        }
+
+        t = udev_device_get_devnode(d);
+        if (!t) {
+                r = -ENODEV;
+                goto finish;
+        }
+
+        n = strdup(t);
+        if (!n) {
+                r = -ENOMEM;
+                goto finish;
+        }
+
+        *ret = n;
+        r = 0;
+
+finish:
+        if (d)
+                udev_device_unref(d);
+
+        return r;
+}
+
 int main(int argc, char *argv[]) {
-        dev_t dev;
+        _cleanup_free_ char *node = NULL;
+        struct udev *udev = NULL;
+        dev_t devno;
         int r;
         if (argc > 1 && argc != 4) {
                 log_error("This program takes three or no arguments.");
-                return EXIT_FAILURE;
+                r = -EINVAL;
+                goto finish;
         }
         if (argc > 1)
@@ -458,31 +480,48 @@ int main(int argc, char *argv[]) {
         umask(0022);
-        if (in_initrd())
-                return EXIT_SUCCESS;
+        if (in_initrd()) {
+                r = 0;
+                goto finish;
+        }
-        r = get_block_device("/", &dev);
+        r = get_block_device("/", &devno);
         if (r < 0) {
                 log_error("Failed to determine block device of root file system: %s", strerror(-r));
-                return EXIT_FAILURE;
+                goto finish;
         }
         if (r == 0) {
                 log_debug("Root file system not on a (single) block device.");
-                return EXIT_SUCCESS;
+                goto finish;
+        }
+
+        udev = udev_new();
+        if (!udev) {
+                r = log_oom();
+                goto finish;
+        }
+
+        r = devno_to_devnode(udev, devno, &node);
+        if (r < 0) {
+                log_error("Failed to determine block device node from major/minor: %s", strerror(-r));
+                goto finish;
         }
-        log_debug("Root device /dev/block/%u:%u.", major(dev), minor(dev));
+        log_debug("Root device %s.", node);
-        r = verify_gpt_partition(dev, NULL, NULL, NULL);
+        r = verify_gpt_partition(node, NULL, NULL, NULL);
         if (r < 0) {
-                log_error("Failed to verify GPT partition /dev/block/%u:%u: %s",
-                          major(dev), minor(dev), strerror(-r));
-                return EXIT_FAILURE;
+                log_error("Failed to verify GPT partition %s: %s", node, strerror(-r));
+                goto finish;
         }
         if (r == 0)
-                return EXIT_SUCCESS;
+                goto finish;
+
+        r = enumerate_partitions(udev, devno);
-        r = enumerate_partitions(dev);
+finish:
+        if (udev)
+                udev_unref(udev);
         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
 }
SOURCES/0038-logind-put-correct-user-object-paths-in-introspectio.patch
New file
@@ -0,0 +1,23 @@
From 31ad5f9f7291e5f97e62402f3198c9a5161548c1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mantas=20Mikul=C4=97nas?= <grawity@gmail.com>
Date: Fri, 20 Sep 2013 18:14:02 +0300
Subject: [PATCH] logind: put correct user object paths in introspection data
Sync with user_bus_path() in logind-user-dbus.c
---
 src/login/logind-dbus.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
index d052e74..77dda10 100644
--- a/src/login/logind-dbus.c
+++ b/src/login/logind-dbus.c
@@ -2256,7 +2256,7 @@ static DBusHandlerResult manager_message_handler(
                 }
                 HASHMAP_FOREACH(user, m->users, i)
-                        fprintf(f, "<node name=\"user/%llu\"/>", (unsigned long long) user->uid);
+                        fprintf(f, "<node name=\"user/_%llu\"/>", (unsigned long long) user->uid);
                 HASHMAP_FOREACH(session, m->sessions, i) {
                         p = bus_path_escape(session->id);
SOURCES/0039-Fix-obsolete-references-to-systemd-random-seed-load..patch
New file
@@ -0,0 +1,38 @@
From fc8c5e4ff8248fa5548de63a5b96d1d9cf2be425 Mon Sep 17 00:00:00 2001
From: Eelco Dolstra <eelco.dolstra@logicblox.com>
Date: Sun, 22 Sep 2013 20:38:24 +0200
Subject: [PATCH] Fix obsolete references to systemd-random-seed-load.service
This service was merged with systemd-random-seed-save.service in
c35b956d34bbb8bb208e49e45de2c103ca11911c.
---
 src/cryptsetup/cryptsetup-generator.c | 2 +-
 units/systemd-random-seed.service.in  | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c
index ba6efa6..8792e6b 100644
--- a/src/cryptsetup/cryptsetup-generator.c
+++ b/src/cryptsetup/cryptsetup-generator.c
@@ -129,7 +129,7 @@ static int create_disk(
                 if (streq(password, "/dev/urandom") ||
                     streq(password, "/dev/random") ||
                     streq(password, "/dev/hw_random"))
-                        fputs("After=systemd-random-seed-load.service\n", f);
+                        fputs("After=systemd-random-seed.service\n", f);
                 else if (!streq(password, "-") &&
                          !streq(password, "none"))
                         fprintf(f,
diff --git a/units/systemd-random-seed.service.in b/units/systemd-random-seed.service.in
index 0c21a04..1879b2f 100644
--- a/units/systemd-random-seed.service.in
+++ b/units/systemd-random-seed.service.in
@@ -7,7 +7,7 @@
 [Unit]
 Description=Load/Save Random Seed
-Documentation=man:systemd-random-seed-load.service(8) man:random(4)
+Documentation=man:systemd-random-seed.service(8) man:random(4)
 DefaultDependencies=no
 RequiresMountsFor=@RANDOM_SEED@
 Conflicts=shutdown.target
SOURCES/0040-cgroup-always-enable-memory.use_hierarchy-for-all-cg.patch
New file
@@ -0,0 +1,28 @@
From 91d2bf71864a1cb9f1228b65b126f5d74d8e09b9 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Mon, 23 Sep 2013 16:02:31 -0500
Subject: [PATCH] cgroup: always enable memory.use_hierarchy= for all cgroups
 in the memory hierarchy
The non-hierarchial mode contradicts the whole idea of a cgroup tree so
let's not support this. In the future the kernel will only support the
hierarchial logic anyway.
---
 src/core/cgroup.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/core/cgroup.c b/src/core/cgroup.c
index 7f29afb..24a2306 100644
--- a/src/core/cgroup.c
+++ b/src/core/cgroup.c
@@ -256,8 +256,9 @@ void cgroup_context_apply(CGroupContext *c, CGroupControllerMask mask, const cha
         }
         if (mask & CGROUP_MEMORY) {
-                char buf[DECIMAL_STR_MAX(uint64_t) + 1];
                 if (c->memory_limit != (uint64_t) -1) {
+                        char buf[DECIMAL_STR_MAX(uint64_t) + 1];
+
                         sprintf(buf, "%" PRIu64 "\n", c->memory_limit);
                         r = cg_set_attribute("memory", path, "memory.limit_in_bytes", buf);
                 } else
SOURCES/0041-journalctl-1-s-adm-systemd-journal.patch
New file
@@ -0,0 +1,22 @@
From 07da21cf4de7428cc2016333f8ae774fcab6e9fd Mon Sep 17 00:00:00 2001
From: Dave Reisner <dreisner@archlinux.org>
Date: Tue, 24 Sep 2013 14:39:40 -0400
Subject: [PATCH] journalctl(1): s/adm/systemd-journal/
---
 man/journalctl.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/man/journalctl.xml b/man/journalctl.xml
index a5778bf..b5a0c53 100644
--- a/man/journalctl.xml
+++ b/man/journalctl.xml
@@ -104,7 +104,7 @@
                 <para>All users are granted access to their private
                 per-user journals. However, by default, only root and
-                users who are members of the <literal>adm</literal>
+                users who are members of the <literal>systemd-journal</literal>
                 group get access to the system journal and the
                 journals of other users.</para>
SOURCES/0042-cgroup-if-we-do-a-cgroup-operation-then-do-something.patch
New file
@@ -0,0 +1,422 @@
From 9c9e7b8fffbb21009d39a90076542e553a5c2190 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Mon, 23 Sep 2013 21:56:05 -0500
Subject: [PATCH] cgroup: if we do a cgroup operation then do something on all
 supported controllers
Previously we did operations like attach, trim or migrate only on the
controllers that were enabled for a specific unit. With this changes we
will now do them for all supproted controllers, and fall back to all
possible prefix paths if the specified paths do not exist.
This fixes issues if a controller is being disabled for a unit where it
was previously enabled, and makes sure that all processes stay as "far
down" the tree as groups exist.
---
 src/core/cgroup.c        |   8 +--
 src/core/execute.c       |   4 +-
 src/core/mount.c         |   2 +-
 src/core/scope.c         |   2 +-
 src/core/service.c       |   2 +-
 src/core/socket.c        |   2 +-
 src/core/swap.c          |   2 +-
 src/shared/cgroup-util.c | 154 ++++++++++++++++++++++++++++++-----------------
 src/shared/cgroup-util.h |  12 ++--
 9 files changed, 118 insertions(+), 70 deletions(-)
diff --git a/src/core/cgroup.c b/src/core/cgroup.c
index 24a2306..2f1e4a3 100644
--- a/src/core/cgroup.c
+++ b/src/core/cgroup.c
@@ -409,13 +409,13 @@ static int unit_create_cgroups(Unit *u, CGroupControllerMask mask) {
         }
         /* First, create our own group */
-        r = cg_create_with_mask(mask, path);
+        r = cg_create_everywhere(u->manager->cgroup_supported, mask, path);
         if (r < 0)
                 log_error("Failed to create cgroup %s: %s", path, strerror(-r));
         /* Then, possibly move things over */
-        if (u->cgroup_path && !streq(path, u->cgroup_path)) {
-                r = cg_migrate_with_mask(mask, u->cgroup_path, path);
+        if (u->cgroup_path) {
+                r = cg_migrate_everywhere(u->manager->cgroup_supported, u->cgroup_path, path);
                 if (r < 0)
                         log_error("Failed to migrate cgroup %s: %s", path, strerror(-r));
         }
@@ -549,7 +549,7 @@ void unit_destroy_cgroup(Unit *u) {
         if (!u->cgroup_path)
                 return;
-        r = cg_trim_with_mask(u->cgroup_mask, u->cgroup_path, !unit_has_name(u, SPECIAL_ROOT_SLICE));
+        r = cg_trim_everywhere(u->manager->cgroup_supported, u->cgroup_path, !unit_has_name(u, SPECIAL_ROOT_SLICE));
         if (r < 0)
                 log_debug("Failed to destroy cgroup %s: %s", u->cgroup_path, strerror(-r));
diff --git a/src/core/execute.c b/src/core/execute.c
index 43b571e..789122e 100644
--- a/src/core/execute.c
+++ b/src/core/execute.c
@@ -1016,7 +1016,7 @@ int exec_spawn(ExecCommand *command,
                bool apply_chroot,
                bool apply_tty_stdin,
                bool confirm_spawn,
-               CGroupControllerMask cgroup_mask,
+               CGroupControllerMask cgroup_supported,
                const char *cgroup_path,
                const char *unit_id,
                int idle_pipe[4],
@@ -1197,7 +1197,7 @@ int exec_spawn(ExecCommand *command,
                 }
                 if (cgroup_path) {
-                        err = cg_attach_with_mask(cgroup_mask, cgroup_path, 0);
+                        err = cg_attach_everywhere(cgroup_supported, cgroup_path, 0);
                         if (err < 0) {
                                 r = EXIT_CGROUP;
                                 goto fail_child;
diff --git a/src/core/mount.c b/src/core/mount.c
index 5c18d4e..78c5c1e 100644
--- a/src/core/mount.c
+++ b/src/core/mount.c
@@ -888,7 +888,7 @@ static int mount_spawn(Mount *m, ExecCommand *c, pid_t *_pid) {
                        true,
                        true,
                        UNIT(m)->manager->confirm_spawn,
-                       UNIT(m)->cgroup_mask,
+                       UNIT(m)->manager->cgroup_supported,
                        UNIT(m)->cgroup_path,
                        UNIT(m)->id,
                        NULL,
diff --git a/src/core/scope.c b/src/core/scope.c
index b94f3ff..50e5dba 100644
--- a/src/core/scope.c
+++ b/src/core/scope.c
@@ -257,7 +257,7 @@ static int scope_start(Unit *u) {
                 return r;
         }
-        r = cg_attach_many_with_mask(u->cgroup_mask, u->cgroup_path, s->pids);
+        r = cg_attach_many_everywhere(u->manager->cgroup_supported, u->cgroup_path, s->pids);
         if (r < 0)
                 return r;
diff --git a/src/core/service.c b/src/core/service.c
index 5953f45..fc04196 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -1826,7 +1826,7 @@ static int service_spawn(
                        apply_chroot,
                        apply_tty_stdin,
                        UNIT(s)->manager->confirm_spawn,
-                       UNIT(s)->cgroup_mask,
+                       UNIT(s)->manager->cgroup_supported,
                        path,
                        UNIT(s)->id,
                        s->type == SERVICE_IDLE ? UNIT(s)->manager->idle_pipe : NULL,
diff --git a/src/core/socket.c b/src/core/socket.c
index 2130e48..25c2a51 100644
--- a/src/core/socket.c
+++ b/src/core/socket.c
@@ -1241,7 +1241,7 @@ static int socket_spawn(Socket *s, ExecCommand *c, pid_t *_pid) {
                        true,
                        true,
                        UNIT(s)->manager->confirm_spawn,
-                       UNIT(s)->cgroup_mask,
+                       UNIT(s)->manager->cgroup_supported,
                        UNIT(s)->cgroup_path,
                        UNIT(s)->id,
                        NULL,
diff --git a/src/core/swap.c b/src/core/swap.c
index 76c7d45..d225485 100644
--- a/src/core/swap.c
+++ b/src/core/swap.c
@@ -625,7 +625,7 @@ static int swap_spawn(Swap *s, ExecCommand *c, pid_t *_pid) {
                        true,
                        true,
                        UNIT(s)->manager->confirm_spawn,
-                       UNIT(s)->cgroup_mask,
+                       UNIT(s)->manager->cgroup_supported,
                        UNIT(s)->cgroup_path,
                        UNIT(s)->id,
                        NULL,
diff --git a/src/shared/cgroup-util.c b/src/shared/cgroup-util.c
index 0bffebd..2e630d4 100644
--- a/src/shared/cgroup-util.c
+++ b/src/shared/cgroup-util.c
@@ -435,6 +435,46 @@ int cg_migrate_recursive(
         return ret;
 }
+int cg_migrate_recursive_fallback(
+                const char *cfrom,
+                const char *pfrom,
+                const char *cto,
+                const char *pto,
+                bool ignore_self,
+                bool rem) {
+
+        int r;
+
+        assert(cfrom);
+        assert(pfrom);
+        assert(cto);
+        assert(pto);
+
+        r = cg_migrate_recursive(cfrom, pfrom, cto, pto, ignore_self, rem);
+        if (r < 0) {
+                char prefix[strlen(pto) + 1];
+
+                /* This didn't work? Then let's try all prefixes of the destination */
+
+                strcpy(prefix, pto);
+                for (;;) {
+                        char *slash;
+
+                        slash = strrchr(prefix, '/');
+                        if (!slash)
+                                break;
+
+                        *slash = 0;
+
+                        r = cg_migrate_recursive(cfrom, pfrom, cto, prefix, ignore_self, rem);
+                        if (r >= 0)
+                                break;
+                }
+        }
+
+        return r;
+}
+
 static const char *normalize_controller(const char *controller) {
         assert(controller);
@@ -607,6 +647,39 @@ int cg_attach(const char *controller, const char *path, pid_t pid) {
         return write_string_file(fs, c);
 }
+int cg_attach_fallback(const char *controller, const char *path, pid_t pid) {
+        int r;
+
+        assert(controller);
+        assert(path);
+        assert(pid >= 0);
+
+        r = cg_attach(controller, path, pid);
+        if (r < 0) {
+                char prefix[strlen(path) + 1];
+
+                /* This didn't work? Then let's try all prefixes of
+                 * the destination */
+
+                strcpy(prefix, path);
+                for (;;) {
+                        char *slash;
+
+                        slash = strrchr(prefix, '/');
+                        if (!slash)
+                                break;
+
+                        *slash = 0;
+
+                        r = cg_attach(controller, prefix, pid);
+                        if (r >= 0)
+                                break;
+                }
+        }
+
+        return r;
+}
+
 int cg_set_group_access(
                 const char *controller,
                 const char *path,
@@ -1607,7 +1680,7 @@ static const char mask_names[] =
         "memory\0"
         "devices\0";
-int cg_create_with_mask(CGroupControllerMask mask, const char *path) {
+int cg_create_everywhere(CGroupControllerMask supported, CGroupControllerMask mask, const char *path) {
         CGroupControllerMask bit = 1;
         const char *n;
         int r;
@@ -1623,102 +1696,75 @@ int cg_create_with_mask(CGroupControllerMask mask, const char *path) {
         /* Then, do the same in the other hierarchies */
         NULSTR_FOREACH(n, mask_names) {
-                if (bit & mask)
+                if (mask & bit)
                         cg_create(n, path);
-                else
+                else if (supported & bit)
                         cg_trim(n, path, true);
                 bit <<= 1;
         }
-        return r;
+        return 0;
 }
-int cg_attach_with_mask(CGroupControllerMask mask, const char *path, pid_t pid) {
+int cg_attach_everywhere(CGroupControllerMask supported, const char *path, pid_t pid) {
         CGroupControllerMask bit = 1;
         const char *n;
         int r;
         r = cg_attach(SYSTEMD_CGROUP_CONTROLLER, path, pid);
+        if (r < 0)
+                return r;
         NULSTR_FOREACH(n, mask_names) {
-                if (bit & mask)
-                        cg_attach(n, path, pid);
-                else {
-                        char prefix[strlen(path) + 1], *slash;
-
-                        /* OK, this one is a bit harder... Now we need
-                         * to add to the closest parent cgroup we
-                         * can find */
-                        strcpy(prefix, path);
-                        while ((slash = strrchr(prefix, '/'))) {
-                                int q;
-                                *slash = 0;
-
-                                q = cg_attach(n, prefix, pid);
-                                if (q >= 0)
-                                        break;
-                        }
-                }
+                if (supported & bit)
+                        cg_attach_fallback(n, path, pid);
                 bit <<= 1;
         }
-        return r;
+        return 0;
 }
-int cg_attach_many_with_mask(CGroupControllerMask mask, const char *path, Set* pids) {
+int cg_attach_many_everywhere(CGroupControllerMask supported, const char *path, Set* pids) {
         Iterator i;
         void *pidp;
         int r = 0;
         SET_FOREACH(pidp, pids, i) {
                 pid_t pid = PTR_TO_LONG(pidp);
-                int k;
+                int q;
-                k = cg_attach_with_mask(mask, path, pid);
-                if (k < 0)
-                        r = k;
+                q = cg_attach_everywhere(supported, path, pid);
+                if (q < 0)
+                        r = q;
         }
         return r;
 }
-int cg_migrate_with_mask(CGroupControllerMask mask, const char *from, const char *to) {
+int cg_migrate_everywhere(CGroupControllerMask supported, const char *from, const char *to) {
         CGroupControllerMask bit = 1;
         const char *n;
         int r;
-        if (path_equal(from, to))
-                return 0;
-
-        r = cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, from, SYSTEMD_CGROUP_CONTROLLER, to, false, true);
+        if (!path_equal(from, to))  {
+                r = cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, from, SYSTEMD_CGROUP_CONTROLLER, to, false, true);
+                if (r < 0)
+                        return r;
+        }
         NULSTR_FOREACH(n, mask_names) {
-                if (bit & mask)
-                        cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, to, n, to, false, false);
-                else {
-                        char prefix[strlen(to) + 1], *slash;
-
-                        strcpy(prefix, to);
-                        while ((slash = strrchr(prefix, '/'))) {
-                                int q;
-
-                                *slash = 0;
-
-                                q = cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, to, n, prefix, false, false);
-                                if (q >= 0)
-                                        break;
-                        }
-                }
+                if (supported & bit)
+                        cg_migrate_recursive_fallback(SYSTEMD_CGROUP_CONTROLLER, to, n, to, false, false);
                 bit <<= 1;
         }
-        return r;
+        return 0;
 }
-int cg_trim_with_mask(CGroupControllerMask mask, const char *path, bool delete_root) {
+int cg_trim_everywhere(CGroupControllerMask supported, const char *path, bool delete_root) {
         CGroupControllerMask bit = 1;
         const char *n;
         int r;
@@ -1728,13 +1774,13 @@ int cg_trim_with_mask(CGroupControllerMask mask, const char *path, bool delete_r
                 return r;
         NULSTR_FOREACH(n, mask_names) {
-                if (bit & mask)
+                if (supported & bit)
                         cg_trim(n, path, delete_root);
                 bit <<= 1;
         }
-        return r;
+        return 0;
 }
 CGroupControllerMask cg_mask_supported(void) {
diff --git a/src/shared/cgroup-util.h b/src/shared/cgroup-util.h
index 0fc93c1..0963450 100644
--- a/src/shared/cgroup-util.h
+++ b/src/shared/cgroup-util.h
@@ -64,6 +64,7 @@ int cg_kill_recursive_and_wait(const char *controller, const char *path, bool re
 int cg_migrate(const char *cfrom, const char *pfrom, const char *cto, const char *pto, bool ignore_self);
 int cg_migrate_recursive(const char *cfrom, const char *pfrom, const char *cto, const char *pto, bool ignore_self, bool remove);
+int cg_migrate_recursive_fallback(const char *cfrom, const char *pfrom, const char *cto, const char *pto, bool ignore_self, bool rem);
 int cg_split_spec(const char *spec, char **controller, char **path);
 int cg_join_spec(const char *controller, const char *path, char **spec);
@@ -81,6 +82,7 @@ int cg_delete(const char *controller, const char *path);
 int cg_create(const char *controller, const char *path);
 int cg_attach(const char *controller, const char *path, pid_t pid);
+int cg_attach_fallback(const char *controller, const char *path, pid_t pid);
 int cg_create_and_attach(const char *controller, const char *path, pid_t pid);
 int cg_set_attribute(const char *controller, const char *path, const char *attribute, const char *value);
@@ -126,10 +128,10 @@ bool cg_controller_is_valid(const char *p, bool allow_named);
 int cg_slice_to_path(const char *unit, char **ret);
-int cg_create_with_mask(CGroupControllerMask mask, const char *path);
-int cg_attach_with_mask(CGroupControllerMask mask, const char *path, pid_t pid);
-int cg_attach_many_with_mask(CGroupControllerMask mask, const char *path, Set* pids);
-int cg_migrate_with_mask(CGroupControllerMask mask, const char *from, const char *to);
-int cg_trim_with_mask(CGroupControllerMask mask, const char *path, bool delete_root);
+int cg_create_everywhere(CGroupControllerMask supported, CGroupControllerMask mask, const char *path);
+int cg_attach_everywhere(CGroupControllerMask supported, const char *path, pid_t pid);
+int cg_attach_many_everywhere(CGroupControllerMask supported, const char *path, Set* pids);
+int cg_migrate_everywhere(CGroupControllerMask supported, const char *from, const char *to);
+int cg_trim_everywhere(CGroupControllerMask supported, const char *path, bool delete_root);
 CGroupControllerMask cg_mask_supported(void);
SOURCES/0043-core-rework-how-we-match-mount-units-against-each-ot.patch
New file
@@ -0,0 +1,1156 @@
From f0af1f20acc04b744f4ce1ed4b028e84576541d7 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Thu, 26 Sep 2013 20:14:24 +0200
Subject: [PATCH] core: rework how we match mount units against each other
Previously to automatically create dependencies between mount units we
matched every mount unit agains all others resulting in O(n^2)
complexity. On setups with large amounts of mount units this might make
things slow.
This change replaces the matching code to use a hashtable that is keyed
by a path prefix, and points to a set of units that require that path to
be around. When a new mount unit is installed it is hence sufficient to
simply look up this set of units via its own file system paths to know
which units to order after itself.
This patch also changes all unit types to only create automatic mount
dependencies via the RequiresMountsFor= logic, and this is exposed to
the outside to make things more transparent.
With this change we still have some O(n) complexities in place when
handling mounts, but that's currently unavoidable due to kernel APIs,
and still substantially better than O(n^2) as before.
https://bugs.freedesktop.org/show_bug.cgi?id=69740
---
 src/core/automount.c                  |  33 +----
 src/core/automount.h                  |   2 -
 src/core/load-fragment-gperf.gperf.m4 |   2 +-
 src/core/load-fragment.c              |  47 ++++---
 src/core/manager.c                    |  44 +++++-
 src/core/manager.h                    |  12 +-
 src/core/mount.c                      | 255 +++++++++-------------------------
 src/core/path.c                       |  32 +----
 src/core/path.h                       |   4 -
 src/core/socket.c                     |  49 ++-----
 src/core/socket.h                     |   4 -
 src/core/swap.c                       |  40 +-----
 src/core/swap.h                       |   2 -
 src/core/unit.c                       | 162 +++++++++++++++++----
 src/core/unit.h                       |   6 +-
 src/shared/socket-util.c              |   8 +-
 src/shared/socket-util.h              |   2 +-
 17 files changed, 309 insertions(+), 395 deletions(-)
diff --git a/src/core/automount.c b/src/core/automount.c
index 6762392..d1379e0 100644
--- a/src/core/automount.c
+++ b/src/core/automount.c
@@ -117,42 +117,17 @@ static void automount_done(Unit *u) {
         a->tokens = NULL;
 }
-int automount_add_one_mount_link(Automount *a, Mount *m) {
+static int automount_add_mount_links(Automount *a) {
+        _cleanup_free_ char *parent = NULL;
         int r;
         assert(a);
-        assert(m);
-
-        if (UNIT(a)->load_state != UNIT_LOADED ||
-            UNIT(m)->load_state != UNIT_LOADED)
-                return 0;
-
-        if (!path_startswith(a->where, m->where))
-                return 0;
-        if (path_equal(a->where, m->where))
-                return 0;
-
-        r = unit_add_two_dependencies(UNIT(a), UNIT_AFTER, UNIT_REQUIRES, UNIT(m), true);
+        r = path_get_parent(a->where, &parent);
         if (r < 0)
                 return r;
-        return 0;
-}
-
-static int automount_add_mount_links(Automount *a) {
-        Unit *other;
-        int r;
-
-        assert(a);
-
-        LIST_FOREACH(units_by_type, other, UNIT(a)->manager->units_by_type[UNIT_MOUNT]) {
-                r = automount_add_one_mount_link(a, MOUNT(other));
-                if (r < 0)
-                        return r;
-        }
-
-        return 0;
+        return unit_require_mounts_for(UNIT(a), parent);
 }
 static int automount_add_default_dependencies(Automount *a) {
diff --git a/src/core/automount.h b/src/core/automount.h
index 0c6b8a7..a7a25d3 100644
--- a/src/core/automount.h
+++ b/src/core/automount.h
@@ -62,8 +62,6 @@ extern const UnitVTable automount_vtable;
 int automount_send_ready(Automount *a, int status);
-int automount_add_one_mount_link(Automount *a, Mount *m);
-
 const char* automount_state_to_string(AutomountState i) _const_;
 AutomountState automount_state_from_string(const char *s) _pure_;
diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
index 33c6880..3f064a9 100644
--- a/src/core/load-fragment-gperf.gperf.m4
+++ b/src/core/load-fragment-gperf.gperf.m4
@@ -117,7 +117,7 @@ Unit.PropagateReloadTo,          config_parse_unit_deps,             UNIT_PROPAG
 Unit.ReloadPropagatedFrom,       config_parse_unit_deps,             UNIT_RELOAD_PROPAGATED_FROM,   0
 Unit.PropagateReloadFrom,        config_parse_unit_deps,             UNIT_RELOAD_PROPAGATED_FROM,   0
 Unit.PartOf,                     config_parse_unit_deps,             UNIT_PART_OF,                  0
-Unit.RequiresMountsFor,          config_parse_unit_requires_mounts_for, 0,                          offsetof(Unit, requires_mounts_for)
+Unit.RequiresMountsFor,          config_parse_unit_requires_mounts_for, 0,                          0
 Unit.StopWhenUnneeded,           config_parse_bool,                  0,                             offsetof(Unit, stop_when_unneeded)
 Unit.RefuseManualStart,          config_parse_bool,                  0,                             offsetof(Unit, refuse_manual_start)
 Unit.RefuseManualStop,           config_parse_bool,                  0,                             offsetof(Unit, refuse_manual_stop)
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
index f4a268c..ed8602f 100644
--- a/src/core/load-fragment.c
+++ b/src/core/load-fragment.c
@@ -1742,33 +1742,48 @@ int config_parse_unit_condition_null(const char *unit,
 DEFINE_CONFIG_PARSE_ENUM(config_parse_notify_access, notify_access, NotifyAccess, "Failed to parse notify access specifier");
 DEFINE_CONFIG_PARSE_ENUM(config_parse_start_limit_action, start_limit_action, StartLimitAction, "Failed to parse start limit action specifier");
-int config_parse_unit_requires_mounts_for(const char *unit,
-                                          const char *filename,
-                                          unsigned line,
-                                          const char *section,
-                                          const char *lvalue,
-                                          int ltype,
-                                          const char *rvalue,
-                                          void *data,
-                                          void *userdata) {
+int config_parse_unit_requires_mounts_for(
+                const char *unit,
+                const char *filename,
+                unsigned line,
+                const char *section,
+                const char *lvalue,
+                int ltype,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
         Unit *u = userdata;
+        char *state;
+        size_t l;
+        char *w;
         int r;
-        bool empty_before;
         assert(filename);
         assert(lvalue);
         assert(rvalue);
         assert(data);
-        empty_before = !u->requires_mounts_for;
+        FOREACH_WORD_QUOTED(w, l, rvalue, state) {
+                _cleanup_free_ char *n;
+
+                n = strndup(w, l);
+                if (!n)
+                        return log_oom();
-        r = config_parse_path_strv(unit, filename, line, section, lvalue, ltype,
-                                   rvalue, data, userdata);
+                if (!utf8_is_valid(n)) {
+                        log_syntax(unit, LOG_ERR, filename, line, EINVAL,
+                                   "Path is not UTF-8 clean, ignoring assignment: %s", rvalue);
+                        continue;
+                }
-        /* Make it easy to find units with requires_mounts set */
-        if (empty_before && u->requires_mounts_for)
-                LIST_PREPEND(Unit, has_requires_mounts_for, u->manager->has_requires_mounts_for, u);
+                r = unit_require_mounts_for(u, n);
+                if (r < 0) {
+                        log_syntax(unit, LOG_ERR, filename, line, r,
+                                   "Failed to add required mount for, ignoring: %s", rvalue);
+                        continue;
+                }
+        }
         return r;
 }
diff --git a/src/core/manager.c b/src/core/manager.c
index 669af15..dadbedd 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -771,6 +771,9 @@ void manager_free(Manager *m) {
         for (i = 0; i < RLIMIT_NLIMITS; i++)
                 free(m->rlimit[i]);
+        assert(hashmap_isempty(m->units_requiring_mounts_for));
+        hashmap_free(m->units_requiring_mounts_for);
+
         free(m);
 }
@@ -783,9 +786,11 @@ int manager_enumerate(Manager *m) {
         /* Let's ask every type to load all units from disk/kernel
          * that it might know */
         for (c = 0; c < _UNIT_TYPE_MAX; c++)
-                if (unit_vtable[c]->enumerate)
-                        if ((q = unit_vtable[c]->enumerate(m)) < 0)
+                if (unit_vtable[c]->enumerate) {
+                        q = unit_vtable[c]->enumerate(m);
+                        if (q < 0)
                                 r = q;
+                }
         manager_dispatch_load_queue(m);
         return r;
@@ -2765,6 +2770,41 @@ void manager_status_printf(Manager *m, bool ephemeral, const char *status, const
         va_end(ap);
 }
+int manager_get_unit_by_path(Manager *m, const char *path, const char *suffix, Unit **_found) {
+        _cleanup_free_ char *p = NULL;
+        Unit *found;
+
+        assert(m);
+        assert(path);
+        assert(suffix);
+        assert(_found);
+
+        p = unit_name_from_path(path, suffix);
+        if (!p)
+                return -ENOMEM;
+
+        found = manager_get_unit(m, p);
+        if (!found) {
+                *_found = NULL;
+                return 0;
+        }
+
+        *_found = found;
+        return 1;
+}
+
+Set *manager_get_units_requiring_mounts_for(Manager *m, const char *path) {
+        char p[strlen(path)+1];
+
+        assert(m);
+        assert(path);
+
+        strcpy(p, path);
+        path_kill_slashes(p);
+
+        return hashmap_get(m->units_requiring_mounts_for, streq(p, "/") ? "" : p);
+}
+
 void watch_init(Watch *w) {
         assert(w);
diff --git a/src/core/manager.h b/src/core/manager.h
index 3969553..a3049b5 100644
--- a/src/core/manager.h
+++ b/src/core/manager.h
@@ -103,9 +103,6 @@ struct Manager {
          * type we maintain a per type linked list */
         LIST_HEAD(Unit, units_by_type[_UNIT_TYPE_MAX]);
-        /* To optimize iteration of units that have requires_mounts_for set */
-        LIST_HEAD(Unit, has_requires_mounts_for);
-
         /* Units that need to be loaded */
         LIST_HEAD(Unit, load_queue); /* this is actually more a stack than a queue, but uh. */
@@ -251,6 +248,11 @@ struct Manager {
         char *switch_root;
         char *switch_root_init;
+
+        /* This maps all possible path prefixes to the units needing
+         * them. It's a hashmap with a path string as key and a Set as
+         * value where Unit objects are contained. */
+        Hashmap *units_requiring_mounts_for;
 };
 int manager_new(SystemdRunningAs running_as, bool reexecuting, Manager **m);
@@ -263,6 +265,8 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds);
 Job *manager_get_job(Manager *m, uint32_t id);
 Unit *manager_get_unit(Manager *m, const char *name);
+int manager_get_unit_by_path(Manager *m, const char *path, const char *suffix, Unit **_found);
+
 int manager_get_job_from_dbus_path(Manager *m, const char *s, Job **_j);
 int manager_load_unit_prepare(Manager *m, const char *name, const char *path, DBusError *e, Unit **_ret);
@@ -316,4 +320,6 @@ void manager_recheck_journal(Manager *m);
 void manager_set_show_status(Manager *m, bool b);
 void manager_status_printf(Manager *m, bool ephemeral, const char *status, const char *format, ...) _printf_attr_(4,5);
+Set *manager_get_units_requiring_mounts_for(Manager *m, const char *path);
+
 void watch_init(Watch *w);
diff --git a/src/core/mount.c b/src/core/mount.c
index 78c5c1e..3d46557 100644
--- a/src/core/mount.c
+++ b/src/core/mount.c
@@ -157,138 +157,58 @@ _pure_ static MountParameters* get_mount_parameters(Mount *m) {
 }
 static int mount_add_mount_links(Mount *m) {
-        Unit *other;
-        int r;
+        _cleanup_free_ char *parent = NULL;
         MountParameters *pm;
-
-        assert(m);
-
-        pm = get_mount_parameters_fragment(m);
-
-        /* Adds in links to other mount points that might lie below or
-         * above us in the hierarchy */
-
-        LIST_FOREACH(units_by_type, other, UNIT(m)->manager->units_by_type[UNIT_MOUNT]) {
-                Mount *n = MOUNT(other);
-                MountParameters *pn;
-
-                if (n == m)
-                        continue;
-
-                if (UNIT(n)->load_state != UNIT_LOADED)
-                        continue;
-
-                pn = get_mount_parameters_fragment(n);
-
-                if (path_startswith(m->where, n->where)) {
-
-                        if ((r = unit_add_dependency(UNIT(m), UNIT_AFTER, UNIT(n), true)) < 0)
-                                return r;
-
-                        if (pn)
-                                if ((r = unit_add_dependency(UNIT(m), UNIT_REQUIRES, UNIT(n), true)) < 0)
-                                        return r;
-
-                } else if (path_startswith(n->where, m->where)) {
-
-                        if ((r = unit_add_dependency(UNIT(n), UNIT_AFTER, UNIT(m), true)) < 0)
-                                return r;
-
-                        if (pm)
-                                if ((r = unit_add_dependency(UNIT(n), UNIT_REQUIRES, UNIT(m), true)) < 0)
-                                        return r;
-
-                } else if (pm && pm->what && path_startswith(pm->what, n->where)) {
-
-                        if ((r = unit_add_dependency(UNIT(m), UNIT_AFTER, UNIT(n), true)) < 0)
-                                return r;
-
-                        if ((r = unit_add_dependency(UNIT(m), UNIT_REQUIRES, UNIT(n), true)) < 0)
-                                return r;
-
-                } else if (pn && pn->what && path_startswith(pn->what, m->where)) {
-
-                        if ((r = unit_add_dependency(UNIT(n), UNIT_AFTER, UNIT(m), true)) < 0)
-                                return r;
-
-                        if ((r = unit_add_dependency(UNIT(n), UNIT_REQUIRES, UNIT(m), true)) < 0)
-                                return r;
-                }
-        }
-
-        return 0;
-}
-
-static int mount_add_swap_links(Mount *m) {
         Unit *other;
+        Iterator i;
+        Set *s;
         int r;
         assert(m);
-        LIST_FOREACH(units_by_type, other, UNIT(m)->manager->units_by_type[UNIT_SWAP]) {
-                r = swap_add_one_mount_link(SWAP(other), m);
+        if (!path_equal(m->where, "/")) {
+                /* Adds in links to other mount points that might lie further
+                 * up in the hierarchy */
+                r = path_get_parent(m->where, &parent);
                 if (r < 0)
                         return r;
-        }
-        return 0;
-}
-
-static int mount_add_path_links(Mount *m) {
-        Unit *other;
-        int r;
-
-        assert(m);
-
-        LIST_FOREACH(units_by_type, other, UNIT(m)->manager->units_by_type[UNIT_PATH]) {
-                r = path_add_one_mount_link(PATH(other), m);
+                r = unit_require_mounts_for(UNIT(m), parent);
                 if (r < 0)
                         return r;
         }
-        return 0;
-}
-
-static int mount_add_automount_links(Mount *m) {
-        Unit *other;
-        int r;
-
-        assert(m);
-
-        LIST_FOREACH(units_by_type, other, UNIT(m)->manager->units_by_type[UNIT_AUTOMOUNT]) {
-                r = automount_add_one_mount_link(AUTOMOUNT(other), m);
+        /* Adds in links to other mount points that might be needed
+         * for the source path (if this is a bind mount) to be
+         * available. */
+        pm = get_mount_parameters_fragment(m);
+        if (pm && path_is_absolute(pm->what)) {
+                r = unit_require_mounts_for(UNIT(m), pm->what);
                 if (r < 0)
                         return r;
         }
-        return 0;
-}
+        /* Adds in links to other units that use this path or paths