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
signature.asc
Description: Digital signature
_______________________________________________ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel