* [PATCH v2 0/2] Improvements to virtio_balloon pm
@ 2024-03-21 1:24 David Stevens
2024-03-21 1:24 ` [PATCH v2 1/2] virtio_balloon: Give the balloon its own wakeup source David Stevens
2024-03-21 1:24 ` [PATCH v2 2/2] virtio_balloon: Treat stats requests as wakeup events David Stevens
0 siblings, 2 replies; 3+ messages in thread
From: David Stevens @ 2024-03-21 1:24 UTC (permalink / raw)
To: Michael S . Tsirkin, David Hildenbrand
Cc: virtualization, linux-kernel, David Stevens
From: David Stevens <stevensd@chromium.org>
The virtio_balloon driver uses wakeup sources to allow the guest to
enter system power management sleep states (e.g. s2idle) without running
the risk of becoming unresponsive to cooperative memory management
requests from the host. This series fixes an issue where wakeup sources
for inflate/deflate were improperly shared between drivers. It also
closes a race where stats requests that come in immediately before a
sleep state transition could fail to be handled in a timely manner.
v1: https://lore.kernel.org/lkml/20240318091034.535573-1-stevensd@google.com/
v1 -> v2:
- Add comment about virtio-balloon's wakeup source
- Rename virtio-balloon wakeup event macros
David Stevens (2):
virtio_balloon: Give the balloon its own wakeup source
virtio_balloon: Treat stats requests as wakeup events
drivers/virtio/virtio_balloon.c | 84 +++++++++++++++++++++------------
1 file changed, 55 insertions(+), 29 deletions(-)
base-commit: e8f897f4afef0031fe618a8e94127a0934896aba
--
2.44.0.291.gc1ea87d7ee-goog
^ permalink raw reply [flat|nested] 3+ messages in thread
* [PATCH v2 1/2] virtio_balloon: Give the balloon its own wakeup source
2024-03-21 1:24 [PATCH v2 0/2] Improvements to virtio_balloon pm David Stevens
@ 2024-03-21 1:24 ` David Stevens
2024-03-21 1:24 ` [PATCH v2 2/2] virtio_balloon: Treat stats requests as wakeup events David Stevens
1 sibling, 0 replies; 3+ messages in thread
From: David Stevens @ 2024-03-21 1:24 UTC (permalink / raw)
To: Michael S . Tsirkin, David Hildenbrand
Cc: virtualization, linux-kernel, David Stevens
From: David Stevens <stevensd@chromium.org>
Wakeup sources don't support nesting multiple events, so sharing a
single object between multiple drivers can result in one driver
overriding the wakeup event processing period specified by another
driver. Have the virtio balloon driver use the wakeup source of the
device it is bound to rather than the wakeup source of the parent
device, to avoid conflicts with the transport layer.
Note that although the virtio balloon's virtio_device itself isn't what
actually wakes up the device, it is responsible for processing wakeup
events. In the same way that EPOLLWAKEUP uses a dedicated wakeup_source
to prevent suspend when userspace is processing wakeup events, a
dedicated wakeup_source is necessary when processing wakeup events in a
higher layer in the kernel.
Fixes: b12fbc3f787e ("virtio_balloon: stay awake while adjusting balloon")
Signed-off-by: David Stevens <stevensd@chromium.org>
Acked-by: David Hildenbrand <david@redhat.com>
---
drivers/virtio/virtio_balloon.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
index 1f5b3dd31fcf..89bc8da80519 100644
--- a/drivers/virtio/virtio_balloon.c
+++ b/drivers/virtio/virtio_balloon.c
@@ -450,7 +450,7 @@ static void start_update_balloon_size(struct virtio_balloon *vb)
vb->adjustment_signal_pending = true;
if (!vb->adjustment_in_progress) {
vb->adjustment_in_progress = true;
- pm_stay_awake(vb->vdev->dev.parent);
+ pm_stay_awake(&vb->vdev->dev);
}
spin_unlock_irqrestore(&vb->adjustment_lock, flags);
@@ -462,7 +462,7 @@ static void end_update_balloon_size(struct virtio_balloon *vb)
spin_lock_irq(&vb->adjustment_lock);
if (!vb->adjustment_signal_pending && vb->adjustment_in_progress) {
vb->adjustment_in_progress = false;
- pm_relax(vb->vdev->dev.parent);
+ pm_relax(&vb->vdev->dev);
}
spin_unlock_irq(&vb->adjustment_lock);
}
@@ -1029,6 +1029,15 @@ static int virtballoon_probe(struct virtio_device *vdev)
spin_lock_init(&vb->adjustment_lock);
+ /*
+ * The virtio balloon itself can't wake up the device, but it is
+ * responsible for processing wakeup events passed up from the transport
+ * layer. Wakeup sources don't support nesting/chaining calls, so we use
+ * our own wakeup source to ensure wakeup events are properly handled
+ * without trampling on the transport layer's wakeup source.
+ */
+ device_set_wakeup_capable(&vb->vdev->dev, true);
+
virtio_device_ready(vdev);
if (towards_target(vb))
--
2.44.0.291.gc1ea87d7ee-goog
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH v2 2/2] virtio_balloon: Treat stats requests as wakeup events
2024-03-21 1:24 [PATCH v2 0/2] Improvements to virtio_balloon pm David Stevens
2024-03-21 1:24 ` [PATCH v2 1/2] virtio_balloon: Give the balloon its own wakeup source David Stevens
@ 2024-03-21 1:24 ` David Stevens
1 sibling, 0 replies; 3+ messages in thread
From: David Stevens @ 2024-03-21 1:24 UTC (permalink / raw)
To: Michael S . Tsirkin, David Hildenbrand
Cc: virtualization, linux-kernel, David Stevens
From: David Stevens <stevensd@chromium.org>
Treat stats requests as wakeup events to ensure that the driver responds
to device requests in a timely manner.
Signed-off-by: David Stevens <stevensd@chromium.org>
Acked-by: David Hildenbrand <david@redhat.com>
---
drivers/virtio/virtio_balloon.c | 75 ++++++++++++++++++++-------------
1 file changed, 46 insertions(+), 29 deletions(-)
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
index 89bc8da80519..b09e8e3c62e5 100644
--- a/drivers/virtio/virtio_balloon.c
+++ b/drivers/virtio/virtio_balloon.c
@@ -121,11 +121,14 @@ struct virtio_balloon {
struct page_reporting_dev_info pr_dev_info;
/* State for keeping the wakeup_source active while adjusting the balloon */
- spinlock_t adjustment_lock;
- bool adjustment_signal_pending;
- bool adjustment_in_progress;
+ spinlock_t wakeup_lock;
+ bool processing_wakeup_event;
+ u32 wakeup_signal_mask;
};
+#define VIRTIO_BALLOON_WAKEUP_SIGNAL_ADJUST (1 << 0)
+#define VIRTIO_BALLOON_WAKEUP_SIGNAL_STATS (1 << 1)
+
static const struct virtio_device_id id_table[] = {
{ VIRTIO_ID_BALLOON, VIRTIO_DEV_ANY_ID },
{ 0 },
@@ -140,6 +143,36 @@ static u32 page_to_balloon_pfn(struct page *page)
return pfn * VIRTIO_BALLOON_PAGES_PER_PAGE;
}
+static void start_wakeup_event(struct virtio_balloon *vb, u32 mask)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&vb->wakeup_lock, flags);
+ vb->wakeup_signal_mask |= mask;
+ if (!vb->processing_wakeup_event) {
+ vb->processing_wakeup_event = true;
+ pm_stay_awake(&vb->vdev->dev);
+ }
+ spin_unlock_irqrestore(&vb->wakeup_lock, flags);
+}
+
+static void process_wakeup_event(struct virtio_balloon *vb, u32 mask)
+{
+ spin_lock_irq(&vb->wakeup_lock);
+ vb->wakeup_signal_mask &= ~mask;
+ spin_unlock_irq(&vb->wakeup_lock);
+}
+
+static void finish_wakeup_event(struct virtio_balloon *vb)
+{
+ spin_lock_irq(&vb->wakeup_lock);
+ if (!vb->wakeup_signal_mask && vb->processing_wakeup_event) {
+ vb->processing_wakeup_event = false;
+ pm_relax(&vb->vdev->dev);
+ }
+ spin_unlock_irq(&vb->wakeup_lock);
+}
+
static void balloon_ack(struct virtqueue *vq)
{
struct virtio_balloon *vb = vq->vdev->priv;
@@ -370,8 +403,10 @@ static void stats_request(struct virtqueue *vq)
struct virtio_balloon *vb = vq->vdev->priv;
spin_lock(&vb->stop_update_lock);
- if (!vb->stop_update)
+ if (!vb->stop_update) {
+ start_wakeup_event(vb, VIRTIO_BALLOON_WAKEUP_SIGNAL_STATS);
queue_work(system_freezable_wq, &vb->update_balloon_stats_work);
+ }
spin_unlock(&vb->stop_update_lock);
}
@@ -444,29 +479,10 @@ static void virtio_balloon_queue_free_page_work(struct virtio_balloon *vb)
static void start_update_balloon_size(struct virtio_balloon *vb)
{
- unsigned long flags;
-
- spin_lock_irqsave(&vb->adjustment_lock, flags);
- vb->adjustment_signal_pending = true;
- if (!vb->adjustment_in_progress) {
- vb->adjustment_in_progress = true;
- pm_stay_awake(&vb->vdev->dev);
- }
- spin_unlock_irqrestore(&vb->adjustment_lock, flags);
-
+ start_wakeup_event(vb, VIRTIO_BALLOON_WAKEUP_SIGNAL_ADJUST);
queue_work(system_freezable_wq, &vb->update_balloon_size_work);
}
-static void end_update_balloon_size(struct virtio_balloon *vb)
-{
- spin_lock_irq(&vb->adjustment_lock);
- if (!vb->adjustment_signal_pending && vb->adjustment_in_progress) {
- vb->adjustment_in_progress = false;
- pm_relax(&vb->vdev->dev);
- }
- spin_unlock_irq(&vb->adjustment_lock);
-}
-
static void virtballoon_changed(struct virtio_device *vdev)
{
struct virtio_balloon *vb = vdev->priv;
@@ -495,7 +511,10 @@ static void update_balloon_stats_func(struct work_struct *work)
vb = container_of(work, struct virtio_balloon,
update_balloon_stats_work);
+
+ process_wakeup_event(vb, VIRTIO_BALLOON_WAKEUP_SIGNAL_STATS);
stats_handle_request(vb);
+ finish_wakeup_event(vb);
}
static void update_balloon_size_func(struct work_struct *work)
@@ -506,9 +525,7 @@ static void update_balloon_size_func(struct work_struct *work)
vb = container_of(work, struct virtio_balloon,
update_balloon_size_work);
- spin_lock_irq(&vb->adjustment_lock);
- vb->adjustment_signal_pending = false;
- spin_unlock_irq(&vb->adjustment_lock);
+ process_wakeup_event(vb, VIRTIO_BALLOON_WAKEUP_SIGNAL_ADJUST);
diff = towards_target(vb);
@@ -523,7 +540,7 @@ static void update_balloon_size_func(struct work_struct *work)
if (diff)
queue_work(system_freezable_wq, work);
else
- end_update_balloon_size(vb);
+ finish_wakeup_event(vb);
}
static int init_vqs(struct virtio_balloon *vb)
@@ -1027,7 +1044,7 @@ static int virtballoon_probe(struct virtio_device *vdev)
goto out_unregister_oom;
}
- spin_lock_init(&vb->adjustment_lock);
+ spin_lock_init(&vb->wakeup_lock);
/*
* The virtio balloon itself can't wake up the device, but it is
--
2.44.0.291.gc1ea87d7ee-goog
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2024-03-21 1:30 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-03-21 1:24 [PATCH v2 0/2] Improvements to virtio_balloon pm David Stevens
2024-03-21 1:24 ` [PATCH v2 1/2] virtio_balloon: Give the balloon its own wakeup source David Stevens
2024-03-21 1:24 ` [PATCH v2 2/2] virtio_balloon: Treat stats requests as wakeup events David Stevens
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).