LCOV - code coverage report
Current view: top level - core - swap.c (source / functions) Hit Total Coverage
Test: systemd test coverage Lines: 44 762 5.8 %
Date: 2015-07-29 18:47:03 Functions: 10 49 20.4 %

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

Generated by: LCOV version 1.11