diff options
Diffstat (limited to 'src/core/mount.c')
-rw-r--r-- | src/core/mount.c | 407 |
1 files changed, 213 insertions, 194 deletions
diff --git a/src/core/mount.c b/src/core/mount.c index 21437dad08..ead9bc1f44 100644 --- a/src/core/mount.c +++ b/src/core/mount.c @@ -11,6 +11,7 @@ #include "alloc-util.h" #include "dbus-mount.h" +#include "dbus-unit.h" #include "device.h" #include "escape.h" #include "exit-status.h" @@ -20,11 +21,12 @@ #include "manager.h" #include "mkdir.h" #include "mount-setup.h" -#include "mount-util.h" #include "mount.h" +#include "mountpoint-util.h" #include "parse-util.h" #include "path-util.h" #include "process-util.h" +#include "serialize.h" #include "special.h" #include "string-table.h" #include "string-util.h" @@ -66,22 +68,18 @@ static bool MOUNT_STATE_WITH_PROCESS(MountState state) { MOUNT_UNMOUNTING_SIGKILL); } -static bool mount_needs_network(const char *options, const char *fstype) { - if (fstab_test_option(options, "_netdev\0")) +static bool mount_is_network(const MountParameters *p) { + assert(p); + + if (fstab_test_option(p->options, "_netdev\0")) return true; - if (fstype && fstype_is_network(fstype)) + if (p->fstype && fstype_is_network(p->fstype)) return true; return false; } -static bool mount_is_network(const MountParameters *p) { - assert(p); - - return mount_needs_network(p->options, p->fstype); -} - static bool mount_is_loop(const MountParameters *p) { assert(p); @@ -127,11 +125,11 @@ static bool mount_is_bound_to_device(const Mount *m) { return fstab_test_option(p->options, "x-systemd.device-bound\0"); } -static bool needs_quota(const MountParameters *p) { +static bool mount_needs_quota(const MountParameters *p) { assert(p); - /* Quotas are not enabled on network filesystems, - * but we want them, for example, on storage connected via iscsi */ + /* Quotas are not enabled on network filesystems, but we want them, for example, on storage connected via + * iscsi. We hence don't use mount_is_network() here, as that would also return true for _netdev devices. */ if (p->fstype && fstype_is_network(p->fstype)) return false; @@ -209,11 +207,9 @@ static void mount_unwatch_control_pid(Mount *m) { static void mount_parameters_done(MountParameters *p) { assert(p); - free(p->what); - free(p->options); - free(p->fstype); - - p->what = p->options = p->fstype = NULL; + p->what = mfree(p->what); + p->options = mfree(p->options); + p->fstype = mfree(p->fstype); } static void mount_done(Unit *u) { @@ -316,7 +312,7 @@ static int mount_add_mount_dependencies(Mount *m) { } static int mount_add_device_dependencies(Mount *m) { - bool device_wants_mount = false; + bool device_wants_mount; UnitDependencyMask mask; MountParameters *p; UnitDependency dep; @@ -346,8 +342,8 @@ static int mount_add_device_dependencies(Mount *m) { if (path_equal(m->where, "/")) return 0; - if (mount_is_auto(p) && !mount_is_automount(p) && MANAGER_IS_SYSTEM(UNIT(m)->manager)) - device_wants_mount = true; + device_wants_mount = + mount_is_auto(p) && !mount_is_automount(p) && MANAGER_IS_SYSTEM(UNIT(m)->manager); /* Mount units from /proc/self/mountinfo are not bound to devices * by default since they're subject to races when devices are @@ -379,16 +375,16 @@ static int mount_add_quota_dependencies(Mount *m) { if (!p) return 0; - if (!needs_quota(p)) + if (!mount_needs_quota(p)) return 0; mask = m->from_fragment ? UNIT_DEPENDENCY_FILE : UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT; - r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_WANTS, SPECIAL_QUOTACHECK_SERVICE, NULL, true, mask); + r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_WANTS, SPECIAL_QUOTACHECK_SERVICE, true, mask); if (r < 0) return r; - r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_WANTS, SPECIAL_QUOTAON_SERVICE, NULL, true, mask); + r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_WANTS, SPECIAL_QUOTAON_SERVICE, true, mask); if (r < 0) return r; @@ -427,10 +423,10 @@ static bool mount_is_extrinsic(Mount *m) { } static int mount_add_default_dependencies(Mount *m) { + const char *after, *before; UnitDependencyMask mask; - int r; MountParameters *p; - const char *after; + int r; assert(m); @@ -456,7 +452,7 @@ static int mount_add_default_dependencies(Mount *m) { * network.target, so that they are shut down only * after this mount unit is stopped. */ - r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, SPECIAL_NETWORK_TARGET, NULL, true, mask); + r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, SPECIAL_NETWORK_TARGET, true, mask); if (r < 0) return r; @@ -467,25 +463,32 @@ static int mount_add_default_dependencies(Mount *m) { * whose purpose it is to delay this until the network * is "up". */ - r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_WANTS, UNIT_AFTER, SPECIAL_NETWORK_ONLINE_TARGET, NULL, true, mask); + r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_WANTS, UNIT_AFTER, SPECIAL_NETWORK_ONLINE_TARGET, true, mask); if (r < 0) return r; after = SPECIAL_REMOTE_FS_PRE_TARGET; - } else + before = SPECIAL_REMOTE_FS_TARGET; + } else { after = SPECIAL_LOCAL_FS_PRE_TARGET; + before = SPECIAL_LOCAL_FS_TARGET; + } + + r = unit_add_dependency_by_name(UNIT(m), UNIT_BEFORE, before, true, mask); + if (r < 0) + return r; - r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, after, NULL, true, mask); + r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, after, true, mask); if (r < 0) return r; - r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true, mask); + r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, true, mask); if (r < 0) return r; /* If this is a tmpfs mount then we have to unmount it before we try to deactivate swaps */ if (streq_ptr(p->fstype, "tmpfs")) { - r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, SPECIAL_SWAP_TARGET, NULL, true, mask); + r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, SPECIAL_SWAP_TARGET, true, mask); if (r < 0) return r; } @@ -540,6 +543,10 @@ static int mount_add_extras(Mount *m) { assert(m); + /* Note: this call might be called after we already have been loaded once (and even when it has already been + * activated), in case data from /proc/self/mountinfo has changed. This means all code here needs to be ready + * to run with an already set up unit. */ + if (u->fragment_path) m->from_fragment = true; @@ -609,28 +616,33 @@ static int mount_load_root_mount(Unit *u) { static int mount_load(Unit *u) { Mount *m = MOUNT(u); - int r; + int r, q, w; assert(u); assert(u->load_state == UNIT_STUB); r = mount_load_root_mount(u); - if (r < 0) - return r; if (m->from_proc_self_mountinfo || u->perpetual) - r = unit_load_fragment_and_dropin_optional(u); + q = unit_load_fragment_and_dropin_optional(u); else - r = unit_load_fragment_and_dropin(u); + q = unit_load_fragment_and_dropin(u); + + /* Add in some extras. Note we do this in all cases (even if we failed to load the unit) when announced by the + * kernel, because we need some things to be set up no matter what when the kernel establishes a mount and thus + * we need to update the state in our unit to track it. After all, consider that we don't allow changing the + * 'slice' field for a unit once it is active. */ + if (u->load_state == UNIT_LOADED || m->from_proc_self_mountinfo || u->perpetual) + w = mount_add_extras(m); + else + w = 0; + if (r < 0) return r; - - /* This is a new unit? Then let's add in some extras */ - if (u->load_state == UNIT_LOADED) { - r = mount_add_extras(m); - if (r < 0) - return r; - } + if (q < 0) + return q; + if (w < 0) + return w; return mount_verify(m); } @@ -639,6 +651,9 @@ static void mount_set_state(Mount *m, MountState state) { MountState old_state; assert(m); + if (m->state != state) + bus_unit_send_pending_change_signal(UNIT(m), false); + old_state = m->state; m->state = state; @@ -746,11 +761,12 @@ static void mount_dump(Unit *u, FILE *f, const char *prefix) { static int mount_spawn(Mount *m, ExecCommand *c, pid_t *_pid) { - ExecParameters exec_params = { - .flags = EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN, - .stdin_fd = -1, - .stdout_fd = -1, - .stderr_fd = -1, + _cleanup_(exec_params_clear) ExecParameters exec_params = { + .flags = EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN, + .stdin_fd = -1, + .stdout_fd = -1, + .stderr_fd = -1, + .exec_fd = -1, }; pid_t pid; int r; @@ -767,7 +783,9 @@ static int mount_spawn(Mount *m, ExecCommand *c, pid_t *_pid) { if (r < 0) return r; - unit_set_exec_params(UNIT(m), &exec_params); + r = unit_set_exec_params(UNIT(m), &exec_params); + if (r < 0) + return r; r = exec_spawn(UNIT(m), c, @@ -795,9 +813,7 @@ static void mount_enter_dead(Mount *m, MountResult f) { if (m->result == MOUNT_SUCCESS) m->result = f; - if (m->result != MOUNT_SUCCESS) - log_unit_warning(UNIT(m), "Failed with result '%s'.", mount_result_to_string(m->result)); - + unit_log_result(UNIT(m), m->result == MOUNT_SUCCESS, mount_result_to_string(m->result)); mount_set_state(m, m->result != MOUNT_SUCCESS ? MOUNT_FAILED : MOUNT_DEAD); m->exec_runtime = exec_runtime_unref(m->exec_runtime, true); @@ -938,7 +954,6 @@ static void mount_enter_mounting(Mount *m) { (void) mkdir_p_label(m->where, m->directory_mode); unit_warn_if_dir_nonempty(UNIT(m), m->where); - unit_warn_leftover_processes(UNIT(m)); m->control_command_id = MOUNT_EXEC_MOUNT; @@ -1042,6 +1057,17 @@ fail: mount_enter_dead_or_mounted(m, MOUNT_SUCCESS); } +static void mount_cycle_clear(Mount *m) { + assert(m); + + /* Clear all state we shall forget for this new cycle */ + + m->result = MOUNT_SUCCESS; + m->reload_result = MOUNT_SUCCESS; + exec_command_reset_status_array(m->exec_command, _MOUNT_EXEC_COMMAND_MAX); + UNIT(m)->reset_accounting = true; +} + static int mount_start(Unit *u) { Mount *m = MOUNT(u); int r; @@ -1072,12 +1098,9 @@ static int mount_start(Unit *u) { if (r < 0) return r; - m->result = MOUNT_SUCCESS; - m->reload_result = MOUNT_SUCCESS; - - u->reset_accounting = true; - + mount_cycle_clear(m); mount_enter_mounting(m); + return 1; } @@ -1138,21 +1161,23 @@ static int mount_serialize(Unit *u, FILE *f, FDSet *fds) { assert(f); assert(fds); - unit_serialize_item(u, f, "state", mount_state_to_string(m->state)); - 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)); + (void) serialize_item(f, "state", mount_state_to_string(m->state)); + (void) serialize_item(f, "result", mount_result_to_string(m->result)); + (void) serialize_item(f, "reload-result", mount_result_to_string(m->reload_result)); + (void) serialize_item_format(f, "n-retry-umount", "%u", m->n_retry_umount); if (m->control_pid > 0) - unit_serialize_item_format(u, f, "control-pid", PID_FMT, m->control_pid); + (void) serialize_item_format(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)); + (void) serialize_item(f, "control-command", mount_exec_command_to_string(m->control_command_id)); return 0; } static int mount_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) { Mount *m = MOUNT(u); + int r; assert(u); assert(key); @@ -1166,6 +1191,7 @@ static int mount_deserialize_item(Unit *u, const char *key, const char *value, F log_unit_debug(u, "Failed to parse state value: %s", value); else m->deserialized_state = state; + } else if (streq(key, "result")) { MountResult f; @@ -1184,13 +1210,17 @@ static int mount_deserialize_item(Unit *u, const char *key, const char *value, F else if (f != MOUNT_SUCCESS) m->reload_result = f; + } else if (streq(key, "n-retry-umount")) { + + r = safe_atou(value, &m->n_retry_umount); + if (r < 0) + log_unit_debug(u, "Failed to parse n-retry-umount value: %s", value); + } else if (streq(key, "control-pid")) { - pid_t pid; - if (parse_pid(value, &pid) < 0) + if (parse_pid(value, &m->control_pid) < 0) log_unit_debug(u, "Failed to parse control-pid value: %s", value); - else - m->control_pid = pid; + } else if (streq(key, "control-command")) { MountExecCommand id; @@ -1265,8 +1295,11 @@ static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) { m->control_command_id = _MOUNT_EXEC_COMMAND_INVALID; } - log_unit_full(u, f == MOUNT_SUCCESS ? LOG_DEBUG : LOG_NOTICE, 0, - "Mount process exited, code=%s status=%i", sigchld_code_to_string(code), status); + unit_log_process_exit( + u, f == MOUNT_SUCCESS ? LOG_DEBUG : LOG_NOTICE, + "Mount process", + mount_exec_command_to_string(m->control_command_id), + code, status); /* 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. */ @@ -1395,59 +1428,77 @@ static int mount_dispatch_timer(sd_event_source *source, usec_t usec, void *user return 0; } -typedef struct { - bool is_mounted; - bool just_mounted; - bool just_changed; -} MountSetupFlags; +static int update_parameters_proc_self_mount_info( + Mount *m, + const char *what, + const char *options, + const char *fstype) { + + MountParameters *p; + int r, q, w; + + p = &m->parameters_proc_self_mountinfo; + + r = free_and_strdup(&p->what, what); + if (r < 0) + return r; + + q = free_and_strdup(&p->options, options); + if (q < 0) + return q; + + w = free_and_strdup(&p->fstype, fstype); + if (w < 0) + return w; + + return r > 0 || q > 0 || w > 0; +} static int mount_setup_new_unit( - Unit *u, + Manager *m, + const char *name, const char *what, const char *where, const char *options, const char *fstype, - MountSetupFlags *flags) { - - MountParameters *p; + MountProcFlags *ret_flags, + Unit **ret) { - assert(u); - assert(flags); + _cleanup_(unit_freep) Unit *u = NULL; + int r; - u->source_path = strdup("/proc/self/mountinfo"); - MOUNT(u)->where = strdup(where); - if (!u->source_path || !MOUNT(u)->where) - return -ENOMEM; + assert(m); + assert(name); + assert(ret_flags); + assert(ret); - /* Make sure to initialize those fields before mount_is_extrinsic(). */ - MOUNT(u)->from_proc_self_mountinfo = true; - p = &MOUNT(u)->parameters_proc_self_mountinfo; + r = unit_new_for_name(m, sizeof(Mount), name, &u); + if (r < 0) + return r; - p->what = strdup(what); - p->options = strdup(options); - p->fstype = strdup(fstype); - if (!p->what || !p->options || !p->fstype) - return -ENOMEM; + r = free_and_strdup(&u->source_path, "/proc/self/mountinfo"); + if (r < 0) + return r; - if (!mount_is_extrinsic(MOUNT(u))) { - const char *target; - int r; + r = free_and_strdup(&MOUNT(u)->where, where); + if (r < 0) + return r; - target = mount_is_network(p) ? SPECIAL_REMOTE_FS_TARGET : SPECIAL_LOCAL_FS_TARGET; - r = unit_add_dependency_by_name(u, UNIT_BEFORE, target, NULL, true, UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT); - if (r < 0) - return r; + r = update_parameters_proc_self_mount_info(MOUNT(u), what, options, fstype); + if (r < 0) + return r; - r = unit_add_dependency_by_name(u, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true, UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT); - if (r < 0) - return r; - } + /* This unit was generated because /proc/self/mountinfo reported it. Remember this, so that by the time we load + * the unit file for it (and thus add in extra deps right after) we know what source to attributes the deps + * to.*/ + MOUNT(u)->from_proc_self_mountinfo = true; + /* We have only allocated the stub now, let's enqueue this unit for loading now, so that everything else is + * loaded in now. */ unit_add_to_load_queue(u); - flags->is_mounted = true; - flags->just_mounted = true; - flags->just_changed = true; + *ret_flags = MOUNT_PROC_IS_MOUNTED | MOUNT_PROC_JUST_MOUNTED | MOUNT_PROC_JUST_CHANGED; + *ret = TAKE_PTR(u); return 0; } @@ -1457,11 +1508,10 @@ static int mount_setup_existing_unit( const char *where, const char *options, const char *fstype, - MountSetupFlags *flags) { + MountProcFlags *ret_flags) { - MountParameters *p; - bool load_extras = false; - int r1, r2, r3; + MountProcFlags flags = MOUNT_PROC_IS_MOUNTED; + int r; assert(u); assert(flags); @@ -1472,49 +1522,38 @@ static int mount_setup_existing_unit( return -ENOMEM; } - /* Make sure to initialize those fields before mount_is_extrinsic(). */ - p = &MOUNT(u)->parameters_proc_self_mountinfo; - - r1 = free_and_strdup(&p->what, what); - r2 = free_and_strdup(&p->options, options); - r3 = free_and_strdup(&p->fstype, fstype); - if (r1 < 0 || r2 < 0 || r3 < 0) - return -ENOMEM; - - flags->just_changed = r1 > 0 || r2 > 0 || r3 > 0; - flags->is_mounted = true; - flags->just_mounted = !MOUNT(u)->from_proc_self_mountinfo || MOUNT(u)->just_mounted; - - MOUNT(u)->from_proc_self_mountinfo = true; + r = update_parameters_proc_self_mount_info(MOUNT(u), what, options, fstype); + if (r < 0) + return r; + if (r > 0) + flags |= MOUNT_PROC_JUST_CHANGED; - if (!mount_is_extrinsic(MOUNT(u)) && mount_is_network(p)) { - /* _netdev option may have shown up late, or on a - * remount. Add remote-fs dependencies, even though - * local-fs ones may already be there. - * - * Note: due to a current limitation (we don't track - * in the dependency "Set*" objects who created a - * dependency), we can only add deps, never lose them, - * until the next full daemon-reload. */ - unit_add_dependency_by_name(u, UNIT_BEFORE, SPECIAL_REMOTE_FS_TARGET, NULL, true, UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT); - load_extras = true; + if (!MOUNT(u)->from_proc_self_mountinfo) { + flags |= MOUNT_PROC_JUST_MOUNTED; + MOUNT(u)->from_proc_self_mountinfo = true; } - if (u->load_state == UNIT_NOT_FOUND) { + if (IN_SET(u->load_state, UNIT_NOT_FOUND, UNIT_BAD_SETTING, UNIT_ERROR)) { + /* The unit was previously not found or otherwise not loaded. Now that the unit shows up in + * /proc/self/mountinfo we should reconsider it this, hence set it to UNIT_LOADED. */ u->load_state = UNIT_LOADED; u->load_error = 0; - /* Load in the extras later on, after we - * finished initialization of the unit */ - - /* FIXME: since we're going to load the unit later on, why setting load_extras=true ? */ - load_extras = true; - flags->just_changed = true; + flags |= MOUNT_PROC_JUST_CHANGED; } - if (load_extras) - return mount_add_extras(MOUNT(u)); + if (FLAGS_SET(flags, MOUNT_PROC_JUST_CHANGED)) { + /* If things changed, then make sure that all deps are regenerated. Let's + * first remove all automatic deps, and then add in the new ones. */ + + unit_remove_dependencies(u, UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT); + r = mount_add_extras(MOUNT(u)); + if (r < 0) + return r; + } + + *ret_flags = flags; return 0; } @@ -1527,7 +1566,7 @@ static int mount_setup_unit( bool set_flags) { _cleanup_free_ char *e = NULL; - MountSetupFlags flags; + MountProcFlags flags; Unit *u; int r; @@ -1551,45 +1590,32 @@ static int mount_setup_unit( r = unit_name_from_path(where, ".mount", &e); if (r < 0) - return r; + return log_error_errno(r, "Failed to generate unit name from path '%s': %m", where); u = manager_get_unit(m, e); - if (!u) { - /* First time we see this mount point meaning that it's - * not been initiated by a mount unit but rather by the - * sysadmin having called mount(8) directly. */ - r = unit_new_for_name(m, sizeof(Mount), e, &u); - if (r < 0) - goto fail; - - r = mount_setup_new_unit(u, what, where, options, fstype, &flags); - if (r < 0) - unit_free(u); - } else + if (u) r = mount_setup_existing_unit(u, what, where, options, fstype, &flags); - + else + /* First time we see this mount point meaning that it's not been initiated by a mount unit but rather + * by the sysadmin having called mount(8) directly. */ + r = mount_setup_new_unit(m, e, what, where, options, fstype, &flags, &u); if (r < 0) - goto fail; + return log_warning_errno(r, "Failed to set up mount unit: %m"); - if (set_flags) { - MOUNT(u)->is_mounted = flags.is_mounted; - MOUNT(u)->just_mounted = flags.just_mounted; - MOUNT(u)->just_changed = flags.just_changed; - } - - if (flags.just_changed) + /* If the mount changed properties or state, let's notify our clients */ + if (flags & (MOUNT_PROC_JUST_CHANGED|MOUNT_PROC_JUST_MOUNTED)) unit_add_to_dbus_queue(u); + if (set_flags) + MOUNT(u)->proc_flags = flags; + return 0; -fail: - log_warning_errno(r, "Failed to set up mount unit: %m"); - return r; } static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) { _cleanup_(mnt_free_tablep) struct libmnt_table *t = NULL; _cleanup_(mnt_free_iterp) struct libmnt_iter *i = NULL; - int r = 0; + int r; assert(m); @@ -1602,7 +1628,6 @@ static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) { if (r < 0) return log_error_errno(r, "Failed to parse /proc/self/mountinfo: %m"); - r = 0; for (;;) { struct libmnt_fs *fs; const char *device, *path, *options, *fstype; @@ -1631,12 +1656,10 @@ static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) { device_found_node(m, d, DEVICE_FOUND_MOUNT, DEVICE_FOUND_MOUNT); - k = mount_setup_unit(m, d, p, options, fstype, set_flags); - if (r == 0 && k < 0) - r = k; + (void) mount_setup_unit(m, d, p, options, fstype, set_flags); } - return r; + return 0; } static void mount_shutdown(Manager *m) { @@ -1694,7 +1717,7 @@ static void mount_enumerate_perpetual(Manager *m) { static bool mount_is_mounted(Mount *m) { assert(m); - return UNIT(m)->perpetual || m->is_mounted; + return UNIT(m)->perpetual || FLAGS_SET(m->proc_flags, MOUNT_PROC_IS_MOUNTED); } static void mount_enumerate(Manager *m) { @@ -1758,7 +1781,7 @@ fail: } static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) { - _cleanup_set_free_ Set *around = NULL, *gone = NULL; + _cleanup_set_free_free_ Set *around = NULL, *gone = NULL; Manager *m = userdata; const char *what; Iterator i; @@ -1783,7 +1806,7 @@ static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents, if (r == 0) rescan = true; else if (r < 0) - return log_error_errno(r, "Failed to drain libmount events"); + return log_error_errno(r, "Failed to drain libmount events: %m"); } while (r == 0); log_debug("libmount event [rescan: %s]", yes_no(rescan)); @@ -1794,11 +1817,8 @@ static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents, r = mount_load_proc_self_mountinfo(m, true); if (r < 0) { /* Reset flags, just in case, for later calls */ - 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; - } + LIST_FOREACH(units_by_type, u, m->units_by_type[UNIT_MOUNT]) + MOUNT(u)->proc_flags = 0; return 0; } @@ -1819,7 +1839,7 @@ static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents, /* Remember that this device might just have disappeared */ if (set_ensure_allocated(&gone, &path_hash_ops) < 0 || - set_put(gone, mount->parameters_proc_self_mountinfo.what) < 0) + set_put_strdup(gone, mount->parameters_proc_self_mountinfo.what) < 0) log_oom(); /* we don't care too much about OOM here... */ } @@ -1828,10 +1848,7 @@ static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents, switch (mount->state) { case MOUNT_MOUNTED: - /* This has just been unmounted by - * somebody else, follow the state - * change. */ - mount->result = MOUNT_SUCCESS; /* make sure we forget any earlier umount failures */ + /* This has just been unmounted by somebody else, follow the state change. */ mount_enter_dead(mount, MOUNT_SUCCESS); break; @@ -1839,7 +1856,7 @@ static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents, break; } - } else if (mount->just_mounted || mount->just_changed) { + } else if (mount->proc_flags & (MOUNT_PROC_JUST_MOUNTED|MOUNT_PROC_JUST_CHANGED)) { /* A mount point was added or changed */ @@ -1850,7 +1867,8 @@ static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents, /* This has just been mounted by somebody else, follow the state change, but let's * generate a new invocation ID for this implicitly and automatically. */ - (void) unit_acquire_invocation_id(UNIT(mount)); + (void) unit_acquire_invocation_id(u); + mount_cycle_clear(mount); mount_enter_mounted(mount, MOUNT_SUCCESS); break; @@ -1872,14 +1890,15 @@ static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents, if (mount_is_mounted(mount) && mount->from_proc_self_mountinfo && mount->parameters_proc_self_mountinfo.what) { + /* Track devices currently used */ if (set_ensure_allocated(&around, &path_hash_ops) < 0 || - set_put(around, mount->parameters_proc_self_mountinfo.what) < 0) + set_put_strdup(around, mount->parameters_proc_self_mountinfo.what) < 0) log_oom(); } /* Reset the flags for later calls */ - mount->is_mounted = mount->just_mounted = mount->just_changed = false; + mount->proc_flags = 0; } SET_FOREACH(what, gone, i) { |