923a60
From 75b183700853e616362cf2f22831e1e9dc8a5515 Mon Sep 17 00:00:00 2001
923a60
From: Harald Hoyer <harald@redhat.com>
923a60
Date: Tue, 24 Nov 2015 09:41:26 +0100
923a60
Subject: [PATCH] core: Do not bind a mount unit to a device, if it was from
923a60
 mountinfo
923a60
923a60
If a mount unit is bound to a device, systemd tries to umount the
923a60
mount point, if it thinks the device has gone away.
923a60
923a60
Due to the uevent queue and inotify of /proc/self/mountinfo being two
923a60
different sources, systemd can never get the ordering reliably correct.
923a60
923a60
It can happen, that in the uevent queue ADD,REMOVE,ADD is queued
923a60
and an inotify of mountinfo (or libmount event) happend with the
923a60
device in question.
923a60
923a60
systemd cannot know, at which point of time the mount happend in the
923a60
ADD,REMOVE,ADD sequence.
923a60
923a60
The real ordering might have been ADD,REMOVE,ADD,mount
923a60
and systemd might think ADD,mount,REMOVE,ADD and would umount the
923a60
mountpoint.
923a60
923a60
A test script which triggered this behaviour is:
923a60
rm -f test-efi-disk.img
923a60
dd if=/dev/null of=test-efi-disk.img bs=1M seek=512 count=1
923a60
parted --script test-efi-disk.img \
923a60
  "mklabel gpt" \
923a60
  "mkpart ESP fat32 1MiB 511MiB" \
923a60
  "set 1 boot on"
923a60
LOOP=$(losetup --show -f -P test-efi-disk.img)
923a60
udevadm settle
923a60
mkfs.vfat -F32 ${LOOP}p1
923a60
mkdir -p mnt
923a60
mount ${LOOP}p1 mnt
923a60
... <dostuffwith mnt>
923a60
923a60
Without the "udevadm settle" systemd unmounted mnt while the script was
923a60
operating on mnt.
923a60
923a60
Of course the question is, why there was a REMOVE in the first place,
923a60
but this is not part of this patch.
923a60
923a60
Cherry-picked from: 9d06297e262966de71095debd1537fc223f940a3
923a60
Resolves: #1283579
923a60
---
923a60
 src/core/mount.c  | 2 +-
923a60
 src/core/socket.c | 2 +-
923a60
 src/core/swap.c   | 2 +-
923a60
 src/core/unit.c   | 4 ++--
923a60
 src/core/unit.h   | 2 +-
923a60
 5 files changed, 6 insertions(+), 6 deletions(-)
923a60
923a60
diff --git a/src/core/mount.c b/src/core/mount.c
923a60
index 1f1a41ab66..23f63ce32c 100644
923a60
--- a/src/core/mount.c
923a60
+++ b/src/core/mount.c
923a60
@@ -321,7 +321,7 @@ static int mount_add_device_links(Mount *m) {
923a60
         if (mount_is_auto(p) && UNIT(m)->manager->running_as == SYSTEMD_SYSTEM)
923a60
                 device_wants_mount = true;
923a60
 
923a60
-        r = unit_add_node_link(UNIT(m), p->what, device_wants_mount);
923a60
+        r = unit_add_node_link(UNIT(m), p->what, device_wants_mount, m->from_fragment ? UNIT_BINDS_TO : UNIT_REQUIRES);
923a60
         if (r < 0)
923a60
                 return r;
923a60
 
923a60
diff --git a/src/core/socket.c b/src/core/socket.c
923a60
index 7022e77b53..bc677a20f8 100644
923a60
--- a/src/core/socket.c
923a60
+++ b/src/core/socket.c
923a60
@@ -267,7 +267,7 @@ static int socket_add_device_link(Socket *s) {
923a60
                 return 0;
923a60
 
923a60
         t = strjoina("/sys/subsystem/net/devices/", s->bind_to_device);
923a60
-        return unit_add_node_link(UNIT(s), t, false);
923a60
+        return unit_add_node_link(UNIT(s), t, false, UNIT_BINDS_TO);
923a60
 }
923a60
 
923a60
 static int socket_add_default_dependencies(Socket *s) {
923a60
diff --git a/src/core/swap.c b/src/core/swap.c
923a60
index 369abf0f53..34a2c406d8 100644
923a60
--- a/src/core/swap.c
923a60
+++ b/src/core/swap.c
923a60
@@ -201,7 +201,7 @@ static int swap_add_device_links(Swap *s) {
923a60
                 return 0;
923a60
 
923a60
         if (is_device_path(s->what))
923a60
-                return unit_add_node_link(UNIT(s), s->what, UNIT(s)->manager->running_as == SYSTEMD_SYSTEM);
923a60
+                return unit_add_node_link(UNIT(s), s->what, UNIT(s)->manager->running_as == SYSTEMD_SYSTEM, UNIT_BINDS_TO);
923a60
         else
923a60
                 /* File based swap devices need to be ordered after
923a60
                  * systemd-remount-fs.service, since they might need a
923a60
diff --git a/src/core/unit.c b/src/core/unit.c
923a60
index fa17567dd3..ae47a28765 100644
923a60
--- a/src/core/unit.c
923a60
+++ b/src/core/unit.c
923a60
@@ -2823,7 +2823,7 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) {
923a60
         }
923a60
 }
923a60
 
923a60
-int unit_add_node_link(Unit *u, const char *what, bool wants) {
923a60
+int unit_add_node_link(Unit *u, const char *what, bool wants, UnitDependency dep) {
923a60
         Unit *device;
923a60
         _cleanup_free_ char *e = NULL;
923a60
         int r;
923a60
@@ -2850,7 +2850,7 @@ int unit_add_node_link(Unit *u, const char *what, bool wants) {
923a60
         if (r < 0)
923a60
                 return r;
923a60
 
923a60
-        r = unit_add_two_dependencies(u, UNIT_AFTER, u->manager->running_as == SYSTEMD_SYSTEM ? UNIT_BINDS_TO : UNIT_WANTS, device, true);
923a60
+        r = unit_add_two_dependencies(u, UNIT_AFTER, u->manager->running_as == SYSTEMD_SYSTEM ? dep : UNIT_WANTS, device, true);
923a60
         if (r < 0)
923a60
                 return r;
923a60
 
923a60
diff --git a/src/core/unit.h b/src/core/unit.h
923a60
index 7ebc489c80..0eebc0b891 100644
923a60
--- a/src/core/unit.h
923a60
+++ b/src/core/unit.h
923a60
@@ -548,7 +548,7 @@ void unit_serialize_item_format(Unit *u, FILE *f, const char *key, const char *v
923a60
 void unit_serialize_item(Unit *u, FILE *f, const char *key, const char *value);
923a60
 int unit_deserialize(Unit *u, FILE *f, FDSet *fds);
923a60
 
923a60
-int unit_add_node_link(Unit *u, const char *what, bool wants);
923a60
+int unit_add_node_link(Unit *u, const char *what, bool wants, UnitDependency d);
923a60
 
923a60
 int unit_coldplug(Unit *u, Hashmap *deferred_work);
923a60