summaryrefslogtreecommitdiff
path: root/src/core/mount.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/mount.c')
-rw-r--r--src/core/mount.c407
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) {