[libvirt PATCH] nodedev: fix race in API usage vs initial device enumeration

Michal Prívozník mprivozn at redhat.com
Mon Mar 16 16:03:59 UTC 2020


On 13. 3. 2020 13:00, Daniel P. Berrangé wrote:
> During startup the udev node device driver impl uses a background thread
> to populate the list of devices to avoid blocking the daemon startup
> entirely. There is no synchronization to the public APIs, so it is
> possible for an application to start calling APIs before the device
> initialization is complete.
> 
> This was not a problem in the old approach where libvirtd was started
> on boot, as initialization would easily complete before any APIs were
> called.
> 
> With the use of socket activation, however, APIs are invoked from the
> very moment the daemon starts. This is easily seen by doing a
> 
>   'virsh -c nodedev:///system list'
> 
> the first time it runs it will only show one or two devices. The second
> time it runs it will show all devices. The solution is to introduce a
> flag and condition variable for APIs to synchronize against before
> returning any data.
> 
> Signed-off-by: Daniel P. Berrangé <berrange at redhat.com>
> ---
>  src/conf/virnodedeviceobj.h          |  2 ++
>  src/node_device/node_device_driver.c | 44 ++++++++++++++++++++++++++++
>  src/node_device/node_device_hal.c    | 15 ++++++++++
>  src/node_device/node_device_udev.c   | 13 ++++++++
>  4 files changed, 74 insertions(+)
> 

For both drivers:

> @@ -1744,6 +1745,11 @@ nodeStateInitializeEnumerate(void *opaque)
>      if (udevEnumerateDevices(udev) != 0)
>          goto error;
>  
> +    nodeDeviceLock();
> +    driver->initialized = true;
> +    nodeDeviceUnlock();
> +    virCondBroadcast(&driver->initCond);

Should this broadcast be in the critical section? Just asking, for this
simple case it may be okay.

> +
>      return;
>  
>   error:
> @@ -1806,6 +1812,13 @@ nodeStateInitialize(bool privileged,
>          VIR_FREE(driver);
>          return VIR_DRV_STATE_INIT_ERROR;
>      }
> +    if (virCondInit(&driver->initCond) < 0) {
> +        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> +                       _("Unable to initialize condition variable"));

And perhaps, virReportSystemError() would be nicer.

> +        virMutexDestroy(&driver->lock);
> +        VIR_FREE(driver);
> +        return VIR_DRV_STATE_INIT_ERROR;
> +    }
>  
>      driver->privileged = privileged;
>  
> 

Reviewed-by: Michal Privoznik <mprivozn at redhat.com>

Michal




More information about the libvir-list mailing list