LCOV - code coverage report
Current view: top level - core - swap.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 291 798 36.5 %
Date: 2019-08-23 13:36:53 Functions: 29 53 54.7 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 201 787 25.5 %

           Branch data     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                 :        264 : static bool SWAP_STATE_WITH_PROCESS(SwapState state) {
      49         [ -  + ]:        264 :         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                 :        264 : static void swap_unset_proc_swaps(Swap *s) {
      58         [ -  + ]:        264 :         assert(s);
      59                 :            : 
      60         [ -  + ]:        264 :         if (!s->from_proc_swaps)
      61                 :          0 :                 return;
      62                 :            : 
      63                 :        264 :         s->parameters_proc_swaps.what = mfree(s->parameters_proc_swaps.what);
      64                 :            : 
      65                 :        264 :         s->from_proc_swaps = false;
      66                 :            : }
      67                 :            : 
      68                 :        528 : static int swap_set_devnode(Swap *s, const char *devnode) {
      69                 :            :         Hashmap *swaps;
      70                 :            :         Swap *first;
      71                 :            :         int r;
      72                 :            : 
      73         [ -  + ]:        528 :         assert(s);
      74                 :            : 
      75         [ +  - ]:        528 :         r = hashmap_ensure_allocated(&UNIT(s)->manager->swaps_by_devnode, &path_hash_ops);
      76         [ -  + ]:        528 :         if (r < 0)
      77                 :          0 :                 return r;
      78                 :            : 
      79         [ +  - ]:        528 :         swaps = UNIT(s)->manager->swaps_by_devnode;
      80                 :            : 
      81         [ +  + ]:        528 :         if (s->devnode) {
      82                 :        264 :                 first = hashmap_get(swaps, s->devnode);
      83                 :            : 
      84   [ -  +  +  +  :        264 :                 LIST_REMOVE(same_devnode, first, s);
             +  +  -  + ]
      85         [ +  + ]:        264 :                 if (first)
      86                 :        220 :                         hashmap_replace(swaps, first->devnode, first);
      87                 :            :                 else
      88                 :         44 :                         hashmap_remove(swaps, s->devnode);
      89                 :            : 
      90                 :        264 :                 s->devnode = mfree(s->devnode);
      91                 :            :         }
      92                 :            : 
      93         [ +  + ]:        528 :         if (devnode) {
      94                 :        264 :                 s->devnode = strdup(devnode);
      95         [ -  + ]:        264 :                 if (!s->devnode)
      96                 :          0 :                         return -ENOMEM;
      97                 :            : 
      98                 :        264 :                 first = hashmap_get(swaps, s->devnode);
      99   [ -  +  +  + ]:        264 :                 LIST_PREPEND(same_devnode, first, s);
     100                 :            : 
     101                 :        264 :                 return hashmap_replace(swaps, first->devnode, first);
     102                 :            :         }
     103                 :            : 
     104                 :        264 :         return 0;
     105                 :            : }
     106                 :            : 
     107                 :        264 : static void swap_init(Unit *u) {
     108                 :        264 :         Swap *s = SWAP(u);
     109                 :            : 
     110         [ -  + ]:        264 :         assert(s);
     111   [ +  -  -  + ]:        264 :         assert(UNIT(s)->load_state == UNIT_STUB);
     112                 :            : 
     113                 :        264 :         s->timeout_usec = u->manager->default_timeout_start_usec;
     114                 :            : 
     115                 :        264 :         s->exec_context.std_output = u->manager->default_std_output;
     116                 :        264 :         s->exec_context.std_error = u->manager->default_std_error;
     117                 :            : 
     118                 :        264 :         s->parameters_proc_swaps.priority = s->parameters_fragment.priority = -1;
     119                 :            : 
     120                 :        264 :         s->control_command_id = _SWAP_EXEC_COMMAND_INVALID;
     121                 :            : 
     122                 :        264 :         u->ignore_on_isolate = true;
     123                 :        264 : }
     124                 :            : 
     125                 :        528 : static void swap_unwatch_control_pid(Swap *s) {
     126         [ -  + ]:        528 :         assert(s);
     127                 :            : 
     128         [ +  - ]:        528 :         if (s->control_pid <= 0)
     129                 :        528 :                 return;
     130                 :            : 
     131         [ #  # ]:          0 :         unit_unwatch_pid(UNIT(s), s->control_pid);
     132                 :          0 :         s->control_pid = 0;
     133                 :            : }
     134                 :            : 
     135                 :        264 : static void swap_done(Unit *u) {
     136                 :        264 :         Swap *s = SWAP(u);
     137                 :            : 
     138         [ -  + ]:        264 :         assert(s);
     139                 :            : 
     140                 :        264 :         swap_unset_proc_swaps(s);
     141                 :        264 :         swap_set_devnode(s, NULL);
     142                 :            : 
     143                 :        264 :         s->what = mfree(s->what);
     144                 :        264 :         s->parameters_fragment.what = mfree(s->parameters_fragment.what);
     145                 :        264 :         s->parameters_fragment.options = mfree(s->parameters_fragment.options);
     146                 :            : 
     147                 :        264 :         s->exec_runtime = exec_runtime_unref(s->exec_runtime, false);
     148                 :        264 :         exec_command_done_array(s->exec_command, _SWAP_EXEC_COMMAND_MAX);
     149                 :        264 :         s->control_command = NULL;
     150                 :            : 
     151                 :        264 :         dynamic_creds_unref(&s->dynamic_creds);
     152                 :            : 
     153                 :        264 :         swap_unwatch_control_pid(s);
     154                 :            : 
     155                 :        264 :         s->timer_event_source = sd_event_source_unref(s->timer_event_source);
     156                 :        264 : }
     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                 :        264 : static int swap_add_device_dependencies(Swap *s) {
     189         [ -  + ]:        264 :         assert(s);
     190                 :            : 
     191         [ -  + ]:        264 :         if (!s->what)
     192                 :          0 :                 return 0;
     193                 :            : 
     194         [ +  - ]:        264 :         if (!s->from_fragment)
     195                 :        264 :                 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                 :        264 : static int swap_add_default_dependencies(Swap *s) {
     207                 :            :         int r;
     208                 :            : 
     209         [ -  + ]:        264 :         assert(s);
     210                 :            : 
     211   [ +  -  -  + ]:        264 :         if (!UNIT(s)->default_dependencies)
     212                 :          0 :                 return 0;
     213                 :            : 
     214   [ +  -  +  - ]:        264 :         if (!MANAGER_IS_SYSTEM(UNIT(s)->manager))
     215                 :        264 :                 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                 :        264 : static int swap_verify(Swap *s) {
     230                 :        264 :         _cleanup_free_ char *e = NULL;
     231                 :            :         int r;
     232                 :            : 
     233   [ +  -  -  + ]:        264 :         if (UNIT(s)->load_state != UNIT_LOADED)
     234                 :          0 :                 return 0;
     235                 :            : 
     236                 :        264 :         r = unit_name_from_path(s->what, ".swap", &e);
     237         [ -  + ]:        264 :         if (r < 0)
     238   [ #  #  #  # ]:          0 :                 return log_unit_error_errno(UNIT(s), r, "Failed to generate unit name from path: %m");
     239                 :            : 
     240   [ +  -  -  + ]:        264 :         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   [ -  +  #  # ]:        264 :         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                 :        264 :         return 0;
     251                 :            : }
     252                 :            : 
     253                 :        264 : static int swap_load_devnode(Swap *s) {
     254                 :        264 :         _cleanup_(sd_device_unrefp) sd_device *d = NULL;
     255                 :            :         struct stat st;
     256                 :            :         const char *p;
     257                 :            :         int r;
     258                 :            : 
     259         [ -  + ]:        264 :         assert(s);
     260                 :            : 
     261   [ +  -  -  + ]:        264 :         if (stat(s->what, &st) < 0 || !S_ISBLK(st.st_mode))
     262                 :          0 :                 return 0;
     263                 :            : 
     264                 :        264 :         r = device_new_from_stat_rdev(&d, &st);
     265         [ -  + ]:        264 :         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         [ -  + ]:        264 :         if (sd_device_get_devname(d, &p) < 0)
     272                 :          0 :                 return 0;
     273                 :            : 
     274                 :        264 :         return swap_set_devnode(s, p);
     275                 :            : }
     276                 :            : 
     277                 :        264 : static int swap_add_extras(Swap *s) {
     278                 :            :         int r;
     279                 :            : 
     280         [ -  + ]:        264 :         assert(s);
     281                 :            : 
     282   [ +  -  -  + ]:        264 :         if (UNIT(s)->fragment_path)
     283                 :          0 :                 s->from_fragment = true;
     284                 :            : 
     285         [ -  + ]:        264 :         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                 :        264 :         path_simplify(s->what, false);
     301                 :            : 
     302   [ +  -  +  - ]:        264 :         if (!UNIT(s)->description) {
     303         [ +  - ]:        264 :                 r = unit_set_description(UNIT(s), s->what);
     304         [ -  + ]:        264 :                 if (r < 0)
     305                 :          0 :                         return r;
     306                 :            :         }
     307                 :            : 
     308         [ +  - ]:        264 :         r = unit_require_mounts_for(UNIT(s), s->what, UNIT_DEPENDENCY_IMPLICIT);
     309         [ -  + ]:        264 :         if (r < 0)
     310                 :          0 :                 return r;
     311                 :            : 
     312                 :        264 :         r = swap_add_device_dependencies(s);
     313         [ -  + ]:        264 :         if (r < 0)
     314                 :          0 :                 return r;
     315                 :            : 
     316                 :        264 :         r = swap_load_devnode(s);
     317         [ -  + ]:        264 :         if (r < 0)
     318                 :          0 :                 return r;
     319                 :            : 
     320         [ +  - ]:        264 :         r = unit_patch_contexts(UNIT(s));
     321         [ -  + ]:        264 :         if (r < 0)
     322                 :          0 :                 return r;
     323                 :            : 
     324         [ +  - ]:        264 :         r = unit_add_exec_dependencies(UNIT(s), &s->exec_context);
     325         [ -  + ]:        264 :         if (r < 0)
     326                 :          0 :                 return r;
     327                 :            : 
     328         [ +  - ]:        264 :         r = unit_set_default_slice(UNIT(s));
     329         [ -  + ]:        264 :         if (r < 0)
     330                 :          0 :                 return r;
     331                 :            : 
     332                 :        264 :         r = swap_add_default_dependencies(s);
     333         [ -  + ]:        264 :         if (r < 0)
     334                 :          0 :                 return r;
     335                 :            : 
     336                 :        264 :         return 0;
     337                 :            : }
     338                 :            : 
     339                 :        264 : static int swap_load(Unit *u) {
     340                 :        264 :         Swap *s = SWAP(u);
     341                 :            :         int r, q;
     342                 :            : 
     343         [ -  + ]:        264 :         assert(s);
     344         [ -  + ]:        264 :         assert(u->load_state == UNIT_STUB);
     345                 :            : 
     346                 :            :         /* Load a .swap file */
     347         [ +  - ]:        264 :         if (SWAP(u)->from_proc_swaps)
     348                 :        264 :                 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   [ -  +  #  # ]:        264 :         if (u->load_state == UNIT_LOADED || s->from_proc_swaps)
     355                 :        264 :                 q = swap_add_extras(s);
     356                 :            :         else
     357                 :          0 :                 q = 0;
     358                 :            : 
     359         [ -  + ]:        264 :         if (r < 0)
     360                 :          0 :                 return r;
     361         [ -  + ]:        264 :         if (q < 0)
     362                 :          0 :                 return q;
     363                 :            : 
     364                 :        264 :         return swap_verify(s);
     365                 :            : }
     366                 :            : 
     367                 :        264 : 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                 :        264 :         _cleanup_free_ char *e = NULL;
     375                 :        264 :         bool delete = false;
     376                 :        264 :         Unit *u = NULL;
     377                 :            :         int r;
     378                 :            :         SwapParameters *p;
     379                 :            : 
     380         [ -  + ]:        264 :         assert(m);
     381         [ -  + ]:        264 :         assert(what);
     382         [ -  + ]:        264 :         assert(what_proc_swaps);
     383                 :            : 
     384                 :        264 :         r = unit_name_from_path(what, ".swap", &e);
     385         [ -  + ]:        264 :         if (r < 0)
     386         [ #  # ]:          0 :                 return log_unit_error_errno(u, r, "Failed to generate unit name from path: %m");
     387                 :            : 
     388                 :        264 :         u = manager_get_unit(m, e);
     389   [ -  +  #  # ]:        264 :         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         [ +  - ]:        264 :         if (!u) {
     397                 :        264 :                 delete = true;
     398                 :            : 
     399                 :        264 :                 r = unit_new_for_name(m, sizeof(Swap), e, &u);
     400         [ -  + ]:        264 :                 if (r < 0)
     401                 :          0 :                         goto fail;
     402                 :            : 
     403                 :        264 :                 SWAP(u)->what = strdup(what);
     404         [ -  + ]:        264 :                 if (!SWAP(u)->what) {
     405                 :          0 :                         r = -ENOMEM;
     406                 :          0 :                         goto fail;
     407                 :            :                 }
     408                 :            : 
     409                 :        264 :                 unit_add_to_load_queue(u);
     410                 :            :         } else
     411                 :          0 :                 delete = false;
     412                 :            : 
     413                 :        264 :         p = &SWAP(u)->parameters_proc_swaps;
     414                 :            : 
     415         [ +  - ]:        264 :         if (!p->what) {
     416                 :        264 :                 p->what = strdup(what_proc_swaps);
     417         [ -  + ]:        264 :                 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   [ -  +  -  + ]:        264 :         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         [ -  + ]:        264 :         if (set_flags) {
     431                 :          0 :                 SWAP(u)->is_active = true;
     432                 :          0 :                 SWAP(u)->just_activated = !SWAP(u)->from_proc_swaps;
     433                 :            :         }
     434                 :            : 
     435                 :        264 :         SWAP(u)->from_proc_swaps = true;
     436                 :            : 
     437                 :        264 :         p->priority = priority;
     438                 :            : 
     439                 :        264 :         unit_add_to_dbus_queue(u);
     440                 :        264 :         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                 :         44 : static int swap_process_new(Manager *m, const char *device, int prio, bool set_flags) {
     452                 :         44 :         _cleanup_(sd_device_unrefp) sd_device *d = NULL;
     453                 :            :         const char *dn, *devlink;
     454                 :            :         struct stat st, st_link;
     455                 :            :         int r;
     456                 :            : 
     457         [ -  + ]:         44 :         assert(m);
     458                 :            : 
     459                 :         44 :         r = swap_setup_unit(m, device, device, prio, set_flags);
     460         [ -  + ]:         44 :         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   [ +  -  -  + ]:         44 :         if (stat(device, &st) < 0 || !S_ISBLK(st.st_mode))
     466                 :          0 :                 return 0;
     467                 :            : 
     468                 :         44 :         r = device_new_from_stat_rdev(&d, &st);
     469         [ -  + ]:         44 :         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   [ +  -  -  + ]:         44 :         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         [ +  + ]:        264 :         FOREACH_DEVICE_DEVLINK(d, devlink) {
     481                 :            : 
     482                 :            :                 /* Don't bother with the /dev/block links */
     483         [ -  + ]:        220 :                 if (streq(devlink, device))
     484                 :          0 :                         continue;
     485                 :            : 
     486         [ -  + ]:        220 :                 if (path_startswith(devlink, "/dev/block/"))
     487                 :          0 :                         continue;
     488                 :            : 
     489         [ +  - ]:        220 :                 if (stat(devlink, &st_link) >= 0 &&
     490         [ +  - ]:        220 :                     (!S_ISBLK(st_link.st_mode) ||
     491         [ -  + ]:        220 :                      st_link.st_rdev != st.st_rdev))
     492                 :          0 :                         continue;
     493                 :            : 
     494                 :        220 :                 swap_setup_unit(m, devlink, device, prio, set_flags);
     495                 :            :         }
     496                 :            : 
     497                 :         44 :         return 0;
     498                 :            : }
     499                 :            : 
     500                 :        264 : static void swap_set_state(Swap *s, SwapState state) {
     501                 :            :         SwapState old_state;
     502                 :            :         Swap *other;
     503                 :            : 
     504         [ -  + ]:        264 :         assert(s);
     505                 :            : 
     506         [ +  - ]:        264 :         if (s->state != state)
     507         [ +  - ]:        264 :                 bus_unit_send_pending_change_signal(UNIT(s), false);
     508                 :            : 
     509                 :        264 :         old_state = s->state;
     510                 :        264 :         s->state = state;
     511                 :            : 
     512         [ +  - ]:        264 :         if (!SWAP_STATE_WITH_PROCESS(state)) {
     513                 :        264 :                 s->timer_event_source = sd_event_source_unref(s->timer_event_source);
     514                 :        264 :                 swap_unwatch_control_pid(s);
     515                 :        264 :                 s->control_command = NULL;
     516                 :        264 :                 s->control_command_id = _SWAP_EXEC_COMMAND_INVALID;
     517                 :            :         }
     518                 :            : 
     519         [ +  - ]:        264 :         if (state != old_state)
     520   [ +  -  +  - ]:        264 :                 log_unit_debug(UNIT(s), "Changed %s -> %s", swap_state_to_string(old_state), swap_state_to_string(state));
     521                 :            : 
     522         [ +  - ]:        264 :         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   [ +  -  +  +  :       2244 :         LIST_FOREACH_OTHERS(same_devnode, other, s)
          +  +  +  +  +  
                      + ]
     530   [ +  -  -  + ]:       1320 :                 if (UNIT(other)->job)
     531         [ #  # ]:          0 :                         job_add_to_run_queue(UNIT(other)->job);
     532                 :        264 : }
     533                 :            : 
     534                 :        264 : static int swap_coldplug(Unit *u) {
     535                 :        264 :         Swap *s = SWAP(u);
     536                 :        264 :         SwapState new_state = SWAP_DEAD;
     537                 :            :         int r;
     538                 :            : 
     539         [ -  + ]:        264 :         assert(s);
     540         [ -  + ]:        264 :         assert(s->state == SWAP_DEAD);
     541                 :            : 
     542         [ -  + ]:        264 :         if (s->deserialized_state != s->state)
     543                 :          0 :                 new_state = s->deserialized_state;
     544         [ +  - ]:        264 :         else if (s->from_proc_swaps)
     545                 :        264 :                 new_state = SWAP_ACTIVE;
     546                 :            : 
     547         [ -  + ]:        264 :         if (new_state == s->state)
     548                 :          0 :                 return 0;
     549                 :            : 
     550   [ -  +  #  # ]:        264 :         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   [ -  +  +  - ]:        264 :         if (!IN_SET(new_state, SWAP_DEAD, SWAP_FAILED)) {
     564                 :        264 :                 (void) unit_setup_dynamic_creds(u);
     565                 :        264 :                 (void) unit_setup_exec_runtime(u);
     566                 :            :         }
     567                 :            : 
     568                 :        264 :         swap_set_state(s, new_state);
     569                 :        264 :         return 0;
     570                 :            : }
     571                 :            : 
     572                 :        144 : static void swap_dump(Unit *u, FILE *f, const char *prefix) {
     573                 :            :         char buf[FORMAT_TIMESPAN_MAX];
     574                 :        144 :         Swap *s = SWAP(u);
     575                 :            :         SwapParameters *p;
     576                 :            : 
     577         [ -  + ]:        144 :         assert(s);
     578         [ -  + ]:        144 :         assert(f);
     579                 :            : 
     580         [ +  - ]:        144 :         if (s->from_proc_swaps)
     581                 :        144 :                 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                 :        144 :         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                 :        144 :                 prefix, yes_no(s->from_proc_swaps),
     597                 :        144 :                 prefix, yes_no(s->from_fragment));
     598                 :            : 
     599         [ +  - ]:        144 :         if (s->devnode)
     600                 :        144 :                 fprintf(f, "%sDevice Node: %s\n", prefix, s->devnode);
     601                 :            : 
     602         [ +  - ]:        144 :         if (p)
     603                 :        144 :                 fprintf(f,
     604                 :            :                         "%sPriority: %i\n"
     605                 :            :                         "%sOptions: %s\n",
     606                 :            :                         prefix, p->priority,
     607                 :        144 :                         prefix, strempty(p->options));
     608                 :            : 
     609                 :        144 :         fprintf(f,
     610                 :            :                 "%sTimeoutSec: %s\n",
     611                 :            :                 prefix, format_timespan(buf, sizeof(buf), s->timeout_usec, USEC_PER_SEC));
     612                 :            : 
     613         [ -  + ]:        144 :         if (s->control_pid > 0)
     614                 :          0 :                 fprintf(f,
     615                 :            :                         "%sControl PID: "PID_FMT"\n",
     616                 :            :                         prefix, s->control_pid);
     617                 :            : 
     618                 :        144 :         exec_context_dump(&s->exec_context, f, prefix);
     619                 :        144 :         kill_context_dump(&s->kill_context, f, prefix);
     620                 :        144 :         cgroup_context_dump(&s->cgroup_context, f, prefix);
     621                 :        144 : }
     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                 :       2540 : _pure_ static UnitActiveState swap_active_state(Unit *u) {
     986         [ -  + ]:       2540 :         assert(u);
     987                 :            : 
     988                 :       2540 :         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                 :        264 : _pure_ static bool swap_may_gc(Unit *u) {
     998                 :        264 :         Swap *s = SWAP(u);
     999                 :            : 
    1000         [ -  + ]:        264 :         assert(s);
    1001                 :            : 
    1002         [ +  - ]:        264 :         if (s->from_proc_swaps)
    1003                 :        264 :                 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                 :         44 : static int swap_load_proc_swaps(Manager *m, bool set_flags) {
    1120                 :            :         unsigned i;
    1121                 :            : 
    1122         [ -  + ]:         44 :         assert(m);
    1123                 :            : 
    1124                 :         44 :         rewind(m->proc_swaps);
    1125                 :            : 
    1126                 :         44 :         (void) fscanf(m->proc_swaps, "%*s %*s %*s %*s %*s\n");
    1127                 :            : 
    1128                 :         88 :         for (i = 1;; i++) {
    1129   [ +  +  -  -  :        132 :                 _cleanup_free_ char *dev = NULL, *d = NULL;
             +  +  -  - ]
    1130                 :         88 :                 int prio = 0, k;
    1131                 :            : 
    1132                 :         88 :                 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         [ +  + ]:         88 :                 if (k != 2) {
    1140         [ +  - ]:         44 :                         if (k == EOF)
    1141                 :         44 :                                 break;
    1142                 :            : 
    1143         [ #  # ]:          0 :                         log_warning("Failed to parse /proc/swaps:%u.", i);
    1144                 :          0 :                         continue;
    1145                 :            :                 }
    1146                 :            : 
    1147         [ -  + ]:         44 :                 if (cunescape(dev, UNESCAPE_RELAX, &d) < 0)
    1148                 :          0 :                         return log_oom();
    1149                 :            : 
    1150                 :         44 :                 device_found_node(m, d, DEVICE_FOUND_SWAP, DEVICE_FOUND_SWAP);
    1151                 :            : 
    1152                 :         44 :                 (void) swap_process_new(m, d, prio, set_flags);
    1153                 :            :         }
    1154                 :            : 
    1155                 :         44 :         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                 :        144 : static Unit *swap_following(Unit *u) {
    1247                 :        144 :         Swap *s = SWAP(u);
    1248                 :        144 :         Swap *other, *first = NULL;
    1249                 :            : 
    1250         [ -  + ]:        144 :         assert(s);
    1251                 :            : 
    1252                 :            :         /* If the user configured the swap through /etc/fstab or
    1253                 :            :          * a device unit, follow that. */
    1254                 :            : 
    1255         [ -  + ]:        144 :         if (s->from_fragment)
    1256                 :          0 :                 return NULL;
    1257                 :            : 
    1258   [ +  -  +  +  :       1224 :         LIST_FOREACH_OTHERS(same_devnode, other, s)
          +  +  +  +  +  
                      + ]
    1259         [ -  + ]:        720 :                 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         [ +  + ]:        144 :         if (streq_ptr(s->what, s->devnode))
    1266                 :         24 :                 return NULL;
    1267                 :            : 
    1268         [ +  + ]:        360 :         LIST_FOREACH_AFTER(same_devnode, other, s)
    1269         [ -  + ]:        240 :                 if (streq_ptr(other->what, other->devnode))
    1270         [ #  # ]:          0 :                         return UNIT(other);
    1271                 :            : 
    1272         [ +  - ]:        360 :         LIST_FOREACH_BEFORE(same_devnode, other, s) {
    1273         [ +  + ]:        360 :                 if (streq_ptr(other->what, other->devnode))
    1274         [ +  - ]:        120 :                         return UNIT(other);
    1275                 :            : 
    1276                 :        240 :                 first = other;
    1277                 :            :         }
    1278                 :            : 
    1279                 :            :         /* Fall back to the first on the list */
    1280         [ #  # ]:          0 :         return UNIT(first);
    1281                 :            : }
    1282                 :            : 
    1283                 :        144 : static int swap_following_set(Unit *u, Set **_set) {
    1284                 :        144 :         Swap *s = SWAP(u), *other;
    1285                 :        144 :         _cleanup_set_free_ Set *set = NULL;
    1286                 :            :         int r;
    1287                 :            : 
    1288         [ -  + ]:        144 :         assert(s);
    1289         [ -  + ]:        144 :         assert(_set);
    1290                 :            : 
    1291   [ +  +  -  + ]:        144 :         if (LIST_JUST_US(same_devnode, s)) {
    1292                 :          0 :                 *_set = NULL;
    1293                 :          0 :                 return 0;
    1294                 :            :         }
    1295                 :            : 
    1296                 :        144 :         set = set_new(NULL);
    1297         [ -  + ]:        144 :         if (!set)
    1298                 :          0 :                 return -ENOMEM;
    1299                 :            : 
    1300   [ +  -  +  +  :       1224 :         LIST_FOREACH_OTHERS(same_devnode, other, s) {
          +  +  +  +  +  
                      + ]
    1301                 :        720 :                 r = set_put(set, other);
    1302         [ -  + ]:        720 :                 if (r < 0)
    1303                 :          0 :                         return r;
    1304                 :            :         }
    1305                 :            : 
    1306                 :        144 :         *_set = TAKE_PTR(set);
    1307                 :        144 :         return 1;
    1308                 :            : }
    1309                 :            : 
    1310                 :         56 : static void swap_shutdown(Manager *m) {
    1311         [ -  + ]:         56 :         assert(m);
    1312                 :            : 
    1313                 :         56 :         m->swap_event_source = sd_event_source_unref(m->swap_event_source);
    1314                 :         56 :         m->proc_swaps = safe_fclose(m->proc_swaps);
    1315                 :         56 :         m->swaps_by_devnode = hashmap_free(m->swaps_by_devnode);
    1316                 :         56 : }
    1317                 :            : 
    1318                 :         44 : static void swap_enumerate(Manager *m) {
    1319                 :            :         int r;
    1320                 :            : 
    1321         [ -  + ]:         44 :         assert(m);
    1322                 :            : 
    1323         [ +  - ]:         44 :         if (!m->proc_swaps) {
    1324                 :         44 :                 m->proc_swaps = fopen("/proc/swaps", "re");
    1325         [ -  + ]:         44 :                 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                 :         44 :                 r = sd_event_add_io(m->event, &m->swap_event_source, fileno(m->proc_swaps), EPOLLPRI, swap_dispatch_io, m);
    1335         [ -  + ]:         44 :                 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                 :         44 :                 r = sd_event_source_set_priority(m->swap_event_source, SD_EVENT_PRIORITY_NORMAL-10);
    1344         [ -  + ]:         44 :                 if (r < 0) {
    1345         [ #  # ]:          0 :                         log_error_errno(r, "Failed to change /proc/swaps priority: %m");
    1346                 :          0 :                         goto fail;
    1347                 :            :                 }
    1348                 :            : 
    1349                 :         44 :                 (void) sd_event_source_set_description(m->swap_event_source, "swap-proc");
    1350                 :            :         }
    1351                 :            : 
    1352                 :         44 :         r = swap_load_proc_swaps(m, false);
    1353         [ -  + ]:         44 :         if (r < 0)
    1354                 :          0 :                 goto fail;
    1355                 :            : 
    1356                 :         44 :         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                 :         88 : 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         [ +  + ]:         88 :         if (supported < 0)
    1463                 :         20 :                 supported =
    1464   [ +  -  +  - ]:         40 :                         access("/proc/swaps", F_OK) >= 0 &&
    1465                 :         20 :                         detect_container() <= 0;
    1466                 :            : 
    1467                 :         88 :         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   [ +  +  +  + ]:         32 : 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   [ +  +  +  + ]:        216 : 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