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