]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sleep-config: remove HibernateState= & HybridSleepState=, restrict
authorMike Yuan <me@yhndnzj.com>
Fri, 20 Oct 2023 16:21:20 +0000 (00:21 +0800)
committerMike Yuan <me@yhndnzj.com>
Mon, 23 Oct 2023 15:12:27 +0000 (23:12 +0800)
SuspendState= not to include "disk"

I don't know why these existed in the first place, but as I
justified in the comments, it's simply not sensible to allow
HibernateState= or HybridSleepState= to take values other than
'disk'. So let's just remove those options. Also, SuspendState=
should not contain 'disk'.

man/systemd-sleep.conf.xml
src/shared/sleep-config.c
src/sleep/sleep.conf

index 67933ebaf209780f08be2ab09d01e2dbaced5a81..b33699b6c56f81c6d2a5dc9f5d4614f6369fa358 100644 (file)
       <varlistentry>
         <term><varname>AllowSuspend=</varname></term>
         <term><varname>AllowHibernation=</varname></term>
-        <term><varname>AllowSuspendThenHibernate=</varname></term>
         <term><varname>AllowHybridSleep=</varname></term>
+        <term><varname>AllowSuspendThenHibernate=</varname></term>
 
         <listitem><para>By default any power-saving mode is advertised if possible (i.e.
         the kernel supports that mode, the necessary resources are available). Those
       </varlistentry>
 
       <varlistentry>
-        <term><varname>SuspendMode=</varname></term>
         <term><varname>HibernateMode=</varname></term>
         <term><varname>HybridSleepMode=</varname></term>
 
         <listitem><para>The string to be written to <filename>/sys/power/disk</filename> by, respectively,
-        <citerefentry><refentrytitle>systemd-suspend.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
-        <citerefentry><refentrytitle>systemd-hibernate.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
-        or
+        <citerefentry><refentrytitle>systemd-hibernate.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+        and
         <citerefentry><refentrytitle>systemd-hybrid-sleep.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
         More than one value can be specified by separating multiple values with whitespace. They will be
         tried in turn, until one is written without error. If none of the writes succeed, the operation will
         url="https://www.kernel.org/doc/html/latest/admin-guide/pm/sleep-states.html#basic-sysfs-interfaces-for-system-suspend-and-hibernation">the
         kernel documentation</ulink> for more details.</para>
 
+        <para>Note that hybrid sleep corresponds to the <literal>suspend</literal> disk mode. If <varname>HybridSleepMode=</varname>
+        is overridden, you might get plain hibernation instead.</para>
+
         <para>
         <citerefentry><refentrytitle>systemd-suspend-then-hibernate.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
         uses the value of <varname>SuspendMode=</varname> when suspending and the value of
 
       <varlistentry>
         <term><varname>SuspendState=</varname></term>
-        <term><varname>HibernateState=</varname></term>
-        <term><varname>HybridSleepState=</varname></term>
 
-        <listitem><para>The string to be written to <filename>/sys/power/state</filename> by, respectively,
-        <citerefentry><refentrytitle>systemd-suspend.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
-        <citerefentry><refentrytitle>systemd-hibernate.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
-        or
-        <citerefentry><refentrytitle>systemd-hybrid-sleep.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
+        <listitem><para>The string to be written to <filename>/sys/power/state</filename> by <citerefentry>
+        <refentrytitle>systemd-suspend.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
         More than one value can be specified by separating multiple values with whitespace. They will be
         tried in turn, until one is written without error. If none of the writes succeed, the operation will
-        be aborted.
-        </para>
+        be aborted.</para>
 
         <para>The allowed set of values is determined by the kernel and is shown in the file itself (use
         <command>cat /sys/power/state</command> to display). See <ulink
 
         <para>
         <citerefentry><refentrytitle>systemd-suspend-then-hibernate.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
-        uses the value of <varname>SuspendState=</varname> when suspending and the value of
-        <varname>HibernateState=</varname> when hibernating.</para>
+        uses this value when suspending.</para>
 
         <xi:include href="version-info.xml" xpointer="v203"/></listitem>
       </varlistentry>
index deba2b1c588a2e86c86be5bca8ed4e2000b5b142..03d04775e611c7b16919df13ac8f30e4e64a8b98 100644 (file)
@@ -33,18 +33,55 @@ static const char* const sleep_operation_table[_SLEEP_OPERATION_MAX] = {
 
 DEFINE_STRING_TABLE_LOOKUP(sleep_operation, SleepOperation);
 
+static char* const* const sleep_default_state_table[_SLEEP_OPERATION_CONFIG_MAX] = {
+        [SLEEP_SUSPEND]      = STRV_MAKE("mem", "standby", "freeze"),
+        [SLEEP_HIBERNATE]    = STRV_MAKE("disk"),
+        [SLEEP_HYBRID_SLEEP] = STRV_MAKE("disk"),
+};
+
+static char* const* const sleep_default_mode_table[_SLEEP_OPERATION_CONFIG_MAX] = {
+        /* Not used by SLEEP_SUSPEND */
+        [SLEEP_HIBERNATE]    = STRV_MAKE("platform", "shutdown"),
+        [SLEEP_HYBRID_SLEEP] = STRV_MAKE("suspend", "platform", "shutdown"),
+};
+
 SleepConfig* sleep_config_free(SleepConfig *sc) {
         if (!sc)
                 return NULL;
 
         for (SleepOperation i = 0; i < _SLEEP_OPERATION_CONFIG_MAX; i++) {
-                strv_free(sc->modes[i]);
                 strv_free(sc->states[i]);
+                strv_free(sc->modes[i]);
         }
 
         return mfree(sc);
 }
 
+static void sleep_config_validate_state_and_mode(SleepConfig *sc) {
+        assert(sc);
+
+        /* So we should really not allow setting SuspendState= to 'disk', which means hibernation. We have
+         * SLEEP_HIBERNATE for proper hibernation support, which includes checks for resume support (through
+         * EFI variable or resume= kernel command line option). It's simply not sensible to call the suspend
+         * operation but eventually do an unsafe hibernation. */
+        if (strv_contains(sc->states[SLEEP_SUSPEND], "disk")) {
+                strv_remove(sc->states[SLEEP_SUSPEND], "disk");
+                log_warning("Sleep state 'disk' is not supported by operation %s, ignoring.",
+                            sleep_operation_to_string(SLEEP_SUSPEND));
+        }
+        assert(!sc->modes[SLEEP_SUSPEND]);
+
+        /* People should use hybrid-sleep instead of setting HibernateMode=suspend. Warn about it but don't
+         * drop it in this case. */
+        if (strv_contains(sc->modes[SLEEP_HIBERNATE], "suspend"))
+                log_warning("Sleep mode 'suspend' should not be used by operation %s. Please use %s instead.",
+                            sleep_operation_to_string(SLEEP_HIBERNATE), sleep_operation_to_string(SLEEP_HYBRID_SLEEP));
+
+        if (!strv_contains(sc->modes[SLEEP_HYBRID_SLEEP], "suspend"))
+                log_warning("Sleep mode 'suspend' is not set for operation %s. This would likely result in a plain hibernation.",
+                            sleep_operation_to_string(SLEEP_HYBRID_SLEEP));
+}
+
 int parse_sleep_config(SleepConfig **ret) {
         _cleanup_(sleep_config_freep) SleepConfig *sc = NULL;
         int allow_suspend = -1, allow_hibernate = -1, allow_s2h = -1, allow_hybrid_sleep = -1;
@@ -60,20 +97,22 @@ int parse_sleep_config(SleepConfig **ret) {
         };
 
         const ConfigTableItem items[] = {
-                { "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, sc->modes + SLEEP_SUSPEND       },
-                { "Sleep", "SuspendState",              config_parse_strv,     0, sc->states + SLEEP_SUSPEND      },
-                { "Sleep", "HibernateMode",             config_parse_strv,     0, sc->modes + SLEEP_HIBERNATE     },
-                { "Sleep", "HibernateState",            config_parse_strv,     0, sc->states + SLEEP_HIBERNATE    },
-                { "Sleep", "HybridSleepMode",           config_parse_strv,     0, sc->modes + SLEEP_HYBRID_SLEEP  },
-                { "Sleep", "HybridSleepState",          config_parse_strv,     0, sc->states + SLEEP_HYBRID_SLEEP },
-
-                { "Sleep", "HibernateDelaySec",         config_parse_sec,      0, &sc->hibernate_delay_usec       },
-                { "Sleep", "SuspendEstimationSec",      config_parse_sec,      0, &sc->suspend_estimation_usec    },
+                { "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", "SuspendState",              config_parse_strv,        0,               sc->states + SLEEP_SUSPEND     },
+                { "Sleep", "SuspendMode",               config_parse_warn_compat, DISABLED_LEGACY, NULL                           },
+
+                { "Sleep", "HibernateState",            config_parse_warn_compat, DISABLED_LEGACY, NULL                           },
+                { "Sleep", "HibernateMode",             config_parse_strv,        0,               sc->modes + SLEEP_HIBERNATE    },
+
+                { "Sleep", "HybridSleepState",          config_parse_warn_compat, DISABLED_LEGACY, NULL                           },
+                { "Sleep", "HybridSleepMode",           config_parse_strv,        0,               sc->modes + SLEEP_HYBRID_SLEEP },
+
+                { "Sleep", "HibernateDelaySec",         config_parse_sec,         0,               &sc->hibernate_delay_usec      },
+                { "Sleep", "SuspendEstimationSec",      config_parse_sec,         0,               &sc->suspend_estimation_usec   },
                 {}
         };
 
@@ -89,26 +128,26 @@ int parse_sleep_config(SleepConfig **ret) {
         sc->allow[SLEEP_SUSPEND_THEN_HIBERNATE] = allow_s2h >= 0 ? allow_s2h
                 : (allow_suspend != 0 && allow_hibernate != 0);
 
-        if (!sc->states[SLEEP_SUSPEND])
-                sc->states[SLEEP_SUSPEND] = strv_new("mem", "standby", "freeze");
-        if (!sc->modes[SLEEP_HIBERNATE])
-                sc->modes[SLEEP_HIBERNATE] = strv_new("platform", "shutdown");
-        if (!sc->states[SLEEP_HIBERNATE])
-                sc->states[SLEEP_HIBERNATE] = strv_new("disk");
-        if (!sc->modes[SLEEP_HYBRID_SLEEP])
-                sc->modes[SLEEP_HYBRID_SLEEP] = strv_new("suspend", "platform", "shutdown");
-        if (!sc->states[SLEEP_HYBRID_SLEEP])
-                sc->states[SLEEP_HYBRID_SLEEP] = strv_new("disk");
+        for (SleepOperation i = 0; i < _SLEEP_OPERATION_CONFIG_MAX; i++) {
+                if (!sc->states[i] && sleep_default_state_table[i]) {
+                        sc->states[i] = strv_copy(sleep_default_state_table[i]);
+                        if (!sc->states[i])
+                                return log_oom();
+                }
+
+                if (!sc->modes[i] && sleep_default_mode_table[i]) {
+                        sc->modes[i] = strv_copy(sleep_default_mode_table[i]);
+                        if (!sc->modes[i])
+                                return log_oom();
+                }
+        }
+
         if (sc->suspend_estimation_usec == 0)
                 sc->suspend_estimation_usec = DEFAULT_SUSPEND_ESTIMATION_USEC;
 
-        /* Ensure values set for all required fields */
-        if (!sc->states[SLEEP_SUSPEND] || !sc->modes[SLEEP_HIBERNATE]
-            || !sc->states[SLEEP_HIBERNATE] || !sc->modes[SLEEP_HYBRID_SLEEP] || !sc->states[SLEEP_HYBRID_SLEEP])
-                return log_oom();
+        sleep_config_validate_state_and_mode(sc);
 
         *ret = TAKE_PTR(sc);
-
         return 0;
 }
 
index 8428821b52519bc9c8a4a2c40ca986f6d66dfdae..06f7dc38a4c7eaa3f9e9ededa39951f2bc683d54 100644 (file)
 #AllowHibernation=yes
 #AllowSuspendThenHibernate=yes
 #AllowHybridSleep=yes
-#SuspendMode=
 #SuspendState=mem standby freeze
 #HibernateMode=platform shutdown
-#HibernateState=disk
 #HybridSleepMode=suspend platform shutdown
-#HybridSleepState=disk
 #HibernateDelaySec=
 #SuspendEstimationSec=60min