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