[arch-commits] Commit in systemd/trunk (4 files)
Dave Reisner
dreisner at archlinux.org
Wed Apr 22 01:08:36 UTC 2015
Date: Wednesday, April 22, 2015 @ 03:08:36
Author: dreisner
Revision: 237884
upgpkg: systemd 219-6
- backport fixes for FS#44658
Added:
systemd/trunk/0001-core-don-t-change-removed-devices-to-state-tentative.patch
systemd/trunk/0001-core-rework-device-state-logic.patch
systemd/trunk/0001-unit-use-weaker-dependencies-between-mount-and-devic.patch
Modified:
systemd/trunk/PKGBUILD
-----------------------------------------------------------------+
0001-core-don-t-change-removed-devices-to-state-tentative.patch | 34
0001-core-rework-device-state-logic.patch | 910 ++++++++++
0001-unit-use-weaker-dependencies-between-mount-and-devic.patch | 31
PKGBUILD | 15
4 files changed, 987 insertions(+), 3 deletions(-)
Added: 0001-core-don-t-change-removed-devices-to-state-tentative.patch
===================================================================
--- 0001-core-don-t-change-removed-devices-to-state-tentative.patch (rev 0)
+++ 0001-core-don-t-change-removed-devices-to-state-tentative.patch 2015-04-22 01:08:36 UTC (rev 237884)
@@ -0,0 +1,34 @@
+From 496068a8288084ab3ecf8b179a8403ecff1a6be8 Mon Sep 17 00:00:00 2001
+From: Martin Pitt <martin.pitt at ubuntu.com>
+Date: Fri, 13 Mar 2015 08:35:59 +0100
+Subject: [PATCH] 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.
+---
+ src/core/device.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/core/device.c b/src/core/device.c
+index 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);
+--
+2.3.5
+
Added: 0001-core-rework-device-state-logic.patch
===================================================================
--- 0001-core-rework-device-state-logic.patch (rev 0)
+++ 0001-core-rework-device-state-logic.patch 2015-04-22 01:08:36 UTC (rev 237884)
@@ -0,0 +1,910 @@
+From 628c89cc68ab96fce2de7ebba5933725d147aecc Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart at poettering.net>
+Date: Fri, 27 Feb 2015 21:55:08 +0100
+Subject: [PATCH] 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.
+---
+ src/core/device.c | 368 +++++++++++++++++++++++++++++++++---------------------
+ src/core/device.h | 14 ++-
+ src/core/mount.c | 46 ++++---
+ src/core/swap.c | 32 +++--
+ src/core/swap.h | 4 +-
+ src/core/unit.c | 1 -
+ 6 files changed, 285 insertions(+), 180 deletions(-)
+
+diff --git a/src/core/device.c b/src/core/device.c
+index 2d983cc..e41ed41 100644
+--- a/src/core/device.c
++++ b/src/core/device.c
+@@ -34,7 +34,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);
+@@ -63,6 +64,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);
+
+@@ -110,8 +146,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;
+ }
+@@ -140,49 +181,9 @@ _pure_ static const char *device_sub_state_to_string(Unit *u) {
+ 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);
+@@ -207,13 +208,16 @@ static int device_make_description(Unit *u, struct udev_device *dev, const char
+
+ 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) {
+@@ -240,20 +244,20 @@ static int device_add_udev_wants(Unit *u, struct udev_device *dev) {
+
+ 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;
+@@ -267,12 +271,18 @@ static int device_update_unit(Manager *m, struct udev_device *dev, const char *p
+ 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;
+@@ -281,7 +291,7 @@ static int device_update_unit(Manager *m, struct udev_device *dev, const char *p
+ if (!u)
+ return log_oom();
+
+- r = device_add_escaped_name(u, path);
++ r = unit_add_name(u, e);
+ if (r < 0)
+ goto fail;
+
+@@ -293,37 +303,16 @@ static int device_update_unit(Manager *m, struct udev_device *dev, const char *p
+ * 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 */
+@@ -332,7 +321,7 @@ static int device_update_unit(Manager *m, struct udev_device *dev, const char *p
+ 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);
+@@ -340,7 +329,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;
+@@ -352,14 +341,14 @@ static int device_process_new_device(Manager *m, struct udev_device *dev) {
+ 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);
+@@ -386,7 +375,7 @@ static int device_process_new_device(Manager *m, struct udev_device *dev) {
+ 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
+@@ -403,7 +392,7 @@ static int device_process_new_device(Manager *m, struct udev_device *dev) {
+ 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);
+ }
+@@ -414,39 +403,62 @@ static int device_process_new_device(Manager *m, struct udev_device *dev) {
+ 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;
+ }
+
+@@ -462,22 +474,6 @@ static bool device_is_ready(struct udev_device *dev) {
+ 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;
+@@ -604,12 +600,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;
+ }
+@@ -617,7 +632,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);
+@@ -639,33 +654,47 @@ static int device_dispatch_io(sd_event_source *source, int fd, uint32_t revents,
+ 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;
+@@ -684,9 +713,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);
+diff --git a/src/core/device.h b/src/core/device.h
+index 9065085..9f46e08 100644
+--- a/src/core/device.h
++++ b/src/core/device.h
+@@ -28,20 +28,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;
+@@ -51,3 +59,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);
+diff --git a/src/core/mount.c b/src/core/mount.c
+index 40037e7..8e4a376 100644
+--- a/src/core/mount.c
++++ b/src/core/mount.c
+@@ -1386,7 +1386,7 @@ static int mount_dispatch_timer(sd_event_source *source, usec_t usec, void *user
+ return 0;
+ }
+
+-static int mount_add_one(
++static int mount_setup_unit(
+ Manager *m,
+ const char *what,
+ const char *where,
+@@ -1429,7 +1429,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)
+@@ -1542,6 +1542,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);
+
+@@ -1549,33 +1551,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();
+
+- r = mnt_table_parse_mtab(tb, NULL);
++ i = mnt_new_iter(MNT_ITER_FORWARD);
++ if (!i)
++ return log_oom();
++
++ 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);
+@@ -1583,11 +1588,16 @@ static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) {
+ 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;
+ }
+@@ -1731,8 +1741,6 @@ static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents,
+
+ 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);
+@@ -1765,6 +1773,10 @@ static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents,
+ 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 */
+diff --git a/src/core/swap.c b/src/core/swap.c
+index f73a8e6..de3a5d8 100644
+--- a/src/core/swap.c
++++ b/src/core/swap.c
+@@ -331,7 +331,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,
+@@ -356,8 +356,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;
+@@ -372,7 +374,7 @@ static int swap_add_one(
+
+ SWAP(u)->what = strdup(what);
+ if (!SWAP(u)->what) {
+- r = log_oom();
++ r = -ENOMEM;
+ goto fail;
+ }
+
+@@ -400,7 +402,6 @@ static int swap_add_one(
+ p->priority = priority;
+
+ unit_add_to_dbus_queue(u);
+-
+ return 0;
+
+ fail:
+@@ -412,7 +413,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;
+@@ -421,7 +422,7 @@ static int swap_process_new_swap(Manager *m, const char *device, int prio, bool
+
+ 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;
+
+@@ -437,7 +438,7 @@ static int swap_process_new_swap(Manager *m, const char *device, int prio, bool
+ /* 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);
+@@ -458,7 +459,7 @@ static int swap_process_new_swap(Manager *m, const char *device, int prio, bool
+ 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;
+@@ -1084,15 +1085,17 @@ static int swap_load_proc_swaps(Manager *m, bool set_flags) {
+ 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;
+ }
+@@ -1144,6 +1147,9 @@ static int swap_dispatch_io(sd_event_source *source, int fd, uint32_t revents, v
+ break;
+ }
+
++ if (swap->what)
++ device_found_node(m, swap->what, false, DEVICE_FOUND_SWAP, true);
++
+ } else if (swap->just_activated) {
+
+ /* New swap entry */
+@@ -1291,7 +1297,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;
+@@ -1334,7 +1340,7 @@ int swap_process_new_device(Manager *m, struct udev_device *dev) {
+ 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;
+diff --git a/src/core/swap.h b/src/core/swap.h
+index c36c6f2..5de8c20 100644
+--- a/src/core/swap.h
++++ b/src/core/swap.h
+@@ -115,8 +115,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_;
+diff --git a/src/core/unit.c b/src/core/unit.c
+index 63ccd67..7cd7043 100644
+--- a/src/core/unit.c
++++ b/src/core/unit.c
+@@ -2834,7 +2834,6 @@ int unit_add_node_link(Unit *u, const char *what, bool wants) {
+ return -ENOMEM;
+
+ r = manager_load_unit(u->manager, e, NULL, NULL, &device);
+-
+ if (r < 0)
+ return r;
+
+--
+2.3.5
+
Added: 0001-unit-use-weaker-dependencies-between-mount-and-devic.patch
===================================================================
--- 0001-unit-use-weaker-dependencies-between-mount-and-devic.patch (rev 0)
+++ 0001-unit-use-weaker-dependencies-between-mount-and-devic.patch 2015-04-22 01:08:36 UTC (rev 237884)
@@ -0,0 +1,31 @@
+From 5bd4b173605142c7be493aa4d958ebaef21f421d Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart at poettering.net>
+Date: Wed, 25 Feb 2015 22:05:14 +0100
+Subject: [PATCH] unit: use weaker dependencies between mount and device units
+ in --user mode
+
+When running in user mode unmounting of mount units when a device
+vanishes is unlikely to work, and even if it would work is already done
+by PID 1 anyway. HEnce, when creating implicit dependencies between
+mount units and their backing devices, created a Wants= type dependency
+in --user mode, but leave a BindsTo= dependency in --system mode.
+---
+ src/core/unit.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/core/unit.c b/src/core/unit.c
+index ad5348b..875befa 100644
+--- a/src/core/unit.c
++++ b/src/core/unit.c
+@@ -2839,7 +2839,7 @@ int unit_add_node_link(Unit *u, const char *what, bool wants) {
+ if (r < 0)
+ return r;
+
+- r = unit_add_two_dependencies(u, UNIT_AFTER, UNIT_BINDS_TO, device, true);
++ r = unit_add_two_dependencies(u, UNIT_AFTER, u->manager->running_as == SYSTEMD_SYSTEM ? UNIT_BINDS_TO : UNIT_WANTS, device, true);
+ if (r < 0)
+ return r;
+
+--
+2.3.5
+
Modified: PKGBUILD
===================================================================
--- PKGBUILD 2015-04-21 20:45:03 UTC (rev 237883)
+++ PKGBUILD 2015-04-22 01:08:36 UTC (rev 237884)
@@ -4,7 +4,7 @@
pkgbase=systemd
pkgname=('systemd' 'libsystemd' 'systemd-sysvcompat')
pkgver=219
-pkgrel=5
+pkgrel=6
arch=('i686' 'x86_64')
url="http://www.freedesktop.org/wiki/Software/systemd"
makedepends=('acl' 'cryptsetup' 'docbook-xsl' 'gobject-introspection' 'gperf'
@@ -21,7 +21,10 @@
'0001-core-shared-in-deserializing-match-same-files-reache.patch'
'0001-tmpfiles-Fix-handling-of-duplicate-lines.patch'
'0001-core-do-not-spawn-jobs-or-touch-other-units-during-c.patch'
- '0001-use-x-machine-unix-prefix-for-the-container-bus-on-dbus1.patch')
+ '0001-use-x-machine-unix-prefix-for-the-container-bus-on-dbus1.patch'
+ '0001-unit-use-weaker-dependencies-between-mount-and-devic.patch'
+ '0001-core-rework-device-state-logic.patch'
+ '0001-core-don-t-change-removed-devices-to-state-tentative.patch')
md5sums=('e0d6c9a4b4f69f66932d2230298c9a34'
'90ea67a7bb237502094914622a39e281'
'58af51bd4c0464f195b3433b4e17cf6c'
@@ -31,7 +34,10 @@
'9d46aebfc04cc849fd4295f449b239a2'
'c4c9c0f0a06314450563ed571962881e'
'6b9d611dffd92c94641360c3ef2659c1'
- '3a0fc672b34ced18ca1364edf8644165')
+ '3a0fc672b34ced18ca1364edf8644165'
+ 'cd2719e8e93ad662c00bf9f195fdce66'
+ '12e01f00c91e54680098a799517698f2'
+ 'd0aa4e5ec598063eab2e79fb95bceece')
prepare() {
cd "$pkgname-$pkgver"
@@ -42,6 +48,9 @@
patch -Np1 <../0001-tmpfiles-Fix-handling-of-duplicate-lines.patch
patch -Np1 <../0001-core-do-not-spawn-jobs-or-touch-other-units-during-c.patch
patch -Np1 <../0001-use-x-machine-unix-prefix-for-the-container-bus-on-dbus1.patch
+ patch -Np1 <../0001-unit-use-weaker-dependencies-between-mount-and-devic.patch
+ patch -Np1 <../0001-core-rework-device-state-logic.patch
+ patch -Np1 <../0001-core-don-t-change-removed-devices-to-state-tentative.patch
}
build() {
More information about the arch-commits
mailing list