swap.c revision be847e82cf95bf8eb589778df2aa2b3d1d7ae99e
e3169126793f43be3d840874ffb3935a51097001Patrik Flykt/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
e3169126793f43be3d840874ffb3935a51097001Patrik Flykt This file is part of systemd.
e3169126793f43be3d840874ffb3935a51097001Patrik Flykt Copyright 2010 Lennart Poettering
e3169126793f43be3d840874ffb3935a51097001Patrik Flykt systemd is free software; you can redistribute it and/or modify it
e3169126793f43be3d840874ffb3935a51097001Patrik Flykt under the terms of the GNU Lesser General Public License as published by
e3169126793f43be3d840874ffb3935a51097001Patrik Flykt the Free Software Foundation; either version 2.1 of the License, or
e3169126793f43be3d840874ffb3935a51097001Patrik Flykt (at your option) any later version.
e3169126793f43be3d840874ffb3935a51097001Patrik Flykt systemd is distributed in the hope that it will be useful, but
e3169126793f43be3d840874ffb3935a51097001Patrik Flykt WITHOUT ANY WARRANTY; without even the implied warranty of
e3169126793f43be3d840874ffb3935a51097001Patrik Flykt MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
e3169126793f43be3d840874ffb3935a51097001Patrik Flykt Lesser General Public License for more details.
e3169126793f43be3d840874ffb3935a51097001Patrik Flykt You should have received a copy of the GNU Lesser General Public License
e3169126793f43be3d840874ffb3935a51097001Patrik Flykt along with systemd; If not, see <http://www.gnu.org/licenses/>.
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flyktstatic const UnitActiveState state_translation_table[_SWAP_STATE_MAX] = {
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt [SWAP_DEACTIVATING_SIGTERM] = UNIT_DEACTIVATING,
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt [SWAP_DEACTIVATING_SIGKILL] = UNIT_DEACTIVATING,
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flyktstatic int swap_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata);
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flyktstatic int swap_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flyktstatic int swap_set_devnode(Swap *s, const char *devnode) {
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt r = hashmap_ensure_allocated(&UNIT(s)->manager->swaps_by_devnode, &string_hash_ops);
if (s->devnode) {
if (first)
if (devnode) {
if (!s->devnode)
return -ENOMEM;
assert(s);
u->ignore_on_isolate = true;
assert(s);
if (s->control_pid <= 0)
s->control_pid = 0;
assert(s);
assert(s);
if (s->timeout_usec <= 0) {
if (s->timer_event_source) {
return sd_event_add_time(
&s->timer_event_source,
swap_dispatch_timer, s);
assert(s);
if (!s->what)
if (!s->from_fragment)
* systemd-remount-fs.service, since they might need a
assert(s);
return unit_add_two_dependencies_by_name(UNIT(s), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true);
return log_oom();
log_unit_error(UNIT(s)->id, "%s: Value of \"What\" and unit name do not match, not loading.", UNIT(s)->id);
return -EINVAL;
log_unit_error(UNIT(s)->id, "%s has PAM enabled. Kill mode must be set to 'control-group'. Refusing to load.", UNIT(s)->id);
return -EINVAL;
assert(s);
p = udev_device_get_devnode(d);
return swap_set_devnode(s, p);
assert(s);
s->from_fragment = true;
if (!s->what) {
if (!s->what)
return -ENOMEM;
r = swap_add_device_links(s);
r = swap_load_devnode(s);
r = unit_patch_contexts(u);
r = swap_add_default_dependencies(s);
return swap_verify(s);
static int swap_setup_unit(
Manager *m,
const char *what,
const char *what_proc_swaps,
int priority,
bool set_flags) {
bool delete = false;
SwapParameters *p;
assert(m);
return log_oom();
u = manager_get_unit(m, e);
log_error("Swap %s appeared twice with different device paths %s and %s", e, SWAP(u)->parameters_proc_swaps.what, what_proc_swaps);
return -EEXIST;
delete = true;
return log_oom();
r = unit_add_name(u, e);
goto fail;
r = -ENOMEM;
goto fail;
delete = false;
if (!p->what) {
if (!p->what) {
r = -ENOMEM;
goto fail;
if (set_flags) {
fail:
if (delete && u)
unit_free(u);
const char *dn;
assert(m);
assert(s);
assert(s);
else if (s->from_proc_swaps)
if (s->control_pid <= 0)
return -EBADMSG;
r = swap_arm_timer(s);
SwapParameters *p;
assert(s);
assert(f);
if (s->from_proc_swaps)
p = &s->parameters_proc_swaps;
else if (s->from_fragment)
p = &s->parameters_fragment;
p = NULL;
fprintf(f,
if (s->devnode)
fprintf(f,
if (s->control_pid > 0)
fprintf(f,
.apply_permissions = true,
.apply_chroot = true,
.apply_tty_stdin = true,
assert(s);
assert(c);
if (s->reset_cpu_usage) {
s->reset_cpu_usage = false;
goto fail;
r = swap_arm_timer(s);
goto fail;
r = exec_spawn(c,
&s->exec_context,
s->exec_runtime,
&pid);
goto fail;
goto fail;
fail:
assert(s);
if (f != SWAP_SUCCESS)
s->result = f;
exec_context_destroy_runtime_directory(&s->exec_context, manager_get_runtime_prefix(UNIT(s)->manager));
assert(s);
if (f != SWAP_SUCCESS)
s->result = f;
assert(s);
if (f != SWAP_SUCCESS)
s->result = f;
r = unit_kill_context(
UNIT(s),
&s->kill_context,
s->control_pid,
goto fail;
r = swap_arm_timer(s);
goto fail;
fail:
assert(s);
if (s->from_fragment) {
if (priority < 0) {
goto fail;
if (priority >= 0) {
char p[DECIMAL_STR_MAX(int)];
goto fail;
const char *discard_arg;
goto fail;
goto fail;
goto fail;
fail:
assert(s);
s->what,
NULL);
goto fail;
goto fail;
fail:
assert(s);
return -EAGAIN;
return -EPERM;
return -EAGAIN;
s->reset_cpu_usage = true;
assert(s);
return -EPERM;
assert(s);
assert(f);
if (s->control_pid > 0)
if (s->control_command_id >= 0)
assert(s);
if (state < 0)
SwapResult f;
else if (f != SWAP_SUCCESS)
s->result = f;
if (id < 0)
assert(u);
assert(u);
assert(s);
return s->from_proc_swaps;
SwapResult f;
assert(s);
s->control_pid = 0;
f = SWAP_SUCCESS;
f = SWAP_FAILURE_SIGNAL;
if (f != SWAP_SUCCESS)
s->result = f;
if (s->control_command) {
switch (s->state) {
case SWAP_ACTIVATING:
case SWAP_ACTIVATING_DONE:
case SWAP_ACTIVATING_SIGTERM:
case SWAP_ACTIVATING_SIGKILL:
if (f == SWAP_SUCCESS)
swap_enter_active(s, f);
swap_enter_dead(s, f);
case SWAP_DEACTIVATING:
swap_enter_dead(s, f);
assert(s);
switch (s->state) {
case SWAP_ACTIVATING:
case SWAP_ACTIVATING_DONE:
case SWAP_DEACTIVATING:
case SWAP_ACTIVATING_SIGTERM:
log_unit_warning(UNIT(s)->id, "%s deactivation timed out. Skipping SIGKILL. Ignoring.", UNIT(s)->id);
case SWAP_ACTIVATING_SIGKILL:
log_unit_warning(UNIT(s)->id, "%s swap process still around after SIGKILL. Ignoring.", UNIT(s)->id);
assert(m);
int prio = 0, k;
if (k == EOF)
return log_oom();
Unit *u;
assert(m);
r = swap_load_proc_swaps(m, true);
case SWAP_ACTIVE:
case SWAP_DEAD:
case SWAP_FAILED:
case SWAP_ACTIVATING:
assert(s);
if (s->from_fragment)
return NULL;
return NULL;
assert(s);
if (!set)
return -ENOMEM;
goto fail;
fail:
assert(m);
if (m->proc_swaps) {
assert(m);
if (!m->proc_swaps) {
if (!m->proc_swaps)
r = sd_event_add_io(m->event, &m->swap_event_source, fileno(m->proc_swaps), EPOLLPRI, swap_dispatch_io, m);
goto fail;
goto fail;
r = swap_load_proc_swaps(m, false);
goto fail;
fail:
swap_shutdown(m);
const char *dn;
Swap *s;
assert(m);
if (!dn)
return -ENOMEM;
return -ENOMEM;
const char *dn;
Swap *s;
if (!dn)
assert(s);
if (!s->timer_event_source)
if (supported < 0)
return supported;
.sections =
.no_alias = true,
.no_instances = true,
.starting_stopping = {
.finished_start_job = {
.finished_stop_job = {