X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fmount.c;h=ed0f819c7ba71090449541b5f8cf904ce6eb6efe;hp=5c45686c2a0806d6f80e8bf7506cb7a8112b2e0b;hb=133176702a03e5f6264f35c403dd7720d9e05c3f;hpb=1124fe6f01b1d59d016c238026f20380f38d98dc diff --git a/src/mount.c b/src/mount.c index 5c45686c2..ed0f819c7 100644 --- a/src/mount.c +++ b/src/mount.c @@ -160,7 +160,7 @@ static int mount_add_mount_links(Mount *m) { * above us in the hierarchy */ LIST_FOREACH(units_by_type, other, UNIT(m)->manager->units_by_type[UNIT_MOUNT]) { - Mount *n = (Mount*) other; + Mount *n = MOUNT(other); MountParameters *pn; if (n == m) @@ -189,7 +189,7 @@ static int mount_add_mount_links(Mount *m) { if ((r = unit_add_dependency(UNIT(n), UNIT_REQUIRES, UNIT(m), true)) < 0) return r; - } else if (pm && path_startswith(pm->what, n->where)) { + } else if (pm && pm->what && path_startswith(pm->what, n->where)) { if ((r = unit_add_dependency(UNIT(m), UNIT_AFTER, UNIT(n), true)) < 0) return r; @@ -197,7 +197,7 @@ static int mount_add_mount_links(Mount *m) { if ((r = unit_add_dependency(UNIT(m), UNIT_REQUIRES, UNIT(n), true)) < 0) return r; - } else if (pn && path_startswith(pn->what, m->where)) { + } else if (pn && pn->what && path_startswith(pn->what, m->where)) { if ((r = unit_add_dependency(UNIT(n), UNIT_AFTER, UNIT(m), true)) < 0) return r; @@ -217,7 +217,7 @@ static int mount_add_swap_links(Mount *m) { assert(m); LIST_FOREACH(units_by_type, other, UNIT(m)->manager->units_by_type[UNIT_SWAP]) - if ((r = swap_add_one_mount_link((Swap*) other, m)) < 0) + if ((r = swap_add_one_mount_link(SWAP(other), m)) < 0) return r; return 0; @@ -230,7 +230,7 @@ static int mount_add_path_links(Mount *m) { assert(m); LIST_FOREACH(units_by_type, other, UNIT(m)->manager->units_by_type[UNIT_PATH]) - if ((r = path_add_one_mount_link((Path*) other, m)) < 0) + if ((r = path_add_one_mount_link(PATH(other), m)) < 0) return r; return 0; @@ -243,7 +243,7 @@ static int mount_add_automount_links(Mount *m) { assert(m); LIST_FOREACH(units_by_type, other, UNIT(m)->manager->units_by_type[UNIT_AUTOMOUNT]) - if ((r = automount_add_one_mount_link((Automount*) other, m)) < 0) + if ((r = automount_add_one_mount_link(AUTOMOUNT(other), m)) < 0) return r; return 0; @@ -256,7 +256,7 @@ static int mount_add_socket_links(Mount *m) { assert(m); LIST_FOREACH(units_by_type, other, UNIT(m)->manager->units_by_type[UNIT_SOCKET]) - if ((r = socket_add_one_mount_link((Socket*) other, m)) < 0) + if ((r = socket_add_one_mount_link(SOCKET(other), m)) < 0) return r; return 0; @@ -271,7 +271,7 @@ static char* mount_test_option(const char *haystack, const char *needle) { * struct mntent */ if (!haystack) - return false; + return NULL; zero(me); me.mnt_opts = (char*) haystack; @@ -320,7 +320,7 @@ static bool needs_quota(MountParameters *p) { } static int mount_add_fstab_links(Mount *m) { - const char *target, *after = NULL, *after2 = NULL; + const char *target, *after, *tu_wants = NULL; MountParameters *p; Unit *tu; int r; @@ -350,23 +350,27 @@ static int mount_add_fstab_links(Mount *m) { if (mount_is_network(p)) { target = SPECIAL_REMOTE_FS_TARGET; - after = SPECIAL_REMOTE_FS_PRE_TARGET; - after2 = SPECIAL_NETWORK_TARGET; + after = tu_wants = SPECIAL_REMOTE_FS_PRE_TARGET; } else { target = SPECIAL_LOCAL_FS_TARGET; after = SPECIAL_LOCAL_FS_PRE_TARGET; } - if ((r = manager_load_unit(UNIT(m)->manager, target, NULL, NULL, &tu)) < 0) + r = manager_load_unit(UNIT(m)->manager, target, NULL, NULL, &tu); + if (r < 0) return r; - if (after) - if ((r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, after, NULL, true)) < 0) + if (tu_wants) { + r = unit_add_dependency_by_name(tu, UNIT_WANTS, tu_wants, NULL, true); + if (r < 0) return r; + } - if (after2) - if ((r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, after2, NULL, true)) < 0) + if (after) { + r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, after, NULL, true); + if (r < 0) return r; + } if (automount) { Unit *am; @@ -583,6 +587,11 @@ static int mount_load(Unit *u) { if (UNIT(m)->fragment_path) m->from_fragment = true; + else if (m->from_etc_fstab) + /* We always add several default dependencies to fstab mounts, + * but we do not want the implicit complementing of Wants= with After= + * in the target unit that this mount unit will be hooked into. */ + UNIT(m)->default_dependencies = false; if (!m->where) if (!(m->where = unit_name_to_path(u->id))) @@ -615,7 +624,7 @@ static int mount_load(Unit *u) { if ((r = mount_add_fstab_links(m)) < 0) return r; - if (UNIT(m)->default_dependencies) + if (UNIT(m)->default_dependencies || m->from_etc_fstab) if ((r = mount_add_default_dependencies(m)) < 0) return r; @@ -688,8 +697,8 @@ static void mount_set_state(Mount *m, MountState state) { mount_state_to_string(old_state), mount_state_to_string(state)); - unit_notify(UNIT(m), state_translation_table[old_state], state_translation_table[state], !m->reload_failure); - m->reload_failure = false; + unit_notify(UNIT(m), state_translation_table[old_state], state_translation_table[state], m->reload_result == MOUNT_SUCCESS); + m->reload_result = MOUNT_SUCCESS; } static int mount_coldplug(Unit *u) { @@ -745,6 +754,7 @@ static void mount_dump(Unit *u, FILE *f, const char *prefix) { fprintf(f, "%sMount State: %s\n" + "%sResult: %s\n" "%sWhere: %s\n" "%sWhat: %s\n" "%sFile System Type: %s\n" @@ -754,6 +764,7 @@ static void mount_dump(Unit *u, FILE *f, const char *prefix) { "%sFrom fragment: %s\n" "%sDirectoryMode: %04o\n", prefix, mount_state_to_string(m->state), + prefix, mount_result_to_string(m->result), prefix, m->where, prefix, strna(p->what), prefix, strna(p->fstype), @@ -810,33 +821,33 @@ fail: return r; } -static void mount_enter_dead(Mount *m, bool success) { +static void mount_enter_dead(Mount *m, MountResult f) { assert(m); - if (!success) - m->failure = true; + if (f != MOUNT_SUCCESS) + m->result = f; - mount_set_state(m, m->failure ? MOUNT_FAILED : MOUNT_DEAD); + mount_set_state(m, m->result != MOUNT_SUCCESS ? MOUNT_FAILED : MOUNT_DEAD); } -static void mount_enter_mounted(Mount *m, bool success) { +static void mount_enter_mounted(Mount *m, MountResult f) { assert(m); - if (!success) - m->failure = true; + if (f != MOUNT_SUCCESS) + m->result = f; mount_set_state(m, MOUNT_MOUNTED); } -static void mount_enter_signal(Mount *m, MountState state, bool success) { +static void mount_enter_signal(Mount *m, MountState state, MountResult f) { int r; Set *pid_set = NULL; bool wait_for_exit = false; assert(m); - if (!success) - m->failure = true; + if (f != MOUNT_SUCCESS) + m->result = f; if (m->exec_context.kill_mode != KILL_NONE) { int sig = (state == MOUNT_MOUNTING_SIGTERM || @@ -880,9 +891,9 @@ static void mount_enter_signal(Mount *m, MountState state, bool success) { mount_set_state(m, state); } else if (state == MOUNT_REMOUNTING_SIGTERM || state == MOUNT_REMOUNTING_SIGKILL) - mount_enter_mounted(m, true); + mount_enter_mounted(m, MOUNT_SUCCESS); else - mount_enter_dead(m, true); + mount_enter_dead(m, MOUNT_SUCCESS); return; @@ -890,22 +901,19 @@ fail: log_warning("%s failed to kill processes: %s", UNIT(m)->id, strerror(-r)); if (state == MOUNT_REMOUNTING_SIGTERM || state == MOUNT_REMOUNTING_SIGKILL) - mount_enter_mounted(m, false); + mount_enter_mounted(m, MOUNT_FAILURE_RESOURCES); else - mount_enter_dead(m, false); + mount_enter_dead(m, MOUNT_FAILURE_RESOURCES); if (pid_set) set_free(pid_set); } -static void mount_enter_unmounting(Mount *m, bool success) { +static void mount_enter_unmounting(Mount *m) { int r; assert(m); - if (!success) - m->failure = true; - m->control_command_id = MOUNT_EXEC_UNMOUNT; m->control_command = m->exec_command + MOUNT_EXEC_UNMOUNT; @@ -927,7 +935,7 @@ static void mount_enter_unmounting(Mount *m, bool success) { fail: log_warning("%s failed to run 'umount' task: %s", UNIT(m)->id, strerror(-r)); - mount_enter_mounted(m, false); + mount_enter_mounted(m, MOUNT_FAILURE_RESOURCES); } static void mount_enter_mounting(Mount *m) { @@ -978,7 +986,7 @@ static void mount_enter_mounting(Mount *m) { fail: log_warning("%s failed to run 'mount' task: %s", UNIT(m)->id, strerror(-r)); - mount_enter_dead(m, false); + mount_enter_dead(m, MOUNT_FAILURE_RESOURCES); } static void mount_enter_mounting_done(Mount *m) { @@ -987,14 +995,11 @@ static void mount_enter_mounting_done(Mount *m) { mount_set_state(m, MOUNT_MOUNTING_DONE); } -static void mount_enter_remounting(Mount *m, bool success) { +static void mount_enter_remounting(Mount *m) { int r; assert(m); - if (!success) - m->failure = true; - m->control_command_id = MOUNT_EXEC_REMOUNT; m->control_command = m->exec_command + MOUNT_EXEC_REMOUNT; @@ -1046,8 +1051,8 @@ static void mount_enter_remounting(Mount *m, bool success) { fail: log_warning("%s failed to run 'remount' task: %s", UNIT(m)->id, strerror(-r)); - m->reload_failure = true; - mount_enter_mounted(m, true); + m->reload_result = MOUNT_FAILURE_RESOURCES; + mount_enter_mounted(m, MOUNT_SUCCESS); } static int mount_start(Unit *u) { @@ -1070,7 +1075,9 @@ static int mount_start(Unit *u) { assert(m->state == MOUNT_DEAD || m->state == MOUNT_FAILED); - m->failure = false; + m->result = MOUNT_SUCCESS; + m->reload_result = MOUNT_SUCCESS; + mount_enter_mounting(m); return 0; } @@ -1095,7 +1102,7 @@ static int mount_stop(Unit *u) { m->state == MOUNT_REMOUNTING_SIGTERM || m->state == MOUNT_REMOUNTING_SIGKILL); - mount_enter_unmounting(m, true); + mount_enter_unmounting(m); return 0; } @@ -1109,7 +1116,7 @@ static int mount_reload(Unit *u) { assert(m->state == MOUNT_MOUNTED); - mount_enter_remounting(m, true); + mount_enter_remounting(m); return 0; } @@ -1121,7 +1128,8 @@ static int mount_serialize(Unit *u, FILE *f, FDSet *fds) { assert(fds); unit_serialize_item(u, f, "state", mount_state_to_string(m->state)); - unit_serialize_item(u, f, "failure", yes_no(m->failure)); + unit_serialize_item(u, f, "result", mount_result_to_string(m->result)); + unit_serialize_item(u, f, "reload-result", mount_result_to_string(m->reload_result)); if (m->control_pid > 0) unit_serialize_item_format(u, f, "control-pid", "%lu", (unsigned long) m->control_pid); @@ -1147,13 +1155,23 @@ static int mount_deserialize_item(Unit *u, const char *key, const char *value, F log_debug("Failed to parse state value %s", value); else m->deserialized_state = state; - } else if (streq(key, "failure")) { - int b; + } else if (streq(key, "result")) { + MountResult f; - if ((b = parse_boolean(value)) < 0) - log_debug("Failed to parse failure value %s", value); - else - m->failure = b || m->failure; + f = mount_result_from_string(value); + if (f < 0) + log_debug("Failed to parse result value %s", value); + else if (f != MOUNT_SUCCESS) + m->result = f; + + } else if (streq(key, "reload-result")) { + MountResult f; + + f = mount_result_from_string(value); + if (f < 0) + log_debug("Failed to parse reload result value %s", value); + else if (f != MOUNT_SUCCESS) + m->reload_result = f; } else if (streq(key, "control-pid")) { pid_t pid; @@ -1200,7 +1218,7 @@ static bool mount_check_gc(Unit *u) { static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) { Mount *m = MOUNT(u); - bool success; + MountResult f; assert(m); assert(pid >= 0); @@ -1210,16 +1228,28 @@ static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) { m->control_pid = 0; - success = is_clean_exit(code, status); - m->failure = m->failure || !success; + if (is_clean_exit(code, status)) + f = MOUNT_SUCCESS; + else if (code == CLD_EXITED) + f = MOUNT_FAILURE_EXIT_CODE; + else if (code == CLD_KILLED) + f = MOUNT_FAILURE_SIGNAL; + else if (code == CLD_DUMPED) + f = MOUNT_FAILURE_CORE_DUMP; + else + assert_not_reached("Unknown code"); + + if (f != MOUNT_SUCCESS) + m->result = f; if (m->control_command) { exec_status_exit(&m->control_command->exec_status, &m->exec_context, pid, code, status); + m->control_command = NULL; m->control_command_id = _MOUNT_EXEC_COMMAND_INVALID; } - log_full(success ? LOG_DEBUG : LOG_NOTICE, + log_full(f == MOUNT_SUCCESS ? LOG_DEBUG : LOG_NOTICE, "%s mount process exited, code=%s status=%i", u->id, sigchld_code_to_string(code), status); /* Note that mount(8) returning and the kernel sending us a @@ -1236,23 +1266,23 @@ static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) { case MOUNT_MOUNTING_SIGKILL: case MOUNT_MOUNTING_SIGTERM: - if (success) - mount_enter_mounted(m, true); + if (f == MOUNT_SUCCESS) + mount_enter_mounted(m, f); else if (m->from_proc_self_mountinfo) - mount_enter_mounted(m, false); + mount_enter_mounted(m, f); else - mount_enter_dead(m, false); + mount_enter_dead(m, f); break; case MOUNT_REMOUNTING: case MOUNT_REMOUNTING_SIGKILL: case MOUNT_REMOUNTING_SIGTERM: - m->reload_failure = !success; + m->reload_result = f; if (m->from_proc_self_mountinfo) - mount_enter_mounted(m, true); + mount_enter_mounted(m, MOUNT_SUCCESS); else - mount_enter_dead(m, true); + mount_enter_dead(m, MOUNT_SUCCESS); break; @@ -1260,12 +1290,12 @@ static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) { case MOUNT_UNMOUNTING_SIGKILL: case MOUNT_UNMOUNTING_SIGTERM: - if (success) - mount_enter_dead(m, true); + if (f == MOUNT_SUCCESS) + mount_enter_dead(m, f); else if (m->from_proc_self_mountinfo) - mount_enter_mounted(m, false); + mount_enter_mounted(m, f); else - mount_enter_dead(m, false); + mount_enter_dead(m, f); break; default: @@ -1288,59 +1318,59 @@ static void mount_timer_event(Unit *u, uint64_t elapsed, Watch *w) { case MOUNT_MOUNTING: case MOUNT_MOUNTING_DONE: log_warning("%s mounting timed out. Stopping.", u->id); - mount_enter_signal(m, MOUNT_MOUNTING_SIGTERM, false); + mount_enter_signal(m, MOUNT_MOUNTING_SIGTERM, MOUNT_FAILURE_TIMEOUT); break; case MOUNT_REMOUNTING: log_warning("%s remounting timed out. Stopping.", u->id); - m->reload_failure = true; - mount_enter_mounted(m, true); + m->reload_result = MOUNT_FAILURE_TIMEOUT; + mount_enter_mounted(m, MOUNT_SUCCESS); break; case MOUNT_UNMOUNTING: log_warning("%s unmounting timed out. Stopping.", u->id); - mount_enter_signal(m, MOUNT_UNMOUNTING_SIGTERM, false); + mount_enter_signal(m, MOUNT_UNMOUNTING_SIGTERM, MOUNT_FAILURE_TIMEOUT); break; case MOUNT_MOUNTING_SIGTERM: if (m->exec_context.send_sigkill) { log_warning("%s mounting timed out. Killing.", u->id); - mount_enter_signal(m, MOUNT_MOUNTING_SIGKILL, false); + mount_enter_signal(m, MOUNT_MOUNTING_SIGKILL, MOUNT_FAILURE_TIMEOUT); } else { log_warning("%s mounting timed out. Skipping SIGKILL. Ignoring.", u->id); if (m->from_proc_self_mountinfo) - mount_enter_mounted(m, false); + mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT); else - mount_enter_dead(m, false); + mount_enter_dead(m, MOUNT_FAILURE_TIMEOUT); } break; case MOUNT_REMOUNTING_SIGTERM: if (m->exec_context.send_sigkill) { log_warning("%s remounting timed out. Killing.", u->id); - mount_enter_signal(m, MOUNT_REMOUNTING_SIGKILL, false); + mount_enter_signal(m, MOUNT_REMOUNTING_SIGKILL, MOUNT_FAILURE_TIMEOUT); } else { log_warning("%s remounting timed out. Skipping SIGKILL. Ignoring.", u->id); if (m->from_proc_self_mountinfo) - mount_enter_mounted(m, false); + mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT); else - mount_enter_dead(m, false); + mount_enter_dead(m, MOUNT_FAILURE_TIMEOUT); } break; case MOUNT_UNMOUNTING_SIGTERM: if (m->exec_context.send_sigkill) { log_warning("%s unmounting timed out. Killing.", u->id); - mount_enter_signal(m, MOUNT_UNMOUNTING_SIGKILL, false); + mount_enter_signal(m, MOUNT_UNMOUNTING_SIGKILL, MOUNT_FAILURE_TIMEOUT); } else { log_warning("%s unmounting timed out. Skipping SIGKILL. Ignoring.", u->id); if (m->from_proc_self_mountinfo) - mount_enter_mounted(m, false); + mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT); else - mount_enter_dead(m, false); + mount_enter_dead(m, MOUNT_FAILURE_TIMEOUT); } break; @@ -1350,9 +1380,9 @@ static void mount_timer_event(Unit *u, uint64_t elapsed, Watch *w) { log_warning("%s mount process still around after SIGKILL. Ignoring.", u->id); if (m->from_proc_self_mountinfo) - mount_enter_mounted(m, false); + mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT); else - mount_enter_dead(m, false); + mount_enter_dead(m, MOUNT_FAILURE_TIMEOUT); break; default: @@ -1548,7 +1578,7 @@ static int mount_load_etc_fstab(Manager *m) { free(what); free(where); - if (r < 0) + if (k < 0) r = k; } @@ -1679,7 +1709,7 @@ fail: } void mount_fd_event(Manager *m, int events) { - Unit *meta; + Unit *u; int r; assert(m); @@ -1693,8 +1723,8 @@ void mount_fd_event(Manager *m, int events) { log_error("Failed to reread /proc/self/mountinfo: %s", strerror(-r)); /* Reset flags, just in case, for later calls */ - LIST_FOREACH(units_by_type, meta, m->units_by_type[UNIT_MOUNT]) { - Mount *mount = (Mount*) meta; + LIST_FOREACH(units_by_type, u, m->units_by_type[UNIT_MOUNT]) { + Mount *mount = MOUNT(u); mount->is_mounted = mount->just_mounted = mount->just_changed = false; } @@ -1704,8 +1734,8 @@ void mount_fd_event(Manager *m, int events) { manager_dispatch_load_queue(m); - LIST_FOREACH(units_by_type, meta, m->units_by_type[UNIT_MOUNT]) { - Mount *mount = (Mount*) meta; + LIST_FOREACH(units_by_type, u, m->units_by_type[UNIT_MOUNT]) { + Mount *mount = MOUNT(u); if (!mount->is_mounted) { /* This has just been unmounted. */ @@ -1715,7 +1745,7 @@ void mount_fd_event(Manager *m, int events) { switch (mount->state) { case MOUNT_MOUNTED: - mount_enter_dead(mount, true); + mount_enter_dead(mount, MOUNT_SUCCESS); break; default: @@ -1732,7 +1762,7 @@ void mount_fd_event(Manager *m, int events) { case MOUNT_DEAD: case MOUNT_FAILED: - mount_enter_mounted(mount, true); + mount_enter_mounted(mount, MOUNT_SUCCESS); break; case MOUNT_MOUNTING: @@ -1763,7 +1793,8 @@ static void mount_reset_failed(Unit *u) { if (m->state == MOUNT_FAILED) mount_set_state(m, MOUNT_DEAD); - m->failure = false; + m->result = MOUNT_SUCCESS; + m->reload_result = MOUNT_SUCCESS; } static int mount_kill(Unit *u, KillWho who, KillMode mode, int signo, DBusError *error) { @@ -1839,6 +1870,17 @@ static const char* const mount_exec_command_table[_MOUNT_EXEC_COMMAND_MAX] = { DEFINE_STRING_TABLE_LOOKUP(mount_exec_command, MountExecCommand); +static const char* const mount_result_table[_MOUNT_RESULT_MAX] = { + [MOUNT_SUCCESS] = "success", + [MOUNT_FAILURE_RESOURCES] = "resources", + [MOUNT_FAILURE_TIMEOUT] = "timeout", + [MOUNT_FAILURE_EXIT_CODE] = "exit-code", + [MOUNT_FAILURE_SIGNAL] = "signal", + [MOUNT_FAILURE_CORE_DUMP] = "core-dump" +}; + +DEFINE_STRING_TABLE_LOOKUP(mount_result, MountResult); + const UnitVTable mount_vtable = { .suffix = ".mount", .object_size = sizeof(Mount),