X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fmount.c;h=d651e8714bb2115abf8b16e15fc75f2fc2f44cb3;hp=ac33787e61e42c8307a3386419dcc7056b566a1d;hb=c68364b790d1a13ef1df0e2fbb99ded6d67e60e3;hpb=11ce3427242b8b4ddf638ed5703d69041d719b4c diff --git a/src/mount.c b/src/mount.c index ac33787e6..d651e8714 100644 --- a/src/mount.c +++ b/src/mount.c @@ -50,7 +50,7 @@ static const UnitActiveState state_translation_table[_MOUNT_STATE_MAX] = { [MOUNT_REMOUNTING_SIGKILL] = UNIT_RELOADING, [MOUNT_UNMOUNTING_SIGTERM] = UNIT_DEACTIVATING, [MOUNT_UNMOUNTING_SIGKILL] = UNIT_DEACTIVATING, - [MOUNT_MAINTENANCE] = UNIT_MAINTENANCE + [MOUNT_FAILED] = UNIT_FAILED }; static void mount_init(Unit *u) { @@ -244,7 +244,8 @@ static int mount_add_target_links(Mount *m) { noauto = !!mount_test_option(p->options, MNTOPT_NOAUTO); user = mount_test_option(p->options, "user") || mount_test_option(p->options, "users"); - handle = !!mount_test_option(p->options, "comment=systemd.mount"); + handle = !!mount_test_option(p->options, "comment=systemd.mount") || + m->meta.manager->mount_auto; automount = !!mount_test_option(p->options, "comment=systemd.automount"); if (mount_test_option(p->options, "_netdev") || @@ -265,7 +266,11 @@ static int mount_add_target_links(Mount *m) { return unit_add_two_dependencies(tu, UNIT_AFTER, UNIT_WANTS, UNIT(am), true); } else { - if (!noauto && handle) + /* Automatically add mount points that aren't natively + * configured to local-fs.target */ + if (!noauto && + handle && + !m->from_fragment) if (user || m->meta.manager->running_as == MANAGER_SYSTEM) if ((r = unit_add_dependency(tu, UNIT_WANTS, UNIT(m), true)) < 0) return r; @@ -274,6 +279,30 @@ static int mount_add_target_links(Mount *m) { } } +static int mount_add_device_links(Mount *m) { + MountParameters *p; + bool nofail, noauto; + + assert(m); + + if (m->from_fragment) + p = &m->parameters_fragment; + else if (m->from_etc_fstab) + p = &m->parameters_etc_fstab; + else + return 0; + + if (!p->what || path_equal(m->where, "/")) + return 0; + + noauto = !!mount_test_option(p->options, MNTOPT_NOAUTO); + nofail = !!mount_test_option(p->options, "nofail"); + + return unit_add_node_link(UNIT(m), p->what, + !noauto && nofail && + UNIT(m)->meta.manager->running_as == MANAGER_SYSTEM); +} + static int mount_add_default_dependencies(Mount *m) { int r; @@ -361,9 +390,8 @@ static int mount_load(Unit *u) { else if (m->from_proc_self_mountinfo && m->parameters_proc_self_mountinfo.what) what = m->parameters_proc_self_mountinfo.what; - if (what) - if ((r = unit_add_node_link(u, what, u->meta.manager->running_as == MANAGER_SYSTEM)) < 0) - return r; + if ((r = mount_add_device_links(m)) < 0) + return r; if ((r = mount_add_mount_links(m)) < 0) return r; @@ -440,7 +468,7 @@ static void mount_set_state(Mount *m, MountState state) { state == MOUNT_REMOUNTING_SIGKILL || state == MOUNT_UNMOUNTING_SIGTERM || state == MOUNT_UNMOUNTING_SIGKILL || - state == MOUNT_MAINTENANCE) + state == MOUNT_FAILED) mount_notify_automount(m, -ENODEV); if (state != old_state) @@ -580,7 +608,7 @@ static void mount_enter_dead(Mount *m, bool success) { if (!success) m->failure = true; - mount_set_state(m, m->failure ? MOUNT_MAINTENANCE : MOUNT_DEAD); + mount_set_state(m, m->failure ? MOUNT_FAILED : MOUNT_DEAD); } static void mount_enter_mounted(Mount *m, bool success) { @@ -594,7 +622,8 @@ static void mount_enter_mounted(Mount *m, bool success) { static void mount_enter_signal(Mount *m, MountState state, bool success) { int r; - bool sent = false; + Set *pid_set = NULL; + bool wait_for_exit = false; assert(m); @@ -606,26 +635,39 @@ static void mount_enter_signal(Mount *m, MountState state, bool success) { state == MOUNT_UNMOUNTING_SIGTERM || state == MOUNT_REMOUNTING_SIGTERM) ? m->exec_context.kill_signal : SIGKILL; - if (m->exec_context.kill_mode == KILL_CONTROL_GROUP) { + if (m->control_pid > 0) { + if (kill(m->exec_context.kill_mode == KILL_PROCESS_GROUP ? + -m->control_pid : + m->control_pid, sig) < 0 && errno != ESRCH) - if ((r = cgroup_bonding_kill_list(m->meta.cgroup_bondings, sig)) < 0) { - if (r != -EAGAIN && r != -ESRCH) - goto fail; - } else - sent = true; + log_warning("Failed to kill control process %li: %m", (long) m->control_pid); + else + wait_for_exit = true; } - if (!sent && m->control_pid > 0) - if (kill(m->exec_context.kill_mode == KILL_PROCESS ? - m->control_pid : - -m->control_pid, sig) < 0 && errno != ESRCH) { + if (m->exec_context.kill_mode == KILL_CONTROL_GROUP) { - r = -errno; + if (!(pid_set = set_new(trivial_hash_func, trivial_compare_func))) { + r = -ENOMEM; goto fail; } + + /* Exclude the control pid from being killed via the cgroup */ + if (m->control_pid > 0) + if ((r = set_put(pid_set, LONG_TO_PTR(m->control_pid))) < 0) + goto fail; + + if ((r = cgroup_bonding_kill_list(m->meta.cgroup_bondings, sig, pid_set)) < 0) { + if (r != -EAGAIN && r != -ESRCH && r != -ENOENT) + log_warning("Failed to kill control group: %s", strerror(-r)); + } else if (r > 0) + wait_for_exit = true; + + set_free(pid_set); + } } - if (sent) { + if (wait_for_exit) { if ((r = unit_watch_timer(UNIT(m), m->timeout_usec, &m->timer_watch)) < 0) goto fail; @@ -644,6 +686,9 @@ fail: mount_enter_mounted(m, false); else mount_enter_dead(m, false); + + if (pid_set) + set_free(pid_set); } static void mount_enter_unmounting(Mount *m, bool success) { @@ -811,7 +856,7 @@ static int mount_start(Unit *u) { m->state == MOUNT_MOUNTING_SIGKILL) return 0; - assert(m->state == MOUNT_DEAD || m->state == MOUNT_MAINTENANCE); + assert(m->state == MOUNT_DEAD || m->state == MOUNT_FAILED); m->failure = false; mount_enter_mounting(m); @@ -1286,6 +1331,7 @@ static int mount_load_etc_fstab(Manager *m) { what, pri, !!mount_test_option(me->mnt_opts, MNTOPT_NOAUTO), + !!mount_test_option(me->mnt_opts, "nofail"), !!mount_test_option(me->mnt_opts, "comment=systemd.swapon"), false); } else @@ -1478,7 +1524,7 @@ void mount_fd_event(Manager *m, int events) { switch (mount->state) { case MOUNT_DEAD: - case MOUNT_MAINTENANCE: + case MOUNT_FAILED: mount_enter_mounted(mount, true); break; @@ -1502,12 +1548,12 @@ void mount_fd_event(Manager *m, int events) { } } -static void mount_reset_maintenance(Unit *u) { +static void mount_reset_failed(Unit *u) { Mount *m = MOUNT(u); assert(m); - if (m->state == MOUNT_MAINTENANCE) + if (m->state == MOUNT_FAILED) mount_set_state(m, MOUNT_DEAD); m->failure = false; @@ -1526,7 +1572,7 @@ static const char* const mount_state_table[_MOUNT_STATE_MAX] = { [MOUNT_REMOUNTING_SIGKILL] = "remounting-sigkill", [MOUNT_UNMOUNTING_SIGTERM] = "unmounting-sigterm", [MOUNT_UNMOUNTING_SIGKILL] = "unmounting-sigkill", - [MOUNT_MAINTENANCE] = "maintenance" + [MOUNT_FAILED] = "failed" }; DEFINE_STRING_TABLE_LOOKUP(mount_state, MountState); @@ -1570,7 +1616,7 @@ const UnitVTable mount_vtable = { .sigchld_event = mount_sigchld_event, .timer_event = mount_timer_event, - .reset_maintenance = mount_reset_maintenance, + .reset_failed = mount_reset_failed, .bus_interface = "org.freedesktop.systemd1.Mount", .bus_message_handler = bus_mount_message_handler,