LCOV - code coverage report
Current view: top level - core - swap.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 291 798 36.5 %
Date: 2019-08-22 15:41:25 Functions: 29 53 54.7 %

          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             : };

Generated by: LCOV version 1.14