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