1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 ProFUSION embedded systems
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
23 #include <sys/types.h>
24 #include <sys/reboot.h>
25 #include <linux/reboot.h>
27 #include <sys/types.h>
29 #include <sys/mount.h>
30 #include <sys/syscall.h>
50 #define FINALIZE_ATTEMPTS 50
52 static int prepare_new_root(void) {
53 static const char dirs[] =
54 "/run/initramfs/oldroot\0"
55 "/run/initramfs/proc\0"
56 "/run/initramfs/sys\0"
57 "/run/initramfs/dev\0"
58 "/run/initramfs/run\0";
62 if (mount("/run/initramfs", "/run/initramfs", NULL, MS_BIND, NULL) < 0) {
63 log_error("Failed to mount bind /run/initramfs on /run/initramfs: %m");
67 if (mount(NULL, "/run/initramfs", NULL, MS_PRIVATE, NULL) < 0) {
68 log_error("Failed to make /run/initramfs private mount: %m");
72 NULSTR_FOREACH(dir, dirs)
73 if (mkdir_p_label(dir, 0755) < 0 && errno != EEXIST) {
74 log_error("Failed to mkdir %s: %m", dir);
78 if (mount("/sys", "/run/initramfs/sys", NULL, MS_BIND, NULL) < 0) {
79 log_error("Failed to mount bind /sys on /run/initramfs/sys: %m");
83 if (mount("/proc", "/run/initramfs/proc", NULL, MS_BIND, NULL) < 0) {
84 log_error("Failed to mount bind /proc on /run/initramfs/proc: %m");
88 if (mount("/dev", "/run/initramfs/dev", NULL, MS_BIND, NULL) < 0) {
89 log_error("Failed to mount bind /dev on /run/initramfs/dev: %m");
93 if (mount("/run", "/run/initramfs/run", NULL, MS_BIND, NULL) < 0) {
94 log_error("Failed to mount bind /run on /run/initramfs/run: %m");
101 static int pivot_to_new_root(void) {
103 if (chdir("/run/initramfs") < 0) {
104 log_error("Failed to change directory to /run/initramfs: %m");
108 /* Work-around for a kernel bug: for some reason the kernel
109 * refuses switching root if any file systems are mounted
110 * MS_SHARED. Hence remount them MS_PRIVATE here as a
113 * https://bugzilla.redhat.com/show_bug.cgi?id=847418 */
114 if (mount(NULL, "/", NULL, MS_REC|MS_PRIVATE, NULL) < 0)
115 log_warning("Failed to make \"/\" private mount: %m");
117 if (pivot_root(".", "oldroot") < 0) {
118 log_error("pivot failed: %m");
119 /* only chroot if pivot root succeeded */
126 make_console_stdio();
128 log_info("Successfully changed into root pivot.");
133 int main(int argc, char *argv[]) {
134 _cleanup_free_ char *line = NULL;
137 bool need_umount = true, need_swapoff = true, need_loop_detach = true, need_dm_detach = true;
138 bool in_container, use_watchdog = false;
141 /* suppress shutdown status output if 'quiet' is used */
142 r = read_one_line_file("/proc/cmdline", &line);
147 FOREACH_WORD_QUOTED(w, l, line, state)
148 if (streq(w, "quiet")) {
149 log_set_max_level(LOG_WARNING);
154 log_parse_environment();
155 log_set_target(LOG_TARGET_CONSOLE); /* syslog will die if not gone yet */
161 log_error("Not executed by init (pid 1).");
167 log_error("Invalid number of arguments.");
172 in_container = detect_container(NULL) > 0;
174 if (streq(argv[1], "reboot"))
176 else if (streq(argv[1], "poweroff"))
178 else if (streq(argv[1], "halt"))
179 cmd = RB_HALT_SYSTEM;
180 else if (streq(argv[1], "kexec"))
181 cmd = LINUX_REBOOT_CMD_KEXEC;
183 log_error("Unknown action '%s'.", argv[1]);
188 use_watchdog = !!getenv("WATCHDOG_USEC");
190 /* lock us into memory */
191 mlockall(MCL_CURRENT|MCL_FUTURE);
193 log_info("Sending SIGTERM to remaining processes...");
194 broadcast_signal(SIGTERM, true);
196 log_info("Sending SIGKILL to remaining processes...");
197 broadcast_signal(SIGKILL, true);
200 need_swapoff = false;
201 need_dm_detach = false;
202 need_loop_detach = false;
205 /* Unmount all mountpoints, swaps, and loopback devices */
206 for (retries = 0; retries < FINALIZE_ATTEMPTS; retries++) {
207 bool changed = false;
213 log_info("Unmounting file systems.");
214 r = umount_all(&changed);
217 log_info("All filesystems unmounted.");
219 log_info("Not all file systems unmounted, %d left.", r);
221 log_error("Failed to unmount file systems: %s", strerror(-r));
225 log_info("Deactivating swaps.");
226 r = swapoff_all(&changed);
228 need_swapoff = false;
229 log_info("All swaps deactivated.");
231 log_info("Not all swaps deactivated, %d left.", r);
233 log_error("Failed to deactivate swaps: %s", strerror(-r));
236 if (need_loop_detach) {
237 log_info("Detaching loop devices.");
238 r = loopback_detach_all(&changed);
240 need_loop_detach = false;
241 log_info("All loop devices detached.");
243 log_info("Not all loop devices detached, %d left.", r);
245 log_error("Failed to detach loop devices: %s", strerror(-r));
248 if (need_dm_detach) {
249 log_info("Detaching DM devices.");
250 r = dm_detach_all(&changed);
252 need_dm_detach = false;
253 log_info("All DM devices detached.");
255 log_info("Not all DM devices detached, %d left.", r);
257 log_error("Failed to detach DM devices: %s", strerror(-r));
260 if (!need_umount && !need_swapoff && !need_loop_detach && !need_dm_detach) {
262 log_info("All filesystems, swaps, loop devices, DM devices detached.");
267 /* If in this iteration we didn't manage to
268 * unmount/deactivate anything, we simply give up */
270 log_error("Cannot finalize remaining file systems and devices, giving up.");
274 log_debug("Couldn't finalize remaining file systems and devices after %u retries, trying again.", retries+1);
277 if (retries >= FINALIZE_ATTEMPTS)
278 log_error("Too many iterations, giving up.");
280 log_info("Storage is finalized.");
283 arguments[1] = argv[1];
285 execute_directory(SYSTEM_SHUTDOWN_PATH, NULL, arguments);
287 if (!in_container && !in_initrd() &&
288 access("/run/initramfs/shutdown", X_OK) == 0) {
290 if (prepare_new_root() >= 0 &&
291 pivot_to_new_root() >= 0) {
293 log_info("Returning to initrd...");
295 execv("/shutdown", argv);
296 log_error("Failed to execute shutdown binary: %m");
300 /* The kernel will automaticall flush ATA disks and suchlike
301 * on reboot(), but the file systems need to be synce'd
302 * explicitly in advance. So let's do this here, but not
303 * needlessly slow down containers. */
307 if (cmd == LINUX_REBOOT_CMD_KEXEC) {
310 /* We cheat and exec kexec to avoid doing all its work */
314 log_error("Could not fork: %m. Falling back to normal reboot.");
316 wait_for_terminate_and_warn("kexec", pid);
317 log_warning("kexec failed. Falling back to normal reboot.");
320 const char *args[3] = { "/sbin/kexec", "-e", NULL };
321 execv(args[0], (char * const *) args);
331 if (errno == EPERM && in_container) {
332 /* If we are in a container, and we lacked
333 * CAP_SYS_BOOT just exit, this will kill our
334 * container for good. */
335 log_error("Exiting container.");
339 log_error("Failed to invoke reboot(): %m");
343 log_error("Critical error while doing system shutdown: %s", strerror(-r));