chiark / gitweb /
conf-parse: don't accept invalid bus names as BusName= arguments in service units
[elogind.git] / src / core / mount.c
index e271d437cb536dacad4bf1431a502ebbd962719a..13c634807b07672ea0b8eba1aa4a831958348b99 100644 (file)
@@ -45,6 +45,8 @@
 #include "exit-status.h"
 #include "def.h"
 
+#define RETRY_UMOUNT_MAX 32
+
 DEFINE_TRIVIAL_CLEANUP_FUNC(struct libmnt_table*, mnt_free_table);
 DEFINE_TRIVIAL_CLEANUP_FUNC(struct libmnt_iter*, mnt_free_iter);
 
@@ -867,20 +869,26 @@ static void mount_enter_unmounting(Mount *m) {
 
         assert(m);
 
+        /* Start counting our attempts */
+        if (!IN_SET(m->state,
+                    MOUNT_UNMOUNTING,
+                    MOUNT_UNMOUNTING_SIGTERM,
+                    MOUNT_UNMOUNTING_SIGKILL))
+                m->n_retry_umount = 0;
+
         m->control_command_id = MOUNT_EXEC_UNMOUNT;
         m->control_command = m->exec_command + MOUNT_EXEC_UNMOUNT;
 
-        if ((r = exec_command_set(
-                             m->control_command,
-                             "/bin/umount",
-                             "-n",
-                             m->where,
-                             NULL)) < 0)
+        r = exec_command_set(m->control_command, "/bin/umount", m->where, NULL);
+        if (r >= 0 && UNIT(m)->manager->running_as == SYSTEMD_SYSTEM)
+                r = exec_command_append(m->control_command, "-n", NULL);
+        if (r < 0)
                 goto fail;
 
         mount_unwatch_control_pid(m);
 
-        if ((r = mount_spawn(m, m->control_command, &m->control_pid)) < 0)
+        r = mount_spawn(m, m->control_command, &m->control_pid);
+        if (r < 0)
                 goto fail;
 
         mount_set_state(m, MOUNT_UNMOUNTING);
@@ -916,17 +924,18 @@ static void mount_enter_mounting(Mount *m) {
         if (r < 0)
                 goto fail;
 
-        if (m->from_fragment)
-                r = exec_command_set(
-                                m->control_command,
-                                "/bin/mount",
-                                m->sloppy_options ? "-ns" : "-n",
-                                m->parameters_fragment.what,
-                                m->where,
-                                "-t", m->parameters_fragment.fstype ? m->parameters_fragment.fstype : "auto",
-                                m->parameters_fragment.options ? "-o" : NULL, m->parameters_fragment.options,
-                                NULL);
-        else
+        if (m->from_fragment) {
+                r = exec_command_set(m->control_command, "/bin/mount",
+                                     m->parameters_fragment.what, m->where, NULL);
+                if (r >= 0 && UNIT(m)->manager->running_as == SYSTEMD_SYSTEM)
+                        r = exec_command_append(m->control_command, "-n", NULL);
+                if (r >= 0 && m->sloppy_options)
+                        r = exec_command_append(m->control_command, "-s", NULL);
+                if (r >= 0 && m->parameters_fragment.fstype)
+                        r = exec_command_append(m->control_command, "-t", m->parameters_fragment.fstype, NULL);
+                if (r >= 0 && m->parameters_fragment.options)
+                        r = exec_command_append(m->control_command, "-o", m->parameters_fragment.options, NULL);
+        } else
                 r = -ENOENT;
 
         if (r < 0)
@@ -965,15 +974,15 @@ static void mount_enter_remounting(Mount *m) {
                 else
                         o = "remount";
 
-                r = exec_command_set(
-                                m->control_command,
-                                "/bin/mount",
-                                m->sloppy_options ? "-ns" : "-n",
-                                m->parameters_fragment.what,
-                                m->where,
-                                "-t", m->parameters_fragment.fstype ? m->parameters_fragment.fstype : "auto",
-                                "-o", o,
-                                NULL);
+                r = exec_command_set(m->control_command, "/bin/mount",
+                                     m->parameters_fragment.what, m->where,
+                                     "-o", o, NULL);
+                if (r >= 0 && UNIT(m)->manager->running_as == SYSTEMD_SYSTEM)
+                        r = exec_command_append(m->control_command, "-n", NULL);
+                if (r >= 0 && m->sloppy_options)
+                        r = exec_command_append(m->control_command, "-s", NULL);
+                if (r >= 0 && m->parameters_fragment.fstype)
+                        r = exec_command_append(m->control_command, "-t", m->parameters_fragment.fstype, NULL);
         } else
                 r = -ENOENT;
 
@@ -1239,9 +1248,31 @@ static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) {
         case MOUNT_UNMOUNTING_SIGKILL:
         case MOUNT_UNMOUNTING_SIGTERM:
 
-                if (f == MOUNT_SUCCESS)
-                        mount_enter_dead(m, f);
-                else if (m->from_proc_self_mountinfo)
+                if (f == MOUNT_SUCCESS) {
+
+                        if (m->from_proc_self_mountinfo) {
+
+                                /* Still a mount point? If so, let's
+                                 * try again. Most likely there were
+                                 * multiple mount points stacked on
+                                 * top of each other. Note that due to
+                                 * the io event priority logic we can
+                                 * be sure the new mountinfo is loaded
+                                 * before we process the SIGCHLD for
+                                 * the mount command. */
+
+                                if (m->n_retry_umount < RETRY_UMOUNT_MAX) {
+                                        log_unit_debug(u->id, "%s: mount still present, trying again.", u->id);
+                                        m->n_retry_umount++;
+                                        mount_enter_unmounting(m);
+                                } else {
+                                        log_unit_debug(u->id, "%s: mount still present after %u attempts to unmount, giving up.", u->id, m->n_retry_umount);
+                                        mount_enter_mounted(m, f);
+                                }
+                        } else
+                                mount_enter_dead(m, f);
+
+                } else if (m->from_proc_self_mountinfo)
                         mount_enter_mounted(m, f);
                 else
                         mount_enter_dead(m, f);
@@ -1415,7 +1446,6 @@ static int mount_add_one(
                         goto fail;
                 }
 
-
                 if (m->running_as == SYSTEMD_SYSTEM) {
                         const char* target;
 
@@ -1670,11 +1700,11 @@ static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents,
                  * internal behaviour of libmount here. */
 
                 for (;;) {
-                        uint8_t buffer[INOTIFY_EVENT_MAX] _alignas_(struct inotify_event);
+                        union inotify_event_buffer buffer;
                         struct inotify_event *e;
                         ssize_t l;
 
-                        l = read(fd, buffer, sizeof(buffer));
+                        l = read(fd, &buffer, sizeof(buffer));
                         if (l < 0) {
                                 if (errno == EAGAIN || errno == EINTR)
                                         break;