Patchwork [2/2] QMP: Introduce DISK_ERROR event

login
register
mail settings
Submitter Luiz Capitulino
Date Feb. 1, 2010, 6:07 p.m.
Message ID <1265047668-15039-3-git-send-email-lcapitulino@redhat.com>
Download mbox | patch
Permalink /patch/44215/
State New
Headers show

Comments

Luiz Capitulino - Feb. 1, 2010, 6:07 p.m.
It's emitted when a disk write or read fails, some device information
is provided. We can also provide error details in the future.

Example:

{ "event": "DISK_ERROR",
    "data": { "device": "ide0-hd1",
              "operation": "write",
              "action": "stop" }
    "timestamp": { "seconds": 1265044230, "microseconds": 450486 } }

NOTE: Adding a small reference in QMP/qmp-events.txt, but this file is
wrong and will be replaced by proper documentation shortly.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 QMP/qmp-events.txt |    7 +++++++
 monitor.c          |    3 +++
 monitor.h          |    1 +
 vl.c               |   34 +++++++++++++++++++++++++++++++++-
 4 files changed, 44 insertions(+), 1 deletions(-)
Kevin Wolf - Feb. 2, 2010, 9:30 a.m.
Am 01.02.2010 19:07, schrieb Luiz Capitulino:
> It's emitted when a disk write or read fails, some device information
> is provided. We can also provide error details in the future.
> 
> Example:
> 
> { "event": "DISK_ERROR",
>     "data": { "device": "ide0-hd1",
>               "operation": "write",
>               "action": "stop" }
>     "timestamp": { "seconds": 1265044230, "microseconds": 450486 } }
> 
> NOTE: Adding a small reference in QMP/qmp-events.txt, but this file is
> wrong and will be replaced by proper documentation shortly.
> 
> Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
> ---
>  QMP/qmp-events.txt |    7 +++++++
>  monitor.c          |    3 +++
>  monitor.h          |    1 +
>  vl.c               |   34 +++++++++++++++++++++++++++++++++-
>  4 files changed, 44 insertions(+), 1 deletions(-)
> 
> diff --git a/QMP/qmp-events.txt b/QMP/qmp-events.txt
> index dc48ccc..e968ef5 100644
> --- a/QMP/qmp-events.txt
> +++ b/QMP/qmp-events.txt
> @@ -43,3 +43,10 @@ Data: 'server' and 'client' keys with the same keys as 'query-vnc'.
>  
>  Description: Issued when the VNC session is made active.
>  Data: 'server' and 'client' keys with the same keys as 'query-vnc'.
> +
> +7 DISK_ERROR
> +------------
> +
> +Description: Issued when a disk I/O error occurs
> +Data: 'device' (device name), 'action' (action to be taken),
> +      'operation' ("read" or "write")
> diff --git a/monitor.c b/monitor.c
> index fb7c572..82edd79 100644
> --- a/monitor.c
> +++ b/monitor.c
> @@ -378,6 +378,9 @@ void monitor_protocol_event(MonitorEvent event, QObject *data)
>          case QEVENT_VNC_DISCONNECTED:
>              event_name = "VNC_DISCONNECTED";
>              break;
> +        case QEVENT_DISK_ERROR:
> +            event_name = "DISK_ERROR";
> +            break;
>          default:
>              abort();
>              break;
> diff --git a/monitor.h b/monitor.h
> index b0f9270..beaddaf 100644
> --- a/monitor.h
> +++ b/monitor.h
> @@ -23,6 +23,7 @@ typedef enum MonitorEvent {
>      QEVENT_VNC_CONNECTED,
>      QEVENT_VNC_INITIALIZED,
>      QEVENT_VNC_DISCONNECTED,
> +    QEVENT_DISK_ERROR,
>      QEVENT_MAX,
>  } MonitorEvent;
>  
> diff --git a/vl.c b/vl.c
> index 57c439d..1f69f56 100644
> --- a/vl.c
> +++ b/vl.c
> @@ -1856,10 +1856,42 @@ static BlockInterfaceErrorAction drive_get_err_action(
>      return is_read ? BLOCK_ERR_REPORT : BLOCK_ERR_STOP_ENOSPC;
>  }
>  
> +static void driver_err_event(
> +    BlockInterfaceErrorAction action, int is_read, const char *device)
> +{
> +    QObject *data;
> +    const char *action_str;
> +
> +    switch (action) {
> +    case BLOCK_ERR_REPORT:
> +        action_str = "report";
> +        break;
> +    case BLOCK_ERR_IGNORE:
> +        action_str = "ignore";
> +        break;
> +    case BLOCK_ERR_STOP_ANY:
> +    case BLOCK_ERR_STOP_ENOSPC:
> +        action_str = "stop";

This is wrong. If it's BLOCK_ERR_STOP_ENOSPC, the action taken depends
on the error code. It might as well be a "report" instead of "stop" if
it was an EIO, for example.

But the problem is probably going to go away when you stop abusing a
getter function and add some calls that are explicitly made for your
requirements.

Kevin

Patch

diff --git a/QMP/qmp-events.txt b/QMP/qmp-events.txt
index dc48ccc..e968ef5 100644
--- a/QMP/qmp-events.txt
+++ b/QMP/qmp-events.txt
@@ -43,3 +43,10 @@  Data: 'server' and 'client' keys with the same keys as 'query-vnc'.
 
 Description: Issued when the VNC session is made active.
 Data: 'server' and 'client' keys with the same keys as 'query-vnc'.
+
+7 DISK_ERROR
+------------
+
+Description: Issued when a disk I/O error occurs
+Data: 'device' (device name), 'action' (action to be taken),
+      'operation' ("read" or "write")
diff --git a/monitor.c b/monitor.c
index fb7c572..82edd79 100644
--- a/monitor.c
+++ b/monitor.c
@@ -378,6 +378,9 @@  void monitor_protocol_event(MonitorEvent event, QObject *data)
         case QEVENT_VNC_DISCONNECTED:
             event_name = "VNC_DISCONNECTED";
             break;
+        case QEVENT_DISK_ERROR:
+            event_name = "DISK_ERROR";
+            break;
         default:
             abort();
             break;
diff --git a/monitor.h b/monitor.h
index b0f9270..beaddaf 100644
--- a/monitor.h
+++ b/monitor.h
@@ -23,6 +23,7 @@  typedef enum MonitorEvent {
     QEVENT_VNC_CONNECTED,
     QEVENT_VNC_INITIALIZED,
     QEVENT_VNC_DISCONNECTED,
+    QEVENT_DISK_ERROR,
     QEVENT_MAX,
 } MonitorEvent;
 
diff --git a/vl.c b/vl.c
index 57c439d..1f69f56 100644
--- a/vl.c
+++ b/vl.c
@@ -1856,10 +1856,42 @@  static BlockInterfaceErrorAction drive_get_err_action(
     return is_read ? BLOCK_ERR_REPORT : BLOCK_ERR_STOP_ENOSPC;
 }
 
+static void driver_err_event(
+    BlockInterfaceErrorAction action, int is_read, const char *device)
+{
+    QObject *data;
+    const char *action_str;
+
+    switch (action) {
+    case BLOCK_ERR_REPORT:
+        action_str = "report";
+        break;
+    case BLOCK_ERR_IGNORE:
+        action_str = "ignore";
+        break;
+    case BLOCK_ERR_STOP_ANY:
+    case BLOCK_ERR_STOP_ENOSPC:
+        action_str = "stop";
+        break;
+    default:
+        abort();
+    }
+
+    data = qobject_from_jsonf("{'device': %s, 'action': %s, 'operation': %s}",
+                              device, action_str, is_read ? "read" : "write");
+    monitor_protocol_event(QEVENT_DISK_ERROR, data);
+    qobject_decref(data);
+}
+
 BlockInterfaceErrorAction drive_get_on_error(
     BlockDriverState *bdrv, int is_read)
 {
-    return drive_get_err_action(bdrv, is_read);
+    BlockInterfaceErrorAction action;
+
+    action = drive_get_err_action(bdrv, is_read);
+    driver_err_event(action, is_read, bdrv->device_name);
+
+    return action;
 }
 
 static void bdrv_format_print(void *opaque, const char *name)