LCOV - code coverage report
Current view: top level - core - dbus-cgroup.c (source / functions) Hit Total Coverage
Test: systemd test coverage Lines: 0 354 0.0 %
Date: 2015-07-29 18:47:03 Functions: 0 7 0.0 %

          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 "bus-util.h"
      23             : #include "path-util.h"
      24             : #include "cgroup-util.h"
      25             : #include "cgroup.h"
      26             : #include "dbus-cgroup.h"
      27             : 
      28           0 : static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_cgroup_device_policy, cgroup_device_policy, CGroupDevicePolicy);
      29             : 
      30           0 : static int property_get_blockio_device_weight(
      31             :                 sd_bus *bus,
      32             :                 const char *path,
      33             :                 const char *interface,
      34             :                 const char *property,
      35             :                 sd_bus_message *reply,
      36             :                 void *userdata,
      37             :                 sd_bus_error *error) {
      38             : 
      39           0 :         CGroupContext *c = userdata;
      40             :         CGroupBlockIODeviceWeight *w;
      41             :         int r;
      42             : 
      43           0 :         assert(bus);
      44           0 :         assert(reply);
      45           0 :         assert(c);
      46             : 
      47           0 :         r = sd_bus_message_open_container(reply, 'a', "(st)");
      48           0 :         if (r < 0)
      49           0 :                 return r;
      50             : 
      51           0 :         LIST_FOREACH(device_weights, w, c->blockio_device_weights) {
      52           0 :                 r = sd_bus_message_append(reply, "(st)", w->path, w->weight);
      53           0 :                 if (r < 0)
      54           0 :                         return r;
      55             :         }
      56             : 
      57           0 :         return sd_bus_message_close_container(reply);
      58             : }
      59             : 
      60           0 : static int property_get_blockio_device_bandwidths(
      61             :                 sd_bus *bus,
      62             :                 const char *path,
      63             :                 const char *interface,
      64             :                 const char *property,
      65             :                 sd_bus_message *reply,
      66             :                 void *userdata,
      67             :                 sd_bus_error *error) {
      68             : 
      69           0 :         CGroupContext *c = userdata;
      70             :         CGroupBlockIODeviceBandwidth *b;
      71             :         int r;
      72             : 
      73           0 :         assert(bus);
      74           0 :         assert(reply);
      75           0 :         assert(c);
      76             : 
      77           0 :         r = sd_bus_message_open_container(reply, 'a', "(st)");
      78           0 :         if (r < 0)
      79           0 :                 return r;
      80             : 
      81           0 :         LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) {
      82             : 
      83           0 :                 if (streq(property, "BlockIOReadBandwidth") != b->read)
      84           0 :                         continue;
      85             : 
      86           0 :                 r = sd_bus_message_append(reply, "(st)", b->path, b->bandwidth);
      87           0 :                 if (r < 0)
      88           0 :                         return r;
      89             :         }
      90             : 
      91           0 :         return sd_bus_message_close_container(reply);
      92             : }
      93             : 
      94           0 : static int property_get_device_allow(
      95             :                 sd_bus *bus,
      96             :                 const char *path,
      97             :                 const char *interface,
      98             :                 const char *property,
      99             :                 sd_bus_message *reply,
     100             :                 void *userdata,
     101             :                 sd_bus_error *error) {
     102             : 
     103           0 :         CGroupContext *c = userdata;
     104             :         CGroupDeviceAllow *a;
     105             :         int r;
     106             : 
     107           0 :         assert(bus);
     108           0 :         assert(reply);
     109           0 :         assert(c);
     110             : 
     111           0 :         r = sd_bus_message_open_container(reply, 'a', "(ss)");
     112           0 :         if (r < 0)
     113           0 :                 return r;
     114             : 
     115           0 :         LIST_FOREACH(device_allow, a, c->device_allow) {
     116           0 :                 unsigned k = 0;
     117             :                 char rwm[4];
     118             : 
     119           0 :                 if (a->r)
     120           0 :                         rwm[k++] = 'r';
     121           0 :                 if (a->w)
     122           0 :                         rwm[k++] = 'w';
     123           0 :                 if (a->m)
     124           0 :                         rwm[k++] = 'm';
     125             : 
     126           0 :                 rwm[k] = 0;
     127             : 
     128           0 :                 r = sd_bus_message_append(reply, "(ss)", a->path, rwm);
     129           0 :                 if (r < 0)
     130           0 :                         return r;
     131             :         }
     132             : 
     133           0 :         return sd_bus_message_close_container(reply);
     134             : }
     135             : 
     136           0 : static int property_get_ulong_as_u64(
     137             :                 sd_bus *bus,
     138             :                 const char *path,
     139             :                 const char *interface,
     140             :                 const char *property,
     141             :                 sd_bus_message *reply,
     142             :                 void *userdata,
     143             :                 sd_bus_error *error) {
     144             : 
     145           0 :         unsigned long *ul = userdata;
     146             : 
     147           0 :         assert(bus);
     148           0 :         assert(reply);
     149           0 :         assert(ul);
     150             : 
     151           0 :         return sd_bus_message_append(reply, "t", *ul == (unsigned long) -1 ? (uint64_t) -1 : (uint64_t) *ul);
     152             : }
     153             : 
     154             : const sd_bus_vtable bus_cgroup_vtable[] = {
     155             :         SD_BUS_VTABLE_START(0),
     156             :         SD_BUS_PROPERTY("Delegate", "b", bus_property_get_bool, offsetof(CGroupContext, delegate), 0),
     157             :         SD_BUS_PROPERTY("CPUAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, cpu_accounting), 0),
     158             :         SD_BUS_PROPERTY("CPUShares", "t", property_get_ulong_as_u64, offsetof(CGroupContext, cpu_shares), 0),
     159             :         SD_BUS_PROPERTY("StartupCPUShares", "t", property_get_ulong_as_u64, offsetof(CGroupContext, startup_cpu_shares), 0),
     160             :         SD_BUS_PROPERTY("CPUQuotaPerSecUSec", "t", bus_property_get_usec, offsetof(CGroupContext, cpu_quota_per_sec_usec), 0),
     161             :         SD_BUS_PROPERTY("BlockIOAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, blockio_accounting), 0),
     162             :         SD_BUS_PROPERTY("BlockIOWeight", "t", property_get_ulong_as_u64, offsetof(CGroupContext, blockio_weight), 0),
     163             :         SD_BUS_PROPERTY("StartupBlockIOWeight", "t", property_get_ulong_as_u64, offsetof(CGroupContext, startup_blockio_weight), 0),
     164             :         SD_BUS_PROPERTY("BlockIODeviceWeight", "a(st)", property_get_blockio_device_weight, 0, 0),
     165             :         SD_BUS_PROPERTY("BlockIOReadBandwidth", "a(st)", property_get_blockio_device_bandwidths, 0, 0),
     166             :         SD_BUS_PROPERTY("BlockIOWriteBandwidth", "a(st)", property_get_blockio_device_bandwidths, 0, 0),
     167             :         SD_BUS_PROPERTY("MemoryAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, memory_accounting), 0),
     168             :         SD_BUS_PROPERTY("MemoryLimit", "t", NULL, offsetof(CGroupContext, memory_limit), 0),
     169             :         SD_BUS_PROPERTY("DevicePolicy", "s", property_get_cgroup_device_policy, offsetof(CGroupContext, device_policy), 0),
     170             :         SD_BUS_PROPERTY("DeviceAllow", "a(ss)", property_get_device_allow, 0, 0),
     171             :         SD_BUS_VTABLE_END
     172             : };
     173             : 
     174           0 : static int bus_cgroup_set_transient_property(
     175             :                 Unit *u,
     176             :                 CGroupContext *c,
     177             :                 const char *name,
     178             :                 sd_bus_message *message,
     179             :                 UnitSetPropertiesMode mode,
     180             :                 sd_bus_error *error) {
     181             : 
     182             :         int r;
     183             : 
     184           0 :         assert(u);
     185           0 :         assert(c);
     186           0 :         assert(name);
     187           0 :         assert(message);
     188             : 
     189           0 :         if (streq(name, "Delegate")) {
     190             :                 int b;
     191             : 
     192           0 :                 r = sd_bus_message_read(message, "b", &b);
     193           0 :                 if (r < 0)
     194           0 :                         return r;
     195             : 
     196           0 :                 if (mode != UNIT_CHECK) {
     197           0 :                         c->delegate = b;
     198           0 :                         unit_write_drop_in_private(u, mode, name, b ? "Delegate=yes" : "Delegate=no");
     199             :                 }
     200             : 
     201           0 :                 return 1;
     202             :         }
     203             : 
     204           0 :         return 0;
     205             : }
     206             : 
     207           0 : int bus_cgroup_set_property(
     208             :                 Unit *u,
     209             :                 CGroupContext *c,
     210             :                 const char *name,
     211             :                 sd_bus_message *message,
     212             :                 UnitSetPropertiesMode mode,
     213             :                 sd_bus_error *error) {
     214             : 
     215             :         int r;
     216             : 
     217           0 :         assert(u);
     218           0 :         assert(c);
     219           0 :         assert(name);
     220           0 :         assert(message);
     221             : 
     222           0 :         if (streq(name, "CPUAccounting")) {
     223             :                 int b;
     224             : 
     225           0 :                 r = sd_bus_message_read(message, "b", &b);
     226           0 :                 if (r < 0)
     227           0 :                         return r;
     228             : 
     229           0 :                 if (mode != UNIT_CHECK) {
     230           0 :                         c->cpu_accounting = b;
     231           0 :                         u->cgroup_realized_mask &= ~CGROUP_CPUACCT;
     232           0 :                         unit_write_drop_in_private(u, mode, name, b ? "CPUAccounting=yes" : "CPUAccounting=no");
     233             :                 }
     234             : 
     235           0 :                 return 1;
     236             : 
     237           0 :         } else if (streq(name, "CPUShares")) {
     238             :                 uint64_t u64;
     239             :                 unsigned long ul;
     240             : 
     241           0 :                 r = sd_bus_message_read(message, "t", &u64);
     242           0 :                 if (r < 0)
     243           0 :                         return r;
     244             : 
     245           0 :                 if (u64 == (uint64_t) -1)
     246           0 :                         ul = (unsigned long) -1;
     247             :                 else {
     248           0 :                         ul = (unsigned long) u64;
     249           0 :                         if (ul <= 0 || (uint64_t) ul != u64)
     250           0 :                                 return sd_bus_error_set_errnof(error, EINVAL, "CPUShares value out of range");
     251             :                 }
     252             : 
     253           0 :                 if (mode != UNIT_CHECK) {
     254           0 :                         c->cpu_shares = ul;
     255           0 :                         u->cgroup_realized_mask &= ~CGROUP_CPU;
     256           0 :                         unit_write_drop_in_private_format(u, mode, name, "CPUShares=%lu", ul);
     257             :                 }
     258             : 
     259           0 :                 return 1;
     260             : 
     261           0 :         } else if (streq(name, "StartupCPUShares")) {
     262             :                 uint64_t u64;
     263             :                 unsigned long ul;
     264             : 
     265           0 :                 r = sd_bus_message_read(message, "t", &u64);
     266           0 :                 if (r < 0)
     267           0 :                         return r;
     268             : 
     269           0 :                 if (u64 == (uint64_t) -1)
     270           0 :                         ul = (unsigned long) -1;
     271             :                 else {
     272           0 :                         ul = (unsigned long) u64;
     273           0 :                         if (ul <= 0 || (uint64_t) ul != u64)
     274           0 :                                 return sd_bus_error_set_errnof(error, EINVAL, "StartupCPUShares value out of range");
     275             :                 }
     276             : 
     277           0 :                 if (mode != UNIT_CHECK) {
     278           0 :                         c->startup_cpu_shares = ul;
     279           0 :                         u->cgroup_realized_mask &= ~CGROUP_CPU;
     280           0 :                         unit_write_drop_in_private_format(u, mode, name, "StartupCPUShares=%lu", ul);
     281             :                 }
     282             : 
     283           0 :                 return 1;
     284             : 
     285           0 :         } else if (streq(name, "CPUQuotaPerSecUSec")) {
     286             :                 uint64_t u64;
     287             : 
     288           0 :                 r = sd_bus_message_read(message, "t", &u64);
     289           0 :                 if (r < 0)
     290           0 :                         return r;
     291             : 
     292           0 :                 if (u64 <= 0)
     293           0 :                         return sd_bus_error_set_errnof(error, EINVAL, "CPUQuotaPerSecUSec value out of range");
     294             : 
     295           0 :                 if (mode != UNIT_CHECK) {
     296           0 :                         c->cpu_quota_per_sec_usec = u64;
     297           0 :                         u->cgroup_realized_mask &= ~CGROUP_CPU;
     298           0 :                         unit_write_drop_in_private_format(u, mode, "CPUQuota", "CPUQuota=%0.f%%", (double) (c->cpu_quota_per_sec_usec / 10000));
     299             :                 }
     300             : 
     301           0 :                 return 1;
     302             : 
     303           0 :         } else if (streq(name, "BlockIOAccounting")) {
     304             :                 int b;
     305             : 
     306           0 :                 r = sd_bus_message_read(message, "b", &b);
     307           0 :                 if (r < 0)
     308           0 :                         return r;
     309             : 
     310           0 :                 if (mode != UNIT_CHECK) {
     311           0 :                         c->blockio_accounting = b;
     312           0 :                         u->cgroup_realized_mask &= ~CGROUP_BLKIO;
     313           0 :                         unit_write_drop_in_private(u, mode, name, b ? "BlockIOAccounting=yes" : "BlockIOAccounting=no");
     314             :                 }
     315             : 
     316           0 :                 return 1;
     317             : 
     318           0 :         } else if (streq(name, "BlockIOWeight")) {
     319             :                 uint64_t u64;
     320             :                 unsigned long ul;
     321             : 
     322           0 :                 r = sd_bus_message_read(message, "t", &u64);
     323           0 :                 if (r < 0)
     324           0 :                         return r;
     325             : 
     326           0 :                 if (u64 == (uint64_t) -1)
     327           0 :                         ul = (unsigned long) -1;
     328             :                 else  {
     329           0 :                         ul = (unsigned long) u64;
     330           0 :                         if (ul < 10 || ul > 1000)
     331           0 :                                 return sd_bus_error_set_errnof(error, EINVAL, "BlockIOWeight value out of range");
     332             :                 }
     333             : 
     334           0 :                 if (mode != UNIT_CHECK) {
     335           0 :                         c->blockio_weight = ul;
     336           0 :                         u->cgroup_realized_mask &= ~CGROUP_BLKIO;
     337           0 :                         unit_write_drop_in_private_format(u, mode, name, "BlockIOWeight=%lu", ul);
     338             :                 }
     339             : 
     340           0 :                 return 1;
     341             : 
     342           0 :         } else if (streq(name, "StartupBlockIOWeight")) {
     343             :                 uint64_t u64;
     344             :                 unsigned long ul;
     345             : 
     346           0 :                 r = sd_bus_message_read(message, "t", &u64);
     347           0 :                 if (r < 0)
     348           0 :                         return r;
     349             : 
     350           0 :                 if (u64 == (uint64_t) -1)
     351           0 :                         ul = (unsigned long) -1;
     352             :                 else  {
     353           0 :                         ul = (unsigned long) u64;
     354           0 :                         if (ul < 10 || ul > 1000)
     355           0 :                                 return sd_bus_error_set_errnof(error, EINVAL, "StartupBlockIOWeight value out of range");
     356             :                 }
     357             : 
     358           0 :                 if (mode != UNIT_CHECK) {
     359           0 :                         c->startup_blockio_weight = ul;
     360           0 :                         u->cgroup_realized_mask &= ~CGROUP_BLKIO;
     361           0 :                         unit_write_drop_in_private_format(u, mode, name, "StartupBlockIOWeight=%lu", ul);
     362             :                 }
     363             : 
     364           0 :                 return 1;
     365             : 
     366           0 :         } else if (streq(name, "BlockIOReadBandwidth") || streq(name, "BlockIOWriteBandwidth")) {
     367             :                 const char *path;
     368           0 :                 bool read = true;
     369           0 :                 unsigned n = 0;
     370             :                 uint64_t u64;
     371             : 
     372           0 :                 if (streq(name, "BlockIOWriteBandwidth"))
     373           0 :                         read = false;
     374             : 
     375           0 :                 r = sd_bus_message_enter_container(message, 'a', "(st)");
     376           0 :                 if (r < 0)
     377           0 :                         return r;
     378             : 
     379           0 :                 while ((r = sd_bus_message_read(message, "(st)", &path, &u64)) > 0) {
     380             : 
     381           0 :                         if (mode != UNIT_CHECK) {
     382           0 :                                 CGroupBlockIODeviceBandwidth *a = NULL, *b;
     383             : 
     384           0 :                                 LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) {
     385           0 :                                         if (path_equal(path, b->path) && read == b->read) {
     386           0 :                                                 a = b;
     387           0 :                                                 break;
     388             :                                         }
     389             :                                 }
     390             : 
     391           0 :                                 if (!a) {
     392           0 :                                         a = new0(CGroupBlockIODeviceBandwidth, 1);
     393           0 :                                         if (!a)
     394           0 :                                                 return -ENOMEM;
     395             : 
     396           0 :                                         a->read = read;
     397           0 :                                         a->path = strdup(path);
     398           0 :                                         if (!a->path) {
     399           0 :                                                 free(a);
     400           0 :                                                 return -ENOMEM;
     401             :                                         }
     402             : 
     403           0 :                                         LIST_PREPEND(device_bandwidths, c->blockio_device_bandwidths, a);
     404             :                                 }
     405             : 
     406           0 :                                 a->bandwidth = u64;
     407             :                         }
     408             : 
     409           0 :                         n++;
     410             :                 }
     411           0 :                 if (r < 0)
     412           0 :                         return r;
     413             : 
     414           0 :                 r = sd_bus_message_exit_container(message);
     415           0 :                 if (r < 0)
     416           0 :                         return r;
     417             : 
     418           0 :                 if (mode != UNIT_CHECK) {
     419             :                         CGroupBlockIODeviceBandwidth *a, *next;
     420           0 :                         _cleanup_free_ char *buf = NULL;
     421           0 :                         _cleanup_fclose_ FILE *f = NULL;
     422           0 :                         size_t size = 0;
     423             : 
     424           0 :                         if (n == 0) {
     425           0 :                                 LIST_FOREACH_SAFE(device_bandwidths, a, next, c->blockio_device_bandwidths)
     426           0 :                                         if (a->read == read)
     427           0 :                                                 cgroup_context_free_blockio_device_bandwidth(c, a);
     428             :                         }
     429             : 
     430           0 :                         u->cgroup_realized_mask &= ~CGROUP_BLKIO;
     431             : 
     432           0 :                         f = open_memstream(&buf, &size);
     433           0 :                         if (!f)
     434           0 :                                 return -ENOMEM;
     435             : 
     436           0 :                          if (read) {
     437           0 :                                 fputs("BlockIOReadBandwidth=\n", f);
     438           0 :                                  LIST_FOREACH(device_bandwidths, a, c->blockio_device_bandwidths)
     439           0 :                                         if (a->read)
     440           0 :                                                 fprintf(f, "BlockIOReadBandwidth=%s %" PRIu64 "\n", a->path, a->bandwidth);
     441             :                         } else {
     442           0 :                                 fputs("BlockIOWriteBandwidth=\n", f);
     443           0 :                                 LIST_FOREACH(device_bandwidths, a, c->blockio_device_bandwidths)
     444           0 :                                         if (!a->read)
     445           0 :                                                 fprintf(f, "BlockIOWriteBandwidth=%s %" PRIu64 "\n", a->path, a->bandwidth);
     446             :                         }
     447             : 
     448           0 :                         fflush(f);
     449           0 :                         unit_write_drop_in_private(u, mode, name, buf);
     450             :                 }
     451             : 
     452           0 :                 return 1;
     453             : 
     454           0 :         } else if (streq(name, "BlockIODeviceWeight")) {
     455             :                 const char *path;
     456             :                 uint64_t u64;
     457           0 :                 unsigned n = 0;
     458             : 
     459           0 :                 r = sd_bus_message_enter_container(message, 'a', "(st)");
     460           0 :                 if (r < 0)
     461           0 :                         return r;
     462             : 
     463           0 :                 while ((r = sd_bus_message_read(message, "(st)", &path, &u64)) > 0) {
     464           0 :                         unsigned long ul = u64;
     465             : 
     466           0 :                         if (ul < 10 || ul > 1000)
     467           0 :                                 return sd_bus_error_set_errnof(error, EINVAL, "BlockIODeviceWeight out of range");
     468             : 
     469           0 :                         if (mode != UNIT_CHECK) {
     470           0 :                                 CGroupBlockIODeviceWeight *a = NULL, *b;
     471             : 
     472           0 :                                 LIST_FOREACH(device_weights, b, c->blockio_device_weights) {
     473           0 :                                         if (path_equal(b->path, path)) {
     474           0 :                                                 a = b;
     475           0 :                                                 break;
     476             :                                         }
     477             :                                 }
     478             : 
     479           0 :                                 if (!a) {
     480           0 :                                         a = new0(CGroupBlockIODeviceWeight, 1);
     481           0 :                                         if (!a)
     482           0 :                                                 return -ENOMEM;
     483             : 
     484           0 :                                         a->path = strdup(path);
     485           0 :                                         if (!a->path) {
     486           0 :                                                 free(a);
     487           0 :                                                 return -ENOMEM;
     488             :                                         }
     489           0 :                                         LIST_PREPEND(device_weights,c->blockio_device_weights, a);
     490             :                                 }
     491             : 
     492           0 :                                 a->weight = ul;
     493             :                         }
     494             : 
     495           0 :                         n++;
     496             :                 }
     497             : 
     498           0 :                 r = sd_bus_message_exit_container(message);
     499           0 :                 if (r < 0)
     500           0 :                         return r;
     501             : 
     502           0 :                 if (mode != UNIT_CHECK) {
     503           0 :                         _cleanup_free_ char *buf = NULL;
     504           0 :                         _cleanup_fclose_ FILE *f = NULL;
     505             :                         CGroupBlockIODeviceWeight *a;
     506           0 :                         size_t size = 0;
     507             : 
     508           0 :                         if (n == 0) {
     509           0 :                                 while (c->blockio_device_weights)
     510           0 :                                         cgroup_context_free_blockio_device_weight(c, c->blockio_device_weights);
     511             :                         }
     512             : 
     513           0 :                         u->cgroup_realized_mask &= ~CGROUP_BLKIO;
     514             : 
     515           0 :                         f = open_memstream(&buf, &size);
     516           0 :                         if (!f)
     517           0 :                                 return -ENOMEM;
     518             : 
     519           0 :                         fputs("BlockIODeviceWeight=\n", f);
     520           0 :                         LIST_FOREACH(device_weights, a, c->blockio_device_weights)
     521           0 :                                 fprintf(f, "BlockIODeviceWeight=%s %lu\n", a->path, a->weight);
     522             : 
     523           0 :                         fflush(f);
     524           0 :                         unit_write_drop_in_private(u, mode, name, buf);
     525             :                 }
     526             : 
     527           0 :                 return 1;
     528             : 
     529           0 :         } else if (streq(name, "MemoryAccounting")) {
     530             :                 int b;
     531             : 
     532           0 :                 r = sd_bus_message_read(message, "b", &b);
     533           0 :                 if (r < 0)
     534           0 :                         return r;
     535             : 
     536           0 :                 if (mode != UNIT_CHECK) {
     537           0 :                         c->memory_accounting = b;
     538           0 :                         u->cgroup_realized_mask &= ~CGROUP_MEMORY;
     539           0 :                         unit_write_drop_in_private(u, mode, name, b ? "MemoryAccounting=yes" : "MemoryAccounting=no");
     540             :                 }
     541             : 
     542           0 :                 return 1;
     543             : 
     544           0 :         } else if (streq(name, "MemoryLimit")) {
     545             :                 uint64_t limit;
     546             : 
     547           0 :                 r = sd_bus_message_read(message, "t", &limit);
     548           0 :                 if (r < 0)
     549           0 :                         return r;
     550             : 
     551           0 :                 if (mode != UNIT_CHECK) {
     552           0 :                         c->memory_limit = limit;
     553           0 :                         u->cgroup_realized_mask &= ~CGROUP_MEMORY;
     554           0 :                         unit_write_drop_in_private_format(u, mode, name, "%s=%" PRIu64, name, limit);
     555             :                 }
     556             : 
     557           0 :                 return 1;
     558             : 
     559           0 :         } else if (streq(name, "DevicePolicy")) {
     560             :                 const char *policy;
     561             :                 CGroupDevicePolicy p;
     562             : 
     563           0 :                 r = sd_bus_message_read(message, "s", &policy);
     564           0 :                 if (r < 0)
     565           0 :                         return r;
     566             : 
     567           0 :                 p = cgroup_device_policy_from_string(policy);
     568           0 :                 if (p < 0)
     569           0 :                         return -EINVAL;
     570             : 
     571           0 :                 if (mode != UNIT_CHECK) {
     572             :                         char *buf;
     573             : 
     574           0 :                         c->device_policy = p;
     575           0 :                         u->cgroup_realized_mask &= ~CGROUP_DEVICE;
     576             : 
     577           0 :                         buf = strjoina("DevicePolicy=", policy);
     578           0 :                         unit_write_drop_in_private(u, mode, name, buf);
     579             :                 }
     580             : 
     581           0 :                 return 1;
     582             : 
     583           0 :         } else if (streq(name, "DeviceAllow")) {
     584             :                 const char *path, *rwm;
     585           0 :                 unsigned n = 0;
     586             : 
     587           0 :                 r = sd_bus_message_enter_container(message, 'a', "(ss)");
     588           0 :                 if (r < 0)
     589           0 :                         return r;
     590             : 
     591           0 :                 while ((r = sd_bus_message_read(message, "(ss)", &path, &rwm)) > 0) {
     592             : 
     593           0 :                         if ((!startswith(path, "/dev/") &&
     594           0 :                              !startswith(path, "block-") &&
     595           0 :                              !startswith(path, "char-")) ||
     596           0 :                             strpbrk(path, WHITESPACE))
     597           0 :                             return sd_bus_error_set_errnof(error, EINVAL, "DeviceAllow= requires device node");
     598             : 
     599           0 :                         if (isempty(rwm))
     600           0 :                                 rwm = "rwm";
     601             : 
     602           0 :                         if (!in_charset(rwm, "rwm"))
     603           0 :                                 return sd_bus_error_set_errnof(error, EINVAL, "DeviceAllow= requires combination of rwm flags");
     604             : 
     605           0 :                         if (mode != UNIT_CHECK) {
     606           0 :                                 CGroupDeviceAllow *a = NULL, *b;
     607             : 
     608           0 :                                 LIST_FOREACH(device_allow, b, c->device_allow) {
     609           0 :                                         if (path_equal(b->path, path)) {
     610           0 :                                                 a = b;
     611           0 :                                                 break;
     612             :                                         }
     613             :                                 }
     614             : 
     615           0 :                                 if (!a) {
     616           0 :                                         a = new0(CGroupDeviceAllow, 1);
     617           0 :                                         if (!a)
     618           0 :                                                 return -ENOMEM;
     619             : 
     620           0 :                                         a->path = strdup(path);
     621           0 :                                         if (!a->path) {
     622           0 :                                                 free(a);
     623           0 :                                                 return -ENOMEM;
     624             :                                         }
     625             : 
     626           0 :                                         LIST_PREPEND(device_allow, c->device_allow, a);
     627             :                                 }
     628             : 
     629           0 :                                 a->r = !!strchr(rwm, 'r');
     630           0 :                                 a->w = !!strchr(rwm, 'w');
     631           0 :                                 a->m = !!strchr(rwm, 'm');
     632             :                         }
     633             : 
     634           0 :                         n++;
     635             :                 }
     636           0 :                 if (r < 0)
     637           0 :                         return r;
     638             : 
     639           0 :                 r = sd_bus_message_exit_container(message);
     640           0 :                 if (r < 0)
     641           0 :                         return r;
     642             : 
     643           0 :                 if (mode != UNIT_CHECK) {
     644           0 :                         _cleanup_free_ char *buf = NULL;
     645           0 :                         _cleanup_fclose_ FILE *f = NULL;
     646             :                         CGroupDeviceAllow *a;
     647           0 :                         size_t size = 0;
     648             : 
     649           0 :                         if (n == 0) {
     650           0 :                                 while (c->device_allow)
     651           0 :                                         cgroup_context_free_device_allow(c, c->device_allow);
     652             :                         }
     653             : 
     654           0 :                         u->cgroup_realized_mask &= ~CGROUP_DEVICE;
     655             : 
     656           0 :                         f = open_memstream(&buf, &size);
     657           0 :                         if (!f)
     658           0 :                                 return -ENOMEM;
     659             : 
     660           0 :                         fputs("DeviceAllow=\n", f);
     661           0 :                         LIST_FOREACH(device_allow, a, c->device_allow)
     662           0 :                                 fprintf(f, "DeviceAllow=%s %s%s%s\n", a->path, a->r ? "r" : "", a->w ? "w" : "", a->m ? "m" : "");
     663             : 
     664           0 :                         fflush(f);
     665           0 :                         unit_write_drop_in_private(u, mode, name, buf);
     666             :                 }
     667             : 
     668           0 :                 return 1;
     669             : 
     670             :         }
     671             : 
     672           0 :         if (u->transient && u->load_state == UNIT_STUB) {
     673           0 :                 r = bus_cgroup_set_transient_property(u, c, name, message, mode, error);
     674           0 :                 if (r != 0)
     675           0 :                         return r;
     676             : 
     677             :         }
     678             : 
     679           0 :         return 0;
     680             : }

Generated by: LCOV version 1.11