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