This source file includes following definitions.
- sysrq_trigger
- panic_local
- panic_sbd
- pcmk__panic
- pcmk__locate_sbd
- pcmk__get_sbd_timeout
- pcmk__get_sbd_sync_resource_startup
- pcmk__auto_watchdog_timeout
- pcmk__valid_sbd_timeout
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #include <sched.h>
13 #include <sys/ioctl.h>
14 #include <sys/reboot.h>
15
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #include <unistd.h>
19 #include <ctype.h>
20 #include <dirent.h>
21 #include <signal.h>
22
23 #ifdef _POSIX_MEMLOCK
24 # include <sys/mman.h>
25 #endif
26
27 static pid_t sbd_pid = 0;
28
29 static void
30 sysrq_trigger(char t)
31 {
32 #if HAVE_LINUX_PROCFS
33 FILE *procf;
34
35
36 procf = fopen("/proc/sysrq-trigger", "a");
37 if (!procf) {
38 crm_perror(LOG_WARNING, "Opening sysrq-trigger failed");
39 return;
40 }
41 crm_info("sysrq-trigger: %c", t);
42 fprintf(procf, "%c\n", t);
43 fclose(procf);
44 #endif
45 return;
46 }
47
48
49
50
51
52
53 static void
54 panic_local(void)
55 {
56 int rc = pcmk_ok;
57 uid_t uid = geteuid();
58 pid_t ppid = getppid();
59
60 if(uid != 0 && ppid > 1) {
61
62
63
64
65
66
67 crm_emerg("Signaling parent %lld to panic", (long long) ppid);
68 crm_exit(CRM_EX_PANIC);
69 return;
70
71 } else if (uid != 0) {
72 #if HAVE_LINUX_PROCFS
73
74
75
76
77 union sigval signal_value;
78
79 memset(&signal_value, 0, sizeof(signal_value));
80 ppid = pcmk__procfs_pid_of("pacemakerd");
81 crm_emerg("Signaling pacemakerd[%lld] to panic", (long long) ppid);
82
83 if(ppid > 1 && sigqueue(ppid, SIGQUIT, signal_value) < 0) {
84 crm_perror(LOG_EMERG, "Cannot signal pacemakerd[%lld] to panic",
85 (long long) ppid);
86 }
87 #endif
88
89
90 crm_exit(CRM_EX_PANIC);
91 return;
92 }
93
94
95
96 if (pcmk__str_eq("crash", getenv("PCMK_panic_action"), pcmk__str_casei)) {
97 sysrq_trigger('c');
98 } else if (pcmk__str_eq("sync-crash", getenv("PCMK_panic_action"), pcmk__str_casei)) {
99 sync();
100 sysrq_trigger('c');
101 } else {
102 if (pcmk__str_eq("sync-reboot", getenv("PCMK_panic_action"), pcmk__str_casei)) {
103 sync();
104 }
105 sysrq_trigger('b');
106 }
107
108 reboot(RB_AUTOBOOT);
109 rc = errno;
110
111 crm_emerg("Reboot failed, escalating to parent %lld: %s " CRM_XS " rc=%d",
112 (long long) ppid, pcmk_rc_str(rc), rc);
113
114 if(ppid > 1) {
115
116 exit(CRM_EX_PANIC);
117 } else {
118
119 exit(CRM_EX_FATAL);
120 }
121 }
122
123
124
125
126
127 static void
128 panic_sbd(void)
129 {
130 union sigval signal_value;
131 pid_t ppid = getppid();
132
133 crm_emerg("Signaling sbd[%lld] to panic", (long long) sbd_pid);
134
135 memset(&signal_value, 0, sizeof(signal_value));
136
137 if(sigqueue(sbd_pid, SIGKILL, signal_value) < 0) {
138 crm_perror(LOG_EMERG, "Cannot signal sbd[%lld] to terminate",
139 (long long) sbd_pid);
140 panic_local();
141 }
142
143 if(ppid > 1) {
144
145 exit(CRM_EX_PANIC);
146 } else {
147
148 exit(CRM_EX_FATAL);
149 }
150 }
151
152
153
154
155
156
157
158
159
160
161 void
162 pcmk__panic(const char *origin)
163 {
164
165 (void) pcmk__locate_sbd();
166
167 pcmk__if_tracing(
168 {
169
170 crm_emerg("Shutting down instead of panicking the node "
171 CRM_XS " origin=%s sbd=%lld parent=%d",
172 origin, (long long) sbd_pid, getppid());
173 crm_exit(CRM_EX_FATAL);
174 return;
175 },
176 {}
177 );
178
179 if(sbd_pid > 1) {
180 crm_emerg("Signaling sbd[%lld] to panic the system: %s",
181 (long long) sbd_pid, origin);
182 panic_sbd();
183
184 } else {
185 crm_emerg("Panicking the system directly: %s", origin);
186 panic_local();
187 }
188 }
189
190
191
192
193
194 pid_t
195 pcmk__locate_sbd(void)
196 {
197 char *pidfile = NULL;
198 char *sbd_path = NULL;
199 int rc;
200
201 if(sbd_pid > 1) {
202 return sbd_pid;
203 }
204
205
206 pidfile = crm_strdup_printf(PCMK_RUN_DIR "/sbd.pid");
207 sbd_path = crm_strdup_printf("%s/sbd", SBIN_DIR);
208
209
210 rc = pcmk__pidfile_matches(pidfile, 0, sbd_path, &sbd_pid);
211 if (rc == pcmk_rc_ok) {
212 crm_trace("SBD detected at pid %lld (via PID file %s)",
213 (long long) sbd_pid, pidfile);
214
215 #if HAVE_LINUX_PROCFS
216 } else {
217
218 sbd_pid = pcmk__procfs_pid_of("sbd");
219 crm_trace("SBD detected at pid %lld (via procfs)",
220 (long long) sbd_pid);
221 #endif
222 }
223
224 if(sbd_pid < 0) {
225 sbd_pid = 0;
226 crm_trace("SBD not detected");
227 }
228
229 free(pidfile);
230 free(sbd_path);
231
232 return sbd_pid;
233 }
234
235 long
236 pcmk__get_sbd_timeout(void)
237 {
238 static long sbd_timeout = -2;
239
240 if (sbd_timeout == -2) {
241 sbd_timeout = crm_get_msec(getenv("SBD_WATCHDOG_TIMEOUT"));
242 }
243 return sbd_timeout;
244 }
245
246 bool
247 pcmk__get_sbd_sync_resource_startup(void)
248 {
249 static int sync_resource_startup = PCMK__SBD_SYNC_DEFAULT;
250 static bool checked_sync_resource_startup = false;
251
252 if (!checked_sync_resource_startup) {
253 const char *sync_env = getenv("SBD_SYNC_RESOURCE_STARTUP");
254
255 if (sync_env == NULL) {
256 crm_trace("Defaulting to %sstart-up synchronization with sbd",
257 (PCMK__SBD_SYNC_DEFAULT? "" : "no "));
258
259 } else if (crm_str_to_boolean(sync_env, &sync_resource_startup) < 0) {
260 crm_warn("Defaulting to %sstart-up synchronization with sbd "
261 "because environment value '%s' is invalid",
262 (PCMK__SBD_SYNC_DEFAULT? "" : "no "), sync_env);
263 }
264 checked_sync_resource_startup = true;
265 }
266 return sync_resource_startup != 0;
267 }
268
269 long
270 pcmk__auto_watchdog_timeout(void)
271 {
272 long sbd_timeout = pcmk__get_sbd_timeout();
273
274 return (sbd_timeout <= 0)? 0 : (2 * sbd_timeout);
275 }
276
277 bool
278 pcmk__valid_sbd_timeout(const char *value)
279 {
280 long st_timeout = value? crm_get_msec(value) : 0;
281
282 if (st_timeout < 0) {
283 st_timeout = pcmk__auto_watchdog_timeout();
284 crm_debug("Using calculated value %ld for stonith-watchdog-timeout (%s)",
285 st_timeout, value);
286 }
287
288 if (st_timeout == 0) {
289 crm_debug("Watchdog may be enabled but stonith-watchdog-timeout is disabled (%s)",
290 value? value : "default");
291
292 } else if (pcmk__locate_sbd() == 0) {
293 crm_emerg("Shutting down: stonith-watchdog-timeout configured (%s) "
294 "but SBD not active", (value? value : "auto"));
295 crm_exit(CRM_EX_FATAL);
296 return false;
297
298 } else {
299 long sbd_timeout = pcmk__get_sbd_timeout();
300
301 if (st_timeout < sbd_timeout) {
302 crm_emerg("Shutting down: stonith-watchdog-timeout (%s) too short "
303 "(must be >%ldms)", value, sbd_timeout);
304 crm_exit(CRM_EX_FATAL);
305 return false;
306 }
307 crm_info("Watchdog configured with stonith-watchdog-timeout %s and SBD timeout %ldms",
308 value, sbd_timeout);
309 }
310 return true;
311 }