mirror of
https://github.com/systemd/systemd-stable.git
synced 2024-12-25 23:21:33 +03:00
Merge pull request #10980 from poettering/mount-no-extras
mount and swap improvements
This commit is contained in:
commit
e474bf118c
358
src/core/mount.c
358
src/core/mount.c
@ -68,20 +68,16 @@ 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"))
|
||||
return true;
|
||||
|
||||
if (fstype && fstype_is_network(fstype))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool mount_is_network(const MountParameters *p) {
|
||||
assert(p);
|
||||
|
||||
return mount_needs_network(p->options, p->fstype);
|
||||
if (fstab_test_option(p->options, "_netdev\0"))
|
||||
return true;
|
||||
|
||||
if (p->fstype && fstype_is_network(p->fstype))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool mount_is_loop(const MountParameters *p) {
|
||||
@ -129,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;
|
||||
|
||||
@ -211,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) {
|
||||
@ -318,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;
|
||||
@ -348,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
|
||||
@ -381,7 +375,7 @@ 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;
|
||||
@ -429,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);
|
||||
|
||||
@ -474,8 +468,15 @@ static int mount_add_default_dependencies(Mount *m) {
|
||||
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, true, mask);
|
||||
if (r < 0)
|
||||
@ -542,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;
|
||||
|
||||
@ -611,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);
|
||||
}
|
||||
@ -944,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;
|
||||
@ -1048,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;
|
||||
@ -1078,13 +1098,9 @@ static int mount_start(Unit *u) {
|
||||
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;
|
||||
}
|
||||
|
||||
@ -1148,6 +1164,7 @@ static int mount_serialize(Unit *u, FILE *f, FDSet *fds) {
|
||||
(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)
|
||||
(void) serialize_item_format(f, "control-pid", PID_FMT, m->control_pid);
|
||||
@ -1160,6 +1177,7 @@ static int mount_serialize(Unit *u, FILE *f, FDSet *fds) {
|
||||
|
||||
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);
|
||||
@ -1173,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;
|
||||
|
||||
@ -1191,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, "control-pid")) {
|
||||
pid_t pid;
|
||||
} else if (streq(key, "n-retry-umount")) {
|
||||
|
||||
if (parse_pid(value, &pid) < 0)
|
||||
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")) {
|
||||
|
||||
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;
|
||||
|
||||
@ -1405,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) {
|
||||
MountProcFlags *ret_flags,
|
||||
Unit **ret) {
|
||||
|
||||
MountParameters *p;
|
||||
_cleanup_(unit_freep) Unit *u = NULL;
|
||||
int r;
|
||||
|
||||
assert(u);
|
||||
assert(flags);
|
||||
assert(m);
|
||||
assert(name);
|
||||
assert(ret_flags);
|
||||
assert(ret);
|
||||
|
||||
u->source_path = strdup("/proc/self/mountinfo");
|
||||
MOUNT(u)->where = strdup(where);
|
||||
if (!u->source_path || !MOUNT(u)->where)
|
||||
return -ENOMEM;
|
||||
r = unit_new_for_name(m, sizeof(Mount), name, &u);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* Make sure to initialize those fields before mount_is_extrinsic(). */
|
||||
r = free_and_strdup(&u->source_path, "/proc/self/mountinfo");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = free_and_strdup(&MOUNT(u)->where, where);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = update_parameters_proc_self_mount_info(MOUNT(u), what, options, fstype);
|
||||
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;
|
||||
p = &MOUNT(u)->parameters_proc_self_mountinfo;
|
||||
|
||||
p->what = strdup(what);
|
||||
p->options = strdup(options);
|
||||
p->fstype = strdup(fstype);
|
||||
if (!p->what || !p->options || !p->fstype)
|
||||
return -ENOMEM;
|
||||
|
||||
if (!mount_is_extrinsic(MOUNT(u))) {
|
||||
const char *target;
|
||||
int r;
|
||||
|
||||
target = mount_is_network(p) ? SPECIAL_REMOTE_FS_TARGET : SPECIAL_LOCAL_FS_TARGET;
|
||||
r = unit_add_dependency_by_name(u, UNIT_BEFORE, target, true, UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = unit_add_dependency_by_name(u, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, true, UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
@ -1467,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);
|
||||
@ -1482,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;
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
@ -1537,7 +1566,7 @@ static int mount_setup_unit(
|
||||
bool set_flags) {
|
||||
|
||||
_cleanup_free_ char *e = NULL;
|
||||
MountSetupFlags flags;
|
||||
MountProcFlags flags;
|
||||
Unit *u;
|
||||
int r;
|
||||
|
||||
@ -1561,44 +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:
|
||||
return log_warning_errno(r, "Failed to set up mount unit: %m");
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
@ -1611,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;
|
||||
@ -1640,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) {
|
||||
@ -1703,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) {
|
||||
@ -1767,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;
|
||||
@ -1803,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;
|
||||
}
|
||||
@ -1828,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... */
|
||||
}
|
||||
|
||||
@ -1837,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;
|
||||
|
||||
@ -1848,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 */
|
||||
|
||||
@ -1859,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;
|
||||
|
||||
@ -1881,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) {
|
||||
|
@ -34,6 +34,13 @@ typedef struct MountParameters {
|
||||
char *fstype;
|
||||
} MountParameters;
|
||||
|
||||
/* Used while looking for mount points that vanished or got added from/to /proc/self/mountinfo */
|
||||
typedef enum MountProcFlags {
|
||||
MOUNT_PROC_IS_MOUNTED = 1 << 0,
|
||||
MOUNT_PROC_JUST_MOUNTED = 1 << 1,
|
||||
MOUNT_PROC_JUST_CHANGED = 1 << 2,
|
||||
} MountProcFlags;
|
||||
|
||||
struct Mount {
|
||||
Unit meta;
|
||||
|
||||
@ -45,11 +52,7 @@ struct Mount {
|
||||
bool from_proc_self_mountinfo:1;
|
||||
bool from_fragment:1;
|
||||
|
||||
/* Used while looking for mount points that vanished or got
|
||||
* added from/to /proc/self/mountinfo */
|
||||
bool is_mounted:1;
|
||||
bool just_mounted:1;
|
||||
bool just_changed:1;
|
||||
MountProcFlags proc_flags;
|
||||
|
||||
bool sloppy_options;
|
||||
|
||||
|
167
src/core/swap.c
167
src/core/swap.c
@ -273,9 +273,71 @@ static int swap_load_devnode(Swap *s) {
|
||||
return swap_set_devnode(s, p);
|
||||
}
|
||||
|
||||
static int swap_load(Unit *u) {
|
||||
static int swap_add_extras(Swap *s) {
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
|
||||
if (UNIT(s)->fragment_path)
|
||||
s->from_fragment = true;
|
||||
|
||||
if (!s->what) {
|
||||
if (s->parameters_fragment.what)
|
||||
s->what = strdup(s->parameters_fragment.what);
|
||||
else if (s->parameters_proc_swaps.what)
|
||||
s->what = strdup(s->parameters_proc_swaps.what);
|
||||
else {
|
||||
r = unit_name_to_path(UNIT(s)->id, &s->what);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (!s->what)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
path_simplify(s->what, false);
|
||||
|
||||
if (!UNIT(s)->description) {
|
||||
r = unit_set_description(UNIT(s), s->what);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = unit_require_mounts_for(UNIT(s), s->what, UNIT_DEPENDENCY_IMPLICIT);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = swap_add_device_dependencies(s);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = swap_load_devnode(s);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = unit_patch_contexts(UNIT(s));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = unit_add_exec_dependencies(UNIT(s), &s->exec_context);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = unit_set_default_slice(UNIT(s));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = swap_add_default_dependencies(s);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int swap_load(Unit *u) {
|
||||
Swap *s = SWAP(u);
|
||||
int r, q;
|
||||
|
||||
assert(s);
|
||||
assert(u->load_state == UNIT_STUB);
|
||||
@ -285,65 +347,18 @@ static int swap_load(Unit *u) {
|
||||
r = unit_load_fragment_and_dropin_optional(u);
|
||||
else
|
||||
r = unit_load_fragment_and_dropin(u);
|
||||
|
||||
/* Add in some extras, and do so either when we successfully loaded something or when /proc/swaps is already
|
||||
* active. */
|
||||
if (u->load_state == UNIT_LOADED || s->from_proc_swaps)
|
||||
q = swap_add_extras(s);
|
||||
else
|
||||
q = 0;
|
||||
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (u->load_state == UNIT_LOADED) {
|
||||
|
||||
if (UNIT(s)->fragment_path)
|
||||
s->from_fragment = true;
|
||||
|
||||
if (!s->what) {
|
||||
if (s->parameters_fragment.what)
|
||||
s->what = strdup(s->parameters_fragment.what);
|
||||
else if (s->parameters_proc_swaps.what)
|
||||
s->what = strdup(s->parameters_proc_swaps.what);
|
||||
else {
|
||||
r = unit_name_to_path(u->id, &s->what);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (!s->what)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
path_simplify(s->what, false);
|
||||
|
||||
if (!UNIT(s)->description) {
|
||||
r = unit_set_description(u, s->what);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = unit_require_mounts_for(UNIT(s), s->what, UNIT_DEPENDENCY_IMPLICIT);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = swap_add_device_dependencies(s);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = swap_load_devnode(s);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = unit_patch_contexts(u);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = unit_add_exec_dependencies(u, &s->exec_context);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = unit_set_default_slice(u);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = swap_add_default_dependencies(s);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
if (q < 0)
|
||||
return q;
|
||||
|
||||
return swap_verify(s);
|
||||
}
|
||||
@ -370,7 +385,6 @@ static int swap_setup_unit(
|
||||
return log_unit_error_errno(u, r, "Failed to generate unit name from path: %m");
|
||||
|
||||
u = manager_get_unit(m, e);
|
||||
|
||||
if (u &&
|
||||
SWAP(u)->from_proc_swaps &&
|
||||
!path_equal(SWAP(u)->parameters_proc_swaps.what, what_proc_swaps))
|
||||
@ -405,6 +419,13 @@ static int swap_setup_unit(
|
||||
}
|
||||
}
|
||||
|
||||
/* The unit is definitely around now, mark it as loaded if it was previously referenced but could not be
|
||||
* loaded. After all we can load it now, from the data in /proc/swaps. */
|
||||
if (IN_SET(u->load_state, UNIT_NOT_FOUND, UNIT_BAD_SETTING, UNIT_ERROR)) {
|
||||
u->load_state = UNIT_LOADED;
|
||||
u->load_error = 0;
|
||||
}
|
||||
|
||||
if (set_flags) {
|
||||
SWAP(u)->is_active = true;
|
||||
SWAP(u)->just_activated = !SWAP(u)->from_proc_swaps;
|
||||
@ -472,7 +493,7 @@ static int swap_process_new(Manager *m, const char *device, int prio, bool set_f
|
||||
swap_setup_unit(m, devlink, device, prio, set_flags);
|
||||
}
|
||||
|
||||
return r;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void swap_set_state(Swap *s, SwapState state) {
|
||||
@ -813,6 +834,14 @@ fail:
|
||||
swap_enter_dead_or_active(s, SWAP_FAILURE_RESOURCES);
|
||||
}
|
||||
|
||||
static void swap_cycle_clear(Swap *s) {
|
||||
assert(s);
|
||||
|
||||
s->result = SWAP_SUCCESS;
|
||||
exec_command_reset_status_array(s->exec_command, _SWAP_EXEC_COMMAND_MAX);
|
||||
UNIT(s)->reset_accounting = true;
|
||||
}
|
||||
|
||||
static int swap_start(Unit *u) {
|
||||
Swap *s = SWAP(u), *other;
|
||||
int r;
|
||||
@ -852,11 +881,7 @@ static int swap_start(Unit *u) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
s->result = SWAP_SUCCESS;
|
||||
exec_command_reset_status_array(s->exec_command, _SWAP_EXEC_COMMAND_MAX);
|
||||
|
||||
u->reset_accounting = true;
|
||||
|
||||
swap_cycle_clear(s);
|
||||
swap_enter_activating(s);
|
||||
return 1;
|
||||
}
|
||||
@ -1088,7 +1113,6 @@ static int swap_dispatch_timer(sd_event_source *source, usec_t usec, void *userd
|
||||
|
||||
static int swap_load_proc_swaps(Manager *m, bool set_flags) {
|
||||
unsigned i;
|
||||
int r = 0;
|
||||
|
||||
assert(m);
|
||||
|
||||
@ -1120,12 +1144,10 @@ static int swap_load_proc_swaps(Manager *m, bool set_flags) {
|
||||
|
||||
device_found_node(m, d, DEVICE_FOUND_SWAP, DEVICE_FOUND_SWAP);
|
||||
|
||||
k = swap_process_new(m, d, prio, set_flags);
|
||||
if (k < 0)
|
||||
r = k;
|
||||
(void) swap_process_new(m, d, prio, set_flags);
|
||||
}
|
||||
|
||||
return r;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int swap_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
|
||||
@ -1156,13 +1178,13 @@ static int swap_dispatch_io(sd_event_source *source, int fd, uint32_t revents, v
|
||||
Swap *swap = SWAP(u);
|
||||
|
||||
if (!swap->is_active) {
|
||||
/* This has just been deactivated */
|
||||
|
||||
swap_unset_proc_swaps(swap);
|
||||
|
||||
switch (swap->state) {
|
||||
|
||||
case SWAP_ACTIVE:
|
||||
/* This has just been deactivated */
|
||||
swap_enter_dead(swap, SWAP_SUCCESS);
|
||||
break;
|
||||
|
||||
@ -1183,7 +1205,8 @@ static int swap_dispatch_io(sd_event_source *source, int fd, uint32_t revents, v
|
||||
|
||||
case SWAP_DEAD:
|
||||
case SWAP_FAILED:
|
||||
(void) unit_acquire_invocation_id(UNIT(swap));
|
||||
(void) unit_acquire_invocation_id(u);
|
||||
swap_cycle_clear(swap);
|
||||
swap_enter_active(swap, SWAP_SUCCESS);
|
||||
break;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user