Last active
November 28, 2018 17:30
-
-
Save rail/51c1293a1c7c9a35e199a95d1232d97d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
How to generate the diff: | |
git clone https://salsa.debian.org/systemd-team/systemd.git | |
cd systemd | |
git diff ubuntu/219-4ubuntu4..ubuntu/219-4ubuntu10 | |
diff --git a/debian/changelog b/debian/changelog | |
index 420893cd9a..607453997f 100644 | |
--- a/debian/changelog | |
+++ b/debian/changelog | |
@@ -1,3 +1,67 @@ | |
+systemd (219-4ubuntu10) vivid; urgency=medium | |
+ | |
+ * Cherry-pick a couple of upstream commits for adding transient state, | |
+ fixing a race where mounts become available before the device being | |
+ available. | |
+ * Refresh core-mount-ensure-that-we-parse-proc-self-mountinfo.patch for | |
+ the above cherry-pick. | |
+ | |
+ -- Didier Roche <didrocks@ubuntu.com> Tue, 24 Mar 2015 16:02:25 +0100 | |
+ | |
+systemd (219-4ubuntu9) vivid; urgency=medium | |
+ | |
+ * debian/control: | |
+ - systemd-sysv now conflicts with upstart-sysv, not upstart itself | |
+ which contains upstart binaries. (LP: #1422681) | |
+ * debian/test/*: | |
+ - re-enable upstart boot test and switch to upstart instead of | |
+ upstart-bin | |
+ * debian/systemd-sysv.postinst: | |
+ - fix syntax for better portability | |
+ | |
+ -- Didier Roche <didrocks@ubuntu.com> Mon, 23 Mar 2015 10:21:34 +0100 | |
+ | |
+systemd (219-4ubuntu8) vivid; urgency=medium | |
+ | |
+ * force ifup@ to run after systemd-tmpfiles-setup as ifupdown | |
+ operations require /run/network which is being created by tmpfiles | |
+ (LP: #1434020). | |
+ | |
+ -- Scott Moser <smoser@ubuntu.com> Fri, 20 Mar 2015 09:48:23 -0400 | |
+ | |
+systemd (219-4ubuntu7) vivid; urgency=medium | |
+ | |
+ * use systemd-ifupdown-helper script to handle ifup and ifdown | |
+ of auto or hotplug devices. This allows iscsi root volumes | |
+ to work again. (LP: #1432829) | |
+ * debian/control/tests: disable running of upstart tests until | |
+ upstart packaging bug 1422681 is resolved. | |
+ | |
+ -- Scott Moser <smoser@ubuntu.com> Thu, 19 Mar 2015 11:43:14 -0400 | |
+ | |
+systemd (219-4ubuntu6) vivid; urgency=medium | |
+ | |
+ * d/extra/units/ifup@.service, d/extra/tmpfiles.d/debian.conf: | |
+ use tmpfiles.d population of /run/network rather than | |
+ 'RuntimeDirectory' in the ifup service. This way files created | |
+ in initramfs are not deleted. (LP: #1432821) | |
+ | |
+ -- Scott Moser <smoser@ubuntu.com> Tue, 17 Mar 2015 19:40:45 -0400 | |
+ | |
+systemd (219-4ubuntu5) vivid; urgency=medium | |
+ | |
+ * Merge from experimental branch: | |
+ - /lib/lsb/init-functions.d/40-systemd: Don't ignore systemd unit | |
+ dependencies in "degraded" mode. (LP: #1429734) | |
+ - rules-ubuntu/71-power-switch-proliant.rules: Add support for HP ProLiant | |
+ m400 Server Cartridge soft powerdown on Linux 3.16. (LP: #1428811) | |
+ * systemctl: Don't forward telinit u to upstart. This works around upstart's | |
+ Restart() always reexec'ing /sbin/init on Restart(), even if that changes | |
+ to point to systemd during the upgrade. This avoids running systemd during | |
+ a dist-upgrade. (LP: #1430479) | |
+ | |
+ -- Martin Pitt <martin.pitt@ubuntu.com> Wed, 11 Mar 2015 11:01:36 +0100 | |
+ | |
systemd (219-4ubuntu4) vivid; urgency=medium | |
* debian/udev.postinst: Only call update-initramfs if it actually exists. | |
@@ -25,6 +89,12 @@ systemd (219-5) UNRELEASED; urgency=medium | |
* Check for correct architecture identifiers for SuperH. (Closes: #779710) | |
* Fix tmpfiles.d to only apply the first match again (regression in 219). | |
(LP: #1428540) | |
+ * /lib/lsb/init-functions.d/40-systemd: Don't ignore systemd unit | |
+ dependencies in "degraded" mode. (LP: #1429734) | |
+ | |
+ [ Craig Magina ] | |
+ * rules-ubuntu/71-power-switch-proliant.rules: Add support for HP ProLiant | |
+ m400 Server Cartridge soft powerdown on Linux 3.16. (LP: #1428811) | |
-- Martin Pitt <mpitt@debian.org> Tue, 03 Mar 2015 14:51:46 +0100 | |
diff --git a/debian/control b/debian/control | |
index 11a6c9264c..8eab33e3fc 100644 | |
--- a/debian/control | |
+++ b/debian/control | |
@@ -87,10 +87,12 @@ Multi-Arch: foreign | |
Section: admin | |
Priority: extra | |
Conflicts: sysvinit-core, | |
- upstart | |
+ upstart-sysv, | |
+ upstart (<< 1.13.2-0ubuntu10~), | |
Replaces: sysvinit (<< 2.88dsf-44~), | |
sysvinit-core, | |
- upstart | |
+ upstart-sysv, | |
+ upstart (<< 1.13.2-0ubuntu10~), | |
Pre-Depends: systemd | |
Depends: ${shlibs:Depends}, | |
${misc:Depends}, | |
diff --git a/debian/extra/init-functions.d/40-systemd b/debian/extra/init-functions.d/40-systemd | |
index faa87b3674..53f5058d48 100644 | |
--- a/debian/extra/init-functions.d/40-systemd | |
+++ b/debian/extra/init-functions.d/40-systemd | |
@@ -64,7 +64,7 @@ systemctl_redirect () { | |
# the synchronous wait plus systemd's normal behaviour of | |
# transactionally processing all dependencies first easily | |
# causes dependency loops | |
- if ! systemctl --quiet is-system-running; then | |
+ if ! OUT=$(systemctl is-system-running 2>/dev/null) && [ "$OUT" != "degraded" ]; then | |
sctl_args="--job-mode=ignore-dependencies" | |
fi | |
diff --git a/debian/extra/rules-ubuntu/71-power-switch-proliant.rules b/debian/extra/rules-ubuntu/71-power-switch-proliant.rules | |
index 816924e082..022baebf74 100644 | |
--- a/debian/extra/rules-ubuntu/71-power-switch-proliant.rules | |
+++ b/debian/extra/rules-ubuntu/71-power-switch-proliant.rules | |
@@ -1,2 +1,2 @@ | |
-ACTION!="remove", SUBSYSTEM=="input", KERNEL=="event*", SUBSYSTEMS=="platform", KERNELS=="gpio_keys.6", PROGRAM="/bin/cat /proc/device-tree/model", RESULT=="HP ProLiant m400 Server Cartridge", TAG+="power-switch" | |
+ACTION!="remove", SUBSYSTEM=="input", KERNEL=="event*", SUBSYSTEMS=="platform", KERNELS=="gpio_keys.6|soc:gpio_keys", PROGRAM="/bin/cat /proc/device-tree/model", RESULT=="HP ProLiant m400 Server Cartridge", TAG+="power-switch" | |
ACTION!="remove", SUBSYSTEM=="input", KERNEL=="event*", SUBSYSTEMS=="platform", KERNELS=="gpio_keys.12", ATTRS{keys}=="116", PROGRAM="/bin/cat /proc/device-tree/model", RESULT=="HP ProLiant m800 Server Cartridge", TAG+="power-switch" | |
diff --git a/debian/extra/systemd-ifupdown-helper b/debian/extra/systemd-ifupdown-helper | |
new file mode 100755 | |
index 0000000000..ee21958b37 | |
--- /dev/null | |
+++ b/debian/extra/systemd-ifupdown-helper | |
@@ -0,0 +1,83 @@ | |
+#!/bin/sh | |
+ | |
+CR=" | |
+" | |
+IFSTATE_FILE="/run/network/ifstate" | |
+ | |
+do_ifup() { | |
+ local ifname="$1" | |
+ ifquery --list --allow=hotplug | grep -q "^$ifname$" || | |
+ ifquery --list --allow=auto | grep -q "^$ifname$" || | |
+ return 0 | |
+ ifup "$ifname" | |
+} | |
+ | |
+is_persistent_initramfs_iface() { | |
+ # open-iscsi.interface is written by open-iscsi when booting from | |
+ # an iscsi volume, when you can't bounce the interface that the root | |
+ # device is on. The other file, is meant as a more generic location | |
+ # for an initramfs job to write "persistent" network devices. | |
+ grep -qs "^$1$" /run/initramfs/open-iscsi.interface \ | |
+ "/run/network/initramfs-persistent-iface" | |
+} | |
+ | |
+adjust_resolvconf() { | |
+ local ifname="$1" data="" | |
+ command -v resolvconf >/dev/null 2>&1 || return 0 | |
+ | |
+ # /run/net-eth0.conf is written by 'ipconfig' in klibc | |
+ [ -f "/run/net-$ifname.conf" ] || return 0 | |
+ . "/run/net-$ifname.conf" | |
+ data="" | |
+ [ -n "$DOMAINSEARCH" ] && data="$data${CR}domainsearch $DOMAINSEARCH" | |
+ for ns in "$IPV4DNS0" "$IPV4DNS1"; do | |
+ [ -n "$ns" -a "$ns" != "0.0.0.0" ] && data="$data${CR}nameserver $ns" | |
+ done | |
+ data=${data#${CR}} | |
+ [ -z "$data" ] && return 0 | |
+ echo "$data" | resolvconf -a "$ifname.initramfs" | |
+} | |
+ | |
+do_ifup_persistent() { | |
+ local ifname="$1" | |
+ # already done | |
+ grep -qs "$ifname=" $IFSTATE_FILE && return 0 | |
+ | |
+ adjust_resolvconf "$ifname" || return | |
+ # write to the ifstate file, so ifupdown thinks its up. | |
+ echo "$ifname=$ifname" >> $IFSTATE_FILE | |
+} | |
+ | |
+start_main() { | |
+ local ifname=$1 | |
+ shift | |
+ if is_persistent_initramfs_iface "$ifname"; then | |
+ do_ifup_persistent "$ifname" "$@" || return | |
+ fi | |
+ do_ifup "$ifname" "$@" | |
+} | |
+ | |
+stop_main() { | |
+ local ifname="$1" fail=0 | |
+ shift | |
+ if ! is_persistent_initramfs_iface "$ifname"; then | |
+ /sbin/ifdown "$ifname" | |
+ return | |
+ fi | |
+ # we only pretend to bring the interface down | |
+ # if interface is not present, we're already done | |
+ grep -qs "^$ifname=" $IFSTATE_FILE || return 0 | |
+ | |
+ sed -i "/^$ifname=/d" "$IFSTATE_FILE" || fail=1 | |
+ resolvconf -d "$ifname.initramfs" || fail=1 | |
+ return $fail | |
+} | |
+ | |
+mode="$1" | |
+shift; | |
+case "$mode" in | |
+ start) start_main "$@";; | |
+ stop) stop_main "$@";; | |
+ *) echo "$0: unknown mode '$mode'" 1>&2; exit 1;; | |
+esac | |
+exit | |
diff --git a/debian/extra/tmpfiles.d/debian.conf b/debian/extra/tmpfiles.d/debian.conf | |
index 83f75864ea..02612dc42f 100644 | |
--- a/debian/extra/tmpfiles.d/debian.conf | |
+++ b/debian/extra/tmpfiles.d/debian.conf | |
@@ -11,3 +11,4 @@ | |
L /run/initctl - - - - /run/systemd/initctl/fifo | |
L /run/shm - - - - /dev/shm | |
d /run/sendsigs.omit.d 0755 root root - | |
+d /run/network 0755 root root - | |
diff --git a/debian/extra/units/ifup@.service b/debian/extra/units/ifup@.service | |
index d6dd1b0c48..8b2ec75be7 100644 | |
--- a/debian/extra/units/ifup@.service | |
+++ b/debian/extra/units/ifup@.service | |
@@ -1,16 +1,12 @@ | |
[Unit] | |
Description=ifup for %I | |
-After=local-fs.target network-pre.target | |
+After=local-fs.target network-pre.target systemd-tmpfiles-setup.service | |
Before=network.target | |
BindsTo=sys-subsystem-net-devices-%i.device | |
DefaultDependencies=no | |
[Service] | |
Type=oneshot | |
-RuntimeDirectory=network | |
-ExecStart=/sbin/ifup --allow=hotplug %I | |
-ExecStartPost=/sbin/ifup --allow=auto %I | |
-# only fail if ifupdown knows about the iface AND it's not up | |
-ExecStartPost=/bin/sh -c 'if ifquery %I >/dev/null; then ifquery --state %I >/dev/null; fi' | |
-ExecStop=/sbin/ifdown %I | |
+ExecStart=/lib/systemd/systemd-ifupdown-helper start %I | |
+ExecStop=/lib/systemd/systemd-ifupdown-helper stop %I | |
RemainAfterExit=true | |
diff --git a/debian/patches/Add_tentative_state.patch b/debian/patches/Add_tentative_state.patch | |
new file mode 100644 | |
index 0000000000..838c543bf8 | |
--- /dev/null | |
+++ b/debian/patches/Add_tentative_state.patch | |
@@ -0,0 +1,900 @@ | |
+commit 628c89cc68ab96fce2de7ebba5933725d147aecc | |
+Author: Lennart Poettering <lennart@poettering.net> | |
+Date: Fri Feb 27 21:55:08 2015 +0100 | |
+ | |
+ core: rework device state logic | |
+ | |
+ This change introduces a new state "tentative" for device units. Device | |
+ units are considered "plugged" when udev announced them, "dead" when | |
+ they are not available in the kernel, and "tentative" when they are | |
+ referenced in /proc/self/mountinfo or /proc/swaps but not (yet) | |
+ announced via udev. | |
+ | |
+ This should fix a race when device nodes (like loop devices) are created | |
+ and immediately mounted. Previously, systemd might end up seeing the | |
+ mount unit before the device, and would thus pull down the mount because | |
+ its BindTo dependency on the device would not be fulfilled. | |
+ | |
+Index: systemd-219/src/core/device.c | |
+=================================================================== | |
+--- systemd-219.orig/src/core/device.c | |
++++ systemd-219/src/core/device.c | |
+@@ -36,7 +36,8 @@ | |
+ | |
+ static const UnitActiveState state_translation_table[_DEVICE_STATE_MAX] = { | |
+ [DEVICE_DEAD] = UNIT_INACTIVE, | |
+- [DEVICE_PLUGGED] = UNIT_ACTIVE | |
++ [DEVICE_TENTATIVE] = UNIT_ACTIVATING, | |
++ [DEVICE_PLUGGED] = UNIT_ACTIVE, | |
+ }; | |
+ | |
+ static int device_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata); | |
+@@ -65,6 +66,41 @@ static void device_unset_sysfs(Device *d | |
+ d->sysfs = NULL; | |
+ } | |
+ | |
++static int device_set_sysfs(Device *d, const char *sysfs) { | |
++ Device *first; | |
++ char *copy; | |
++ int r; | |
++ | |
++ assert(d); | |
++ | |
++ if (streq_ptr(d->sysfs, sysfs)) | |
++ return 0; | |
++ | |
++ r = hashmap_ensure_allocated(&UNIT(d)->manager->devices_by_sysfs, &string_hash_ops); | |
++ if (r < 0) | |
++ return r; | |
++ | |
++ copy = strdup(sysfs); | |
++ if (!copy) | |
++ return -ENOMEM; | |
++ | |
++ device_unset_sysfs(d); | |
++ | |
++ first = hashmap_get(UNIT(d)->manager->devices_by_sysfs, sysfs); | |
++ LIST_PREPEND(same_sysfs, first, d); | |
++ | |
++ r = hashmap_replace(UNIT(d)->manager->devices_by_sysfs, copy, first); | |
++ if (r < 0) { | |
++ LIST_REMOVE(same_sysfs, first, d); | |
++ free(copy); | |
++ return r; | |
++ } | |
++ | |
++ d->sysfs = copy; | |
++ | |
++ return 0; | |
++} | |
++ | |
+ static void device_init(Unit *u) { | |
+ Device *d = DEVICE(u); | |
+ | |
+@@ -112,8 +148,13 @@ static int device_coldplug(Unit *u) { | |
+ assert(d); | |
+ assert(d->state == DEVICE_DEAD); | |
+ | |
+- if (d->sysfs) | |
++ if (d->found & DEVICE_FOUND_UDEV) | |
++ /* If udev says the device is around, it's around */ | |
+ device_set_state(d, DEVICE_PLUGGED); | |
++ else if (d->found != DEVICE_NOT_FOUND) | |
++ /* If a device is found in /proc/self/mountinfo or | |
++ * /proc/swaps, it's "tentatively" around. */ | |
++ device_set_state(d, DEVICE_TENTATIVE); | |
+ | |
+ return 0; | |
+ } | |
+@@ -142,49 +183,9 @@ _pure_ static const char *device_sub_sta | |
+ return device_state_to_string(DEVICE(u)->state); | |
+ } | |
+ | |
+-static int device_add_escaped_name(Unit *u, const char *dn) { | |
+- _cleanup_free_ char *e = NULL; | |
+- int r; | |
+- | |
+- assert(u); | |
+- assert(dn); | |
+- assert(dn[0] == '/'); | |
+- | |
+- e = unit_name_from_path(dn, ".device"); | |
+- if (!e) | |
+- return -ENOMEM; | |
+- | |
+- r = unit_add_name(u, e); | |
+- if (r < 0 && r != -EEXIST) | |
+- return r; | |
+- | |
+- return 0; | |
+-} | |
+- | |
+-static int device_find_escape_name(Manager *m, const char *dn, Unit **_u) { | |
+- _cleanup_free_ char *e = NULL; | |
+- Unit *u; | |
+- | |
+- assert(m); | |
+- assert(dn); | |
+- assert(dn[0] == '/'); | |
+- assert(_u); | |
+- | |
+- e = unit_name_from_path(dn, ".device"); | |
+- if (!e) | |
+- return -ENOMEM; | |
+- | |
+- u = manager_get_unit(m, e); | |
+- if (u) { | |
+- *_u = u; | |
+- return 1; | |
+- } | |
+- | |
+- return 0; | |
+-} | |
+- | |
+-static int device_make_description(Unit *u, struct udev_device *dev, const char *path) { | |
++static int device_update_description(Unit *u, struct udev_device *dev, const char *path) { | |
+ const char *model; | |
++ int r; | |
+ | |
+ assert(u); | |
+ assert(dev); | |
+@@ -209,13 +210,16 @@ static int device_make_description(Unit | |
+ | |
+ j = strjoin(model, " ", label, NULL); | |
+ if (j) | |
+- return unit_set_description(u, j); | |
+- } | |
++ r = unit_set_description(u, j); | |
++ } else | |
++ r = unit_set_description(u, model); | |
++ } else | |
++ r = unit_set_description(u, path); | |
+ | |
+- return unit_set_description(u, model); | |
+- } | |
++ if (r < 0) | |
++ log_unit_error_errno(u->id, r, "Failed to set device description: %m"); | |
+ | |
+- return unit_set_description(u, path); | |
++ return r; | |
+ } | |
+ | |
+ static int device_add_udev_wants(Unit *u, struct udev_device *dev) { | |
+@@ -242,20 +246,20 @@ static int device_add_udev_wants(Unit *u | |
+ | |
+ n = unit_name_mangle(e, MANGLE_NOGLOB); | |
+ if (!n) | |
+- return -ENOMEM; | |
++ return log_oom(); | |
+ | |
+ r = unit_add_dependency_by_name(u, UNIT_WANTS, n, NULL, true); | |
+ if (r < 0) | |
+- return r; | |
++ return log_unit_error_errno(u->id, r, "Failed to add wants dependency: %m"); | |
+ } | |
+ if (!isempty(state)) | |
+- log_unit_warning(u->id, "Property %s on %s has trailing garbage, ignoring.", | |
+- property, strna(udev_device_get_syspath(dev))); | |
++ log_unit_warning(u->id, "Property %s on %s has trailing garbage, ignoring.", property, strna(udev_device_get_syspath(dev))); | |
+ | |
+ return 0; | |
+ } | |
+ | |
+-static int device_update_unit(Manager *m, struct udev_device *dev, const char *path, bool main) { | |
++static int device_setup_unit(Manager *m, struct udev_device *dev, const char *path, bool main) { | |
++ _cleanup_free_ char *e = NULL; | |
+ const char *sysfs; | |
+ Unit *u = NULL; | |
+ bool delete; | |
+@@ -269,12 +273,18 @@ static int device_update_unit(Manager *m | |
+ if (!sysfs) | |
+ return 0; | |
+ | |
+- r = device_find_escape_name(m, path, &u); | |
+- if (r < 0) | |
+- return r; | |
++ e = unit_name_from_path(path, ".device"); | |
++ if (!e) | |
++ return log_oom(); | |
++ | |
++ u = manager_get_unit(m, e); | |
+ | |
+- if (u && DEVICE(u)->sysfs && !path_equal(DEVICE(u)->sysfs, sysfs)) | |
++ if (u && | |
++ DEVICE(u)->sysfs && | |
++ !path_equal(DEVICE(u)->sysfs, sysfs)) { | |
++ log_unit_error(u->id, "Device %s appeared twice with different sysfs paths %s and %s", e, DEVICE(u)->sysfs, sysfs); | |
+ return -EEXIST; | |
++ } | |
+ | |
+ if (!u) { | |
+ delete = true; | |
+@@ -283,7 +293,7 @@ static int device_update_unit(Manager *m | |
+ if (!u) | |
+ return log_oom(); | |
+ | |
+- r = device_add_escaped_name(u, path); | |
++ r = unit_add_name(u, e); | |
+ if (r < 0) | |
+ goto fail; | |
+ | |
+@@ -295,37 +305,16 @@ static int device_update_unit(Manager *m | |
+ * actually been seen yet ->sysfs will not be | |
+ * initialized. Hence initialize it if necessary. */ | |
+ | |
+- if (!DEVICE(u)->sysfs) { | |
+- Device *first; | |
+- | |
+- DEVICE(u)->sysfs = strdup(sysfs); | |
+- if (!DEVICE(u)->sysfs) { | |
+- r = -ENOMEM; | |
+- goto fail; | |
+- } | |
+- | |
+- r = hashmap_ensure_allocated(&m->devices_by_sysfs, &string_hash_ops); | |
+- if (r < 0) | |
+- goto fail; | |
+- | |
+- first = hashmap_get(m->devices_by_sysfs, sysfs); | |
+- LIST_PREPEND(same_sysfs, first, DEVICE(u)); | |
+- | |
+- r = hashmap_replace(m->devices_by_sysfs, DEVICE(u)->sysfs, first); | |
+- if (r < 0) | |
+- goto fail; | |
+- } | |
+- | |
+- device_make_description(u, dev, path); | |
++ r = device_set_sysfs(DEVICE(u), sysfs); | |
++ if (r < 0) | |
++ goto fail; | |
+ | |
+- if (main) { | |
+- /* The additional systemd udev properties we only | |
+- * interpret for the main object */ | |
++ (void) device_update_description(u, dev, path); | |
+ | |
+- r = device_add_udev_wants(u, dev); | |
+- if (r < 0) | |
+- goto fail; | |
+- } | |
++ /* The additional systemd udev properties we only interpret | |
++ * for the main object */ | |
++ if (main) | |
++ (void) device_add_udev_wants(u, dev); | |
+ | |
+ /* Note that this won't dispatch the load queue, the caller | |
+ * has to do that if needed and appropriate */ | |
+@@ -334,7 +323,7 @@ static int device_update_unit(Manager *m | |
+ return 0; | |
+ | |
+ fail: | |
+- log_warning_errno(r, "Failed to load device unit: %m"); | |
++ log_unit_warning_errno(u->id, r, "Failed to set up device unit: %m"); | |
+ | |
+ if (delete && u) | |
+ unit_free(u); | |
+@@ -342,7 +331,7 @@ fail: | |
+ return r; | |
+ } | |
+ | |
+-static int device_process_new_device(Manager *m, struct udev_device *dev) { | |
++static int device_process_new(Manager *m, struct udev_device *dev) { | |
+ const char *sysfs, *dn, *alias; | |
+ struct udev_list_entry *item = NULL, *first = NULL; | |
+ int r; | |
+@@ -354,14 +343,14 @@ static int device_process_new_device(Man | |
+ return 0; | |
+ | |
+ /* Add the main unit named after the sysfs path */ | |
+- r = device_update_unit(m, dev, sysfs, true); | |
++ r = device_setup_unit(m, dev, sysfs, true); | |
+ if (r < 0) | |
+ return r; | |
+ | |
+ /* Add an additional unit for the device node */ | |
+ dn = udev_device_get_devnode(dev); | |
+ if (dn) | |
+- device_update_unit(m, dev, dn, false); | |
++ (void) device_setup_unit(m, dev, dn, false); | |
+ | |
+ /* Add additional units for all symlinks */ | |
+ first = udev_device_get_devlinks_list_entry(dev); | |
+@@ -388,7 +377,7 @@ static int device_process_new_device(Man | |
+ st.st_rdev != udev_device_get_devnum(dev)) | |
+ continue; | |
+ | |
+- device_update_unit(m, dev, p, false); | |
++ (void) device_setup_unit(m, dev, p, false); | |
+ } | |
+ | |
+ /* Add additional units for all explicitly configured | |
+@@ -405,7 +394,7 @@ static int device_process_new_device(Man | |
+ e[l] = 0; | |
+ | |
+ if (path_is_absolute(e)) | |
+- device_update_unit(m, dev, e, false); | |
++ (void) device_setup_unit(m, dev, e, false); | |
+ else | |
+ log_warning("SYSTEMD_ALIAS for %s is not an absolute path, ignoring: %s", sysfs, e); | |
+ } | |
+@@ -416,39 +405,62 @@ static int device_process_new_device(Man | |
+ return 0; | |
+ } | |
+ | |
+-static void device_set_path_plugged(Manager *m, struct udev_device *dev) { | |
+- const char *sysfs; | |
++static void device_update_found_one(Device *d, bool add, DeviceFound found, bool now) { | |
++ DeviceFound n; | |
++ | |
++ assert(d); | |
++ | |
++ n = add ? (d->found | found) : (d->found & ~found); | |
++ if (n == d->found) | |
++ return; | |
++ | |
++ d->found = n; | |
++ | |
++ if (now) { | |
++ if (d->found & DEVICE_FOUND_UDEV) | |
++ device_set_state(d, DEVICE_PLUGGED); | |
++ else if (d->found != DEVICE_NOT_FOUND) | |
++ device_set_state(d, DEVICE_TENTATIVE); | |
++ else | |
++ device_set_state(d, DEVICE_DEAD); | |
++ } | |
++} | |
++ | |
++static int device_update_found_by_sysfs(Manager *m, const char *sysfs, bool add, DeviceFound found, bool now) { | |
+ Device *d, *l; | |
+ | |
+ assert(m); | |
+- assert(dev); | |
++ assert(sysfs); | |
+ | |
+- sysfs = udev_device_get_syspath(dev); | |
+- if (!sysfs) | |
+- return; | |
++ if (found == DEVICE_NOT_FOUND) | |
++ return 0; | |
+ | |
+ l = hashmap_get(m->devices_by_sysfs, sysfs); | |
+ LIST_FOREACH(same_sysfs, d, l) | |
+- device_set_state(d, DEVICE_PLUGGED); | |
++ device_update_found_one(d, add, found, now); | |
++ | |
++ return 0; | |
+ } | |
+ | |
+-static int device_process_removed_device(Manager *m, struct udev_device *dev) { | |
+- const char *sysfs; | |
+- Device *d; | |
++static int device_update_found_by_name(Manager *m, const char *path, bool add, DeviceFound found, bool now) { | |
++ _cleanup_free_ char *e = NULL; | |
++ Unit *u; | |
+ | |
+ assert(m); | |
+- assert(dev); | |
++ assert(path); | |
+ | |
+- sysfs = udev_device_get_syspath(dev); | |
+- if (!sysfs) | |
+- return -ENOMEM; | |
++ if (found == DEVICE_NOT_FOUND) | |
++ return 0; | |
+ | |
+- /* Remove all units of this sysfs path */ | |
+- while ((d = hashmap_get(m->devices_by_sysfs, sysfs))) { | |
+- device_unset_sysfs(d); | |
+- device_set_state(d, DEVICE_DEAD); | |
+- } | |
++ e = unit_name_from_path(path, ".device"); | |
++ if (!e) | |
++ return log_oom(); | |
+ | |
++ u = manager_get_unit(m, e); | |
++ if (!u) | |
++ return 0; | |
++ | |
++ device_update_found_one(DEVICE(u), add, found, now); | |
+ return 0; | |
+ } | |
+ | |
+@@ -464,22 +476,6 @@ static bool device_is_ready(struct udev_ | |
+ return parse_boolean(ready) != 0; | |
+ } | |
+ | |
+-static int device_process_new_path(Manager *m, const char *path) { | |
+- _cleanup_udev_device_unref_ struct udev_device *dev = NULL; | |
+- | |
+- assert(m); | |
+- assert(path); | |
+- | |
+- dev = udev_device_new_from_syspath(m->udev, path); | |
+- if (!dev) | |
+- return log_oom(); | |
+- | |
+- if (!device_is_ready(dev)) | |
+- return 0; | |
+- | |
+- return device_process_new_device(m, dev); | |
+-} | |
+- | |
+ static Unit *device_following(Unit *u) { | |
+ Device *d = DEVICE(u); | |
+ Device *other, *first = NULL; | |
+@@ -606,12 +602,31 @@ static int device_enumerate(Manager *m) | |
+ goto fail; | |
+ | |
+ first = udev_enumerate_get_list_entry(e); | |
+- udev_list_entry_foreach(item, first) | |
+- device_process_new_path(m, udev_list_entry_get_name(item)); | |
++ udev_list_entry_foreach(item, first) { | |
++ _cleanup_udev_device_unref_ struct udev_device *dev = NULL; | |
++ const char *sysfs; | |
++ | |
++ sysfs = udev_list_entry_get_name(item); | |
++ | |
++ dev = udev_device_new_from_syspath(m->udev, sysfs); | |
++ if (!dev) { | |
++ log_oom(); | |
++ continue; | |
++ } | |
++ | |
++ if (!device_is_ready(dev)) | |
++ continue; | |
++ | |
++ (void) device_process_new(m, dev); | |
++ | |
++ device_update_found_by_sysfs(m, sysfs, true, DEVICE_FOUND_UDEV, false); | |
++ } | |
+ | |
+ return 0; | |
+ | |
+ fail: | |
++ log_error_errno(r, "Failed to enumerate devices: %m"); | |
++ | |
+ device_shutdown(m); | |
+ return r; | |
+ } | |
+@@ -619,7 +634,7 @@ fail: | |
+ static int device_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) { | |
+ _cleanup_udev_device_unref_ struct udev_device *dev = NULL; | |
+ Manager *m = userdata; | |
+- const char *action; | |
++ const char *action, *sysfs; | |
+ int r; | |
+ | |
+ assert(m); | |
+@@ -641,33 +656,47 @@ static int device_dispatch_io(sd_event_s | |
+ if (!dev) | |
+ return 0; | |
+ | |
++ sysfs = udev_device_get_syspath(dev); | |
++ if (!sysfs) { | |
++ log_error("Failed to get udev sys path."); | |
++ return 0; | |
++ } | |
++ | |
+ action = udev_device_get_action(dev); | |
+ if (!action) { | |
+ log_error("Failed to get udev action string."); | |
+ return 0; | |
+ } | |
+ | |
+- if (streq(action, "remove") || !device_is_ready(dev)) { | |
+- r = device_process_removed_device(m, dev); | |
+- if (r < 0) | |
+- log_error_errno(r, "Failed to process device remove event: %m"); | |
+- | |
+- r = swap_process_removed_device(m, dev); | |
++ if (streq(action, "remove")) { | |
++ r = swap_process_device_remove(m, dev); | |
+ if (r < 0) | |
+ log_error_errno(r, "Failed to process swap device remove event: %m"); | |
+ | |
+- } else { | |
+- r = device_process_new_device(m, dev); | |
+- if (r < 0) | |
+- log_error_errno(r, "Failed to process device new event: %m"); | |
++ /* If we get notified that a device was removed by | |
++ * udev, then it's completely gone, hence unset all | |
++ * found bits */ | |
++ device_update_found_by_sysfs(m, sysfs, false, DEVICE_FOUND_UDEV|DEVICE_FOUND_MOUNT|DEVICE_FOUND_SWAP, true); | |
+ | |
+- r = swap_process_new_device(m, dev); | |
++ } else if (device_is_ready(dev)) { | |
++ | |
++ (void) device_process_new(m, dev); | |
++ | |
++ r = swap_process_device_new(m, dev); | |
+ if (r < 0) | |
+ log_error_errno(r, "Failed to process swap device new event: %m"); | |
+ | |
+ manager_dispatch_load_queue(m); | |
+ | |
+- device_set_path_plugged(m, dev); | |
++ /* The device is found now, set the udev found bit */ | |
++ device_update_found_by_sysfs(m, sysfs, true, DEVICE_FOUND_UDEV, true); | |
++ | |
++ } else { | |
++ /* The device is nominally around, but not ready for | |
++ * us. Hence unset the udev bit, but leave the rest | |
++ * around. */ | |
++ | |
++ device_update_found_by_sysfs(m, sysfs, false, DEVICE_FOUND_UDEV, true); | |
+ } | |
+ | |
+ return 0; | |
+@@ -686,9 +715,58 @@ static bool device_supported(Manager *m) | |
+ return read_only <= 0; | |
+ } | |
+ | |
++int device_found_node(Manager *m, const char *node, bool add, DeviceFound found, bool now) { | |
++ _cleanup_udev_device_unref_ struct udev_device *dev = NULL; | |
++ struct stat st; | |
++ | |
++ assert(m); | |
++ assert(node); | |
++ | |
++ /* This is called whenever we find a device referenced in | |
++ * /proc/swaps or /proc/self/mounts. Such a device might be | |
++ * mounted/enabled at a time where udev has not finished | |
++ * probing it yet, and we thus haven't learned about it | |
++ * yet. In this case we will set the device unit to | |
++ * "tentative" state. */ | |
++ | |
++ if (add) { | |
++ if (!path_startswith(node, "/dev")) | |
++ return 0; | |
++ | |
++ if (stat(node, &st) < 0) { | |
++ if (errno == ENOENT) | |
++ return 0; | |
++ | |
++ return log_error_errno(errno, "Failed to stat device node file %s: %m", node); | |
++ } | |
++ | |
++ if (!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode)) | |
++ return 0; | |
++ | |
++ dev = udev_device_new_from_devnum(m->udev, S_ISBLK(st.st_mode) ? 'b' : 'c', st.st_rdev); | |
++ if (!dev) { | |
++ if (errno == ENOENT) | |
++ return 0; | |
++ | |
++ return log_oom(); | |
++ } | |
++ | |
++ /* If the device is known in the kernel and newly | |
++ * appeared, then we'll create a device unit for it, | |
++ * under the name referenced in /proc/swaps or | |
++ * /proc/self/mountinfo. */ | |
++ | |
++ (void) device_setup_unit(m, dev, node, false); | |
++ } | |
++ | |
++ /* Update the device unit's state, should it exist */ | |
++ return device_update_found_by_name(m, node, add, found, now); | |
++} | |
++ | |
+ static const char* const device_state_table[_DEVICE_STATE_MAX] = { | |
+ [DEVICE_DEAD] = "dead", | |
+- [DEVICE_PLUGGED] = "plugged" | |
++ [DEVICE_TENTATIVE] = "tentative", | |
++ [DEVICE_PLUGGED] = "plugged", | |
+ }; | |
+ | |
+ DEFINE_STRING_TABLE_LOOKUP(device_state, DeviceState); | |
+Index: systemd-219/src/core/device.h | |
+=================================================================== | |
+--- systemd-219.orig/src/core/device.h | |
++++ systemd-219/src/core/device.h | |
+@@ -29,20 +29,28 @@ typedef struct Device Device; | |
+ * simplifies the state engine greatly */ | |
+ typedef enum DeviceState { | |
+ DEVICE_DEAD, | |
+- DEVICE_PLUGGED, | |
++ DEVICE_TENTATIVE, /* mounted or swapped, but not (yet) announced by udev */ | |
++ DEVICE_PLUGGED, /* announced by udev */ | |
+ _DEVICE_STATE_MAX, | |
+ _DEVICE_STATE_INVALID = -1 | |
+ } DeviceState; | |
+ | |
++typedef enum DeviceFound { | |
++ DEVICE_NOT_FOUND = 0, | |
++ DEVICE_FOUND_UDEV = 1, | |
++ DEVICE_FOUND_MOUNT = 2, | |
++ DEVICE_FOUND_SWAP = 4, | |
++} DeviceFound; | |
++ | |
+ struct Device { | |
+ Unit meta; | |
+ | |
+ char *sysfs; | |
++ DeviceFound found; | |
+ | |
+ /* In order to be able to distinguish dependencies on | |
+ different device nodes we might end up creating multiple | |
+ devices for the same sysfs path. We chain them up here. */ | |
+- | |
+ LIST_FIELDS(struct Device, same_sysfs); | |
+ | |
+ DeviceState state; | |
+@@ -52,3 +60,5 @@ extern const UnitVTable device_vtable; | |
+ | |
+ const char* device_state_to_string(DeviceState i) _const_; | |
+ DeviceState device_state_from_string(const char *s) _pure_; | |
++ | |
++int device_found_node(Manager *m, const char *node, bool add, DeviceFound found, bool now); | |
+Index: systemd-219/src/core/mount.c | |
+=================================================================== | |
+--- systemd-219.orig/src/core/mount.c | |
++++ systemd-219/src/core/mount.c | |
+@@ -1391,7 +1391,7 @@ static int mount_dispatch_timer(sd_event | |
+ return 0; | |
+ } | |
+ | |
+-static int mount_add_one( | |
++static int mount_setup_unit( | |
+ Manager *m, | |
+ const char *what, | |
+ const char *where, | |
+@@ -1434,7 +1434,7 @@ static int mount_add_one( | |
+ | |
+ u = unit_new(m, sizeof(Mount)); | |
+ if (!u) | |
+- return -ENOMEM; | |
++ return log_oom(); | |
+ | |
+ r = unit_add_name(u, e); | |
+ if (r < 0) | |
+@@ -1547,6 +1547,8 @@ static int mount_add_one( | |
+ return 0; | |
+ | |
+ fail: | |
++ log_warning_errno(r, "Failed to set up mount unit: %m"); | |
++ | |
+ if (delete && u) | |
+ unit_free(u); | |
+ | |
+@@ -1554,33 +1556,36 @@ fail: | |
+ } | |
+ | |
+ static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) { | |
+- _cleanup_(mnt_free_tablep) struct libmnt_table *tb = NULL; | |
+- _cleanup_(mnt_free_iterp) struct libmnt_iter *itr = NULL; | |
+- struct libmnt_fs *fs; | |
++ _cleanup_(mnt_free_tablep) struct libmnt_table *t = NULL; | |
++ _cleanup_(mnt_free_iterp) struct libmnt_iter *i = NULL; | |
+ int r = 0; | |
+ | |
+ assert(m); | |
+ | |
+- tb = mnt_new_table(); | |
+- itr = mnt_new_iter(MNT_ITER_FORWARD); | |
+- if (!tb || !itr) | |
++ t = mnt_new_table(); | |
++ if (!t) | |
++ return log_oom(); | |
++ | |
++ i = mnt_new_iter(MNT_ITER_FORWARD); | |
++ if (!i) | |
+ return log_oom(); | |
+ | |
+- r = mnt_table_parse_mtab(tb, NULL); | |
++ r = mnt_table_parse_mtab(t, NULL); | |
+ if (r < 0) | |
+- return r; | |
++ return log_error_errno(r, "Failed to parse /proc/self/mountinfo: %m"); | |
+ | |
+ r = 0; | |
+ for (;;) { | |
+ const char *device, *path, *options, *fstype; | |
+ _cleanup_free_ const char *d = NULL, *p = NULL; | |
++ struct libmnt_fs *fs; | |
+ int k; | |
+ | |
+- k = mnt_table_next_fs(tb, itr, &fs); | |
++ k = mnt_table_next_fs(t, i, &fs); | |
+ if (k == 1) | |
+ break; | |
+- else if (k < 0) | |
+- return log_error_errno(k, "Failed to get next entry from /etc/fstab: %m"); | |
++ if (k < 0) | |
++ return log_error_errno(k, "Failed to get next entry from /proc/self/mountinfo: %m"); | |
+ | |
+ device = mnt_fs_get_source(fs); | |
+ path = mnt_fs_get_target(fs); | |
+@@ -1588,11 +1593,16 @@ static int mount_load_proc_self_mountinf | |
+ fstype = mnt_fs_get_fstype(fs); | |
+ | |
+ d = cunescape(device); | |
++ if (!d) | |
++ return log_oom(); | |
++ | |
+ p = cunescape(path); | |
+- if (!d || !p) | |
++ if (!p) | |
+ return log_oom(); | |
+ | |
+- k = mount_add_one(m, d, p, options, fstype, set_flags); | |
++ (void) device_found_node(m, d, true, DEVICE_FOUND_MOUNT, set_flags); | |
++ | |
++ k = mount_setup_unit(m, d, p, options, fstype, set_flags); | |
+ if (r == 0 && k < 0) | |
+ r = k; | |
+ } | |
+@@ -1736,8 +1746,6 @@ static int mount_dispatch_io(sd_event_so | |
+ | |
+ r = mount_load_proc_self_mountinfo(m, true); | |
+ if (r < 0) { | |
+- log_error_errno(r, "Failed to reread /proc/self/mountinfo: %m"); | |
+- | |
+ /* Reset flags, just in case, for later calls */ | |
+ LIST_FOREACH(units_by_type, u, m->units_by_type[UNIT_MOUNT]) { | |
+ Mount *mount = MOUNT(u); | |
+@@ -1770,6 +1778,10 @@ static int mount_dispatch_io(sd_event_so | |
+ break; | |
+ } | |
+ | |
++ if (mount->parameters_proc_self_mountinfo.what) | |
++ (void) device_found_node(m, mount->parameters_proc_self_mountinfo.what, false, DEVICE_FOUND_MOUNT, true); | |
++ | |
++ | |
+ } else if (mount->just_mounted || mount->just_changed) { | |
+ | |
+ /* New or changed mount entry */ | |
+Index: systemd-219/src/core/swap.c | |
+=================================================================== | |
+--- systemd-219.orig/src/core/swap.c | |
++++ systemd-219/src/core/swap.c | |
+@@ -338,7 +338,7 @@ static int swap_load(Unit *u) { | |
+ return swap_verify(s); | |
+ } | |
+ | |
+-static int swap_add_one( | |
++static int swap_setup_unit( | |
+ Manager *m, | |
+ const char *what, | |
+ const char *what_proc_swaps, | |
+@@ -363,8 +363,10 @@ static int swap_add_one( | |
+ | |
+ if (u && | |
+ SWAP(u)->from_proc_swaps && | |
+- !path_equal(SWAP(u)->parameters_proc_swaps.what, what_proc_swaps)) | |
++ !path_equal(SWAP(u)->parameters_proc_swaps.what, what_proc_swaps)) { | |
++ log_error("Swap %s appeared twice with different device paths %s and %s", e, SWAP(u)->parameters_proc_swaps.what, what_proc_swaps); | |
+ return -EEXIST; | |
++ } | |
+ | |
+ if (!u) { | |
+ delete = true; | |
+@@ -379,7 +381,7 @@ static int swap_add_one( | |
+ | |
+ SWAP(u)->what = strdup(what); | |
+ if (!SWAP(u)->what) { | |
+- r = log_oom(); | |
++ r = -ENOMEM; | |
+ goto fail; | |
+ } | |
+ | |
+@@ -407,7 +409,6 @@ static int swap_add_one( | |
+ p->priority = priority; | |
+ | |
+ unit_add_to_dbus_queue(u); | |
+- | |
+ return 0; | |
+ | |
+ fail: | |
+@@ -419,7 +420,7 @@ fail: | |
+ return r; | |
+ } | |
+ | |
+-static int swap_process_new_swap(Manager *m, const char *device, int prio, bool set_flags) { | |
++static int swap_process_new(Manager *m, const char *device, int prio, bool set_flags) { | |
+ _cleanup_udev_device_unref_ struct udev_device *d = NULL; | |
+ struct udev_list_entry *item = NULL, *first = NULL; | |
+ const char *dn; | |
+@@ -428,7 +429,7 @@ static int swap_process_new_swap(Manager | |
+ | |
+ assert(m); | |
+ | |
+- r = swap_add_one(m, device, device, prio, set_flags); | |
++ r = swap_setup_unit(m, device, device, prio, set_flags); | |
+ if (r < 0) | |
+ return r; | |
+ | |
+@@ -444,7 +445,7 @@ static int swap_process_new_swap(Manager | |
+ /* Add the main device node */ | |
+ dn = udev_device_get_devnode(d); | |
+ if (dn && !streq(dn, device)) | |
+- swap_add_one(m, dn, device, prio, set_flags); | |
++ swap_setup_unit(m, dn, device, prio, set_flags); | |
+ | |
+ /* Add additional units for all symlinks */ | |
+ first = udev_device_get_devlinks_list_entry(d); | |
+@@ -465,7 +466,7 @@ static int swap_process_new_swap(Manager | |
+ st.st_rdev != udev_device_get_devnum(d)) | |
+ continue; | |
+ | |
+- swap_add_one(m, p, device, prio, set_flags); | |
++ swap_setup_unit(m, p, device, prio, set_flags); | |
+ } | |
+ | |
+ return r; | |
+@@ -1091,15 +1092,17 @@ static int swap_load_proc_swaps(Manager | |
+ if (k == EOF) | |
+ break; | |
+ | |
+- log_warning("Failed to parse /proc/swaps:%u", i); | |
++ log_warning("Failed to parse /proc/swaps:%u.", i); | |
+ continue; | |
+ } | |
+ | |
+ d = cunescape(dev); | |
+ if (!d) | |
+- return -ENOMEM; | |
++ return log_oom(); | |
++ | |
++ device_found_node(m, d, true, DEVICE_FOUND_SWAP, set_flags); | |
+ | |
+- k = swap_process_new_swap(m, d, prio, set_flags); | |
++ k = swap_process_new(m, d, prio, set_flags); | |
+ if (k < 0) | |
+ r = k; | |
+ } | |
+@@ -1151,6 +1154,9 @@ static int swap_dispatch_io(sd_event_sou | |
+ break; | |
+ } | |
+ | |
++ if (swap->what) | |
++ device_found_node(m, swap->what, false, DEVICE_FOUND_SWAP, true); | |
++ | |
+ } else if (swap->just_activated) { | |
+ | |
+ /* New swap entry */ | |
+@@ -1298,7 +1304,7 @@ fail: | |
+ return r; | |
+ } | |
+ | |
+-int swap_process_new_device(Manager *m, struct udev_device *dev) { | |
++int swap_process_device_new(Manager *m, struct udev_device *dev) { | |
+ struct udev_list_entry *item = NULL, *first = NULL; | |
+ _cleanup_free_ char *e = NULL; | |
+ const char *dn; | |
+@@ -1341,7 +1347,7 @@ int swap_process_new_device(Manager *m, | |
+ return r; | |
+ } | |
+ | |
+-int swap_process_removed_device(Manager *m, struct udev_device *dev) { | |
++int swap_process_device_remove(Manager *m, struct udev_device *dev) { | |
+ const char *dn; | |
+ int r = 0; | |
+ Swap *s; | |
+Index: systemd-219/src/core/swap.h | |
+=================================================================== | |
+--- systemd-219.orig/src/core/swap.h | |
++++ systemd-219/src/core/swap.h | |
+@@ -116,8 +116,8 @@ struct Swap { | |
+ | |
+ extern const UnitVTable swap_vtable; | |
+ | |
+-int swap_process_new_device(Manager *m, struct udev_device *dev); | |
+-int swap_process_removed_device(Manager *m, struct udev_device *dev); | |
++int swap_process_device_new(Manager *m, struct udev_device *dev); | |
++int swap_process_device_remove(Manager *m, struct udev_device *dev); | |
+ | |
+ const char* swap_state_to_string(SwapState i) _const_; | |
+ SwapState swap_state_from_string(const char *s) _pure_; | |
+Index: systemd-219/src/core/unit.c | |
+=================================================================== | |
+--- systemd-219.orig/src/core/unit.c | |
++++ systemd-219/src/core/unit.c | |
+@@ -2841,7 +2841,6 @@ int unit_add_node_link(Unit *u, const ch | |
+ return -ENOMEM; | |
+ | |
+ r = manager_load_unit(u->manager, e, NULL, NULL, &device); | |
+- | |
+ if (r < 0) | |
+ return r; | |
+ | |
diff --git a/debian/patches/Dont_change_removed_devices_to_tentative.patch b/debian/patches/Dont_change_removed_devices_to_tentative.patch | |
new file mode 100644 | |
index 0000000000..9fce919771 | |
--- /dev/null | |
+++ b/debian/patches/Dont_change_removed_devices_to_tentative.patch | |
@@ -0,0 +1,29 @@ | |
+commit 496068a8288084ab3ecf8b179a8403ecff1a6be8 | |
+Author: Martin Pitt <martin.pitt@ubuntu.com> | |
+Date: Fri Mar 13 08:35:59 2015 +0100 | |
+ | |
+ core: don't change removed devices to state "tentative" | |
+ | |
+ Commit 628c89c introduced the "tentative" device state, which caused | |
+ devices to go from "plugged" to "tentative" on a remove uevent. This | |
+ breaks the cleanup of stale mounts (see commit 3b48ce4), as that only | |
+ applies to "dead" devices. | |
+ | |
+ The "tentative" state only really makes sense on adding a device when | |
+ we don't know where it was coming from (i. e. not from udev). But when | |
+ we get a device removal from udev we definitively know that it's gone, | |
+ so change the device state back to "dead" as before 628c89c. | |
+ | |
+diff --git a/src/core/device.c b/src/core/device.c | |
+index 4bfd71f..b5d9d82 100644 | |
+--- a/src/core/device.c | |
++++ b/src/core/device.c | |
+@@ -419,7 +419,7 @@ static void device_update_found_one(Device *d, bool add, DeviceFound found, bool | |
+ if (now) { | |
+ if (d->found & DEVICE_FOUND_UDEV) | |
+ device_set_state(d, DEVICE_PLUGGED); | |
+- else if (d->found != DEVICE_NOT_FOUND) | |
++ else if (add && d->found != DEVICE_NOT_FOUND) | |
+ device_set_state(d, DEVICE_TENTATIVE); | |
+ else | |
+ device_set_state(d, DEVICE_DEAD); | |
diff --git a/debian/patches/core-mount-ensure-that-we-parse-proc-self-mountinfo.patch b/debian/patches/core-mount-ensure-that-we-parse-proc-self-mountinfo.patch | |
index f5d878c5e8..5d9d39656d 100644 | |
--- a/debian/patches/core-mount-ensure-that-we-parse-proc-self-mountinfo.patch | |
+++ b/debian/patches/core-mount-ensure-that-we-parse-proc-self-mountinfo.patch | |
@@ -28,20 +28,20 @@ https://launchpad.net/bugs/1419623 | |
src/core/mount.c | 6 +++++- | |
1 file changed, 5 insertions(+), 1 deletion(-) | |
-diff --git a/src/core/mount.c b/src/core/mount.c | |
-index f3977e6..3e7d005 100644 | |
---- a/src/core/mount.c | |
-+++ b/src/core/mount.c | |
-@@ -1566,7 +1566,11 @@ static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) { | |
- if (!tb || !itr) | |
+Index: systemd-219/src/core/mount.c | |
+=================================================================== | |
+--- systemd-219.orig/src/core/mount.c | |
++++ systemd-219/src/core/mount.c | |
+@@ -1570,7 +1570,11 @@ static int mount_load_proc_self_mountinf | |
+ if (!i) | |
return log_oom(); | |
-- r = mnt_table_parse_mtab(tb, NULL); | |
+- r = mnt_table_parse_mtab(t, NULL); | |
+ /* FIXME: We really mean "/proc/self/mountinfo" here, but as that's a | |
+ * regular file this will trick libmount into not parsing | |
+ * /run/mount/utab; so give it an invalid file to trigger the fallback | |
+ * to /proc/self/mountinfo. */ | |
-+ r = mnt_table_parse_mtab(tb, "/"); | |
++ r = mnt_table_parse_mtab(t, "/"); | |
if (r < 0) | |
- return r; | |
+ return log_error_errno(r, "Failed to parse /proc/self/mountinfo: %m"); | |
diff --git a/debian/patches/series b/debian/patches/series | |
index 9a765ed345..bffcfaad83 100644 | |
--- a/debian/patches/series | |
+++ b/debian/patches/series | |
@@ -15,6 +15,8 @@ bootchart-fix-default-init-path.patch | |
journal-fix-Inappropriate-ioctl-for-device-on-ext4.patch | |
Use-correct-uname-identifiers-in-arch_map-for-SuperH.patch | |
tmpfiles-Fix-handling-of-duplicate-lines.patch | |
+Add_tentative_state.patch | |
+Dont_change_removed_devices_to_tentative.patch | |
## Debian specific patches | |
Add-back-support-for-Debian-specific-config-files.patch | |
@@ -73,5 +75,6 @@ Revert-journald-allow-restarting-journald-without-lo.patch | |
## Ubuntu patches: | |
Support-system-image-read-only-etc.patch | |
Provide-shutdown-fallback-for-upstart.patch | |
+systemctl-Don-t-forward-telinit-u-to-upstart.patch | |
Get-RTC-is-in-local-time-setting-from-etc-default-rc.patch | |
core-Put-session-scopes-into-all-cgroup-controllers.patch | |
diff --git a/debian/patches/systemctl-Don-t-forward-telinit-u-to-upstart.patch b/debian/patches/systemctl-Don-t-forward-telinit-u-to-upstart.patch | |
new file mode 100644 | |
index 0000000000..8249d14e43 | |
--- /dev/null | |
+++ b/debian/patches/systemctl-Don-t-forward-telinit-u-to-upstart.patch | |
@@ -0,0 +1,36 @@ | |
+From: Martin Pitt <martin.pitt@ubuntu.com> | |
+Date: Wed, 11 Mar 2015 10:37:47 +0100 | |
+Subject: systemctl: Don't forward telinit u to upstart | |
+ | |
+When dist-upgrading and /sbin/init changes from upstart to systemd, upstart's | |
+Restart() exec's argv[0] which is still /sbin/init, and thus it execs systemd. | |
+This is triggered by glibc upgrades or other things which call "telinit u" in | |
+their postinst scripts. | |
+ | |
+This should eventually be fixed in upstart itself, but as we can't | |
+retroactively fix it in previous releases we upgrade from, we simply ignore | |
+the request. | |
+ | |
+https://launchpad.net/bugs/1430479 | |
+--- | |
+ src/systemctl/systemctl.c | 7 +++++++ | |
+ 1 file changed, 7 insertions(+) | |
+ | |
+diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c | |
+index 37517df..cfc501c 100644 | |
+--- a/src/systemctl/systemctl.c | |
++++ b/src/systemctl/systemctl.c | |
+@@ -6995,6 +6995,13 @@ static int parse_argv(int argc, char *argv[]) { | |
+ * request to it. For now we simply | |
+ * guess that it is Upstart. */ | |
+ | |
++ /* work around upstart exec'ing systemd when /sbin/init | |
++ * changes (https://launchpad.net/bugs/1430479) */ | |
++ if (argv[1] != NULL && streq(argv[1], "u")) { | |
++ log_warning("Ignoring telinit u request, systemd is not running"); | |
++ return -ENOTSUP; | |
++ } | |
++ | |
+ execv(TELINIT, argv); | |
+ | |
+ log_error("Couldn't find an alternative telinit implementation to spawn."); | |
diff --git a/debian/systemd-sysv.postinst b/debian/systemd-sysv.postinst | |
index 797ec60e18..e2fd036ec0 100644 | |
--- a/debian/systemd-sysv.postinst | |
+++ b/debian/systemd-sysv.postinst | |
@@ -3,7 +3,7 @@ set -e | |
# update grub on first install, so that the alternative init system boot | |
# entries get updated | |
-if [ "$1" = configure -a -z "$2" -a -e /boot/grub/grub.cfg ] && type update-grub >/dev/null 2>&1; then | |
+if [ "$1" = configure ] && [ -z "$2" ] && [ -e /boot/grub/grub.cfg ] && which update-grub >/dev/null 2>&1; then | |
update-grub || true | |
fi | |
diff --git a/debian/systemd.install b/debian/systemd.install | |
index e0eaed5815..cff37199f5 100644 | |
--- a/debian/systemd.install | |
+++ b/debian/systemd.install | |
@@ -53,3 +53,4 @@ usr/share/locale/ | |
../../extra/tmpfiles.d/*.conf usr/lib/tmpfiles.d/ | |
../../extra/debian-fixup lib/systemd/ | |
../../extra/units/* lib/systemd/system/ | |
+../../extra/systemd-ifupdown-helper lib/systemd/ | |
diff --git a/debian/tests/cmdline-upstart-boot b/debian/tests/cmdline-upstart-boot | |
index 010893635a..9bdbb8eccb 100755 | |
--- a/debian/tests/cmdline-upstart-boot | |
+++ b/debian/tests/cmdline-upstart-boot | |
@@ -68,8 +68,8 @@ class ServicesTest(unittest.TestCase): | |
def configure_boot(): | |
'''Reboot with upstart as init''' | |
- print('Installing upstart-bin and rebooting...') | |
- subprocess.check_call('apt-get -y install upstart-bin 2>&1', | |
+ print('Installing upstart and rebooting...') | |
+ subprocess.check_call('apt-get -y install upstart 2>&1', | |
shell=True) | |
print('Setting init=/sbin/upstart in grub kernel command line...') | |
subprocess.check_call(['sh', '-ec', "sed -i '/^GRUB_CMDLINE_LINUX_DEFAULT/" | |
@@ -86,10 +86,10 @@ def configure_boot(): | |
if __name__ == '__main__': | |
- # Ubuntu split out upstart-bin, Debian doesn't | |
- if subprocess.call(['apt-cache', 'show', 'upstart-bin'], | |
+ # Don't run this test under Debian as Ubuntu split out upstart-sysv, Debian doesn't | |
+ if subprocess.call(['apt-cache', 'show', 'upstart-sysv'], | |
stdout=subprocess.PIPE, stderr=subprocess.PIPE) != 0: | |
- print('SKIP: upstart-bin not available') | |
+ print('SKIP: upstart-sysv not available') | |
sys.exit(0) | |
if not os.getenv('ADT_REBOOT_MARK'): |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment