summaryrefslogtreecommitdiff
path: root/drivers/char
diff options
context:
space:
mode:
authorLaurent Vivier <lvivier@redhat.com>2021-10-28 13:11:09 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2023-07-27 09:43:59 +0300
commitd13ea82bfe150fce7cbd5defc888d31d3a33fc91 (patch)
treead5526a9ddf1ab926801c796eb7a88fe87448bd1 /drivers/char
parent5f23dae018c6b916e96ca398fa933750cca939e2 (diff)
downloadlinux-d13ea82bfe150fce7cbd5defc888d31d3a33fc91.tar.xz
hwrng: virtio - don't wait on cleanup
[ Upstream commit 2bb31abdbe55742c89f4dc0cc26fcbc8467364f6 ] When virtio-rng device was dropped by the hwrng core we were forced to wait the buffer to come back from the device to not have remaining ongoing operation that could spoil the buffer. But now, as the buffer is internal to the virtio-rng we can release the waiting loop immediately, the buffer will be retrieve and use when the virtio-rng driver will be selected again. This avoids to hang on an rng_current write command if the virtio-rng device is blocked by a lack of entropy. This allows to select another entropy source if the current one is empty. Signed-off-by: Laurent Vivier <lvivier@redhat.com> Link: https://lore.kernel.org/r/20211028101111.128049-3-lvivier@redhat.com Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Stable-dep-of: ac52578d6e8d ("hwrng: virtio - Fix race on data_avail and actual data") Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/hw_random/virtio-rng.c7
1 files changed, 6 insertions, 1 deletions
diff --git a/drivers/char/hw_random/virtio-rng.c b/drivers/char/hw_random/virtio-rng.c
index 208c547dcac1..173aeea835bb 100644
--- a/drivers/char/hw_random/virtio-rng.c
+++ b/drivers/char/hw_random/virtio-rng.c
@@ -82,6 +82,11 @@ static int virtio_read(struct hwrng *rng, void *buf, size_t size, bool wait)
ret = wait_for_completion_killable(&vi->have_data);
if (ret < 0)
return ret;
+ /* if vi->data_avail is 0, we have been interrupted
+ * by a cleanup, but buffer stays in the queue
+ */
+ if (vi->data_avail == 0)
+ return read;
chunk = min_t(unsigned int, size, vi->data_avail);
memcpy(buf + read, vi->data, chunk);
@@ -105,7 +110,7 @@ static void virtio_cleanup(struct hwrng *rng)
struct virtrng_info *vi = (struct virtrng_info *)rng->priv;
if (vi->busy)
- wait_for_completion(&vi->have_data);
+ complete(&vi->have_data);
}
static int probe_common(struct virtio_device *vdev)