[systemd-devel] [PATCH] core: add startup resource control option

WaLyong Cho walyong.cho at samsung.com
Wed May 21 06:54:05 PDT 2014


On 05/21/2014 09:02 PM, Umut Tezduyar Lindskog wrote:
> Hi Cho,
> 
> Do you have any technical reason why CPU shares are reverted back to
> the default value on "StartupFinished" but instead when the unit is in
> "activated" state?

Sorry, I couldn't understand what you say. Did you mean if service has
only "StartupCPUShares="(not CPUShares=), then cpu.shares of the service
is changed to default? If this is what you mean, this is intended
operation. I've already explained about this.
http://lists.freedesktop.org/archives/systemd-devel/2014-April/018873.html

In summery, if only "CPUShares=" is given, then same with current
systemd operation. The given weight also have effect on "starting" state.
If only "StartupCPUShares=" is given, then cpu.shares will be set as
given during only "starting" state. After changing to "running", then
cpu.shares will be changed to default. So if you want to set
cpu.shares(not default), then use the "CPUShares=". And if you want to
set different weight on each state, then be specified both of
"StartupCPUShares=" and "CPUShares="

> 
> Through out the boot, until StartupFinished, a unit might get
> activated quite early but still having a higher CPU share. If the
> service has some low priority task scheduled to do some non important
> jobs, up until StartupFinished, low priority task is getting more CPU.
> Thoughts?

Sorry, can not understand this also. Do you want split "activating"
state with "active" of a unit? That was not considered.

> 
> Just out of curiosity, how does it work when the service is restarted
> before StartupFinished is reached?

It is not matter of the service state. It's the matter of manager(system
global) state. It is on "starting" or "running". If the manager is
entered to running state then the "StartupCPUShares=" has no effect.

> 
> On Thu, May 15, 2014 at 5:09 PM, WaLyong Cho <walyong.cho at samsung.com> wrote:
>> Similar to CPUShares= and BlockIOWeight= respectively. However only
>> assign the specified weight during startup. Each control group
>> attribute is re-assigned as weight by CPUShares=weight and
>> BlockIOWeight=weight after startup.  If not CPUShares= or
>> BlockIOWeight= be specified, then the attribute is re-assigned to each
>> default attribute value. (default cpu.shares=1024, blkio.weight=1000)
>> If only CPUShares=weight or BlockIOWeight=weight be specified, then
>> that implies StartupCPUShares=weight and StartupBlockIOWeight=weight.
>> ---
>>  man/systemd.resource-control.xml      | 24 ++++++++++
>>  src/core/cgroup.c                     | 40 ++++++++++++-----
>>  src/core/cgroup.h                     |  8 +++-
>>  src/core/dbus-cgroup.c                | 42 ++++++++++++++++++
>>  src/core/load-fragment-gperf.gperf.m4 |  2 +
>>  src/core/load-fragment.c              | 83 +++++++++++++++++++++++++++++++++++
>>  src/core/load-fragment.h              |  2 +
>>  src/core/manager.c                    | 16 +++++++
>>  src/core/manager.h                    |  3 ++
>>  src/core/unit.c                       | 18 ++++++++
>>  10 files changed, 226 insertions(+), 12 deletions(-)
>>
>> diff --git a/man/systemd.resource-control.xml b/man/systemd.resource-control.xml
>> index 80c365b..33d2f2e 100644
>> --- a/man/systemd.resource-control.xml
>> +++ b/man/systemd.resource-control.xml
>> @@ -171,6 +171,18 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>.
>>        </varlistentry>
>>
>>        <varlistentry>
>> +        <term><varname>StartupCPUShares=<replaceable>weight</replaceable></varname></term>
>> +
>> +        <listitem>
>> +          <para>Similar to <varname>CPUShares=</varname>. However,
>> +          only be assigned on startup state. After finishing startup, will be
>> +          re-assigned by <varname>CPUShares=</varname>. If
>> +          <varname>CPUShares=</varname> is not specified, then it will be
>> +          assigned to default(1024).</para>
>> +        </listitem>
>> +      </varlistentry>
>> +
>> +      <varlistentry>
>>          <term><varname>MemoryAccounting=</varname></term>
>>
>>          <listitem>
>> @@ -241,6 +253,18 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>.
>>        </varlistentry>
>>
>>        <varlistentry>
>> +        <term><varname>StartupBlockIOWeight=<replaceable>weight</replaceable></varname></term>
>> +
>> +        <listitem>
>> +          <para>Similar to <varname>BlockIOWeight=</varname>. However,
>> +          only be assigned on startup state. After finishing startup, will be
>> +          re-assigned by <varname>BlockIOWeight=</varname>. If
>> +          <varname>BlockIOWeight=</varname> is not specified, then it will be
>> +          assigned to default(1000).</para>
>> +        </listitem>
>> +      </varlistentry>
>> +
>> +      <varlistentry>
>>          <term><varname>BlockIODeviceWeight=<replaceable>device</replaceable> <replaceable>weight</replaceable></varname></term>
>>
>>          <listitem>
>> diff --git a/src/core/cgroup.c b/src/core/cgroup.c
>> index 29ab645..80a5575 100644
>> --- a/src/core/cgroup.c
>> +++ b/src/core/cgroup.c
>> @@ -34,8 +34,12 @@ void cgroup_context_init(CGroupContext *c) {
>>           * structure is preinitialized to 0 */
>>
>>          c->cpu_shares = 1024;
>> +        c->startup_cpu_shares = 1024;
>> +        c->startup_cpu_shares_set = false;
> 
> I really think patch can be implemented without startup_cpu_shares_set
> and startup_blockio_weight_set. In the end, c->startup_cpu_shares =
> 1024 and c->cpu_shares = 1024 means that we don't want any special
> treatment.

Hmm, maybe no. The "startup_cpu_shares_set" is used at both option is
specified. We can think about two case: one is "StartupCPUShares=" is
specified before "CPUShares=". And the other is "CPUShares=" is
specified before "StartupCPUShares=".
In the former case, config_parse_startup_cpu_shares will be called
first. And startup_cpu_shares_set is set as true. And prevent re-set
again in config_parse_cpu_shares. If startup_cpu_shares_set is not
exist, then hard to know "StartupCPUShares=" is specified or not in
config_parse_cpu_shares.
In the latter case, startup_cpu_shares also be set in
config_parse_cpu_shares because startup_cpu_shares_set is initialized as
false. And, in config_parse_startup_cpu_shares, startup_cpu_shares_set
is set as given in the unit file.

Am I wrong?

Thanks,
WaLyong

> 
> Thanks,
> Umut
> 
>>          c->memory_limit = (uint64_t) -1;
>>          c->blockio_weight = 1000;
>> +        c->startup_blockio_weight = 1000;
>> +        c->startup_blockio_weight_set = false;
>>
>>          c->cpu_quota_per_sec_usec = (usec_t) -1;
>>          c->cpu_quota_usec = (usec_t) -1;
>> @@ -124,20 +128,24 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
>>                  "%sBlockIOAccounting=%s\n"
>>                  "%sMemoryAccounting=%s\n"
>>                  "%sCPUShares=%lu\n"
>> +                "%sStartupCPUShares=%lu\n"
>>                  "%sCPUQuota=%s\n"
>>                  "%sCPUQuotaPerSecSec=%s\n"
>>                  "%sCPUQuotaPeriodSec=%s\n"
>>                  "%sBlockIOWeight=%lu\n"
>> +                "%sStartupBlockIOWeight=%lu\n"
>>                  "%sMemoryLimit=%" PRIu64 "\n"
>>                  "%sDevicePolicy=%s\n",
>>                  prefix, yes_no(c->cpu_accounting),
>>                  prefix, yes_no(c->blockio_accounting),
>>                  prefix, yes_no(c->memory_accounting),
>>                  prefix, c->cpu_shares,
>> +                prefix, c->startup_cpu_shares,
>>                  prefix, strna(format_timespan(u, sizeof(u), cgroup_context_get_cpu_quota_usec(c), 1)),
>>                  prefix, strna(format_timespan(t, sizeof(t), cgroup_context_get_cpu_quota_per_sec_usec(c), 1)),
>>                  prefix, strna(format_timespan(s, sizeof(s), c->cpu_quota_period_usec, 1)),
>>                  prefix, c->blockio_weight,
>> +                prefix, c->startup_blockio_weight,
>>                  prefix, c->memory_limit,
>>                  prefix, cgroup_device_policy_to_string(c->device_policy));
>>
>> @@ -306,7 +314,7 @@ fail:
>>          return -errno;
>>  }
>>
>> -void cgroup_context_apply(CGroupContext *c, CGroupControllerMask mask, const char *path) {
>> +void cgroup_context_apply(Manager *m, CGroupContext *c, CGroupControllerMask mask, const char *path) {
>>          bool is_root;
>>          int r;
>>
>> @@ -324,7 +332,9 @@ void cgroup_context_apply(CGroupContext *c, CGroupControllerMask mask, const cha
>>                  char buf[MAX(DECIMAL_STR_MAX(unsigned long), DECIMAL_STR_MAX(usec_t)) + 1];
>>                  usec_t q;
>>
>> -                sprintf(buf, "%lu\n", c->cpu_shares);
>> +                sprintf(buf, "%lu\n", manager_state(m) == MANAGER_STARTING
>> +                        ? c->startup_cpu_shares
>> +                        : c->cpu_shares);
>>                  r = cg_set_attribute("cpu", path, "cpu.shares", buf);
>>                  if (r < 0)
>>                          log_warning("Failed to set cpu.shares on %s: %s", path, strerror(-r));
>> @@ -352,7 +362,9 @@ void cgroup_context_apply(CGroupContext *c, CGroupControllerMask mask, const cha
>>                  CGroupBlockIODeviceBandwidth *b;
>>
>>                  if (!is_root) {
>> -                        sprintf(buf, "%lu\n", c->blockio_weight);
>> +                        sprintf(buf, "%lu\n", manager_state(m) == MANAGER_STARTING
>> +                                ? c->startup_blockio_weight
>> +                                : c->blockio_weight);
>>                          r = cg_set_attribute("blkio", path, "blkio.weight", buf);
>>                          if (r < 0)
>>                                  log_warning("Failed to set blkio.weight on %s: %s", path, strerror(-r));
>> @@ -462,22 +474,30 @@ void cgroup_context_apply(CGroupContext *c, CGroupControllerMask mask, const cha
>>          }
>>  }
>>
>> -CGroupControllerMask cgroup_context_get_mask(CGroupContext *c) {
>> +CGroupControllerMask cgroup_context_get_mask(Manager *m, CGroupContext *c) {
>>          CGroupControllerMask mask = 0;
>>
>>          /* Figure out which controllers we need */
>>
>>          if (c->cpu_accounting ||
>> -            c->cpu_shares != 1024 ||
>> +            (manager_state(m) == MANAGER_STARTING ? c->startup_cpu_shares : c->cpu_shares) != 1024 ||
>> +            (manager_state(m) != MANAGER_STARTING && c->startup_cpu_shares_set && c->startup_cpu_shares != c->cpu_shares) ||
>>              c->cpu_quota_usec != (usec_t) -1 ||
>> -            c->cpu_quota_per_sec_usec != (usec_t) -1)
>> +            c->cpu_quota_per_sec_usec != (usec_t) -1) {
>>                  mask |= CGROUP_CPUACCT | CGROUP_CPU;
>> +                if (manager_state(m) != MANAGER_STARTING)
>> +                        c->startup_cpu_shares_set = false;
>> +        }
>>
>>          if (c->blockio_accounting ||
>> -            c->blockio_weight != 1000 ||
>> +            (manager_state(m) == MANAGER_STARTING ? c->startup_blockio_weight : c->blockio_weight) != 1000 ||
>> +            (manager_state(m) != MANAGER_STARTING && c->startup_blockio_weight_set && c->startup_blockio_weight != c->blockio_weight) ||
>>              c->blockio_device_weights ||
>> -            c->blockio_device_bandwidths)
>> +            c->blockio_device_bandwidths) {
>>                  mask |= CGROUP_BLKIO;
>> +                if (manager_state(m) != MANAGER_STARTING)
>> +                        c->startup_blockio_weight_set = false;
>> +        }
>>
>>          if (c->memory_accounting ||
>>              c->memory_limit != (uint64_t) -1)
>> @@ -496,7 +516,7 @@ CGroupControllerMask unit_get_cgroup_mask(Unit *u) {
>>          if (!c)
>>                  return 0;
>>
>> -        return cgroup_context_get_mask(c);
>> +        return cgroup_context_get_mask(u->manager, c);
>>  }
>>
>>  CGroupControllerMask unit_get_members_mask(Unit *u) {
>> @@ -700,7 +720,7 @@ static int unit_realize_cgroup_now(Unit *u) {
>>                  return r;
>>
>>          /* Finally, apply the necessary attributes. */
>> -        cgroup_context_apply(unit_get_cgroup_context(u), mask, u->cgroup_path);
>> +        cgroup_context_apply(u->manager, unit_get_cgroup_context(u), mask, u->cgroup_path);
>>
>>          return 0;
>>  }
>> diff --git a/src/core/cgroup.h b/src/core/cgroup.h
>> index 2b19add..64d3ac6 100644
>> --- a/src/core/cgroup.h
>> +++ b/src/core/cgroup.h
>> @@ -71,11 +71,15 @@ struct CGroupContext {
>>          bool memory_accounting;
>>
>>          unsigned long cpu_shares;
>> +        unsigned long startup_cpu_shares;
>> +        bool startup_cpu_shares_set:1;
>>          usec_t cpu_quota_per_sec_usec;
>>          usec_t cpu_quota_usec;
>>          usec_t cpu_quota_period_usec;
>>
>>          unsigned long blockio_weight;
>> +        unsigned long startup_blockio_weight;
>> +        bool startup_blockio_weight_set:1;
>>          LIST_HEAD(CGroupBlockIODeviceWeight, blockio_device_weights);
>>          LIST_HEAD(CGroupBlockIODeviceBandwidth, blockio_device_bandwidths);
>>
>> @@ -92,9 +96,9 @@ struct CGroupContext {
>>  void cgroup_context_init(CGroupContext *c);
>>  void cgroup_context_done(CGroupContext *c);
>>  void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix);
>> -void cgroup_context_apply(CGroupContext *c, CGroupControllerMask mask, const char *path);
>> +void cgroup_context_apply(Manager *m, CGroupContext *c, CGroupControllerMask mask, const char *path);
>>
>> -CGroupControllerMask cgroup_context_get_mask(CGroupContext *c);
>> +CGroupControllerMask cgroup_context_get_mask(Manager *m, CGroupContext *c);
>>
>>  void cgroup_context_free_device_allow(CGroupContext *c, CGroupDeviceAllow *a);
>>  void cgroup_context_free_blockio_device_weight(CGroupContext *c, CGroupBlockIODeviceWeight *w);
>> diff --git a/src/core/dbus-cgroup.c b/src/core/dbus-cgroup.c
>> index e9bdabf..a7c8ca6 100644
>> --- a/src/core/dbus-cgroup.c
>> +++ b/src/core/dbus-cgroup.c
>> @@ -173,11 +173,13 @@ const sd_bus_vtable bus_cgroup_vtable[] = {
>>          SD_BUS_VTABLE_START(0),
>>          SD_BUS_PROPERTY("CPUAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, cpu_accounting), 0),
>>          SD_BUS_PROPERTY("CPUShares", "t", bus_property_get_ulong, offsetof(CGroupContext, cpu_shares), 0),
>> +        SD_BUS_PROPERTY("StartupCPUShares", "t", bus_property_get_ulong, offsetof(CGroupContext, startup_cpu_shares), 0),
>>          SD_BUS_PROPERTY("CPUQuotaPerSecUSec", "t", property_get_cpu_quota_per_sec_usec, 0, 0),
>>          SD_BUS_PROPERTY("CPUQuotaUSec", "t", property_get_cpu_quota_usec, 0, 0),
>>          SD_BUS_PROPERTY("CPUQuotaPeriodUSec", "t", bus_property_get_usec, offsetof(CGroupContext, cpu_quota_period_usec), 0),
>>          SD_BUS_PROPERTY("BlockIOAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, blockio_accounting), 0),
>>          SD_BUS_PROPERTY("BlockIOWeight", "t", bus_property_get_ulong, offsetof(CGroupContext, blockio_weight), 0),
>> +        SD_BUS_PROPERTY("StartupBlockIOWeight", "t", bus_property_get_ulong, offsetof(CGroupContext, startup_blockio_weight), 0),
>>          SD_BUS_PROPERTY("BlockIODeviceWeight", "a(st)", property_get_blockio_device_weight, 0, 0),
>>          SD_BUS_PROPERTY("BlockIOReadBandwidth", "a(st)", property_get_blockio_device_bandwidths, 0, 0),
>>          SD_BUS_PROPERTY("BlockIOWriteBandwidth", "a(st)", property_get_blockio_device_bandwidths, 0, 0),
>> @@ -238,6 +240,26 @@ int bus_cgroup_set_property(
>>
>>                  return 1;
>>
>> +        } else if (streq(name, "StartupCPUShares")) {
>> +                uint64_t u64;
>> +                unsigned long ul;
>> +
>> +                r = sd_bus_message_read(message, "t", &u64);
>> +                if (r < 0)
>> +                        return r;
>> +
>> +                ul = (unsigned long) u64;
>> +                if (ul <= 0 || (uint64_t) ul != u64)
>> +                        return sd_bus_error_set_errnof(error, EINVAL, "StartupCPUShares value out of range");
>> +
>> +                if (mode != UNIT_CHECK) {
>> +                        c->startup_cpu_shares = ul;
>> +                        c->startup_cpu_shares_set = true;
>> +                        unit_write_drop_in_private_format(u, mode, name, "StartupCPUShares=%lu", ul);
>> +                }
>> +
>> +                return 1;
>> +
>>          } else if (streq(name, "CPUQuotaPerSecUSec")) {
>>                  uint64_t u64;
>>
>> @@ -330,6 +352,26 @@ int bus_cgroup_set_property(
>>
>>                  return 1;
>>
>> +        } else if (streq(name, "StartupBlockIOWeight")) {
>> +                uint64_t u64;
>> +                unsigned long ul;
>> +
>> +                r = sd_bus_message_read(message, "t", &u64);
>> +                if (r < 0)
>> +                        return r;
>> +
>> +                ul = (unsigned long) u64;
>> +                if (ul < 10 || ul > 1000)
>> +                        return sd_bus_error_set_errnof(error, EINVAL, "StartupBlockIOWeight value out of range");
>> +
>> +                if (mode != UNIT_CHECK) {
>> +                        c->startup_blockio_weight = ul;
>> +                        c->startup_blockio_weight_set = true;
>> +                        unit_write_drop_in_private_format(u, mode, name, "StartupBlockIOWeight=%lu", ul);
>> +                }
>> +
>> +                return 1;
>> +
>>          } else if (streq(name, "BlockIOReadBandwidth") || streq(name, "BlockIOWriteBandwidth")) {
>>                  const char *path;
>>                  bool read = true;
>> diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
>> index 21bccbb..91061df 100644
>> --- a/src/core/load-fragment-gperf.gperf.m4
>> +++ b/src/core/load-fragment-gperf.gperf.m4
>> @@ -106,6 +106,7 @@ m4_define(`CGROUP_CONTEXT_CONFIG_ITEMS',
>>  `$1.Slice,                       config_parse_unit_slice,            0,                             0
>>  $1.CPUAccounting,                config_parse_bool,                  0,                             offsetof($1, cgroup_context.cpu_accounting)
>>  $1.CPUShares,                    config_parse_cpu_shares,            0,                             offsetof($1, cgroup_context)
>> +$1.StartupCPUShares,             config_parse_startup_cpu_shares,    0,                             offsetof($1, cgroup_context)
>>  $1.CPUQuota,                     config_parse_cpu_quota,             0,                             offsetof($1, cgroup_context)
>>  $1.CPUQuotaPeriodSec,            config_parse_sec,                   0,                             offsetof($1, cgroup_context.cpu_quota_period_usec)
>>  $1.MemoryAccounting,             config_parse_bool,                  0,                             offsetof($1, cgroup_context.memory_accounting)
>> @@ -114,6 +115,7 @@ $1.DeviceAllow,                  config_parse_device_allow,          0,
>>  $1.DevicePolicy,                 config_parse_device_policy,         0,                             offsetof($1, cgroup_context.device_policy)
>>  $1.BlockIOAccounting,            config_parse_bool,                  0,                             offsetof($1, cgroup_context.blockio_accounting)
>>  $1.BlockIOWeight,                config_parse_blockio_weight,        0,                             offsetof($1, cgroup_context)
>> +$1.StartupBlockIOWeight,         config_parse_startup_blockio_weight, 0,                            offsetof($1, cgroup_context)
>>  $1.BlockIODeviceWeight,          config_parse_blockio_device_weight, 0,                             offsetof($1, cgroup_context)
>>  $1.BlockIOReadBandwidth,         config_parse_blockio_bandwidth,     0,                             offsetof($1, cgroup_context)
>>  $1.BlockIOWriteBandwidth,        config_parse_blockio_bandwidth,     0,                             offsetof($1, cgroup_context)'
>> diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
>> index 14c194b..9605d8d 100644
>> --- a/src/core/load-fragment.c
>> +++ b/src/core/load-fragment.c
>> @@ -2451,6 +2451,47 @@ int config_parse_cpu_shares(
>>          }
>>
>>          c->cpu_shares = lu;
>> +        if (!c->startup_cpu_shares_set)
>> +                c->startup_cpu_shares = lu;
>> +
>> +        return 0;
>> +}
>> +
>> +int config_parse_startup_cpu_shares(
>> +                const char *unit,
>> +                const char *filename,
>> +                unsigned line,
>> +                const char *section,
>> +                unsigned section_line,
>> +                const char *lvalue,
>> +                int ltype,
>> +                const char *rvalue,
>> +                void *data,
>> +                void *userdata) {
>> +
>> +        CGroupContext *c = data;
>> +        unsigned long lu;
>> +        int r;
>> +
>> +        assert(filename);
>> +        assert(lvalue);
>> +        assert(rvalue);
>> +
>> +        if (isempty(rvalue)) {
>> +                c->startup_cpu_shares = 1024;
>> +                return 0;
>> +        }
>> +
>> +        r = safe_atolu(rvalue, &lu);
>> +        if (r < 0 || lu <= 0) {
>> +                log_syntax(unit, LOG_ERR, filename, line, EINVAL,
>> +                           "Startup CPU shares '%s' invalid. Ignoring.", rvalue);
>> +                return 0;
>> +        }
>> +
>> +        c->startup_cpu_shares = lu;
>> +        c->startup_cpu_shares_set = true;
>> +
>>          return 0;
>>  }
>>
>> @@ -2628,6 +2669,46 @@ int config_parse_blockio_weight(
>>          }
>>
>>          c->blockio_weight = lu;
>> +        if (!c->startup_blockio_weight_set)
>> +                c->startup_blockio_weight = lu;
>> +
>> +        return 0;
>> +}
>> +
>> +int config_parse_startup_blockio_weight(
>> +                const char *unit,
>> +                const char *filename,
>> +                unsigned line,
>> +                const char *section,
>> +                unsigned section_line,
>> +                const char *lvalue,
>> +                int ltype,
>> +                const char *rvalue,
>> +                void *data,
>> +                void *userdata) {
>> +
>> +        CGroupContext *c = data;
>> +        unsigned long lu;
>> +        int r;
>> +
>> +        assert(filename);
>> +        assert(lvalue);
>> +        assert(rvalue);
>> +
>> +        if (isempty(rvalue)) {
>> +                c->startup_blockio_weight = 1000;
>> +                return 0;
>> +        }
>> +
>> +        r = safe_atolu(rvalue, &lu);
>> +        if (r < 0 || lu < 10 || lu > 1000) {
>> +                log_syntax(unit, LOG_ERR, filename, line, EINVAL,
>> +                           "Startup Block IO weight '%s' invalid. Ignoring.", rvalue);
>> +                return 0;
>> +        }
>> +
>> +        c->startup_blockio_weight = lu;
>> +        c->startup_blockio_weight_set = true;
>>
>>          return 0;
>>  }
>> @@ -3445,11 +3526,13 @@ void unit_dump_config_items(FILE *f) {
>>                  { config_parse_address_families,      "FAMILIES" },
>>  #endif
>>                  { config_parse_cpu_shares,            "SHARES" },
>> +                { config_parse_startup_cpu_shares,    "STARTUPSHARES" },
>>                  { config_parse_memory_limit,          "LIMIT" },
>>                  { config_parse_device_allow,          "DEVICE" },
>>                  { config_parse_device_policy,         "POLICY" },
>>                  { config_parse_blockio_bandwidth,     "BANDWIDTH" },
>>                  { config_parse_blockio_weight,        "WEIGHT" },
>> +                { config_parse_startup_blockio_weight, "STARTUPWEIGHT" },
>>                  { config_parse_blockio_device_weight, "DEVICEWEIGHT" },
>>                  { config_parse_long,                  "LONG" },
>>                  { config_parse_socket_service,        "SERVICE" },
>> diff --git a/src/core/load-fragment.h b/src/core/load-fragment.h
>> index 242fd27..5b1bcf9 100644
>> --- a/src/core/load-fragment.h
>> +++ b/src/core/load-fragment.h
>> @@ -80,10 +80,12 @@ int config_parse_syscall_errno(const char *unit, const char *filename, unsigned
>>  int config_parse_environ(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
>>  int config_parse_unit_slice(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
>>  int config_parse_cpu_shares(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
>> +int config_parse_startup_cpu_shares(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
>>  int config_parse_memory_limit(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
>>  int config_parse_device_policy(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
>>  int config_parse_device_allow(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
>>  int config_parse_blockio_weight(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
>> +int config_parse_startup_blockio_weight(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
>>  int config_parse_blockio_device_weight(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
>>  int config_parse_blockio_bandwidth(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
>>  int config_parse_job_mode(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
>> diff --git a/src/core/manager.c b/src/core/manager.c
>> index 5772f40..809d995 100644
>> --- a/src/core/manager.c
>> +++ b/src/core/manager.c
>> @@ -456,6 +456,10 @@ int manager_new(SystemdRunningAs running_as, Manager **_m) {
>>          if (r < 0)
>>                  goto fail;
>>
>> +        r = set_ensure_allocated(&m->startup_units, trivial_hash_func, trivial_compare_func);
>> +        if (r < 0)
>> +                goto fail;
>> +
>>          r = set_ensure_allocated(&m->failed_units, trivial_hash_func, trivial_compare_func);
>>          if (r < 0)
>>                  goto fail;
>> @@ -794,6 +798,7 @@ void manager_free(Manager *m) {
>>          hashmap_free(m->watch_pids2);
>>          hashmap_free(m->watch_bus);
>>
>> +        set_free(m->startup_units);
>>          set_free(m->failed_units);
>>
>>          sd_event_source_unref(m->signal_event_source);
>> @@ -2446,6 +2451,9 @@ bool manager_unit_inactive_or_pending(Manager *m, const char *name) {
>>  void manager_check_finished(Manager *m) {
>>          char userspace[FORMAT_TIMESPAN_MAX], initrd[FORMAT_TIMESPAN_MAX], kernel[FORMAT_TIMESPAN_MAX], sum[FORMAT_TIMESPAN_MAX];
>>          usec_t firmware_usec, loader_usec, kernel_usec, initrd_usec, userspace_usec, total_usec;
>> +        Unit *u = NULL;
>> +        Iterator i;
>> +        UnitActiveState state;
>>
>>          assert(m);
>>
>> @@ -2533,6 +2541,14 @@ void manager_check_finished(Manager *m) {
>>                                     NULL);
>>          }
>>
>> +        SET_FOREACH(u, m->startup_units, i) {
>> +                u = set_steal_first(m->startup_units);
>> +                state = unit_active_state(u);
>> +                if (!UNIT_IS_ACTIVE_OR_ACTIVATING(state))
>> +                        continue;
>> +                cgroup_context_apply(m, unit_get_cgroup_context(u), unit_get_cgroup_mask(u), u->cgroup_path);
>> +        }
>> +
>>          bus_manager_send_finished(m, firmware_usec, loader_usec, kernel_usec, initrd_usec, userspace_usec, total_usec);
>>
>>          sd_notifyf(false,
>> diff --git a/src/core/manager.h b/src/core/manager.h
>> index a3de351..ab4cafc 100644
>> --- a/src/core/manager.h
>> +++ b/src/core/manager.h
>> @@ -116,6 +116,9 @@ struct Manager {
>>          Hashmap *watch_pids1;  /* pid => Unit object n:1 */
>>          Hashmap *watch_pids2;  /* pid => Unit object n:1 */
>>
>> +        /* A set contains all units which cgroup should be refreshed after startup */
>> +        Set *startup_units;
>> +
>>          /* A set which contains all currently failed units */
>>          Set *failed_units;
>>
>> diff --git a/src/core/unit.c b/src/core/unit.c
>> index 6ac359e..cb50bcc 100644
>> --- a/src/core/unit.c
>> +++ b/src/core/unit.c
>> @@ -1071,6 +1071,20 @@ static int unit_add_mount_dependencies(Unit *u) {
>>          return 0;
>>  }
>>
>> +static int unit_add_startup_units(Unit *u) {
>> +        CGroupContext *c;
>> +        int r = 0;
>> +
>> +        c = unit_get_cgroup_context(u);
>> +        if (c != NULL && manager_state(u->manager) == MANAGER_STARTING &&
>> +            (c->startup_cpu_shares_set || c->startup_blockio_weight_set)) {
>> +                r = set_put(u->manager->startup_units, u);
>> +                if (r == -EEXIST)
>> +                        r = 0;
>> +        }
>> +        return r;
>> +}
>> +
>>  int unit_load(Unit *u) {
>>          int r;
>>
>> @@ -1112,6 +1126,10 @@ int unit_load(Unit *u) {
>>                  if (r < 0)
>>                          goto fail;
>>
>> +                r = unit_add_startup_units(u);
>> +                if (r < 0)
>> +                        goto fail;
>> +
>>                  if (u->on_failure_job_mode == JOB_ISOLATE && set_size(u->dependencies[UNIT_ON_FAILURE]) > 1) {
>>                          log_error_unit(u->id, "More than one OnFailure= dependencies specified for %s but OnFailureJobMode=isolate set. Refusing.", u->id);
>>                          r = -EINVAL;
>> --
>> 1.9.0
>>
>> _______________________________________________
>> systemd-devel mailing list
>> systemd-devel at lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/systemd-devel
> 


More information about the systemd-devel mailing list