LCOV - code coverage report
Current view: top level - core - slice.c (source / functions) Hit Total Coverage
Test: systemd test coverage Lines: 75 120 62.5 %
Date: 2015-07-29 18:47:03 Functions: 11 16 68.8 %

          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 2013 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             : 
      24             : #include "unit.h"
      25             : #include "slice.h"
      26             : #include "log.h"
      27             : #include "dbus-slice.h"
      28             : #include "special.h"
      29             : #include "unit-name.h"
      30             : 
      31             : static const UnitActiveState state_translation_table[_SLICE_STATE_MAX] = {
      32             :         [SLICE_DEAD] = UNIT_INACTIVE,
      33             :         [SLICE_ACTIVE] = UNIT_ACTIVE
      34             : };
      35             : 
      36           6 : static void slice_set_state(Slice *t, SliceState state) {
      37             :         SliceState old_state;
      38           6 :         assert(t);
      39             : 
      40           6 :         old_state = t->state;
      41           6 :         t->state = state;
      42             : 
      43           6 :         if (state != old_state)
      44           6 :                 log_debug("%s changed %s -> %s",
      45             :                           UNIT(t)->id,
      46             :                           slice_state_to_string(old_state),
      47             :                           slice_state_to_string(state));
      48             : 
      49           6 :         unit_notify(UNIT(t), state_translation_table[old_state], state_translation_table[state], true);
      50           6 : }
      51             : 
      52          12 : static int slice_add_parent_slice(Slice *s) {
      53             :         char *a, *dash;
      54             :         Unit *parent;
      55             :         int r;
      56             : 
      57          12 :         assert(s);
      58             : 
      59          12 :         if (UNIT_ISSET(UNIT(s)->slice))
      60           0 :                 return 0;
      61             : 
      62          12 :         if (unit_has_name(UNIT(s), SPECIAL_ROOT_SLICE))
      63          10 :                 return 0;
      64             : 
      65           2 :         a = strdupa(UNIT(s)->id);
      66           2 :         dash = strrchr(a, '-');
      67           2 :         if (dash)
      68           1 :                 strcpy(dash, ".slice");
      69             :         else
      70           1 :                 a = (char*) SPECIAL_ROOT_SLICE;
      71             : 
      72           2 :         r = manager_load_unit(UNIT(s)->manager, a, NULL, NULL, &parent);
      73           2 :         if (r < 0)
      74           0 :                 return r;
      75             : 
      76           2 :         unit_ref_set(&UNIT(s)->slice, parent);
      77           2 :         return 0;
      78             : }
      79             : 
      80          12 : static int slice_add_default_dependencies(Slice *s) {
      81             :         int r;
      82             : 
      83          12 :         assert(s);
      84             : 
      85             :         /* Make sure slices are unloaded on shutdown */
      86          12 :         r = unit_add_two_dependencies_by_name(
      87             :                         UNIT(s),
      88             :                         UNIT_BEFORE, UNIT_CONFLICTS,
      89             :                         SPECIAL_SHUTDOWN_TARGET, NULL, true);
      90          12 :         if (r < 0)
      91           0 :                 return r;
      92             : 
      93          12 :         return 0;
      94             : }
      95             : 
      96             : 
      97          12 : static int slice_verify(Slice *s) {
      98          24 :         _cleanup_free_ char *parent = NULL;
      99             :         int r;
     100             : 
     101          12 :         assert(s);
     102             : 
     103          12 :         if (UNIT(s)->load_state != UNIT_LOADED)
     104           0 :                 return 0;
     105             : 
     106          12 :         if (!slice_name_is_valid(UNIT(s)->id)) {
     107           0 :                 log_unit_error(UNIT(s), "Slice name %s is not valid. Refusing.", UNIT(s)->id);
     108           0 :                 return -EINVAL;
     109             :         }
     110             : 
     111          12 :         r = slice_build_parent_slice(UNIT(s)->id, &parent);
     112          12 :         if (r < 0)
     113           0 :                 return log_unit_error_errno(UNIT(s), r, "Failed to determine parent slice: %m");
     114             : 
     115          12 :         if (parent ? !unit_has_name(UNIT_DEREF(UNIT(s)->slice), parent) : UNIT_ISSET(UNIT(s)->slice)) {
     116           0 :                 log_unit_error(UNIT(s), "Located outside of parent slice. Refusing.");
     117           0 :                 return -EINVAL;
     118             :         }
     119             : 
     120          12 :         return 0;
     121             : }
     122             : 
     123          12 : static int slice_load(Unit *u) {
     124          12 :         Slice *s = SLICE(u);
     125             :         int r;
     126             : 
     127          12 :         assert(s);
     128             : 
     129          12 :         r = unit_load_fragment_and_dropin_optional(u);
     130          12 :         if (r < 0)
     131           0 :                 return r;
     132             : 
     133             :         /* This is a new unit? Then let's add in some extras */
     134          12 :         if (u->load_state == UNIT_LOADED) {
     135             : 
     136          12 :                 r = unit_patch_contexts(u);
     137          12 :                 if (r < 0)
     138           0 :                         return r;
     139             : 
     140          12 :                 r = slice_add_parent_slice(s);
     141          12 :                 if (r < 0)
     142           0 :                         return r;
     143             : 
     144          12 :                 if (u->default_dependencies) {
     145          12 :                         r = slice_add_default_dependencies(s);
     146          12 :                         if (r < 0)
     147           0 :                                 return r;
     148             :                 }
     149             :         }
     150             : 
     151          12 :         return slice_verify(s);
     152             : }
     153             : 
     154          10 : static int slice_coldplug(Unit *u) {
     155          10 :         Slice *t = SLICE(u);
     156             : 
     157          10 :         assert(t);
     158          10 :         assert(t->state == SLICE_DEAD);
     159             : 
     160          10 :         if (t->deserialized_state != t->state)
     161           0 :                 slice_set_state(t, t->deserialized_state);
     162             : 
     163          10 :         return 0;
     164             : }
     165             : 
     166           4 : static void slice_dump(Unit *u, FILE *f, const char *prefix) {
     167           4 :         Slice *t = SLICE(u);
     168             : 
     169           4 :         assert(t);
     170           4 :         assert(f);
     171             : 
     172           4 :         fprintf(f,
     173             :                 "%sSlice State: %s\n",
     174             :                 prefix, slice_state_to_string(t->state));
     175             : 
     176           4 :         cgroup_context_dump(&t->cgroup_context, f, prefix);
     177           4 : }
     178             : 
     179           6 : static int slice_start(Unit *u) {
     180           6 :         Slice *t = SLICE(u);
     181             : 
     182           6 :         assert(t);
     183           6 :         assert(t->state == SLICE_DEAD);
     184             : 
     185           6 :         (void) unit_realize_cgroup(u);
     186           6 :         (void) unit_reset_cpu_usage(u);
     187             : 
     188           6 :         slice_set_state(t, SLICE_ACTIVE);
     189           6 :         return 1;
     190             : }
     191             : 
     192           0 : static int slice_stop(Unit *u) {
     193           0 :         Slice *t = SLICE(u);
     194             : 
     195           0 :         assert(t);
     196           0 :         assert(t->state == SLICE_ACTIVE);
     197             : 
     198             :         /* We do not need to destroy the cgroup explicitly,
     199             :          * unit_notify() will do that for us anyway. */
     200             : 
     201           0 :         slice_set_state(t, SLICE_DEAD);
     202           0 :         return 1;
     203             : }
     204             : 
     205           0 : static int slice_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
     206           0 :         return unit_kill_common(u, who, signo, -1, -1, error);
     207             : }
     208             : 
     209           0 : static int slice_serialize(Unit *u, FILE *f, FDSet *fds) {
     210           0 :         Slice *s = SLICE(u);
     211             : 
     212           0 :         assert(s);
     213           0 :         assert(f);
     214           0 :         assert(fds);
     215             : 
     216           0 :         unit_serialize_item(u, f, "state", slice_state_to_string(s->state));
     217           0 :         return 0;
     218             : }
     219             : 
     220           0 : static int slice_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
     221           0 :         Slice *s = SLICE(u);
     222             : 
     223           0 :         assert(u);
     224           0 :         assert(key);
     225           0 :         assert(value);
     226           0 :         assert(fds);
     227             : 
     228           0 :         if (streq(key, "state")) {
     229             :                 SliceState state;
     230             : 
     231           0 :                 state = slice_state_from_string(value);
     232           0 :                 if (state < 0)
     233           0 :                         log_debug("Failed to parse state value %s", value);
     234             :                 else
     235           0 :                         s->deserialized_state = state;
     236             : 
     237             :         } else
     238           0 :                 log_debug("Unknown serialization key '%s'", key);
     239             : 
     240           0 :         return 0;
     241             : }
     242             : 
     243          88 : _pure_ static UnitActiveState slice_active_state(Unit *u) {
     244          88 :         assert(u);
     245             : 
     246          88 :         return state_translation_table[SLICE(u)->state];
     247             : }
     248             : 
     249           0 : _pure_ static const char *slice_sub_state_to_string(Unit *u) {
     250           0 :         assert(u);
     251             : 
     252           0 :         return slice_state_to_string(SLICE(u)->state);
     253             : }
     254             : 
     255             : static const char* const slice_state_table[_SLICE_STATE_MAX] = {
     256             :         [SLICE_DEAD] = "dead",
     257             :         [SLICE_ACTIVE] = "active"
     258             : };
     259             : 
     260          12 : DEFINE_STRING_TABLE_LOOKUP(slice_state, SliceState);
     261             : 
     262             : const UnitVTable slice_vtable = {
     263             :         .object_size = sizeof(Slice),
     264             :         .cgroup_context_offset = offsetof(Slice, cgroup_context),
     265             : 
     266             :         .sections =
     267             :                 "Unit\0"
     268             :                 "Slice\0"
     269             :                 "Install\0",
     270             :         .private_section = "Slice",
     271             : 
     272             :         .no_alias = true,
     273             :         .no_instances = true,
     274             : 
     275             :         .load = slice_load,
     276             : 
     277             :         .coldplug = slice_coldplug,
     278             : 
     279             :         .dump = slice_dump,
     280             : 
     281             :         .start = slice_start,
     282             :         .stop = slice_stop,
     283             : 
     284             :         .kill = slice_kill,
     285             : 
     286             :         .serialize = slice_serialize,
     287             :         .deserialize_item = slice_deserialize_item,
     288             : 
     289             :         .active_state = slice_active_state,
     290             :         .sub_state_to_string = slice_sub_state_to_string,
     291             : 
     292             :         .bus_interface = "org.freedesktop.systemd1.Slice",
     293             :         .bus_vtable = bus_slice_vtable,
     294             :         .bus_set_property = bus_slice_set_property,
     295             :         .bus_commit_properties = bus_slice_commit_properties,
     296             : 
     297             :         .status_message_formats = {
     298             :                 .finished_start_job = {
     299             :                         [JOB_DONE]       = "Created slice %s.",
     300             :                 },
     301             :                 .finished_stop_job = {
     302             :                         [JOB_DONE]       = "Removed slice %s.",
     303             :                 },
     304             :         },
     305             : };

Generated by: LCOV version 1.11