From: Lennart Poettering Date: Mon, 26 Jun 2017 15:40:08 +0000 (+0200) Subject: core: make IOSchedulingClass= and IOSchedulingPriority= settable for transient units X-Git-Tag: v234~83^2~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=7f452159b8f7ad83e6f9082b6fbb6d838b615d94;p=platform%2Fupstream%2Fsystemd.git core: make IOSchedulingClass= and IOSchedulingPriority= settable for transient units This patch is a bit more complex thant I hoped. In particular the single IOScheduling= property exposed on the bus is split up into IOSchedulingClass= and IOSchedulingPriority= (though compat is retained). Otherwise the asymmetry between setting props and getting them is a bit too nasty. Fixes #5613 --- diff --git a/src/basic/process-util.c b/src/basic/process-util.c index a21dc35..b80caca 100644 --- a/src/basic/process-util.c +++ b/src/basic/process-util.c @@ -905,6 +905,23 @@ int pid_compare_func(const void *a, const void *b) { return 0; } +int ioprio_parse_priority(const char *s, int *ret) { + int i, r; + + assert(s); + assert(ret); + + r = safe_atoi(s, &i); + if (r < 0) + return r; + + if (!ioprio_priority_is_valid(i)) + return -EINVAL; + + *ret = i; + return 0; +} + static const char *const ioprio_class_table[] = { [IOPRIO_CLASS_NONE] = "none", [IOPRIO_CLASS_RT] = "realtime", diff --git a/src/basic/process-util.h b/src/basic/process-util.h index d378901..28d8d74 100644 --- a/src/basic/process-util.h +++ b/src/basic/process-util.h @@ -25,10 +25,11 @@ #include #include #include -#include #include +#include #include "format-util.h" +#include "ioprio.h" #include "macro.h" #define procfs_file_alloca(pid, field) \ @@ -108,3 +109,13 @@ int pid_compare_func(const void *a, const void *b); static inline bool nice_is_valid(int n) { return n >= PRIO_MIN && n < PRIO_MAX; } + +static inline bool ioprio_class_is_valid(int i) { + return IN_SET(i, IOPRIO_CLASS_NONE, IOPRIO_CLASS_RT, IOPRIO_CLASS_BE, IOPRIO_CLASS_IDLE); +} + +static inline bool ioprio_priority_is_valid(int i) { + return i >= 0 && i < IOPRIO_BE_NR; +} + +int ioprio_parse_priority(const char *s, int *ret); diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c index 7e165be..8f9d717 100644 --- a/src/core/dbus-execute.c +++ b/src/core/dbus-execute.c @@ -160,21 +160,51 @@ static int property_get_ioprio( ExecContext *c = userdata; - int32_t n; assert(bus); assert(reply); assert(c); - if (c->ioprio_set) - n = c->ioprio; - else { - n = ioprio_get(IOPRIO_WHO_PROCESS, 0); - if (n < 0) - n = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 4); - } + return sd_bus_message_append(reply, "i", exec_context_get_effective_ioprio(c)); +} - return sd_bus_message_append(reply, "i", n); +static int property_get_ioprio_class( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + + ExecContext *c = userdata; + + assert(bus); + assert(reply); + assert(c); + + return sd_bus_message_append(reply, "i", IOPRIO_PRIO_CLASS(exec_context_get_effective_ioprio(c))); +} + + +static int property_get_ioprio_priority( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + + ExecContext *c = userdata; + + assert(bus); + assert(reply); + assert(c); + + return sd_bus_message_append(reply, "i", IOPRIO_PRIO_DATA(exec_context_get_effective_ioprio(c))); } static int property_get_cpu_sched_policy( @@ -762,7 +792,8 @@ const sd_bus_vtable bus_exec_vtable[] = { SD_BUS_PROPERTY("RootImage", "s", NULL, offsetof(ExecContext, root_image), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("OOMScoreAdjust", "i", property_get_oom_score_adjust, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Nice", "i", property_get_nice, 0, SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("IOScheduling", "i", property_get_ioprio, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("IOSchedulingClass", "i", property_get_ioprio_class, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("IOSchedulingPriority", "i", property_get_ioprio_priority, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("CPUSchedulingPolicy", "i", property_get_cpu_sched_policy, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("CPUSchedulingPriority", "i", property_get_cpu_sched_priority, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("CPUAffinity", "ay", property_get_cpu_affinity, 0, SD_BUS_VTABLE_PROPERTY_CONST), @@ -784,7 +815,6 @@ const sd_bus_vtable bus_exec_vtable[] = { SD_BUS_PROPERTY("SyslogLevelPrefix", "b", bus_property_get_bool, offsetof(ExecContext, syslog_level_prefix), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("SyslogLevel", "i", property_get_syslog_level, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("SyslogFacility", "i", property_get_syslog_facility, 0, SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("Capabilities", "s", property_get_empty_string, 0, SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), SD_BUS_PROPERTY("SecureBits", "i", bus_property_get_int, offsetof(ExecContext, secure_bits), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("CapabilityBoundingSet", "t", property_get_capability_bounding_set, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("AmbientCapabilities", "t", property_get_ambient_capabilities, 0, SD_BUS_VTABLE_PROPERTY_CONST), @@ -794,9 +824,6 @@ const sd_bus_vtable bus_exec_vtable[] = { SD_BUS_PROPERTY("RemoveIPC", "b", bus_property_get_bool, offsetof(ExecContext, remove_ipc), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("SupplementaryGroups", "as", NULL, offsetof(ExecContext, supplementary_groups), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("PAMName", "s", NULL, offsetof(ExecContext, pam_name), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("ReadWriteDirectories", "as", NULL, offsetof(ExecContext, read_write_paths), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), - SD_BUS_PROPERTY("ReadOnlyDirectories", "as", NULL, offsetof(ExecContext, read_only_paths), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), - SD_BUS_PROPERTY("InaccessibleDirectories", "as", NULL, offsetof(ExecContext, inaccessible_paths), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), SD_BUS_PROPERTY("ReadWritePaths", "as", NULL, offsetof(ExecContext, read_write_paths), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("ReadOnlyPaths", "as", NULL, offsetof(ExecContext, read_only_paths), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("InaccessiblePaths", "as", NULL, offsetof(ExecContext, inaccessible_paths), SD_BUS_VTABLE_PROPERTY_CONST), @@ -831,6 +858,14 @@ const sd_bus_vtable bus_exec_vtable[] = { SD_BUS_PROPERTY("BindPaths", "a(ssbt)", property_get_bind_paths, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("BindReadOnlyPaths", "a(ssbt)", property_get_bind_paths, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("MountAPIVFS", "b", bus_property_get_bool, offsetof(ExecContext, mount_apivfs), SD_BUS_VTABLE_PROPERTY_CONST), + + /* Obsolete/redundant properties: */ + SD_BUS_PROPERTY("Capabilities", "s", property_get_empty_string, 0, SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), + SD_BUS_PROPERTY("ReadWriteDirectories", "as", NULL, offsetof(ExecContext, read_write_paths), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), + SD_BUS_PROPERTY("ReadOnlyDirectories", "as", NULL, offsetof(ExecContext, read_only_paths), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), + SD_BUS_PROPERTY("InaccessibleDirectories", "as", NULL, offsetof(ExecContext, inaccessible_paths), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), + SD_BUS_PROPERTY("IOScheduling", "i", property_get_ioprio, 0, SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), + SD_BUS_VTABLE_END }; @@ -1050,6 +1085,50 @@ int bus_exec_context_set_transient_property( return 1; + } else if (streq(name, "IOSchedulingClass")) { + int32_t q; + + r = sd_bus_message_read(message, "i", &q); + if (r < 0) + return r; + + if (!ioprio_class_is_valid(q)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid IO scheduling class: %i", q); + + if (mode != UNIT_CHECK) { + _cleanup_free_ char *s = NULL; + + r = ioprio_class_to_string_alloc(q, &s); + if (r < 0) + return r; + + c->ioprio = IOPRIO_PRIO_VALUE(q, IOPRIO_PRIO_DATA(c->ioprio)); + c->ioprio_set = true; + + unit_write_drop_in_private_format(u, mode, name, "IOSchedulingClass=%s", s); + } + + return 1; + + } else if (streq(name, "IOSchedulingPriority")) { + int32_t p; + + r = sd_bus_message_read(message, "i", &p); + if (r < 0) + return r; + + if (!ioprio_priority_is_valid(p)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid IO scheduling priority: %i", p); + + if (mode != UNIT_CHECK) { + c->ioprio = IOPRIO_PRIO_VALUE(IOPRIO_PRIO_CLASS(c->ioprio), p); + c->ioprio_set = true; + + unit_write_drop_in_private_format(u, mode, name, "IOSchedulingPriority=%i", p); + } + + return 1; + } else if (STR_IN_SET(name, "TTYPath", "RootDirectory", "RootImage")) { const char *s; diff --git a/src/core/execute.c b/src/core/execute.c index 340939d..d72e5bf 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -3701,6 +3701,21 @@ bool exec_context_maintains_privileges(ExecContext *c) { return false; } +int exec_context_get_effective_ioprio(ExecContext *c) { + int p; + + assert(c); + + if (c->ioprio_set) + return c->ioprio; + + p = ioprio_get(IOPRIO_WHO_PROCESS, 0); + if (p < 0) + return IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 4); + + return p; +} + void exec_status_start(ExecStatus *s, pid_t pid) { assert(s); diff --git a/src/core/execute.h b/src/core/execute.h index 1363193..9f07aa4 100644 --- a/src/core/execute.h +++ b/src/core/execute.h @@ -307,6 +307,8 @@ const char* exec_context_fdname(const ExecContext *c, int fd_index); bool exec_context_may_touch_console(ExecContext *c); bool exec_context_maintains_privileges(ExecContext *c); +int exec_context_get_effective_ioprio(ExecContext *c); + void exec_status_start(ExecStatus *s, pid_t pid); void exec_status_exit(ExecStatus *s, ExecContext *context, pid_t pid, int code, int status); void exec_status_dump(ExecStatus *s, FILE *f, const char *prefix); diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c index af3c6a4..8d7153f 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -940,8 +940,8 @@ int config_parse_exec_io_priority(const char *unit, assert(rvalue); assert(data); - r = safe_atoi(rvalue, &i); - if (r < 0 || i < 0 || i >= IOPRIO_BE_NR) { + r = ioprio_parse_priority(rvalue, &i); + if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse IO priority, ignoring: %s", rvalue); return 0; } diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c index 7b0bc82..e4204fd 100644 --- a/src/shared/bus-unit-util.c +++ b/src/shared/bus-unit-util.c @@ -389,6 +389,24 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen r = sd_bus_message_append(m, "v", "i", (int32_t) n); + } else if (streq(field, "IOSchedulingClass")) { + int c; + + c = ioprio_class_from_string(eq); + if (c < 0) + return log_error_errno(r, "Failed to parse IO scheduling class: %s", eq); + + r = sd_bus_message_append(m, "v", "i", (int32_t) c); + + } else if (streq(field, "IOSchedulingPriority")) { + int q; + + r = ioprio_parse_priority(eq, &q); + if (r < 0) + return log_error_errno(r, "Failed to parse IO scheduling priority: %s", eq); + + r = sd_bus_message_append(m, "v", "i", (int32_t) q); + } else if (STR_IN_SET(field, "Environment", "PassEnvironment")) { const char *p;