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>
28 #include <sys/mount.h>
29 #include <sys/syscall.h>
49 #include "cgroup-util.h"
51 #include "switch-root.h"
53 #define FINALIZE_ATTEMPTS 50
55 static char* arg_verb;
57 static int parse_argv(int argc, char *argv[]) {
59 ARG_LOG_LEVEL = 0x100,
65 static const struct option options[] = {
66 { "log-level", required_argument, NULL, ARG_LOG_LEVEL },
67 { "log-target", required_argument, NULL, ARG_LOG_TARGET },
68 { "log-color", optional_argument, NULL, ARG_LOG_COLOR },
69 { "log-location", optional_argument, NULL, ARG_LOG_LOCATION },
78 /* "-" prevents getopt from permuting argv[] and moving the verb away
79 * from argv[1]. Our interface to initrd promises it'll be there. */
80 while ((c = getopt_long(argc, argv, "-", options, NULL)) >= 0)
84 r = log_set_max_level_from_string(optarg);
86 log_error("Failed to parse log level %s, ignoring.", optarg);
91 r = log_set_target_from_string(optarg);
93 log_error("Failed to parse log target %s, ignoring", optarg);
100 r = log_show_color_from_string(optarg);
102 log_error("Failed to parse log color setting %s, ignoring", optarg);
104 log_show_color(true);
108 case ARG_LOG_LOCATION:
110 r = log_show_location_from_string(optarg);
112 log_error("Failed to parse log location setting %s, ignoring", optarg);
114 log_show_location(true);
122 log_error("Excess arguments, ignoring");
129 assert_not_reached("Unhandled option code.");
133 log_error("Verb argument missing.");
140 static int switch_root_initramfs(void) {
141 if (mount("/run/initramfs", "/run/initramfs", NULL, MS_BIND, NULL) < 0)
142 return log_error_errno(errno, "Failed to mount bind /run/initramfs on /run/initramfs: %m");
144 if (mount(NULL, "/run/initramfs", NULL, MS_PRIVATE, NULL) < 0)
145 return log_error_errno(errno, "Failed to make /run/initramfs private mount: %m");
147 /* switch_root with MS_BIND, because there might still be processes lurking around, which have open file desriptors.
148 * /run/initramfs/shutdown will take care of these.
149 * Also do not detach the old root, because /run/initramfs/shutdown needs to access it.
151 return switch_root("/run/initramfs", "/oldroot", false, MS_BIND);
155 int main(int argc, char *argv[]) {
156 bool need_umount, need_swapoff, need_loop_detach, need_dm_detach;
157 bool in_container, use_watchdog = false;
158 _cleanup_free_ char *cgroup = NULL;
163 log_parse_environment();
164 r = parse_argv(argc, argv);
168 /* journald will die if not gone yet. The log target defaults
169 * to console, but may have been changed by command line options. */
171 log_close_console(); /* force reopen of /dev/console */
177 log_error("Not executed by init (PID 1).");
182 if (streq(arg_verb, "reboot"))
184 else if (streq(arg_verb, "poweroff"))
186 else if (streq(arg_verb, "halt"))
187 cmd = RB_HALT_SYSTEM;
188 else if (streq(arg_verb, "kexec"))
189 cmd = LINUX_REBOOT_CMD_KEXEC;
192 log_error("Unknown action '%s'.", arg_verb);
196 cg_get_root_path(&cgroup);
198 use_watchdog = !!getenv("WATCHDOG_USEC");
200 /* lock us into memory */
201 mlockall(MCL_CURRENT|MCL_FUTURE);
203 log_info("Sending SIGTERM to remaining processes...");
204 broadcast_signal(SIGTERM, true, true);
206 log_info("Sending SIGKILL to remaining processes...");
207 broadcast_signal(SIGKILL, true, false);
209 in_container = detect_container(NULL) > 0;
211 need_umount = !in_container;
212 need_swapoff = !in_container;
213 need_loop_detach = !in_container;
214 need_dm_detach = !in_container;
216 /* Unmount all mountpoints, swaps, and loopback devices */
217 for (retries = 0; retries < FINALIZE_ATTEMPTS; retries++) {
218 bool changed = false;
223 /* Let's trim the cgroup tree on each iteration so
224 that we leave an empty cgroup tree around, so that
225 container managers get a nice notify event when we
228 cg_trim(SYSTEMD_CGROUP_CONTROLLER, cgroup, false);
231 log_info("Unmounting file systems.");
232 r = umount_all(&changed);
235 log_info("All filesystems unmounted.");
237 log_info("Not all file systems unmounted, %d left.", r);
239 log_error_errno(r, "Failed to unmount file systems: %m");
243 log_info("Deactivating swaps.");
244 r = swapoff_all(&changed);
246 need_swapoff = false;
247 log_info("All swaps deactivated.");
249 log_info("Not all swaps deactivated, %d left.", r);
251 log_error_errno(r, "Failed to deactivate swaps: %m");
254 if (need_loop_detach) {
255 log_info("Detaching loop devices.");
256 r = loopback_detach_all(&changed);
258 need_loop_detach = false;
259 log_info("All loop devices detached.");
261 log_info("Not all loop devices detached, %d left.", r);
263 log_error_errno(r, "Failed to detach loop devices: %m");
266 if (need_dm_detach) {
267 log_info("Detaching DM devices.");
268 r = dm_detach_all(&changed);
270 need_dm_detach = false;
271 log_info("All DM devices detached.");
273 log_info("Not all DM devices detached, %d left.", r);
275 log_error_errno(r, "Failed to detach DM devices: %m");
278 if (!need_umount && !need_swapoff && !need_loop_detach && !need_dm_detach) {
280 log_info("All filesystems, swaps, loop devices, DM devices detached.");
285 /* If in this iteration we didn't manage to
286 * unmount/deactivate anything, we simply give up */
288 log_info("Cannot finalize remaining%s%s%s%s continuing.",
289 need_umount ? " file systems," : "",
290 need_swapoff ? " swap devices," : "",
291 need_loop_detach ? " loop devices," : "",
292 need_dm_detach ? " DM devices," : "");
296 log_debug("After %u retries, couldn't finalize remaining %s%s%s%s trying again.",
298 need_umount ? " file systems," : "",
299 need_swapoff ? " swap devices," : "",
300 need_loop_detach ? " loop devices," : "",
301 need_dm_detach ? " DM devices," : "");
304 log_error("Too many iterations, giving up.");
309 arguments[1] = arg_verb;
311 execute_directory(SYSTEM_SHUTDOWN_PATH, NULL, DEFAULT_TIMEOUT_USEC, arguments);
313 if (!in_container && !in_initrd() &&
314 access("/run/initramfs/shutdown", X_OK) == 0) {
315 r = switch_root_initramfs();
317 argv[0] = (char*) "/shutdown";
320 make_console_stdio();
322 log_info("Successfully changed into root pivot.\n"
323 "Returning to initrd...");
325 execv("/shutdown", argv);
326 log_error_errno(errno, "Failed to execute shutdown binary: %m");
328 log_error_errno(r, "Failed to switch root to \"/run/initramfs\": %m");
332 if (need_umount || need_swapoff || need_loop_detach || need_dm_detach)
333 log_error("Failed to finalize %s%s%s%s ignoring",
334 need_umount ? " file systems," : "",
335 need_swapoff ? " swap devices," : "",
336 need_loop_detach ? " loop devices," : "",
337 need_dm_detach ? " DM devices," : "");
339 /* The kernel will automaticall flush ATA disks and suchlike
340 * on reboot(), but the file systems need to be synce'd
341 * explicitly in advance. So let's do this here, but not
342 * needlessly slow down containers. */
348 case LINUX_REBOOT_CMD_KEXEC:
351 /* We cheat and exec kexec to avoid doing all its work */
354 log_info("Rebooting with kexec.");
358 log_error_errno(errno, "Failed to fork: %m");
361 const char * const args[] = {
367 execv(args[0], (char * const *) args);
370 wait_for_terminate_and_warn("kexec", pid, true);
379 _cleanup_free_ char *param = NULL;
381 if (read_one_line_file(REBOOT_PARAM_FILE, ¶m) >= 0) {
382 log_info("Rebooting with argument '%s'.", param);
383 syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART2, param);
387 log_info("Rebooting.");
391 log_info("Powering off.");
395 log_info("Halting system.");
399 assert_not_reached("Unknown magic");
403 if (errno == EPERM && in_container) {
404 /* If we are in a container, and we lacked
405 * CAP_SYS_BOOT just exit, this will kill our
406 * container for good. */
407 log_info("Exiting container.");
411 log_error_errno(errno, "Failed to invoke reboot(): %m");
415 log_emergency_errno(r, "Critical error while doing system shutdown: %m");