[systemd-devel] [PATCH 3/6] systemd: try to use fsinfo for sigchld handling

Ian Kent ikent at redhat.com
Mon Jul 27 04:58:14 UTC 2020


From: Ian Kent <raven at themaw.net>

Try and use the new fsinfo() system call when handing SIGCHLD from
systemd mount unit mounting.

Signed-off-by: Ian Kent <raven at themaw.net>
---
 src/core/mount.c |   52 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 51 insertions(+), 1 deletion(-)

diff --git a/src/core/mount.c b/src/core/mount.c
index 9c9abd9b8d..632aa73e1f 100644
--- a/src/core/mount.c
+++ b/src/core/mount.c
@@ -4,6 +4,8 @@
 #include <signal.h>
 #include <stdio.h>
 #include <sys/epoll.h>
+#include <sys/mount.h>
+#include <libmount.h>
 
 #include "sd-messages.h"
 
@@ -52,6 +54,7 @@ static const UnitActiveState state_translation_table[_MOUNT_STATE_MAX] = {
 static int mount_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata);
 static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
 static void mount_update_unit_state(Mount *m, Set *gone, Set *around);
+static int mount_setup_unit(Manager *m, const char *what, const char *where, const char *options, const char *fstype, bool set_flags);
 static int mount_process_proc_self_mountinfo(Manager *m);
 
 static bool MOUNT_STATE_WITH_PROCESS(MountState state) {
@@ -1351,7 +1354,54 @@ static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) {
          * race, let's explicitly scan /proc/self/mountinfo before we start processing /usr/bin/(u)mount
          * dying. It's ugly, but it makes our ordering systematic again, and makes sure we always see
          * /proc/self/mountinfo changes before our mount/umount exits. */
-        (void) mount_process_proc_self_mountinfo(u->manager);
+        if (!mnt_has_fsinfo())
+                (void) mount_process_proc_self_mountinfo(u->manager);
+        else {
+                _cleanup_set_free_free_ Set *around = NULL, *gone = NULL;
+                const char *device, *options, *fstype;
+                struct libmnt_fs *fs;
+                const char *what;
+                Iterator i;
+
+                fs = mnt_new_fs();
+                if (!fs) {
+                        log_error_errno(-ENOMEM, "failed to allocate libmount fs struct");
+                        return;
+                }
+
+                mnt_fs_set_target(fs, m->where);
+
+                mnt_fs_enable_fsinfo(fs, 1);
+                device = mnt_fs_get_source(fs);
+                options = mnt_fs_get_options(fs);
+                fstype = mnt_fs_get_fstype(fs);
+
+                if (device && fstype) {
+                        device_found_node(u->manager, device, DEVICE_FOUND_MOUNT, DEVICE_FOUND_MOUNT);
+                        (void) mount_setup_unit(u->manager, device, m->where, options, fstype, true);
+                }
+
+                mnt_unref_fs(fs);
+
+                manager_dispatch_load_queue(u->manager);
+
+                gone = set_new(NULL);
+                around = set_new(NULL);
+                if (!gone || !around) {
+                        log_error_errno(-ENOMEM, "failed to allocate set");
+                        return;
+                }
+
+                mount_update_unit_state(m, gone, around);
+
+                SET_FOREACH(what, gone, i) {
+                        if (set_contains(around, what))
+                                continue;
+
+                        /* Let the device units know that the device is no longer mounted */
+                        device_found_node(u->manager, what, 0, DEVICE_FOUND_MOUNT);
+                }
+        }
 
         m->control_pid = 0;
 




More information about the systemd-devel mailing list