Hello all,

Dimitri John Ledkov [2015-05-13 12:48 +0100]:
> I am booting without initramfs, using a plan9 filesystem as rootfs in a kvm.
> 
> Thus my /proc/cmdline has:
> root=/dev/root rootflags=rw,trans=virtio,version=9p2000.L rootfstype=9p
> 
> # mount
> /dev/root on / type 9p
> (rw,relatime,sync,dirsync,rw,trans=virtio,version=9p2000.L)
> 
> Yet, dev-root.device is dead:
> # systemctl status dev-root.device
> ● dev-root.device
>    Loaded: loaded
>    Active: inactive (dead)
> 
> This is very bad. As a harmless action like following:
> 
> # mount --bind /opt /opt
> 
> Results in opt.mount unit to be generated which BindsTo
> dev-root.device, which is inactive, thus systemd tries to stop that
> unit straight away, and umount fails and is retried infinitely...
> effectively DoSing init.

As I mentioned before, simply ignoring /dev/root doesn't help in all
cases, and hardcoding it in the code is a bit ugly.

The attached patch is a more general solution which stops creating
dead stub .device units for devices which don't exist at all. I. e.
while in your case -.mount was probably BindsTo=dev-root.device (or in
my case, in my container I had mnt.mount BindsTo=dev-sda3.device,
which exists on the host but not in the container), but with this
patch it should now not be bound to anything.

Lennart, if you don't like this there is an alternative, and more
complicated solution: We could instead teach device_found_node() to
actually do create a proper .device with the passed DeviceFound (which
is "MOUNT"), resulting in creating a state "tentative" device. I have
a half-working patch for this, but it's brittle as with pretty much
any uevent or moutinfo change the status changes back to "dead",
causing the unmount attempt. IMHO this approach isn't conceptually
correct either -- in such containers, if don't have the corresponding
device nodes at all, we shouldn't try to react to hotplug events and
clean up mounts. I. e. the "tentative" concept does not really apply
there. But I have misunderstood the intent.

Thanks for considering,

Martin

-- 
Martin Pitt                        | http://www.piware.de
Ubuntu Developer (www.ubuntu.com)  | Debian Developer  (www.debian.org)
From 76d3bc23db5aacd5e153b4472f10795d3b7b5212 Mon Sep 17 00:00:00 2001
From: Martin Pitt <martin.p...@ubuntu.com>
Date: Thu, 14 May 2015 12:36:44 +0200
Subject: [PATCH 2/2] device: Don't bind to nonexisting devices

In containers, with remote/NFS/other non-device file systems, or with /dev/root
it is common to have mountinfo entries which don't have an actual device node
in /dev, and thus device_found_node() will not create a .device unit for them
(not even a tentative one).

When binding a .mount to a .device, only do that if the .device actually
exists; if not, it would be immediately (attempted to) get unmounted again. The
previously used manager_load_unit() would create stub .device units with state
"dead", causing the above effect; so use manager_get_unit() instead.

Also revert commit 7ba2711d; it's a special case of this, and a rather ugly
hardcoding of a device name.

https://launchpad.net/bugs/1444402
http://lists.freedesktop.org/archives/systemd-devel/2015-May/031658.html
---
 src/core/mount.c | 6 ------
 src/core/unit.c  | 8 +++++---
 2 files changed, 5 insertions(+), 9 deletions(-)

diff --git a/src/core/mount.c b/src/core/mount.c
index 8853311..e143f6b 100644
--- a/src/core/mount.c
+++ b/src/core/mount.c
@@ -317,12 +317,6 @@ static int mount_add_device_links(Mount *m) {
         if (!is_device_path(p->what))
                 return 0;
 
-        /* /dev/root is a really weird thing, it's not a real device,
-         * but just a path the kernel exports for the root file system
-         * specified on the kernel command line. Ignore it here. */
-        if (path_equal(p->what, "/dev/root"))
-                return 0;
-
         if (path_equal(m->where, "/"))
                 return 0;
 
diff --git a/src/core/unit.c b/src/core/unit.c
index 1c1d9cf..9f028c4 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -2832,9 +2832,11 @@ int unit_add_node_link(Unit *u, const char *what, bool wants) {
         if (r < 0)
                 return r;
 
-        r = manager_load_unit(u->manager, e, NULL, NULL, &device);
-        if (r < 0)
-                return r;
+        device = manager_get_unit(u->manager, e);
+        if (!device) {
+                log_unit_debug(u, "Device %s does not exist, not linking to it", e);
+                return 0;
+        }
 
         r = unit_add_two_dependencies(u, UNIT_AFTER, u->manager->running_as == MANAGER_SYSTEM ? UNIT_BINDS_TO : UNIT_WANTS, device, true);
         if (r < 0)
-- 
2.1.4

Attachment: signature.asc
Description: Digital signature

_______________________________________________
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel

Reply via email to