]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/swap.c
Merge pull request #19556 from lucasrangit/network-wifi-interface-type-typos
[thirdparty/systemd.git] / src / core / swap.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
07b0b134
ML
2
3#include <errno.h>
07b0b134
ML
4#include <sys/epoll.h>
5#include <sys/stat.h>
4f5dd394 6#include <unistd.h>
07b0b134 7
4366e598 8#include "sd-device.h"
b4bbcaa9 9
b5efdb8a 10#include "alloc-util.h"
07b0b134 11#include "dbus-swap.h"
6fcbec6f 12#include "dbus-unit.h"
4366e598 13#include "device-util.h"
57b7a260 14#include "device.h"
4f5dd394 15#include "escape.h"
9a57c629 16#include "exit-status.h"
3ffd4af2 17#include "fd-util.h"
f97b34a6 18#include "format-util.h"
4f5dd394 19#include "fstab-util.h"
6bedfcbb 20#include "parse-util.h"
9eb977db 21#include "path-util.h"
7b3e062c 22#include "process-util.h"
d68c645b 23#include "serialize.h"
4f5dd394 24#include "special.h"
8b43440b 25#include "string-table.h"
07630cea 26#include "string-util.h"
3ffd4af2 27#include "swap.h"
4f5dd394
LP
28#include "unit-name.h"
29#include "unit.h"
30#include "virt.h"
07b0b134
ML
31
32static const UnitActiveState state_translation_table[_SWAP_STATE_MAX] = {
33 [SWAP_DEAD] = UNIT_INACTIVE,
e04aad61 34 [SWAP_ACTIVATING] = UNIT_ACTIVATING,
5bcb0f2b 35 [SWAP_ACTIVATING_DONE] = UNIT_ACTIVE,
07b0b134 36 [SWAP_ACTIVE] = UNIT_ACTIVE,
e04aad61 37 [SWAP_DEACTIVATING] = UNIT_DEACTIVATING,
e04aad61
LP
38 [SWAP_DEACTIVATING_SIGTERM] = UNIT_DEACTIVATING,
39 [SWAP_DEACTIVATING_SIGKILL] = UNIT_DEACTIVATING,
a8b689b7
YW
40 [SWAP_FAILED] = UNIT_FAILED,
41 [SWAP_CLEANING] = UNIT_MAINTENANCE,
07b0b134
ML
42};
43
718db961
LP
44static int swap_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata);
45static int swap_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
bcce581d 46static int swap_process_proc_swaps(Manager *m);
718db961 47
dedf3719
LP
48static bool SWAP_STATE_WITH_PROCESS(SwapState state) {
49 return IN_SET(state,
50 SWAP_ACTIVATING,
51 SWAP_ACTIVATING_DONE,
52 SWAP_DEACTIVATING,
53 SWAP_DEACTIVATING_SIGTERM,
a8b689b7
YW
54 SWAP_DEACTIVATING_SIGKILL,
55 SWAP_CLEANING);
dedf3719
LP
56}
57
39c79477
ZJS
58_pure_ static UnitActiveState swap_active_state(Unit *u) {
59 assert(u);
60
61 return state_translation_table[SWAP(u)->state];
62}
63
64_pure_ static const char *swap_sub_state_to_string(Unit *u) {
65 assert(u);
66
67 return swap_state_to_string(SWAP(u)->state);
68}
69
70_pure_ static bool swap_may_gc(Unit *u) {
71 Swap *s = SWAP(u);
72
73 assert(s);
74
75 if (s->from_proc_swaps)
76 return false;
77
78 return true;
79}
80
81_pure_ static bool swap_is_extrinsic(Unit *u) {
82 assert(SWAP(u));
83
84 return MANAGER_IS_USER(u->manager);
85}
86
e04aad61 87static void swap_unset_proc_swaps(Swap *s) {
9670d583
LP
88 assert(s);
89
90 if (!s->from_proc_swaps)
91 return;
92
a1e58e8e 93 s->parameters_proc_swaps.what = mfree(s->parameters_proc_swaps.what);
9670d583
LP
94 s->from_proc_swaps = false;
95}
96
97static int swap_set_devnode(Swap *s, const char *devnode) {
df326b84 98 Hashmap *swaps;
5bcb0f2b 99 Swap *first;
9670d583 100 int r;
e04aad61
LP
101
102 assert(s);
103
548f6937 104 r = hashmap_ensure_allocated(&UNIT(s)->manager->swaps_by_devnode, &path_hash_ops);
9670d583
LP
105 if (r < 0)
106 return r;
e04aad61 107
9670d583 108 swaps = UNIT(s)->manager->swaps_by_devnode;
e04aad61 109
9670d583
LP
110 if (s->devnode) {
111 first = hashmap_get(swaps, s->devnode);
e04aad61 112
9670d583
LP
113 LIST_REMOVE(same_devnode, first, s);
114 if (first)
115 hashmap_replace(swaps, first->devnode, first);
116 else
117 hashmap_remove(swaps, s->devnode);
5bcb0f2b 118
a1e58e8e 119 s->devnode = mfree(s->devnode);
9670d583
LP
120 }
121
122 if (devnode) {
123 s->devnode = strdup(devnode);
124 if (!s->devnode)
125 return -ENOMEM;
126
127 first = hashmap_get(swaps, s->devnode);
128 LIST_PREPEND(same_devnode, first, s);
129
130 return hashmap_replace(swaps, first->devnode, first);
131 }
132
133 return 0;
e04aad61
LP
134}
135
f6cebb3b 136static void swap_init(Unit *u) {
6e620bec
LP
137 Swap *s = SWAP(u);
138
139 assert(s);
1124fe6f 140 assert(UNIT(s)->load_state == UNIT_STUB);
6e620bec 141
1f19a534 142 s->timeout_usec = u->manager->default_timeout_start_usec;
e04aad61 143
ac155bb8
MS
144 s->exec_context.std_output = u->manager->default_std_output;
145 s->exec_context.std_error = u->manager->default_std_error;
085afe36 146
e1770af8 147 s->control_command_id = _SWAP_EXEC_COMMAND_INVALID;
c8f4d764 148
5bcb0f2b 149 u->ignore_on_isolate = true;
e04aad61
LP
150}
151
152static void swap_unwatch_control_pid(Swap *s) {
153 assert(s);
154
155 if (s->control_pid <= 0)
156 return;
157
158 unit_unwatch_pid(UNIT(s), s->control_pid);
159 s->control_pid = 0;
6e620bec
LP
160}
161
4e85aff4
LP
162static void swap_done(Unit *u) {
163 Swap *s = SWAP(u);
07b0b134 164
4e85aff4 165 assert(s);
07b0b134 166
e04aad61 167 swap_unset_proc_swaps(s);
9670d583 168 swap_set_devnode(s, NULL);
e04aad61 169
a1e58e8e
LP
170 s->what = mfree(s->what);
171 s->parameters_fragment.what = mfree(s->parameters_fragment.what);
172 s->parameters_fragment.options = mfree(s->parameters_fragment.options);
86b23b07 173
e8a565cb 174 s->exec_runtime = exec_runtime_unref(s->exec_runtime, false);
e04aad61
LP
175 exec_command_done_array(s->exec_command, _SWAP_EXEC_COMMAND_MAX);
176 s->control_command = NULL;
177
29206d46
LP
178 dynamic_creds_unref(&s->dynamic_creds);
179
e04aad61
LP
180 swap_unwatch_control_pid(s);
181
718db961
LP
182 s->timer_event_source = sd_event_source_unref(s->timer_event_source);
183}
184
36c16a7c 185static int swap_arm_timer(Swap *s, usec_t usec) {
718db961
LP
186 int r;
187
188 assert(s);
189
718db961 190 if (s->timer_event_source) {
36c16a7c 191 r = sd_event_source_set_time(s->timer_event_source, usec);
718db961
LP
192 if (r < 0)
193 return r;
194
195 return sd_event_source_set_enabled(s->timer_event_source, SD_EVENT_ONESHOT);
196 }
197
36c16a7c
LP
198 if (usec == USEC_INFINITY)
199 return 0;
200
7dfbe2e3 201 r = sd_event_add_time(
6a0f1f6d
LP
202 UNIT(s)->manager->event,
203 &s->timer_event_source,
204 CLOCK_MONOTONIC,
36c16a7c 205 usec, 0,
6a0f1f6d 206 swap_dispatch_timer, s);
7dfbe2e3
TG
207 if (r < 0)
208 return r;
209
210 (void) sd_event_source_set_description(s->timer_event_source, "swap-timer");
211
212 return 0;
07b0b134
ML
213}
214
61f9cf4e
LP
215static SwapParameters* swap_get_parameters(Swap *s) {
216 assert(s);
217
218 if (s->from_proc_swaps)
219 return &s->parameters_proc_swaps;
220
221 if (s->from_fragment)
222 return &s->parameters_fragment;
223
224 return NULL;
225}
226
eef85c4a 227static int swap_add_device_dependencies(Swap *s) {
61f9cf4e
LP
228 UnitDependencyMask mask;
229 SwapParameters *p;
44b0d1fd 230 int r;
61f9cf4e 231
173a8d04
LP
232 assert(s);
233
234 if (!s->what)
235 return 0;
236
61f9cf4e 237 p = swap_get_parameters(s);
d4a3494e 238 if (!p || !p->what)
f10af76d
LP
239 return 0;
240
61f9cf4e
LP
241 mask = s->from_proc_swaps ? UNIT_DEPENDENCY_PROC_SWAP : UNIT_DEPENDENCY_FILE;
242
44b0d1fd
LP
243 if (is_device_path(p->what)) {
244 r = unit_add_node_dependency(UNIT(s), p->what, UNIT_REQUIRES, mask);
245 if (r < 0)
246 return r;
247
248 return unit_add_blockdev_dependency(UNIT(s), p->what, mask);
249 }
9b88bb50 250
61f9cf4e
LP
251 /* File based swap devices need to be ordered after systemd-remount-fs.service, since they might need
252 * a writable file system. */
253 return unit_add_dependency_by_name(UNIT(s), UNIT_AFTER, SPECIAL_REMOUNT_FS_SERVICE, true, mask);
173a8d04
LP
254}
255
2edd4434 256static int swap_add_default_dependencies(Swap *s) {
8bf23dc7
FB
257 int r;
258
2edd4434
LP
259 assert(s);
260
4c9ea260
LP
261 if (!UNIT(s)->default_dependencies)
262 return 0;
263
463d0d15 264 if (!MANAGER_IS_SYSTEM(UNIT(s)->manager))
6b1dc2bd 265 return 0;
2edd4434 266
75f86906 267 if (detect_container() > 0)
c0387ebf
LP
268 return 0;
269
8bf23dc7
FB
270 /* swap units generated for the swap dev links are missing the
271 * ordering dep against the swap target. */
35d8c19a 272 r = unit_add_dependency_by_name(UNIT(s), UNIT_BEFORE, SPECIAL_SWAP_TARGET, true, UNIT_DEPENDENCY_DEFAULT);
8bf23dc7
FB
273 if (r < 0)
274 return r;
275
5a724170 276 return unit_add_two_dependencies_by_name(UNIT(s), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, true, UNIT_DEPENDENCY_DEFAULT);
2edd4434
LP
277}
278
4e85aff4 279static int swap_verify(Swap *s) {
7fd1b19b 280 _cleanup_free_ char *e = NULL;
7410616c 281 int r;
4e85aff4 282
75193d41 283 assert(UNIT(s)->load_state == UNIT_LOADED);
4e85aff4 284
7410616c
LP
285 r = unit_name_from_path(s->what, ".swap", &e);
286 if (r < 0)
f2341e0a 287 return log_unit_error_errno(UNIT(s), r, "Failed to generate unit name from path: %m");
4e85aff4 288
d85ff944
YW
289 if (!unit_has_name(UNIT(s), e))
290 return log_unit_error_errno(UNIT(s), SYNTHETIC_ERRNO(ENOEXEC), "Value of What= and unit name do not match, not loading.");
4e85aff4 291
d85ff944
YW
292 if (s->exec_context.pam_name && s->kill_context.kill_mode != KILL_CONTROL_GROUP)
293 return log_unit_error_errno(UNIT(s), SYNTHETIC_ERRNO(ENOEXEC), "Unit has PAM enabled. Kill mode must be set to 'control-group'. Refusing to load.");
e04aad61 294
4e85aff4
LP
295 return 0;
296}
297
9670d583 298static int swap_load_devnode(Swap *s) {
4366e598 299 _cleanup_(sd_device_unrefp) sd_device *d = NULL;
9670d583
LP
300 struct stat st;
301 const char *p;
e5ca27b7 302 int r;
9670d583
LP
303
304 assert(s);
305
306 if (stat(s->what, &st) < 0 || !S_ISBLK(st.st_mode))
307 return 0;
308
a1130022 309 r = sd_device_new_from_stat_rdev(&d, &st);
e5ca27b7 310 if (r < 0) {
8ed6f81b
YW
311 log_unit_full_errno(UNIT(s), r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r,
312 "Failed to allocate device for swap %s: %m", s->what);
9670d583 313 return 0;
e5ca27b7 314 }
9670d583 315
4366e598 316 if (sd_device_get_devname(d, &p) < 0)
9670d583
LP
317 return 0;
318
319 return swap_set_devnode(s, p);
320}
321
15332d73 322static int swap_add_extras(Swap *s) {
07b0b134 323 int r;
07b0b134
ML
324
325 assert(s);
07b0b134 326
15332d73
LP
327 if (UNIT(s)->fragment_path)
328 s->from_fragment = true;
07b0b134 329
15332d73
LP
330 if (!s->what) {
331 if (s->parameters_fragment.what)
332 s->what = strdup(s->parameters_fragment.what);
333 else if (s->parameters_proc_swaps.what)
334 s->what = strdup(s->parameters_proc_swaps.what);
335 else {
336 r = unit_name_to_path(UNIT(s)->id, &s->what);
5bcb0f2b 337 if (r < 0)
4e85aff4 338 return r;
5bcb0f2b 339 }
4e85aff4 340
15332d73
LP
341 if (!s->what)
342 return -ENOMEM;
343 }
07b0b134 344
15332d73 345 path_simplify(s->what, false);
07b0b134 346
15332d73
LP
347 if (!UNIT(s)->description) {
348 r = unit_set_description(UNIT(s), s->what);
9670d583
LP
349 if (r < 0)
350 return r;
15332d73 351 }
9670d583 352
15332d73
LP
353 r = unit_require_mounts_for(UNIT(s), s->what, UNIT_DEPENDENCY_IMPLICIT);
354 if (r < 0)
355 return r;
598459ce 356
15332d73
LP
357 r = swap_add_device_dependencies(s);
358 if (r < 0)
359 return r;
598459ce 360
15332d73
LP
361 r = swap_load_devnode(s);
362 if (r < 0)
363 return r;
a016b922 364
15332d73
LP
365 r = unit_patch_contexts(UNIT(s));
366 if (r < 0)
367 return r;
368
369 r = unit_add_exec_dependencies(UNIT(s), &s->exec_context);
370 if (r < 0)
371 return r;
372
373 r = unit_set_default_slice(UNIT(s));
374 if (r < 0)
375 return r;
376
377 r = swap_add_default_dependencies(s);
378 if (r < 0)
379 return r;
380
381 return 0;
382}
383
384static int swap_load(Unit *u) {
385 Swap *s = SWAP(u);
75193d41 386 int r, q = 0;
15332d73
LP
387
388 assert(s);
389 assert(u->load_state == UNIT_STUB);
390
391 /* Load a .swap file */
c3620770
ZJS
392 bool fragment_optional = s->from_proc_swaps;
393 r = unit_load_fragment_and_dropin(u, !fragment_optional);
15332d73 394
75193d41
ZJS
395 /* Add in some extras, and do so either when we successfully loaded something or when /proc/swaps is
396 * already active. */
06721f39
LP
397 if (u->load_state == UNIT_LOADED || s->from_proc_swaps)
398 q = swap_add_extras(s);
15332d73 399
06721f39
LP
400 if (r < 0)
401 return r;
402 if (q < 0)
403 return q;
75193d41
ZJS
404 if (u->load_state != UNIT_LOADED)
405 return 0;
07b0b134
ML
406
407 return swap_verify(s);
408}
409
628c89cc 410static int swap_setup_unit(
4e85aff4
LP
411 Manager *m,
412 const char *what,
e04aad61 413 const char *what_proc_swaps,
4e85aff4 414 int priority,
e04aad61
LP
415 bool set_flags) {
416
7fd1b19b 417 _cleanup_free_ char *e = NULL;
2c7c6144 418 bool delete = false;
5bcb0f2b 419 Unit *u = NULL;
07b0b134 420 int r;
4e85aff4
LP
421 SwapParameters *p;
422
423 assert(m);
424 assert(what);
6b1dc2bd 425 assert(what_proc_swaps);
07b0b134 426
7410616c
LP
427 r = unit_name_from_path(what, ".swap", &e);
428 if (r < 0)
f2341e0a 429 return log_unit_error_errno(u, r, "Failed to generate unit name from path: %m");
07b0b134 430
e04aad61 431 u = manager_get_unit(m, e);
6b1dc2bd 432 if (u &&
e04aad61 433 SWAP(u)->from_proc_swaps &&
baaa35ad
ZJS
434 !path_equal(SWAP(u)->parameters_proc_swaps.what, what_proc_swaps))
435 return log_error_errno(SYNTHETIC_ERRNO(EEXIST),
436 "Swap %s appeared twice with different device paths %s and %s",
437 e, SWAP(u)->parameters_proc_swaps.what, what_proc_swaps);
4e85aff4
LP
438
439 if (!u) {
07b0b134
ML
440 delete = true;
441
a581e45a 442 r = unit_new_for_name(m, sizeof(Swap), e, &u);
7d17cfbc 443 if (r < 0)
e04aad61
LP
444 goto fail;
445
7d17cfbc
MS
446 SWAP(u)->what = strdup(what);
447 if (!SWAP(u)->what) {
628c89cc 448 r = -ENOMEM;
e04aad61
LP
449 goto fail;
450 }
451
452 unit_add_to_load_queue(u);
4e85aff4
LP
453 } else
454 delete = false;
07b0b134 455
6b1dc2bd 456 p = &SWAP(u)->parameters_proc_swaps;
07b0b134 457
6b1dc2bd 458 if (!p->what) {
5bcb0f2b
LP
459 p->what = strdup(what_proc_swaps);
460 if (!p->what) {
461 r = -ENOMEM;
6b1dc2bd
LP
462 goto fail;
463 }
6b1dc2bd 464 }
e04aad61 465
46f94480
LP
466 /* The unit is definitely around now, mark it as loaded if it was previously referenced but could not be
467 * loaded. After all we can load it now, from the data in /proc/swaps. */
468 if (IN_SET(u->load_state, UNIT_NOT_FOUND, UNIT_BAD_SETTING, UNIT_ERROR)) {
469 u->load_state = UNIT_LOADED;
470 u->load_error = 0;
471 }
472
6b1dc2bd
LP
473 if (set_flags) {
474 SWAP(u)->is_active = true;
475 SWAP(u)->just_activated = !SWAP(u)->from_proc_swaps;
4e85aff4 476 }
07b0b134 477
6b1dc2bd
LP
478 SWAP(u)->from_proc_swaps = true;
479
4e85aff4 480 p->priority = priority;
7477451b 481 p->priority_set = true;
07b0b134 482
4e85aff4 483 unit_add_to_dbus_queue(u);
07b0b134
ML
484 return 0;
485
486fail:
f2341e0a 487 log_unit_warning_errno(u, r, "Failed to load swap unit: %m");
e04aad61 488
c9d5c9c0 489 if (delete)
07b0b134
ML
490 unit_free(u);
491
4e85aff4 492 return r;
07b0b134
ML
493}
494
628c89cc 495static int swap_process_new(Manager *m, const char *device, int prio, bool set_flags) {
4366e598
YW
496 _cleanup_(sd_device_unrefp) sd_device *d = NULL;
497 const char *dn, *devlink;
498 struct stat st, st_link;
5bcb0f2b 499 int r;
e04aad61
LP
500
501 assert(m);
502
628c89cc 503 r = swap_setup_unit(m, device, device, prio, set_flags);
5bcb0f2b
LP
504 if (r < 0)
505 return r;
e04aad61 506
5bcb0f2b
LP
507 /* If this is a block device, then let's add duplicates for
508 * all other names of this block device */
509 if (stat(device, &st) < 0 || !S_ISBLK(st.st_mode))
510 return 0;
e04aad61 511
a1130022 512 r = sd_device_new_from_stat_rdev(&d, &st);
e5ca27b7
LP
513 if (r < 0) {
514 log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r,
4366e598 515 "Failed to allocate device for swap %s: %m", device);
5bcb0f2b 516 return 0;
e5ca27b7 517 }
e04aad61 518
5bcb0f2b 519 /* Add the main device node */
4366e598 520 if (sd_device_get_devname(d, &dn) >= 0 && !streq(dn, device))
628c89cc 521 swap_setup_unit(m, dn, device, prio, set_flags);
e04aad61 522
5bcb0f2b 523 /* Add additional units for all symlinks */
4366e598 524 FOREACH_DEVICE_DEVLINK(d, devlink) {
e04aad61 525
5bcb0f2b 526 /* Don't bother with the /dev/block links */
4366e598 527 if (streq(devlink, device))
5bcb0f2b 528 continue;
e04aad61 529
4366e598 530 if (path_startswith(devlink, "/dev/block/"))
5bcb0f2b 531 continue;
e04aad61 532
4366e598
YW
533 if (stat(devlink, &st_link) >= 0 &&
534 (!S_ISBLK(st_link.st_mode) ||
535 st_link.st_rdev != st.st_rdev))
536 continue;
e04aad61 537
4366e598 538 swap_setup_unit(m, devlink, device, prio, set_flags);
e04aad61
LP
539 }
540
a0a42408 541 return 0;
e04aad61
LP
542}
543
07b0b134
ML
544static void swap_set_state(Swap *s, SwapState state) {
545 SwapState old_state;
37cf8fee 546 Swap *other;
e04aad61 547
07b0b134
ML
548 assert(s);
549
6fcbec6f
LP
550 if (s->state != state)
551 bus_unit_send_pending_change_signal(UNIT(s), false);
552
07b0b134
ML
553 old_state = s->state;
554 s->state = state;
555
dedf3719 556 if (!SWAP_STATE_WITH_PROCESS(state)) {
718db961 557 s->timer_event_source = sd_event_source_unref(s->timer_event_source);
e04aad61
LP
558 swap_unwatch_control_pid(s);
559 s->control_command = NULL;
560 s->control_command_id = _SWAP_EXEC_COMMAND_INVALID;
561 }
562
07b0b134 563 if (state != old_state)
f2341e0a 564 log_unit_debug(UNIT(s), "Changed %s -> %s", swap_state_to_string(old_state), swap_state_to_string(state));
07b0b134 565
2ad2e41a 566 unit_notify(UNIT(s), state_translation_table[old_state], state_translation_table[state], 0);
37cf8fee
LP
567
568 /* If there other units for the same device node have a job
569 queued it might be worth checking again if it is runnable
570 now. This is necessary, since swap_start() refuses
571 operation with EAGAIN if there's already another job for
572 the same device node queued. */
573 LIST_FOREACH_OTHERS(same_devnode, other, s)
574 if (UNIT(other)->job)
575 job_add_to_run_queue(UNIT(other)->job);
07b0b134
ML
576}
577
be847e82 578static int swap_coldplug(Unit *u) {
07b0b134
ML
579 Swap *s = SWAP(u);
580 SwapState new_state = SWAP_DEAD;
e04aad61 581 int r;
07b0b134
ML
582
583 assert(s);
584 assert(s->state == SWAP_DEAD);
585
586 if (s->deserialized_state != s->state)
587 new_state = s->deserialized_state;
4e85aff4 588 else if (s->from_proc_swaps)
07b0b134
ML
589 new_state = SWAP_ACTIVE;
590
5bcb0f2b
LP
591 if (new_state == s->state)
592 return 0;
e04aad61 593
c386f588
LP
594 if (s->control_pid > 0 &&
595 pid_is_unwaited(s->control_pid) &&
dedf3719 596 SWAP_STATE_WITH_PROCESS(new_state)) {
e04aad61 597
f75f613d 598 r = unit_watch_pid(UNIT(s), s->control_pid, false);
5bcb0f2b
LP
599 if (r < 0)
600 return r;
e04aad61 601
36c16a7c 602 r = swap_arm_timer(s, usec_add(u->state_change_timestamp.monotonic, s->timeout_usec));
5bcb0f2b
LP
603 if (r < 0)
604 return r;
e04aad61 605 }
07b0b134 606
e8a565cb 607 if (!IN_SET(new_state, SWAP_DEAD, SWAP_FAILED)) {
29206d46 608 (void) unit_setup_dynamic_creds(u);
e8a565cb
YW
609 (void) unit_setup_exec_runtime(u);
610 }
29206d46 611
5bcb0f2b 612 swap_set_state(s, new_state);
07b0b134
ML
613 return 0;
614}
615
616static void swap_dump(Unit *u, FILE *f, const char *prefix) {
f2e18ef1 617 char buf[FORMAT_TIMESPAN_MAX];
07b0b134 618 Swap *s = SWAP(u);
4e85aff4 619 SwapParameters *p;
07b0b134
ML
620
621 assert(s);
4e85aff4
LP
622 assert(f);
623
624 if (s->from_proc_swaps)
625 p = &s->parameters_proc_swaps;
626 else if (s->from_fragment)
627 p = &s->parameters_fragment;
b6bfc7bb
LP
628 else
629 p = NULL;
07b0b134
ML
630
631 fprintf(f,
4e85aff4 632 "%sSwap State: %s\n"
e1770af8 633 "%sResult: %s\n"
a8b689b7 634 "%sClean Result: %s\n"
07b0b134 635 "%sWhat: %s\n"
4e85aff4 636 "%sFrom /proc/swaps: %s\n"
39c79477
ZJS
637 "%sFrom fragment: %s\n"
638 "%sExtrinsic: %s\n",
07b0b134 639 prefix, swap_state_to_string(s->state),
e1770af8 640 prefix, swap_result_to_string(s->result),
a8b689b7 641 prefix, swap_result_to_string(s->clean_result),
07b0b134 642 prefix, s->what,
4e85aff4 643 prefix, yes_no(s->from_proc_swaps),
39c79477
ZJS
644 prefix, yes_no(s->from_fragment),
645 prefix, yes_no(swap_is_extrinsic(u)));
e04aad61 646
9670d583
LP
647 if (s->devnode)
648 fprintf(f, "%sDevice Node: %s\n", prefix, s->devnode);
649
b6bfc7bb
LP
650 if (p)
651 fprintf(f,
652 "%sPriority: %i\n"
47cb901e 653 "%sOptions: %s\n",
b6bfc7bb 654 prefix, p->priority,
47cb901e 655 prefix, strempty(p->options));
b6bfc7bb 656
9bd0e1b8
YW
657 fprintf(f,
658 "%sTimeoutSec: %s\n",
659 prefix, format_timespan(buf, sizeof(buf), s->timeout_usec, USEC_PER_SEC));
660
e04aad61
LP
661 if (s->control_pid > 0)
662 fprintf(f,
de0671ee
ZJS
663 "%sControl PID: "PID_FMT"\n",
664 prefix, s->control_pid);
e04aad61
LP
665
666 exec_context_dump(&s->exec_context, f, prefix);
4819ff03 667 kill_context_dump(&s->kill_context, f, prefix);
bc0623df 668 cgroup_context_dump(UNIT(s), f, prefix);
e04aad61
LP
669}
670
671static int swap_spawn(Swap *s, ExecCommand *c, pid_t *_pid) {
3c7416b6 672
b9c04eaf 673 _cleanup_(exec_params_clear) ExecParameters exec_params = {
1703fa41 674 .flags = EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN,
c39f1ce2
LP
675 .stdin_fd = -1,
676 .stdout_fd = -1,
677 .stderr_fd = -1,
5686391b 678 .exec_fd = -1,
9fa95f85 679 };
3c7416b6
LP
680 pid_t pid;
681 int r;
e04aad61
LP
682
683 assert(s);
684 assert(c);
685 assert(_pid);
686
3c7416b6 687 r = unit_prepare_exec(UNIT(s));
29206d46 688 if (r < 0)
3c7416b6 689 return r;
29206d46 690
36c16a7c 691 r = swap_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_usec));
646134dc 692 if (r < 0)
e04aad61
LP
693 goto fail;
694
1ad6e8b3
LP
695 r = unit_set_exec_params(UNIT(s), &exec_params);
696 if (r < 0)
697 goto fail;
9fa95f85 698
f2341e0a
LP
699 r = exec_spawn(UNIT(s),
700 c,
646134dc 701 &s->exec_context,
9fa95f85 702 &exec_params,
613b411c 703 s->exec_runtime,
29206d46 704 &s->dynamic_creds,
646134dc
ZJS
705 &pid);
706 if (r < 0)
e04aad61
LP
707 goto fail;
708
f75f613d 709 r = unit_watch_pid(UNIT(s), pid, true);
646134dc 710 if (r < 0)
e04aad61
LP
711 goto fail;
712
713 *_pid = pid;
714
715 return 0;
716
717fail:
718db961 718 s->timer_event_source = sd_event_source_unref(s->timer_event_source);
3536f49e 719
e04aad61 720 return r;
07b0b134
ML
721}
722
e1770af8 723static void swap_enter_dead(Swap *s, SwapResult f) {
07b0b134
ML
724 assert(s);
725
a0fef983 726 if (s->result == SWAP_SUCCESS)
e1770af8 727 s->result = f;
e04aad61 728
aac99f30 729 unit_log_result(UNIT(s), s->result == SWAP_SUCCESS, swap_result_to_string(s->result));
4c425434 730 unit_warn_leftover_processes(UNIT(s), unit_log_leftover_process_stop);
29206d46
LP
731 swap_set_state(s, s->result != SWAP_SUCCESS ? SWAP_FAILED : SWAP_DEAD);
732
e8a565cb 733 s->exec_runtime = exec_runtime_unref(s->exec_runtime, true);
613b411c 734
bb0c0d6f 735 unit_destroy_runtime_data(UNIT(s), &s->exec_context);
e66cf1a3 736
00d9ef85
LP
737 unit_unref_uid_gid(UNIT(s), true);
738
29206d46 739 dynamic_creds_destroy(&s->dynamic_creds);
07b0b134
ML
740}
741
e1770af8 742static void swap_enter_active(Swap *s, SwapResult f) {
e04aad61
LP
743 assert(s);
744
a0fef983 745 if (s->result == SWAP_SUCCESS)
e1770af8 746 s->result = f;
e04aad61
LP
747
748 swap_set_state(s, SWAP_ACTIVE);
749}
750
50864457
LP
751static void swap_enter_dead_or_active(Swap *s, SwapResult f) {
752 assert(s);
753
9c1f969d
HD
754 if (s->from_proc_swaps) {
755 Swap *other;
756
50864457 757 swap_enter_active(s, f);
9c1f969d
HD
758
759 LIST_FOREACH_OTHERS(same_devnode, other, s)
760 if (UNIT(other)->job)
761 swap_enter_dead_or_active(other, f);
762 } else
50864457
LP
763 swap_enter_dead(s, f);
764}
765
a232ebcc
ZJS
766static int state_to_kill_operation(Swap *s, SwapState state) {
767 if (state == SWAP_DEACTIVATING_SIGTERM) {
768 if (unit_has_job_type(UNIT(s), JOB_RESTART))
769 return KILL_RESTART;
770 else
771 return KILL_TERMINATE;
772 }
773
774 return KILL_KILL;
775}
776
e1770af8 777static void swap_enter_signal(Swap *s, SwapState state, SwapResult f) {
07b0b134
ML
778 int r;
779
780 assert(s);
e04aad61 781
a0fef983 782 if (s->result == SWAP_SUCCESS)
e1770af8 783 s->result = f;
e04aad61 784
a232ebcc
ZJS
785 r = unit_kill_context(UNIT(s),
786 &s->kill_context,
787 state_to_kill_operation(s, state),
788 -1,
789 s->control_pid,
790 false);
cd2086fe
LP
791 if (r < 0)
792 goto fail;
e04aad61 793
cd2086fe 794 if (r > 0) {
36c16a7c 795 r = swap_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_usec));
646134dc 796 if (r < 0)
e04aad61
LP
797 goto fail;
798
799 swap_set_state(s, state);
50864457 800 } else if (state == SWAP_DEACTIVATING_SIGTERM && s->kill_context.send_sigkill)
ac84d1fb
LP
801 swap_enter_signal(s, SWAP_DEACTIVATING_SIGKILL, SWAP_SUCCESS);
802 else
50864457 803 swap_enter_dead_or_active(s, SWAP_SUCCESS);
e04aad61
LP
804
805 return;
806
807fail:
f2341e0a 808 log_unit_warning_errno(UNIT(s), r, "Failed to kill processes: %m");
50864457 809 swap_enter_dead_or_active(s, SWAP_FAILURE_RESOURCES);
e04aad61
LP
810}
811
812static void swap_enter_activating(Swap *s) {
bf1d7ba7
KZ
813 _cleanup_free_ char *opts = NULL;
814 int r;
e04aad61
LP
815
816 assert(s);
817
4c425434 818 unit_warn_leftover_processes(UNIT(s), unit_log_leftover_process_start);
a4634b21 819
e04aad61
LP
820 s->control_command_id = SWAP_EXEC_ACTIVATE;
821 s->control_command = s->exec_command + SWAP_EXEC_ACTIVATE;
07b0b134 822
86b23b07 823 if (s->from_fragment) {
7477451b 824 int priority = 0;
47cb901e 825
bf1d7ba7
KZ
826 r = fstab_find_pri(s->parameters_fragment.options, &priority);
827 if (r < 0)
af4454cb
LP
828 log_unit_warning_errno(UNIT(s), r, "Failed to parse swap priority \"%s\", ignoring: %m", s->parameters_fragment.options);
829 else if (r > 0 && s->parameters_fragment.priority_set)
830 log_unit_warning(UNIT(s), "Duplicate swap priority configuration by Priority= and Options= fields.");
bf1d7ba7 831
7477451b 832 if (r <= 0 && s->parameters_fragment.priority_set) {
bf1d7ba7
KZ
833 if (s->parameters_fragment.options)
834 r = asprintf(&opts, "%s,pri=%i", s->parameters_fragment.options, s->parameters_fragment.priority);
835 else
836 r = asprintf(&opts, "pri=%i", s->parameters_fragment.priority);
6fca66a7
LP
837 if (r < 0) {
838 r = -ENOMEM;
bf1d7ba7 839 goto fail;
6fca66a7 840 }
e64d5235 841 }
86b23b07
JS
842 }
843
844 r = exec_command_set(s->control_command, "/sbin/swapon", NULL);
845 if (r < 0)
846 goto fail;
4e85aff4 847
bf1d7ba7
KZ
848 if (s->parameters_fragment.options || opts) {
849 r = exec_command_append(s->control_command, "-o",
af4454cb 850 opts ?: s->parameters_fragment.options, NULL);
86b23b07
JS
851 if (r < 0)
852 goto fail;
853 }
e04aad61 854
86b23b07 855 r = exec_command_append(s->control_command, s->what, NULL);
e04aad61
LP
856 if (r < 0)
857 goto fail;
858
859 swap_unwatch_control_pid(s);
860
646134dc
ZJS
861 r = swap_spawn(s, s->control_command, &s->control_pid);
862 if (r < 0)
e04aad61
LP
863 goto fail;
864
865 swap_set_state(s, SWAP_ACTIVATING);
e04aad61
LP
866 return;
867
868fail:
f2341e0a 869 log_unit_warning_errno(UNIT(s), r, "Failed to run 'swapon' task: %m");
50864457 870 swap_enter_dead_or_active(s, SWAP_FAILURE_RESOURCES);
e04aad61
LP
871}
872
e1770af8 873static void swap_enter_deactivating(Swap *s) {
e04aad61
LP
874 int r;
875
876 assert(s);
877
e04aad61
LP
878 s->control_command_id = SWAP_EXEC_DEACTIVATE;
879 s->control_command = s->exec_command + SWAP_EXEC_DEACTIVATE;
880
646134dc 881 r = exec_command_set(s->control_command,
e04aad61
LP
882 "/sbin/swapoff",
883 s->what,
646134dc
ZJS
884 NULL);
885 if (r < 0)
e04aad61
LP
886 goto fail;
887
888 swap_unwatch_control_pid(s);
889
646134dc
ZJS
890 r = swap_spawn(s, s->control_command, &s->control_pid);
891 if (r < 0)
e04aad61
LP
892 goto fail;
893
894 swap_set_state(s, SWAP_DEACTIVATING);
895
896 return;
897
898fail:
f2341e0a 899 log_unit_warning_errno(UNIT(s), r, "Failed to run 'swapoff' task: %m");
50864457 900 swap_enter_dead_or_active(s, SWAP_FAILURE_RESOURCES);
e04aad61
LP
901}
902
31135818
LP
903static void swap_cycle_clear(Swap *s) {
904 assert(s);
905
906 s->result = SWAP_SUCCESS;
907 exec_command_reset_status_array(s->exec_command, _SWAP_EXEC_COMMAND_MAX);
908 UNIT(s)->reset_accounting = true;
909}
910
e04aad61 911static int swap_start(Unit *u) {
37cf8fee 912 Swap *s = SWAP(u), *other;
07299350 913 int r;
e04aad61
LP
914
915 assert(s);
916
50864457 917 /* We cannot fulfill this request right now, try again later please! */
d31ae548
FB
918 if (IN_SET(s->state,
919 SWAP_DEACTIVATING,
920 SWAP_DEACTIVATING_SIGTERM,
a8b689b7
YW
921 SWAP_DEACTIVATING_SIGKILL,
922 SWAP_CLEANING))
e04aad61
LP
923 return -EAGAIN;
924
50864457 925 /* Already on it! */
e04aad61
LP
926 if (s->state == SWAP_ACTIVATING)
927 return 0;
928
d31ae548 929 assert(IN_SET(s->state, SWAP_DEAD, SWAP_FAILED));
e04aad61 930
75f86906 931 if (detect_container() > 0)
a5c3034f
LP
932 return -EPERM;
933
37cf8fee
LP
934 /* If there's a job for another swap unit for the same node
935 * running, then let's not dispatch this one for now, and wait
936 * until that other job has finished. */
937 LIST_FOREACH_OTHERS(same_devnode, other, s)
938 if (UNIT(other)->job && UNIT(other)->job->state == JOB_RUNNING)
939 return -EAGAIN;
940
97a3f4ee 941 r = unit_test_start_limit(u);
07299350
LP
942 if (r < 0) {
943 swap_enter_dead(s, SWAP_FAILURE_START_LIMIT_HIT);
944 return r;
945 }
946
4b58153d
LP
947 r = unit_acquire_invocation_id(u);
948 if (r < 0)
949 return r;
950
31135818 951 swap_cycle_clear(s);
e04aad61 952 swap_enter_activating(s);
82a2b6bb 953 return 1;
07b0b134
ML
954}
955
956static int swap_stop(Unit *u) {
957 Swap *s = SWAP(u);
07b0b134
ML
958
959 assert(s);
960
50864457
LP
961 switch (s->state) {
962
963 case SWAP_DEACTIVATING:
964 case SWAP_DEACTIVATING_SIGTERM:
965 case SWAP_DEACTIVATING_SIGKILL:
966 /* Already on it */
e04aad61 967 return 0;
07b0b134 968
50864457
LP
969 case SWAP_ACTIVATING:
970 case SWAP_ACTIVATING_DONE:
971 /* There's a control process pending, directly enter kill mode */
972 swap_enter_signal(s, SWAP_DEACTIVATING_SIGTERM, SWAP_SUCCESS);
973 return 0;
07b0b134 974
50864457
LP
975 case SWAP_ACTIVE:
976 if (detect_container() > 0)
977 return -EPERM;
a5c3034f 978
50864457
LP
979 swap_enter_deactivating(s);
980 return 1;
981
a8b689b7
YW
982 case SWAP_CLEANING:
983 /* If we are currently cleaning, then abort it, brutally. */
984 swap_enter_signal(s, SWAP_DEACTIVATING_SIGKILL, SWAP_SUCCESS);
985 return 0;
986
50864457
LP
987 default:
988 assert_not_reached("Unexpected state.");
989 }
07b0b134
ML
990}
991
992static int swap_serialize(Unit *u, FILE *f, FDSet *fds) {
993 Swap *s = SWAP(u);
994
995 assert(s);
996 assert(f);
997 assert(fds);
998
d68c645b
LP
999 (void) serialize_item(f, "state", swap_state_to_string(s->state));
1000 (void) serialize_item(f, "result", swap_result_to_string(s->result));
e04aad61
LP
1001
1002 if (s->control_pid > 0)
d68c645b 1003 (void) serialize_item_format(f, "control-pid", PID_FMT, s->control_pid);
e04aad61
LP
1004
1005 if (s->control_command_id >= 0)
d68c645b 1006 (void) serialize_item(f, "control-command", swap_exec_command_to_string(s->control_command_id));
07b0b134
ML
1007
1008 return 0;
1009}
1010
1011static int swap_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
1012 Swap *s = SWAP(u);
1013
1014 assert(s);
1015 assert(fds);
1016
1017 if (streq(key, "state")) {
1018 SwapState state;
1019
646134dc
ZJS
1020 state = swap_state_from_string(value);
1021 if (state < 0)
f2341e0a 1022 log_unit_debug(u, "Failed to parse state value: %s", value);
07b0b134
ML
1023 else
1024 s->deserialized_state = state;
e1770af8
LP
1025 } else if (streq(key, "result")) {
1026 SwapResult f;
1027
1028 f = swap_result_from_string(value);
1029 if (f < 0)
f2341e0a 1030 log_unit_debug(u, "Failed to parse result value: %s", value);
e1770af8
LP
1031 else if (f != SWAP_SUCCESS)
1032 s->result = f;
e04aad61
LP
1033 } else if (streq(key, "control-pid")) {
1034 pid_t pid;
1035
1036 if (parse_pid(value, &pid) < 0)
f2341e0a 1037 log_unit_debug(u, "Failed to parse control-pid value: %s", value);
e04aad61
LP
1038 else
1039 s->control_pid = pid;
1040
1041 } else if (streq(key, "control-command")) {
1042 SwapExecCommand id;
1043
646134dc
ZJS
1044 id = swap_exec_command_from_string(value);
1045 if (id < 0)
f2341e0a 1046 log_unit_debug(u, "Failed to parse exec-command value: %s", value);
e04aad61
LP
1047 else {
1048 s->control_command_id = id;
1049 s->control_command = s->exec_command + id;
1050 }
07b0b134 1051 } else
f2341e0a 1052 log_unit_debug(u, "Unknown serialization key: %s", key);
07b0b134
ML
1053
1054 return 0;
1055}
1056
e04aad61
LP
1057static void swap_sigchld_event(Unit *u, pid_t pid, int code, int status) {
1058 Swap *s = SWAP(u);
e1770af8 1059 SwapResult f;
e04aad61
LP
1060
1061 assert(s);
1062 assert(pid >= 0);
1063
1064 if (pid != s->control_pid)
1065 return;
1066
bcce581d
LP
1067 /* Let's scan /proc/swaps before we process SIGCHLD. For the reasoning see the similar code in
1068 * mount.c */
1069 (void) swap_process_proc_swaps(u->manager);
1070
e04aad61
LP
1071 s->control_pid = 0;
1072
1f0958f6 1073 if (is_clean_exit(code, status, EXIT_CLEAN_COMMAND, NULL))
e1770af8
LP
1074 f = SWAP_SUCCESS;
1075 else if (code == CLD_EXITED)
1076 f = SWAP_FAILURE_EXIT_CODE;
1077 else if (code == CLD_KILLED)
1078 f = SWAP_FAILURE_SIGNAL;
1079 else if (code == CLD_DUMPED)
1080 f = SWAP_FAILURE_CORE_DUMP;
1081 else
1082 assert_not_reached("Unknown code");
1083
a0fef983 1084 if (s->result == SWAP_SUCCESS)
e1770af8 1085 s->result = f;
e04aad61
LP
1086
1087 if (s->control_command) {
6ea832a2 1088 exec_status_exit(&s->control_command->exec_status, &s->exec_context, pid, code, status);
e1770af8 1089
e04aad61
LP
1090 s->control_command = NULL;
1091 s->control_command_id = _SWAP_EXEC_COMMAND_INVALID;
1092 }
1093
91bbd9b7 1094 unit_log_process_exit(
5cc2cd1c 1095 u,
91bbd9b7
LP
1096 "Swap process",
1097 swap_exec_command_to_string(s->control_command_id),
5cc2cd1c 1098 f == SWAP_SUCCESS,
91bbd9b7 1099 code, status);
e04aad61
LP
1100
1101 switch (s->state) {
1102
1103 case SWAP_ACTIVATING:
5bcb0f2b 1104 case SWAP_ACTIVATING_DONE:
e04aad61 1105
50864457 1106 if (f == SWAP_SUCCESS || s->from_proc_swaps)
e1770af8 1107 swap_enter_active(s, f);
e04aad61 1108 else
e1770af8 1109 swap_enter_dead(s, f);
e04aad61
LP
1110 break;
1111
1112 case SWAP_DEACTIVATING:
1113 case SWAP_DEACTIVATING_SIGKILL:
1114 case SWAP_DEACTIVATING_SIGTERM:
1115
50864457 1116 swap_enter_dead_or_active(s, f);
e04aad61
LP
1117 break;
1118
a8b689b7
YW
1119 case SWAP_CLEANING:
1120 if (s->clean_result == SWAP_SUCCESS)
1121 s->clean_result = f;
1122
1123 swap_enter_dead(s, SWAP_SUCCESS);
1124 break;
1125
e04aad61
LP
1126 default:
1127 assert_not_reached("Uh, control process died at wrong time.");
1128 }
1129
1130 /* Notify clients about changed exit status */
1131 unit_add_to_dbus_queue(u);
e04aad61
LP
1132}
1133
718db961
LP
1134static int swap_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) {
1135 Swap *s = SWAP(userdata);
e04aad61
LP
1136
1137 assert(s);
718db961 1138 assert(s->timer_event_source == source);
e04aad61
LP
1139
1140 switch (s->state) {
1141
1142 case SWAP_ACTIVATING:
5bcb0f2b 1143 case SWAP_ACTIVATING_DONE:
f2341e0a 1144 log_unit_warning(UNIT(s), "Activation timed out. Stopping.");
50864457 1145 swap_enter_signal(s, SWAP_DEACTIVATING_SIGTERM, SWAP_FAILURE_TIMEOUT);
e04aad61
LP
1146 break;
1147
1148 case SWAP_DEACTIVATING:
f2341e0a 1149 log_unit_warning(UNIT(s), "Deactivation timed out. Stopping.");
e1770af8 1150 swap_enter_signal(s, SWAP_DEACTIVATING_SIGTERM, SWAP_FAILURE_TIMEOUT);
e04aad61
LP
1151 break;
1152
e04aad61 1153 case SWAP_DEACTIVATING_SIGTERM:
4819ff03 1154 if (s->kill_context.send_sigkill) {
50864457 1155 log_unit_warning(UNIT(s), "Swap process timed out. Killing.");
e1770af8 1156 swap_enter_signal(s, SWAP_DEACTIVATING_SIGKILL, SWAP_FAILURE_TIMEOUT);
ba035df2 1157 } else {
50864457
LP
1158 log_unit_warning(UNIT(s), "Swap process timed out. Skipping SIGKILL. Ignoring.");
1159 swap_enter_dead_or_active(s, SWAP_FAILURE_TIMEOUT);
ba035df2 1160 }
e04aad61
LP
1161 break;
1162
e04aad61 1163 case SWAP_DEACTIVATING_SIGKILL:
f2341e0a 1164 log_unit_warning(UNIT(s), "Swap process still around after SIGKILL. Ignoring.");
50864457 1165 swap_enter_dead_or_active(s, SWAP_FAILURE_TIMEOUT);
e04aad61
LP
1166 break;
1167
a8b689b7
YW
1168 case SWAP_CLEANING:
1169 log_unit_warning(UNIT(s), "Cleaning timed out. killing.");
1170
1171 if (s->clean_result == SWAP_SUCCESS)
1172 s->clean_result = SWAP_FAILURE_TIMEOUT;
1173
1174 swap_enter_signal(s, SWAP_DEACTIVATING_SIGKILL, 0);
1175 break;
1176
e04aad61
LP
1177 default:
1178 assert_not_reached("Timeout at wrong time.");
1179 }
718db961
LP
1180
1181 return 0;
e04aad61
LP
1182}
1183
1184static int swap_load_proc_swaps(Manager *m, bool set_flags) {
e04aad61
LP
1185 assert(m);
1186
07b0b134 1187 rewind(m->proc_swaps);
bab45044 1188
4e85aff4 1189 (void) fscanf(m->proc_swaps, "%*s %*s %*s %*s %*s\n");
07b0b134 1190
fe96c0f8 1191 for (unsigned i = 1;; i++) {
9fb3675e 1192 _cleanup_free_ char *dev = NULL, *d = NULL;
07b0b134
ML
1193 int prio = 0, k;
1194
646134dc
ZJS
1195 k = fscanf(m->proc_swaps,
1196 "%ms " /* device/file */
1197 "%*s " /* type of swap */
1198 "%*s " /* swap size */
1199 "%*s " /* used */
1200 "%i\n", /* priority */
1201 &dev, &prio);
1202 if (k != 2) {
07b0b134 1203 if (k == EOF)
4e85aff4 1204 break;
07b0b134 1205
628c89cc 1206 log_warning("Failed to parse /proc/swaps:%u.", i);
e04aad61 1207 continue;
07b0b134 1208 }
07b0b134 1209
527b7a42 1210 if (cunescape(dev, UNESCAPE_RELAX, &d) < 0)
628c89cc
LP
1211 return log_oom();
1212
485ae697 1213 device_found_node(m, d, DEVICE_FOUND_SWAP, DEVICE_FOUND_SWAP);
4e85aff4 1214
eb04385d 1215 (void) swap_process_new(m, d, prio, set_flags);
07b0b134
ML
1216 }
1217
eb04385d 1218 return 0;
e04aad61
LP
1219}
1220
bcce581d 1221static int swap_process_proc_swaps(Manager *m) {
595ed347 1222 Unit *u;
4e434314
LP
1223 int r;
1224
1225 assert(m);
4e434314 1226
646134dc
ZJS
1227 r = swap_load_proc_swaps(m, true);
1228 if (r < 0) {
da927ba9 1229 log_error_errno(r, "Failed to reread /proc/swaps: %m");
e04aad61
LP
1230
1231 /* Reset flags, just in case, for late calls */
595ed347
MS
1232 LIST_FOREACH(units_by_type, u, m->units_by_type[UNIT_SWAP]) {
1233 Swap *swap = SWAP(u);
e04aad61
LP
1234
1235 swap->is_active = swap->just_activated = false;
1236 }
1237
1238 return 0;
1239 }
1240
1241 manager_dispatch_load_queue(m);
1242
595ed347
MS
1243 LIST_FOREACH(units_by_type, u, m->units_by_type[UNIT_SWAP]) {
1244 Swap *swap = SWAP(u);
e04aad61
LP
1245
1246 if (!swap->is_active) {
e04aad61 1247
e04aad61
LP
1248 swap_unset_proc_swaps(swap);
1249
1250 switch (swap->state) {
1251
1252 case SWAP_ACTIVE:
ba6fbb2c 1253 /* This has just been deactivated */
e1770af8 1254 swap_enter_dead(swap, SWAP_SUCCESS);
e04aad61
LP
1255 break;
1256
1257 default:
5bcb0f2b 1258 /* Fire again */
e04aad61
LP
1259 swap_set_state(swap, swap->state);
1260 break;
1261 }
1262
628c89cc 1263 if (swap->what)
485ae697 1264 device_found_node(m, swap->what, 0, DEVICE_FOUND_SWAP);
628c89cc 1265
e04aad61
LP
1266 } else if (swap->just_activated) {
1267
1268 /* New swap entry */
1269
1270 switch (swap->state) {
1271
1272 case SWAP_DEAD:
1273 case SWAP_FAILED:
31135818
LP
1274 (void) unit_acquire_invocation_id(u);
1275 swap_cycle_clear(swap);
e1770af8 1276 swap_enter_active(swap, SWAP_SUCCESS);
e04aad61
LP
1277 break;
1278
5bcb0f2b
LP
1279 case SWAP_ACTIVATING:
1280 swap_set_state(swap, SWAP_ACTIVATING_DONE);
1281 break;
1282
e04aad61
LP
1283 default:
1284 /* Nothing really changed, but let's
1285 * issue an notification call
1286 * nonetheless, in case somebody is
1287 * waiting for this. */
1288 swap_set_state(swap, swap->state);
1289 break;
1290 }
1291 }
1292
1293 /* Reset the flags for later calls */
1294 swap->is_active = swap->just_activated = false;
1295 }
1296
1297 return 1;
1298}
1299
bcce581d
LP
1300static int swap_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
1301 Manager *m = userdata;
1302
1303 assert(m);
1304 assert(revents & EPOLLPRI);
1305
1306 return swap_process_proc_swaps(m);
1307}
1308
e04aad61
LP
1309static Unit *swap_following(Unit *u) {
1310 Swap *s = SWAP(u);
1311 Swap *other, *first = NULL;
1312
1313 assert(s);
1314
cdc89820
ZJS
1315 /* If the user configured the swap through /etc/fstab or
1316 * a device unit, follow that. */
1317
1318 if (s->from_fragment)
e04aad61
LP
1319 return NULL;
1320
caac2704 1321 LIST_FOREACH_OTHERS(same_devnode, other, s)
cdc89820
ZJS
1322 if (other->from_fragment)
1323 return UNIT(other);
1324
b938cb90 1325 /* Otherwise, make everybody follow the unit that's named after
cdc89820
ZJS
1326 * the swap device in the kernel */
1327
1328 if (streq_ptr(s->what, s->devnode))
1329 return NULL;
e04aad61 1330
9670d583
LP
1331 LIST_FOREACH_AFTER(same_devnode, other, s)
1332 if (streq_ptr(other->what, other->devnode))
e04aad61
LP
1333 return UNIT(other);
1334
9670d583
LP
1335 LIST_FOREACH_BEFORE(same_devnode, other, s) {
1336 if (streq_ptr(other->what, other->devnode))
e04aad61
LP
1337 return UNIT(other);
1338
1339 first = other;
1340 }
1341
cdc89820 1342 /* Fall back to the first on the list */
e04aad61 1343 return UNIT(first);
07b0b134
ML
1344}
1345
6210e7fc 1346static int swap_following_set(Unit *u, Set **_set) {
5bcb0f2b 1347 Swap *s = SWAP(u), *other;
af4fa99d 1348 _cleanup_set_free_ Set *set = NULL;
6210e7fc
LP
1349 int r;
1350
1351 assert(s);
1352 assert(_set);
1353
9670d583 1354 if (LIST_JUST_US(same_devnode, s)) {
6210e7fc
LP
1355 *_set = NULL;
1356 return 0;
1357 }
1358
d5099efc 1359 set = set_new(NULL);
5bcb0f2b 1360 if (!set)
6210e7fc
LP
1361 return -ENOMEM;
1362
caac2704 1363 LIST_FOREACH_OTHERS(same_devnode, other, s) {
5bcb0f2b
LP
1364 r = set_put(set, other);
1365 if (r < 0)
95f14a3e 1366 return r;
5bcb0f2b 1367 }
6210e7fc 1368
95f14a3e 1369 *_set = TAKE_PTR(set);
6210e7fc 1370 return 1;
6210e7fc
LP
1371}
1372
07b0b134
ML
1373static void swap_shutdown(Manager *m) {
1374 assert(m);
1375
718db961 1376 m->swap_event_source = sd_event_source_unref(m->swap_event_source);
74ca738f 1377 m->proc_swaps = safe_fclose(m->proc_swaps);
525d3cc7 1378 m->swaps_by_devnode = hashmap_free(m->swaps_by_devnode);
07b0b134
ML
1379}
1380
ba64af90 1381static void swap_enumerate(Manager *m) {
07b0b134 1382 int r;
9670d583 1383
07b0b134
ML
1384 assert(m);
1385
4e434314 1386 if (!m->proc_swaps) {
646134dc 1387 m->proc_swaps = fopen("/proc/swaps", "re");
ba64af90
LP
1388 if (!m->proc_swaps) {
1389 if (errno == ENOENT)
cb209a04 1390 log_debug_errno(errno, "Not swap enabled, skipping enumeration.");
ba64af90 1391 else
cb209a04 1392 log_warning_errno(errno, "Failed to open /proc/swaps, ignoring: %m");
ba64af90
LP
1393
1394 return;
1395 }
4e434314 1396
151b9b96 1397 r = sd_event_add_io(m->event, &m->swap_event_source, fileno(m->proc_swaps), EPOLLPRI, swap_dispatch_io, m);
ba64af90
LP
1398 if (r < 0) {
1399 log_error_errno(r, "Failed to watch /proc/swaps: %m");
29083707 1400 goto fail;
ba64af90 1401 }
29083707
LP
1402
1403 /* Dispatch this before we dispatch SIGCHLD, so that
1404 * we always get the events from /proc/swaps before
1405 * the SIGCHLD of /sbin/swapon. */
83231637 1406 r = sd_event_source_set_priority(m->swap_event_source, SD_EVENT_PRIORITY_NORMAL-10);
ba64af90
LP
1407 if (r < 0) {
1408 log_error_errno(r, "Failed to change /proc/swaps priority: %m");
718db961 1409 goto fail;
ba64af90 1410 }
7dfbe2e3
TG
1411
1412 (void) sd_event_source_set_description(m->swap_event_source, "swap-proc");
4e434314
LP
1413 }
1414
646134dc
ZJS
1415 r = swap_load_proc_swaps(m, false);
1416 if (r < 0)
718db961
LP
1417 goto fail;
1418
ba64af90 1419 return;
07b0b134 1420
718db961
LP
1421fail:
1422 swap_shutdown(m);
07b0b134
ML
1423}
1424
4366e598 1425int swap_process_device_new(Manager *m, sd_device *dev) {
9670d583 1426 _cleanup_free_ char *e = NULL;
4366e598 1427 const char *dn, *devlink;
cabf58b2 1428 Unit *u;
c53aafb7 1429 int r;
9670d583
LP
1430
1431 assert(m);
1432 assert(dev);
1433
4366e598
YW
1434 r = sd_device_get_devname(dev, &dn);
1435 if (r < 0)
9670d583
LP
1436 return 0;
1437
7410616c
LP
1438 r = unit_name_from_path(dn, ".swap", &e);
1439 if (r < 0)
1440 return r;
9670d583 1441
cabf58b2
FB
1442 u = manager_get_unit(m, e);
1443 if (u)
1444 r = swap_set_devnode(SWAP(u), dn);
9670d583 1445
4366e598 1446 FOREACH_DEVICE_DEVLINK(dev, devlink) {
9670d583 1447 _cleanup_free_ char *n = NULL;
7410616c 1448 int q;
9670d583 1449
4366e598 1450 q = unit_name_from_path(devlink, ".swap", &n);
7410616c
LP
1451 if (q < 0)
1452 return q;
9670d583 1453
cabf58b2
FB
1454 u = manager_get_unit(m, n);
1455 if (u) {
1456 q = swap_set_devnode(SWAP(u), dn);
9670d583
LP
1457 if (q < 0)
1458 r = q;
1459 }
1460 }
1461
1462 return r;
1463}
1464
4366e598 1465int swap_process_device_remove(Manager *m, sd_device *dev) {
9670d583 1466 const char *dn;
c53aafb7 1467 int r;
9670d583
LP
1468 Swap *s;
1469
4366e598
YW
1470 r = sd_device_get_devname(dev, &dn);
1471 if (r < 0)
9670d583
LP
1472 return 0;
1473
1474 while ((s = hashmap_get(m->swaps_by_devnode, dn))) {
1475 int q;
1476
1477 q = swap_set_devnode(s, NULL);
1478 if (q < 0)
1479 r = q;
1480 }
1481
1482 return r;
1483}
1484
fdf20a31 1485static void swap_reset_failed(Unit *u) {
5632e374
LP
1486 Swap *s = SWAP(u);
1487
1488 assert(s);
1489
fdf20a31 1490 if (s->state == SWAP_FAILED)
5632e374 1491 swap_set_state(s, SWAP_DEAD);
e04aad61 1492
e1770af8 1493 s->result = SWAP_SUCCESS;
a8b689b7 1494 s->clean_result = SWAP_SUCCESS;
5632e374
LP
1495}
1496
718db961 1497static int swap_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
814cc562 1498 return unit_kill_common(u, who, signo, -1, SWAP(u)->control_pid, error);
8a0867d6
LP
1499}
1500
7a7821c8 1501static int swap_get_timeout(Unit *u, usec_t *timeout) {
68db7a3b 1502 Swap *s = SWAP(u);
7a7821c8 1503 usec_t t;
68db7a3b
ZJS
1504 int r;
1505
1506 if (!s->timer_event_source)
1507 return 0;
1508
7a7821c8 1509 r = sd_event_source_get_time(s->timer_event_source, &t);
68db7a3b
ZJS
1510 if (r < 0)
1511 return r;
7a7821c8
LP
1512 if (t == USEC_INFINITY)
1513 return 0;
68db7a3b 1514
7a7821c8 1515 *timeout = t;
68db7a3b
ZJS
1516 return 1;
1517}
1518
1c2e9646 1519static bool swap_supported(void) {
0faacd47
LP
1520 static int supported = -1;
1521
1522 /* If swap support is not available in the kernel, or we are
1523 * running in a container we don't support swap units, and any
1524 * attempts to starting one should fail immediately. */
1525
1526 if (supported < 0)
1527 supported =
1528 access("/proc/swaps", F_OK) >= 0 &&
75f86906 1529 detect_container() <= 0;
0faacd47
LP
1530
1531 return supported;
1532}
1533
291d565a
LP
1534static int swap_control_pid(Unit *u) {
1535 Swap *s = SWAP(u);
1536
1537 assert(s);
1538
1539 return s->control_pid;
1540}
1541
a8b689b7
YW
1542static int swap_clean(Unit *u, ExecCleanMask mask) {
1543 _cleanup_strv_free_ char **l = NULL;
1544 Swap *s = SWAP(u);
1545 int r;
1546
1547 assert(s);
1548 assert(mask != 0);
1549
1550 if (s->state != SWAP_DEAD)
1551 return -EBUSY;
1552
1553 r = exec_context_get_clean_directories(&s->exec_context, u->manager->prefix, mask, &l);
1554 if (r < 0)
1555 return r;
1556
1557 if (strv_isempty(l))
1558 return -EUNATCH;
1559
1560 swap_unwatch_control_pid(s);
1561 s->clean_result = SWAP_SUCCESS;
1562 s->control_command = NULL;
1563 s->control_command_id = _SWAP_EXEC_COMMAND_INVALID;
1564
1565 r = swap_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->exec_context.timeout_clean_usec));
1566 if (r < 0)
1567 goto fail;
1568
1569 r = unit_fork_and_watch_rm_rf(u, l, &s->control_pid);
1570 if (r < 0)
1571 goto fail;
1572
1573 swap_set_state(s, SWAP_CLEANING);
1574
1575 return 0;
1576
1577fail:
1578 log_unit_warning_errno(u, r, "Failed to initiate cleaning: %m");
1579 s->clean_result = SWAP_FAILURE_RESOURCES;
1580 s->timer_event_source = sd_event_source_unref(s->timer_event_source);
1581 return r;
1582}
1583
1584static int swap_can_clean(Unit *u, ExecCleanMask *ret) {
1585 Swap *s = SWAP(u);
1586
1587 assert(s);
1588
1589 return exec_context_get_clean_mask(&s->exec_context, ret);
1590}
1591
e04aad61
LP
1592static const char* const swap_exec_command_table[_SWAP_EXEC_COMMAND_MAX] = {
1593 [SWAP_EXEC_ACTIVATE] = "ExecActivate",
1594 [SWAP_EXEC_DEACTIVATE] = "ExecDeactivate",
1595};
1596
1597DEFINE_STRING_TABLE_LOOKUP(swap_exec_command, SwapExecCommand);
1598
e1770af8
LP
1599static const char* const swap_result_table[_SWAP_RESULT_MAX] = {
1600 [SWAP_SUCCESS] = "success",
1601 [SWAP_FAILURE_RESOURCES] = "resources",
1602 [SWAP_FAILURE_TIMEOUT] = "timeout",
1603 [SWAP_FAILURE_EXIT_CODE] = "exit-code",
1604 [SWAP_FAILURE_SIGNAL] = "signal",
07299350
LP
1605 [SWAP_FAILURE_CORE_DUMP] = "core-dump",
1606 [SWAP_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
e1770af8
LP
1607};
1608
1609DEFINE_STRING_TABLE_LOOKUP(swap_result, SwapResult);
1610
07b0b134 1611const UnitVTable swap_vtable = {
7d17cfbc 1612 .object_size = sizeof(Swap),
718db961
LP
1613 .exec_context_offset = offsetof(Swap, exec_context),
1614 .cgroup_context_offset = offsetof(Swap, cgroup_context),
1615 .kill_context_offset = offsetof(Swap, kill_context),
613b411c 1616 .exec_runtime_offset = offsetof(Swap, exec_runtime),
29206d46 1617 .dynamic_creds_offset = offsetof(Swap, dynamic_creds),
3ef63c31 1618
f975e971
LP
1619 .sections =
1620 "Unit\0"
1621 "Swap\0"
1622 "Install\0",
4ad49000 1623 .private_section = "Swap",
71645aca 1624
c80a9a33
LP
1625 .can_fail = true,
1626
4e85aff4 1627 .init = swap_init,
07b0b134 1628 .load = swap_load,
6e620bec 1629 .done = swap_done,
07b0b134
ML
1630
1631 .coldplug = swap_coldplug,
1632
1633 .dump = swap_dump,
1634
1635 .start = swap_start,
1636 .stop = swap_stop,
1637
8a0867d6 1638 .kill = swap_kill,
a8b689b7
YW
1639 .clean = swap_clean,
1640 .can_clean = swap_can_clean,
8a0867d6 1641
68db7a3b
ZJS
1642 .get_timeout = swap_get_timeout,
1643
07b0b134
ML
1644 .serialize = swap_serialize,
1645 .deserialize_item = swap_deserialize_item,
1646
1647 .active_state = swap_active_state,
1648 .sub_state_to_string = swap_sub_state_to_string,
1649
52a12341
YW
1650 .will_restart = unit_will_restart_default,
1651
f2f725e5 1652 .may_gc = swap_may_gc,
39c79477 1653 .is_extrinsic = swap_is_extrinsic,
07b0b134 1654
e04aad61 1655 .sigchld_event = swap_sigchld_event,
e04aad61
LP
1656
1657 .reset_failed = swap_reset_failed,
1658
291d565a
LP
1659 .control_pid = swap_control_pid,
1660
74c964d3
LP
1661 .bus_set_property = bus_swap_set_property,
1662 .bus_commit_properties = bus_swap_commit_properties,
07b0b134 1663
e04aad61 1664 .following = swap_following,
6210e7fc 1665 .following_set = swap_following_set,
5632e374 1666
6e620bec 1667 .enumerate = swap_enumerate,
c6918296 1668 .shutdown = swap_shutdown,
0faacd47 1669 .supported = swap_supported,
c6918296
MS
1670
1671 .status_message_formats = {
1672 .starting_stopping = {
1673 [0] = "Activating swap %s...",
1674 [1] = "Deactivating swap %s...",
1675 },
1676 .finished_start_job = {
1677 [JOB_DONE] = "Activated swap %s.",
1678 [JOB_FAILED] = "Failed to activate swap %s.",
c6918296
MS
1679 [JOB_TIMEOUT] = "Timed out activating swap %s.",
1680 },
1681 .finished_stop_job = {
1682 [JOB_DONE] = "Deactivated swap %s.",
1683 [JOB_FAILED] = "Failed deactivating swap %s.",
1684 [JOB_TIMEOUT] = "Timed out deactivating swap %s.",
1685 },
1686 },
07b0b134 1687};