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