diff options
Diffstat (limited to 'src/core')
62 files changed, 573 insertions, 319 deletions
diff --git a/src/core/.gitignore b/src/core/.gitignore index f293bbdc93..465b4fcc20 100644 --- a/src/core/.gitignore +++ b/src/core/.gitignore @@ -1,2 +1,3 @@ /macros.systemd +/triggers.systemd /systemd.pc diff --git a/src/core/audit-fd.c b/src/core/audit-fd.c index 3ae46d8cfb..0a484d89fc 100644 --- a/src/core/audit-fd.c +++ b/src/core/audit-fd.c @@ -21,16 +21,17 @@ #include <errno.h> + #include "audit-fd.h" #ifdef HAVE_AUDIT -#include <stdbool.h> #include <libaudit.h> +#include <stdbool.h> +#include "fd-util.h" #include "log.h" #include "util.h" -#include "fd-util.h" static bool initialized = false; static int audit_fd; diff --git a/src/core/bus-endpoint.h b/src/core/bus-endpoint.h index 4a31f4c4be..f6c5f7c5af 100644 --- a/src/core/bus-endpoint.h +++ b/src/core/bus-endpoint.h @@ -24,8 +24,8 @@ typedef struct BusEndpoint BusEndpoint; typedef struct BusEndpointPolicy BusEndpointPolicy; -#include "hashmap.h" #include "bus-policy.h" +#include "hashmap.h" struct BusEndpointPolicy { char *name; diff --git a/src/core/bus-policy.h b/src/core/bus-policy.h index 3b04f5457a..2f61289185 100644 --- a/src/core/bus-policy.h +++ b/src/core/bus-policy.h @@ -21,9 +21,9 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include "kdbus.h" #include "list.h" #include "macro.h" -#include "kdbus.h" typedef struct BusNamePolicy BusNamePolicy; diff --git a/src/core/cgroup.c b/src/core/cgroup.c index bed01fde21..d122175417 100644 --- a/src/core/cgroup.c +++ b/src/core/cgroup.c @@ -217,7 +217,7 @@ static int whitelist_device(const char *path, const char *node, const char *acc) r = cg_set_attribute("devices", path, "devices.allow", buf); if (r < 0) - log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EINVAL) ? LOG_DEBUG : LOG_WARNING, r, + log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EINVAL, -EACCES) ? LOG_DEBUG : LOG_WARNING, r, "Failed to set devices.allow on %s: %m", path); return r; @@ -288,7 +288,7 @@ static int whitelist_major(const char *path, const char *name, char type, const r = cg_set_attribute("devices", path, "devices.allow", buf); if (r < 0) - log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EINVAL) ? LOG_DEBUG : LOG_WARNING, r, + log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EINVAL, -EACCES) ? LOG_DEBUG : LOG_WARNING, r, "Failed to set devices.allow on %s: %m", path); } @@ -328,13 +328,13 @@ void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, u c->cpu_shares != CGROUP_CPU_SHARES_INVALID ? c->cpu_shares : CGROUP_CPU_SHARES_DEFAULT); r = cg_set_attribute("cpu", path, "cpu.shares", buf); if (r < 0) - log_full_errno(IN_SET(r, -ENOENT, -EROFS) ? LOG_DEBUG : LOG_WARNING, r, + log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r, "Failed to set cpu.shares on %s: %m", path); sprintf(buf, USEC_FMT "\n", CGROUP_CPU_QUOTA_PERIOD_USEC); r = cg_set_attribute("cpu", path, "cpu.cfs_period_us", buf); if (r < 0) - log_full_errno(IN_SET(r, -ENOENT, -EROFS) ? LOG_DEBUG : LOG_WARNING, r, + log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r, "Failed to set cpu.cfs_period_us on %s: %m", path); if (c->cpu_quota_per_sec_usec != USEC_INFINITY) { @@ -343,7 +343,7 @@ void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, u } else r = cg_set_attribute("cpu", path, "cpu.cfs_quota_us", "-1"); if (r < 0) - log_full_errno(IN_SET(r, -ENOENT, -EROFS) ? LOG_DEBUG : LOG_WARNING, r, + log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r, "Failed to set cpu.cfs_quota_us on %s: %m", path); } @@ -359,7 +359,7 @@ void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, u c->blockio_weight != CGROUP_BLKIO_WEIGHT_INVALID ? c->blockio_weight : CGROUP_BLKIO_WEIGHT_DEFAULT); r = cg_set_attribute("blkio", path, "blkio.weight", buf); if (r < 0) - log_full_errno(IN_SET(r, -ENOENT, -EROFS) ? LOG_DEBUG : LOG_WARNING, r, + log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r, "Failed to set blkio.weight on %s: %m", path); /* FIXME: no way to reset this list */ @@ -373,7 +373,7 @@ void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, u sprintf(buf, "%u:%u %" PRIu64 "\n", major(dev), minor(dev), w->weight); r = cg_set_attribute("blkio", path, "blkio.weight_device", buf); if (r < 0) - log_full_errno(IN_SET(r, -ENOENT, -EROFS) ? LOG_DEBUG : LOG_WARNING, r, + log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r, "Failed to set blkio.weight_device on %s: %m", path); } } @@ -392,7 +392,7 @@ void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, u sprintf(buf, "%u:%u %" PRIu64 "\n", major(dev), minor(dev), b->bandwidth); r = cg_set_attribute("blkio", path, a, buf); if (r < 0) - log_full_errno(IN_SET(r, -ENOENT, -EROFS) ? LOG_DEBUG : LOG_WARNING, r, + log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r, "Failed to set %s on %s: %m", a, path); } } @@ -416,7 +416,7 @@ void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, u } if (r < 0) - log_full_errno(IN_SET(r, -ENOENT, -EROFS) ? LOG_DEBUG : LOG_WARNING, r, + log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r, "Failed to set memory.limit_in_bytes/memory.max on %s: %m", path); } @@ -432,7 +432,7 @@ void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, u else r = cg_set_attribute("devices", path, "devices.allow", "a"); if (r < 0) - log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EINVAL) ? LOG_DEBUG : LOG_WARNING, r, + log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EINVAL, -EACCES) ? LOG_DEBUG : LOG_WARNING, r, "Failed to reset devices.list on %s: %m", path); if (c->device_policy == CGROUP_CLOSED || @@ -494,7 +494,7 @@ void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, u r = cg_set_attribute("pids", path, "pids.max", "max"); if (r < 0) - log_full_errno(IN_SET(r, -ENOENT, -EROFS) ? LOG_DEBUG : LOG_WARNING, r, + log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r, "Failed to set pids.max on %s: %m", path); } @@ -505,7 +505,7 @@ void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, u r = cg_set_attribute("net_cls", path, "net_cls.classid", buf); if (r < 0) - log_full_errno(IN_SET(r, -ENOENT, -EROFS) ? LOG_DEBUG : LOG_WARNING, r, + log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r, "Failed to set net_cls.classid on %s: %m", path); } } diff --git a/src/core/cgroup.h b/src/core/cgroup.h index 457544b49f..1b18d06652 100644 --- a/src/core/cgroup.h +++ b/src/core/cgroup.h @@ -112,8 +112,8 @@ struct CGroupContext { bool delegate; }; -#include "unit.h" #include "cgroup-util.h" +#include "unit.h" void cgroup_context_init(CGroupContext *c); void cgroup_context_done(CGroupContext *c); diff --git a/src/core/dbus-automount.c b/src/core/dbus-automount.c index 45f2c2ffd6..54830a515b 100644 --- a/src/core/dbus-automount.c +++ b/src/core/dbus-automount.c @@ -21,8 +21,8 @@ #include "automount.h" #include "bus-util.h" -#include "string-util.h" #include "dbus-automount.h" +#include "string-util.h" static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, automount_result, AutomountResult); diff --git a/src/core/dbus-busname.c b/src/core/dbus-busname.c index 05ac89c3c0..445b237643 100644 --- a/src/core/dbus-busname.c +++ b/src/core/dbus-busname.c @@ -21,9 +21,9 @@ #include "bus-util.h" #include "busname.h" +#include "dbus-busname.h" #include "string-util.h" #include "unit.h" -#include "dbus-busname.h" static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, busname_result, BusNameResult); diff --git a/src/core/dbus-device.c b/src/core/dbus-device.c index cb156fd37c..97e4a47556 100644 --- a/src/core/dbus-device.c +++ b/src/core/dbus-device.c @@ -19,9 +19,9 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include "unit.h" -#include "device.h" #include "dbus-device.h" +#include "device.h" +#include "unit.h" const sd_bus_vtable bus_device_vtable[] = { SD_BUS_VTABLE_START(0), diff --git a/src/core/dbus-kill.c b/src/core/dbus-kill.c index 3b8116281c..c633eb1b76 100644 --- a/src/core/dbus-kill.c +++ b/src/core/dbus-kill.c @@ -19,11 +19,10 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include "signal-util.h" #include "bus-util.h" - -#include "kill.h" #include "dbus-kill.h" +#include "kill.h" +#include "signal-util.h" static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_kill_mode, kill_mode, KillMode); diff --git a/src/core/dbus-kill.h b/src/core/dbus-kill.h index 794c402048..1d32fca547 100644 --- a/src/core/dbus-kill.h +++ b/src/core/dbus-kill.h @@ -23,8 +23,8 @@ #include "sd-bus.h" -#include "unit.h" #include "kill.h" +#include "unit.h" extern const sd_bus_vtable bus_kill_vtable[]; diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c index f58ac55009..2562396180 100644 --- a/src/core/dbus-manager.c +++ b/src/core/dbus-manager.c @@ -648,6 +648,7 @@ static int transient_unit_from_message( Unit **unit, sd_bus_error *error) { + UnitType t; Unit *u; int r; @@ -655,12 +656,18 @@ static int transient_unit_from_message( assert(message); assert(name); + t = unit_name_to_type(name); + if (t < 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid unit name or type."); + + if (!unit_vtable[t]->can_transient) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unit type %s does not support transient units.", unit_type_to_string(t)); + r = manager_load_unit(m, name, NULL, error, &u); if (r < 0) return r; - if (u->load_state != UNIT_NOT_FOUND || - set_size(u->dependencies[UNIT_REFERENCED_BY]) > 0) + if (!unit_is_pristine(u)) return sd_bus_error_setf(error, BUS_ERROR_UNIT_EXISTS, "Unit %s already exists.", name); /* OK, the unit failed to load and is unreferenced, now let's @@ -674,6 +681,9 @@ static int transient_unit_from_message( if (r < 0) return r; + /* Now load the missing bits of the unit we just created */ + manager_dispatch_load_queue(m); + *unit = u; return 0; @@ -684,8 +694,6 @@ static int transient_aux_units_from_message( sd_bus_message *message, sd_bus_error *error) { - Unit *u; - char *name = NULL; int r; assert(m); @@ -696,20 +704,17 @@ static int transient_aux_units_from_message( return r; while ((r = sd_bus_message_enter_container(message, 'r', "sa(sv)")) > 0) { + const char *name = NULL; + Unit *u; + r = sd_bus_message_read(message, "s", &name); if (r < 0) return r; r = transient_unit_from_message(m, message, name, &u, error); - if (r < 0 && r != -EEXIST) + if (r < 0) return r; - if (r != -EEXIST) { - r = unit_load(u); - if (r < 0) - return r; - } - r = sd_bus_message_exit_container(message); if (r < 0) return r; @@ -728,7 +733,6 @@ static int method_start_transient_unit(sd_bus_message *message, void *userdata, const char *name, *smode; Manager *m = userdata; JobMode mode; - UnitType t; Unit *u; int r; @@ -743,13 +747,6 @@ static int method_start_transient_unit(sd_bus_message *message, void *userdata, if (r < 0) return r; - t = unit_name_to_type(name); - if (t < 0) - return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid unit type."); - - if (!unit_vtable[t]->can_transient) - return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unit type %s does not support transient units.", unit_type_to_string(t)); - mode = job_mode_from_string(smode); if (mode < 0) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Job mode %s is invalid.", smode); @@ -768,13 +765,6 @@ static int method_start_transient_unit(sd_bus_message *message, void *userdata, if (r < 0) return r; - /* And load this stub fully */ - r = unit_load(u); - if (r < 0) - return r; - - manager_dispatch_load_queue(m); - /* Finally, start it */ return bus_unit_queue_job(message, u, JOB_START, mode, false, error); } @@ -1964,6 +1954,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), diff --git a/src/core/dbus-mount.c b/src/core/dbus-mount.c index 90a6d37073..bc5751a10d 100644 --- a/src/core/dbus-mount.c +++ b/src/core/dbus-mount.c @@ -23,10 +23,10 @@ #include "dbus-cgroup.h" #include "dbus-execute.h" #include "dbus-kill.h" +#include "dbus-mount.h" #include "mount.h" #include "string-util.h" #include "unit.h" -#include "dbus-mount.h" static int property_get_what( sd_bus *bus, diff --git a/src/core/dbus-path.c b/src/core/dbus-path.c index 9e32b5fb06..e0544e9161 100644 --- a/src/core/dbus-path.c +++ b/src/core/dbus-path.c @@ -20,10 +20,10 @@ ***/ #include "bus-util.h" +#include "dbus-path.h" #include "path.h" #include "string-util.h" #include "unit.h" -#include "dbus-path.h" static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, path_result, PathResult); diff --git a/src/core/dbus-scope.h b/src/core/dbus-scope.h index 33beda47b7..4fb0b25e09 100644 --- a/src/core/dbus-scope.h +++ b/src/core/dbus-scope.h @@ -22,6 +22,7 @@ ***/ #include "sd-bus.h" + #include "unit.h" extern const sd_bus_vtable bus_scope_vtable[]; diff --git a/src/core/dbus-service.h b/src/core/dbus-service.h index aab9f7aa26..a67b64ab5b 100644 --- a/src/core/dbus-service.h +++ b/src/core/dbus-service.h @@ -22,6 +22,7 @@ ***/ #include "sd-bus.h" + #include "unit.h" extern const sd_bus_vtable bus_service_vtable[]; diff --git a/src/core/dbus-slice.c b/src/core/dbus-slice.c index 09e78d1f33..469e3e1c93 100644 --- a/src/core/dbus-slice.c +++ b/src/core/dbus-slice.c @@ -19,10 +19,10 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include "unit.h" -#include "slice.h" #include "dbus-cgroup.h" #include "dbus-slice.h" +#include "slice.h" +#include "unit.h" const sd_bus_vtable bus_slice_vtable[] = { SD_BUS_VTABLE_START(0), diff --git a/src/core/dbus-slice.h b/src/core/dbus-slice.h index eadc3b1a9c..117d11471b 100644 --- a/src/core/dbus-slice.h +++ b/src/core/dbus-slice.h @@ -22,6 +22,7 @@ ***/ #include "sd-bus.h" + #include "unit.h" extern const sd_bus_vtable bus_slice_vtable[]; diff --git a/src/core/dbus-socket.c b/src/core/dbus-socket.c index be5ef261a6..895dd07753 100644 --- a/src/core/dbus-socket.c +++ b/src/core/dbus-socket.c @@ -150,6 +150,7 @@ const sd_bus_vtable bus_socket_vtable[] = { SD_BUS_PROPERTY("NConnections", "u", bus_property_get_unsigned, offsetof(Socket, n_connections), 0), SD_BUS_PROPERTY("NAccepted", "u", bus_property_get_unsigned, offsetof(Socket, n_accepted), 0), SD_BUS_PROPERTY("FileDescriptorName", "s", property_get_fdname, 0, 0), + SD_BUS_PROPERTY("SocketProtocol", "i", bus_property_get_int, offsetof(Socket, socket_protocol), SD_BUS_VTABLE_PROPERTY_CONST), BUS_EXEC_COMMAND_LIST_VTABLE("ExecStartPre", offsetof(Socket, exec_command[SOCKET_EXEC_START_PRE]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), BUS_EXEC_COMMAND_LIST_VTABLE("ExecStartPost", offsetof(Socket, exec_command[SOCKET_EXEC_START_POST]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), BUS_EXEC_COMMAND_LIST_VTABLE("ExecStopPre", offsetof(Socket, exec_command[SOCKET_EXEC_STOP_PRE]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), diff --git a/src/core/dbus-socket.h b/src/core/dbus-socket.h index 17164d9871..8dad6ea2e9 100644 --- a/src/core/dbus-socket.h +++ b/src/core/dbus-socket.h @@ -22,6 +22,7 @@ ***/ #include "sd-bus.h" + #include "unit.h" extern const sd_bus_vtable bus_socket_vtable[]; diff --git a/src/core/dbus-swap.c b/src/core/dbus-swap.c index 603ca95fd9..f2a0f1d172 100644 --- a/src/core/dbus-swap.c +++ b/src/core/dbus-swap.c @@ -23,10 +23,10 @@ #include "bus-util.h" #include "dbus-cgroup.h" #include "dbus-execute.h" +#include "dbus-swap.h" #include "string-util.h" #include "swap.h" #include "unit.h" -#include "dbus-swap.h" static int property_get_priority( sd_bus *bus, diff --git a/src/core/dbus-swap.h b/src/core/dbus-swap.h index 9469f68ab8..a414ca7f75 100644 --- a/src/core/dbus-swap.h +++ b/src/core/dbus-swap.h @@ -23,6 +23,7 @@ ***/ #include "sd-bus.h" + #include "unit.h" extern const sd_bus_vtable bus_swap_vtable[]; diff --git a/src/core/dbus-target.c b/src/core/dbus-target.c index 350f5c3ed2..654bcf1a29 100644 --- a/src/core/dbus-target.c +++ b/src/core/dbus-target.c @@ -19,8 +19,8 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include "unit.h" #include "dbus-target.h" +#include "unit.h" const sd_bus_vtable bus_target_vtable[] = { SD_BUS_VTABLE_START(0), diff --git a/src/core/dbus-timer.c b/src/core/dbus-timer.c index a8a280d961..ec301df6d7 100644 --- a/src/core/dbus-timer.c +++ b/src/core/dbus-timer.c @@ -180,8 +180,10 @@ const sd_bus_vtable bus_timer_vtable[] = { BUS_PROPERTY_DUAL_TIMESTAMP("LastTriggerUSec", offsetof(Timer, last_trigger), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Timer, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("AccuracyUSec", "t", bus_property_get_usec, offsetof(Timer, accuracy_usec), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("RandomizedDelayUSec", "t", bus_property_get_usec, offsetof(Timer, random_usec), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Persistent", "b", bus_property_get_bool, offsetof(Timer, persistent), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("WakeSystem", "b", bus_property_get_bool, offsetof(Timer, wake_system), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("RemainAfterElapse", "b", bus_property_get_bool, offsetof(Timer, remain_after_elapse), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_VTABLE_END }; @@ -282,8 +284,23 @@ static int bus_timer_set_transient_property( return 1; - } else if (streq(name, "WakeSystem")) { + } else if (streq(name, "RandomizedDelayUSec")) { + usec_t u = 0; + + r = sd_bus_message_read(message, "t", &u); + if (r < 0) + return r; + + if (mode != UNIT_CHECK) { + char time[FORMAT_TIMESPAN_MAX]; + + t->random_usec = u; + unit_write_drop_in_private_format(UNIT(t), mode, name, "RandomizedDelaySec=%s\n", format_timespan(time, sizeof(time), u, USEC_PER_MSEC)); + } + + return 1; + } else if (streq(name, "WakeSystem")) { int b; r = sd_bus_message_read(message, "b", &b); @@ -292,11 +309,24 @@ static int bus_timer_set_transient_property( if (mode != UNIT_CHECK) { t->wake_system = b; - unit_write_drop_in_private_format(UNIT(t), mode, name, "%s=%s\n", name, yes_no(t->wake_system)); + unit_write_drop_in_private_format(UNIT(t), mode, name, "%s=%s\n", name, yes_no(b)); } return 1; + } else if (streq(name, "RemainAfterElapse")) { + int b; + + r = sd_bus_message_read(message, "b", &b); + if (r < 0) + return r; + + if (mode != UNIT_CHECK) { + t->remain_after_elapse = b; + unit_write_drop_in_private_format(UNIT(t), mode, name, "%s=%s\n", name, yes_no(b)); + } + + return 1; } return 0; diff --git a/src/core/dbus-timer.h b/src/core/dbus-timer.h index 103172f055..ca35c4b8c1 100644 --- a/src/core/dbus-timer.h +++ b/src/core/dbus-timer.h @@ -22,6 +22,7 @@ ***/ #include "sd-bus.h" + #include "unit.h" extern const sd_bus_vtable bus_timer_vtable[]; diff --git a/src/core/dbus-unit.h b/src/core/dbus-unit.h index 0d7e5f8d83..ac9ee2d6b8 100644 --- a/src/core/dbus-unit.h +++ b/src/core/dbus-unit.h @@ -22,6 +22,7 @@ ***/ #include "sd-bus.h" + #include "unit.h" extern const sd_bus_vtable bus_unit_vtable[]; diff --git a/src/core/execute.c b/src/core/execute.c index 07979bf8b3..677480cbe1 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -2414,8 +2414,8 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) { for (i = 0; i < RLIM_NLIMITS; i++) if (c->rlimit[i]) - fprintf(f, "%s%s: "RLIM_FMT"\n", - prefix, rlimit_to_string(i), c->rlimit[i]->rlim_max); + fprintf(f, "%s%s: " RLIM_FMT " " RLIM_FMT "\n", + prefix, rlimit_to_string(i), c->rlimit[i]->rlim_cur, c->rlimit[i]->rlim_max); if (c->ioprio_set) { _cleanup_free_ char *class_str = NULL; diff --git a/src/core/execute.h b/src/core/execute.h index 1faff160cb..be5be9f531 100644 --- a/src/core/execute.h +++ b/src/core/execute.h @@ -27,16 +27,16 @@ typedef struct ExecContext ExecContext; typedef struct ExecRuntime ExecRuntime; typedef struct ExecParameters ExecParameters; -#include <sys/capability.h> +#include <sched.h> #include <stdbool.h> #include <stdio.h> -#include <sched.h> +#include <sys/capability.h> -#include "list.h" +#include "bus-endpoint.h" #include "fdset.h" +#include "list.h" #include "missing.h" #include "namespace.h" -#include "bus-endpoint.h" typedef enum ExecUtmpMode { EXEC_UTMP_INIT, @@ -204,8 +204,8 @@ struct ExecContext { BusEndpoint *bus_endpoint; }; -#include "cgroup.h" #include "cgroup-util.h" +#include "cgroup.h" struct ExecParameters { char **argv; diff --git a/src/core/hostname-setup.c b/src/core/hostname-setup.c index 3645f9c515..d92a9a764f 100644 --- a/src/core/hostname-setup.c +++ b/src/core/hostname-setup.c @@ -25,12 +25,12 @@ #include "alloc-util.h" #include "fileio.h" +#include "hostname-setup.h" #include "hostname-util.h" #include "log.h" #include "macro.h" #include "string-util.h" #include "util.h" -#include "hostname-setup.h" int hostname_setup(void) { int r; diff --git a/src/core/ima-setup.c b/src/core/ima-setup.c index 9572fa17d9..4f42ae6f31 100644 --- a/src/core/ima-setup.c +++ b/src/core/ima-setup.c @@ -21,8 +21,8 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <unistd.h> #include <errno.h> +#include <unistd.h> #include "fd-util.h" #include "fileio.h" diff --git a/src/core/job.c b/src/core/job.c index 53e0947215..9654590635 100644 --- a/src/core/job.c +++ b/src/core/job.c @@ -500,17 +500,26 @@ static void job_change_type(Job *j, JobType newtype) { } static int job_perform_on_unit(Job **j) { - /* While we execute this operation the job might go away (for - * example: because it finishes immediately or is replaced by a new, - * conflicting job.) To make sure we don't access a freed job later on - * we store the id here, so that we can verify the job is still - * valid. */ - Manager *m = (*j)->manager; - Unit *u = (*j)->unit; - JobType t = (*j)->type; - uint32_t id = (*j)->id; + uint32_t id; + Manager *m; + JobType t; + Unit *u; int r; + /* While we execute this operation the job might go away (for + * example: because it finishes immediately or is replaced by + * a new, conflicting job.) To make sure we don't access a + * freed job later on we store the id here, so that we can + * verify the job is still valid. */ + + assert(j); + assert(*j); + + m = (*j)->manager; + u = (*j)->unit; + t = (*j)->type; + id = (*j)->id; + switch (t) { case JOB_START: r = unit_start(u); @@ -518,6 +527,7 @@ static int job_perform_on_unit(Job **j) { case JOB_RESTART: t = JOB_STOP; + /* fall through */ case JOB_STOP: r = unit_stop(u); break; @@ -617,8 +627,7 @@ int job_run_and_invalidate(Job *j) { } _pure_ static const char *job_get_status_message_format(Unit *u, JobType t, JobResult result) { - const char *format; - const UnitStatusMessageFormats *format_table; + static const char *const generic_finished_start_job[_JOB_RESULT_MAX] = { [JOB_DONE] = "Started %s.", [JOB_TIMEOUT] = "Timed out starting %s.", @@ -644,11 +653,14 @@ _pure_ static const char *job_get_status_message_format(Unit *u, JobType t, JobR [JOB_SKIPPED] = "%s is not active.", }; + const UnitStatusMessageFormats *format_table; + const char *format; + assert(u); assert(t >= 0); assert(t < _JOB_TYPE_MAX); - if (t == JOB_START || t == JOB_STOP || t == JOB_RESTART) { + if (IN_SET(t, JOB_START, JOB_STOP, JOB_RESTART)) { format_table = &UNIT_VTABLE(u)->status_message_formats; if (format_table) { format = t == JOB_START ? format_table->finished_start_job[result] : @@ -672,7 +684,6 @@ _pure_ static const char *job_get_status_message_format(Unit *u, JobType t, JobR } static void job_print_status_message(Unit *u, JobType t, JobResult result) { - const char *format; static const char* const job_result_status_table[_JOB_RESULT_MAX] = { [JOB_DONE] = ANSI_GREEN " OK " ANSI_NORMAL, [JOB_TIMEOUT] = ANSI_HIGHLIGHT_RED " TIME " ANSI_NORMAL, @@ -683,10 +694,16 @@ static void job_print_status_message(Unit *u, JobType t, JobResult result) { [JOB_UNSUPPORTED] = ANSI_HIGHLIGHT_YELLOW "UNSUPP" ANSI_NORMAL, }; + const char *format; + assert(u); assert(t >= 0); assert(t < _JOB_TYPE_MAX); + /* Reload status messages have traditionally not been printed to console. */ + if (t == JOB_RELOAD) + return; + format = job_get_status_message_format(u, t, result); if (!format) return; @@ -699,10 +716,10 @@ static void job_print_status_message(Unit *u, JobType t, JobResult result) { REENABLE_WARNING; if (t == JOB_START && result == JOB_FAILED) { - _cleanup_free_ char *quoted = shell_maybe_quote(u->id); + _cleanup_free_ char *quoted; - manager_status_printf(u->manager, STATUS_TYPE_NORMAL, NULL, - "See 'systemctl status %s' for details.", strna(quoted)); + quoted = shell_maybe_quote(u->id); + manager_status_printf(u->manager, STATUS_TYPE_NORMAL, NULL, "See 'systemctl status %s' for details.", strna(quoted)); } } @@ -740,13 +757,22 @@ static void job_log_status_message(Unit *u, JobType t, JobResult result) { snprintf(buf, sizeof(buf), format, unit_description(u)); REENABLE_WARNING; - if (t == JOB_START) + switch (t) { + + case JOB_START: mid = result == JOB_DONE ? SD_MESSAGE_UNIT_STARTED : SD_MESSAGE_UNIT_FAILED; - else if (t == JOB_STOP || t == JOB_RESTART) - mid = SD_MESSAGE_UNIT_STOPPED; - else if (t == JOB_RELOAD) + break; + + case JOB_RELOAD: mid = SD_MESSAGE_UNIT_RELOADED; - else { + break; + + case JOB_STOP: + case JOB_RESTART: + mid = SD_MESSAGE_UNIT_STOPPED; + break; + + default: log_struct(job_result_log_level[result], LOG_UNIT_ID(u), LOG_MESSAGE("%s", buf), @@ -770,10 +796,7 @@ static void job_emit_status_message(Unit *u, JobType t, JobResult result) { return; job_log_status_message(u, t, result); - - /* Reload status messages have traditionally not been printed to console. */ - if (t != JOB_RELOAD) - job_print_status_message(u, t, result); + job_print_status_message(u, t, result); } static void job_fail_dependencies(Unit *u, UnitDependency d) { diff --git a/src/core/job.h b/src/core/job.h index 60d8bd4f3e..118b24e5b7 100644 --- a/src/core/job.h +++ b/src/core/job.h @@ -26,6 +26,7 @@ #include "sd-event.h" #include "list.h" +#include "unit-name.h" typedef struct Job Job; typedef struct JobDependency JobDependency; diff --git a/src/core/kmod-setup.c b/src/core/kmod-setup.c index 651f79a1fe..a6ab8cf4b3 100644 --- a/src/core/kmod-setup.c +++ b/src/core/kmod-setup.c @@ -19,17 +19,17 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <unistd.h> #include <string.h> +#include <unistd.h> #ifdef HAVE_KMOD #include <libkmod.h> #endif -#include "macro.h" -#include "capability-util.h" #include "bus-util.h" +#include "capability-util.h" #include "kmod-setup.h" +#include "macro.h" #ifdef HAVE_KMOD static void systemd_kmod_log( diff --git a/src/core/load-dropin.c b/src/core/load-dropin.c index 11566af51b..3fa66f91aa 100644 --- a/src/core/load-dropin.c +++ b/src/core/load-dropin.c @@ -20,13 +20,13 @@ ***/ -#include "unit.h" +#include "conf-parser.h" #include "load-dropin.h" +#include "load-fragment.h" #include "log.h" #include "strv.h" #include "unit-name.h" -#include "conf-parser.h" -#include "load-fragment.h" +#include "unit.h" static int add_dependency_consumer( UnitDependency dependency, diff --git a/src/core/load-dropin.h b/src/core/load-dropin.h index 1e018c4525..93ffcc4a72 100644 --- a/src/core/load-dropin.h +++ b/src/core/load-dropin.h @@ -21,8 +21,8 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include "unit.h" #include "dropin.h" +#include "unit.h" /* Read service data supplementary drop-in directories */ diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 index 4c5376d601..0408b9a829 100644 --- a/src/core/load-fragment-gperf.gperf.m4 +++ b/src/core/load-fragment-gperf.gperf.m4 @@ -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 @@ -249,6 +249,7 @@ Socket.ListenNetlink, config_parse_socket_listen, SOCKET_SOCK Socket.ListenSpecial, config_parse_socket_listen, SOCKET_SPECIAL, 0 Socket.ListenMessageQueue, config_parse_socket_listen, SOCKET_MQUEUE, 0 Socket.ListenUSBFunction, config_parse_socket_listen, SOCKET_USB_FUNCTION, 0 +Socket.SocketProtocol, config_parse_socket_protocol, 0, 0 Socket.BindIPv6Only, config_parse_socket_bind, 0, 0, Socket.Backlog, config_parse_unsigned, 0, offsetof(Socket, backlog) Socket.BindToDevice, config_parse_socket_bindtodevice, 0, 0 @@ -344,7 +345,9 @@ Timer.OnUnitActiveSec, config_parse_timer, 0, Timer.OnUnitInactiveSec, config_parse_timer, 0, 0 Timer.Persistent, config_parse_bool, 0, offsetof(Timer, persistent) Timer.WakeSystem, config_parse_bool, 0, offsetof(Timer, wake_system) +Timer.RemainAfterElapse, config_parse_bool, 0, offsetof(Timer, remain_after_elapse) Timer.AccuracySec, config_parse_sec, 0, offsetof(Timer, accuracy_usec) +Timer.RandomizedDelaySec, config_parse_sec, 0, offsetof(Timer, random_usec) Timer.Unit, config_parse_trigger_unit, 0, 0 m4_dnl Path.PathExists, config_parse_path_spec, 0, 0 diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c index 62cad0a0c0..3c124495b6 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -32,8 +32,8 @@ #include <sys/resource.h> #include <sys/stat.h> -#include "alloc-util.h" #include "af-list.h" +#include "alloc-util.h" #include "bus-error.h" #include "bus-internal.h" #include "bus-util.h" @@ -421,6 +421,37 @@ int config_parse_socket_listen(const char *unit, return 0; } +int config_parse_socket_protocol(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) { + Socket *s; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + s = SOCKET(data); + + if (streq(rvalue, "udplite")) + s->socket_protocol = IPPROTO_UDPLITE; + else if (streq(rvalue, "sctp")) + s->socket_protocol = IPPROTO_SCTP; + else { + log_syntax(unit, LOG_ERR, filename, line, 0, "Socket protocol not supported, ignoring: %s", rvalue); + return 0; + } + + return 0; +} + int config_parse_socket_bind(const char *unit, const char *filename, unsigned line, @@ -1058,59 +1089,123 @@ int config_parse_bounding_set( return 0; } -int config_parse_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) { +static int rlim_parse_u64(const char *val, rlim_t *res) { + int r = 0; - struct rlimit **rl = data; - rlim_t v; - int r; - - assert(filename); - assert(lvalue); - assert(rvalue); - assert(data); - - rl += ltype; - - if (streq(rvalue, "infinity")) - v = RLIM_INFINITY; + if (streq(val, "infinity")) + *res = RLIM_INFINITY; else { uint64_t u; /* setrlimit(2) suggests rlim_t is always 64bit on Linux. */ assert_cc(sizeof(rlim_t) == sizeof(uint64_t)); - r = safe_atou64(rvalue, &u); + r = safe_atou64(val, &u); if (r >= 0 && u >= (uint64_t) RLIM_INFINITY) r = -ERANGE; - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse resource value, ignoring: %s", rvalue); - return 0; - } + if (r == 0) + *res = (rlim_t) u; + } + return r; +} + +static int rlim_parse_size(const char *val, rlim_t *res) { + int r = 0; + + if (streq(val, "infinity")) + *res = RLIM_INFINITY; + else { + uint64_t u; + + r = parse_size(val, 1024, &u); + if (r >= 0 && u >= (uint64_t) RLIM_INFINITY) + r = -ERANGE; + if (r == 0) + *res = (rlim_t) u; + } + return r; +} + +static int rlim_parse_sec(const char *val, rlim_t *res) { + int r = 0; + + if (streq(val, "infinity")) + *res = RLIM_INFINITY; + else { + usec_t t; + + r = parse_sec(val, &t); + if (r < 0) + return r; + if (t == USEC_INFINITY) + *res = RLIM_INFINITY; + else + *res = (rlim_t) (DIV_ROUND_UP(t, USEC_PER_SEC)); - v = (rlim_t) u; } + return r; +} + +static int rlim_parse_usec(const char *val, rlim_t *res) { + int r = 0; + + if (streq(val, "infinity")) + *res = RLIM_INFINITY; + else { + usec_t t; + + r = parse_time(val, &t, 1); + if (r < 0) + return r; + if (t == USEC_INFINITY) + *res = RLIM_INFINITY; + else + *res = (rlim_t) t; + } + return r; +} + +static int parse_rlimit_range( + const char *unit, + const char *filename, + unsigned line, + const char *value, + struct rlimit **rl, + int (*rlim_parser)(const char *, rlim_t *)) { + + const char *whole_value = value; + rlim_t soft, hard; + _cleanup_free_ char *sword = NULL, *hword = NULL; + int nwords, r; + + assert(value); + + /* <value> or <soft:hard> */ + nwords = extract_many_words(&value, ":", EXTRACT_DONT_COALESCE_SEPARATORS, &sword, &hword, NULL); + r = nwords < 0 ? nwords : nwords == 0 ? -EINVAL : 0; + + if (r == 0) + r = rlim_parser(sword, &soft); + if (r == 0 && nwords == 2) + r = rlim_parser(hword, &hard); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse resource value, ignoring: %s", whole_value); + return 0; + } + if (nwords == 2 && soft > hard) + return log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid resource value ("RLIM_FMT" > "RLIM_FMT"), ignoring: %s", soft, hard, whole_value); if (!*rl) { *rl = new(struct rlimit, 1); if (!*rl) return log_oom(); } - - (*rl)->rlim_cur = (*rl)->rlim_max = v; + (*rl)->rlim_cur = soft; + (*rl)->rlim_max = nwords == 2 ? hard : soft; return 0; } -int config_parse_bytes_limit( +int config_parse_limit( const char *unit, const char *filename, unsigned line, @@ -1123,8 +1218,6 @@ int config_parse_bytes_limit( void *userdata) { struct rlimit **rl = data; - rlim_t bytes; - int r; assert(filename); assert(lvalue); @@ -1132,31 +1225,30 @@ int config_parse_bytes_limit( assert(data); rl += ltype; + return parse_rlimit_range(unit, filename, line, rvalue, rl, rlim_parse_u64); +} - if (streq(rvalue, "infinity")) - bytes = RLIM_INFINITY; - else { - uint64_t u; - - r = parse_size(rvalue, 1024, &u); - if (r >= 0 && u >= (uint64_t) RLIM_INFINITY) - r = -ERANGE; - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse resource value, ignoring: %s", rvalue); - return 0; - } +int config_parse_bytes_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) { - bytes = (rlim_t) u; - } + struct rlimit **rl = data; - if (!*rl) { - *rl = new(struct rlimit, 1); - if (!*rl) - return log_oom(); - } + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); - (*rl)->rlim_cur = (*rl)->rlim_max = bytes; - return 0; + rl += ltype; + return parse_rlimit_range(unit, filename, line, rvalue, rl, rlim_parse_size); } int config_parse_sec_limit( @@ -1172,8 +1264,6 @@ int config_parse_sec_limit( void *userdata) { struct rlimit **rl = data; - rlim_t seconds; - int r; assert(filename); assert(lvalue); @@ -1181,35 +1271,9 @@ int config_parse_sec_limit( assert(data); rl += ltype; - - if (streq(rvalue, "infinity")) - seconds = RLIM_INFINITY; - else { - usec_t t; - - r = parse_sec(rvalue, &t); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse resource value, ignoring: %s", rvalue); - return 0; - } - - if (t == USEC_INFINITY) - seconds = RLIM_INFINITY; - else - seconds = (rlim_t) (DIV_ROUND_UP(t, USEC_PER_SEC)); - } - - if (!*rl) { - *rl = new(struct rlimit, 1); - if (!*rl) - return log_oom(); - } - - (*rl)->rlim_cur = (*rl)->rlim_max = seconds; - return 0; + return parse_rlimit_range(unit, filename, line, rvalue, rl, rlim_parse_sec); } - int config_parse_usec_limit( const char *unit, const char *filename, @@ -1223,8 +1287,6 @@ int config_parse_usec_limit( void *userdata) { struct rlimit **rl = data; - rlim_t useconds; - int r; assert(filename); assert(lvalue); @@ -1232,33 +1294,10 @@ int config_parse_usec_limit( assert(data); rl += ltype; + return parse_rlimit_range(unit, filename, line, rvalue, rl, rlim_parse_usec); +} - if (streq(rvalue, "infinity")) - useconds = RLIM_INFINITY; - else { - usec_t t; - - r = parse_time(rvalue, &t, 1); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse resource value, ignoring: %s", rvalue); - return 0; - } - if (t == USEC_INFINITY) - useconds = RLIM_INFINITY; - else - useconds = (rlim_t) t; - } - - if (!*rl) { - *rl = new(struct rlimit, 1); - if (!*rl) - return log_oom(); - } - - (*rl)->rlim_cur = (*rl)->rlim_max = useconds; - return 0; -} #ifdef HAVE_SYSV_COMPAT int config_parse_sysv_priority(const char *unit, @@ -1305,38 +1344,28 @@ int config_parse_exec_mount_flags(const char *unit, void *data, void *userdata) { - ExecContext *c = data; - const char *word, *state; - size_t l; + unsigned long flags = 0; + ExecContext *c = data; assert(filename); assert(lvalue); assert(rvalue); assert(data); - FOREACH_WORD_SEPARATOR(word, l, rvalue, ", ", state) { - _cleanup_free_ char *t; - - t = strndup(word, l); - if (!t) - return log_oom(); - - if (streq(t, "shared")) - flags = MS_SHARED; - else if (streq(t, "slave")) - flags = MS_SLAVE; - else if (streq(t, "private")) - flags = MS_PRIVATE; - else { - log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse mount flag %s, ignoring: %s", t, rvalue); - return 0; - } + if (streq(rvalue, "shared")) + flags = MS_SHARED; + else if (streq(rvalue, "slave")) + flags = MS_SLAVE; + else if (streq(rvalue, "private")) + flags = MS_PRIVATE; + else { + log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse mount flag %s, ignoring.", rvalue); + return 0; } - if (!isempty(state)) - log_syntax(unit, LOG_ERR, filename, line, 0, "Trailing garbage, ignoring."); c->mount_flags = flags; + return 0; } @@ -2991,12 +3020,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 +3034,7 @@ int config_parse_tasks_max( return 0; } - c->tasks_max = u; + *tasks_max = u; return 0; } diff --git a/src/core/load-fragment.h b/src/core/load-fragment.h index 62300c10f9..a451fc164a 100644 --- a/src/core/load-fragment.h +++ b/src/core/load-fragment.h @@ -38,6 +38,7 @@ int config_parse_unit_path_printf(const char *unit, const char *filename, unsign int config_parse_unit_path_strv_printf(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_documentation(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_socket_listen(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_socket_protocol(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_socket_bind(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_exec_nice(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_exec_oom_score_adjust(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/locale-setup.c b/src/core/locale-setup.c index bd632131b9..4c8d920389 100644 --- a/src/core/locale-setup.c +++ b/src/core/locale-setup.c @@ -24,12 +24,12 @@ #include "env-util.h" #include "fileio.h" +#include "locale-setup.h" #include "locale-util.h" #include "string-util.h" #include "strv.h" #include "util.h" #include "virt.h" -#include "locale-setup.h" int locale_setup(char ***environment) { char **add; diff --git a/src/core/macros.systemd.in b/src/core/macros.systemd.in index bea6ef1da3..2cace3d3ba 100644 --- a/src/core/macros.systemd.in +++ b/src/core/macros.systemd.in @@ -1,4 +1,4 @@ -# -*- Mode: makefile; indent-tabs-mode: t -*- */ +# -*- Mode: rpm-spec; indent-tabs-mode: nil -*- */ # # This file is part of systemd. # @@ -39,17 +39,16 @@ Requires(postun): systemd \ %systemd_post() \ if [ $1 -eq 1 ] ; then \ # Initial installation \ - systemctl preset %{?*} >/dev/null 2>&1 || : \ + systemctl --no-reload preset %{?*} >/dev/null 2>&1 || : \ fi \ %{nil} -%systemd_user_post() %systemd_post --user --global %{?*} +%systemd_user_post() %{expand:%systemd_post \\--user \\--global %%{?*}} %systemd_preun() \ if [ $1 -eq 0 ] ; then \ # Package removal, not upgrade \ - systemctl --no-reload disable %{?*} > /dev/null 2>&1 || : \ - systemctl stop %{?*} > /dev/null 2>&1 || : \ + systemctl --no-reload disable --now %{?*} > /dev/null 2>&1 || : \ fi \ %{nil} @@ -60,14 +59,11 @@ if [ $1 -eq 0 ] ; then \ fi \ %{nil} -%systemd_postun() \ -systemctl daemon-reload >/dev/null 2>&1 || : \ -%{nil} +%systemd_postun() %{nil} %systemd_user_postun() %{nil} %systemd_postun_with_restart() \ -systemctl daemon-reload >/dev/null 2>&1 || : \ if [ $1 -ge 1 ] ; then \ # Package upgrade, not uninstall \ systemctl try-restart %{?*} >/dev/null 2>&1 || : \ diff --git a/src/core/main.c b/src/core/main.c index 33529c3e76..97f904b031 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -37,8 +37,8 @@ #include <valgrind/valgrind.h> #endif -#include "sd-daemon.h" #include "sd-bus.h" +#include "sd-daemon.h" #include "alloc-util.h" #include "architecture.h" @@ -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); diff --git a/src/core/manager.c b/src/core/manager.c index f695b8a66c..edff6758c5 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -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]; diff --git a/src/core/manager.h b/src/core/manager.h index bc3f02f872..f6903a5c34 100644 --- a/src/core/manager.h +++ b/src/core/manager.h @@ -21,12 +21,13 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include <libmount.h> #include <stdbool.h> #include <stdio.h> -#include <libmount.h> #include "sd-bus.h" #include "sd-event.h" + #include "cgroup-util.h" #include "fdset.h" #include "hashmap.h" @@ -260,6 +261,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]; diff --git a/src/core/mount-setup.c b/src/core/mount-setup.c index b2596d1cd1..2b8d590ed1 100644 --- a/src/core/mount-setup.c +++ b/src/core/mount-setup.c @@ -19,11 +19,11 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <sys/mount.h> #include <errno.h> +#include <ftw.h> #include <stdlib.h> +#include <sys/mount.h> #include <unistd.h> -#include <ftw.h> #include "alloc-util.h" #include "bus-util.h" diff --git a/src/core/mount.h b/src/core/mount.h index 83d14ae713..9f78aa9075 100644 --- a/src/core/mount.h +++ b/src/core/mount.h @@ -23,8 +23,8 @@ typedef struct Mount Mount; -#include "kill.h" #include "execute.h" +#include "kill.h" typedef enum MountExecCommand { MOUNT_EXEC_MOUNT, diff --git a/src/core/scope.c b/src/core/scope.c index 5f6527c155..1953af1f88 100644 --- a/src/core/scope.c +++ b/src/core/scope.c @@ -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, }; diff --git a/src/core/selinux-access.c b/src/core/selinux-access.c index 4bcdd27389..8856927c88 100644 --- a/src/core/selinux-access.c +++ b/src/core/selinux-access.c @@ -23,10 +23,10 @@ #ifdef HAVE_SELINUX -#include <stdio.h> #include <errno.h> -#include <selinux/selinux.h> #include <selinux/avc.h> +#include <selinux/selinux.h> +#include <stdio.h> #ifdef HAVE_AUDIT #include <libaudit.h> #endif diff --git a/src/core/selinux-access.h b/src/core/selinux-access.h index 30725521cb..3566ba529f 100644 --- a/src/core/selinux-access.h +++ b/src/core/selinux-access.h @@ -22,6 +22,7 @@ ***/ #include "sd-bus.h" + #include "bus-util.h" #include "manager.h" diff --git a/src/core/selinux-setup.c b/src/core/selinux-setup.c index d9b00fb95c..d4757e0853 100644 --- a/src/core/selinux-setup.c +++ b/src/core/selinux-setup.c @@ -29,10 +29,10 @@ #include "log.h" #include "macro.h" +#include "selinux-setup.h" #include "selinux-util.h" #include "string-util.h" #include "util.h" -#include "selinux-setup.h" #ifdef HAVE_SELINUX _printf_(2,3) diff --git a/src/core/service.h b/src/core/service.h index e765668247..d0faad88e0 100644 --- a/src/core/service.h +++ b/src/core/service.h @@ -24,10 +24,10 @@ typedef struct Service Service; typedef struct ServiceFDStore ServiceFDStore; +#include "exit-status.h" +#include "kill.h" #include "path.h" #include "ratelimit.h" -#include "kill.h" -#include "exit-status.h" typedef enum ServiceRestart { SERVICE_RESTART_NO, diff --git a/src/core/slice.c b/src/core/slice.c index 39dabae055..06ac6f8450 100644 --- a/src/core/slice.c +++ b/src/core/slice.c @@ -24,12 +24,12 @@ #include "alloc-util.h" #include "dbus-slice.h" #include "log.h" +#include "slice.h" #include "special.h" #include "string-util.h" #include "strv.h" #include "unit-name.h" #include "unit.h" -#include "slice.h" static const UnitActiveState state_translation_table[_SLICE_STATE_MAX] = { [SLICE_DEAD] = UNIT_INACTIVE, @@ -305,6 +305,7 @@ const UnitVTable slice_vtable = { .no_alias = true, .no_instances = true, + .can_transient = true, .load = slice_load, diff --git a/src/core/socket.c b/src/core/socket.c index 5b9e32ce9d..687675b24e 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -1266,6 +1266,19 @@ static int socket_open_fds(Socket *s) { know_label = true; } + /* Apply the socket protocol */ + switch(p->address.type) { + case SOCK_STREAM: + case SOCK_SEQPACKET: + if (p->socket->socket_protocol == IPPROTO_SCTP) + p->address.protocol = p->socket->socket_protocol; + break; + case SOCK_DGRAM: + if (p->socket->socket_protocol == IPPROTO_UDPLITE) + p->address.protocol = p->socket->socket_protocol; + break; + } + r = socket_address_listen( &p->address, SOCK_CLOEXEC|SOCK_NONBLOCK, diff --git a/src/core/socket.h b/src/core/socket.h index 94cda8a90d..08033287a6 100644 --- a/src/core/socket.h +++ b/src/core/socket.h @@ -23,9 +23,9 @@ typedef struct Socket Socket; -#include "socket-util.h" #include "mount.h" #include "service.h" +#include "socket-util.h" typedef enum SocketExecCommand { SOCKET_EXEC_START_PRE, @@ -120,6 +120,8 @@ struct Socket { bool remove_on_stop; bool writable; + int socket_protocol; + /* Socket options */ bool keep_alive; bool no_delay; diff --git a/src/core/swap.c b/src/core/swap.c index ee0838e676..b6e4372fc0 100644 --- a/src/core/swap.c +++ b/src/core/swap.c @@ -211,6 +211,8 @@ static int swap_add_device_links(Swap *s) { } static int swap_add_default_dependencies(Swap *s) { + int r; + assert(s); if (!UNIT(s)->default_dependencies) @@ -222,6 +224,12 @@ static int swap_add_default_dependencies(Swap *s) { if (detect_container() > 0) return 0; + /* swap units generated for the swap dev links are missing the + * ordering dep against the swap target. */ + r = unit_add_dependency_by_name(UNIT(s), UNIT_BEFORE, SPECIAL_SWAP_TARGET, NULL, true); + if (r < 0) + return r; + return unit_add_two_dependencies_by_name(UNIT(s), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true); } diff --git a/src/core/system.conf b/src/core/system.conf index 50668e12c4..e2ded27333 100644 --- a/src/core/system.conf +++ b/src/core/system.conf @@ -40,7 +40,8 @@ #DefaultCPUAccounting=no #DefaultBlockIOAccounting=no #DefaultMemoryAccounting=no -#DefaultTasksAccounting=no +#DefaultTasksAccounting=yes +#DefaultTasksMax=512 #DefaultLimitCPU= #DefaultLimitFSIZE= #DefaultLimitDATA= diff --git a/src/core/timer.c b/src/core/timer.c index 51b1d875be..6b0f8e8616 100644 --- a/src/core/timer.c +++ b/src/core/timer.c @@ -27,6 +27,7 @@ #include "dbus-timer.h" #include "fs-util.h" #include "parse-util.h" +#include "random-util.h" #include "special.h" #include "string-table.h" #include "string-util.h" @@ -55,6 +56,7 @@ static void timer_init(Unit *u) { t->next_elapse_monotonic_or_boottime = USEC_INFINITY; t->next_elapse_realtime = USEC_INFINITY; t->accuracy_usec = u->manager->default_timer_accuracy_usec; + t->remain_after_elapse = true; } void timer_free_values(Timer *t) { @@ -217,13 +219,15 @@ static void timer_dump(Unit *u, FILE *f, const char *prefix) { "%sUnit: %s\n" "%sPersistent: %s\n" "%sWakeSystem: %s\n" - "%sAccuracy: %s\n", + "%sAccuracy: %s\n" + "%sRemainAfterElapse: %s\n", prefix, timer_state_to_string(t->state), prefix, timer_result_to_string(t->result), prefix, trigger ? trigger->id : "n/a", prefix, yes_no(t->persistent), prefix, yes_no(t->wake_system), - prefix, format_timespan(buf, sizeof(buf), t->accuracy_usec, 1)); + prefix, format_timespan(buf, sizeof(buf), t->accuracy_usec, 1), + prefix, yes_no(t->remain_after_elapse)); LIST_FOREACH(value, v, t->values) { @@ -275,13 +279,13 @@ static int timer_coldplug(Unit *u) { assert(t); assert(t->state == TIMER_DEAD); - if (t->deserialized_state != t->state) { + if (t->deserialized_state == t->state) + return 0; - if (t->deserialized_state == TIMER_WAITING) - timer_enter_waiting(t, false); - else - timer_set_state(t, t->deserialized_state); - } + if (t->deserialized_state == TIMER_WAITING) + timer_enter_waiting(t, false); + else + timer_set_state(t, t->deserialized_state); return 0; } @@ -295,6 +299,23 @@ static void timer_enter_dead(Timer *t, TimerResult f) { timer_set_state(t, t->result != TIMER_SUCCESS ? TIMER_FAILED : TIMER_DEAD); } +static void timer_enter_elapsed(Timer *t, bool leave_around) { + assert(t); + + /* If a unit is marked with RemainAfterElapse=yes we leave it + * around even after it elapsed once, so that starting it + * later again does not necessarily mean immediate + * retriggering. We unconditionally leave units with + * TIMER_UNIT_ACTIVE or TIMER_UNIT_INACTIVE triggers around, + * since they might be restarted automatically at any time + * later on. */ + + if (t->remain_after_elapse || leave_around) + timer_set_state(t, TIMER_ELAPSED); + else + timer_enter_dead(t, TIMER_SUCCESS); +} + static usec_t monotonic_to_boottime(usec_t t) { usec_t a, b; @@ -310,10 +331,33 @@ static usec_t monotonic_to_boottime(usec_t t) { return 0; } +static void add_random(Timer *t, usec_t *v) { + char s[FORMAT_TIMESPAN_MAX]; + usec_t add; + + assert(t); + assert(*v); + + if (t->random_usec == 0) + return; + if (*v == USEC_INFINITY) + return; + + add = random_u64() % t->random_usec; + + if (*v + add < *v) /* overflow */ + *v = (usec_t) -2; /* Highest possible value, that is not USEC_INFINITY */ + else + *v += add; + + log_unit_info(UNIT(t), "Adding %s random time.", format_timespan(s, sizeof(s), add, 0)); +} + static void timer_enter_waiting(Timer *t, bool initial) { bool found_monotonic = false, found_realtime = false; usec_t ts_realtime, ts_monotonic; usec_t base = 0; + bool leave_around = false; TimerValue *v; int r; @@ -374,7 +418,7 @@ static void timer_enter_waiting(Timer *t, bool initial) { break; case TIMER_UNIT_ACTIVE: - + leave_around = true; base = UNIT_TRIGGER(UNIT(t))->inactive_exit_timestamp.monotonic; if (base <= 0) @@ -386,7 +430,7 @@ static void timer_enter_waiting(Timer *t, bool initial) { break; case TIMER_UNIT_INACTIVE: - + leave_around = true; base = UNIT_TRIGGER(UNIT(t))->inactive_enter_timestamp.monotonic; if (base <= 0) @@ -423,14 +467,18 @@ static void timer_enter_waiting(Timer *t, bool initial) { if (!found_monotonic && !found_realtime) { log_unit_debug(UNIT(t), "Timer is elapsed."); - timer_set_state(t, TIMER_ELAPSED); + timer_enter_elapsed(t, leave_around); return; } if (found_monotonic) { char buf[FORMAT_TIMESPAN_MAX]; + usec_t left; - log_unit_debug(UNIT(t), "Monotonic timer elapses in %s.", format_timespan(buf, sizeof(buf), t->next_elapse_monotonic_or_boottime > ts_monotonic ? t->next_elapse_monotonic_or_boottime - ts_monotonic : 0, 0)); + add_random(t, &t->next_elapse_monotonic_or_boottime); + + left = t->next_elapse_monotonic_or_boottime > ts_monotonic ? t->next_elapse_monotonic_or_boottime - ts_monotonic : 0; + log_unit_debug(UNIT(t), "Monotonic timer elapses in %s.", format_timespan(buf, sizeof(buf), left, 0)); if (t->monotonic_event_source) { r = sd_event_source_set_time(t->monotonic_event_source, t->next_elapse_monotonic_or_boottime); @@ -463,6 +511,9 @@ static void timer_enter_waiting(Timer *t, bool initial) { if (found_realtime) { char buf[FORMAT_TIMESTAMP_MAX]; + + add_random(t, &t->next_elapse_realtime); + log_unit_debug(UNIT(t), "Realtime timer elapses at %s.", format_timestamp(buf, sizeof(buf), t->next_elapse_realtime)); if (t->realtime_event_source) { diff --git a/src/core/timer.h b/src/core/timer.h index ac5af6a93c..0599f07818 100644 --- a/src/core/timer.h +++ b/src/core/timer.h @@ -58,6 +58,7 @@ struct Timer { Unit meta; usec_t accuracy_usec; + usec_t random_usec; LIST_HEAD(TimerValue, values); usec_t next_elapse_realtime; @@ -73,6 +74,7 @@ struct Timer { bool persistent; bool wake_system; + bool remain_after_elapse; char *stamp_path; }; diff --git a/src/core/transaction.c b/src/core/transaction.c index cf37b5eb75..15e79d00b3 100644 --- a/src/core/transaction.c +++ b/src/core/transaction.c @@ -19,8 +19,8 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <unistd.h> #include <fcntl.h> +#include <unistd.h> #include "alloc-util.h" #include "bus-common-errors.h" diff --git a/src/core/transaction.h b/src/core/transaction.h index f7aa3df085..5c4a13edab 100644 --- a/src/core/transaction.h +++ b/src/core/transaction.h @@ -23,10 +23,10 @@ typedef struct Transaction Transaction; -#include "unit.h" -#include "manager.h" -#include "job.h" #include "hashmap.h" +#include "job.h" +#include "manager.h" +#include "unit.h" struct Transaction { /* Jobs to be added */ diff --git a/src/core/triggers.systemd.in b/src/core/triggers.systemd.in new file mode 100644 index 0000000000..9e18a39a67 --- /dev/null +++ b/src/core/triggers.systemd.in @@ -0,0 +1,64 @@ +# -*- Mode: rpm-spec; indent-tabs-mode: nil -*- */ +# +# This file is part of systemd. +# +# Copyright 2015 Zbigniew Jędrzejewski-Szmek +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see <http://www.gnu.org/licenses/>. + +# The contents of this are an example to be copied into systemd.spec. + +%transfiletriggerin -P 900900 -p <lua> -- @systemunitdir@ /etc/systemd/system +-- This script will run after any package is initially installed or +-- upgraded. We care about the case where a package is initially +-- installed, because other cases are covered by the *un scriptlets, +-- so sometimes we will reload needlessly. + +pid = posix.fork() +if pid == 0 then + assert(posix.exec("%{_bindir}/systemctl", "daemon-reload")) +elseif pid > 0 then + posix.wait(pid) +end + +%transfiletriggerun -p <lua> -- @systemunitdir@ /etc/systemd/system +-- On removal, we need to run daemon-reload after any units have been +-- removed. %transfiletriggerpostun would be ideal, but it does not get +-- executed for some reason. +-- On upgrade, we need to run daemon-reload after any new unit files +-- have been installed, but before %postun scripts in packages get +-- executed. %transfiletriggerun gets the right list of files +-- but it is invoked too early (before changes happen). +-- %filetriggerpostun happens at the right time, but it fires for +-- every package. +-- To execute the reload at the right time, we create a state +-- file in %transfiletriggerun and execute the daemon-reload in +-- the first %filetriggerpostun. + +posix.mkdir("%{_localstatedir}/lib") +posix.mkdir("%{_localstatedir}/lib/rpm-state") +posix.mkdir("%{_localstatedir}/lib/rpm-state/systemd") +io.open("%{_localstatedir}/lib/rpm-state/systemd/needs-reload", "w") + +%filetriggerpostun -P 1000100 -p <lua> -- @systemunitdir@ /etc/systemd/system +if posix.access("%{_localstatedir}/lib/rpm-state/systemd/needs-reload") then + posix.unlink("%{_localstatedir}/lib/rpm-state/systemd/needs-reload") + posix.rmdir("%{_localstatedir}/lib/rpm-state/systemd") + pid = posix.fork() + if pid == 0 then + assert(posix.exec("%{_bindir}/systemctl", "daemon-reload")) + elseif pid > 0 then + posix.wait(pid) + end +end diff --git a/src/core/unit.c b/src/core/unit.c index f553f24829..0a02e38aa8 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -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; @@ -1347,12 +1347,18 @@ static bool unit_assert_test(Unit *u) { return u->assert_result; } +void unit_status_printf(Unit *u, const char *status, const char *unit_status_msg_format) { + DISABLE_WARNING_FORMAT_NONLITERAL; + manager_status_printf(u->manager, STATUS_TYPE_NORMAL, status, unit_status_msg_format, unit_description(u)); + REENABLE_WARNING; +} + _pure_ static const char* unit_get_status_message_format(Unit *u, JobType t) { const char *format; const UnitStatusMessageFormats *format_table; assert(u); - assert(t == JOB_START || t == JOB_STOP || t == JOB_RELOAD); + assert(IN_SET(t, JOB_START, JOB_STOP, JOB_RELOAD)); if (t != JOB_RELOAD) { format_table = &UNIT_VTABLE(u)->status_message_formats; @@ -1377,6 +1383,10 @@ static void unit_status_print_starting_stopping(Unit *u, JobType t) { assert(u); + /* Reload status messages have traditionally not been printed to console. */ + if (!IN_SET(t, JOB_START, JOB_STOP)) + return; + format = unit_get_status_message_format(u, t); DISABLE_WARNING_FORMAT_NONLITERAL; @@ -1391,7 +1401,7 @@ static void unit_status_log_starting_stopping_reloading(Unit *u, JobType t) { assert(u); - if (t != JOB_START && t != JOB_STOP && t != JOB_RELOAD) + if (!IN_SET(t, JOB_START, JOB_STOP, JOB_RELOAD)) return; if (log_on_console()) @@ -1423,12 +1433,12 @@ static void unit_status_log_starting_stopping_reloading(Unit *u, JobType t) { } void unit_status_emit_starting_stopping_reloading(Unit *u, JobType t) { + assert(u); + assert(t >= 0); + assert(t < _JOB_TYPE_MAX); unit_status_log_starting_stopping_reloading(u, t); - - /* Reload status messages have traditionally not been printed to console. */ - if (t != JOB_RELOAD) - unit_status_print_starting_stopping(u, t); + unit_status_print_starting_stopping(u, t); } /* Errors: @@ -2896,13 +2906,6 @@ int unit_coldplug(Unit *u) { return 0; } -void unit_status_printf(Unit *u, const char *status, const char *unit_status_msg_format) { - DISABLE_WARNING_FORMAT_NONLITERAL; - manager_status_printf(u->manager, STATUS_TYPE_NORMAL, - status, unit_status_msg_format, unit_description(u)); - REENABLE_WARNING; -} - bool unit_need_daemon_reload(Unit *u) { _cleanup_strv_free_ char **t = NULL; char **path; @@ -3428,7 +3431,15 @@ int unit_make_transient(Unit *u) { u->load_state = UNIT_STUB; u->load_error = 0; u->transient = true; + u->fragment_path = mfree(u->fragment_path); + u->source_path = mfree(u->source_path); + u->dropin_paths = strv_free(u->dropin_paths); + u->fragment_mtime = u->source_mtime = u->dropin_mtime = 0; + + unit_add_to_dbus_queue(u); + unit_add_to_gc_queue(u); + unit_add_to_load_queue(u); return 0; } @@ -3704,3 +3715,21 @@ int unit_fail_if_symlink(Unit *u, const char* where) { return -ELOOP; } + +bool unit_is_pristine(Unit *u) { + assert(u); + + /* Check if the unit already exists or is already around, + * 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. */ + + return !(!IN_SET(u->load_state, UNIT_NOT_FOUND, UNIT_LOADED) || + u->fragment_path || + u->source_path || + !strv_isempty(u->dropin_paths) || + u->job || + u->merged_into); +} diff --git a/src/core/unit.h b/src/core/unit.h index 14e3072146..1681bbf53b 100644 --- a/src/core/unit.h +++ b/src/core/unit.h @@ -30,11 +30,11 @@ typedef struct UnitVTable UnitVTable; typedef struct UnitRef UnitRef; typedef struct UnitStatusMessageFormats UnitStatusMessageFormats; -#include "list.h" #include "condition.h" +#include "failure-action.h" #include "install.h" +#include "list.h" #include "unit-name.h" -#include "failure-action.h" typedef enum KillOperation { KILL_TERMINATE, @@ -242,16 +242,16 @@ typedef enum UnitSetPropertiesMode { UNIT_PERSISTENT = 2, } UnitSetPropertiesMode; -#include "socket.h" +#include "automount.h" #include "busname.h" -#include "target.h" #include "device.h" -#include "automount.h" -#include "swap.h" -#include "timer.h" -#include "slice.h" #include "path.h" #include "scope.h" +#include "slice.h" +#include "socket.h" +#include "swap.h" +#include "target.h" +#include "timer.h" struct UnitVTable { /* How much memory does an object of this unit type need */ @@ -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; }; @@ -589,6 +586,8 @@ int unit_require_mounts_for(Unit *u, const char *path); bool unit_type_supported(UnitType t); +bool unit_is_pristine(Unit *u); + static inline bool unit_supported(Unit *u) { return unit_type_supported(u->type); } |