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>
49 #define FINALIZE_ATTEMPTS 50
51 static int prepare_new_root(void) {
52 static const char dirs[] =
53 "/run/initramfs/oldroot\0"
54 "/run/initramfs/proc\0"
55 "/run/initramfs/sys\0"
56 "/run/initramfs/dev\0"
57 "/run/initramfs/run\0";
61 if (mount("/run/initramfs", "/run/initramfs", NULL, MS_BIND, NULL) < 0) {
62 log_error("Failed to mount bind /run/initramfs on /run/initramfs: %m");
66 if (mount(NULL, "/run/initramfs", NULL, MS_PRIVATE, NULL) < 0) {
67 log_error("Failed to make /run/initramfs private mount: %m");
71 NULSTR_FOREACH(dir, dirs)
72 if (mkdir_p_label(dir, 0755) < 0 && errno != EEXIST) {
73 log_error("Failed to mkdir %s: %m", dir);
77 if (mount("/sys", "/run/initramfs/sys", NULL, MS_BIND, NULL) < 0) {
78 log_error("Failed to mount bind /sys on /run/initramfs/sys: %m");
82 if (mount("/proc", "/run/initramfs/proc", NULL, MS_BIND, NULL) < 0) {
83 log_error("Failed to mount bind /proc on /run/initramfs/proc: %m");
87 if (mount("/dev", "/run/initramfs/dev", NULL, MS_BIND, NULL) < 0) {
88 log_error("Failed to mount bind /dev on /run/initramfs/dev: %m");
92 if (mount("/run", "/run/initramfs/run", NULL, MS_BIND, NULL) < 0) {
93 log_error("Failed to mount bind /run on /run/initramfs/run: %m");
100 static int pivot_to_new_root(void) {
102 if (chdir("/run/initramfs") < 0) {
103 log_error("Failed to change directory to /run/initramfs: %m");
107 /* Work-around for a kernel bug: for some reason the kernel
108 * refuses switching root if any file systems are mounted
109 * MS_SHARED. Hence remount them MS_PRIVATE here as a
112 * https://bugzilla.redhat.com/show_bug.cgi?id=847418 */
113 if (mount(NULL, "/", NULL, MS_REC|MS_PRIVATE, NULL) < 0)
114 log_warning("Failed to make \"/\" private mount: %m");
116 if (pivot_root(".", "oldroot") < 0) {
117 log_error("pivot failed: %m");
118 /* only chroot if pivot root succeeded */
125 make_console_stdio();
127 log_info("Successfully changed into root pivot.");
132 int main(int argc, char *argv[]) {
135 bool need_umount = true, need_swapoff = true, need_loop_detach = true, need_dm_detach = true;
136 bool in_container, use_watchdog = false;
139 log_parse_environment();
140 log_set_target(LOG_TARGET_CONSOLE); /* syslog will die if not gone yet */
146 log_error("Not executed by init (pid 1).");
152 log_error("Invalid number of arguments.");
157 in_container = detect_container(NULL) > 0;
159 if (streq(argv[1], "reboot"))
161 else if (streq(argv[1], "poweroff"))
163 else if (streq(argv[1], "halt"))
164 cmd = RB_HALT_SYSTEM;
165 else if (streq(argv[1], "kexec"))
166 cmd = LINUX_REBOOT_CMD_KEXEC;
168 log_error("Unknown action '%s'.", argv[1]);
173 use_watchdog = !!getenv("WATCHDOG_USEC");
175 /* lock us into memory */
176 mlockall(MCL_CURRENT|MCL_FUTURE);
178 log_info("Sending SIGTERM to remaining processes...");
179 broadcast_signal(SIGTERM, true);
181 log_info("Sending SIGKILL to remaining processes...");
182 broadcast_signal(SIGKILL, true);
185 need_swapoff = false;
186 need_dm_detach = false;
187 need_loop_detach = false;
190 /* Unmount all mountpoints, swaps, and loopback devices */
191 for (retries = 0; retries < FINALIZE_ATTEMPTS; retries++) {
192 bool changed = false;
198 log_info("Unmounting file systems.");
199 r = umount_all(&changed);
202 log_info("All filesystems unmounted.");
204 log_info("Not all file systems unmounted, %d left.", r);
206 log_error("Failed to unmount file systems: %s", strerror(-r));
210 log_info("Deactivating swaps.");
211 r = swapoff_all(&changed);
213 need_swapoff = false;
214 log_info("All swaps deactivated.");
216 log_info("Not all swaps deactivated, %d left.", r);
218 log_error("Failed to deactivate swaps: %s", strerror(-r));
221 if (need_loop_detach) {
222 log_info("Detaching loop devices.");
223 r = loopback_detach_all(&changed);
225 need_loop_detach = false;
226 log_info("All loop devices detached.");
228 log_info("Not all loop devices detached, %d left.", r);
230 log_error("Failed to detach loop devices: %s", strerror(-r));
233 if (need_dm_detach) {
234 log_info("Detaching DM devices.");
235 r = dm_detach_all(&changed);
237 need_dm_detach = false;
238 log_info("All DM devices detached.");
240 log_info("Not all DM devices detached, %d left.", r);
242 log_error("Failed to detach DM devices: %s", strerror(-r));
245 if (!need_umount && !need_swapoff && !need_loop_detach && !need_dm_detach) {
247 log_info("All filesystems, swaps, loop devices, DM devices detached.");
252 /* If in this iteration we didn't manage to
253 * unmount/deactivate anything, we simply give up */
255 log_error("Cannot finalize remaining file systems and devices, giving up.");
259 log_debug("Couldn't finalize remaining file systems and devices after %u retries, trying again.", retries+1);
262 if (retries >= FINALIZE_ATTEMPTS)
263 log_error("Too many iterations, giving up.");
265 log_info("Storage is finalized.");
268 arguments[1] = argv[1];
270 execute_directory(SYSTEM_SHUTDOWN_PATH, NULL, arguments);
272 if (!in_container && !in_initrd() &&
273 access("/run/initramfs/shutdown", X_OK) == 0) {
275 if (prepare_new_root() >= 0 &&
276 pivot_to_new_root() >= 0) {
278 log_info("Returning to initrd...");
280 execv("/shutdown", argv);
281 log_error("Failed to execute shutdown binary: %m");
285 /* The kernel will automaticall flush ATA disks and suchlike
286 * on reboot(), but the file systems need to be synce'd
287 * explicitly in advance. So let's do this here, but not
288 * needlessly slow down containers. */
292 if (cmd == LINUX_REBOOT_CMD_KEXEC) {
295 /* We cheat and exec kexec to avoid doing all its work */
299 log_error("Could not fork: %m. Falling back to normal reboot.");
301 wait_for_terminate_and_warn("kexec", pid);
302 log_warning("kexec failed. Falling back to normal reboot.");
305 const char *args[3] = { "/sbin/kexec", "-e", NULL };
306 execv(args[0], (char * const *) args);
316 if (errno == EPERM && in_container) {
317 /* If we are in a container, and we lacked
318 * CAP_SYS_BOOT just exit, this will kill our
319 * container for good. */
320 log_error("Exiting container.");
324 log_error("Failed to invoke reboot(): %m");
328 log_error("Critical error while doing system shutdown: %s", strerror(-r));