[libvirt] [PATCH 07/11] qemu: chardev: Extract more information about character devices

Jiri Denemark jdenemar at redhat.com
Thu Nov 20 21:12:39 UTC 2014


On Wed, Nov 19, 2014 at 11:23:20 +0100, Peter Krempa wrote:
> Improve the monitor function to also retrieve the guest state of
> character device (if provided) so that we can refresh the state of
> virtio-serial channels and perhaps react to changes in the state in
> future patches.
> 
> This patch changes the returned data from qemuMonitorGetChardevInfo to
> return a structure containing the pty path and the state if the info is
> relevant.
> 
> The change to the testsuite makes sure that the data is parsed
> correctly.
> ---
>  src/qemu/qemu_monitor.c      | 13 +++++++++++-
>  src/qemu/qemu_monitor.h      |  6 ++++++
>  src/qemu/qemu_monitor_json.c | 48 +++++++++++++++++++++++++++++++++-----------
>  src/qemu/qemu_monitor_text.c | 17 +++++++++++-----
>  src/qemu/qemu_process.c      |  8 ++++----
>  tests/qemumonitorjsontest.c  | 39 +++++++++++++++++++++++++++++------
>  6 files changed, 103 insertions(+), 28 deletions(-)
> 
> diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
> index 926619f..c9c84f9 100644
> --- a/src/qemu/qemu_monitor.c
> +++ b/src/qemu/qemu_monitor.c
> @@ -2982,6 +2982,17 @@ qemuMonitorQueryRxFilter(qemuMonitorPtr mon, const char *alias,
>  }
> 
> 
> +static void
> +qemuMonitorChardevInfoFree(void *data,
> +                           const void *name ATTRIBUTE_UNUSED)
> +{
> +    qemuMonitorChardevInfoPtr info = data;
> +
> +    VIR_FREE(info->ptyPath);
> +    VIR_FREE(info);
> +}
> +
> +
>  int
>  qemuMonitorGetChardevInfo(qemuMonitorPtr mon,
>                            virHashTablePtr *retinfo)
> @@ -2997,7 +3008,7 @@ qemuMonitorGetChardevInfo(qemuMonitorPtr mon,
>          goto error;
>      }
> 
> -    if (!(info = virHashCreate(10, virHashValueFree)))
> +    if (!(info = virHashCreate(10, qemuMonitorChardevInfoFree)))
>          goto error;
> 
>      if (mon->json)
> diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
> index 3078be0..21533a4 100644
> --- a/src/qemu/qemu_monitor.h
> +++ b/src/qemu/qemu_monitor.h
> @@ -649,6 +649,12 @@ int qemuMonitorRemoveNetdev(qemuMonitorPtr mon,
>  int qemuMonitorQueryRxFilter(qemuMonitorPtr mon, const char *alias,
>                               virNetDevRxFilterPtr *filter);
> 
> +typedef struct _qemuMonitorChardevInfo qemuMonitorChardevInfo;
> +typedef qemuMonitorChardevInfo *qemuMonitorChardevInfoPtr;
> +struct _qemuMonitorChardevInfo {
> +    char *ptyPath;
> +    virDomainChrDeviceState state;
> +};
>  int qemuMonitorGetChardevInfo(qemuMonitorPtr mon,
>                                virHashTablePtr *retinfo);
> 
> diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
> index 9c8a6fb..5429382 100644
> --- a/src/qemu/qemu_monitor_json.c
> +++ b/src/qemu/qemu_monitor_json.c
> @@ -3426,6 +3426,9 @@ qemuMonitorJSONExtractChardevInfo(virJSONValuePtr reply,
>      virJSONValuePtr data;
>      int ret = -1;
>      size_t i;
> +    char *ptyPath = NULL;
> +    virDomainChrDeviceState state;
> +    qemuMonitorChardevInfoPtr entry = NULL;
> 
>      if (!(data = virJSONValueObjectGet(reply, "return"))) {
>          virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> @@ -3440,44 +3443,65 @@ qemuMonitorJSONExtractChardevInfo(virJSONValuePtr reply,
>      }
> 
>      for (i = 0; i < virJSONValueArraySize(data); i++) {
> -        virJSONValuePtr entry = virJSONValueArrayGet(data, i);
> +        virJSONValuePtr chardev = virJSONValueArrayGet(data, i);
>          const char *type;
> -        const char *id;
> -        if (!entry) {
> +        const char *alias;
> +        bool connected;
> +
> +        if (!chardev) {
>              virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
>                             _("character device information was missing array element"));
>              goto cleanup;
>          }
> 
> -        if (!(type = virJSONValueObjectGetString(entry, "filename"))) {
> +        if (!(alias = virJSONValueObjectGetString(chardev, "label"))) {
>              virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> -                           _("character device information was missing filename"));
> +                           _("character device information was missing alias"));

Shouldn't we report that device information was missing label rather
than alias as we are referring to a field in the QMP event?

>              goto cleanup;
>          }
> 
> -        if (!(id = virJSONValueObjectGetString(entry, "label"))) {
> +        if (!(type = virJSONValueObjectGetString(chardev, "filename"))) {
>              virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
>                             _("character device information was missing filename"));
>              goto cleanup;
>          }
> 
> -        if (STRPREFIX(type, "pty:")) {
> -            char *path;
> -            if (VIR_STRDUP(path, type + strlen("pty:")) < 0)
> +        if (STRPREFIX(type, "pty:") &&
> +            VIR_STRDUP(ptyPath, type + strlen("pty:")) < 0)
> +            goto cleanup;
> +
> +        if (virJSONValueObjectGetBoolean(chardev, "frontend-open", &connected) == 0) {
> +            if (connected)
> +                state = VIR_DOMAIN_CHR_DEVICE_STATE_CONNECTED;
> +            else
> +                state = VIR_DOMAIN_CHR_DEVICE_STATE_DISCONNECTED;
> +        }
> +
> +        if (ptyPath || state != VIR_DOMAIN_CHR_DEVICE_STATE_DEFAULT) {

It took me a while to understand what you want to do here :-) So you
want store only "pty:" char devices or char devices with "frontend-open"
field, right? Any reason for this filtering (apart from the fact we
don't care about other devices now)? I guess storing all devices would
work too and the code would be a bit simpler. Or am I wrong?

> +            if (VIR_ALLOC(entry) < 0)
>                  goto cleanup;
> 
> -            if (virHashAddEntry(info, id, path) < 0) {
> +            entry->ptyPath = ptyPath;
> +            entry->state = state;
> +
> +            if (virHashAddEntry(info, alias, entry) < 0) {
>                  virReportError(VIR_ERR_OPERATION_FAILED,
> -                               _("failed to save chardev path '%s'"), path);
> -                VIR_FREE(path);
> +                               _("failed to add chardev '%s' info"), alias);
>                  goto cleanup;
>              }
> +
> +            entry = NULL;
> +            ptyPath = NULL;
> +            state = VIR_DOMAIN_CHR_DEVICE_STATE_DEFAULT;

Ah, you managed to confuse me again :-) I'd prefer if you moved the
"virDomainChrDeviceState state;" declaration inside the for loop and
initialized state to VIR_DOMAIN_CHR_DEVICE_STATE_DEFAULT there.

However, if you follow my suggestion to remove the condition above, you
can avoid state variable completely and rather assign to entry->state
directly (after moving the allocation of entry before checking for
frontend-open, of course).

>          }
>      }
> 
>      ret = 0;
> 
>   cleanup:
> +    VIR_FREE(entry);
> +    VIR_FREE(ptyPath);
> +
>      return ret;
>  }
> 
...

Jirka




More information about the libvir-list mailing list