static int balloon(void *_vballoon) { struct virtio_balloon *vb = _vballoon; DEFINE_WAIT_FUNC(wait, woken_wake_function); set_freezable(); while (!kthread_should_stop()) { s64 diff; try_to_freeze(); add_wait_queue(&vb->config_change, &wait); for (;;) { if ((diff = towards_target(vb)) != 0 || vb->need_stats_update || kthread_should_stop() || freezing(current)) break; wait_woken(&wait, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT); } remove_wait_queue(&vb->config_change, &wait); if (vb->need_stats_update) stats_handle_request(vb); if (diff > 0) fill_balloon(vb, diff); else if (diff < 0) leak_balloon(vb, -diff); update_balloon_size(vb); /* * For large balloon changes, we could spend a lot of time * and always have work to do. Be nice if preempt disabled. */ cond_resched(); } return 0; }
static int balloon(void *_vballoon) { struct virtio_balloon *vb = _vballoon; set_freezable(); while (!kthread_should_stop()) { s64 diff; try_to_freeze(); wait_event_interruptible(vb->config_change, (diff = towards_target(vb)) != 0 || vb->need_stats_update || kthread_should_stop() || freezing(current)); if (vb->need_stats_update) stats_handle_request(vb); if (diff > 0) fill_balloon(vb, diff); else if (diff < 0) leak_balloon(vb, -diff); update_balloon_size(vb); /* * For large balloon changes, we could spend a lot of time * and always have work to do. Be nice if preempt disabled. */ cond_resched(); } return 0; }
static void remove_common(struct virtio_balloon *vb) { /* There might be pages left in the balloon: free them. */ while (vb->num_pages) leak_balloon(vb, vb->num_pages); update_balloon_size(vb); /* Now we reset the device so we can clean up the queues. */ vb->vdev->config->reset(vb->vdev); vb->vdev->config->del_vqs(vb->vdev); }
static int virtballoon_restore(struct virtio_device *vdev) { struct virtio_balloon *vb = vdev->priv; int ret; ret = init_vqs(vdev->priv); if (ret) return ret; fill_balloon(vb, towards_target(vb)); update_balloon_size(vb); return 0; }
static void update_balloon_size_func(struct work_struct *work) { struct virtio_balloon *vb; s64 diff; vb = container_of(work, struct virtio_balloon, update_balloon_size_work); diff = towards_target(vb); if (diff > 0) diff -= fill_balloon(vb, diff); else if (diff < 0) diff += leak_balloon(vb, -diff); update_balloon_size(vb); if (diff) queue_work(system_freezable_wq, work); }
/* * virtballoon_oom_notify - release pages when system is under severe * memory pressure (called from out_of_memory()) * @self : notifier block struct * @dummy: not used * @parm : returned - number of freed pages * * The balancing of memory by use of the virtio balloon should not cause * the termination of processes while there are pages in the balloon. * If virtio balloon manages to release some memory, it will make the * system return and retry the allocation that forced the OOM killer * to run. */ static int virtballoon_oom_notify(struct notifier_block *self, unsigned long dummy, void *parm) { struct virtio_balloon *vb; unsigned long *freed; unsigned num_freed_pages; vb = container_of(self, struct virtio_balloon, nb); if (!virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_DEFLATE_ON_OOM)) return NOTIFY_OK; freed = parm; num_freed_pages = leak_balloon(vb, oom_pages); update_balloon_size(vb); *freed += num_freed_pages; return NOTIFY_OK; }
static unsigned long shrink_balloon_pages(struct virtio_balloon *vb, unsigned long pages_to_free) { unsigned long pages_freed = 0; /* * One invocation of leak_balloon can deflate at most * VIRTIO_BALLOON_ARRAY_PFNS_MAX balloon pages, so we call it * multiple times to deflate pages till reaching pages_to_free. */ while (vb->num_pages && pages_to_free) { pages_freed += leak_balloon(vb, pages_to_free) / VIRTIO_BALLOON_PAGES_PER_PAGE; pages_to_free -= pages_freed; } update_balloon_size(vb); return pages_freed; }
static int balloon(void *_vballoon) { struct virtio_balloon *vb = _vballoon; set_freezable(); while (!kthread_should_stop()) { s64 diff; try_to_freeze(); wait_event_interruptible(vb->config_change, (diff = towards_target(vb)) != 0 || vb->need_stats_update || kthread_should_stop() || freezing(current)); if (vb->need_stats_update) stats_handle_request(vb); if (diff > 0) fill_balloon(vb, diff); else if (diff < 0) leak_balloon(vb, -diff); update_balloon_size(vb); } return 0; }