]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/swap.c
core: expose consumed CPU time per unit
[thirdparty/systemd.git] / src / core / swap.c
CommitLineData
d6c9574f 1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
07b0b134
ML
2
3/***
4 This file is part of systemd.
5
6 Copyright 2010 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
5430f7f2
LP
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
07b0b134
ML
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5430f7f2 16 Lesser General Public License for more details.
07b0b134 17
5430f7f2 18 You should have received a copy of the GNU Lesser General Public License
07b0b134
ML
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
22#include <errno.h>
07b0b134 23#include <unistd.h>
07b0b134
ML
24#include <sys/epoll.h>
25#include <sys/stat.h>
e04aad61 26#include <libudev.h>
07b0b134
ML
27
28#include "unit.h"
29#include "swap.h"
07b0b134
ML
30#include "unit-name.h"
31#include "dbus-swap.h"
514f4ef5 32#include "special.h"
9a57c629 33#include "exit-status.h"
9eb977db 34#include "path-util.h"
a5c3034f 35#include "virt.h"
5bcb0f2b 36#include "udev-util.h"
d15d0333 37#include "fstab-util.h"
07b0b134
ML
38
39static const UnitActiveState state_translation_table[_SWAP_STATE_MAX] = {
40 [SWAP_DEAD] = UNIT_INACTIVE,
e04aad61 41 [SWAP_ACTIVATING] = UNIT_ACTIVATING,
5bcb0f2b 42 [SWAP_ACTIVATING_DONE] = UNIT_ACTIVE,
07b0b134 43 [SWAP_ACTIVE] = UNIT_ACTIVE,
e04aad61
LP
44 [SWAP_DEACTIVATING] = UNIT_DEACTIVATING,
45 [SWAP_ACTIVATING_SIGTERM] = UNIT_DEACTIVATING,
46 [SWAP_ACTIVATING_SIGKILL] = UNIT_DEACTIVATING,
47 [SWAP_DEACTIVATING_SIGTERM] = UNIT_DEACTIVATING,
48 [SWAP_DEACTIVATING_SIGKILL] = UNIT_DEACTIVATING,
fdf20a31 49 [SWAP_FAILED] = UNIT_FAILED
07b0b134
ML
50};
51
718db961
LP
52static int swap_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata);
53static int swap_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
54
e04aad61 55static void swap_unset_proc_swaps(Swap *s) {
9670d583
LP
56 assert(s);
57
58 if (!s->from_proc_swaps)
59 return;
60
61 free(s->parameters_proc_swaps.what);
62 s->parameters_proc_swaps.what = NULL;
63
64 s->from_proc_swaps = false;
65}
66
67static int swap_set_devnode(Swap *s, const char *devnode) {
df326b84 68 Hashmap *swaps;
5bcb0f2b 69 Swap *first;
9670d583 70 int r;
e04aad61
LP
71
72 assert(s);
73
d5099efc 74 r = hashmap_ensure_allocated(&UNIT(s)->manager->swaps_by_devnode, &string_hash_ops);
9670d583
LP
75 if (r < 0)
76 return r;
e04aad61 77
9670d583 78 swaps = UNIT(s)->manager->swaps_by_devnode;
e04aad61 79
9670d583
LP
80 if (s->devnode) {
81 first = hashmap_get(swaps, s->devnode);
e04aad61 82
9670d583
LP
83 LIST_REMOVE(same_devnode, first, s);
84 if (first)
85 hashmap_replace(swaps, first->devnode, first);
86 else
87 hashmap_remove(swaps, s->devnode);
5bcb0f2b 88
9670d583
LP
89 free(s->devnode);
90 s->devnode = NULL;
91 }
92
93 if (devnode) {
94 s->devnode = strdup(devnode);
95 if (!s->devnode)
96 return -ENOMEM;
97
98 first = hashmap_get(swaps, s->devnode);
99 LIST_PREPEND(same_devnode, first, s);
100
101 return hashmap_replace(swaps, first->devnode, first);
102 }
103
104 return 0;
e04aad61
LP
105}
106
f6cebb3b 107static void swap_init(Unit *u) {
6e620bec
LP
108 Swap *s = SWAP(u);
109
110 assert(s);
1124fe6f 111 assert(UNIT(s)->load_state == UNIT_STUB);
6e620bec 112
1f19a534 113 s->timeout_usec = u->manager->default_timeout_start_usec;
e04aad61 114
ac155bb8
MS
115 s->exec_context.std_output = u->manager->default_std_output;
116 s->exec_context.std_error = u->manager->default_std_error;
085afe36 117
6b1dc2bd 118 s->parameters_proc_swaps.priority = s->parameters_fragment.priority = -1;
e04aad61 119
e1770af8 120 s->control_command_id = _SWAP_EXEC_COMMAND_INVALID;
c8f4d764 121
5bcb0f2b 122 u->ignore_on_isolate = true;
e04aad61
LP
123}
124
125static void swap_unwatch_control_pid(Swap *s) {
126 assert(s);
127
128 if (s->control_pid <= 0)
129 return;
130
131 unit_unwatch_pid(UNIT(s), s->control_pid);
132 s->control_pid = 0;
6e620bec
LP
133}
134
4e85aff4
LP
135static void swap_done(Unit *u) {
136 Swap *s = SWAP(u);
07b0b134 137
4e85aff4 138 assert(s);
07b0b134 139
e04aad61 140 swap_unset_proc_swaps(s);
9670d583 141 swap_set_devnode(s, NULL);
e04aad61 142
4e85aff4 143 free(s->what);
e04aad61
LP
144 s->what = NULL;
145
4e85aff4 146 free(s->parameters_fragment.what);
6b1dc2bd 147 s->parameters_fragment.what = NULL;
e04aad61 148
47cb901e
LP
149 free(s->parameters_fragment.options);
150 s->parameters_fragment.options = NULL;
86b23b07 151
613b411c 152 s->exec_runtime = exec_runtime_unref(s->exec_runtime);
e04aad61
LP
153 exec_command_done_array(s->exec_command, _SWAP_EXEC_COMMAND_MAX);
154 s->control_command = NULL;
155
156 swap_unwatch_control_pid(s);
157
718db961
LP
158 s->timer_event_source = sd_event_source_unref(s->timer_event_source);
159}
160
161static int swap_arm_timer(Swap *s) {
162 int r;
163
164 assert(s);
165
166 if (s->timeout_usec <= 0) {
167 s->timer_event_source = sd_event_source_unref(s->timer_event_source);
168 return 0;
169 }
170
171 if (s->timer_event_source) {
172 r = sd_event_source_set_time(s->timer_event_source, now(CLOCK_MONOTONIC) + s->timeout_usec);
173 if (r < 0)
174 return r;
175
176 return sd_event_source_set_enabled(s->timer_event_source, SD_EVENT_ONESHOT);
177 }
178
6a0f1f6d
LP
179 return sd_event_add_time(
180 UNIT(s)->manager->event,
181 &s->timer_event_source,
182 CLOCK_MONOTONIC,
183 now(CLOCK_MONOTONIC) + s->timeout_usec, 0,
184 swap_dispatch_timer, s);
07b0b134
ML
185}
186
173a8d04 187static int swap_add_device_links(Swap *s) {
173a8d04
LP
188 assert(s);
189
190 if (!s->what)
191 return 0;
192
f10af76d
LP
193 if (!s->from_fragment)
194 return 0;
195
cfcfd4ae 196 if (is_device_path(s->what))
ddb7d6b9 197 return unit_add_node_link(UNIT(s), s->what, UNIT(s)->manager->running_as == SYSTEMD_SYSTEM);
cfcfd4ae
LP
198 else
199 /* File based swap devices need to be ordered after
2b93b027 200 * systemd-remount-fs.service, since they might need a
cfcfd4ae 201 * writable file system. */
2b93b027 202 return unit_add_dependency_by_name(UNIT(s), UNIT_AFTER, SPECIAL_REMOUNT_FS_SERVICE, NULL, true);
173a8d04
LP
203}
204
2edd4434 205static int swap_add_default_dependencies(Swap *s) {
2edd4434
LP
206 assert(s);
207
67445f4e 208 if (UNIT(s)->manager->running_as != SYSTEMD_SYSTEM)
6b1dc2bd 209 return 0;
2edd4434 210
c0387ebf
LP
211 if (detect_container(NULL) > 0)
212 return 0;
213
5607d856 214 return unit_add_two_dependencies_by_name(UNIT(s), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true);
2edd4434
LP
215}
216
4e85aff4
LP
217static int swap_verify(Swap *s) {
218 bool b;
7fd1b19b 219 _cleanup_free_ char *e = NULL;
4e85aff4 220
1124fe6f 221 if (UNIT(s)->load_state != UNIT_LOADED)
5bcb0f2b 222 return 0;
4e85aff4 223
170ca19e 224 e = unit_name_from_path(s->what, ".swap");
5bcb0f2b 225 if (!e)
170ca19e 226 return log_oom();
4e85aff4
LP
227
228 b = unit_has_name(UNIT(s), e);
4e85aff4 229 if (!b) {
79008bdd 230 log_unit_error(UNIT(s)->id, "%s: Value of \"What\" and unit name do not match, not loading.", UNIT(s)->id);
4e85aff4
LP
231 return -EINVAL;
232 }
233
4819ff03 234 if (s->exec_context.pam_name && s->kill_context.kill_mode != KILL_CONTROL_GROUP) {
79008bdd 235 log_unit_error(UNIT(s)->id, "%s has PAM enabled. Kill mode must be set to 'control-group'. Refusing to load.", UNIT(s)->id);
e04aad61
LP
236 return -EINVAL;
237 }
238
4e85aff4
LP
239 return 0;
240}
241
9670d583
LP
242static int swap_load_devnode(Swap *s) {
243 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
244 struct stat st;
245 const char *p;
246
247 assert(s);
248
249 if (stat(s->what, &st) < 0 || !S_ISBLK(st.st_mode))
250 return 0;
251
252 d = udev_device_new_from_devnum(UNIT(s)->manager->udev, 'b', st.st_rdev);
253 if (!d)
254 return 0;
255
256 p = udev_device_get_devnode(d);
257 if (!p)
258 return 0;
259
260 return swap_set_devnode(s, p);
261}
262
07b0b134
ML
263static int swap_load(Unit *u) {
264 int r;
265 Swap *s = SWAP(u);
266
267 assert(s);
ac155bb8 268 assert(u->load_state == UNIT_STUB);
07b0b134
ML
269
270 /* Load a .swap file */
646134dc
ZJS
271 r = unit_load_fragment_and_dropin_optional(u);
272 if (r < 0)
07b0b134
ML
273 return r;
274
ac155bb8 275 if (u->load_state == UNIT_LOADED) {
4e85aff4 276
1124fe6f 277 if (UNIT(s)->fragment_path)
4e85aff4
LP
278 s->from_fragment = true;
279
280 if (!s->what) {
281 if (s->parameters_fragment.what)
282 s->what = strdup(s->parameters_fragment.what);
4e85aff4
LP
283 else if (s->parameters_proc_swaps.what)
284 s->what = strdup(s->parameters_proc_swaps.what);
285 else
ac155bb8 286 s->what = unit_name_to_path(u->id);
4e85aff4
LP
287
288 if (!s->what)
07b0b134 289 return -ENOMEM;
4e85aff4 290 }
07b0b134
ML
291
292 path_kill_slashes(s->what);
293
5bcb0f2b
LP
294 if (!UNIT(s)->description) {
295 r = unit_set_description(u, s->what);
296 if (r < 0)
4e85aff4 297 return r;
5bcb0f2b 298 }
4e85aff4 299
a57f7e2c 300 r = unit_require_mounts_for(UNIT(s), s->what);
646134dc 301 if (r < 0)
07b0b134
ML
302 return r;
303
a57f7e2c 304 r = swap_add_device_links(s);
646134dc 305 if (r < 0)
6e2ef85b 306 return r;
07b0b134 307
9670d583
LP
308 r = swap_load_devnode(s);
309 if (r < 0)
310 return r;
311
598459ce
LP
312 r = unit_patch_contexts(u);
313 if (r < 0)
314 return r;
315
316 r = unit_add_exec_dependencies(u, &s->exec_context);
317 if (r < 0)
318 return r;
319
320 r = unit_add_default_slice(u, &s->cgroup_context);
a016b922
LP
321 if (r < 0)
322 return r;
323
646134dc
ZJS
324 if (UNIT(s)->default_dependencies) {
325 r = swap_add_default_dependencies(s);
326 if (r < 0)
2edd4434 327 return r;
646134dc 328 }
07b0b134
ML
329 }
330
331 return swap_verify(s);
332}
333
628c89cc 334static int swap_setup_unit(
4e85aff4
LP
335 Manager *m,
336 const char *what,
e04aad61 337 const char *what_proc_swaps,
4e85aff4 338 int priority,
e04aad61
LP
339 bool set_flags) {
340
7fd1b19b 341 _cleanup_free_ char *e = NULL;
2c7c6144 342 bool delete = false;
5bcb0f2b 343 Unit *u = NULL;
07b0b134 344 int r;
4e85aff4
LP
345 SwapParameters *p;
346
347 assert(m);
348 assert(what);
6b1dc2bd 349 assert(what_proc_swaps);
07b0b134 350
7d17cfbc
MS
351 e = unit_name_from_path(what, ".swap");
352 if (!e)
170ca19e 353 return log_oom();
07b0b134 354
e04aad61
LP
355 u = manager_get_unit(m, e);
356
6b1dc2bd 357 if (u &&
e04aad61 358 SWAP(u)->from_proc_swaps &&
628c89cc
LP
359 !path_equal(SWAP(u)->parameters_proc_swaps.what, what_proc_swaps)) {
360 log_error("Swap %s appeared twice with different device paths %s and %s", e, SWAP(u)->parameters_proc_swaps.what, what_proc_swaps);
e04aad61 361 return -EEXIST;
628c89cc 362 }
4e85aff4
LP
363
364 if (!u) {
07b0b134
ML
365 delete = true;
366
7d17cfbc 367 u = unit_new(m, sizeof(Swap));
170ca19e
ZJS
368 if (!u)
369 return log_oom();
e04aad61 370
7d17cfbc
MS
371 r = unit_add_name(u, e);
372 if (r < 0)
e04aad61
LP
373 goto fail;
374
7d17cfbc
MS
375 SWAP(u)->what = strdup(what);
376 if (!SWAP(u)->what) {
628c89cc 377 r = -ENOMEM;
e04aad61
LP
378 goto fail;
379 }
380
381 unit_add_to_load_queue(u);
4e85aff4
LP
382 } else
383 delete = false;
07b0b134 384
6b1dc2bd 385 p = &SWAP(u)->parameters_proc_swaps;
07b0b134 386
6b1dc2bd 387 if (!p->what) {
5bcb0f2b
LP
388 p->what = strdup(what_proc_swaps);
389 if (!p->what) {
390 r = -ENOMEM;
6b1dc2bd
LP
391 goto fail;
392 }
6b1dc2bd 393 }
e04aad61 394
6b1dc2bd
LP
395 if (set_flags) {
396 SWAP(u)->is_active = true;
397 SWAP(u)->just_activated = !SWAP(u)->from_proc_swaps;
4e85aff4 398 }
07b0b134 399
6b1dc2bd
LP
400 SWAP(u)->from_proc_swaps = true;
401
4e85aff4 402 p->priority = priority;
07b0b134 403
4e85aff4 404 unit_add_to_dbus_queue(u);
07b0b134
ML
405 return 0;
406
407fail:
31938a85 408 log_unit_warning_errno(e, r, "Failed to load swap unit: %m");
e04aad61 409
4e85aff4 410 if (delete && u)
07b0b134
ML
411 unit_free(u);
412
4e85aff4 413 return r;
07b0b134
ML
414}
415
628c89cc 416static int swap_process_new(Manager *m, const char *device, int prio, bool set_flags) {
5bcb0f2b
LP
417 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
418 struct udev_list_entry *item = NULL, *first = NULL;
419 const char *dn;
e04aad61 420 struct stat st;
5bcb0f2b 421 int r;
e04aad61
LP
422
423 assert(m);
424
628c89cc 425 r = swap_setup_unit(m, device, device, prio, set_flags);
5bcb0f2b
LP
426 if (r < 0)
427 return r;
e04aad61 428
5bcb0f2b
LP
429 /* If this is a block device, then let's add duplicates for
430 * all other names of this block device */
431 if (stat(device, &st) < 0 || !S_ISBLK(st.st_mode))
432 return 0;
e04aad61 433
5bcb0f2b
LP
434 d = udev_device_new_from_devnum(m->udev, 'b', st.st_rdev);
435 if (!d)
436 return 0;
e04aad61 437
5bcb0f2b
LP
438 /* Add the main device node */
439 dn = udev_device_get_devnode(d);
440 if (dn && !streq(dn, device))
628c89cc 441 swap_setup_unit(m, dn, device, prio, set_flags);
e04aad61 442
5bcb0f2b
LP
443 /* Add additional units for all symlinks */
444 first = udev_device_get_devlinks_list_entry(d);
445 udev_list_entry_foreach(item, first) {
446 const char *p;
e04aad61 447
5bcb0f2b
LP
448 /* Don't bother with the /dev/block links */
449 p = udev_list_entry_get_name(item);
e04aad61 450
5bcb0f2b
LP
451 if (streq(p, device))
452 continue;
e04aad61 453
5bcb0f2b
LP
454 if (path_startswith(p, "/dev/block/"))
455 continue;
e04aad61 456
5bcb0f2b
LP
457 if (stat(p, &st) >= 0)
458 if (!S_ISBLK(st.st_mode) ||
459 st.st_rdev != udev_device_get_devnum(d))
460 continue;
e04aad61 461
628c89cc 462 swap_setup_unit(m, p, device, prio, set_flags);
e04aad61
LP
463 }
464
e04aad61
LP
465 return r;
466}
467
07b0b134
ML
468static void swap_set_state(Swap *s, SwapState state) {
469 SwapState old_state;
37cf8fee 470 Swap *other;
e04aad61 471
07b0b134
ML
472 assert(s);
473
474 old_state = s->state;
475 s->state = state;
476
e04aad61
LP
477 if (state != SWAP_ACTIVATING &&
478 state != SWAP_ACTIVATING_SIGTERM &&
479 state != SWAP_ACTIVATING_SIGKILL &&
5bcb0f2b 480 state != SWAP_ACTIVATING_DONE &&
e04aad61
LP
481 state != SWAP_DEACTIVATING &&
482 state != SWAP_DEACTIVATING_SIGTERM &&
483 state != SWAP_DEACTIVATING_SIGKILL) {
718db961 484 s->timer_event_source = sd_event_source_unref(s->timer_event_source);
e04aad61
LP
485 swap_unwatch_control_pid(s);
486 s->control_command = NULL;
487 s->control_command_id = _SWAP_EXEC_COMMAND_INVALID;
488 }
489
07b0b134 490 if (state != old_state)
79008bdd 491 log_unit_debug(UNIT(s)->id,
66870f90
ZJS
492 "%s changed %s -> %s",
493 UNIT(s)->id,
494 swap_state_to_string(old_state),
495 swap_state_to_string(state));
07b0b134 496
5bcb0f2b 497 unit_notify(UNIT(s), state_translation_table[old_state], state_translation_table[state], true);
37cf8fee
LP
498
499 /* If there other units for the same device node have a job
500 queued it might be worth checking again if it is runnable
501 now. This is necessary, since swap_start() refuses
502 operation with EAGAIN if there's already another job for
503 the same device node queued. */
504 LIST_FOREACH_OTHERS(same_devnode, other, s)
505 if (UNIT(other)->job)
506 job_add_to_run_queue(UNIT(other)->job);
07b0b134
ML
507}
508
509static int swap_coldplug(Unit *u) {
510 Swap *s = SWAP(u);
511 SwapState new_state = SWAP_DEAD;
e04aad61 512 int r;
07b0b134
ML
513
514 assert(s);
515 assert(s->state == SWAP_DEAD);
516
517 if (s->deserialized_state != s->state)
518 new_state = s->deserialized_state;
4e85aff4 519 else if (s->from_proc_swaps)
07b0b134
ML
520 new_state = SWAP_ACTIVE;
521
5bcb0f2b
LP
522 if (new_state == s->state)
523 return 0;
e04aad61 524
5bcb0f2b
LP
525 if (new_state == SWAP_ACTIVATING ||
526 new_state == SWAP_ACTIVATING_SIGTERM ||
527 new_state == SWAP_ACTIVATING_SIGKILL ||
528 new_state == SWAP_ACTIVATING_DONE ||
529 new_state == SWAP_DEACTIVATING ||
530 new_state == SWAP_DEACTIVATING_SIGTERM ||
531 new_state == SWAP_DEACTIVATING_SIGKILL) {
e04aad61 532
5bcb0f2b
LP
533 if (s->control_pid <= 0)
534 return -EBADMSG;
e04aad61 535
5bcb0f2b
LP
536 r = unit_watch_pid(UNIT(s), s->control_pid);
537 if (r < 0)
538 return r;
e04aad61 539
5bcb0f2b
LP
540 r = swap_arm_timer(s);
541 if (r < 0)
542 return r;
e04aad61 543 }
07b0b134 544
5bcb0f2b 545 swap_set_state(s, new_state);
07b0b134
ML
546 return 0;
547}
548
549static void swap_dump(Unit *u, FILE *f, const char *prefix) {
550 Swap *s = SWAP(u);
4e85aff4 551 SwapParameters *p;
07b0b134
ML
552
553 assert(s);
4e85aff4
LP
554 assert(f);
555
556 if (s->from_proc_swaps)
557 p = &s->parameters_proc_swaps;
558 else if (s->from_fragment)
559 p = &s->parameters_fragment;
b6bfc7bb
LP
560 else
561 p = NULL;
07b0b134
ML
562
563 fprintf(f,
4e85aff4 564 "%sSwap State: %s\n"
e1770af8 565 "%sResult: %s\n"
07b0b134 566 "%sWhat: %s\n"
4e85aff4
LP
567 "%sFrom /proc/swaps: %s\n"
568 "%sFrom fragment: %s\n",
07b0b134 569 prefix, swap_state_to_string(s->state),
e1770af8 570 prefix, swap_result_to_string(s->result),
07b0b134 571 prefix, s->what,
4e85aff4
LP
572 prefix, yes_no(s->from_proc_swaps),
573 prefix, yes_no(s->from_fragment));
e04aad61 574
9670d583
LP
575 if (s->devnode)
576 fprintf(f, "%sDevice Node: %s\n", prefix, s->devnode);
577
b6bfc7bb
LP
578 if (p)
579 fprintf(f,
580 "%sPriority: %i\n"
47cb901e 581 "%sOptions: %s\n",
b6bfc7bb 582 prefix, p->priority,
47cb901e 583 prefix, strempty(p->options));
b6bfc7bb 584
e04aad61
LP
585 if (s->control_pid > 0)
586 fprintf(f,
de0671ee
ZJS
587 "%sControl PID: "PID_FMT"\n",
588 prefix, s->control_pid);
e04aad61
LP
589
590 exec_context_dump(&s->exec_context, f, prefix);
4819ff03 591 kill_context_dump(&s->kill_context, f, prefix);
e04aad61
LP
592}
593
594static int swap_spawn(Swap *s, ExecCommand *c, pid_t *_pid) {
595 pid_t pid;
596 int r;
9fa95f85
DM
597 ExecParameters exec_params = {
598 .apply_permissions = true,
599 .apply_chroot = true,
600 .apply_tty_stdin = true,
601 };
e04aad61
LP
602
603 assert(s);
604 assert(c);
605 assert(_pid);
606
5ad096b3
LP
607 (void) unit_realize_cgroup(UNIT(s));
608 if (s->reset_cpu_usage) {
609 (void) unit_reset_cpu_usage(UNIT(s));
610 s->reset_cpu_usage = false;
611 }
4ad49000 612
613b411c
LP
613 r = unit_setup_exec_runtime(UNIT(s));
614 if (r < 0)
615 goto fail;
616
718db961 617 r = swap_arm_timer(s);
646134dc 618 if (r < 0)
e04aad61
LP
619 goto fail;
620
9fa95f85
DM
621 exec_params.environment = UNIT(s)->manager->environment;
622 exec_params.confirm_spawn = UNIT(s)->manager->confirm_spawn;
623 exec_params.cgroup_supported = UNIT(s)->manager->cgroup_supported;
624 exec_params.cgroup_path = UNIT(s)->cgroup_path;
a931ad47 625 exec_params.cgroup_delegate = s->cgroup_context.delegate;
9fa95f85
DM
626 exec_params.runtime_prefix = manager_get_runtime_prefix(UNIT(s)->manager);
627 exec_params.unit_id = UNIT(s)->id;
628
646134dc 629 r = exec_spawn(c,
646134dc 630 &s->exec_context,
9fa95f85 631 &exec_params,
613b411c 632 s->exec_runtime,
646134dc
ZJS
633 &pid);
634 if (r < 0)
e04aad61
LP
635 goto fail;
636
646134dc
ZJS
637 r = unit_watch_pid(UNIT(s), pid);
638 if (r < 0)
e04aad61
LP
639 /* FIXME: we need to do something here */
640 goto fail;
641
642 *_pid = pid;
643
644 return 0;
645
646fail:
718db961 647 s->timer_event_source = sd_event_source_unref(s->timer_event_source);
e04aad61 648 return r;
07b0b134
ML
649}
650
e1770af8 651static void swap_enter_dead(Swap *s, SwapResult f) {
07b0b134
ML
652 assert(s);
653
e1770af8
LP
654 if (f != SWAP_SUCCESS)
655 s->result = f;
e04aad61 656
613b411c
LP
657 exec_runtime_destroy(s->exec_runtime);
658 s->exec_runtime = exec_runtime_unref(s->exec_runtime);
659
e66cf1a3
LP
660 exec_context_destroy_runtime_directory(&s->exec_context, manager_get_runtime_prefix(UNIT(s)->manager));
661
e1770af8 662 swap_set_state(s, s->result != SWAP_SUCCESS ? SWAP_FAILED : SWAP_DEAD);
07b0b134
ML
663}
664
e1770af8 665static void swap_enter_active(Swap *s, SwapResult f) {
e04aad61
LP
666 assert(s);
667
e1770af8
LP
668 if (f != SWAP_SUCCESS)
669 s->result = f;
e04aad61
LP
670
671 swap_set_state(s, SWAP_ACTIVE);
672}
673
e1770af8 674static void swap_enter_signal(Swap *s, SwapState state, SwapResult f) {
07b0b134
ML
675 int r;
676
677 assert(s);
e04aad61 678
e1770af8
LP
679 if (f != SWAP_SUCCESS)
680 s->result = f;
e04aad61 681
cd2086fe
LP
682 r = unit_kill_context(
683 UNIT(s),
684 &s->kill_context,
db2cb23b
UTL
685 (state != SWAP_ACTIVATING_SIGTERM && state != SWAP_DEACTIVATING_SIGTERM) ?
686 KILL_KILL : KILL_TERMINATE,
cd2086fe
LP
687 -1,
688 s->control_pid,
689 false);
690 if (r < 0)
691 goto fail;
e04aad61 692
cd2086fe 693 if (r > 0) {
718db961 694 r = swap_arm_timer(s);
646134dc 695 if (r < 0)
e04aad61
LP
696 goto fail;
697
698 swap_set_state(s, state);
ac84d1fb
LP
699 } else if (state == SWAP_ACTIVATING_SIGTERM)
700 swap_enter_signal(s, SWAP_ACTIVATING_SIGKILL, SWAP_SUCCESS);
701 else if (state == SWAP_DEACTIVATING_SIGTERM)
702 swap_enter_signal(s, SWAP_DEACTIVATING_SIGKILL, SWAP_SUCCESS);
703 else
e1770af8 704 swap_enter_dead(s, SWAP_SUCCESS);
e04aad61
LP
705
706 return;
707
708fail:
976dec6e 709 log_unit_warning_errno(UNIT(s)->id, r, "%s failed to kill processes: %m", UNIT(s)->id);
e1770af8 710 swap_enter_dead(s, SWAP_FAILURE_RESOURCES);
e04aad61
LP
711}
712
713static void swap_enter_activating(Swap *s) {
47cb901e
LP
714 _cleanup_free_ char *discard = NULL;
715 int r, priority = -1;
e04aad61
LP
716
717 assert(s);
718
719 s->control_command_id = SWAP_EXEC_ACTIVATE;
720 s->control_command = s->exec_command + SWAP_EXEC_ACTIVATE;
07b0b134 721
86b23b07 722 if (s->from_fragment) {
d15d0333
ZJS
723 fstab_filter_options(s->parameters_fragment.options, "discard\0",
724 NULL, &discard, NULL);
47cb901e 725
4e85aff4 726 priority = s->parameters_fragment.priority;
47cb901e 727 if (priority < 0)
d15d0333 728 fstab_find_pri(s->parameters_fragment.options, &priority);
86b23b07
JS
729 }
730
731 r = exec_command_set(s->control_command, "/sbin/swapon", NULL);
732 if (r < 0)
733 goto fail;
4e85aff4 734
e04aad61 735 if (priority >= 0) {
5bcb0f2b 736 char p[DECIMAL_STR_MAX(int)];
07b0b134 737
5bcb0f2b 738 sprintf(p, "%i", priority);
86b23b07
JS
739 r = exec_command_append(s->control_command, "-p", p, NULL);
740 if (r < 0)
741 goto fail;
742 }
07b0b134 743
86b23b07 744 if (discard && !streq(discard, "none")) {
47cb901e 745 const char *discard_arg;
86b23b07 746
47cb901e
LP
747 if (streq(discard, "all"))
748 discard_arg = "--discard";
749 else
63c372cb 750 discard_arg = strjoina("--discard=", discard);
86b23b07
JS
751
752 r = exec_command_append(s->control_command, discard_arg, NULL);
753 if (r < 0)
754 goto fail;
755 }
e04aad61 756
86b23b07 757 r = exec_command_append(s->control_command, s->what, NULL);
e04aad61
LP
758 if (r < 0)
759 goto fail;
760
761 swap_unwatch_control_pid(s);
762
646134dc
ZJS
763 r = swap_spawn(s, s->control_command, &s->control_pid);
764 if (r < 0)
e04aad61
LP
765 goto fail;
766
767 swap_set_state(s, SWAP_ACTIVATING);
768
769 return;
770
771fail:
976dec6e 772 log_unit_warning_errno(UNIT(s)->id, r, "%s failed to run 'swapon' task: %m", UNIT(s)->id);
e1770af8 773 swap_enter_dead(s, SWAP_FAILURE_RESOURCES);
e04aad61
LP
774}
775
e1770af8 776static void swap_enter_deactivating(Swap *s) {
e04aad61
LP
777 int r;
778
779 assert(s);
780
e04aad61
LP
781 s->control_command_id = SWAP_EXEC_DEACTIVATE;
782 s->control_command = s->exec_command + SWAP_EXEC_DEACTIVATE;
783
646134dc 784 r = exec_command_set(s->control_command,
e04aad61
LP
785 "/sbin/swapoff",
786 s->what,
646134dc
ZJS
787 NULL);
788 if (r < 0)
e04aad61
LP
789 goto fail;
790
791 swap_unwatch_control_pid(s);
792
646134dc
ZJS
793 r = swap_spawn(s, s->control_command, &s->control_pid);
794 if (r < 0)
e04aad61
LP
795 goto fail;
796
797 swap_set_state(s, SWAP_DEACTIVATING);
798
799 return;
800
801fail:
976dec6e 802 log_unit_warning_errno(UNIT(s)->id, r, "%s failed to run 'swapoff' task: %m", UNIT(s)->id);
e1770af8 803 swap_enter_active(s, SWAP_FAILURE_RESOURCES);
e04aad61
LP
804}
805
806static int swap_start(Unit *u) {
37cf8fee 807 Swap *s = SWAP(u), *other;
e04aad61
LP
808
809 assert(s);
810
811 /* We cannot fulfill this request right now, try again later
812 * please! */
813
814 if (s->state == SWAP_DEACTIVATING ||
815 s->state == SWAP_DEACTIVATING_SIGTERM ||
816 s->state == SWAP_DEACTIVATING_SIGKILL ||
817 s->state == SWAP_ACTIVATING_SIGTERM ||
818 s->state == SWAP_ACTIVATING_SIGKILL)
819 return -EAGAIN;
820
821 if (s->state == SWAP_ACTIVATING)
822 return 0;
823
824 assert(s->state == SWAP_DEAD || s->state == SWAP_FAILED);
825
a5c3034f
LP
826 if (detect_container(NULL) > 0)
827 return -EPERM;
828
37cf8fee
LP
829 /* If there's a job for another swap unit for the same node
830 * running, then let's not dispatch this one for now, and wait
831 * until that other job has finished. */
832 LIST_FOREACH_OTHERS(same_devnode, other, s)
833 if (UNIT(other)->job && UNIT(other)->job->state == JOB_RUNNING)
834 return -EAGAIN;
835
e1770af8 836 s->result = SWAP_SUCCESS;
5ad096b3
LP
837 s->reset_cpu_usage = true;
838
e04aad61 839 swap_enter_activating(s);
82a2b6bb 840 return 1;
07b0b134
ML
841}
842
843static int swap_stop(Unit *u) {
844 Swap *s = SWAP(u);
07b0b134
ML
845
846 assert(s);
847
e04aad61
LP
848 if (s->state == SWAP_DEACTIVATING ||
849 s->state == SWAP_DEACTIVATING_SIGTERM ||
850 s->state == SWAP_DEACTIVATING_SIGKILL ||
851 s->state == SWAP_ACTIVATING_SIGTERM ||
852 s->state == SWAP_ACTIVATING_SIGKILL)
853 return 0;
07b0b134 854
e04aad61 855 assert(s->state == SWAP_ACTIVATING ||
5bcb0f2b 856 s->state == SWAP_ACTIVATING_DONE ||
e04aad61 857 s->state == SWAP_ACTIVE);
07b0b134 858
a5c3034f
LP
859 if (detect_container(NULL) > 0)
860 return -EPERM;
861
e1770af8 862 swap_enter_deactivating(s);
82a2b6bb 863 return 1;
07b0b134
ML
864}
865
866static int swap_serialize(Unit *u, FILE *f, FDSet *fds) {
867 Swap *s = SWAP(u);
868
869 assert(s);
870 assert(f);
871 assert(fds);
872
873 unit_serialize_item(u, f, "state", swap_state_to_string(s->state));
e1770af8 874 unit_serialize_item(u, f, "result", swap_result_to_string(s->result));
e04aad61
LP
875
876 if (s->control_pid > 0)
de0671ee 877 unit_serialize_item_format(u, f, "control-pid", PID_FMT, s->control_pid);
e04aad61
LP
878
879 if (s->control_command_id >= 0)
880 unit_serialize_item(u, f, "control-command", swap_exec_command_to_string(s->control_command_id));
07b0b134
ML
881
882 return 0;
883}
884
885static int swap_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
886 Swap *s = SWAP(u);
887
888 assert(s);
889 assert(fds);
890
891 if (streq(key, "state")) {
892 SwapState state;
893
646134dc
ZJS
894 state = swap_state_from_string(value);
895 if (state < 0)
79008bdd 896 log_unit_debug(u->id, "Failed to parse state value %s", value);
07b0b134
ML
897 else
898 s->deserialized_state = state;
e1770af8
LP
899 } else if (streq(key, "result")) {
900 SwapResult f;
901
902 f = swap_result_from_string(value);
903 if (f < 0)
79008bdd 904 log_unit_debug(u->id, "Failed to parse result value %s", value);
e1770af8
LP
905 else if (f != SWAP_SUCCESS)
906 s->result = f;
e04aad61
LP
907 } else if (streq(key, "control-pid")) {
908 pid_t pid;
909
910 if (parse_pid(value, &pid) < 0)
79008bdd 911 log_unit_debug(u->id, "Failed to parse control-pid value %s", value);
e04aad61
LP
912 else
913 s->control_pid = pid;
914
915 } else if (streq(key, "control-command")) {
916 SwapExecCommand id;
917
646134dc
ZJS
918 id = swap_exec_command_from_string(value);
919 if (id < 0)
79008bdd 920 log_unit_debug(u->id, "Failed to parse exec-command value %s", value);
e04aad61
LP
921 else {
922 s->control_command_id = id;
923 s->control_command = s->exec_command + id;
924 }
07b0b134 925 } else
79008bdd 926 log_unit_debug(u->id, "Unknown serialization key '%s'", key);
07b0b134
ML
927
928 return 0;
929}
930
44a6b1b6 931_pure_ static UnitActiveState swap_active_state(Unit *u) {
07b0b134
ML
932 assert(u);
933
934 return state_translation_table[SWAP(u)->state];
935}
936
44a6b1b6 937_pure_ static const char *swap_sub_state_to_string(Unit *u) {
07b0b134
ML
938 assert(u);
939
940 return swap_state_to_string(SWAP(u)->state);
941}
942
44a6b1b6 943_pure_ static bool swap_check_gc(Unit *u) {
07b0b134
ML
944 Swap *s = SWAP(u);
945
946 assert(s);
947
6b1dc2bd 948 return s->from_proc_swaps;
07b0b134
ML
949}
950
e04aad61
LP
951static void swap_sigchld_event(Unit *u, pid_t pid, int code, int status) {
952 Swap *s = SWAP(u);
e1770af8 953 SwapResult f;
e04aad61
LP
954
955 assert(s);
956 assert(pid >= 0);
957
958 if (pid != s->control_pid)
959 return;
960
961 s->control_pid = 0;
962
96342de6 963 if (is_clean_exit(code, status, NULL))
e1770af8
LP
964 f = SWAP_SUCCESS;
965 else if (code == CLD_EXITED)
966 f = SWAP_FAILURE_EXIT_CODE;
967 else if (code == CLD_KILLED)
968 f = SWAP_FAILURE_SIGNAL;
969 else if (code == CLD_DUMPED)
970 f = SWAP_FAILURE_CORE_DUMP;
971 else
972 assert_not_reached("Unknown code");
973
974 if (f != SWAP_SUCCESS)
975 s->result = f;
e04aad61
LP
976
977 if (s->control_command) {
6ea832a2 978 exec_status_exit(&s->control_command->exec_status, &s->exec_context, pid, code, status);
e1770af8 979
e04aad61
LP
980 s->control_command = NULL;
981 s->control_command_id = _SWAP_EXEC_COMMAND_INVALID;
982 }
983
79008bdd
LP
984 log_unit_full(u->id,
985 f == SWAP_SUCCESS ? LOG_DEBUG : LOG_NOTICE,
66870f90
ZJS
986 "%s swap process exited, code=%s status=%i",
987 u->id, sigchld_code_to_string(code), status);
e04aad61
LP
988
989 switch (s->state) {
990
991 case SWAP_ACTIVATING:
5bcb0f2b 992 case SWAP_ACTIVATING_DONE:
e04aad61
LP
993 case SWAP_ACTIVATING_SIGTERM:
994 case SWAP_ACTIVATING_SIGKILL:
995
e1770af8
LP
996 if (f == SWAP_SUCCESS)
997 swap_enter_active(s, f);
e04aad61 998 else
e1770af8 999 swap_enter_dead(s, f);
e04aad61
LP
1000 break;
1001
1002 case SWAP_DEACTIVATING:
1003 case SWAP_DEACTIVATING_SIGKILL:
1004 case SWAP_DEACTIVATING_SIGTERM:
1005
7bb01eff 1006 swap_enter_dead(s, f);
e04aad61
LP
1007 break;
1008
1009 default:
1010 assert_not_reached("Uh, control process died at wrong time.");
1011 }
1012
1013 /* Notify clients about changed exit status */
1014 unit_add_to_dbus_queue(u);
e04aad61
LP
1015}
1016
718db961
LP
1017static int swap_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) {
1018 Swap *s = SWAP(userdata);
e04aad61
LP
1019
1020 assert(s);
718db961 1021 assert(s->timer_event_source == source);
e04aad61
LP
1022
1023 switch (s->state) {
1024
1025 case SWAP_ACTIVATING:
5bcb0f2b 1026 case SWAP_ACTIVATING_DONE:
79008bdd 1027 log_unit_warning(UNIT(s)->id, "%s activation timed out. Stopping.", UNIT(s)->id);
e1770af8 1028 swap_enter_signal(s, SWAP_ACTIVATING_SIGTERM, SWAP_FAILURE_TIMEOUT);
e04aad61
LP
1029 break;
1030
1031 case SWAP_DEACTIVATING:
79008bdd 1032 log_unit_warning(UNIT(s)->id, "%s deactivation timed out. Stopping.", UNIT(s)->id);
e1770af8 1033 swap_enter_signal(s, SWAP_DEACTIVATING_SIGTERM, SWAP_FAILURE_TIMEOUT);
e04aad61
LP
1034 break;
1035
1036 case SWAP_ACTIVATING_SIGTERM:
4819ff03 1037 if (s->kill_context.send_sigkill) {
79008bdd 1038 log_unit_warning(UNIT(s)->id, "%s activation timed out. Killing.", UNIT(s)->id);
e1770af8 1039 swap_enter_signal(s, SWAP_ACTIVATING_SIGKILL, SWAP_FAILURE_TIMEOUT);
ba035df2 1040 } else {
79008bdd 1041 log_unit_warning(UNIT(s)->id, "%s activation timed out. Skipping SIGKILL. Ignoring.", UNIT(s)->id);
e1770af8 1042 swap_enter_dead(s, SWAP_FAILURE_TIMEOUT);
ba035df2 1043 }
e04aad61
LP
1044 break;
1045
1046 case SWAP_DEACTIVATING_SIGTERM:
4819ff03 1047 if (s->kill_context.send_sigkill) {
79008bdd 1048 log_unit_warning(UNIT(s)->id, "%s deactivation timed out. Killing.", UNIT(s)->id);
e1770af8 1049 swap_enter_signal(s, SWAP_DEACTIVATING_SIGKILL, SWAP_FAILURE_TIMEOUT);
ba035df2 1050 } else {
79008bdd 1051 log_unit_warning(UNIT(s)->id, "%s deactivation timed out. Skipping SIGKILL. Ignoring.", UNIT(s)->id);
e1770af8 1052 swap_enter_dead(s, SWAP_FAILURE_TIMEOUT);
ba035df2 1053 }
e04aad61
LP
1054 break;
1055
1056 case SWAP_ACTIVATING_SIGKILL:
1057 case SWAP_DEACTIVATING_SIGKILL:
79008bdd 1058 log_unit_warning(UNIT(s)->id, "%s swap process still around after SIGKILL. Ignoring.", UNIT(s)->id);
e1770af8 1059 swap_enter_dead(s, SWAP_FAILURE_TIMEOUT);
e04aad61
LP
1060 break;
1061
1062 default:
1063 assert_not_reached("Timeout at wrong time.");
1064 }
718db961
LP
1065
1066 return 0;
e04aad61
LP
1067}
1068
1069static int swap_load_proc_swaps(Manager *m, bool set_flags) {
1070 unsigned i;
1071 int r = 0;
1072
1073 assert(m);
1074
07b0b134 1075 rewind(m->proc_swaps);
bab45044 1076
4e85aff4 1077 (void) fscanf(m->proc_swaps, "%*s %*s %*s %*s %*s\n");
07b0b134 1078
e04aad61 1079 for (i = 1;; i++) {
9fb3675e 1080 _cleanup_free_ char *dev = NULL, *d = NULL;
07b0b134
ML
1081 int prio = 0, k;
1082
646134dc
ZJS
1083 k = fscanf(m->proc_swaps,
1084 "%ms " /* device/file */
1085 "%*s " /* type of swap */
1086 "%*s " /* swap size */
1087 "%*s " /* used */
1088 "%i\n", /* priority */
1089 &dev, &prio);
1090 if (k != 2) {
07b0b134 1091 if (k == EOF)
4e85aff4 1092 break;
07b0b134 1093
628c89cc 1094 log_warning("Failed to parse /proc/swaps:%u.", i);
e04aad61 1095 continue;
07b0b134 1096 }
07b0b134 1097
4e85aff4 1098 d = cunescape(dev);
4e85aff4 1099 if (!d)
628c89cc
LP
1100 return log_oom();
1101
1102 device_found_node(m, d, true, DEVICE_FOUND_SWAP, set_flags);
4e85aff4 1103
628c89cc 1104 k = swap_process_new(m, d, prio, set_flags);
07b0b134 1105 if (k < 0)
e04aad61 1106 r = k;
07b0b134
ML
1107 }
1108
e04aad61
LP
1109 return r;
1110}
1111
718db961
LP
1112static int swap_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
1113 Manager *m = userdata;
595ed347 1114 Unit *u;
4e434314
LP
1115 int r;
1116
1117 assert(m);
718db961 1118 assert(revents & EPOLLPRI);
4e434314 1119
646134dc
ZJS
1120 r = swap_load_proc_swaps(m, true);
1121 if (r < 0) {
da927ba9 1122 log_error_errno(r, "Failed to reread /proc/swaps: %m");
e04aad61
LP
1123
1124 /* Reset flags, just in case, for late calls */
595ed347
MS
1125 LIST_FOREACH(units_by_type, u, m->units_by_type[UNIT_SWAP]) {
1126 Swap *swap = SWAP(u);
e04aad61
LP
1127
1128 swap->is_active = swap->just_activated = false;
1129 }
1130
1131 return 0;
1132 }
1133
1134 manager_dispatch_load_queue(m);
1135
595ed347
MS
1136 LIST_FOREACH(units_by_type, u, m->units_by_type[UNIT_SWAP]) {
1137 Swap *swap = SWAP(u);
e04aad61
LP
1138
1139 if (!swap->is_active) {
1140 /* This has just been deactivated */
1141
e04aad61
LP
1142 swap_unset_proc_swaps(swap);
1143
1144 switch (swap->state) {
1145
1146 case SWAP_ACTIVE:
e1770af8 1147 swap_enter_dead(swap, SWAP_SUCCESS);
e04aad61
LP
1148 break;
1149
1150 default:
5bcb0f2b 1151 /* Fire again */
e04aad61
LP
1152 swap_set_state(swap, swap->state);
1153 break;
1154 }
1155
628c89cc
LP
1156 if (swap->what)
1157 device_found_node(m, swap->what, false, DEVICE_FOUND_SWAP, true);
1158
e04aad61
LP
1159 } else if (swap->just_activated) {
1160
1161 /* New swap entry */
1162
1163 switch (swap->state) {
1164
1165 case SWAP_DEAD:
1166 case SWAP_FAILED:
e1770af8 1167 swap_enter_active(swap, SWAP_SUCCESS);
e04aad61
LP
1168 break;
1169
5bcb0f2b
LP
1170 case SWAP_ACTIVATING:
1171 swap_set_state(swap, SWAP_ACTIVATING_DONE);
1172 break;
1173
e04aad61
LP
1174 default:
1175 /* Nothing really changed, but let's
1176 * issue an notification call
1177 * nonetheless, in case somebody is
1178 * waiting for this. */
1179 swap_set_state(swap, swap->state);
1180 break;
1181 }
1182 }
1183
1184 /* Reset the flags for later calls */
1185 swap->is_active = swap->just_activated = false;
1186 }
1187
1188 return 1;
1189}
1190
1191static Unit *swap_following(Unit *u) {
1192 Swap *s = SWAP(u);
1193 Swap *other, *first = NULL;
1194
1195 assert(s);
1196
cdc89820
ZJS
1197 /* If the user configured the swap through /etc/fstab or
1198 * a device unit, follow that. */
1199
1200 if (s->from_fragment)
e04aad61
LP
1201 return NULL;
1202
caac2704 1203 LIST_FOREACH_OTHERS(same_devnode, other, s)
cdc89820
ZJS
1204 if (other->from_fragment)
1205 return UNIT(other);
1206
1207 /* Otherwise make everybody follow the unit that's named after
1208 * the swap device in the kernel */
1209
1210 if (streq_ptr(s->what, s->devnode))
1211 return NULL;
e04aad61 1212
9670d583
LP
1213 LIST_FOREACH_AFTER(same_devnode, other, s)
1214 if (streq_ptr(other->what, other->devnode))
e04aad61
LP
1215 return UNIT(other);
1216
9670d583
LP
1217 LIST_FOREACH_BEFORE(same_devnode, other, s) {
1218 if (streq_ptr(other->what, other->devnode))
e04aad61
LP
1219 return UNIT(other);
1220
1221 first = other;
1222 }
1223
cdc89820 1224 /* Fall back to the first on the list */
e04aad61 1225 return UNIT(first);
07b0b134
ML
1226}
1227
6210e7fc 1228static int swap_following_set(Unit *u, Set **_set) {
5bcb0f2b 1229 Swap *s = SWAP(u), *other;
6210e7fc
LP
1230 Set *set;
1231 int r;
1232
1233 assert(s);
1234 assert(_set);
1235
9670d583 1236 if (LIST_JUST_US(same_devnode, s)) {
6210e7fc
LP
1237 *_set = NULL;
1238 return 0;
1239 }
1240
d5099efc 1241 set = set_new(NULL);
5bcb0f2b 1242 if (!set)
6210e7fc
LP
1243 return -ENOMEM;
1244
caac2704 1245 LIST_FOREACH_OTHERS(same_devnode, other, s) {
5bcb0f2b
LP
1246 r = set_put(set, other);
1247 if (r < 0)
6210e7fc 1248 goto fail;
5bcb0f2b 1249 }
6210e7fc
LP
1250
1251 *_set = set;
1252 return 1;
1253
1254fail:
1255 set_free(set);
1256 return r;
1257}
1258
07b0b134
ML
1259static void swap_shutdown(Manager *m) {
1260 assert(m);
1261
718db961
LP
1262 m->swap_event_source = sd_event_source_unref(m->swap_event_source);
1263
07b0b134
ML
1264 if (m->proc_swaps) {
1265 fclose(m->proc_swaps);
1266 m->proc_swaps = NULL;
1267 }
e04aad61 1268
9670d583
LP
1269 hashmap_free(m->swaps_by_devnode);
1270 m->swaps_by_devnode = NULL;
07b0b134
ML
1271}
1272
07b0b134
ML
1273static int swap_enumerate(Manager *m) {
1274 int r;
9670d583 1275
07b0b134
ML
1276 assert(m);
1277
4e434314 1278 if (!m->proc_swaps) {
646134dc
ZJS
1279 m->proc_swaps = fopen("/proc/swaps", "re");
1280 if (!m->proc_swaps)
718db961 1281 return errno == ENOENT ? 0 : -errno;
4e434314 1282
151b9b96 1283 r = sd_event_add_io(m->event, &m->swap_event_source, fileno(m->proc_swaps), EPOLLPRI, swap_dispatch_io, m);
718db961 1284 if (r < 0)
29083707
LP
1285 goto fail;
1286
1287 /* Dispatch this before we dispatch SIGCHLD, so that
1288 * we always get the events from /proc/swaps before
1289 * the SIGCHLD of /sbin/swapon. */
1290 r = sd_event_source_set_priority(m->swap_event_source, -10);
1291 if (r < 0)
718db961 1292 goto fail;
4e434314
LP
1293 }
1294
646134dc
ZJS
1295 r = swap_load_proc_swaps(m, false);
1296 if (r < 0)
718db961
LP
1297 goto fail;
1298
1299 return 0;
07b0b134 1300
718db961
LP
1301fail:
1302 swap_shutdown(m);
07b0b134
ML
1303 return r;
1304}
1305
628c89cc 1306int swap_process_device_new(Manager *m, struct udev_device *dev) {
9670d583
LP
1307 struct udev_list_entry *item = NULL, *first = NULL;
1308 _cleanup_free_ char *e = NULL;
1309 const char *dn;
1310 Swap *s;
1311 int r = 0;
1312
1313 assert(m);
1314 assert(dev);
1315
1316 dn = udev_device_get_devnode(dev);
1317 if (!dn)
1318 return 0;
1319
1320 e = unit_name_from_path(dn, ".swap");
1321 if (!e)
1322 return -ENOMEM;
1323
1324 s = hashmap_get(m->units, e);
1325 if (s)
1326 r = swap_set_devnode(s, dn);
1327
1328 first = udev_device_get_devlinks_list_entry(dev);
1329 udev_list_entry_foreach(item, first) {
1330 _cleanup_free_ char *n = NULL;
1331
1332 n = unit_name_from_path(udev_list_entry_get_name(item), ".swap");
1333 if (!n)
1334 return -ENOMEM;
1335
1336 s = hashmap_get(m->units, n);
1337 if (s) {
1338 int q;
1339
1340 q = swap_set_devnode(s, dn);
1341 if (q < 0)
1342 r = q;
1343 }
1344 }
1345
1346 return r;
1347}
1348
628c89cc 1349int swap_process_device_remove(Manager *m, struct udev_device *dev) {
9670d583
LP
1350 const char *dn;
1351 int r = 0;
1352 Swap *s;
1353
1354 dn = udev_device_get_devnode(dev);
1355 if (!dn)
1356 return 0;
1357
1358 while ((s = hashmap_get(m->swaps_by_devnode, dn))) {
1359 int q;
1360
1361 q = swap_set_devnode(s, NULL);
1362 if (q < 0)
1363 r = q;
1364 }
1365
1366 return r;
1367}
1368
fdf20a31 1369static void swap_reset_failed(Unit *u) {
5632e374
LP
1370 Swap *s = SWAP(u);
1371
1372 assert(s);
1373
fdf20a31 1374 if (s->state == SWAP_FAILED)
5632e374 1375 swap_set_state(s, SWAP_DEAD);
e04aad61 1376
e1770af8 1377 s->result = SWAP_SUCCESS;
5632e374
LP
1378}
1379
718db961 1380static int swap_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
814cc562 1381 return unit_kill_common(u, who, signo, -1, SWAP(u)->control_pid, error);
8a0867d6
LP
1382}
1383
68db7a3b
ZJS
1384static int swap_get_timeout(Unit *u, uint64_t *timeout) {
1385 Swap *s = SWAP(u);
1386 int r;
1387
1388 if (!s->timer_event_source)
1389 return 0;
1390
1391 r = sd_event_source_get_time(s->timer_event_source, timeout);
1392 if (r < 0)
1393 return r;
1394
1395 return 1;
1396}
1397
0faacd47
LP
1398static bool swap_supported(Manager *m) {
1399 static int supported = -1;
1400
1401 /* If swap support is not available in the kernel, or we are
1402 * running in a container we don't support swap units, and any
1403 * attempts to starting one should fail immediately. */
1404
1405 if (supported < 0)
1406 supported =
1407 access("/proc/swaps", F_OK) >= 0 &&
1408 detect_container(NULL) <= 0;
1409
1410 return supported;
1411}
1412
5632e374
LP
1413static const char* const swap_state_table[_SWAP_STATE_MAX] = {
1414 [SWAP_DEAD] = "dead",
e04aad61 1415 [SWAP_ACTIVATING] = "activating",
5bcb0f2b 1416 [SWAP_ACTIVATING_DONE] = "activating-done",
5632e374 1417 [SWAP_ACTIVE] = "active",
e04aad61
LP
1418 [SWAP_DEACTIVATING] = "deactivating",
1419 [SWAP_ACTIVATING_SIGTERM] = "activating-sigterm",
1420 [SWAP_ACTIVATING_SIGKILL] = "activating-sigkill",
1421 [SWAP_DEACTIVATING_SIGTERM] = "deactivating-sigterm",
1422 [SWAP_DEACTIVATING_SIGKILL] = "deactivating-sigkill",
fdf20a31 1423 [SWAP_FAILED] = "failed"
5632e374
LP
1424};
1425
1426DEFINE_STRING_TABLE_LOOKUP(swap_state, SwapState);
1427
e04aad61
LP
1428static const char* const swap_exec_command_table[_SWAP_EXEC_COMMAND_MAX] = {
1429 [SWAP_EXEC_ACTIVATE] = "ExecActivate",
1430 [SWAP_EXEC_DEACTIVATE] = "ExecDeactivate",
1431};
1432
1433DEFINE_STRING_TABLE_LOOKUP(swap_exec_command, SwapExecCommand);
1434
e1770af8
LP
1435static const char* const swap_result_table[_SWAP_RESULT_MAX] = {
1436 [SWAP_SUCCESS] = "success",
1437 [SWAP_FAILURE_RESOURCES] = "resources",
1438 [SWAP_FAILURE_TIMEOUT] = "timeout",
1439 [SWAP_FAILURE_EXIT_CODE] = "exit-code",
1440 [SWAP_FAILURE_SIGNAL] = "signal",
1441 [SWAP_FAILURE_CORE_DUMP] = "core-dump"
1442};
1443
1444DEFINE_STRING_TABLE_LOOKUP(swap_result, SwapResult);
1445
07b0b134 1446const UnitVTable swap_vtable = {
7d17cfbc 1447 .object_size = sizeof(Swap),
718db961
LP
1448 .exec_context_offset = offsetof(Swap, exec_context),
1449 .cgroup_context_offset = offsetof(Swap, cgroup_context),
1450 .kill_context_offset = offsetof(Swap, kill_context),
613b411c 1451 .exec_runtime_offset = offsetof(Swap, exec_runtime),
3ef63c31 1452
f975e971
LP
1453 .sections =
1454 "Unit\0"
1455 "Swap\0"
1456 "Install\0",
4ad49000 1457 .private_section = "Swap",
71645aca 1458
e04aad61 1459 .no_alias = true,
07b0b134
ML
1460 .no_instances = true,
1461
4e85aff4 1462 .init = swap_init,
07b0b134 1463 .load = swap_load,
6e620bec 1464 .done = swap_done,
07b0b134
ML
1465
1466 .coldplug = swap_coldplug,
1467
1468 .dump = swap_dump,
1469
1470 .start = swap_start,
1471 .stop = swap_stop,
1472
8a0867d6
LP
1473 .kill = swap_kill,
1474
68db7a3b
ZJS
1475 .get_timeout = swap_get_timeout,
1476
07b0b134
ML
1477 .serialize = swap_serialize,
1478 .deserialize_item = swap_deserialize_item,
1479
1480 .active_state = swap_active_state,
1481 .sub_state_to_string = swap_sub_state_to_string,
1482
1483 .check_gc = swap_check_gc,
1484
e04aad61 1485 .sigchld_event = swap_sigchld_event,
e04aad61
LP
1486
1487 .reset_failed = swap_reset_failed,
1488
c4e2ceae 1489 .bus_interface = "org.freedesktop.systemd1.Swap",
718db961 1490 .bus_vtable = bus_swap_vtable,
74c964d3
LP
1491 .bus_set_property = bus_swap_set_property,
1492 .bus_commit_properties = bus_swap_commit_properties,
07b0b134 1493
e04aad61 1494 .following = swap_following,
6210e7fc 1495 .following_set = swap_following_set,
5632e374 1496
6e620bec 1497 .enumerate = swap_enumerate,
c6918296 1498 .shutdown = swap_shutdown,
0faacd47 1499 .supported = swap_supported,
c6918296
MS
1500
1501 .status_message_formats = {
1502 .starting_stopping = {
1503 [0] = "Activating swap %s...",
1504 [1] = "Deactivating swap %s...",
1505 },
1506 .finished_start_job = {
1507 [JOB_DONE] = "Activated swap %s.",
1508 [JOB_FAILED] = "Failed to activate swap %s.",
1509 [JOB_DEPENDENCY] = "Dependency failed for %s.",
1510 [JOB_TIMEOUT] = "Timed out activating swap %s.",
1511 },
1512 .finished_stop_job = {
1513 [JOB_DONE] = "Deactivated swap %s.",
1514 [JOB_FAILED] = "Failed deactivating swap %s.",
1515 [JOB_TIMEOUT] = "Timed out deactivating swap %s.",
1516 },
1517 },
07b0b134 1518};