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 _cleanup_free_ char *word;
150 word = strndup(w, l);
154 if (streq(word, "quiet")) {
155 log_set_max_level(LOG_WARNING);
161 log_parse_environment();
162 log_set_target(LOG_TARGET_CONSOLE); /* syslog will die if not gone yet */
168 log_error("Not executed by init (pid 1).");
174 log_error("Invalid number of arguments.");
179 in_container = detect_container(NULL) > 0;
181 if (streq(argv[1], "reboot"))
183 else if (streq(argv[1], "poweroff"))
185 else if (streq(argv[1], "halt"))
186 cmd = RB_HALT_SYSTEM;
187 else if (streq(argv[1], "kexec"))
188 cmd = LINUX_REBOOT_CMD_KEXEC;
190 log_error("Unknown action '%s'.", argv[1]);
195 use_watchdog = !!getenv("WATCHDOG_USEC");
197 /* lock us into memory */
198 mlockall(MCL_CURRENT|MCL_FUTURE);
200 log_info("Sending SIGTERM to remaining processes...");
201 broadcast_signal(SIGTERM, true);
203 log_info("Sending SIGKILL to remaining processes...");
204 broadcast_signal(SIGKILL, true);
207 need_swapoff = false;
208 need_dm_detach = false;
209 need_loop_detach = false;
212 /* Unmount all mountpoints, swaps, and loopback devices */
213 for (retries = 0; retries < FINALIZE_ATTEMPTS; retries++) {
214 bool changed = false;
220 log_info("Unmounting file systems.");
221 r = umount_all(&changed);
224 log_info("All filesystems unmounted.");
226 log_info("Not all file systems unmounted, %d left.", r);
228 log_error("Failed to unmount file systems: %s", strerror(-r));
232 log_info("Deactivating swaps.");
233 r = swapoff_all(&changed);
235 need_swapoff = false;
236 log_info("All swaps deactivated.");
238 log_info("Not all swaps deactivated, %d left.", r);
240 log_error("Failed to deactivate swaps: %s", strerror(-r));
243 if (need_loop_detach) {
244 log_info("Detaching loop devices.");
245 r = loopback_detach_all(&changed);
247 need_loop_detach = false;
248 log_info("All loop devices detached.");
250 log_info("Not all loop devices detached, %d left.", r);
252 log_error("Failed to detach loop devices: %s", strerror(-r));
255 if (need_dm_detach) {
256 log_info("Detaching DM devices.");
257 r = dm_detach_all(&changed);
259 need_dm_detach = false;
260 log_info("All DM devices detached.");
262 log_info("Not all DM devices detached, %d left.", r);
264 log_error("Failed to detach DM devices: %s", strerror(-r));
267 if (!need_umount && !need_swapoff && !need_loop_detach && !need_dm_detach) {
269 log_info("All filesystems, swaps, loop devices, DM devices detached.");
274 /* If in this iteration we didn't manage to
275 * unmount/deactivate anything, we simply give up */
277 log_error("Cannot finalize remaining file systems and devices, giving up.");
281 log_debug("Couldn't finalize remaining file systems and devices after %u retries, trying again.", retries+1);
284 if (retries >= FINALIZE_ATTEMPTS)
285 log_error("Too many iterations, giving up.");
287 log_info("Storage is finalized.");
290 arguments[1] = argv[1];
292 execute_directory(SYSTEM_SHUTDOWN_PATH, NULL, arguments);
294 if (!in_container && !in_initrd() &&
295 access("/run/initramfs/shutdown", X_OK) == 0) {
297 if (prepare_new_root() >= 0 &&
298 pivot_to_new_root() >= 0) {
300 log_info("Returning to initrd...");
302 execv("/shutdown", argv);
303 log_error("Failed to execute shutdown binary: %m");
307 /* The kernel will automaticall flush ATA disks and suchlike
308 * on reboot(), but the file systems need to be synce'd
309 * explicitly in advance. So let's do this here, but not
310 * needlessly slow down containers. */
314 if (cmd == LINUX_REBOOT_CMD_KEXEC) {
317 /* We cheat and exec kexec to avoid doing all its work */
321 log_error("Could not fork: %m. Falling back to normal reboot.");
323 wait_for_terminate_and_warn("kexec", pid);
324 log_warning("kexec failed. Falling back to normal reboot.");
327 const char *args[3] = { "/sbin/kexec", "-e", NULL };
328 execv(args[0], (char * const *) args);
338 if (errno == EPERM && in_container) {
339 /* If we are in a container, and we lacked
340 * CAP_SYS_BOOT just exit, this will kill our
341 * container for good. */
342 log_error("Exiting container.");
346 log_error("Failed to invoke reboot(): %m");
350 log_error("Critical error while doing system shutdown: %s", strerror(-r));