summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2012-05-05 02:06:58 +0200
committerLennart Poettering <lennart@poettering.net>2012-05-08 13:54:23 +0200
commit6edd7d0a09171ea5ae8e01b7b1cbcb0bdfbfeb16 (patch)
tree85a09e06fd5dfc98cb198fafb9a33b70e79a4c63
parent4943c1c94ba751c98763f4232b4350481b22c90a (diff)
sleep: implement suspend/hibernate as first class targets
-rw-r--r--.gitignore1
-rw-r--r--Makefile.am18
-rw-r--r--TODO5
-rw-r--r--man/systemctl.xml10
-rw-r--r--man/systemd.special.xml34
-rw-r--r--src/core/shutdown.c6
-rw-r--r--src/core/special.h2
-rw-r--r--src/shared/util.c3
l---------src/sleep/Makefile1
-rw-r--r--src/sleep/sleep.c83
-rw-r--r--src/systemctl/systemctl.c16
-rw-r--r--units/.gitignore2
-rw-r--r--units/hibernate.service.in16
-rw-r--r--units/hibernate.target14
-rw-r--r--units/sleep.target13
-rw-r--r--units/suspend.service.in16
-rw-r--r--units/suspend.target14
17 files changed, 243 insertions, 11 deletions
diff --git a/.gitignore b/.gitignore
index 7f22255c5..e61f1cdba 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
+/systemd-sleep
/systemd-inhibit
/systemd-remount-fs
/build-aux
diff --git a/Makefile.am b/Makefile.am
index dbcfeb384..002a86aeb 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -67,6 +67,7 @@ usergeneratordir=$(pkglibexecdir)/user-generators
pkgincludedir=$(includedir)/systemd
systemgeneratordir=$(rootlibexecdir)/system-generators
systemshutdowndir=$(rootlibexecdir)/system-shutdown
+systemsleepdir=$(rootlibexecdir)/system-sleep
systemunitdir=$(rootprefix)/lib/systemd/system
udevlibexecdir=$(rootprefix)/lib/udev
udevhomedir = $(libexecdir)/udev
@@ -117,6 +118,7 @@ AM_CPPFLAGS = \
-DSYSTEMD_CGROUP_AGENT_PATH=\"$(rootlibexecdir)/systemd-cgroups-agent\" \
-DSYSTEMD_BINARY_PATH=\"$(rootlibexecdir)/systemd\" \
-DSYSTEMD_SHUTDOWN_BINARY_PATH=\"$(rootlibexecdir)/systemd-shutdown\" \
+ -DSYSTEMD_SLEEP_BINARY_PATH=\"$(rootlibexecdir)/systemd-sleep\" \
-DSYSTEMCTL_BINARY_PATH=\"$(rootbindir)/systemctl\" \
-DSYSTEMD_TTY_ASK_PASSWORD_AGENT_BINARY_PATH=\"$(rootbindir)/systemd-tty-ask-password-agent\" \
-DSYSTEMD_STDIO_BRIDGE_BINARY_PATH=\"$(bindir)/systemd-stdio-bridge\" \
@@ -230,7 +232,8 @@ rootlibexec_PROGRAMS = \
systemd-fsck \
systemd-timestamp \
systemd-ac-power \
- systemd-sysctl
+ systemd-sysctl \
+ systemd-sleep
systemgenerator_PROGRAMS = \
systemd-getty-generator
@@ -266,6 +269,7 @@ dist_systemunit_DATA = \
units/nss-lookup.target \
units/nss-user-lookup.target \
units/mail-transfer-agent.target \
+ units/hibernate.target \
units/http-daemon.target \
units/poweroff.target \
units/reboot.target \
@@ -276,7 +280,9 @@ dist_systemunit_DATA = \
units/final.target \
units/umount.target \
units/sigpwr.target \
+ units/sleep.target \
units/sockets.target \
+ units/suspend.target \
units/swap.target \
units/systemd-initctl.socket \
units/systemd-shutdownd.socket \
@@ -318,12 +324,14 @@ nodist_systemunit_DATA = \
units/systemd-sysctl.service \
units/halt.service \
units/emergency.service \
+ units/hibernate.service \
units/poweroff.service \
units/reboot.service \
units/kexec.service \
units/fsck@.service \
units/fsck-root.service \
units/rescue.service \
+ units/suspend.service \
units/user@.service \
units/systemd-udev.service \
units/systemd-udev-trigger.service \
@@ -1063,6 +1071,13 @@ systemd_sysctl_LDADD = \
libsystemd-shared.la
# ------------------------------------------------------------------------------
+systemd_sleep_SOURCES = \
+ src/sleep/sleep.c
+
+systemd_sleep_LDADD = \
+ libsystemd-shared.la
+
+# ------------------------------------------------------------------------------
systemd_fsck_SOURCES = \
src/fsck/fsck.c
@@ -3027,6 +3042,7 @@ systemd-install-data-hook:
$(DESTDIR)$(prefix)/lib/sysctl.d \
$(DESTDIR)$(sysconfdir)/sysctl.d \
$(DESTDIR)$(systemshutdowndir) \
+ $(DESTDIR)$(systemsleepdir) \
$(DESTDIR)$(systemgeneratordir) \
$(DESTDIR)$(usergeneratordir)
$(MKDIR_P) -m 0755 \
diff --git a/TODO b/TODO
index cd7aecf49..aeba2b516 100644
--- a/TODO
+++ b/TODO
@@ -53,9 +53,6 @@ Features:
* ExecOnFailure=/usr/bin/foo
-* logind: add "mode" flag to poweroff/suspend inhibit logic so that we can
- support both "inhibit" and "delay" mode.
-
* fedora: make sshd and pam_loginuid work in nspawn containers
* fix utmp for console logins in containers
@@ -72,8 +69,6 @@ Features:
* journald: allow forwarding of log data to specific TTY instea dof console
-* suspend/hibernate/hybrid support, auto-suspend logic with idle hint
-
* add RequiredBy to [Install]
* udev: move to LGPL
diff --git a/man/systemctl.xml b/man/systemctl.xml
index dd0ff786e..9e113eb0f 100644
--- a/man/systemctl.xml
+++ b/man/systemctl.xml
@@ -1149,6 +1149,16 @@
<option>--user</option> option) and
will fail otherwise.</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><command>suspend</command></term>
+
+ <listitem><para>Suspend the system.</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><command>hibernate</command></term>
+
+ <listitem><para>Hibernate the system.</para></listitem>
+ </varlistentry>
</variablelist>
</refsect1>
diff --git a/man/systemd.special.xml b/man/systemd.special.xml
index 39c380221..984e998ab 100644
--- a/man/systemd.special.xml
+++ b/man/systemd.special.xml
@@ -58,6 +58,7 @@
<filename>exit.service</filename>,
<filename>final.service</filename>,
<filename>graphical.target</filename>,
+ <filename>hibernate.target</filename>,
<filename>http-daemon.target</filename>,
<filename>halt.target</filename>,
<filename>kbrequest.target</filename>,
@@ -80,7 +81,9 @@
<filename>runlevel5.target</filename>,
<filename>shutdown.target</filename>,
<filename>sigpwr.target</filename>,
+ <filename>sleep.target</filename>,
<filename>sockets.target</filename>,
+ <filename>suspend.target</filename>,
<filename>swap.target</filename>,
<filename>sysinit.target</filename>,
<filename>syslog.service</filename>,
@@ -240,6 +243,15 @@
</listitem>
</varlistentry>
<varlistentry>
+ <term><filename>hibernate.target</filename></term>
+ <listitem>
+ <para>A special target unit
+ for hibernating the
+ system. This pulls in
+ <filename>sleep.target</filename>.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
<term><filename>http-daemon.target</filename></term>
<listitem>
<para>A target for pulling in
@@ -591,6 +603,19 @@
</listitem>
</varlistentry>
<varlistentry>
+ <term><filename>sleep.target</filename></term>
+ <listitem>
+ <para>A special target unit
+ that is pulled in by
+ <filename>suspend.target</filename>
+ and
+ <filename>hibernate.target</filename>
+ and may be used to hook units
+ into the sleep state
+ logic.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
<term><filename>sockets.target</filename></term>
<listitem>
<para>A special target unit
@@ -605,6 +630,15 @@
</listitem>
</varlistentry>
<varlistentry>
+ <term><filename>suspend.target</filename></term>
+ <listitem>
+ <para>A special target unit
+ for suspending the
+ system. This pulls in
+ <filename>sleep.target</filename>.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
<term><filename>swap.target</filename></term>
<listitem>
<para>Similar to
diff --git a/src/core/shutdown.c b/src/core/shutdown.c
index 2494bb86a..a8dfe2614 100644
--- a/src/core/shutdown.c
+++ b/src/core/shutdown.c
@@ -309,6 +309,7 @@ int main(int argc, char *argv[]) {
unsigned retries;
bool need_umount = true, need_swapoff = true, need_loop_detach = true, need_dm_detach = true;
bool killed_everbody = false, in_container, use_watchdog = false;
+ char *arguments[3];
log_parse_environment();
log_set_target(LOG_TARGET_CONSOLE); /* syslog will die if not gone yet */
@@ -442,7 +443,10 @@ int main(int argc, char *argv[]) {
if (retries >= FINALIZE_ATTEMPTS)
log_error("Too many iterations, giving up.");
- execute_directory(SYSTEM_SHUTDOWN_PATH, NULL, NULL);
+ arguments[0] = NULL;
+ arguments[1] = argv[1];
+ arguments[2] = NULL;
+ execute_directory(SYSTEM_SHUTDOWN_PATH, NULL, arguments);
/* If we are in a container, just exit, this will kill our
* container for good. */
diff --git a/src/core/special.h b/src/core/special.h
index 2db4711c2..bc9b330ff 100644
--- a/src/core/special.h
+++ b/src/core/special.h
@@ -36,6 +36,8 @@
#define SPECIAL_REBOOT_TARGET "reboot.target"
#define SPECIAL_KEXEC_TARGET "kexec.target"
#define SPECIAL_EXIT_TARGET "exit.target"
+#define SPECIAL_SUSPEND_TARGET "suspend.target"
+#define SPECIAL_HIBERNATE_TARGET "hibernate.target"
/* Special boot targets */
#define SPECIAL_RESCUE_TARGET "rescue.target"
diff --git a/src/shared/util.c b/src/shared/util.c
index 8a0b2a1b4..d8d3f1a16 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -4106,8 +4106,7 @@ void execute_directory(const char *directory, DIR *d, char *argv[]) {
_argv[1] = NULL;
argv = _argv;
} else
- if (!argv[0])
- argv[0] = path;
+ argv[0] = path;
execv(path, argv);
diff --git a/src/sleep/Makefile b/src/sleep/Makefile
new file mode 120000
index 000000000..d0b0e8e00
--- /dev/null
+++ b/src/sleep/Makefile
@@ -0,0 +1 @@
+../Makefile \ No newline at end of file
diff --git a/src/sleep/sleep.c b/src/sleep/sleep.c
new file mode 100644
index 000000000..7062dc242
--- /dev/null
+++ b/src/sleep/sleep.c
@@ -0,0 +1,83 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2012 Lennart Poettering
+
+ 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/>.
+***/
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+
+#include "log.h"
+#include "util.h"
+
+int main(int argc, char *argv[]) {
+ const char *verb;
+ char* arguments[4];
+ int r;
+ FILE *f;
+
+ log_set_target(LOG_TARGET_AUTO);
+ log_parse_environment();
+ log_open();
+
+ if (argc != 2) {
+ log_error("Invalid number of arguments.");
+ r = -EINVAL;
+ goto finish;
+ }
+
+ if (streq(argv[1], "suspend"))
+ verb = "mem";
+ else if (streq(argv[1], "hibernate"))
+ verb = "disk";
+ else {
+ log_error("Unknown action '%s'.", argv[1]);
+ r = -EINVAL;
+ goto finish;
+ }
+
+ f = fopen("/sys/power/state", "we");
+ if (!f) {
+ log_error("Failed to open /sys/power/state: %m");
+ r = -errno;
+ goto finish;
+ }
+
+ arguments[0] = NULL;
+ arguments[1] = (char*) "pre";
+ arguments[2] = argv[1];
+ arguments[3] = NULL;
+ execute_directory(SYSTEMD_SLEEP_BINARY_PATH, NULL, arguments);
+
+ fputs(verb, f);
+ fputc('\n', f);
+ fflush(f);
+
+ r = ferror(f) ? -errno : 0;
+
+ arguments[1] = (char*) "post";
+ execute_directory(SYSTEMD_SLEEP_BINARY_PATH, NULL, arguments);
+
+ fclose(f);
+
+finish:
+
+ return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+
+}
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index acede4e76..762b5be34 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -97,6 +97,8 @@ static enum action {
ACTION_REBOOT,
ACTION_KEXEC,
ACTION_EXIT,
+ ACTION_SUSPEND,
+ ACTION_HIBERNATE,
ACTION_RUNLEVEL2,
ACTION_RUNLEVEL3,
ACTION_RUNLEVEL4,
@@ -1605,6 +1607,10 @@ static enum action verb_to_action(const char *verb) {
return ACTION_DEFAULT;
else if (streq(verb, "exit"))
return ACTION_EXIT;
+ else if (streq(verb, "suspend"))
+ return ACTION_SUSPEND;
+ else if (streq(verb, "hibernate"))
+ return ACTION_HIBERNATE;
else
return ACTION_INVALID;
}
@@ -1623,7 +1629,9 @@ static int start_unit(DBusConnection *bus, char **args) {
[ACTION_RESCUE] = SPECIAL_RESCUE_TARGET,
[ACTION_EMERGENCY] = SPECIAL_EMERGENCY_TARGET,
[ACTION_DEFAULT] = SPECIAL_DEFAULT_TARGET,
- [ACTION_EXIT] = SPECIAL_EXIT_TARGET
+ [ACTION_EXIT] = SPECIAL_EXIT_TARGET,
+ [ACTION_SUSPEND] = SPECIAL_SUSPEND_TARGET,
+ [ACTION_HIBERNATE] = SPECIAL_HIBERNATE_TARGET
};
int r, ret = 0;
@@ -4201,7 +4209,9 @@ static int systemctl_help(void) {
" poweroff Shut down and power-off the system\n"
" reboot Shut down and reboot the system\n"
" kexec Shut down and reboot the system with kexec\n"
- " exit Ask for user instance termination\n",
+ " exit Request user instance exit\n"
+ " suspend Suspend the system\n"
+ " hibernate Hibernate the system\n",
program_invocation_short_name);
return 0;
@@ -5135,6 +5145,8 @@ static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError
{ "poweroff", EQUAL, 1, start_special },
{ "reboot", EQUAL, 1, start_special },
{ "kexec", EQUAL, 1, start_special },
+ { "suspend", EQUAL, 1, start_special },
+ { "hibernate", EQUAL, 1, start_special },
{ "default", EQUAL, 1, start_special },
{ "rescue", EQUAL, 1, start_special },
{ "emergency", EQUAL, 1, start_special },
diff --git a/units/.gitignore b/units/.gitignore
index 68c174f1f..dc5e1d47d 100644
--- a/units/.gitignore
+++ b/units/.gitignore
@@ -1,3 +1,5 @@
+/hibernate.service
+/suspend.service
/console-getty.service
/systemd-journald.service
user@.service
diff --git a/units/hibernate.service.in b/units/hibernate.service.in
new file mode 100644
index 000000000..6dba653d3
--- /dev/null
+++ b/units/hibernate.service.in
@@ -0,0 +1,16 @@
+# This file is part of systemd.
+#
+# 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.
+
+[Unit]
+Description=Hibernate
+DefaultDependencies=no
+Requires=sleep.target
+After=sleep.target
+
+[Service]
+Type=oneshot
+ExecStart=@rootlibexecdir@/systemd-sleep hibernate
diff --git a/units/hibernate.target b/units/hibernate.target
new file mode 100644
index 000000000..05238a7cb
--- /dev/null
+++ b/units/hibernate.target
@@ -0,0 +1,14 @@
+# This file is part of systemd.
+#
+# 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.
+
+# See systemd.special(7) for details
+
+[Unit]
+Description=Hibernate
+DefaultDependencies=no
+BindTo=hibernate.service
+After=hibernate.service
diff --git a/units/sleep.target b/units/sleep.target
new file mode 100644
index 000000000..9f4b247eb
--- /dev/null
+++ b/units/sleep.target
@@ -0,0 +1,13 @@
+# This file is part of systemd.
+#
+# 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.
+
+# See systemd.special(7) for details
+
+[Unit]
+Description=Sleep
+DefaultDependencies=no
+RefuseManualStart=yes
diff --git a/units/suspend.service.in b/units/suspend.service.in
new file mode 100644
index 000000000..3cf819e47
--- /dev/null
+++ b/units/suspend.service.in
@@ -0,0 +1,16 @@
+# This file is part of systemd.
+#
+# 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.
+
+[Unit]
+Description=Suspend
+DefaultDependencies=no
+Requires=sleep.target
+After=sleep.target
+
+[Service]
+Type=oneshot
+ExecStart=@rootlibexecdir@/systemd-sleep suspend
diff --git a/units/suspend.target b/units/suspend.target
new file mode 100644
index 000000000..3ddb44975
--- /dev/null
+++ b/units/suspend.target
@@ -0,0 +1,14 @@
+# This file is part of systemd.
+#
+# 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.
+
+# See systemd.special(7) for details
+
+[Unit]
+Description=Suspend
+DefaultDependencies=no
+BindTo=suspend.service
+After=suspend.service