From: Zhang Chen <chen.zh...@intel.com> This patch load pulse_timer and timeout_timer in the new iothread. The pulse timer will send pulse info to awd_node, and the timeout timer will check the reply pulse from awd_node. If timeout occur, it will send opt_script's data to the notification_node.
Signed-off-by: Zhang Chen <chen.zh...@intel.com> --- net/awd.c | 193 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 193 insertions(+) diff --git a/net/awd.c b/net/awd.c index ad3d39c982..04f40e7cc8 100644 --- a/net/awd.c +++ b/net/awd.c @@ -40,17 +40,137 @@ typedef struct AwdState { char *awd_node; char *notification_node; char *opt_script; + char *opt_script_data; uint32_t pulse_interval; uint32_t timeout; CharBackend chr_awd_node; CharBackend chr_notification_node; + SocketReadState awd_rs; + + QEMUTimer *pulse_timer; + QEMUTimer *timeout_timer; IOThread *iothread; + GMainContext *worker_context; } AwdState; typedef struct AwdClass { ObjectClass parent_class; } AwdClass; +static int awd_chr_send(AwdState *s, + const uint8_t *buf, + uint32_t size) +{ + int ret = 0; + uint32_t len = htonl(size); + + if (!size) { + return 0; + } + + ret = qemu_chr_fe_write_all(&s->chr_awd_node, (uint8_t *)&len, + sizeof(len)); + if (ret != sizeof(len)) { + goto err; + } + + ret = qemu_chr_fe_write_all(&s->chr_awd_node, (uint8_t *)buf, + size); + if (ret != size) { + goto err; + } + + return 0; + +err: + return ret < 0 ? ret : -EIO; +} + +static int awd_chr_can_read(void *opaque) +{ + return AWD_READ_LEN_MAX; +} + +static void awd_node_in(void *opaque, const uint8_t *buf, int size) +{ + AwdState *s = AWD(opaque); + int ret; + + ret = net_fill_rstate(&s->awd_rs, buf, size); + if (ret == -1) { + qemu_chr_fe_set_handlers(&s->chr_awd_node, NULL, NULL, NULL, NULL, + NULL, NULL, true); + error_report("advanced-watchdog get pulse error"); + } +} + +static void awd_send_pulse(void *opaque) +{ + AwdState *s = opaque; + char buf[] = "advanced-watchdog pulse"; + + awd_chr_send(s, (uint8_t *)buf, sizeof(buf)); +} + +static void awd_regular_pulse(void *opaque) +{ + AwdState *s = opaque; + + awd_send_pulse(s); + timer_mod(s->pulse_timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + + s->pulse_interval); +} + +static void awd_timeout(void *opaque) +{ + AwdState *s = opaque; + int ret = 0; + + ret = qemu_chr_fe_write_all(&s->chr_notification_node, + (uint8_t *)s->opt_script_data, + strlen(s->opt_script_data)); + if (ret) { + error_report("advanced-watchdog notification failure"); + } +} + +static void awd_timer_init(AwdState *s) +{ + AioContext *ctx = iothread_get_aio_context(s->iothread); + + s->timeout_timer = aio_timer_new(ctx, QEMU_CLOCK_VIRTUAL, SCALE_MS, + awd_timeout, s); + + s->pulse_timer = aio_timer_new(ctx, QEMU_CLOCK_VIRTUAL, SCALE_MS, + awd_regular_pulse, s); + + if (!s->pulse_interval) { + s->pulse_interval = AWD_PULSE_INTERVAL_DEFAULT; + } + + if (!s->timeout) { + s->timeout = AWD_TIMEOUT_DEFAULT; + } + + timer_mod(s->pulse_timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + + s->pulse_interval); +} + +static void awd_timer_del(AwdState *s) +{ + if (s->pulse_timer) { + timer_del(s->pulse_timer); + timer_free(s->pulse_timer); + s->pulse_timer = NULL; + } + + if (s->timeout_timer) { + timer_del(s->timeout_timer); + timer_free(s->timeout_timer); + s->timeout_timer = NULL; + } + } + static char *awd_get_node(Object *obj, Error **errp) { AwdState *s = AWD(obj); @@ -177,6 +297,22 @@ out: error_propagate(errp, local_err); } +static void awd_rs_finalize(SocketReadState *awd_rs) +{ + AwdState *s = container_of(awd_rs, AwdState, awd_rs); + + if (!s->server) { + char buf[] = "advanced-watchdog reply pulse"; + + awd_chr_send(s, (uint8_t *)buf, sizeof(buf)); + } + + timer_mod(s->timeout_timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + + s->timeout); + + error_report("advanced-watchdog got message : %s", awd_rs->buf); +} + static int find_and_check_chardev(Chardev **chr, char *chr_name, Error **errp) @@ -197,6 +333,46 @@ static int find_and_check_chardev(Chardev **chr, return 0; } +static void awd_iothread(AwdState *s) +{ + object_ref(OBJECT(s->iothread)); + s->worker_context = iothread_get_g_main_context(s->iothread); + + qemu_chr_fe_set_handlers(&s->chr_awd_node, awd_chr_can_read, + awd_node_in, NULL, NULL, + s, s->worker_context, true); + + awd_timer_init(s); +} + +static int get_opt_script_data(AwdState *s) +{ + FILE *opt_fd; + long fsize; + + opt_fd = fopen(s->opt_script, "r"); + if (opt_fd == NULL) { + error_report("advanced-watchdog can't open " + "opt_script: %s", s->opt_script); + return -1; + } + + fseek(opt_fd, 0, SEEK_END); + fsize = ftell(opt_fd); + fseek(opt_fd, 0, SEEK_SET); + s->opt_script_data = malloc(fsize + 1); + + if (!fread(s->opt_script_data, 1, fsize, opt_fd)) { + error_report("advanced-watchdog can't read " + "opt_script: %s", s->opt_script); + return -1; + } + + fclose(opt_fd); + + return 0; +} + static void awd_complete(UserCreatable *uc, Error **errp) { AwdState *s = AWD(uc); @@ -224,6 +400,16 @@ static void awd_complete(UserCreatable *uc, Error **errp) return; } + if (get_opt_script_data(s)) { + error_setg(errp, "advanced-watchdog can't get " + "opt script data: %s", s->opt_script); + return; + } + + net_socket_rs_init(&s->awd_rs, awd_rs_finalize, false); + + awd_iothread(s); + return; } @@ -272,6 +458,13 @@ static void awd_finalize(Object *obj) { AwdState *s = AWD(obj); + qemu_chr_fe_deinit(&s->chr_awd_node, false); + qemu_chr_fe_deinit(&s->chr_notification_node, false); + + if (s->iothread) { + awd_timer_del(s); + } + g_free(s->awd_node); g_free(s->notification_node); } -- 2.17.1