return false;
}
-static bool mount_is_auto(const MountParameters *p) {
- assert(p);
-
- return !fstab_test_option(p->options, "noauto\0");
-}
-
-static bool mount_is_automount(const MountParameters *p) {
- assert(p);
-
- return fstab_test_option(p->options,
- "comment=systemd.automount\0"
- "x-systemd.automount\0");
-}
-
static bool mount_is_bound_to_device(const Mount *m) {
const MountParameters *p;
return get_mount_parameters_fragment(m);
}
+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_add_mount_dependencies(Mount *m) {
MountParameters *pm;
Unit *other;
}
static int mount_add_device_dependencies(Mount *m) {
- bool device_wants_mount;
UnitDependencyMask mask;
MountParameters *p;
UnitDependency dep;
if (path_equal(m->where, "/"))
return 0;
- 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
* unplugged. But the user can still force this dep with an
* automatically stopped when the device disappears suddenly. */
dep = mount_is_bound_to_device(m) ? UNIT_BINDS_TO : UNIT_REQUIRES;
- mask = m->from_fragment ? UNIT_DEPENDENCY_FILE : UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT;
+ /* We always use 'what' from /proc/self/mountinfo if mounted */
+ mask = m->from_proc_self_mountinfo ? UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT : UNIT_DEPENDENCY_FILE;
- r = unit_add_node_dependency(UNIT(m), p->what, device_wants_mount, dep, mask);
+ r = unit_add_node_dependency(UNIT(m), p->what, false, dep, mask);
if (r < 0)
return r;
const char *after, *before;
UnitDependencyMask mask;
MountParameters *p;
+ bool nofail;
int r;
assert(m);
return 0;
mask = m->from_fragment ? UNIT_DEPENDENCY_FILE : UNIT_DEPENDENCY_MOUNTINFO_DEFAULT;
+ nofail = m->from_fragment ? fstab_test_yes_no_option(m->parameters_fragment.options, "nofail\0" "fail\0") : false;
if (mount_is_network(p)) {
/* We order ourselves after network.target. This is
before = SPECIAL_LOCAL_FS_TARGET;
}
- r = unit_add_dependency_by_name(UNIT(m), UNIT_BEFORE, before, true, mask);
- if (r < 0)
- return r;
+ if (!nofail) {
+ 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, true, mask);
if (r < 0)
pid_is_unwaited(m->control_pid) &&
MOUNT_STATE_WITH_PROCESS(new_state)) {
- r = unit_watch_pid(UNIT(m), m->control_pid);
+ r = unit_watch_pid(UNIT(m), m->control_pid, false);
if (r < 0)
return r;
"%sSloppyOptions: %s\n"
"%sLazyUnmount: %s\n"
"%sForceUnmount: %s\n"
- "%sTimoutSec: %s\n",
+ "%sTimeoutSec: %s\n",
prefix, mount_state_to_string(m->state),
prefix, mount_result_to_string(m->result),
prefix, m->where,
if (r < 0)
return r;
- r = unit_watch_pid(UNIT(m), pid);
+ r = unit_watch_pid(UNIT(m), pid, true);
if (r < 0)
- /* FIXME: we need to do something here */
return r;
*_pid = pid;
unit_unref_uid_gid(UNIT(m), true);
dynamic_creds_destroy(&m->dynamic_creds);
+
+ /* Any dependencies based on /proc/self/mountinfo are now stale */
+ unit_remove_dependencies(UNIT(m), UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT);
}
static void mount_enter_mounted(Mount *m, MountResult f) {
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;
assert(IN_SET(m->state, MOUNT_DEAD, MOUNT_FAILED));
- r = unit_start_limit_test(u);
+ r = unit_test_start_limit(u);
if (r < 0) {
mount_enter_dead(m, MOUNT_FAILURE_START_LIMIT_HIT);
return r;
if (r < 0)
return r;
- m->result = MOUNT_SUCCESS;
- m->reload_result = MOUNT_SUCCESS;
- exec_command_reset_status_array(m->exec_command, _MOUNT_EXEC_COMMAND_MAX);
-
- u->reset_accounting = true;
-
+ mount_cycle_clear(m);
mount_enter_mounting(m);
+
return 1;
}
return 0;
}
-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;
-}
-
-typedef struct {
- bool is_mounted;
- bool just_mounted;
- bool just_changed;
-} MountSetupFlags;
-
static int mount_setup_new_unit(
Manager *m,
const char *name,
const char *where,
const char *options,
const char *fstype,
- MountSetupFlags *flags,
+ MountProcFlags *ret_flags,
Unit **ret) {
_cleanup_(unit_freep) Unit *u = NULL;
assert(m);
assert(name);
- assert(flags);
+ assert(ret_flags);
assert(ret);
r = unit_new_for_name(m, sizeof(Mount), name, &u);
* 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;
}
const char *where,
const char *options,
const char *fstype,
- MountSetupFlags *flags) {
+ MountProcFlags *ret_flags) {
- bool load_extras = false;
- MountParameters *p;
+ MountProcFlags flags = MOUNT_PROC_IS_MOUNTED;
int r;
assert(u);
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;
- flags->just_changed = r > 0;
- flags->is_mounted = true;
- flags->just_mounted = !MOUNT(u)->from_proc_self_mountinfo || MOUNT(u)->just_mounted;
+ if (!MOUNT(u)->from_proc_self_mountinfo || FLAGS_SET(MOUNT(u)->proc_flags, MOUNT_PROC_JUST_MOUNTED))
+ flags |= MOUNT_PROC_JUST_MOUNTED;
MOUNT(u)->from_proc_self_mountinfo = true;
- p = &MOUNT(u)->parameters_proc_self_mountinfo;
+ 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;
- 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, true, UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT);
- load_extras = true;
+ flags |= MOUNT_PROC_JUST_CHANGED;
}
- if (u->load_state == UNIT_NOT_FOUND) {
- u->load_state = UNIT_LOADED;
- u->load_error = 0;
+ 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. */
- /* Load in the extras later on, after we
- * finished initialization of the unit */
+ unit_remove_dependencies(u, UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT);
- /* FIXME: since we're going to load the unit later on, why setting load_extras=true ? */
- load_extras = true;
- flags->just_changed = true;
+ r = mount_add_extras(MOUNT(u));
+ if (r < 0)
+ return r;
}
- if (load_extras)
- return mount_add_extras(MOUNT(u));
-
+ *ret_flags = flags;
return 0;
}
bool set_flags) {
_cleanup_free_ char *e = NULL;
- MountSetupFlags flags;
+ MountProcFlags flags;
Unit *u;
int r;
if (r < 0)
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;
}
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) {
}
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;
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;
}
/* 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... */
}
mount->from_proc_self_mountinfo = false;
+ assert_se(update_parameters_proc_self_mount_info(mount, NULL, NULL, NULL) >= 0);
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;
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 */
/* 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;
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) {