qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH v2] watchdog: Allow setting action on the fly


From: Markus Armbruster
Subject: Re: [Qemu-devel] [PATCH v2] watchdog: Allow setting action on the fly
Date: Wed, 06 Sep 2017 08:10:21 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/25.2 (gnu/linux)

Michal Privoznik <address@hidden> writes:

> Currently, the only time that users can set watchdog action is at
> the start as all we expose is this -watchdog-action command line
> argument. This is suboptimal when users want to plug the device
> later via monitor. Alternatively, they might want to change the
> action for already existing device on the fly.
>
> At the same time, drop local redefinition of the actions eum in
> watchdog.h in favour of the ones defined in schema.
>
> Inspired by: https://bugzilla.redhat.com/show_bug.cgi?id=1447169
>
> Signed-off-by: Michal Privoznik <address@hidden>
> ---
>
> diff to v1:
> - instead of allowing 'action' to be arbitrary string, use enum for it and 
> thus
>   drop local redefinition of the enum.
>
>  hw/watchdog/watchdog.c    | 52 
> ++++++++++++++++++++++++-----------------------
>  hw/watchdog/wdt_diag288.c |  6 +++---
>  include/sysemu/watchdog.h | 12 ++---------
>  qapi-schema.json          |  9 ++++++++
>  4 files changed, 41 insertions(+), 38 deletions(-)
>
> diff --git a/hw/watchdog/watchdog.c b/hw/watchdog/watchdog.c
> index 0c5c9cde1c..a3e9d7b59b 100644
> --- a/hw/watchdog/watchdog.c
> +++ b/hw/watchdog/watchdog.c
> @@ -29,8 +29,11 @@
>  #include "qapi-event.h"
>  #include "hw/nmi.h"
>  #include "qemu/help_option.h"
> +#include "qmp-commands.h"
> +#include "qapi/qmp/qerror.h"
> +#include "qapi/util.h"
>  
> -static int watchdog_action = WDT_RESET;
> +static WatchdogExpirationAction watchdog_action = 
> WATCHDOG_EXPIRATION_ACTION_RESET;
>  static QLIST_HEAD(watchdog_list, WatchdogTimerModel) watchdog_list;
>  
>  void watchdog_add_model(WatchdogTimerModel *model)
> @@ -77,27 +80,17 @@ int select_watchdog(const char *p)
>  
>  int select_watchdog_action(const char *p)
>  {
> -    if (strcasecmp(p, "reset") == 0)
> -        watchdog_action = WDT_RESET;
> -    else if (strcasecmp(p, "shutdown") == 0)
> -        watchdog_action = WDT_SHUTDOWN;
> -    else if (strcasecmp(p, "poweroff") == 0)
> -        watchdog_action = WDT_POWEROFF;
> -    else if (strcasecmp(p, "pause") == 0)
> -        watchdog_action = WDT_PAUSE;
> -    else if (strcasecmp(p, "debug") == 0)
> -        watchdog_action = WDT_DEBUG;
> -    else if (strcasecmp(p, "none") == 0)
> -        watchdog_action = WDT_NONE;
> -    else if (strcasecmp(p, "inject-nmi") == 0)
> -        watchdog_action = WDT_NMI;
> -    else
> -        return -1;
> +    int action;
>  
> +    action = qapi_enum_parse(WatchdogExpirationAction_lookup, p,
> +                             WATCHDOG_EXPIRATION_ACTION__MAX, -1, NULL);
> +    if (action < 0)
> +        return -1;
> +    qmp_watchdog_set_action(action, NULL);

&error_abort

>      return 0;
>  }
>  
> -int get_watchdog_action(void)
> +WatchdogExpirationAction get_watchdog_action(void)
>  {
>      return watchdog_action;
>  }
> @@ -108,21 +101,21 @@ int get_watchdog_action(void)
>  void watchdog_perform_action(void)
>  {
>      switch (watchdog_action) {
> -    case WDT_RESET:             /* same as 'system_reset' in monitor */
> +    case WATCHDOG_EXPIRATION_ACTION_RESET:      /* same as 'system_reset' in 
> monitor */
>          qapi_event_send_watchdog(WATCHDOG_EXPIRATION_ACTION_RESET, 
> &error_abort);
>          qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
>          break;
>  
> -    case WDT_SHUTDOWN:          /* same as 'system_powerdown' in monitor */
> +    case WATCHDOG_EXPIRATION_ACTION_SHUTDOWN:   /* same as 
> 'system_powerdown' in monitor */
>          qapi_event_send_watchdog(WATCHDOG_EXPIRATION_ACTION_SHUTDOWN, 
> &error_abort);
>          qemu_system_powerdown_request();
>          break;
>  
> -    case WDT_POWEROFF:          /* same as 'quit' command in monitor */
> +    case WATCHDOG_EXPIRATION_ACTION_POWEROFF:   /* same as 'quit' command in 
> monitor */
>          qapi_event_send_watchdog(WATCHDOG_EXPIRATION_ACTION_POWEROFF, 
> &error_abort);
>          exit(0);
>  
> -    case WDT_PAUSE:             /* same as 'stop' command in monitor */
> +    case WATCHDOG_EXPIRATION_ACTION_PAUSE:      /* same as 'stop' command in 
> monitor */
>          /* In a timer callback, when vm_stop calls qemu_clock_enable
>           * you would get a deadlock.  Bypass the problem.
>           */
> @@ -131,19 +124,28 @@ void watchdog_perform_action(void)
>          qemu_system_vmstop_request(RUN_STATE_WATCHDOG);
>          break;
>  
> -    case WDT_DEBUG:
> +    case WATCHDOG_EXPIRATION_ACTION_DEBUG:
>          qapi_event_send_watchdog(WATCHDOG_EXPIRATION_ACTION_DEBUG, 
> &error_abort);
>          fprintf(stderr, "watchdog: timer fired\n");
>          break;
>  
> -    case WDT_NONE:
> +    case WATCHDOG_EXPIRATION_ACTION_NONE:
>          qapi_event_send_watchdog(WATCHDOG_EXPIRATION_ACTION_NONE, 
> &error_abort);
>          break;
>  
> -    case WDT_NMI:
> +    case WATCHDOG_EXPIRATION_ACTION_INJECT_NMI:
>          qapi_event_send_watchdog(WATCHDOG_EXPIRATION_ACTION_INJECT_NMI,
>                                   &error_abort);
>          nmi_monitor_handle(0, NULL);
>          break;
> +
> +    case WATCHDOG_EXPIRATION_ACTION__MAX:
> +        /* keep gcc happy */
> +        break;

       default:
           assert(0);

>      }
>  }
> +
> +void qmp_watchdog_set_action(WatchdogExpirationAction action, Error **errp)
> +{
> +    watchdog_action = action;
> +}
> diff --git a/hw/watchdog/wdt_diag288.c b/hw/watchdog/wdt_diag288.c
> index 47f289216a..451644eb89 100644
> --- a/hw/watchdog/wdt_diag288.c
> +++ b/hw/watchdog/wdt_diag288.c
> @@ -57,9 +57,9 @@ static void diag288_timer_expired(void *dev)
>       * the BQL; reset before triggering the action to avoid races with
>       * diag288 instructions. */
>      switch (get_watchdog_action()) {
> -    case WDT_DEBUG:
> -    case WDT_NONE:
> -    case WDT_PAUSE:
> +    case WATCHDOG_EXPIRATION_ACTION_DEBUG:
> +    case WATCHDOG_EXPIRATION_ACTION_NONE:
> +    case WATCHDOG_EXPIRATION_ACTION_PAUSE:
>          break;
>      default:
>          wdt_diag288_reset(dev);
> diff --git a/include/sysemu/watchdog.h b/include/sysemu/watchdog.h
> index 72a4da07a6..1b830df152 100644
> --- a/include/sysemu/watchdog.h
> +++ b/include/sysemu/watchdog.h
> @@ -23,15 +23,7 @@
>  #define QEMU_WATCHDOG_H
>  
>  #include "qemu/queue.h"
> -
> -/* Possible values for action parameter. */
> -#define WDT_RESET        1      /* Hard reset. */
> -#define WDT_SHUTDOWN     2      /* Shutdown. */
> -#define WDT_POWEROFF     3      /* Quit. */
> -#define WDT_PAUSE        4      /* Pause. */
> -#define WDT_DEBUG        5      /* Prints a message and continues running. */
> -#define WDT_NONE         6      /* Do nothing. */
> -#define WDT_NMI          7      /* Inject nmi into the guest. */
> +#include "qapi-types.h"
>  
>  struct WatchdogTimerModel {
>      QLIST_ENTRY(WatchdogTimerModel) entry;
> @@ -46,7 +38,7 @@ typedef struct WatchdogTimerModel WatchdogTimerModel;
>  /* in hw/watchdog.c */
>  int select_watchdog(const char *p);
>  int select_watchdog_action(const char *action);
> -int get_watchdog_action(void);
> +WatchdogExpirationAction get_watchdog_action(void);
>  void watchdog_add_model(WatchdogTimerModel *model);
>  void watchdog_perform_action(void);
>  
> diff --git a/qapi-schema.json b/qapi-schema.json
> index 802ea53d00..40605be36f 100644
> --- a/qapi-schema.json
> +++ b/qapi-schema.json
> @@ -6539,3 +6539,12 @@
>  # Since 2.9
>  ##
>  { 'command': 'query-vm-generation-id', 'returns': 'GuidInfo' }
> +
> +##
> +# @watchdog-set-action:
> +#
> +# Set watchdog action
> +#
> +# Since 2.11
> +##
> +{ 'command': 'watchdog-set-action', 'data' : {'action': 
> 'WatchdogExpirationAction'} }

I was wondering whether you forgot to include the enum definition, until
I discovered you smartly reused the existing one.

If it was a new one instead, I would suggest naming it WatchdogAction,
because a watchdog's one and only action is the expiration action, and
therefore the shorter name serves just fine.  Hmm, it's used in just two
places...  okay, I'm suggesting you rename it, in a separate preparatory
patch.

This cleans up code duplication.  Worth mentioning in the commit
message.

Looks pretty good overall; a quick respin should get us there.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]