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