1
1
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:
Lennart Poettering 2018-12-08 00:23:15 +01:00 committed by GitHub
commit e474bf118c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 287 additions and 251 deletions

View File

@ -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) {

View File

@ -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;

View File

@ -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;