mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 12:28:41 +08:00
virtio_balloon: stay awake while adjusting balloon
A virtio_balloon's parent device may be configured so that a configuration change interrupt is a wakeup event. Extend the processing of such a wakeup event until the balloon finishes inflating or deflating by calling pm_stay_awake/pm_relax in the virtio_balloon driver. Note that these calls are no-ops if the parent device doesn't support wakeup events or if the wakeup events are not enabled. This change allows the guest to use system power states such as s2idle without running the risk the virtio_balloon's cooperative memory management becoming unresponsive to the host's requests. Tested-by: Theodore Ts'o <tytso@mit.edu> Signed-off-by: David Stevens <stevensd@chromium.org> Signed-off-by: Theodore Ts'o <tytso@mit.edu> Message-Id: <20240110021925.1137333-1-stevensd@google.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
parent
c271fcd909
commit
b12fbc3f78
@ -119,6 +119,11 @@ struct virtio_balloon {
|
||||
/* Free page reporting device */
|
||||
struct virtqueue *reporting_vq;
|
||||
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;
|
||||
};
|
||||
|
||||
static const struct virtio_device_id id_table[] = {
|
||||
@ -437,6 +442,31 @@ static void virtio_balloon_queue_free_page_work(struct virtio_balloon *vb)
|
||||
queue_work(vb->balloon_wq, &vb->report_free_page_work);
|
||||
}
|
||||
|
||||
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.parent);
|
||||
}
|
||||
spin_unlock_irqrestore(&vb->adjustment_lock, flags);
|
||||
|
||||
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.parent);
|
||||
}
|
||||
spin_unlock_irq(&vb->adjustment_lock);
|
||||
}
|
||||
|
||||
static void virtballoon_changed(struct virtio_device *vdev)
|
||||
{
|
||||
struct virtio_balloon *vb = vdev->priv;
|
||||
@ -444,8 +474,7 @@ static void virtballoon_changed(struct virtio_device *vdev)
|
||||
|
||||
spin_lock_irqsave(&vb->stop_update_lock, flags);
|
||||
if (!vb->stop_update) {
|
||||
queue_work(system_freezable_wq,
|
||||
&vb->update_balloon_size_work);
|
||||
start_update_balloon_size(vb);
|
||||
virtio_balloon_queue_free_page_work(vb);
|
||||
}
|
||||
spin_unlock_irqrestore(&vb->stop_update_lock, flags);
|
||||
@ -476,19 +505,25 @@ 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);
|
||||
|
||||
diff = towards_target(vb);
|
||||
|
||||
if (!diff)
|
||||
return;
|
||||
|
||||
if (diff > 0)
|
||||
diff -= fill_balloon(vb, diff);
|
||||
else
|
||||
diff += leak_balloon(vb, -diff);
|
||||
update_balloon_size(vb);
|
||||
if (diff) {
|
||||
if (diff > 0)
|
||||
diff -= fill_balloon(vb, diff);
|
||||
else
|
||||
diff += leak_balloon(vb, -diff);
|
||||
update_balloon_size(vb);
|
||||
}
|
||||
|
||||
if (diff)
|
||||
queue_work(system_freezable_wq, work);
|
||||
else
|
||||
end_update_balloon_size(vb);
|
||||
}
|
||||
|
||||
static int init_vqs(struct virtio_balloon *vb)
|
||||
@ -992,6 +1027,8 @@ static int virtballoon_probe(struct virtio_device *vdev)
|
||||
goto out_unregister_oom;
|
||||
}
|
||||
|
||||
spin_lock_init(&vb->adjustment_lock);
|
||||
|
||||
virtio_device_ready(vdev);
|
||||
|
||||
if (towards_target(vb))
|
||||
|
Loading…
Reference in New Issue
Block a user