X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fcore%2Fmount.c;h=102bbef91b83c1331c9d46db71f1136e27ef92e2;hb=2968644080fd103062f070e83edd620e0a58c44d;hp=e46c72a644fcc088a41c88e7a6c3792f6ca30c39;hpb=613b411c947635136637f8cdd66b94512f761eab;p=elogind.git diff --git a/src/core/mount.c b/src/core/mount.c index e46c72a64..102bbef91 100644 --- a/src/core/mount.c +++ b/src/core/mount.c @@ -62,20 +62,6 @@ 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 char* mount_test_option(const char *haystack, const char *needle) { - struct mntent me = { .mnt_opts = (char*) haystack }; - - assert(needle); - - /* Like glibc's hasmntopt(), but works on a string, not a - * struct mntent */ - - if (!haystack) - return NULL; - - return hasmntopt(&me, needle); -} - static bool mount_is_network(MountParameters *p) { assert(p); @@ -137,8 +123,6 @@ static void mount_init(Unit *u) { m->timeout_usec = u->manager->default_timeout_start_usec; m->directory_mode = 0755; - exec_context_init(&m->exec_context); - if (unit_has_name(u, "-.mount")) { /* Don't allow start/stop for root directory */ u->refuse_manual_start = true; @@ -150,9 +134,6 @@ static void mount_init(Unit *u) { m->exec_context.std_error = u->manager->default_std_error; } - kill_context_init(&m->kill_context); - cgroup_context_init(&m->cgroup_context); - /* We need to make sure that /bin/mount is always called in * the same process group as us, so that the autofs kernel * side doesn't send us another mount request while we are @@ -182,7 +163,12 @@ static int mount_arm_timer(Mount *m) { return sd_event_source_set_enabled(m->timer_event_source, SD_EVENT_ONESHOT); } - return sd_event_add_monotonic(UNIT(m)->manager->event, now(CLOCK_MONOTONIC) + m->timeout_usec, 0, mount_dispatch_timer, m, &m->timer_event_source); + return sd_event_add_time( + UNIT(m)->manager->event, + &m->timer_event_source, + CLOCK_MONOTONIC, + now(CLOCK_MONOTONIC) + m->timeout_usec, 0, + mount_dispatch_timer, m); } static void mount_unwatch_control_pid(Mount *m) { @@ -216,8 +202,6 @@ static void mount_done(Unit *u) { mount_parameters_done(&m->parameters_proc_self_mountinfo); mount_parameters_done(&m->parameters_fragment); - cgroup_context_done(&m->cgroup_context); - exec_context_done(&m->exec_context); m->exec_runtime = exec_runtime_unref(m->exec_runtime); exec_command_done_array(m->exec_command, _MOUNT_EXEC_COMMAND_MAX); m->control_command = NULL; @@ -434,57 +418,6 @@ static int mount_add_default_dependencies(Mount *m) { return 0; } -static int mount_fix_timeouts(Mount *m) { - MountParameters *p; - const char *timeout = NULL; - Unit *other; - Iterator i; - usec_t u; - char *t; - int r; - - assert(m); - - p = get_mount_parameters_fragment(m); - if (!p) - return 0; - - /* Allow configuration how long we wait for a device that - * backs a mount point to show up. This is useful to support - * endless device timeouts for devices that show up only after - * user input, like crypto devices. */ - - if ((timeout = mount_test_option(p->options, "comment=systemd.device-timeout"))) - timeout += 31; - else if ((timeout = mount_test_option(p->options, "x-systemd.device-timeout"))) - timeout += 25; - else - return 0; - - t = strndup(timeout, strcspn(timeout, ",;" WHITESPACE)); - if (!t) - return -ENOMEM; - - r = parse_sec(t, &u); - free(t); - - if (r < 0) { - log_warning_unit(UNIT(m)->id, - "Failed to parse timeout for %s, ignoring: %s", - m->where, timeout); - return r; - } - - SET_FOREACH(other, UNIT(m)->dependencies[UNIT_AFTER], i) { - if (other->type != UNIT_DEVICE) - continue; - - other->job_timeout = u; - } - - return 0; -} - static int mount_verify(Mount *m) { _cleanup_free_ char *e = NULL; bool b; @@ -503,29 +436,22 @@ static int mount_verify(Mount *m) { b = unit_has_name(UNIT(m), e); if (!b) { - log_error_unit(UNIT(m)->id, - "%s's Where setting doesn't match unit name. Refusing.", - UNIT(m)->id); + log_error_unit(UNIT(m)->id, "%s's Where= setting doesn't match unit name. Refusing.", UNIT(m)->id); return -EINVAL; } if (mount_point_is_api(m->where) || mount_point_ignore(m->where)) { - log_error_unit(UNIT(m)->id, - "Cannot create mount unit for API file system %s. Refusing.", - m->where); + log_error_unit(UNIT(m)->id, "Cannot create mount unit for API file system %s. Refusing.", m->where); return -EINVAL; } if (UNIT(m)->fragment_path && !m->parameters_fragment.what) { - log_error_unit(UNIT(m)->id, - "%s's What setting is missing. Refusing.", UNIT(m)->id); + log_error_unit(UNIT(m)->id, "%s's What setting is missing. Refusing.", UNIT(m)->id); return -EBADMSG; } if (m->exec_context.pam_name && m->kill_context.kill_mode != KILL_CONTROL_GROUP) { - log_error_unit(UNIT(m)->id, - "%s has PAM enabled. Kill mode must be set to control-group'. Refusing.", - UNIT(m)->id); + log_error_unit(UNIT(m)->id, "%s has PAM enabled. Kill mode must be set to control-group'. Refusing.",UNIT(m)->id); return -EINVAL; } @@ -536,7 +462,9 @@ static int mount_add_extras(Mount *m) { Unit *u = UNIT(m); int r; - if (UNIT(m)->fragment_path) + assert(m); + + if (u->fragment_path) m->from_fragment = true; if (!m->where) { @@ -547,11 +475,7 @@ static int mount_add_extras(Mount *m) { path_kill_slashes(m->where); - r = unit_add_exec_dependencies(u, &m->exec_context); - if (r < 0) - return r; - - if (!UNIT(m)->description) { + if (!u->description) { r = unit_set_description(u, m->where); if (r < 0) return r; @@ -569,20 +493,24 @@ static int mount_add_extras(Mount *m) { if (r < 0) return r; - if (UNIT(m)->default_dependencies) { - r = mount_add_default_dependencies(m); - if (r < 0) - return r; - } + r = unit_patch_contexts(u); + if (r < 0) + return r; - r = unit_add_default_slice(u); + r = unit_add_exec_dependencies(u, &m->exec_context); if (r < 0) return r; - r = mount_fix_timeouts(m); + r = unit_add_default_slice(u, &m->cgroup_context); if (r < 0) return r; + if (u->default_dependencies) { + r = mount_add_default_dependencies(m); + if (r < 0) + return r; + } + return 0; } @@ -606,10 +534,6 @@ static int mount_load(Unit *u) { r = mount_add_extras(m); if (r < 0) return r; - - r = unit_exec_context_defaults(u, &m->exec_context); - if (r < 0) - return r; } return mount_verify(m); @@ -756,8 +680,8 @@ static void mount_dump(Unit *u, FILE *f, const char *prefix) { if (m->control_pid > 0) fprintf(f, - "%sControl PID: %lu\n", - prefix, (unsigned long) m->control_pid); + "%sControl PID: "PID_FMT"\n", + prefix, m->control_pid); exec_context_dump(&m->exec_context, f, prefix); kill_context_dump(&m->kill_context, f, prefix); @@ -792,7 +716,9 @@ static int mount_spawn(Mount *m, ExecCommand *c, pid_t *_pid) { UNIT(m)->manager->confirm_spawn, UNIT(m)->manager->cgroup_supported, UNIT(m)->cgroup_path, + manager_get_runtime_prefix(UNIT(m)->manager), UNIT(m)->id, + 0, NULL, m->exec_runtime, &pid); @@ -823,6 +749,8 @@ static void mount_enter_dead(Mount *m, MountResult f) { exec_runtime_destroy(m->exec_runtime); m->exec_runtime = exec_runtime_unref(m->exec_runtime); + exec_context_destroy_runtime_directory(&m->exec_context, manager_get_runtime_prefix(UNIT(m)->manager)); + mount_set_state(m, m->result != MOUNT_SUCCESS ? MOUNT_FAILED : MOUNT_DEAD); } @@ -859,8 +787,14 @@ static void mount_enter_signal(Mount *m, MountState state, MountResult f) { goto fail; mount_set_state(m, state); - } else if (state == MOUNT_REMOUNTING_SIGTERM || state == MOUNT_REMOUNTING_SIGKILL) + } else if (state == MOUNT_REMOUNTING_SIGTERM) + mount_enter_signal(m, MOUNT_REMOUNTING_SIGKILL, MOUNT_SUCCESS); + else if (state == MOUNT_REMOUNTING_SIGKILL) mount_enter_mounted(m, MOUNT_SUCCESS); + else if (state == MOUNT_MOUNTING_SIGTERM) + mount_enter_signal(m, MOUNT_MOUNTING_SIGKILL, MOUNT_SUCCESS); + else if (state == MOUNT_UNMOUNTING_SIGTERM) + mount_enter_signal(m, MOUNT_UNMOUNTING_SIGKILL, MOUNT_SUCCESS); else mount_enter_dead(m, MOUNT_SUCCESS); @@ -903,6 +837,7 @@ static void mount_enter_unmounting(Mount *m) { if ((r = exec_command_set( m->control_command, "/bin/umount", + "-n", m->where, NULL)) < 0) goto fail; @@ -945,6 +880,7 @@ static void mount_enter_mounting(Mount *m) { 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", @@ -992,6 +928,7 @@ static void mount_enter_remounting(Mount *m) { 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", @@ -1098,7 +1035,7 @@ static int mount_serialize(Unit *u, FILE *f, FDSet *fds) { 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); + unit_serialize_item_format(u, f, "control-pid", PID_FMT, m->control_pid); if (m->control_command_id >= 0) unit_serialize_item(u, f, "control-command", mount_exec_command_to_string(m->control_command_id)); @@ -1383,12 +1320,13 @@ static int mount_add_one( const char *options, const char *fstype, bool set_flags) { - int r; - Unit *u; - bool delete; - char *e, *w = NULL, *o = NULL, *f = NULL; - MountParameters *p; + + _cleanup_free_ char *e = NULL, *w = NULL, *o = NULL, *f = NULL; bool load_extras = false; + MountParameters *p; + bool delete, changed = false; + Unit *u; + int r; assert(m); assert(what); @@ -1414,20 +1352,13 @@ static int mount_add_one( u = manager_get_unit(m, e); if (!u) { - const char* const target = - fstype_is_network(fstype) ? SPECIAL_REMOTE_FS_TARGET : SPECIAL_LOCAL_FS_TARGET; - delete = true; u = unit_new(m, sizeof(Mount)); - if (!u) { - free(e); + if (!u) return -ENOMEM; - } r = unit_add_name(u, e); - free(e); - if (r < 0) goto fail; @@ -1443,20 +1374,27 @@ static int mount_add_one( goto fail; } - r = unit_add_dependency_by_name(u, UNIT_BEFORE, target, NULL, true); - if (r < 0) - goto fail; - if (should_umount(MOUNT(u))) { - r = unit_add_dependency_by_name(u, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true); + if (m->running_as == SYSTEMD_SYSTEM) { + const char* target; + + target = fstype_is_network(fstype) ? SPECIAL_REMOTE_FS_TARGET : SPECIAL_LOCAL_FS_TARGET; + + r = unit_add_dependency_by_name(u, UNIT_BEFORE, target, NULL, true); if (r < 0) goto fail; + + if (should_umount(MOUNT(u))) { + r = unit_add_dependency_by_name(u, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true); + if (r < 0) + goto fail; + } } unit_add_to_load_queue(u); + changed = true; } else { delete = false; - free(e); if (!MOUNT(u)->where) { MOUNT(u)->where = strdup(where); @@ -1473,33 +1411,44 @@ static int mount_add_one( /* Load in the extras later on, after we * finished initialization of the unit */ load_extras = true; + changed = true; } } - if (!(w = strdup(what)) || - !(o = strdup(options)) || - !(f = strdup(fstype))) { + w = strdup(what); + o = strdup(options); + f = strdup(fstype); + if (!w || !o || !f) { r = -ENOMEM; goto fail; } p = &MOUNT(u)->parameters_proc_self_mountinfo; + + changed = changed || + !streq_ptr(p->options, options) || + !streq_ptr(p->what, what) || + !streq_ptr(p->fstype, fstype); + if (set_flags) { MOUNT(u)->is_mounted = true; MOUNT(u)->just_mounted = !MOUNT(u)->from_proc_self_mountinfo; - MOUNT(u)->just_changed = !streq_ptr(p->options, o); + MOUNT(u)->just_changed = changed; } MOUNT(u)->from_proc_self_mountinfo = true; free(p->what); p->what = w; + w = NULL; free(p->options); p->options = o; + o = NULL; free(p->fstype); p->fstype = f; + f = NULL; if (load_extras) { r = mount_add_extras(MOUNT(u)); @@ -1507,15 +1456,12 @@ static int mount_add_one( goto fail; } - unit_add_to_dbus_queue(u); + if (changed) + unit_add_to_dbus_queue(u); return 0; fail: - free(w); - free(o); - free(f); - if (delete && u) unit_free(u); @@ -1589,6 +1535,20 @@ static void mount_shutdown(Manager *m) { } } +static int mount_get_timeout(Unit *u, uint64_t *timeout) { + Mount *m = MOUNT(u); + int r; + + if (!m->timer_event_source) + return 0; + + r = sd_event_source_get_time(m->timer_event_source, timeout); + if (r < 0) + return r; + + return 1; +} + static int mount_enumerate(Manager *m) { int r; assert(m); @@ -1598,7 +1558,7 @@ static int mount_enumerate(Manager *m) { if (!m->proc_self_mountinfo) return -errno; - r = sd_event_add_io(m->event, fileno(m->proc_self_mountinfo), EPOLLPRI, mount_dispatch_io, m, &m->mount_event_source); + r = sd_event_add_io(m->event, &m->mount_event_source, fileno(m->proc_self_mountinfo), EPOLLPRI, mount_dispatch_io, m); if (r < 0) goto fail; @@ -1653,20 +1613,20 @@ static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents, Mount *mount = MOUNT(u); if (!mount->is_mounted) { - /* This has just been unmounted. */ mount->from_proc_self_mountinfo = false; switch (mount->state) { case MOUNT_MOUNTED: + /* This has just been unmounted by + * somebody else, follow the state + * change. */ mount_enter_dead(mount, MOUNT_SUCCESS); break; default: - mount_set_state(mount, mount->state); break; - } } else if (mount->just_mounted || mount->just_changed) { @@ -1677,6 +1637,9 @@ static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents, case MOUNT_DEAD: case MOUNT_FAILED: + /* This has just been mounted by + * somebody else, follow the state + * change. */ mount_enter_mounted(mount, MOUNT_SUCCESS); break; @@ -1799,10 +1762,13 @@ const UnitVTable mount_vtable = { .bus_interface = "org.freedesktop.systemd1.Mount", .bus_vtable = bus_mount_vtable, - .bus_changing_properties = bus_mount_changing_properties, .bus_set_property = bus_mount_set_property, .bus_commit_properties = bus_mount_commit_properties, + .get_timeout = mount_get_timeout, + + .can_transient = true, + .enumerate = mount_enumerate, .shutdown = mount_shutdown,