Merge pull request #1886 from poettering/tasks-max
Enable TasksMax by default for all units
This commit is contained in:
commit
44690833df
|
@ -1,4 +1,4 @@
|
|||
<?xml version='1.0'?> <!--*-nxml-*-->
|
||||
<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
|
||||
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
|
||||
|
||||
|
@ -277,7 +277,18 @@
|
|||
limit relative to the amount of physical RAM. Defaults to 10%.
|
||||
Note that this size is a safety limit only. As each runtime
|
||||
directory is a tmpfs file system, it will only consume as much
|
||||
memory as is needed. </para></listitem>
|
||||
memory as is needed.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>UserTasksMax=</varname></term>
|
||||
|
||||
<listitem><para>Sets the maximum number of OS tasks each user
|
||||
may run concurrently. This controls the
|
||||
<varname>TasksMax=</varname> setting of the per-user slice
|
||||
unit, see
|
||||
<citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
||||
for details. Defaults to 4096.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<?xml version='1.0'?> <!--*-nxml-*-->
|
||||
<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
|
||||
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
|
||||
|
||||
|
@ -317,7 +317,20 @@
|
|||
<varname>MemoryAccounting=</varname> and
|
||||
<varname>TasksAccounting=</varname>. See
|
||||
<citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
||||
for details on the per-unit settings.</para></listitem>
|
||||
for details on the per-unit
|
||||
settings. <varname>DefaulTasksAccounting=</varname> defaults
|
||||
to on, the other three settings to off.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>DefaultTasksMax=</varname></term>
|
||||
|
||||
<listitem><para>Configure the default value for the per-unit
|
||||
<varname>TasksMax=</varname> setting. See
|
||||
<citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
||||
for details. This setting applies to all unit types that
|
||||
support resource control settings, with the exception of slice
|
||||
units. Defaults to 512.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
|
|
|
@ -241,7 +241,10 @@
|
|||
see <ulink
|
||||
url="https://www.kernel.org/doc/Documentation/cgroups/pids.txt">pids.txt</ulink>.</para>
|
||||
|
||||
<para>Implies <literal>TasksAccounting=true</literal>.</para>
|
||||
<para>Implies <literal>TasksAccounting=true</literal>. The
|
||||
system default for this setting may be controlled with
|
||||
<varname>DefaultTasksMax=</varname> in
|
||||
<citerefentry><refentrytitle>systemd-system.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
|
|
|
@ -82,8 +82,8 @@
|
|||
<listitem><para>hours, hour, hr, h</para></listitem>
|
||||
<listitem><para>days, day, d</para></listitem>
|
||||
<listitem><para>weeks, week, w</para></listitem>
|
||||
<listitem><para>months, month</para></listitem>
|
||||
<listitem><para>years, year, y</para></listitem>
|
||||
<listitem><para>months, month, M (defined as 30.44 days)</para></listitem>
|
||||
<listitem><para>years, year, y (define as 365.25 days)</para></listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>If no time unit is specified, generally seconds are assumed,
|
||||
|
|
|
@ -1423,12 +1423,16 @@ static int copy_quota_hierarchy(int fd, uint64_t old_subvol_id, uint64_t new_sub
|
|||
return n_old_qgroups;
|
||||
|
||||
r = btrfs_subvol_get_parent(fd, old_subvol_id, &old_parent_id);
|
||||
if (r < 0)
|
||||
if (r == -ENXIO)
|
||||
/* We have no parent, hence nothing to copy. */
|
||||
n_old_parent_qgroups = 0;
|
||||
else if (r < 0)
|
||||
return r;
|
||||
|
||||
n_old_parent_qgroups = btrfs_qgroup_find_parents(fd, old_parent_id, &old_parent_qgroups);
|
||||
if (n_old_parent_qgroups < 0)
|
||||
return n_old_parent_qgroups;
|
||||
else {
|
||||
n_old_parent_qgroups = btrfs_qgroup_find_parents(fd, old_parent_id, &old_parent_qgroups);
|
||||
if (n_old_parent_qgroups < 0)
|
||||
return n_old_parent_qgroups;
|
||||
}
|
||||
|
||||
for (i = 0; i < n_old_qgroups; i++) {
|
||||
uint64_t id;
|
||||
|
@ -1885,14 +1889,19 @@ int btrfs_subvol_auto_qgroup_fd(int fd, uint64_t subvol_id, bool insert_intermed
|
|||
if (n > 0) /* already parent qgroups set up, let's bail */
|
||||
return 0;
|
||||
|
||||
r = btrfs_subvol_get_parent(fd, subvol_id, &parent_subvol);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
qgroups = mfree(qgroups);
|
||||
n = btrfs_qgroup_find_parents(fd, parent_subvol, &qgroups);
|
||||
if (n < 0)
|
||||
return n;
|
||||
|
||||
r = btrfs_subvol_get_parent(fd, subvol_id, &parent_subvol);
|
||||
if (r == -ENXIO)
|
||||
/* No parent, hence no qgroup memberships */
|
||||
n = 0;
|
||||
else if (r < 0)
|
||||
return r;
|
||||
else {
|
||||
n = btrfs_qgroup_find_parents(fd, parent_subvol, &qgroups);
|
||||
if (n < 0)
|
||||
return n;
|
||||
}
|
||||
|
||||
if (insert_intermediary_qgroup) {
|
||||
uint64_t lowest = 256, new_qgroupid;
|
||||
|
|
|
@ -323,15 +323,15 @@ char *format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy) {
|
|||
const char *suffix;
|
||||
usec_t usec;
|
||||
} table[] = {
|
||||
{ "y", USEC_PER_YEAR },
|
||||
{ "month", USEC_PER_MONTH },
|
||||
{ "w", USEC_PER_WEEK },
|
||||
{ "d", USEC_PER_DAY },
|
||||
{ "h", USEC_PER_HOUR },
|
||||
{ "min", USEC_PER_MINUTE },
|
||||
{ "s", USEC_PER_SEC },
|
||||
{ "ms", USEC_PER_MSEC },
|
||||
{ "us", 1 },
|
||||
{ "y", USEC_PER_YEAR },
|
||||
{ "month", USEC_PER_MONTH },
|
||||
{ "w", USEC_PER_WEEK },
|
||||
{ "d", USEC_PER_DAY },
|
||||
{ "h", USEC_PER_HOUR },
|
||||
{ "min", USEC_PER_MINUTE },
|
||||
{ "s", USEC_PER_SEC },
|
||||
{ "ms", USEC_PER_MSEC },
|
||||
{ "us", 1 },
|
||||
};
|
||||
|
||||
unsigned i;
|
||||
|
@ -711,33 +711,34 @@ int parse_time(const char *t, usec_t *usec, usec_t default_unit) {
|
|||
const char *suffix;
|
||||
usec_t usec;
|
||||
} table[] = {
|
||||
{ "seconds", USEC_PER_SEC },
|
||||
{ "second", USEC_PER_SEC },
|
||||
{ "sec", USEC_PER_SEC },
|
||||
{ "s", USEC_PER_SEC },
|
||||
{ "seconds", USEC_PER_SEC },
|
||||
{ "second", USEC_PER_SEC },
|
||||
{ "sec", USEC_PER_SEC },
|
||||
{ "s", USEC_PER_SEC },
|
||||
{ "minutes", USEC_PER_MINUTE },
|
||||
{ "minute", USEC_PER_MINUTE },
|
||||
{ "min", USEC_PER_MINUTE },
|
||||
{ "months", USEC_PER_MONTH },
|
||||
{ "month", USEC_PER_MONTH },
|
||||
{ "msec", USEC_PER_MSEC },
|
||||
{ "ms", USEC_PER_MSEC },
|
||||
{ "m", USEC_PER_MINUTE },
|
||||
{ "hours", USEC_PER_HOUR },
|
||||
{ "hour", USEC_PER_HOUR },
|
||||
{ "hr", USEC_PER_HOUR },
|
||||
{ "h", USEC_PER_HOUR },
|
||||
{ "days", USEC_PER_DAY },
|
||||
{ "day", USEC_PER_DAY },
|
||||
{ "d", USEC_PER_DAY },
|
||||
{ "weeks", USEC_PER_WEEK },
|
||||
{ "week", USEC_PER_WEEK },
|
||||
{ "w", USEC_PER_WEEK },
|
||||
{ "years", USEC_PER_YEAR },
|
||||
{ "year", USEC_PER_YEAR },
|
||||
{ "y", USEC_PER_YEAR },
|
||||
{ "usec", 1ULL },
|
||||
{ "us", 1ULL },
|
||||
{ "minute", USEC_PER_MINUTE },
|
||||
{ "min", USEC_PER_MINUTE },
|
||||
{ "months", USEC_PER_MONTH },
|
||||
{ "month", USEC_PER_MONTH },
|
||||
{ "M", USEC_PER_MONTH },
|
||||
{ "msec", USEC_PER_MSEC },
|
||||
{ "ms", USEC_PER_MSEC },
|
||||
{ "m", USEC_PER_MINUTE },
|
||||
{ "hours", USEC_PER_HOUR },
|
||||
{ "hour", USEC_PER_HOUR },
|
||||
{ "hr", USEC_PER_HOUR },
|
||||
{ "h", USEC_PER_HOUR },
|
||||
{ "days", USEC_PER_DAY },
|
||||
{ "day", USEC_PER_DAY },
|
||||
{ "d", USEC_PER_DAY },
|
||||
{ "weeks", USEC_PER_WEEK },
|
||||
{ "week", USEC_PER_WEEK },
|
||||
{ "w", USEC_PER_WEEK },
|
||||
{ "years", USEC_PER_YEAR },
|
||||
{ "year", USEC_PER_YEAR },
|
||||
{ "y", USEC_PER_YEAR },
|
||||
{ "usec", 1ULL },
|
||||
{ "us", 1ULL },
|
||||
};
|
||||
|
||||
const char *p, *s;
|
||||
|
|
|
@ -655,7 +655,18 @@ static int transient_unit_from_message(
|
|||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (u->load_state != UNIT_NOT_FOUND ||
|
||||
/* Check if the unit already exists or is already referenced,
|
||||
* in a number of different ways. Note that to cater for unit
|
||||
* types such as slice, we are generally fine with units that
|
||||
* are marked UNIT_LOADED even even though nothing was
|
||||
* actually loaded, as those unit types don't require a file
|
||||
* on disk to validly load. */
|
||||
|
||||
if (!IN_SET(u->load_state, UNIT_NOT_FOUND, UNIT_LOADED) ||
|
||||
u->fragment_path ||
|
||||
u->source_path ||
|
||||
!strv_isempty(u->dropin_paths) ||
|
||||
u->refs ||
|
||||
set_size(u->dependencies[UNIT_REFERENCED_BY]) > 0)
|
||||
return sd_bus_error_setf(error, BUS_ERROR_UNIT_EXISTS, "Unit %s already exists.", name);
|
||||
|
||||
|
@ -1960,6 +1971,7 @@ const sd_bus_vtable bus_manager_vtable[] = {
|
|||
SD_BUS_PROPERTY("DefaultLimitNICE", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_NICE]), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("DefaultLimitRTPRIO", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_RTPRIO]), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("DefaultLimitRTTIME", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_RTTIME]), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("DefaultTasksMax", "t", NULL, offsetof(Manager, default_tasks_max), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("TimerSlackNSec", "t", property_get_timer_slack_nsec, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
|
||||
SD_BUS_METHOD("GetUnit", "s", "o", method_get_unit, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
|
|
|
@ -126,7 +126,7 @@ $1.BlockIODeviceWeight, config_parse_blockio_device_weight, 0,
|
|||
$1.BlockIOReadBandwidth, config_parse_blockio_bandwidth, 0, offsetof($1, cgroup_context)
|
||||
$1.BlockIOWriteBandwidth, config_parse_blockio_bandwidth, 0, offsetof($1, cgroup_context)
|
||||
$1.TasksAccounting, config_parse_bool, 0, offsetof($1, cgroup_context.tasks_accounting)
|
||||
$1.TasksMax, config_parse_tasks_max, 0, offsetof($1, cgroup_context)
|
||||
$1.TasksMax, config_parse_tasks_max, 0, offsetof($1, cgroup_context.tasks_max)
|
||||
$1.Delegate, config_parse_bool, 0, offsetof($1, cgroup_context.delegate)
|
||||
$1.NetClass, config_parse_netclass, 0, offsetof($1, cgroup_context)'
|
||||
)m4_dnl
|
||||
|
|
|
@ -2991,12 +2991,11 @@ int config_parse_tasks_max(
|
|||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
CGroupContext *c = data;
|
||||
uint64_t u;
|
||||
uint64_t *tasks_max = data, u;
|
||||
int r;
|
||||
|
||||
if (isempty(rvalue) || streq(rvalue, "infinity")) {
|
||||
c->tasks_max = (uint64_t) -1;
|
||||
*tasks_max = (uint64_t) -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -3006,7 +3005,7 @@ int config_parse_tasks_max(
|
|||
return 0;
|
||||
}
|
||||
|
||||
c->tasks_max = u;
|
||||
*tasks_max = u;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -125,7 +125,8 @@ static FILE* arg_serialization = NULL;
|
|||
static bool arg_default_cpu_accounting = false;
|
||||
static bool arg_default_blockio_accounting = false;
|
||||
static bool arg_default_memory_accounting = false;
|
||||
static bool arg_default_tasks_accounting = false;
|
||||
static bool arg_default_tasks_accounting = true;
|
||||
static uint64_t arg_default_tasks_max = UINT64_C(512);
|
||||
|
||||
static void pager_open_if_enabled(void) {
|
||||
|
||||
|
@ -657,7 +658,7 @@ static int parse_config_file(void) {
|
|||
{ "Manager", "DefaultStartLimitInterval", config_parse_sec, 0, &arg_default_start_limit_interval },
|
||||
{ "Manager", "DefaultStartLimitBurst", config_parse_unsigned, 0, &arg_default_start_limit_burst },
|
||||
{ "Manager", "DefaultEnvironment", config_parse_environ, 0, &arg_default_environment },
|
||||
{ "Manager", "DefaultLimitCPU", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_CPU] },
|
||||
{ "Manager", "DefaultLimitCPU", config_parse_sec_limit, 0, &arg_default_rlimit[RLIMIT_CPU] },
|
||||
{ "Manager", "DefaultLimitFSIZE", config_parse_bytes_limit, 0, &arg_default_rlimit[RLIMIT_FSIZE] },
|
||||
{ "Manager", "DefaultLimitDATA", config_parse_bytes_limit, 0, &arg_default_rlimit[RLIMIT_DATA] },
|
||||
{ "Manager", "DefaultLimitSTACK", config_parse_bytes_limit, 0, &arg_default_rlimit[RLIMIT_STACK] },
|
||||
|
@ -672,11 +673,12 @@ static int parse_config_file(void) {
|
|||
{ "Manager", "DefaultLimitMSGQUEUE", config_parse_bytes_limit, 0, &arg_default_rlimit[RLIMIT_MSGQUEUE] },
|
||||
{ "Manager", "DefaultLimitNICE", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_NICE] },
|
||||
{ "Manager", "DefaultLimitRTPRIO", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_RTPRIO] },
|
||||
{ "Manager", "DefaultLimitRTTIME", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_RTTIME] },
|
||||
{ "Manager", "DefaultLimitRTTIME", config_parse_usec_limit, 0, &arg_default_rlimit[RLIMIT_RTTIME] },
|
||||
{ "Manager", "DefaultCPUAccounting", config_parse_bool, 0, &arg_default_cpu_accounting },
|
||||
{ "Manager", "DefaultBlockIOAccounting", config_parse_bool, 0, &arg_default_blockio_accounting },
|
||||
{ "Manager", "DefaultMemoryAccounting", config_parse_bool, 0, &arg_default_memory_accounting },
|
||||
{ "Manager", "DefaultTasksAccounting", config_parse_bool, 0, &arg_default_tasks_accounting },
|
||||
{ "Manager", "DefaultTasksMax", config_parse_tasks_max, 0, &arg_default_tasks_max },
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -712,6 +714,7 @@ static void manager_set_defaults(Manager *m) {
|
|||
m->default_blockio_accounting = arg_default_blockio_accounting;
|
||||
m->default_memory_accounting = arg_default_memory_accounting;
|
||||
m->default_tasks_accounting = arg_default_tasks_accounting;
|
||||
m->default_tasks_max = arg_default_tasks_max;
|
||||
|
||||
manager_set_default_rlimits(m, arg_default_rlimit);
|
||||
manager_environment_add(m, NULL, arg_default_environment);
|
||||
|
|
|
@ -577,6 +577,8 @@ int manager_new(ManagerRunningAs running_as, bool test_run, Manager **_m) {
|
|||
m->running_as = running_as;
|
||||
m->exit_code = _MANAGER_EXIT_CODE_INVALID;
|
||||
m->default_timer_accuracy_usec = USEC_PER_MINUTE;
|
||||
m->default_tasks_accounting = true;
|
||||
m->default_tasks_max = UINT64_C(512);
|
||||
|
||||
/* Prepare log fields we can use for structured logging */
|
||||
m->unit_log_field = unit_log_fields[running_as];
|
||||
|
|
|
@ -260,6 +260,7 @@ struct Manager {
|
|||
bool default_blockio_accounting;
|
||||
bool default_tasks_accounting;
|
||||
|
||||
uint64_t default_tasks_max;
|
||||
usec_t default_timer_accuracy_usec;
|
||||
|
||||
struct rlimit *rlimit[_RLIMIT_MAX];
|
||||
|
|
|
@ -402,15 +402,10 @@ static bool scope_check_gc(Unit *u) {
|
|||
/* Never clean up scopes that still have a process around,
|
||||
* even if the scope is formally dead. */
|
||||
|
||||
if (u->cgroup_path) {
|
||||
int r;
|
||||
if (!u->cgroup_path)
|
||||
return false;
|
||||
|
||||
r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path);
|
||||
if (r <= 0)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path) <= 0;
|
||||
}
|
||||
|
||||
static void scope_notify_cgroup_empty_event(Unit *u) {
|
||||
|
@ -577,6 +572,7 @@ const UnitVTable scope_vtable = {
|
|||
|
||||
.no_alias = true,
|
||||
.no_instances = true,
|
||||
.can_transient = true,
|
||||
|
||||
.init = scope_init,
|
||||
.load = scope_load,
|
||||
|
@ -611,7 +607,5 @@ const UnitVTable scope_vtable = {
|
|||
.bus_set_property = bus_scope_set_property,
|
||||
.bus_commit_properties = bus_scope_commit_properties,
|
||||
|
||||
.can_transient = true,
|
||||
|
||||
.enumerate = scope_enumerate,
|
||||
};
|
||||
|
|
|
@ -305,6 +305,7 @@ const UnitVTable slice_vtable = {
|
|||
|
||||
.no_alias = true,
|
||||
.no_instances = true,
|
||||
.can_transient = true,
|
||||
|
||||
.load = slice_load,
|
||||
|
||||
|
|
|
@ -40,7 +40,8 @@
|
|||
#DefaultCPUAccounting=no
|
||||
#DefaultBlockIOAccounting=no
|
||||
#DefaultMemoryAccounting=no
|
||||
#DefaultTasksAccounting=no
|
||||
#DefaultTasksAccounting=yes
|
||||
#DefaultTasksMax=512
|
||||
#DefaultLimitCPU=
|
||||
#DefaultLimitFSIZE=
|
||||
#DefaultLimitDATA=
|
||||
|
|
|
@ -132,6 +132,9 @@ static void unit_init(Unit *u) {
|
|||
cc->blockio_accounting = u->manager->default_blockio_accounting;
|
||||
cc->memory_accounting = u->manager->default_memory_accounting;
|
||||
cc->tasks_accounting = u->manager->default_tasks_accounting;
|
||||
|
||||
if (u->type != UNIT_SLICE)
|
||||
cc->tasks_max = u->manager->default_tasks_max;
|
||||
}
|
||||
|
||||
ec = unit_get_exec_context(u);
|
||||
|
@ -314,9 +317,6 @@ bool unit_check_gc(Unit *u) {
|
|||
if (state != UNIT_INACTIVE)
|
||||
return true;
|
||||
|
||||
if (UNIT_VTABLE(u)->no_gc)
|
||||
return true;
|
||||
|
||||
if (u->no_gc)
|
||||
return true;
|
||||
|
||||
|
|
|
@ -403,9 +403,6 @@ struct UnitVTable {
|
|||
/* Instances make no sense for this type */
|
||||
bool no_instances:1;
|
||||
|
||||
/* Exclude from automatic gc */
|
||||
bool no_gc:1;
|
||||
|
||||
/* True if transient units of this type are OK */
|
||||
bool can_transient:1;
|
||||
};
|
||||
|
|
|
@ -2753,13 +2753,101 @@ int manager_send_changed(Manager *manager, const char *property, ...) {
|
|||
l);
|
||||
}
|
||||
|
||||
int manager_start_slice(
|
||||
Manager *manager,
|
||||
const char *slice,
|
||||
const char *description,
|
||||
const char *after,
|
||||
const char *after2,
|
||||
uint64_t tasks_max,
|
||||
sd_bus_error *error,
|
||||
char **job) {
|
||||
|
||||
_cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
|
||||
int r;
|
||||
|
||||
assert(manager);
|
||||
assert(slice);
|
||||
|
||||
r = sd_bus_message_new_method_call(
|
||||
manager->bus,
|
||||
&m,
|
||||
"org.freedesktop.systemd1",
|
||||
"/org/freedesktop/systemd1",
|
||||
"org.freedesktop.systemd1.Manager",
|
||||
"StartTransientUnit");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_message_append(m, "ss", strempty(slice), "fail");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_message_open_container(m, 'a', "(sv)");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!isempty(description)) {
|
||||
r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (!isempty(after)) {
|
||||
r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (!isempty(after2)) {
|
||||
r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after2);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = sd_bus_message_append(m, "(sv)", "TasksMax", "t", tasks_max);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_message_close_container(m);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_message_append(m, "a(sa(sv))", 0);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_call(manager->bus, m, 0, error, &reply);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (job) {
|
||||
const char *j;
|
||||
char *copy;
|
||||
|
||||
r = sd_bus_message_read(reply, "o", &j);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
copy = strdup(j);
|
||||
if (!copy)
|
||||
return -ENOMEM;
|
||||
|
||||
*job = copy;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int manager_start_scope(
|
||||
Manager *manager,
|
||||
const char *scope,
|
||||
pid_t pid,
|
||||
const char *slice,
|
||||
const char *description,
|
||||
const char *after, const char *after2,
|
||||
const char *after,
|
||||
const char *after2,
|
||||
uint64_t tasks_max,
|
||||
sd_bus_error *error,
|
||||
char **job) {
|
||||
|
||||
|
@ -2827,6 +2915,10 @@ int manager_start_scope(
|
|||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_message_append(m, "(sv)", "TasksMax", "t", tasks_max);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_message_close_container(m);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
|
|
@ -34,3 +34,4 @@ Login.IdleAction, config_parse_handle_action, 0, offsetof(Manag
|
|||
Login.IdleActionSec, config_parse_sec, 0, offsetof(Manager, idle_action_usec)
|
||||
Login.RuntimeDirectorySize, config_parse_tmpfs_size, 0, offsetof(Manager, runtime_dir_size)
|
||||
Login.RemoveIPC, config_parse_bool, 0, offsetof(Manager, remove_ipc)
|
||||
Login.UserTasksMax, config_parse_uint64, 0, offsetof(Manager, user_tasks_max)
|
||||
|
|
|
@ -513,25 +513,31 @@ static int session_start_scope(Session *s) {
|
|||
|
||||
assert(s);
|
||||
assert(s->user);
|
||||
assert(s->user->slice);
|
||||
|
||||
if (!s->scope) {
|
||||
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
_cleanup_free_ char *description = NULL;
|
||||
char *scope, *job = NULL;
|
||||
|
||||
description = strjoin("Session ", s->id, " of user ", s->user->name, NULL);
|
||||
if (!description)
|
||||
return log_oom();
|
||||
const char *description;
|
||||
|
||||
scope = strjoin("session-", s->id, ".scope", NULL);
|
||||
if (!scope)
|
||||
return log_oom();
|
||||
|
||||
r = manager_start_scope(s->manager, scope, s->leader, s->user->slice, description, "systemd-logind.service", "systemd-user-sessions.service", &error, &job);
|
||||
description = strjoina("Session ", s->id, " of user ", s->user->name, NULL);
|
||||
|
||||
r = manager_start_scope(
|
||||
s->manager,
|
||||
scope,
|
||||
s->leader,
|
||||
s->user->slice,
|
||||
description,
|
||||
"systemd-logind.service",
|
||||
"systemd-user-sessions.service",
|
||||
(uint64_t) -1, /* disable TasksMax= for the scope, rely on the slice setting for it */
|
||||
&error,
|
||||
&job);
|
||||
if (r < 0) {
|
||||
log_error("Failed to start session scope %s: %s %s",
|
||||
scope, bus_error_message(&error, r), error.name);
|
||||
log_error_errno(r, "Failed to start session scope %s: %s", scope, bus_error_message(&error, r));
|
||||
free(scope);
|
||||
return r;
|
||||
} else {
|
||||
|
@ -543,7 +549,7 @@ static int session_start_scope(Session *s) {
|
|||
}
|
||||
|
||||
if (s->scope)
|
||||
hashmap_put(s->manager->session_units, s->scope, s);
|
||||
(void) hashmap_put(s->manager->session_units, s->scope, s);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <unistd.h>
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "bus-common-errors.h"
|
||||
#include "bus-error.h"
|
||||
#include "bus-util.h"
|
||||
#include "clean-ipc.h"
|
||||
|
@ -44,6 +45,7 @@
|
|||
#include "rm-rf.h"
|
||||
#include "smack-util.h"
|
||||
#include "special.h"
|
||||
#include "stdio-util.h"
|
||||
#include "string-table.h"
|
||||
#include "unit-name.h"
|
||||
#include "user-util.h"
|
||||
|
@ -392,34 +394,51 @@ fail:
|
|||
}
|
||||
|
||||
static int user_start_slice(User *u) {
|
||||
char *job;
|
||||
int r;
|
||||
|
||||
assert(u);
|
||||
|
||||
if (!u->slice) {
|
||||
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
char lu[DECIMAL_STR_MAX(uid_t) + 1], *slice;
|
||||
sprintf(lu, UID_FMT, u->uid);
|
||||
char lu[DECIMAL_STR_MAX(uid_t) + 1], *slice, *job;
|
||||
const char *description;
|
||||
|
||||
u->slice_job = mfree(u->slice_job);
|
||||
|
||||
xsprintf(lu, UID_FMT, u->uid);
|
||||
r = slice_build_subslice(SPECIAL_USER_SLICE, lu, &slice);
|
||||
if (r < 0)
|
||||
return r;
|
||||
return log_error_errno(r, "Failed to build slice name: %m");
|
||||
|
||||
r = manager_start_unit(u->manager, slice, &error, &job);
|
||||
description = strjoina("User Slice of ", u->name);
|
||||
|
||||
r = manager_start_slice(
|
||||
u->manager,
|
||||
slice,
|
||||
description,
|
||||
"systemd-logind.service",
|
||||
"systemd-user-sessions.service",
|
||||
u->manager->user_tasks_max,
|
||||
&error,
|
||||
&job);
|
||||
if (r < 0) {
|
||||
log_error("Failed to start user slice: %s", bus_error_message(&error, r));
|
||||
free(slice);
|
||||
|
||||
if (sd_bus_error_has_name(&error, BUS_ERROR_UNIT_EXISTS))
|
||||
/* The slice already exists? If so, that's fine, let's just reuse it */
|
||||
u->slice = slice;
|
||||
else {
|
||||
log_error_errno(r, "Failed to start user slice %s, ignoring: %s (%s)", slice, bus_error_message(&error, r), error.name);
|
||||
free(slice);
|
||||
/* we don't fail due to this, let's try to continue */
|
||||
}
|
||||
} else {
|
||||
u->slice = slice;
|
||||
|
||||
free(u->slice_job);
|
||||
u->slice_job = job;
|
||||
}
|
||||
}
|
||||
|
||||
if (u->slice)
|
||||
hashmap_put(u->manager->user_units, u->slice, u);
|
||||
(void) hashmap_put(u->manager->user_units, u->slice, u);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -433,16 +452,21 @@ static int user_start_service(User *u) {
|
|||
|
||||
if (!u->service) {
|
||||
char lu[DECIMAL_STR_MAX(uid_t) + 1], *service;
|
||||
sprintf(lu, UID_FMT, u->uid);
|
||||
|
||||
xsprintf(lu, UID_FMT, u->uid);
|
||||
r = unit_name_build("user", lu, ".service", &service);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to build service name: %m");
|
||||
|
||||
r = manager_start_unit(u->manager, service, &error, &job);
|
||||
r = manager_start_unit(
|
||||
u->manager,
|
||||
service,
|
||||
&error,
|
||||
&job);
|
||||
if (r < 0) {
|
||||
log_error("Failed to start user service: %s", bus_error_message(&error, r));
|
||||
log_error_errno(r, "Failed to start user service, ignoring: %s", bus_error_message(&error, r));
|
||||
free(service);
|
||||
/* we don't fail due to this, let's try to continue */
|
||||
} else {
|
||||
u->service = service;
|
||||
|
||||
|
@ -452,7 +476,7 @@ static int user_start_service(User *u) {
|
|||
}
|
||||
|
||||
if (u->service)
|
||||
hashmap_put(u->manager->user_units, u->service, u);
|
||||
(void) hashmap_put(u->manager->user_units, u->service, u);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -70,6 +70,7 @@ static Manager *manager_new(void) {
|
|||
m->idle_action_not_before_usec = now(CLOCK_MONOTONIC);
|
||||
|
||||
m->runtime_dir_size = PAGE_ALIGN((size_t) (physical_memory() / 10)); /* 10% */
|
||||
m->user_tasks_max = UINT64_C(4096);
|
||||
|
||||
m->devices = hashmap_new(&string_hash_ops);
|
||||
m->seats = hashmap_new(&string_hash_ops);
|
||||
|
|
|
@ -32,3 +32,4 @@
|
|||
#IdleActionSec=30min
|
||||
#RuntimeDirectorySize=10%
|
||||
#RemoveIPC=yes
|
||||
#UserTasksMax=4096
|
||||
|
|
|
@ -134,6 +134,7 @@ struct Manager {
|
|||
sd_event_source *lid_switch_ignore_event_source;
|
||||
|
||||
size_t runtime_dir_size;
|
||||
uint64_t user_tasks_max;
|
||||
};
|
||||
|
||||
int manager_add_device(Manager *m, const char *sysfs, bool master, Device **_device);
|
||||
|
@ -171,7 +172,8 @@ int bus_manager_shutdown_or_sleep_now_or_later(Manager *m, const char *unit_name
|
|||
|
||||
int manager_send_changed(Manager *manager, const char *property, ...) _sentinel_;
|
||||
|
||||
int manager_start_scope(Manager *manager, const char *scope, pid_t pid, const char *slice, const char *description, const char *after, const char *after2, sd_bus_error *error, char **job);
|
||||
int manager_start_slice(Manager *manager, const char *slice, const char *description, const char *after, const char *after2, uint64_t tasks_max, sd_bus_error *error, char **job);
|
||||
int manager_start_scope(Manager *manager, const char *scope, pid_t pid, const char *slice, const char *description, const char *after, const char *after2, uint64_t tasks_max, sd_bus_error *error, char **job);
|
||||
int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job);
|
||||
int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job);
|
||||
int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *error);
|
||||
|
|
|
@ -105,6 +105,10 @@ int register_machine(
|
|||
return bus_log_create_error(r);
|
||||
}
|
||||
|
||||
r = sd_bus_message_append(m, "(sv)", "TasksMax", "t", 8192);
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
||||
r = sd_bus_message_append(m, "(sv)", "DevicePolicy", "s", "strict");
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
|
|
@ -40,6 +40,16 @@ static int test_cgroup_mask(void) {
|
|||
puts("manager_new: Permission denied. Skipping test.");
|
||||
return EXIT_TEST_SKIP;
|
||||
}
|
||||
|
||||
/* Turn off all kinds of default accouning, so that we can
|
||||
* verify the masks resulting of our configuration and nothing
|
||||
* else. */
|
||||
m->default_cpu_accounting =
|
||||
m->default_memory_accounting =
|
||||
m->default_blockio_accounting =
|
||||
m->default_tasks_accounting = false;
|
||||
m->default_tasks_max = (uint64_t) -1;
|
||||
|
||||
assert_se(r >= 0);
|
||||
assert_se(manager_startup(m, serial, fdset) >= 0);
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ RestartForceExitStatus=133
|
|||
SuccessExitStatus=133
|
||||
Slice=machine.slice
|
||||
Delegate=yes
|
||||
TasksMax=8192
|
||||
|
||||
# Enforce a strict device policy, similar to the one nspawn configures
|
||||
# when it allocates its own scope unit. Make sure to keep these
|
||||
|
|
Loading…
Reference in a new issue