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/reboot.h>
24 #include <linux/reboot.h>
26 #include <sys/mount.h>
42 #include "cgroup-util.h"
44 #include "switch-root.h"
46 #define FINALIZE_ATTEMPTS 50
48 static char* arg_verb;
50 static int parse_argv(int argc, char *argv[]) {
52 ARG_LOG_LEVEL = 0x100,
58 static const struct option options[] = {
59 { "log-level", required_argument, NULL, ARG_LOG_LEVEL },
60 { "log-target", required_argument, NULL, ARG_LOG_TARGET },
61 { "log-color", optional_argument, NULL, ARG_LOG_COLOR },
62 { "log-location", optional_argument, NULL, ARG_LOG_LOCATION },
71 /* "-" prevents getopt from permuting argv[] and moving the verb away
72 * from argv[1]. Our interface to initrd promises it'll be there. */
73 while ((c = getopt_long(argc, argv, "-", options, NULL)) >= 0)
77 r = log_set_max_level_from_string(optarg);
79 log_error("Failed to parse log level %s, ignoring.", optarg);
84 r = log_set_target_from_string(optarg);
86 log_error("Failed to parse log target %s, ignoring", optarg);
93 r = log_show_color_from_string(optarg);
95 log_error("Failed to parse log color setting %s, ignoring", optarg);
101 case ARG_LOG_LOCATION:
103 r = log_show_location_from_string(optarg);
105 log_error("Failed to parse log location setting %s, ignoring", optarg);
107 log_show_location(true);
115 log_error("Excess arguments, ignoring");
122 assert_not_reached("Unhandled option code.");
126 log_error("Verb argument missing.");
133 static int switch_root_initramfs(void) {
134 if (mount("/run/initramfs", "/run/initramfs", NULL, MS_BIND, NULL) < 0)
135 return log_error_errno(errno, "Failed to mount bind /run/initramfs on /run/initramfs: %m");
137 if (mount(NULL, "/run/initramfs", NULL, MS_PRIVATE, NULL) < 0)
138 return log_error_errno(errno, "Failed to make /run/initramfs private mount: %m");
140 /* switch_root with MS_BIND, because there might still be processes lurking around, which have open file descriptors.
141 * /run/initramfs/shutdown will take care of these.
142 * Also do not detach the old root, because /run/initramfs/shutdown needs to access it.
144 return switch_root("/run/initramfs", "/oldroot", false, MS_BIND);
148 int main(int argc, char *argv[]) {
149 bool need_umount, need_swapoff, need_loop_detach, need_dm_detach;
150 bool in_container, use_watchdog = false;
151 _cleanup_free_ char *cgroup = NULL;
155 static const char* const dirs[] = {SYSTEM_SHUTDOWN_PATH, NULL};
157 log_parse_environment();
158 r = parse_argv(argc, argv);
162 /* journald will die if not gone yet. The log target defaults
163 * to console, but may have been changed by command line options. */
165 log_close_console(); /* force reopen of /dev/console */
171 log_error("Not executed by init (PID 1).");
176 if (streq(arg_verb, "reboot"))
178 else if (streq(arg_verb, "poweroff"))
180 else if (streq(arg_verb, "halt"))
181 cmd = RB_HALT_SYSTEM;
182 else if (streq(arg_verb, "kexec"))
183 cmd = LINUX_REBOOT_CMD_KEXEC;
186 log_error("Unknown action '%s'.", arg_verb);
190 cg_get_root_path(&cgroup);
192 use_watchdog = !!getenv("WATCHDOG_USEC");
194 /* lock us into memory */
195 mlockall(MCL_CURRENT|MCL_FUTURE);
197 log_info("Sending SIGTERM to remaining processes...");
198 broadcast_signal(SIGTERM, true, true);
200 log_info("Sending SIGKILL to remaining processes...");
201 broadcast_signal(SIGKILL, true, false);
203 in_container = detect_container(NULL) > 0;
205 need_umount = !in_container;
206 need_swapoff = !in_container;
207 need_loop_detach = !in_container;
208 need_dm_detach = !in_container;
210 /* Unmount all mountpoints, swaps, and loopback devices */
211 for (retries = 0; retries < FINALIZE_ATTEMPTS; retries++) {
212 bool changed = false;
217 /* Let's trim the cgroup tree on each iteration so
218 that we leave an empty cgroup tree around, so that
219 container managers get a nice notify event when we
222 cg_trim(SYSTEMD_CGROUP_CONTROLLER, cgroup, false);
225 log_info("Unmounting file systems.");
226 r = umount_all(&changed);
229 log_info("All filesystems unmounted.");
231 log_info("Not all file systems unmounted, %d left.", r);
233 log_error_errno(r, "Failed to unmount file systems: %m");
237 log_info("Deactivating swaps.");
238 r = swapoff_all(&changed);
240 need_swapoff = false;
241 log_info("All swaps deactivated.");
243 log_info("Not all swaps deactivated, %d left.", r);
245 log_error_errno(r, "Failed to deactivate swaps: %m");
248 if (need_loop_detach) {
249 log_info("Detaching loop devices.");
250 r = loopback_detach_all(&changed);
252 need_loop_detach = false;
253 log_info("All loop devices detached.");
255 log_info("Not all loop devices detached, %d left.", r);
257 log_error_errno(r, "Failed to detach loop devices: %m");
260 if (need_dm_detach) {
261 log_info("Detaching DM devices.");
262 r = dm_detach_all(&changed);
264 need_dm_detach = false;
265 log_info("All DM devices detached.");
267 log_info("Not all DM devices detached, %d left.", r);
269 log_error_errno(r, "Failed to detach DM devices: %m");
272 if (!need_umount && !need_swapoff && !need_loop_detach && !need_dm_detach) {
274 log_info("All filesystems, swaps, loop devices, DM devices detached.");
279 /* If in this iteration we didn't manage to
280 * unmount/deactivate anything, we simply give up */
282 log_info("Cannot finalize remaining%s%s%s%s continuing.",
283 need_umount ? " file systems," : "",
284 need_swapoff ? " swap devices," : "",
285 need_loop_detach ? " loop devices," : "",
286 need_dm_detach ? " DM devices," : "");
290 log_debug("After %u retries, couldn't finalize remaining %s%s%s%s trying again.",
292 need_umount ? " file systems," : "",
293 need_swapoff ? " swap devices," : "",
294 need_loop_detach ? " loop devices," : "",
295 need_dm_detach ? " DM devices," : "");
298 log_error("Too many iterations, giving up.");
303 arguments[1] = arg_verb;
305 execute_directories(dirs, DEFAULT_TIMEOUT_USEC, arguments);
307 if (!in_container && !in_initrd() &&
308 access("/run/initramfs/shutdown", X_OK) == 0) {
309 r = switch_root_initramfs();
311 argv[0] = (char*) "/shutdown";
314 make_console_stdio();
316 log_info("Successfully changed into root pivot.\n"
317 "Returning to initrd...");
319 execv("/shutdown", argv);
320 log_error_errno(errno, "Failed to execute shutdown binary: %m");
322 log_error_errno(r, "Failed to switch root to \"/run/initramfs\": %m");
326 if (need_umount || need_swapoff || need_loop_detach || need_dm_detach)
327 log_error("Failed to finalize %s%s%s%s ignoring",
328 need_umount ? " file systems," : "",
329 need_swapoff ? " swap devices," : "",
330 need_loop_detach ? " loop devices," : "",
331 need_dm_detach ? " DM devices," : "");
333 /* The kernel will automaticall flush ATA disks and suchlike
334 * on reboot(), but the file systems need to be synce'd
335 * explicitly in advance. So let's do this here, but not
336 * needlessly slow down containers. */
342 case LINUX_REBOOT_CMD_KEXEC:
345 /* We cheat and exec kexec to avoid doing all its work */
348 log_info("Rebooting with kexec.");
352 log_error_errno(errno, "Failed to fork: %m");
355 const char * const args[] = {
361 execv(args[0], (char * const *) args);
364 wait_for_terminate_and_warn("kexec", pid, true);
373 _cleanup_free_ char *param = NULL;
375 if (read_one_line_file(REBOOT_PARAM_FILE, ¶m) >= 0) {
376 log_info("Rebooting with argument '%s'.", param);
377 syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART2, param);
381 log_info("Rebooting.");
385 log_info("Powering off.");
389 log_info("Halting system.");
393 assert_not_reached("Unknown magic");
397 if (errno == EPERM && in_container) {
398 /* If we are in a container, and we lacked
399 * CAP_SYS_BOOT just exit, this will kill our
400 * container for good. */
401 log_info("Exiting container.");
405 log_error_errno(errno, "Failed to invoke reboot(): %m");
409 log_emergency_errno(r, "Critical error while doing system shutdown: %m");