Re: [libvirt PATCH v4 05/25] nodedev: add ability to parse mdevs from mdevctl

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

 



On Wed, Feb 03, 2021 at 11:38:49AM -0600, Jonathon Jongsma wrote:
> This function will parse the list of mediated devices that are returned
> by mdevctl and convert it into our internal node device representation.
> 
> Signed-off-by: Jonathon Jongsma <jjongsma@xxxxxxxxxx>
> ---
>  src/node_device/node_device_driver.c          | 145 ++++++++++++++++++
>  src/node_device/node_device_driver.h          |   4 +
>  .../mdevctl-list-multiple.json                |  59 +++++++
>  .../mdevctl-list-multiple.out.xml             |  39 +++++
>  tests/nodedevmdevctltest.c                    |  56 ++++++-
>  5 files changed, 301 insertions(+), 2 deletions(-)
>  create mode 100644 tests/nodedevmdevctldata/mdevctl-list-multiple.json
>  create mode 100644 tests/nodedevmdevctldata/mdevctl-list-multiple.out.xml
> 
> diff --git a/src/node_device/node_device_driver.c b/src/node_device/node_device_driver.c
> index 6143459618..fc5ac1d27e 100644
> --- a/src/node_device/node_device_driver.c
> +++ b/src/node_device/node_device_driver.c
> @@ -853,6 +853,151 @@ virMdevctlStop(virNodeDeviceDefPtr def)
>  }
>  
>  
> +static void mdevGenerateDeviceName(virNodeDeviceDefPtr dev)
> +{
> +    nodeDeviceGenerateName(dev, "mdev", dev->caps->data.mdev.uuid, NULL);
> +}
> +
> +
> +static virNodeDeviceDefPtr
> +nodeDeviceParseMdevctlChildDevice(const char *parent,
> +                                  virJSONValuePtr json)
> +{
> +    virNodeDevCapMdevPtr mdev;
> +    const char *uuid;
> +    virJSONValuePtr props, attrs;

^This was the other "One declaration per line" place I could not remember
during v3 review.

...

> +int
> +nodeDeviceParseMdevctlJSON(const char *jsonstring,
> +                           virNodeDeviceDefPtr **devs)
> +{
> +    int n;
> +    g_autoptr(virJSONValue) json_devicelist = NULL;
> +    virNodeDeviceDefPtr *outdevs = NULL;
> +    size_t noutdevs = 0;
> +    size_t i;
> +    size_t j;
> +
> +    json_devicelist = virJSONValueFromString(jsonstring);
> +
> +    if (!json_devicelist || !virJSONValueIsArray(json_devicelist)) {
> +        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> +                       _("JSON response contains no devices"));

I'd make it even more specific - "mdevctl JSON response..."

> +        goto error;
> +    }
> +
> +    n = virJSONValueArraySize(json_devicelist);
> +
> +    for (i = 0; i < n; i++) {
> +        virJSONValuePtr obj = virJSONValueArrayGet(json_devicelist, i);
> +        const char *parent;
> +        virJSONValuePtr child_array;
> +        int nchildren;
> +
> +        if (!virJSONValueIsObject(obj)) {
> +            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> +                           _("Parent device is not an object"));
> +            goto error;
> +        }
> +
> +        /* mdevctl returns an array of objects.  Each object is a parent device
> +         * object containing a single key-value pair which maps from the name
> +         * of the parent device to an array of child devices */
> +        if (virJSONValueObjectKeysNumber(obj) != 1) {
> +            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> +                           _("Unexpected format for parent device object"));
> +            goto error;
> +        }
> +
> +        parent = virJSONValueObjectGetKey(obj, 0);
> +        child_array = virJSONValueObjectGetValue(obj, 0);
> +
> +        if (!virJSONValueIsArray(child_array)) {
> +            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> +                           _("Child list is not an array"));

"Parent device's JSON object data is not an array" - or something along those
lines

> +            goto error;
> +        }
> +
> +        nchildren = virJSONValueArraySize(child_array);
> +
> +        for (j = 0; j < nchildren; j++) {
> +            g_autoptr(virNodeDeviceDef) child = NULL;
> +            virJSONValuePtr child_obj = virJSONValueArrayGet(child_array, j);
> +
> +            if (!(child = nodeDeviceParseMdevctlChildDevice(parent, child_obj))) {
> +                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> +                               _("Unable to parse child device"));

"Unable to parse mdev child device"

> +                goto error;
> +            }
> +
> +            if (VIR_APPEND_ELEMENT(outdevs, noutdevs, child) < 0) {
> +                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> +                               _("Unable to append child device to list"));

APPEND_ELEMENT will either report an "Out of bounds" error or abort on
allocation failure, so please drop ^this virReportError.

> +                goto error;
> +            }
> +        }
> +    }
> +
> +    *devs = outdevs;
> +    return noutdevs;
> +
> + error:
> +    for (i = 0; i < noutdevs; i++)
> +        virNodeDeviceDefFree(outdevs[i]);
> +    VIR_FREE(outdevs);
> +    return -1;
> +}
> +
> +
>  int
>  nodeDeviceDestroy(virNodeDevicePtr device)
>  {
> diff --git a/src/node_device/node_device_driver.h b/src/node_device/node_device_driver.h
> index 02baf56dab..2a162513c0 100644
> --- a/src/node_device/node_device_driver.h
> +++ b/src/node_device/node_device_driver.h
> @@ -119,6 +119,10 @@ nodeDeviceGetMdevctlStartCommand(virNodeDeviceDefPtr def,
>  virCommandPtr
>  nodeDeviceGetMdevctlStopCommand(const char *uuid);
>  
> +int
> +nodeDeviceParseMdevctlJSON(const char *jsonstring,
> +                           virNodeDeviceDefPtr **devs);
> +
>  void
>  nodeDeviceGenerateName(virNodeDeviceDefPtr def,
>                         const char *subsystem,
> diff --git a/tests/nodedevmdevctldata/mdevctl-list-multiple.json b/tests/nodedevmdevctldata/mdevctl-list-multiple.json
> new file mode 100644
> index 0000000000..eefcd90c62
> --- /dev/null
> +++ b/tests/nodedevmdevctldata/mdevctl-list-multiple.json
> @@ -0,0 +1,59 @@
> +[
> +  {
> +    "0000:00:02.0": [
> +      {
> +        "200f228a-c80a-4d50-bfb7-f5a0e4e34045": {
> +          "mdev_type": "i915-GVTg_V5_4",
> +          "start": "manual"
> +        }
> +      },
> +      {
> +        "de807ffc-1923-4d5f-b6c9-b20ecebc6d4b": {
> +          "mdev_type": "i915-GVTg_V5_4",
> +          "start": "auto"
> +        }
> +      },
> +      {
> +        "435722ea-5f43-468a-874f-da34f1217f13": {
> +          "mdev_type": "i915-GVTg_V5_8",
> +          "start": "manual",
> +          "attrs": [
> +            {
> +              "testattr": "42"
> +            }
> +          ]
> +        }
> +      }
> +    ]
> +  },
> +  {
> +    "matrix": [
> +      { "783e6dbb-ea0e-411f-94e2-717eaad438bf": {
> +        "mdev_type": "vfio_ap-passthrough",
> +        "start": "manual",
> +        "attrs": [
> +          {
> +            "assign_adapter": "5"
> +          },
> +          {
> +            "assign_adapter": "6"
> +          },

I'd still like to know why there are 2 assign_adapter and 2 assign_domain
attributes here, I'm simply confused what the outcome should be.

> +          {
> +            "assign_domain": "0xab"
> +          },
> +          {
> +            "assign_control_domain": "0xab"
> +          },
> +          {
> +            "assign_domain": "4"
> +          },
> +          {
> +            "assign_control_domain": "4"
> +          }
> +        ]
> +      }
> +      }
> +    ]
> +  }
> +]
> +


...


> +  <name>mdev_783e6dbb_ea0e_411f_94e2_717eaad438bf</name>
> +  <parent>matrix</parent>
> +  <capability type='mdev'>
> +    <type id='vfio_ap-passthrough'/>
> +    <iommuGroup number='0'/>
> +    <attr name='assign_adapter' value='5'/>
> +    <attr name='assign_adapter' value='6'/>
> +    <attr name='assign_domain' value='0xab'/>
> +    <attr name='assign_control_domain' value='0xab'/>
> +    <attr name='assign_domain' value='4'/>
> +    <attr name='assign_control_domain' value='4'/>

Here too I'd like to hear an opinion (since v3) on naming the attributes in
such way that they correspond to the respective elements: ap-adapter,
ap-domain, etc.  This naming is very unintuitive if not documented properly;
unless there's an internal reason why they have to be named "assign_control",
etc.

Erik




[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]

  Powered by Linux