From e5ac9d202b9a8189a34cecf2529afd72bc1ff024 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Wed, 26 Sep 2018 11:17:36 +0200 Subject: shared/sleep-config: add switches to kill specific sleep modes /etc/systemd/sleep.conf gains four new switches: AllowSuspend=, AllowHibernation=, AllowSuspendThenHibernate=, AllowHybridSleep=. Disabling specific modes was already possible by masking suspend.target, hibernate.target, suspend-then-hibernate.target, or hybrid-sleep.target. But this is not convenient for distributions, which want to set some defaults based on what they want to support. Having those available as configuration makes it easy to put a config file in /usr/lib/systemd/sleep.conf.d/ that overrides the defaults and gives instructions how to undo that override. (cherry picked from commit e8f1d00d695f491654d50e57c82623288d3bcbeb) --- src/shared/sleep-config.c | 77 +++++++++++++++++++++++++++++++++-------------- src/shared/sleep-config.h | 2 +- src/sleep/sleep.c | 15 +++++---- 3 files changed, 65 insertions(+), 29 deletions(-) diff --git a/src/shared/sleep-config.c b/src/shared/sleep-config.c index 0d80bf313..74ed2bd8e 100644 --- a/src/shared/sleep-config.c +++ b/src/shared/sleep-config.c @@ -29,8 +29,10 @@ #include "strv.h" #if 0 /// UNNEEDED by elogind -int parse_sleep_config(const char *verb, char ***_modes, char ***_states, usec_t *_delay) { - +int parse_sleep_config(const char *verb, bool *ret_allow, char ***ret_modes, char ***ret_states, usec_t *ret_delay) { + int allow_suspend = -1, allow_hibernate = -1, + allow_s2h = -1, allow_hybrid_sleep = -1; + bool allow; _cleanup_strv_free_ char **suspend_mode = NULL, **suspend_state = NULL, **hibernate_mode = NULL, **hibernate_state = NULL, @@ -39,13 +41,19 @@ int parse_sleep_config(const char *verb, char ***_modes, char ***_states, usec_t usec_t delay = 180 * USEC_PER_MINUTE; const ConfigTableItem items[] = { - { "Sleep", "SuspendMode", config_parse_strv, 0, &suspend_mode }, - { "Sleep", "SuspendState", config_parse_strv, 0, &suspend_state }, - { "Sleep", "HibernateMode", config_parse_strv, 0, &hibernate_mode }, - { "Sleep", "HibernateState", config_parse_strv, 0, &hibernate_state }, - { "Sleep", "HybridSleepMode", config_parse_strv, 0, &hybrid_mode }, - { "Sleep", "HybridSleepState", config_parse_strv, 0, &hybrid_state }, - { "Sleep", "HibernateDelaySec", config_parse_sec, 0, &delay}, + { "Sleep", "AllowSuspend", config_parse_tristate, 0, &allow_suspend }, + { "Sleep", "AllowHibernation", config_parse_tristate, 0, &allow_hibernate }, + { "Sleep", "AllowSuspendThenHibernate", config_parse_tristate, 0, &allow_s2h }, + { "Sleep", "AllowHybridSleep", config_parse_tristate, 0, &allow_hybrid_sleep }, + + { "Sleep", "SuspendMode", config_parse_strv, 0, &suspend_mode }, + { "Sleep", "SuspendState", config_parse_strv, 0, &suspend_state }, + { "Sleep", "HibernateMode", config_parse_strv, 0, &hibernate_mode }, + { "Sleep", "HibernateState", config_parse_strv, 0, &hibernate_state }, + { "Sleep", "HybridSleepMode", config_parse_strv, 0, &hybrid_mode }, + { "Sleep", "HybridSleepState", config_parse_strv, 0, &hybrid_state }, + + { "Sleep", "HibernateDelaySec", config_parse_sec, 0, &delay}, {} }; @@ -55,6 +63,8 @@ int parse_sleep_config(const char *verb, char ***_modes, char ***_states, usec_t CONFIG_PARSE_WARN, NULL); if (streq(verb, "suspend")) { + allow = allow_suspend != 0; + /* empty by default */ modes = TAKE_PTR(suspend_mode); @@ -64,6 +74,8 @@ int parse_sleep_config(const char *verb, char ***_modes, char ***_states, usec_t states = strv_new("mem", "standby", "freeze", NULL); } else if (streq(verb, "hibernate")) { + allow = allow_hibernate != 0; + if (hibernate_mode) modes = TAKE_PTR(hibernate_mode); else @@ -75,6 +87,9 @@ int parse_sleep_config(const char *verb, char ***_modes, char ***_states, usec_t states = strv_new("disk", NULL); } else if (streq(verb, "hybrid-sleep")) { + allow = allow_hybrid_sleep > 0 || + (allow_suspend != 0 && allow_hibernate != 0); + if (hybrid_mode) modes = TAKE_PTR(hybrid_mode); else @@ -85,21 +100,26 @@ int parse_sleep_config(const char *verb, char ***_modes, char ***_states, usec_t else states = strv_new("disk", NULL); - } else if (streq(verb, "suspend-then-hibernate")) + } else if (streq(verb, "suspend-then-hibernate")) { + allow = allow_s2h > 0 || + (allow_suspend != 0 && allow_hibernate != 0); + modes = states = NULL; - else + } else assert_not_reached("what verb"); if ((!modes && STR_IN_SET(verb, "hibernate", "hybrid-sleep")) || (!states && !streq(verb, "suspend-then-hibernate"))) return log_oom(); - if (_modes) - *_modes = TAKE_PTR(modes); - if (_states) - *_states = TAKE_PTR(states); - if (_delay) - *_delay = delay; + if (ret_allow) + *ret_allow = allow; + if (ret_modes) + *ret_modes = TAKE_PTR(modes); + if (ret_states) + *ret_states = TAKE_PTR(states); + if (ret_delay) + *ret_delay = delay; return 0; } @@ -444,6 +464,8 @@ int read_fiemap(int fd, struct fiemap **ret) { return 0; } +static int can_sleep_internal(const char *verb, bool check_allowed); + #if 0 /// elogind has to ask the manager for some stuff static bool can_s2h(void) { #else @@ -461,7 +483,7 @@ static bool can_s2h(Manager *m) { FOREACH_STRING(p, "suspend", "hibernate") { #if 0 /// elogind must transport a pointer to its managers instance - r = can_sleep(p); + r = can_sleep_internal(p, false); if (IN_SET(r, 0, -ENOSPC, -EADV)) { #else r = can_sleep(m, p); @@ -478,7 +500,8 @@ static bool can_s2h(Manager *m) { #if 0 /// elogind has to ask the manager for some stuff -int can_sleep(const char *verb) { +static int can_sleep_internal(const char *verb, bool check_allowed) { + bool allow; _cleanup_strv_free_ char **modes = NULL, **states = NULL; int r; #else @@ -495,19 +518,25 @@ int can_sleep(Manager *m, const char *verb) { assert(STR_IN_SET(verb, "suspend", "hibernate", "hybrid-sleep", "suspend-then-hibernate")); - if (streq(verb, "suspend-then-hibernate")) #if 0 /// elogind must transport a pointer to its managers instance - return can_s2h(); #else return can_s2h(m); #endif // 0 #if 0 /// already parsed by elogind config - r = parse_sleep_config(verb, &modes, &states, NULL); + r = parse_sleep_config(verb, &allow, &modes, &states, NULL); if (r < 0) return false; #endif // 0 + if (check_allowed && !allow) { + log_debug("Sleep mode \"%s\" is disabled by configuration.", verb); + return false; + } + + if (streq(verb, "suspend-then-hibernate")) + return can_s2h(); + if (!can_sleep_state(states) || !can_sleep_disk(modes)) return false; @@ -524,3 +553,7 @@ int can_sleep(Manager *m, const char *verb) { return true; } + +int can_sleep(const char *verb) { + return can_sleep_internal(verb, true); +} diff --git a/src/shared/sleep-config.h b/src/shared/sleep-config.h index b29165143..e3eceb9b0 100644 --- a/src/shared/sleep-config.h +++ b/src/shared/sleep-config.h @@ -6,8 +6,8 @@ int read_fiemap(int fd, struct fiemap **ret); #if 0 /// UNNEEDED by elogind -int parse_sleep_config(const char *verb, char ***modes, char ***states, usec_t *delay); #endif // 0 +int parse_sleep_config(const char *verb, bool *ret_allow, char ***ret_modes, char ***ret_states, usec_t *ret_delay); int find_hibernate_location(char **device, char **type, size_t *size, size_t *used); #if 0 /// elogind has to transport its manager instance diff --git a/src/sleep/sleep.c b/src/sleep/sleep.c index f104e5dac..890dae7ab 100644 --- a/src/sleep/sleep.c +++ b/src/sleep/sleep.c @@ -149,7 +149,6 @@ static int execute(Manager *m, const char *verb) { streq(arg_verb, "hibernate") ? m->hibernate_state : m->hybrid_sleep_state; #endif // 0 - char *arguments[] = { NULL, (char*) "pre", @@ -242,13 +241,11 @@ static int execute_s2h(Manager *m) { int r; #if 0 /// Already parsed by elogind config - r = parse_sleep_config("suspend", &suspend_modes, &suspend_states, - NULL); + r = parse_sleep_config("suspend", NULL, &suspend_modes, &suspend_states, NULL); if (r < 0) return r; - r = parse_sleep_config("hibernate", &hibernate_modes, - &hibernate_states, NULL); + r = parse_sleep_config("hibernate", NULL, &hibernate_modes, &hibernate_states, NULL); if (r < 0) return r; #endif // 0 @@ -363,6 +360,7 @@ static int parse_argv(int argc, char *argv[]) { } int main(int argc, char *argv[]) { + bool allow; _cleanup_strv_free_ char **modes = NULL, **states = NULL; usec_t delay = 0; int r; @@ -375,10 +373,15 @@ int main(int argc, char *argv[]) { if (r <= 0) goto finish; - r = parse_sleep_config(arg_verb, &modes, &states, &delay); + r = parse_sleep_config(arg_verb, &allow, &modes, &states, &delay); if (r < 0) goto finish; + if (!allow) { + log_error("Sleep mode \"%s\" is disabled by configuration, refusing.", arg_verb); + return EXIT_FAILURE; + } + if (streq(arg_verb, "suspend-then-hibernate")) r = execute_s2h(delay); else -- cgit v1.2.3