]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/emergency-action.c
Merge pull request #13905 from poettering/cpuset-fixes
[thirdparty/systemd.git] / src / core / emergency-action.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
2928b0a8
LP
2
3#include <sys/reboot.h>
2928b0a8 4
2928b0a8 5#include "bus-error.h"
8b43440b 6#include "bus-util.h"
87a47f99 7#include "emergency-action.h"
c52a937b 8#include "raw-reboot.h"
e3631d1c 9#include "reboot-util.h"
8b43440b
LP
10#include "special.h"
11#include "string-table.h"
288a74cc 12#include "terminal-util.h"
a400bd8c 13#include "virt.h"
2928b0a8 14
c7adcb1a
ZJS
15static void log_and_status(Manager *m, bool warn, const char *message, const char *reason) {
16 log_full(warn ? LOG_WARNING : LOG_DEBUG, "%s: %s", message, reason);
17 if (warn)
18 manager_status_printf(m, STATUS_TYPE_EMERGENCY,
19 ANSI_HIGHLIGHT_RED " !! " ANSI_NORMAL,
20 "%s: %s", message, reason);
ebc5788e
ZJS
21}
22
36c4dc08 23void emergency_action(
2928b0a8 24 Manager *m,
87a47f99 25 EmergencyAction action,
1710d4be 26 EmergencyActionFlags options,
87a47f99 27 const char *reboot_arg,
7af67e9a 28 int exit_status,
87a47f99 29 const char *reason) {
2928b0a8 30
2928b0a8
LP
31 assert(m);
32 assert(action >= 0);
87a47f99 33 assert(action < _EMERGENCY_ACTION_MAX);
2928b0a8 34
87a47f99 35 if (action == EMERGENCY_ACTION_NONE)
36c4dc08 36 return;
2928b0a8 37
1710d4be 38 if (FLAGS_SET(options, EMERGENCY_ACTION_IS_WATCHDOG) && !m->service_watchdogs) {
2a12e32e 39 log_warning("Watchdog disabled! Not acting on: %s", reason);
36c4dc08 40 return;
2a12e32e
JK
41 }
42
c7adcb1a
ZJS
43 bool warn = FLAGS_SET(options, EMERGENCY_ACTION_WARN);
44
f07756bf 45 switch (action) {
2928b0a8 46
87a47f99 47 case EMERGENCY_ACTION_REBOOT:
c7adcb1a 48 log_and_status(m, warn, "Rebooting", reason);
2928b0a8 49
77defcf5 50 (void) update_reboot_parameter_and_warn(reboot_arg, true);
50cbaba4 51 (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_REBOOT_TARGET, JOB_REPLACE_IRREVERSIBLY, NULL, NULL);
2928b0a8 52 break;
2928b0a8 53
87a47f99 54 case EMERGENCY_ACTION_REBOOT_FORCE:
c7adcb1a 55 log_and_status(m, warn, "Forcibly rebooting", reason);
ebc5788e 56
77defcf5 57 (void) update_reboot_parameter_and_warn(reboot_arg, true);
af41e508 58 m->objective = MANAGER_REBOOT;
27c06cb5 59
2928b0a8
LP
60 break;
61
87a47f99 62 case EMERGENCY_ACTION_REBOOT_IMMEDIATE:
c7adcb1a 63 log_and_status(m, warn, "Rebooting immediately", reason);
2928b0a8
LP
64
65 sync();
66
27c06cb5 67 if (!isempty(reboot_arg)) {
2928b0a8 68 log_info("Rebooting with argument '%s'.", reboot_arg);
c52a937b 69 (void) raw_reboot(LINUX_REBOOT_CMD_RESTART2, reboot_arg);
27c06cb5 70 log_warning_errno(errno, "Failed to reboot with parameter, retrying without: %m");
2928b0a8
LP
71 }
72
73 log_info("Rebooting.");
118cf952 74 (void) reboot(RB_AUTOBOOT);
2928b0a8
LP
75 break;
76
54fcb619 77 case EMERGENCY_ACTION_EXIT:
7af67e9a
LP
78
79 if (exit_status >= 0)
80 m->return_value = exit_status;
81
a400bd8c 82 if (MANAGER_IS_USER(m) || detect_container() > 0) {
c7adcb1a 83 log_and_status(m, warn, "Exiting", reason);
50cbaba4 84 (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_EXIT_TARGET, JOB_REPLACE_IRREVERSIBLY, NULL, NULL);
a400bd8c
ZJS
85 break;
86 }
54fcb619 87
a400bd8c
ZJS
88 log_notice("Doing \"poweroff\" action instead of an \"exit\" emergency action.");
89 _fallthrough_;
54fcb619 90
87a47f99 91 case EMERGENCY_ACTION_POWEROFF:
c7adcb1a 92 log_and_status(m, warn, "Powering off", reason);
50cbaba4 93 (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_POWEROFF_TARGET, JOB_REPLACE_IRREVERSIBLY, NULL, NULL);
f07756bf 94 break;
f07756bf 95
54fcb619 96 case EMERGENCY_ACTION_EXIT_FORCE:
7af67e9a
LP
97
98 if (exit_status >= 0)
99 m->return_value = exit_status;
100
a400bd8c 101 if (MANAGER_IS_USER(m) || detect_container() > 0) {
c7adcb1a 102 log_and_status(m, warn, "Exiting immediately", reason);
a400bd8c
ZJS
103 m->objective = MANAGER_EXIT;
104 break;
105 }
54fcb619 106
a400bd8c
ZJS
107 log_notice("Doing \"poweroff-force\" action instead of an \"exit-force\" emergency action.");
108 _fallthrough_;
54fcb619 109
87a47f99 110 case EMERGENCY_ACTION_POWEROFF_FORCE:
c7adcb1a 111 log_and_status(m, warn, "Forcibly powering off", reason);
af41e508 112 m->objective = MANAGER_POWEROFF;
f07756bf
LP
113 break;
114
87a47f99 115 case EMERGENCY_ACTION_POWEROFF_IMMEDIATE:
c7adcb1a 116 log_and_status(m, warn, "Powering off immediately", reason);
f07756bf
LP
117
118 sync();
119
120 log_info("Powering off.");
118cf952 121 (void) reboot(RB_POWER_OFF);
f07756bf
LP
122 break;
123
2928b0a8 124 default:
87a47f99 125 assert_not_reached("Unknown emergency action");
2928b0a8 126 }
2928b0a8
LP
127}
128
87a47f99
LN
129static const char* const emergency_action_table[_EMERGENCY_ACTION_MAX] = {
130 [EMERGENCY_ACTION_NONE] = "none",
131 [EMERGENCY_ACTION_REBOOT] = "reboot",
132 [EMERGENCY_ACTION_REBOOT_FORCE] = "reboot-force",
133 [EMERGENCY_ACTION_REBOOT_IMMEDIATE] = "reboot-immediate",
134 [EMERGENCY_ACTION_POWEROFF] = "poweroff",
135 [EMERGENCY_ACTION_POWEROFF_FORCE] = "poweroff-force",
54fcb619
ZJS
136 [EMERGENCY_ACTION_POWEROFF_IMMEDIATE] = "poweroff-immediate",
137 [EMERGENCY_ACTION_EXIT] = "exit",
138 [EMERGENCY_ACTION_EXIT_FORCE] = "exit-force",
2928b0a8 139};
87a47f99 140DEFINE_STRING_TABLE_LOOKUP(emergency_action, EmergencyAction);
54fcb619
ZJS
141
142int parse_emergency_action(
143 const char *value,
144 bool system,
145 EmergencyAction *ret) {
146
147 EmergencyAction x;
148
149 x = emergency_action_from_string(value);
150 if (x < 0)
151 return -EINVAL;
152
a400bd8c 153 if (!system && x != EMERGENCY_ACTION_NONE && x < _EMERGENCY_ACTION_FIRST_USER_ACTION)
54fcb619
ZJS
154 return -EOPNOTSUPP;
155
156 *ret = x;
157 return 0;
158}