39 #include <sys/ioctl.h>
40 #include <linux/types.h>
41 #include <linux/watchdog.h>
42 #include <sys/reboot.h>
79 static int wd_exec_exit_fn (
void);
80 static void wd_resource_check_fn (
void* resource_ref);
83 #define WD_DEFAULT_TIMEOUT_SEC 6
84 #define WD_DEFAULT_TIMEOUT_MS (WD_DEFAULT_TIMEOUT_SEC * CS_TIME_MS_IN_SEC)
85 #define WD_MIN_TIMEOUT_MS 500
86 #define WD_MAX_TIMEOUT_MS (120 * CS_TIME_MS_IN_SEC)
91 static int watchdog_ok = 1;
94 .
name =
"corosync watchdog service",
97 .private_data_size = 0,
102 .lib_engine_count = 0,
104 .exec_engine_count = 0,
106 .exec_init_fn = wd_exec_init_fn,
107 .exec_exit_fn = wd_exec_exit_fn,
116 static void wd_config_changed (
struct cs_fsm* fsm, int32_t event,
void * data);
117 static void wd_resource_failed (
struct cs_fsm* fsm, int32_t event,
void * data);
147 return (&wd_service_engine);
150 static const char * wd_res_state_to_str(
struct cs_fsm* fsm,
167 static const char * wd_res_event_to_str(
struct cs_fsm* fsm,
181 static void wd_fsm_cb (
struct cs_fsm *fsm,
int cb_event, int32_t curr_state,
182 int32_t next_state, int32_t fsm_event,
void *data)
215 static int32_t wd_resource_state_is_ok (
struct resource *ref)
218 uint64_t last_updated;
220 uint64_t allowed_period;
240 if (last_updated == 0) {
246 my_time = cs_timestamp_get();
253 if ((last_updated + allowed_period) < my_time) {
255 "last_updated %"PRIu64
" ms too late, period:%"PRIu64
".",
271 static void wd_config_changed (
struct cs_fsm* fsm, int32_t event,
void * data)
275 uint64_t next_timeout;
285 "poll_period changing from:%"PRIu64
" to %"PRIu64
".",
296 "Could NOT use poll_period:%"PRIu64
" ms for resource %s",
297 tmp_value, ref->
name);
306 "resource %s missing a recovery key.", ref->
name);
315 "resource %s missing a state key.", ref->
name);
334 static void wd_resource_failed (
struct cs_fsm* fsm, int32_t event,
void * data)
345 if (strcmp (ref->
recovery,
"watchdog") == 0 ||
346 strcmp (ref->
recovery,
"quit") == 0) {
349 else if (strcmp (ref->
recovery,
"reboot") == 0) {
352 else if (strcmp (ref->
recovery,
"shutdown") == 0) {
353 reboot(RB_POWER_OFF);
355 cs_fsm_state_set(fsm,
WD_S_FAILED, data, wd_fsm_cb);
358 static void wd_key_changed(
360 const char *key_name,
372 last_key_part = strrchr(key_name,
'.');
373 if (last_key_part == NULL) {
379 if (strcmp(last_key_part,
"last_updated") == 0 ||
380 strcmp(last_key_part,
"current") == 0) {
388 if (strcmp(last_key_part,
"state") != 0) {
393 "resource \"%s\" deleted from cmap!",
404 static void wd_resource_check_fn (
void* resource_ref)
408 if (wd_resource_state_is_ok (ref) ==
CS_FALSE) {
420 static int32_t wd_resource_create (
char *
res_path,
char *res_name)
431 strcpy(ref->
name, res_name);
448 "Could NOT use poll_period:%"PRIu64
" ms for resource %s",
449 tmp_value, ref->
name);
463 "resource %s missing a recovery key.", ref->
name);
471 "resource %s missing a state key.", ref->
name);
497 static void wd_tickle_fn (
void* arg)
503 ioctl(dog, WDIOC_KEEPALIVE, &watchdog_ok);
506 wd_tickle_fn, &wd_timer);
514 static void wd_resource_created_cb(
516 const char *key_name,
530 res = sscanf(key_name,
"resources.%[^.].%[^.].%[^.]", res_type, res_name, tmp_key);
535 if (strcmp(tmp_key,
"state") != 0) {
540 wd_resource_create (tmp_key, res_name);
543 static void wd_scan_resources (
void)
548 const char *key_name;
558 res = sscanf(key_name,
"resources.%[^.].%[^.].%[^.]", res_type, res_name, tmp_key);
563 if (strcmp(tmp_key,
"state") != 0) {
568 if (wd_resource_create (tmp_key, res_name) == 0) {
575 wd_resource_created_cb, NULL, &icmap_track);
577 wd_resource_created_cb, NULL, &icmap_track);
579 if (res_count == 0) {
585 static void watchdog_timeout_apply (uint32_t
new)
587 struct watchdog_info ident;
588 uint32_t original_timeout = watchdog_timeout;
590 if (
new == original_timeout) {
594 watchdog_timeout =
new;
597 ioctl(dog, WDIOC_GETSUPPORT, &ident);
598 if (ident.options & WDIOF_SETTIMEOUT) {
601 ioctl(dog, WDIOC_SETTIMEOUT, &watchdog_timeout);
603 ioctl(dog, WDIOC_GETTIMEOUT, &watchdog_timeout);
606 if (watchdog_timeout ==
new) {
613 wd_tickle_fn, &wd_timer);
619 "Could not change the Watchdog timeout from %d to %d seconds",
620 original_timeout,
new);
625 static int setup_watchdog(
void)
627 struct watchdog_info ident;
630 if (access (
"/dev/watchdog", W_OK) != 0) {
638 dog = open(
"/dev/watchdog", O_WRONLY);
650 ioctl(dog, WDIOC_GETSUPPORT, &ident);
654 watchdog_timeout_apply (watchdog_timeout);
656 ioctl(dog, WDIOC_SETOPTIONS, WDIOS_ENABLECARD);
661 static void wd_top_level_key_changed(
663 const char *key_name,
668 uint32_t tmp_value_32;
673 if (tmp_value_32 >= 2 && tmp_value_32 <= 120) {
674 watchdog_timeout_apply (tmp_value_32);
682 static void watchdog_timeout_get_initial (
void)
684 uint32_t tmp_value_32;
695 if (tmp_value_32 >= 2 && tmp_value_32 <= 120) {
696 watchdog_timeout_apply (tmp_value_32);
703 wd_top_level_key_changed, NULL, &icmap_track);
714 watchdog_timeout_get_initial();
721 wd_tickle_fn, &wd_timer);
726 static int wd_exec_exit_fn (
void)
733 write (dog, &magic, 1);
const char * wd_running_str
const char * icmap_iter_next(icmap_iter_t iter, size_t *value_len, icmap_value_types_t *type)
#define LOGSYS_LEVEL_INFO
const char * wd_config_changed_str
void(* timer_delete)(corosync_timer_handle_t timer_handle)
const char * wd_failed_str
void icmap_iter_finalize(icmap_iter_t iter)
int(* timer_add_duration)(unsigned long long nanoseconds_in_future, void *data, void(*timer_nf)(void *data), corosync_timer_handle_t *handle)
#define corosync_exit_error(err)
#define WD_DEFAULT_TIMEOUT_SEC
cs_fsm_event_to_str_fn event_to_str
#define log_printf(level, format, args...)
corosync_timer_handle_t check_timer
#define ICMAP_TRACK_DELETE
#define ICMAP_KEYNAME_MAXLEN
const char * wd_failure_str
char res_path[ICMAP_KEYNAME_MAXLEN]
#define LOGSYS_LEVEL_WARNING
#define ICMAP_TRACK_MODIFY
struct corosync_service_engine * wd_get_service_engine_ver0(void)
cs_error_t icmap_set_uint32(const char *key_name, uint32_t value)
icmap_track_t icmap_track
struct corosync_service_engine wd_service_engine
#define LOGSYS_LEVEL_ERROR
#define DECLARE_LIST_INIT(name)
cs_error_t icmap_track_delete(icmap_track_t icmap_track)
#define LOGSYS_LEVEL_DEBUG
char name[CS_MAX_NAME_LENGTH]
#define CS_FSM_CB_EVENT_STATE_SET
cs_error_t icmap_get_uint32(const char *key_name, uint32_t *u32)
struct cs_fsm_entry wd_fsm_table[]
#define WD_MAX_TIMEOUT_MS
cs_error_t icmap_set_uint64(const char *key_name, uint64_t value)
cs_fsm_state_to_str_fn state_to_str
#define MILLI_2_NANO_SECONDS
#define CS_FSM_CB_EVENT_PROCESS_NF
cs_error_t icmap_get_uint64(const char *key_name, uint64_t *u64)
#define WD_DEFAULT_TIMEOUT_MS
#define CS_FSM_CB_EVENT_STATE_SET_NF
#define CS_MAX_NAME_LENGTH
#define WD_MIN_TIMEOUT_MS
qb_loop_timer_handle corosync_timer_handle_t
cs_error_t icmap_get_string(const char *key_name, char **str)
#define LOGSYS_LEVEL_CRIT
#define LOGSYS_LEVEL_ALERT
#define CS_TIME_MS_IN_SEC
struct cs_fsm_entry * table
icmap_iter_t icmap_iter_init(const char *prefix)
qb_map_iter_t * icmap_iter_t
const char * wd_stopped_str
cs_error_t icmap_track_add(const char *key_name, int32_t track_type, icmap_notify_fn_t notify_fn, void *user_data, icmap_track_t *icmap_track)
LOGSYS_DECLARE_SUBSYS("WD")
#define ICMAP_TRACK_PREFIX