]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/swap.c
update TODO
[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
151b9b96 187 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
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);
ac84d1fb
LP
715 } else if (state == SWAP_ACTIVATING_SIGTERM)
716 swap_enter_signal(s, SWAP_ACTIVATING_SIGKILL, SWAP_SUCCESS);
717 else if (state == SWAP_DEACTIVATING_SIGTERM)
718 swap_enter_signal(s, SWAP_DEACTIVATING_SIGKILL, SWAP_SUCCESS);
719 else
e1770af8 720 swap_enter_dead(s, SWAP_SUCCESS);
e04aad61
LP
721
722 return;
723
724fail:
66870f90
ZJS
725 log_warning_unit(UNIT(s)->id,
726 "%s failed to kill processes: %s", UNIT(s)->id, strerror(-r));
e04aad61 727
e1770af8 728 swap_enter_dead(s, SWAP_FAILURE_RESOURCES);
e04aad61
LP
729}
730
731static void swap_enter_activating(Swap *s) {
732 int r, priority;
733
734 assert(s);
735
736 s->control_command_id = SWAP_EXEC_ACTIVATE;
737 s->control_command = s->exec_command + SWAP_EXEC_ACTIVATE;
07b0b134 738
4e85aff4
LP
739 if (s->from_fragment)
740 priority = s->parameters_fragment.priority;
e04aad61
LP
741 else
742 priority = -1;
4e85aff4 743
e04aad61 744 if (priority >= 0) {
5bcb0f2b 745 char p[DECIMAL_STR_MAX(int)];
07b0b134 746
5bcb0f2b 747 sprintf(p, "%i", priority);
07b0b134 748
e04aad61
LP
749 r = exec_command_set(
750 s->control_command,
751 "/sbin/swapon",
752 "-p",
753 p,
754 s->what,
755 NULL);
756 } else
757 r = exec_command_set(
758 s->control_command,
759 "/sbin/swapon",
760 s->what,
761 NULL);
762
763 if (r < 0)
764 goto fail;
765
766 swap_unwatch_control_pid(s);
767
646134dc
ZJS
768 r = swap_spawn(s, s->control_command, &s->control_pid);
769 if (r < 0)
e04aad61
LP
770 goto fail;
771
772 swap_set_state(s, SWAP_ACTIVATING);
773
774 return;
775
776fail:
66870f90
ZJS
777 log_warning_unit(UNIT(s)->id,
778 "%s failed to run 'swapon' task: %s",
779 UNIT(s)->id, strerror(-r));
e1770af8 780 swap_enter_dead(s, SWAP_FAILURE_RESOURCES);
e04aad61
LP
781}
782
e1770af8 783static void swap_enter_deactivating(Swap *s) {
e04aad61
LP
784 int r;
785
786 assert(s);
787
e04aad61
LP
788 s->control_command_id = SWAP_EXEC_DEACTIVATE;
789 s->control_command = s->exec_command + SWAP_EXEC_DEACTIVATE;
790
646134dc 791 r = exec_command_set(s->control_command,
e04aad61
LP
792 "/sbin/swapoff",
793 s->what,
646134dc
ZJS
794 NULL);
795 if (r < 0)
e04aad61
LP
796 goto fail;
797
798 swap_unwatch_control_pid(s);
799
646134dc
ZJS
800 r = swap_spawn(s, s->control_command, &s->control_pid);
801 if (r < 0)
e04aad61
LP
802 goto fail;
803
804 swap_set_state(s, SWAP_DEACTIVATING);
805
806 return;
807
808fail:
66870f90
ZJS
809 log_warning_unit(UNIT(s)->id,
810 "%s failed to run 'swapoff' task: %s",
811 UNIT(s)->id, strerror(-r));
e1770af8 812 swap_enter_active(s, SWAP_FAILURE_RESOURCES);
e04aad61
LP
813}
814
815static int swap_start(Unit *u) {
816 Swap *s = SWAP(u);
817
818 assert(s);
819
820 /* We cannot fulfill this request right now, try again later
821 * please! */
822
823 if (s->state == SWAP_DEACTIVATING ||
824 s->state == SWAP_DEACTIVATING_SIGTERM ||
825 s->state == SWAP_DEACTIVATING_SIGKILL ||
826 s->state == SWAP_ACTIVATING_SIGTERM ||
827 s->state == SWAP_ACTIVATING_SIGKILL)
828 return -EAGAIN;
829
830 if (s->state == SWAP_ACTIVATING)
831 return 0;
832
833 assert(s->state == SWAP_DEAD || s->state == SWAP_FAILED);
834
a5c3034f
LP
835 if (detect_container(NULL) > 0)
836 return -EPERM;
837
e1770af8 838 s->result = SWAP_SUCCESS;
e04aad61 839 swap_enter_activating(s);
07b0b134
ML
840 return 0;
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);
07b0b134
ML
863 return 0;
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)
877 unit_serialize_item_format(u, f, "control-pid", "%lu", (unsigned long) s->control_pid);
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)
66870f90 896 log_debug_unit(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)
66870f90 904 log_debug_unit(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)
66870f90 911 log_debug_unit(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)
66870f90 920 log_debug_unit(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
66870f90 926 log_debug_unit(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
66870f90
ZJS
984 log_full_unit(f == SWAP_SUCCESS ? LOG_DEBUG : LOG_NOTICE,
985 u->id,
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:
718db961 1027 log_warning_unit(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:
718db961 1032 log_warning_unit(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) {
718db961 1038 log_warning_unit(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 {
718db961 1041 log_warning_unit(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) {
718db961 1048 log_warning_unit(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 {
718db961 1051 log_warning_unit(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:
718db961 1058 log_warning_unit(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) {
e04aad61
LP
1120 log_error("Failed to reread /proc/swaps: %s", strerror(-r));
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
9670d583 1192 if (streq_ptr(s->what, s->devnode))
e04aad61
LP
1193 return NULL;
1194
1195 /* Make everybody follow the unit that's named after the swap
1196 * device in the kernel */
1197
9670d583
LP
1198 LIST_FOREACH_AFTER(same_devnode, other, s)
1199 if (streq_ptr(other->what, other->devnode))
e04aad61
LP
1200 return UNIT(other);
1201
9670d583
LP
1202 LIST_FOREACH_BEFORE(same_devnode, other, s) {
1203 if (streq_ptr(other->what, other->devnode))
e04aad61
LP
1204 return UNIT(other);
1205
1206 first = other;
1207 }
1208
1209 return UNIT(first);
07b0b134
ML
1210}
1211
6210e7fc 1212static int swap_following_set(Unit *u, Set **_set) {
5bcb0f2b 1213 Swap *s = SWAP(u), *other;
6210e7fc
LP
1214 Set *set;
1215 int r;
1216
1217 assert(s);
1218 assert(_set);
1219
9670d583 1220 if (LIST_JUST_US(same_devnode, s)) {
6210e7fc
LP
1221 *_set = NULL;
1222 return 0;
1223 }
1224
5bcb0f2b
LP
1225 set = set_new(NULL, NULL);
1226 if (!set)
6210e7fc
LP
1227 return -ENOMEM;
1228
9670d583 1229 LIST_FOREACH_AFTER(same_devnode, other, s) {
5bcb0f2b
LP
1230 r = set_put(set, other);
1231 if (r < 0)
6210e7fc 1232 goto fail;
5bcb0f2b 1233 }
6210e7fc 1234
9670d583 1235 LIST_FOREACH_BEFORE(same_devnode, other, s) {
5bcb0f2b
LP
1236 r = set_put(set, other);
1237 if (r < 0)
6210e7fc 1238 goto fail;
5bcb0f2b 1239 }
6210e7fc
LP
1240
1241 *_set = set;
1242 return 1;
1243
1244fail:
1245 set_free(set);
1246 return r;
1247}
1248
07b0b134
ML
1249static void swap_shutdown(Manager *m) {
1250 assert(m);
1251
718db961
LP
1252 m->swap_event_source = sd_event_source_unref(m->swap_event_source);
1253
07b0b134
ML
1254 if (m->proc_swaps) {
1255 fclose(m->proc_swaps);
1256 m->proc_swaps = NULL;
1257 }
e04aad61 1258
9670d583
LP
1259 hashmap_free(m->swaps_by_devnode);
1260 m->swaps_by_devnode = NULL;
07b0b134
ML
1261}
1262
07b0b134
ML
1263static int swap_enumerate(Manager *m) {
1264 int r;
9670d583 1265
07b0b134
ML
1266 assert(m);
1267
4e434314 1268 if (!m->proc_swaps) {
646134dc
ZJS
1269 m->proc_swaps = fopen("/proc/swaps", "re");
1270 if (!m->proc_swaps)
718db961 1271 return errno == ENOENT ? 0 : -errno;
4e434314 1272
151b9b96 1273 r = sd_event_add_io(m->event, &m->swap_event_source, fileno(m->proc_swaps), EPOLLPRI, swap_dispatch_io, m);
718db961 1274 if (r < 0)
29083707
LP
1275 goto fail;
1276
1277 /* Dispatch this before we dispatch SIGCHLD, so that
1278 * we always get the events from /proc/swaps before
1279 * the SIGCHLD of /sbin/swapon. */
1280 r = sd_event_source_set_priority(m->swap_event_source, -10);
1281 if (r < 0)
718db961 1282 goto fail;
4e434314
LP
1283 }
1284
646134dc
ZJS
1285 r = swap_load_proc_swaps(m, false);
1286 if (r < 0)
718db961
LP
1287 goto fail;
1288
1289 return 0;
07b0b134 1290
718db961
LP
1291fail:
1292 swap_shutdown(m);
07b0b134
ML
1293 return r;
1294}
1295
9670d583
LP
1296int swap_process_new_device(Manager *m, struct udev_device *dev) {
1297 struct udev_list_entry *item = NULL, *first = NULL;
1298 _cleanup_free_ char *e = NULL;
1299 const char *dn;
1300 Swap *s;
1301 int r = 0;
1302
1303 assert(m);
1304 assert(dev);
1305
1306 dn = udev_device_get_devnode(dev);
1307 if (!dn)
1308 return 0;
1309
1310 e = unit_name_from_path(dn, ".swap");
1311 if (!e)
1312 return -ENOMEM;
1313
1314 s = hashmap_get(m->units, e);
1315 if (s)
1316 r = swap_set_devnode(s, dn);
1317
1318 first = udev_device_get_devlinks_list_entry(dev);
1319 udev_list_entry_foreach(item, first) {
1320 _cleanup_free_ char *n = NULL;
1321
1322 n = unit_name_from_path(udev_list_entry_get_name(item), ".swap");
1323 if (!n)
1324 return -ENOMEM;
1325
1326 s = hashmap_get(m->units, n);
1327 if (s) {
1328 int q;
1329
1330 q = swap_set_devnode(s, dn);
1331 if (q < 0)
1332 r = q;
1333 }
1334 }
1335
1336 return r;
1337}
1338
1339int swap_process_removed_device(Manager *m, struct udev_device *dev) {
9670d583
LP
1340 const char *dn;
1341 int r = 0;
1342 Swap *s;
1343
1344 dn = udev_device_get_devnode(dev);
1345 if (!dn)
1346 return 0;
1347
1348 while ((s = hashmap_get(m->swaps_by_devnode, dn))) {
1349 int q;
1350
1351 q = swap_set_devnode(s, NULL);
1352 if (q < 0)
1353 r = q;
1354 }
1355
1356 return r;
1357}
1358
fdf20a31 1359static void swap_reset_failed(Unit *u) {
5632e374
LP
1360 Swap *s = SWAP(u);
1361
1362 assert(s);
1363
fdf20a31 1364 if (s->state == SWAP_FAILED)
5632e374 1365 swap_set_state(s, SWAP_DEAD);
e04aad61 1366
e1770af8 1367 s->result = SWAP_SUCCESS;
5632e374
LP
1368}
1369
718db961 1370static int swap_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
814cc562 1371 return unit_kill_common(u, who, signo, -1, SWAP(u)->control_pid, error);
8a0867d6
LP
1372}
1373
68db7a3b
ZJS
1374static int swap_get_timeout(Unit *u, uint64_t *timeout) {
1375 Swap *s = SWAP(u);
1376 int r;
1377
1378 if (!s->timer_event_source)
1379 return 0;
1380
1381 r = sd_event_source_get_time(s->timer_event_source, timeout);
1382 if (r < 0)
1383 return r;
1384
1385 return 1;
1386}
1387
5632e374
LP
1388static const char* const swap_state_table[_SWAP_STATE_MAX] = {
1389 [SWAP_DEAD] = "dead",
e04aad61 1390 [SWAP_ACTIVATING] = "activating",
5bcb0f2b 1391 [SWAP_ACTIVATING_DONE] = "activating-done",
5632e374 1392 [SWAP_ACTIVE] = "active",
e04aad61
LP
1393 [SWAP_DEACTIVATING] = "deactivating",
1394 [SWAP_ACTIVATING_SIGTERM] = "activating-sigterm",
1395 [SWAP_ACTIVATING_SIGKILL] = "activating-sigkill",
1396 [SWAP_DEACTIVATING_SIGTERM] = "deactivating-sigterm",
1397 [SWAP_DEACTIVATING_SIGKILL] = "deactivating-sigkill",
fdf20a31 1398 [SWAP_FAILED] = "failed"
5632e374
LP
1399};
1400
1401DEFINE_STRING_TABLE_LOOKUP(swap_state, SwapState);
1402
e04aad61
LP
1403static const char* const swap_exec_command_table[_SWAP_EXEC_COMMAND_MAX] = {
1404 [SWAP_EXEC_ACTIVATE] = "ExecActivate",
1405 [SWAP_EXEC_DEACTIVATE] = "ExecDeactivate",
1406};
1407
1408DEFINE_STRING_TABLE_LOOKUP(swap_exec_command, SwapExecCommand);
1409
e1770af8
LP
1410static const char* const swap_result_table[_SWAP_RESULT_MAX] = {
1411 [SWAP_SUCCESS] = "success",
1412 [SWAP_FAILURE_RESOURCES] = "resources",
1413 [SWAP_FAILURE_TIMEOUT] = "timeout",
1414 [SWAP_FAILURE_EXIT_CODE] = "exit-code",
1415 [SWAP_FAILURE_SIGNAL] = "signal",
1416 [SWAP_FAILURE_CORE_DUMP] = "core-dump"
1417};
1418
1419DEFINE_STRING_TABLE_LOOKUP(swap_result, SwapResult);
1420
07b0b134 1421const UnitVTable swap_vtable = {
7d17cfbc 1422 .object_size = sizeof(Swap),
718db961
LP
1423 .exec_context_offset = offsetof(Swap, exec_context),
1424 .cgroup_context_offset = offsetof(Swap, cgroup_context),
1425 .kill_context_offset = offsetof(Swap, kill_context),
613b411c 1426 .exec_runtime_offset = offsetof(Swap, exec_runtime),
3ef63c31 1427
f975e971
LP
1428 .sections =
1429 "Unit\0"
1430 "Swap\0"
1431 "Install\0",
4ad49000 1432 .private_section = "Swap",
71645aca 1433
e04aad61 1434 .no_alias = true,
07b0b134
ML
1435 .no_instances = true,
1436
4e85aff4 1437 .init = swap_init,
07b0b134 1438 .load = swap_load,
6e620bec 1439 .done = swap_done,
07b0b134
ML
1440
1441 .coldplug = swap_coldplug,
1442
1443 .dump = swap_dump,
1444
1445 .start = swap_start,
1446 .stop = swap_stop,
1447
8a0867d6
LP
1448 .kill = swap_kill,
1449
68db7a3b
ZJS
1450 .get_timeout = swap_get_timeout,
1451
07b0b134
ML
1452 .serialize = swap_serialize,
1453 .deserialize_item = swap_deserialize_item,
1454
1455 .active_state = swap_active_state,
1456 .sub_state_to_string = swap_sub_state_to_string,
1457
1458 .check_gc = swap_check_gc,
1459
e04aad61 1460 .sigchld_event = swap_sigchld_event,
e04aad61
LP
1461
1462 .reset_failed = swap_reset_failed,
1463
c4e2ceae 1464 .bus_interface = "org.freedesktop.systemd1.Swap",
718db961 1465 .bus_vtable = bus_swap_vtable,
74c964d3
LP
1466 .bus_set_property = bus_swap_set_property,
1467 .bus_commit_properties = bus_swap_commit_properties,
07b0b134 1468
e04aad61 1469 .following = swap_following,
6210e7fc 1470 .following_set = swap_following_set,
5632e374 1471
6e620bec 1472 .enumerate = swap_enumerate,
c6918296
MS
1473 .shutdown = swap_shutdown,
1474
1475 .status_message_formats = {
1476 .starting_stopping = {
1477 [0] = "Activating swap %s...",
1478 [1] = "Deactivating swap %s...",
1479 },
1480 .finished_start_job = {
1481 [JOB_DONE] = "Activated swap %s.",
1482 [JOB_FAILED] = "Failed to activate swap %s.",
1483 [JOB_DEPENDENCY] = "Dependency failed for %s.",
1484 [JOB_TIMEOUT] = "Timed out activating swap %s.",
1485 },
1486 .finished_stop_job = {
1487 [JOB_DONE] = "Deactivated swap %s.",
1488 [JOB_FAILED] = "Failed deactivating swap %s.",
1489 [JOB_TIMEOUT] = "Timed out deactivating swap %s.",
1490 },
1491 },
07b0b134 1492};