X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fcore%2Fmount.c;h=13c634807b07672ea0b8eba1aa4a831958348b99;hp=e271d437cb536dacad4bf1431a502ebbd962719a;hb=b02cb41c78c61c27bf1432e19f241a3c3d47a419;hpb=96aad8d15a324d0e956a4e5653a11a67b209b41a diff --git a/src/core/mount.c b/src/core/mount.c index e271d437c..13c634807 100644 --- a/src/core/mount.c +++ b/src/core/mount.c @@ -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;